6#include <QtCore/private/qsystemerror_p.h>
11#if __has_include(<pix.h>)
13#define QRHI_D3D12_HAS_OLD_PIX
16#ifdef __ID3D12Device2_INTERFACE_DEFINED__
150static const D3D_FEATURE_LEVEL MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
152QRhiD3D12::QRhiD3D12(QRhiD3D12InitParams *
params, QRhiD3D12NativeHandles *importParams)
154 debugLayer =
params->enableDebugLayer;
156 if (importParams->dev) {
157 ID3D12Device *d3d12Device =
reinterpret_cast<ID3D12Device *
>(importParams->dev);
158 if (SUCCEEDED(d3d12Device->QueryInterface(__uuidof(ID3D12Device2),
reinterpret_cast<void **
>(&dev)))) {
160 d3d12Device->Release();
161 importedDevice =
true;
163 qWarning(
"ID3D12Device2 not supported, cannot import device");
166 if (importParams->commandQueue) {
167 cmdQueue =
reinterpret_cast<ID3D12CommandQueue *
>(importParams->commandQueue);
168 importedCommandQueue =
true;
170 minimumFeatureLevel = D3D_FEATURE_LEVEL(importParams->minimumFeatureLevel);
171 adapterLuid.LowPart = importParams->adapterLuidLow;
172 adapterLuid.HighPart = importParams->adapterLuidHigh;
179 return (
v + byteAlign - 1) & ~(byteAlign - 1);
182static inline UINT calcSubresource(UINT mipSlice, UINT arraySlice, UINT mipLevels)
184 return mipSlice + arraySlice * mipLevels;
191 return &
QRHI_RES(QD3D12SwapChainRenderTarget, rt)->d;
193 return &
QRHI_RES(QD3D12TextureRenderTarget, rt)->d;
198 Q_UNREACHABLE_RETURN(
nullptr);
201bool QRhiD3D12::create(QRhi::Flags
flags)
205 UINT factoryFlags = 0;
207 factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
208 HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2),
reinterpret_cast<void **
>(&dxgiFactory));
212 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
213 "Attempting to create DXGIFactory2 without it.");
214 factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG;
215 hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2),
reinterpret_cast<void **
>(&dxgiFactory));
220 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
221 qPrintable(QSystemError::windowsComString(hr)));
226 supportsAllowTearing =
false;
227 IDXGIFactory5 *factory5 =
nullptr;
228 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<void **
>(&factory5)))) {
229 BOOL allowTearing =
false;
230 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
231 supportsAllowTearing = allowTearing;
236 ID3D12Debug1 *
debug =
nullptr;
237 if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1),
reinterpret_cast<void **
>(&
debug)))) {
238 qCDebug(QRHI_LOG_INFO,
"Enabling D3D12 debug layer");
239 debug->EnableDebugLayer();
244 if (!importedDevice) {
245 IDXGIAdapter1 *adapter;
246 int requestedAdapterIndex = -1;
251 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
252 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
253 DXGI_ADAPTER_DESC1
desc;
254 adapter->GetDesc1(&desc);
256 if (
desc.AdapterLuid.LowPart == adapterLuid.LowPart
257 &&
desc.AdapterLuid.HighPart == adapterLuid.HighPart)
259 requestedAdapterIndex = adapterIndex;
266 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
267 DXGI_ADAPTER_DESC1
desc;
268 adapter->GetDesc1(&desc);
271 requestedAdapterIndex = adapterIndex;
277 activeAdapter =
nullptr;
278 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
279 DXGI_ADAPTER_DESC1
desc;
280 adapter->GetDesc1(&desc);
282 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
288 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
289 activeAdapter = adapter;
290 adapterLuid =
desc.AdapterLuid;
292 qCDebug(QRHI_LOG_INFO,
" using this adapter");
297 if (!activeAdapter) {
302 if (minimumFeatureLevel == 0)
303 minimumFeatureLevel = MIN_FEATURE_LEVEL;
305 hr = D3D12CreateDevice(activeAdapter,
307 __uuidof(ID3D12Device2),
308 reinterpret_cast<void **
>(&dev));
310 qWarning(
"Failed to create D3D12 device: %s",
qPrintable(QSystemError::windowsComString(hr)));
316 adapterLuid = dev->GetAdapterLuid();
317 IDXGIAdapter1 *adapter;
318 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
319 DXGI_ADAPTER_DESC1
desc;
320 adapter->GetDesc1(&desc);
321 if (
desc.AdapterLuid.LowPart == adapterLuid.LowPart
322 &&
desc.AdapterLuid.HighPart == adapterLuid.HighPart)
324 activeAdapter = adapter;
331 if (!activeAdapter) {
335 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
339 ID3D12InfoQueue *infoQueue;
340 if (SUCCEEDED(dev->QueryInterface(__uuidof(ID3D12InfoQueue),
reinterpret_cast<void **
>(&infoQueue)))) {
342 infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION,
true);
343 infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR,
true);
344 infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING,
true);
346 D3D12_INFO_QUEUE_FILTER
filter = {};
347 D3D12_MESSAGE_ID suppressedMessages[2] = {
349 D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
351 D3D12_MESSAGE_ID_DRAW_EMPTY_SCISSOR_RECTANGLE
353 filter.DenyList.NumIDs = 2;
354 filter.DenyList.pIDList = suppressedMessages;
357 D3D12_MESSAGE_SEVERITY infoSev = D3D12_MESSAGE_SEVERITY_INFO;
358 filter.DenyList.NumSeverities = 1;
359 filter.DenyList.pSeverityList = &infoSev;
360 infoQueue->PushStorageFilter(&
filter);
361 infoQueue->Release();
365 if (!importedCommandQueue) {
366 D3D12_COMMAND_QUEUE_DESC queueDesc = {};
367 queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
368 queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
369 hr = dev->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue),
reinterpret_cast<void **
>(&cmdQueue));
371 qWarning(
"Failed to create command queue: %s",
qPrintable(QSystemError::windowsComString(hr)));
376 hr = dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence),
reinterpret_cast<void **
>(&fullFence));
378 qWarning(
"Failed to create fence: %s",
qPrintable(QSystemError::windowsComString(hr)));
381 fullFenceEvent = CreateEvent(
nullptr, FALSE, FALSE,
nullptr);
382 fullFenceCounter = 0;
384 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
385 hr = dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
386 __uuidof(ID3D12CommandAllocator),
387 reinterpret_cast<void **
>(&cmdAllocators[
i]));
389 qWarning(
"Failed to create command allocator: %s",
qPrintable(QSystemError::windowsComString(hr)));
394 if (!vma.create(dev, activeAdapter)) {
395 qWarning(
"Failed to initialize graphics memory suballocator");
399 if (!rtvPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
"main RTV pool")) {
400 qWarning(
"Could not create RTV pool");
404 if (!dsvPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
"main DSV pool")) {
405 qWarning(
"Could not create DSV pool");
409 if (!cbvSrvUavPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
"main CBV-SRV-UAV pool")) {
410 qWarning(
"Could not create CBV-SRV-UAV pool");
414 resourcePool.create(
"main resource pool");
415 pipelinePool.create(
"main pipeline pool");
416 rootSignaturePool.create(
"main root signature pool");
417 releaseQueue.create(&resourcePool, &pipelinePool, &rootSignaturePool);
418 barrierGen.create(&resourcePool);
420 if (!samplerMgr.create(dev)) {
421 qWarning(
"Could not create sampler pool and shader-visible sampler heap");
425 if (!mipmapGen.create(
this)) {
426 qWarning(
"Could not initialize mipmap generator");
430 const qint32 smallStagingSize =
aligned(SMALL_STAGING_AREA_BYTES_PER_FRAME, QD3D12StagingArea::ALIGNMENT);
431 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
432 if (!smallStagingAreas[
i].
create(
this, smallStagingSize, D3D12_HEAP_TYPE_UPLOAD)) {
433 qWarning(
"Could not create host-visible staging area");
438 smallStagingAreas[
i].mem.buffer->SetName(
reinterpret_cast<LPCWSTR
>(decoratedName.utf16()));
441 if (!shaderVisibleCbvSrvUavHeap.create(dev,
442 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
443 SHADER_VISIBLE_CBV_SRV_UAV_HEAP_PER_FRAME_START_SIZE))
445 qWarning(
"Could not create first shader-visible CBV/SRV/UAV heap");
466 if (wantsStablePowerState)
467 dev->SetStablePowerState(TRUE);
469 hr = cmdQueue->GetTimestampFrequency(×tampTicksPerSecond);
471 qWarning(
"Failed to query timestamp frequency: %s",
472 qPrintable(QSystemError::windowsComString(hr)));
475 if (!timestampQueryHeap.create(dev, QD3D12_FRAMES_IN_FLIGHT * 2, D3D12_QUERY_HEAP_TYPE_TIMESTAMP)) {
476 qWarning(
"Failed to create timestamp query pool");
479 const quint32 readbackBufSize = QD3D12_FRAMES_IN_FLIGHT * 2 *
sizeof(
quint64);
480 if (!timestampReadbackArea.create(
this, readbackBufSize, D3D12_HEAP_TYPE_READBACK)) {
481 qWarning(
"Failed to create timestamp readback buffer");
484 timestampReadbackArea.mem.buffer->SetName(L
"Timestamp readback buffer");
485 memset(timestampReadbackArea.mem.p, 0, readbackBufSize);
489 D3D12_FEATURE_DATA_D3D12_OPTIONS3 options3 = {};
490 if (SUCCEEDED(dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &options3,
sizeof(options3)))) {
491 caps.multiView = options3.ViewInstancingTier != D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED;
493 caps.textureViewFormat = options3.CastingFullyTypedFormatSupported;
497 offscreenActive =
false;
499 nativeHandlesStruct.dev = dev;
500 nativeHandlesStruct.minimumFeatureLevel = minimumFeatureLevel;
501 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
502 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
503 nativeHandlesStruct.commandQueue = cmdQueue;
508void QRhiD3D12::destroy()
510 if (!deviceLost && fullFence && fullFenceEvent)
513 releaseQueue.releaseAll();
515 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
516 if (offscreenCb[
i]) {
517 if (offscreenCb[
i]->cmdList)
518 offscreenCb[
i]->cmdList->Release();
519 delete offscreenCb[
i];
520 offscreenCb[
i] =
nullptr;
524 timestampQueryHeap.destroy();
525 timestampReadbackArea.destroy();
527 shaderVisibleCbvSrvUavHeap.destroy();
529 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i)
530 smallStagingAreas[
i].destroy();
533 samplerMgr.destroy();
534 resourcePool.destroy();
535 pipelinePool.destroy();
536 rootSignaturePool.destroy();
539 cbvSrvUavPool.destroy();
541 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
542 if (cmdAllocators[
i]) {
543 cmdAllocators[
i]->Release();
544 cmdAllocators[
i] =
nullptr;
548 if (fullFenceEvent) {
549 CloseHandle(fullFenceEvent);
550 fullFenceEvent =
nullptr;
554 fullFence->Release();
558 if (!importedCommandQueue) {
567 if (!importedDevice) {
575 dcompDevice->Release();
576 dcompDevice =
nullptr;
580 activeAdapter->Release();
581 activeAdapter =
nullptr;
585 dxgiFactory->Release();
586 dxgiFactory =
nullptr;
590QList<int> QRhiD3D12::supportedSampleCounts()
const
592 return { 1, 2, 4, 8 };
597 return new QD3D12SwapChain(
this);
605int QRhiD3D12::ubufAlignment()
const
607 return D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
610bool QRhiD3D12::isYUpInFramebuffer()
const
615bool QRhiD3D12::isYUpInNDC()
const
620bool QRhiD3D12::isClipDepthZeroToOne()
const
625QMatrix4x4 QRhiD3D12::clipSpaceCorrMatrix()
const
630 if (
m.isIdentity()) {
633 0.0f, 1.0f, 0.0f, 0.0f,
634 0.0f, 0.0f, 0.5f, 0.5f,
635 0.0f, 0.0f, 0.0f, 1.0f);
650bool QRhiD3D12::isFeatureSupported(
QRhi::Feature feature)
const
658#ifdef QRHI_D3D12_HAS_OLD_PIX
738 return caps.multiView;
740 return caps.textureViewFormat;
759 return QD3D12_FRAMES_IN_FLIGHT;
761 return QD3D12_FRAMES_IN_FLIGHT;
786 return &nativeHandlesStruct;
791 return driverInfoStruct;
799 D3D12MA::Budget budgets[2];
800 vma.getBudget(&budgets[0], &budgets[1]);
801 for (
int i = 0;
i < 2; ++
i) {
802 const D3D12MA::Statistics &stats(budgets[
i].Stats);
803 result.blockCount += stats.BlockCount;
804 result.allocCount += stats.AllocationCount;
805 result.usedBytes += stats.AllocationBytes;
806 result.unusedBytes += stats.BlockBytes - stats.AllocationBytes;
807 result.totalUsageBytes += budgets[
i].UsageBytes;
813bool QRhiD3D12::makeThreadLocalNativeContextCurrent()
819void QRhiD3D12::releaseCachedResources()
821 shaderBytecodeCache.data.clear();
824bool QRhiD3D12::isDeviceLost()
const
840 int sampleCount, QRhiRenderBuffer::Flags
flags,
843 return new QD3D12RenderBuffer(
this,
type, pixelSize, sampleCount,
flags, backingFormatHint);
847 const QSize &pixelSize,
int depth,
int arraySize,
848 int sampleCount, QRhiTexture::Flags
flags)
850 return new QD3D12Texture(
this,
format, pixelSize,
depth, arraySize, sampleCount,
flags);
857 return new QD3D12Sampler(
this, magFilter, minFilter, mipmapMode, u,
v,
w);
861 QRhiTextureRenderTarget::Flags
flags)
863 return new QD3D12TextureRenderTarget(
this, desc,
flags);
868 return new QD3D12GraphicsPipeline(
this);
873 return new QD3D12ComputePipeline(
this);
878 return new QD3D12ShaderResourceBindings(
this);
883 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
884 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
885 QD3D12GraphicsPipeline *psD =
QRHI_RES(QD3D12GraphicsPipeline, ps);
886 const bool pipelineChanged = cbD->currentGraphicsPipeline != psD || cbD->currentPipelineGeneration != psD->generation;
888 if (pipelineChanged) {
889 cbD->currentGraphicsPipeline = psD;
890 cbD->currentComputePipeline =
nullptr;
891 cbD->currentPipelineGeneration = psD->generation;
893 if (QD3D12Pipeline *pipeline = pipelinePool.lookupRef(psD->handle)) {
894 Q_ASSERT(pipeline->type == QD3D12Pipeline::Graphics);
895 cbD->cmdList->SetPipelineState(pipeline->pso);
896 if (QD3D12RootSignature *rs = rootSignaturePool.lookupRef(psD->rootSigHandle))
897 cbD->cmdList->SetGraphicsRootSignature(rs->rootSig);
900 cbD->cmdList->IASetPrimitiveTopology(psD->topology);
902 if (psD->viewInstanceMask)
903 cbD->cmdList->SetViewInstanceMask(psD->viewInstanceMask);
907void QD3D12CommandBuffer::visitUniformBuffer(QD3D12Stage
s,
911 int dynamicOffsetCount,
914 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer,
d.buf);
916 if (
d.hasDynamicOffset) {
917 for (
int i = 0;
i < dynamicOffsetCount; ++
i) {
919 if (dynOfs.first == binding) {
926 visitorData.cbufs[
s].append({ bufD->handles[rhiD->currentFrameSlot],
offset });
929void QD3D12CommandBuffer::visitTexture(QD3D12Stage
s,
933 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
d.tex);
934 visitorData.srvs[
s].append(texD->srv);
937void QD3D12CommandBuffer::visitSampler(QD3D12Stage
s,
941 QD3D12Sampler *samplerD =
QRHI_RES(QD3D12Sampler,
d.sampler);
942 visitorData.samplers[
s].append(samplerD->lookupOrCreateShaderVisibleDescriptor());
945void QD3D12CommandBuffer::visitStorageBuffer(QD3D12Stage
s,
947 QD3D12ShaderResourceVisitor::StorageOp,
950 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer,
d.buf);
952 D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
953 uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
954 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
955 uavDesc.Buffer.FirstElement =
d.offset / 4;
956 uavDesc.Buffer.NumElements =
aligned(bufD->m_size -
d.offset, 4u) / 4;
957 uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
958 visitorData.uavs[
s].append({ bufD->handles[0], uavDesc });
961void QD3D12CommandBuffer::visitStorageImage(QD3D12Stage
s,
963 QD3D12ShaderResourceVisitor::StorageOp,
966 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
d.tex);
970 D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
971 uavDesc.Format = texD->rtFormat;
973 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
974 uavDesc.Texture2DArray.MipSlice = UINT(
d.level);
975 uavDesc.Texture2DArray.FirstArraySlice = 0;
976 uavDesc.Texture2DArray.ArraySize = 6;
977 }
else if (isArray) {
978 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
979 uavDesc.Texture2DArray.MipSlice = UINT(
d.level);
980 uavDesc.Texture2DArray.FirstArraySlice = 0;
981 uavDesc.Texture2DArray.ArraySize = UINT(
qMax(0, texD->m_arraySize));
983 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
984 uavDesc.Texture3D.MipSlice = UINT(
d.level);
986 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
987 uavDesc.Texture2D.MipSlice = UINT(
d.level);
989 visitorData.uavs[
s].append({ texD->handle, uavDesc });
993 int dynamicOffsetCount,
996 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
997 Q_ASSERT(cbD->recordingPass != QD3D12CommandBuffer::NoPass);
998 QD3D12GraphicsPipeline *gfxPsD =
QRHI_RES(QD3D12GraphicsPipeline, cbD->currentGraphicsPipeline);
999 QD3D12ComputePipeline *compPsD =
QRHI_RES(QD3D12ComputePipeline, cbD->currentComputePipeline);
1003 srb = gfxPsD->m_shaderResourceBindings;
1005 srb = compPsD->m_shaderResourceBindings;
1008 QD3D12ShaderResourceBindings *srbD =
QRHI_RES(QD3D12ShaderResourceBindings, srb);
1010 for (
int i = 0, ie = srbD->m_bindings.size();
i != ie; ++
i) {
1015 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer,
b->u.ubuf.buf);
1018 bufD->executeHostWritesForFrameSlot(currentFrameSlot);
1026 for (
int elem = 0; elem <
data->count; ++elem) {
1027 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
data->texSamplers[elem].tex);
1028 QD3D12Sampler *samplerD =
QRHI_RES(QD3D12Sampler,
data->texSamplers[elem].sampler);
1036 state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
1038 state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1040 state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1042 barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATES(
state));
1043 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1052 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
b->u.simage.tex);
1053 if (QD3D12Resource *
res = resourcePool.lookupRef(texD->handle)) {
1054 if (
res->uavUsage) {
1055 if (
res->uavUsage & QD3D12Resource::UavUsageWrite) {
1057 barrierGen.enqueueUavBarrier(cbD, texD->handle);
1063 barrierGen.enqueueUavBarrier(cbD, texD->handle);
1069 res->uavUsage |= QD3D12Resource::UavUsageRead;
1071 res->uavUsage |= QD3D12Resource::UavUsageWrite;
1072 barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
1073 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1081 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer,
b->u.sbuf.buf);
1084 if (QD3D12Resource *
res = resourcePool.lookupRef(bufD->handles[0])) {
1085 if (
res->uavUsage) {
1086 if (
res->uavUsage & QD3D12Resource::UavUsageWrite) {
1088 barrierGen.enqueueUavBarrier(cbD, bufD->handles[0]);
1094 barrierGen.enqueueUavBarrier(cbD, bufD->handles[0]);
1100 res->uavUsage |= QD3D12Resource::UavUsageRead;
1102 res->uavUsage |= QD3D12Resource::UavUsageWrite;
1103 barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
1104 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1111 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1112 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1114 if (srbChanged || srbRebuilt || srbD->hasDynamicOffset) {
1115 const QD3D12ShaderStageData *stageData = gfxPsD ? gfxPsD->stageData.data() : &compPsD->stageData;
1121 QD3D12ShaderResourceVisitor visitor(srbD, stageData, gfxPsD ? 5 : 1);
1123 QD3D12CommandBuffer::VisitorData &visitorData(cbD->visitorData);
1126 using namespace std::placeholders;
1127 visitor.uniformBuffer = std::bind(&QD3D12CommandBuffer::visitUniformBuffer, cbD, _1, _2, _3, _4, dynamicOffsetCount, dynamicOffsets);
1128 visitor.texture = std::bind(&QD3D12CommandBuffer::visitTexture, cbD, _1, _2, _3);
1129 visitor.sampler = std::bind(&QD3D12CommandBuffer::visitSampler, cbD, _1, _2, _3);
1130 visitor.storageBuffer = std::bind(&QD3D12CommandBuffer::visitStorageBuffer, cbD, _1, _2, _3, _4);
1131 visitor.storageImage = std::bind(&QD3D12CommandBuffer::visitStorageImage, cbD, _1, _2, _3, _4);
1136 for (
int s = 0;
s < 6; ++
s) {
1138 cbvSrvUavCount += visitorData.srvs[
s].count();
1139 cbvSrvUavCount += visitorData.uavs[
s].count();
1142 bool gotNewHeap =
false;
1143 if (!ensureShaderVisibleDescriptorHeapCapacity(&shaderVisibleCbvSrvUavHeap,
1144 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1152 qCDebug(QRHI_LOG_INFO,
"Created new shader-visible CBV/SRV/UAV descriptor heap,"
1153 " per-frame slice size is now %u,"
1154 " if this happens frequently then that's not great.",
1155 shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[0].capacity);
1156 bindShaderVisibleHeaps(cbD);
1159 int rootParamIndex = 0;
1160 for (
int s = 0;
s < 6; ++
s) {
1161 if (!visitorData.cbufs[
s].isEmpty()) {
1162 for (
int i = 0,
count = visitorData.cbufs[
s].count();
i <
count; ++
i) {
1163 const auto &cbuf(visitorData.cbufs[
s][
i]);
1164 if (QD3D12Resource *
res = resourcePool.lookupRef(cbuf.first)) {
1166 D3D12_GPU_VIRTUAL_ADDRESS gpuAddr =
res->resource->GetGPUVirtualAddress() +
offset;
1167 if (cbD->currentGraphicsPipeline)
1168 cbD->cmdList->SetGraphicsRootConstantBufferView(rootParamIndex, gpuAddr);
1170 cbD->cmdList->SetComputeRootConstantBufferView(rootParamIndex, gpuAddr);
1172 rootParamIndex += 1;
1176 for (
int s = 0;
s < 6; ++
s) {
1177 if (!visitorData.srvs[
s].isEmpty()) {
1178 QD3D12DescriptorHeap &gpuSrvHeap(shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot]);
1179 QD3D12Descriptor startDesc = gpuSrvHeap.get(visitorData.srvs[
s].count());
1180 for (
int i = 0,
count = visitorData.srvs[
s].count();
i <
count; ++
i) {
1181 const auto &srv(visitorData.srvs[
s][
i]);
1182 dev->CopyDescriptorsSimple(1, gpuSrvHeap.incremented(startDesc,
i).cpuHandle, srv.cpuHandle,
1183 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1186 if (cbD->currentGraphicsPipeline)
1187 cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
1188 else if (cbD->currentComputePipeline)
1189 cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
1191 rootParamIndex += 1;
1194 for (
int s = 0;
s < 6; ++
s) {
1197 for (
const QD3D12Descriptor &samplerDescriptor : visitorData.
samplers[
s]) {
1198 if (cbD->currentGraphicsPipeline)
1199 cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, samplerDescriptor.gpuHandle);
1200 else if (cbD->currentComputePipeline)
1201 cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, samplerDescriptor.gpuHandle);
1203 rootParamIndex += 1;
1206 for (
int s = 0;
s < 6; ++
s) {
1207 if (!visitorData.uavs[
s].isEmpty()) {
1208 QD3D12DescriptorHeap &gpuUavHeap(shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot]);
1209 QD3D12Descriptor startDesc = gpuUavHeap.get(visitorData.uavs[
s].count());
1210 for (
int i = 0,
count = visitorData.uavs[
s].count();
i <
count; ++
i) {
1211 const auto &uav(visitorData.uavs[
s][
i]);
1212 if (QD3D12Resource *
res = resourcePool.lookupRef(uav.first)) {
1213 dev->CreateUnorderedAccessView(
res->resource,
nullptr, &uav.second,
1214 gpuUavHeap.incremented(startDesc,
i).cpuHandle);
1216 dev->CreateUnorderedAccessView(
nullptr,
nullptr,
nullptr,
1217 gpuUavHeap.incremented(startDesc,
i).cpuHandle);
1221 if (cbD->currentGraphicsPipeline)
1222 cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
1223 else if (cbD->currentComputePipeline)
1224 cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
1226 rootParamIndex += 1;
1231 cbD->currentGraphicsSrb = srb;
1232 cbD->currentComputeSrb =
nullptr;
1234 cbD->currentGraphicsSrb =
nullptr;
1235 cbD->currentComputeSrb = srb;
1237 cbD->currentSrbGeneration = srbD->generation;
1245 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1246 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1248 bool needsBindVBuf =
false;
1249 for (
int i = 0;
i < bindingCount; ++
i) {
1250 const int inputSlot = startBinding +
i;
1255 bufD->executeHostWritesForFrameSlot(currentFrameSlot);
1257 if (cbD->currentVertexBuffers[inputSlot] != bufD->handles[isDynamic ? currentFrameSlot : 0]
1258 || cbD->currentVertexOffsets[inputSlot] != bindings[
i].second)
1260 needsBindVBuf =
true;
1261 cbD->currentVertexBuffers[inputSlot] = bufD->handles[isDynamic ? currentFrameSlot : 0];
1262 cbD->currentVertexOffsets[inputSlot] = bindings[
i].second;
1266 if (needsBindVBuf) {
1267 QVarLengthArray<D3D12_VERTEX_BUFFER_VIEW, 4> vbv;
1268 vbv.reserve(bindingCount);
1270 QD3D12GraphicsPipeline *psD = cbD->currentGraphicsPipeline;
1272 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1274 for (
int i = 0, ie =
qMin(bindingCount, inputBindingCount);
i != ie; ++
i) {
1281 barrierGen.addTransitionBarrier(
handle, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
1282 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1285 if (QD3D12Resource *
res = resourcePool.lookupRef(
handle)) {
1287 res->resource->GetGPUVirtualAddress() +
offset,
1294 cbD->cmdList->IASetVertexBuffers(UINT(startBinding), vbv.count(), vbv.constData());
1298 QD3D12Buffer *ibufD =
QRHI_RES(QD3D12Buffer, indexBuf);
1302 ibufD->executeHostWritesForFrameSlot(currentFrameSlot);
1305 : DXGI_FORMAT_R32_UINT;
1306 if (cbD->currentIndexBuffer != ibufD->handles[isDynamic ? currentFrameSlot : 0]
1307 || cbD->currentIndexOffset != indexOffset
1308 || cbD->currentIndexFormat != dxgiFormat)
1310 cbD->currentIndexBuffer = ibufD->handles[isDynamic ? currentFrameSlot : 0];
1311 cbD->currentIndexOffset = indexOffset;
1312 cbD->currentIndexFormat = dxgiFormat;
1315 barrierGen.addTransitionBarrier(cbD->currentIndexBuffer, D3D12_RESOURCE_STATE_INDEX_BUFFER);
1316 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1319 if (QD3D12Resource *
res = resourcePool.lookupRef(cbD->currentIndexBuffer)) {
1320 const D3D12_INDEX_BUFFER_VIEW ibv = {
1321 res->resource->GetGPUVirtualAddress() + indexOffset,
1322 UINT(
res->desc.Width - indexOffset),
1325 cbD->cmdList->IASetIndexBuffer(&ibv);
1333 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1334 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1336 const QSize outputSize = cbD->currentTarget->pixelSize();
1340 if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h))
1350 cbD->cmdList->RSSetViewports(1, &
v);
1352 if (cbD->currentGraphicsPipeline
1355 qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h);
1362 cbD->cmdList->RSSetScissorRects(1, &
r);
1368 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1369 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1371 const QSize outputSize = cbD->currentTarget->pixelSize();
1375 if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.
scissor(), &
x, &
y, &
w, &
h))
1384 cbD->cmdList->RSSetScissorRects(1, &
r);
1389 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1390 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1391 float v[4] = {
c.redF(),
c.greenF(),
c.blueF(),
c.alphaF() };
1392 cbD->cmdList->OMSetBlendFactor(
v);
1397 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1398 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1399 cbD->cmdList->OMSetStencilRef(refValue);
1405 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1406 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1407 cbD->cmdList->DrawInstanced(vertexCount,
instanceCount, firstVertex, firstInstance);
1413 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1414 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1415 cbD->cmdList->DrawIndexedInstanced(indexCount,
instanceCount,
1416 firstIndex, vertexOffset,
1425 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1426#ifdef QRHI_D3D12_HAS_OLD_PIX
1439 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1440#ifdef QRHI_D3D12_HAS_OLD_PIX
1441 PIXEndEvent(cbD->cmdList);
1452 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1453#ifdef QRHI_D3D12_HAS_OLD_PIX
1454 PIXSetMarker(cbD->cmdList, PIX_COLOR_DEFAULT,
reinterpret_cast<LPCWSTR
>(
QString::fromLatin1(msg).utf16()));
1463 return QRHI_RES(QD3D12CommandBuffer,
cb)->nativeHandles();
1473 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1474 cbD->resetPerPassState();
1475 bindShaderVisibleHeaps(cbD);
1476 if (cbD->currentTarget) {
1477 QD3D12RenderTargetData *rtD =
rtData(cbD->currentTarget);
1478 cbD->cmdList->OMSetRenderTargets(UINT(rtD->colorAttCount),
1481 rtD->dsAttCount ? &rtD->dsv :
nullptr);
1487 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1488 return cbD->lastGpuTime;
1491static void calculateGpuTime(QD3D12CommandBuffer *cbD,
1492 int timestampPairStartIndex,
1493 const quint8 *readbackBufPtr,
1494 quint64 timestampTicksPerSecond)
1496 const size_t byteOffset = timestampPairStartIndex *
sizeof(
quint64);
1497 const quint64 *
p =
reinterpret_cast<const quint64 *
>(readbackBufPtr + byteOffset);
1502 const double timeSec = ticks / double(timestampTicksPerSecond);
1503 cbD->lastGpuTime = timeSec;
1511 QD3D12SwapChain *swapChainD =
QRHI_RES(QD3D12SwapChain, swapChain);
1512 currentSwapChain = swapChainD;
1513 currentFrameSlot = swapChainD->currentFrameSlot;
1514 QD3D12SwapChain::FrameResources &fr(swapChainD->frameRes[currentFrameSlot]);
1527 for (QD3D12SwapChain *sc :
std::as_const(swapchains))
1528 sc->waitCommandCompletionForFrameSlot(currentFrameSlot);
1530 HRESULT hr = cmdAllocators[currentFrameSlot]->Reset();
1532 qWarning(
"Failed to reset command allocator: %s",
1533 qPrintable(QSystemError::windowsComString(hr)));
1537 if (!startCommandListForCurrentFrameSlot(&fr.cmdList))
1540 QD3D12CommandBuffer *cbD = &swapChainD->cbWrapper;
1541 cbD->cmdList = fr.cmdList;
1543 swapChainD->rtWrapper.d.rtv[0] = swapChainD->sampleDesc.Count > 1
1544 ? swapChainD->msaaRtvs[swapChainD->currentBackBufferIndex].cpuHandle
1545 : swapChainD->rtvs[swapChainD->currentBackBufferIndex].cpuHandle;
1547 swapChainD->rtWrapper.d.dsv = swapChainD->ds ? swapChainD->ds->dsv.cpuHandle
1548 : D3D12_CPU_DESCRIPTOR_HANDLE { 0 };
1550 if (swapChainD->stereo) {
1551 swapChainD->rtWrapperRight.d.rtv[0] = swapChainD->sampleDesc.Count > 1
1552 ? swapChainD->msaaRtvs[swapChainD->currentBackBufferIndex].cpuHandle
1553 : swapChainD->rtvsRight[swapChainD->currentBackBufferIndex].cpuHandle;
1555 swapChainD->rtWrapperRight.d.dsv =
1556 swapChainD->ds ? swapChainD->ds->dsv.cpuHandle : D3D12_CPU_DESCRIPTOR_HANDLE{ 0 };
1563 releaseQueue.executeDeferredReleases(currentFrameSlot);
1569 shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
1571 smallStagingAreas[currentFrameSlot].head = 0;
1573 bindShaderVisibleHeaps(cbD);
1575 finishActiveReadbacks();
1577 if (timestampQueryHeap.isValid() && timestampTicksPerSecond) {
1580 const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
1581 calculateGpuTime(cbD,
1582 timestampPairStartIndex,
1583 timestampReadbackArea.mem.p,
1584 timestampTicksPerSecond);
1586 cbD->cmdList->EndQuery(timestampQueryHeap.heap,
1587 D3D12_QUERY_TYPE_TIMESTAMP,
1588 timestampPairStartIndex);
1596 QD3D12SwapChain *swapChainD =
QRHI_RES(QD3D12SwapChain, swapChain);
1597 Q_ASSERT(currentSwapChain == swapChainD);
1598 QD3D12CommandBuffer *cbD = &swapChainD->cbWrapper;
1600 QD3D12ObjectHandle backBufferResourceHandle = swapChainD->colorBuffers[swapChainD->currentBackBufferIndex];
1601 if (swapChainD->sampleDesc.Count > 1) {
1602 QD3D12ObjectHandle msaaBackBufferResourceHandle = swapChainD->msaaBuffers[swapChainD->currentBackBufferIndex];
1603 barrierGen.addTransitionBarrier(msaaBackBufferResourceHandle, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
1604 barrierGen.addTransitionBarrier(backBufferResourceHandle, D3D12_RESOURCE_STATE_RESOLVE_DEST);
1605 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1606 const QD3D12Resource *
src = resourcePool.lookupRef(msaaBackBufferResourceHandle);
1607 const QD3D12Resource *
dst = resourcePool.lookupRef(backBufferResourceHandle);
1609 cbD->cmdList->ResolveSubresource(
dst->resource, 0,
src->resource, 0, swapChainD->colorFormat);
1612 barrierGen.addTransitionBarrier(backBufferResourceHandle, D3D12_RESOURCE_STATE_PRESENT);
1613 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1615 if (timestampQueryHeap.isValid()) {
1616 const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
1617 cbD->cmdList->EndQuery(timestampQueryHeap.heap,
1618 D3D12_QUERY_TYPE_TIMESTAMP,
1619 timestampPairStartIndex + 1);
1620 cbD->cmdList->ResolveQueryData(timestampQueryHeap.heap,
1621 D3D12_QUERY_TYPE_TIMESTAMP,
1622 timestampPairStartIndex,
1624 timestampReadbackArea.mem.buffer,
1625 timestampPairStartIndex *
sizeof(
quint64));
1628 ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
1629 HRESULT hr = cmdList->Close();
1631 qWarning(
"Failed to close command list: %s",
1632 qPrintable(QSystemError::windowsComString(hr)));
1636 ID3D12CommandList *execList[] = { cmdList };
1637 cmdQueue->ExecuteCommandLists(1, execList);
1640 UINT presentFlags = 0;
1641 if (swapChainD->swapInterval == 0
1642 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1644 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1646 if (!swapChainD->swapChain) {
1647 qWarning(
"Failed to present, no swapchain");
1650 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1651 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1652 qWarning(
"Device loss detected in Present()");
1655 }
else if (FAILED(hr)) {
1660 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1661 dcompDevice->Commit();
1664 swapChainD->addCommandCompletionSignalForCurrentFrameSlot();
1671 releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
1677 swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D12_FRAMES_IN_FLIGHT;
1678 swapChainD->currentBackBufferIndex = swapChainD->swapChain->GetCurrentBackBufferIndex();
1681 currentSwapChain =
nullptr;
1698 currentFrameSlot = (currentFrameSlot + 1) % QD3D12_FRAMES_IN_FLIGHT;
1700 for (QD3D12SwapChain *sc :
std::as_const(swapchains))
1701 sc->waitCommandCompletionForFrameSlot(currentFrameSlot);
1703 if (!offscreenCb[currentFrameSlot])
1704 offscreenCb[currentFrameSlot] =
new QD3D12CommandBuffer(
this);
1705 QD3D12CommandBuffer *cbD = offscreenCb[currentFrameSlot];
1706 if (!startCommandListForCurrentFrameSlot(&cbD->cmdList))
1709 releaseQueue.executeDeferredReleases(currentFrameSlot);
1711 shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
1712 smallStagingAreas[currentFrameSlot].head = 0;
1714 bindShaderVisibleHeaps(cbD);
1716 if (timestampQueryHeap.isValid() && timestampTicksPerSecond) {
1717 cbD->cmdList->EndQuery(timestampQueryHeap.heap,
1718 D3D12_QUERY_TYPE_TIMESTAMP,
1719 currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT);
1722 offscreenActive =
true;
1732 offscreenActive =
false;
1734 QD3D12CommandBuffer *cbD = offscreenCb[currentFrameSlot];
1735 if (timestampQueryHeap.isValid()) {
1736 const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
1737 cbD->cmdList->EndQuery(timestampQueryHeap.heap,
1738 D3D12_QUERY_TYPE_TIMESTAMP,
1739 timestampPairStartIndex + 1);
1740 cbD->cmdList->ResolveQueryData(timestampQueryHeap.heap,
1741 D3D12_QUERY_TYPE_TIMESTAMP,
1742 timestampPairStartIndex,
1744 timestampReadbackArea.mem.buffer,
1745 timestampPairStartIndex *
sizeof(
quint64));
1748 ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
1749 HRESULT hr = cmdList->Close();
1751 qWarning(
"Failed to close command list: %s",
1752 qPrintable(QSystemError::windowsComString(hr)));
1756 ID3D12CommandList *execList[] = { cmdList };
1757 cmdQueue->ExecuteCommandLists(1, execList);
1759 releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
1766 finishActiveReadbacks(
true);
1769 if (timestampQueryHeap.isValid()) {
1770 calculateGpuTime(cbD,
1771 currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT,
1772 timestampReadbackArea.mem.p,
1773 timestampTicksPerSecond);
1784 QD3D12CommandBuffer *cbD =
nullptr;
1785 if (offscreenActive) {
1787 cbD = offscreenCb[currentFrameSlot];
1790 cbD = ¤tSwapChain->cbWrapper;
1795 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
1797 ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
1798 HRESULT hr = cmdList->Close();
1800 qWarning(
"Failed to close command list: %s",
1801 qPrintable(QSystemError::windowsComString(hr)));
1805 ID3D12CommandList *execList[] = { cmdList };
1806 cmdQueue->ExecuteCommandLists(1, execList);
1808 releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
1813 hr = cmdAllocators[currentFrameSlot]->Reset();
1815 qWarning(
"Failed to reset command allocator: %s",
1816 qPrintable(QSystemError::windowsComString(hr)));
1820 if (!startCommandListForCurrentFrameSlot(&cmdList))
1825 shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
1826 smallStagingAreas[currentFrameSlot].head = 0;
1828 bindShaderVisibleHeaps(cbD);
1830 releaseQueue.executeDeferredReleases(currentFrameSlot);
1832 finishActiveReadbacks(
true);
1839 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1840 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
1841 enqueueResourceUpdates(cbD, resourceUpdates);
1846 const QColor &colorClearValue,
1849 QRhiCommandBuffer::BeginPassFlags)
1851 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1852 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
1854 if (resourceUpdates)
1855 enqueueResourceUpdates(cbD, resourceUpdates);
1857 QD3D12RenderTargetData *rtD =
rtData(rt);
1858 bool wantsColorClear =
true;
1859 bool wantsDsClear =
true;
1861 QD3D12TextureRenderTarget *rtTex =
QRHI_RES(QD3D12TextureRenderTarget, rt);
1864 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D12Texture, QD3D12RenderBuffer>(rtTex->description(), rtD->currentResIdList))
1867 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
it != itEnd; ++
it) {
1868 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
it->texture());
1869 QD3D12Texture *resolveTexD =
QRHI_RES(QD3D12Texture,
it->resolveTexture());
1870 QD3D12RenderBuffer *rbD =
QRHI_RES(QD3D12RenderBuffer,
it->renderBuffer());
1872 barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
1874 barrierGen.addTransitionBarrier(rbD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
1876 barrierGen.addTransitionBarrier(resolveTexD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
1878 if (rtTex->m_desc.depthStencilBuffer()) {
1879 QD3D12RenderBuffer *rbD =
QRHI_RES(QD3D12RenderBuffer, rtTex->m_desc.depthStencilBuffer());
1881 barrierGen.addTransitionBarrier(rbD->handle, D3D12_RESOURCE_STATE_DEPTH_WRITE);
1882 }
else if (rtTex->m_desc.depthTexture()) {
1883 QD3D12Texture *depthTexD =
QRHI_RES(QD3D12Texture, rtTex->m_desc.depthTexture());
1884 barrierGen.addTransitionBarrier(depthTexD->handle, D3D12_RESOURCE_STATE_DEPTH_WRITE);
1886 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1889 barrierGen.addTransitionBarrier(currentSwapChain->sampleDesc.Count > 1
1890 ? currentSwapChain->msaaBuffers[currentSwapChain->currentBackBufferIndex]
1891 : currentSwapChain->colorBuffers[currentSwapChain->currentBackBufferIndex],
1892 D3D12_RESOURCE_STATE_RENDER_TARGET);
1893 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1896 cbD->cmdList->OMSetRenderTargets(UINT(rtD->colorAttCount),
1899 rtD->dsAttCount ? &rtD->dsv :
nullptr);
1901 if (rtD->colorAttCount && wantsColorClear) {
1902 float clearColor[4] = {
1903 colorClearValue.redF(),
1904 colorClearValue.greenF(),
1905 colorClearValue.blueF(),
1906 colorClearValue.alphaF()
1908 for (
int i = 0;
i < rtD->colorAttCount; ++
i)
1909 cbD->cmdList->ClearRenderTargetView(rtD->rtv[
i], clearColor, 0,
nullptr);
1911 if (rtD->dsAttCount && wantsDsClear) {
1912 cbD->cmdList->ClearDepthStencilView(rtD->dsv,
1913 D3D12_CLEAR_FLAGS(D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL),
1914 depthStencilClearValue.depthClearValue(),
1915 UINT8(depthStencilClearValue.stencilClearValue()),
1920 cbD->recordingPass = QD3D12CommandBuffer::RenderPass;
1921 cbD->currentTarget = rt;
1923 cbD->resetPerPassState();
1928 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
1929 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
1932 QD3D12TextureRenderTarget *rtTex =
QRHI_RES(QD3D12TextureRenderTarget, cbD->currentTarget);
1933 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
1937 if (!colorAtt.resolveTexture())
1940 QD3D12Texture *dstTexD =
QRHI_RES(QD3D12Texture, colorAtt.resolveTexture());
1941 QD3D12Resource *dstRes = resourcePool.lookupRef(dstTexD->handle);
1945 QD3D12Texture *srcTexD =
QRHI_RES(QD3D12Texture, colorAtt.texture());
1946 QD3D12RenderBuffer *srcRbD =
QRHI_RES(QD3D12RenderBuffer, colorAtt.renderBuffer());
1948 QD3D12Resource *srcRes = resourcePool.lookupRef(srcTexD ? srcTexD->handle : srcRbD->
handle);
1953 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
1954 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
1955 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
1958 if (srcTexD->sampleDesc.Count <= 1) {
1959 qWarning(
"Cannot resolve a non-multisample texture");
1962 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
1963 qWarning(
"Resolve source and destination sizes do not match");
1967 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
1968 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
1969 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
1972 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
1973 qWarning(
"Resolve source and destination sizes do not match");
1978 barrierGen.addTransitionBarrier(srcTexD ? srcTexD->handle : srcRbD->
handle, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
1979 barrierGen.addTransitionBarrier(dstTexD->handle, D3D12_RESOURCE_STATE_RESOLVE_DEST);
1980 barrierGen.enqueueBufferedTransitionBarriers(cbD);
1982 const UINT resolveCount = colorAtt.multiViewCount() >= 2 ? colorAtt.multiViewCount() : 1;
1983 for (UINT resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
1984 const UINT srcSubresource = calcSubresource(0, UINT(colorAtt.layer()) + resolveIdx, 1);
1985 const UINT dstSubresource = calcSubresource(UINT(colorAtt.resolveLevel()),
1986 UINT(colorAtt.resolveLayer()) + resolveIdx,
1987 dstTexD->mipLevelCount);
1988 cbD->cmdList->ResolveSubresource(dstRes->resource, dstSubresource,
1989 srcRes->resource, srcSubresource,
1990 dstTexD->dxgiFormat);
1993 if (rtTex->m_desc.depthResolveTexture())
1994 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
1997 cbD->recordingPass = QD3D12CommandBuffer::NoPass;
1998 cbD->currentTarget =
nullptr;
2000 if (resourceUpdates)
2001 enqueueResourceUpdates(cbD, resourceUpdates);
2006 QRhiCommandBuffer::BeginPassFlags)
2008 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
2009 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
2011 if (resourceUpdates)
2012 enqueueResourceUpdates(cbD, resourceUpdates);
2014 cbD->recordingPass = QD3D12CommandBuffer::ComputePass;
2016 cbD->resetPerPassState();
2021 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
2022 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
2024 cbD->recordingPass = QD3D12CommandBuffer::NoPass;
2026 if (resourceUpdates)
2027 enqueueResourceUpdates(cbD, resourceUpdates);
2032 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
2033 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
2034 QD3D12ComputePipeline *psD =
QRHI_RES(QD3D12ComputePipeline, ps);
2035 const bool pipelineChanged = cbD->currentComputePipeline != psD || cbD->currentPipelineGeneration != psD->generation;
2037 if (pipelineChanged) {
2038 cbD->currentGraphicsPipeline =
nullptr;
2039 cbD->currentComputePipeline = psD;
2040 cbD->currentPipelineGeneration = psD->generation;
2042 if (QD3D12Pipeline *pipeline = pipelinePool.lookupRef(psD->handle)) {
2043 Q_ASSERT(pipeline->type == QD3D12Pipeline::Compute);
2044 cbD->cmdList->SetPipelineState(pipeline->pso);
2045 if (QD3D12RootSignature *rs = rootSignaturePool.lookupRef(psD->rootSigHandle))
2046 cbD->cmdList->SetComputeRootSignature(rs->rootSig);
2053 QD3D12CommandBuffer *cbD =
QRHI_RES(QD3D12CommandBuffer,
cb);
2054 Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
2055 cbD->cmdList->Dispatch(UINT(
x), UINT(
y), UINT(
z));
2058bool QD3D12DescriptorHeap::create(ID3D12Device *
device,
2060 D3D12_DESCRIPTOR_HEAP_TYPE heapType,
2061 D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags)
2065 this->heapType = heapType;
2066 this->heapFlags = heapFlags;
2068 D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
2069 heapDesc.Type = heapType;
2070 heapDesc.NumDescriptors =
capacity;
2071 heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAGS(heapFlags);
2073 HRESULT hr =
device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap),
reinterpret_cast<void **
>(&heap));
2075 qWarning(
"Failed to create descriptor heap: %s",
qPrintable(QSystemError::windowsComString(hr)));
2081 descriptorByteSize =
device->GetDescriptorHandleIncrementSize(heapType);
2082 heapStart.cpuHandle = heap->GetCPUDescriptorHandleForHeapStart();
2083 if (heapFlags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
2084 heapStart.gpuHandle = heap->GetGPUDescriptorHandleForHeapStart();
2089void QD3D12DescriptorHeap::createWithExisting(
const QD3D12DescriptorHeap &
other,
2096 heapType =
other.heapType;
2097 heapFlags =
other.heapFlags;
2098 descriptorByteSize =
other.descriptorByteSize;
2099 heapStart = incremented(
other.heapStart, offsetInDescriptors);
2102void QD3D12DescriptorHeap::destroy()
2111void QD3D12DescriptorHeap::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
2114 releaseQueue->deferredReleaseDescriptorHeap(heap);
2120QD3D12Descriptor QD3D12DescriptorHeap::get(
quint32 count)
2131QD3D12Descriptor QD3D12DescriptorHeap::at(
quint32 index)
const
2133 const quint32 startOffset =
index * descriptorByteSize;
2135 result.cpuHandle.ptr = heapStart.cpuHandle.ptr + startOffset;
2136 if (heapStart.gpuHandle.ptr != 0)
2137 result.gpuHandle.ptr = heapStart.gpuHandle.ptr + startOffset;
2141bool QD3D12CpuDescriptorPool::create(ID3D12Device *
device, D3D12_DESCRIPTOR_HEAP_TYPE heapType,
const char *debugName)
2143 QD3D12DescriptorHeap firstHeap;
2144 if (!firstHeap.create(
device, DESCRIPTORS_PER_HEAP, heapType, D3D12_DESCRIPTOR_HEAP_FLAG_NONE))
2146 heaps.append(HeapWithMap::init(firstHeap, DESCRIPTORS_PER_HEAP));
2147 descriptorByteSize = heaps[0].heap.descriptorByteSize;
2149 this->debugName = debugName;
2153void QD3D12CpuDescriptorPool::destroy()
2157 static bool leakCheck =
true;
2163 for (HeapWithMap &heap : heaps) {
2164 const int leakedDescriptorCount = heap.map.count(
true);
2165 if (leakedDescriptorCount > 0) {
2166 qWarning(
"QD3D12CpuDescriptorPool::destroy(): "
2167 "Heap %p for descriptor pool %p '%s' has %d unreleased descriptors",
2168 &heap.heap,
this, debugName, leakedDescriptorCount);
2172 for (HeapWithMap &heap : heaps)
2173 heap.heap.destroy();
2177QD3D12Descriptor QD3D12CpuDescriptorPool::allocate(
quint32 count)
2181 HeapWithMap &last(heaps.last());
2182 if (last.heap.head +
count <= last.heap.capacity) {
2183 quint32 firstIndex = last.heap.head;
2185 last.map.setBit(firstIndex +
i);
2186 return last.heap.get(
count);
2189 for (HeapWithMap &heap : heaps) {
2191 for (
quint32 i = 0;
i < DESCRIPTORS_PER_HEAP; ++
i) {
2192 if (heap.map.testBit(
i)) {
2196 if (freeCount ==
count) {
2197 quint32 firstIndex =
i - (freeCount - 1);
2199 heap.map.setBit(firstIndex +
j);
2200 return heap.heap.at(firstIndex);
2207 QD3D12DescriptorHeap newHeap;
2208 if (!newHeap.create(
device, DESCRIPTORS_PER_HEAP, last.heap.heapType, last.heap.heapFlags))
2211 heaps.append(HeapWithMap::init(newHeap, DESCRIPTORS_PER_HEAP));
2214 heaps.last().map.setBit(
i);
2216 return heaps.last().heap.get(
count);
2219void QD3D12CpuDescriptorPool::release(
const QD3D12Descriptor &descriptor,
quint32 count)
2222 if (!descriptor.isValid())
2225 const SIZE_T
addr = descriptor.cpuHandle.ptr;
2226 for (HeapWithMap &heap : heaps) {
2227 const SIZE_T
begin = heap.heap.heapStart.cpuHandle.ptr;
2228 const SIZE_T
end =
begin + heap.heap.descriptorByteSize * heap.heap.capacity;
2232 heap.map.setBit(firstIndex +
i,
false);
2237 qWarning(
"QD3D12CpuDescriptorPool::release: Descriptor with address %llu is not in any heap",
2238 quint64(descriptor.cpuHandle.ptr));
2241bool QD3D12QueryHeap::create(ID3D12Device *
device,
2243 D3D12_QUERY_HEAP_TYPE heapType)
2247 D3D12_QUERY_HEAP_DESC heapDesc = {};
2248 heapDesc.Type = heapType;
2251 HRESULT hr =
device->CreateQueryHeap(&heapDesc, __uuidof(ID3D12QueryHeap),
reinterpret_cast<void **
>(&heap));
2253 qWarning(
"Failed to create query heap: %s",
qPrintable(QSystemError::windowsComString(hr)));
2262void QD3D12QueryHeap::destroy()
2271bool QD3D12StagingArea::create(QRhiD3D12 *rhi,
quint32 capacity, D3D12_HEAP_TYPE heapType)
2273 Q_ASSERT(heapType == D3D12_HEAP_TYPE_UPLOAD || heapType == D3D12_HEAP_TYPE_READBACK);
2274 D3D12_RESOURCE_DESC resourceDesc = {};
2275 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
2277 resourceDesc.Height = 1;
2278 resourceDesc.DepthOrArraySize = 1;
2279 resourceDesc.MipLevels = 1;
2280 resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
2281 resourceDesc.SampleDesc = { 1, 0 };
2282 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
2283 resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
2284 UINT
state = heapType == D3D12_HEAP_TYPE_UPLOAD ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST;
2285 HRESULT hr = rhi->vma.createResource(heapType,
2287 D3D12_RESOURCE_STATES(
state),
2290 __uuidof(ID3D12Resource),
2291 reinterpret_cast<void **
>(&resource));
2293 qWarning(
"Failed to create buffer for staging area: %s",
2294 qPrintable(QSystemError::windowsComString(hr)));
2298 hr = resource->Map(0,
nullptr, &
p);
2300 qWarning(
"Failed to map buffer for staging area: %s",
2301 qPrintable(QSystemError::windowsComString(hr)));
2306 mem.p =
static_cast<quint8 *
>(
p);
2307 mem.gpuAddr = resource->GetGPUVirtualAddress();
2308 mem.buffer = resource;
2309 mem.bufferOffset = 0;
2317void QD3D12StagingArea::destroy()
2320 resource->Release();
2330void QD3D12StagingArea::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
2333 releaseQueue->deferredReleaseResourceAndAllocation(resource,
allocation);
2337QD3D12StagingArea::Allocation QD3D12StagingArea::get(
quint32 byteSize)
2341 qWarning(
"Failed to allocate %u (%u) bytes from staging area of size %u with %u bytes left",
2342 allocSize, byteSize,
capacity, remainingCapacity());
2358void QD3D12ReleaseQueue::deferredReleaseResource(
const QD3D12ObjectHandle &
handle)
2360 DeferredReleaseEntry e;
2365void QD3D12ReleaseQueue::deferredReleaseResourceWithViews(
const QD3D12ObjectHandle &
handle,
2366 QD3D12CpuDescriptorPool *
pool,
2367 const QD3D12Descriptor &viewsStart,
2370 DeferredReleaseEntry e;
2371 e.type = DeferredReleaseEntry::Resource;
2373 e.poolForViews =
pool;
2374 e.viewsStart = viewsStart;
2375 e.viewCount = viewCount;
2379void QD3D12ReleaseQueue::deferredReleasePipeline(
const QD3D12ObjectHandle &
handle)
2381 DeferredReleaseEntry e;
2382 e.type = DeferredReleaseEntry::Pipeline;
2387void QD3D12ReleaseQueue::deferredReleaseRootSignature(
const QD3D12ObjectHandle &
handle)
2389 DeferredReleaseEntry e;
2390 e.type = DeferredReleaseEntry::RootSignature;
2395void QD3D12ReleaseQueue::deferredReleaseCallback(std::function<
void(
void*)> callback,
void *userData)
2397 DeferredReleaseEntry e;
2398 e.type = DeferredReleaseEntry::Callback;
2399 e.callback = callback;
2400 e.callbackUserData = userData;
2404void QD3D12ReleaseQueue::deferredReleaseResourceAndAllocation(ID3D12Resource *resource,
2407 DeferredReleaseEntry e;
2408 e.type = DeferredReleaseEntry::ResourceAndAllocation;
2409 e.resourceAndAllocation = { resource,
allocation };
2413void QD3D12ReleaseQueue::deferredReleaseDescriptorHeap(ID3D12DescriptorHeap *heap)
2415 DeferredReleaseEntry e;
2416 e.type = DeferredReleaseEntry::DescriptorHeap;
2417 e.descriptorHeap = heap;
2421void QD3D12ReleaseQueue::deferredReleaseViews(QD3D12CpuDescriptorPool *
pool,
2422 const QD3D12Descriptor &viewsStart,
2425 DeferredReleaseEntry e;
2426 e.type = DeferredReleaseEntry::Views;
2427 e.poolForViews =
pool;
2428 e.viewsStart = viewsStart;
2429 e.viewCount = viewCount;
2433void QD3D12ReleaseQueue::activatePendingDeferredReleaseRequests(
int frameSlot)
2435 for (DeferredReleaseEntry &e :
queue) {
2436 if (!e.frameSlotToBeReleasedIn.has_value())
2437 e.frameSlotToBeReleasedIn = frameSlot;
2441void QD3D12ReleaseQueue::executeDeferredReleases(
int frameSlot,
bool forced)
2443 for (
int i =
queue.count() - 1;
i >= 0; --
i) {
2444 const DeferredReleaseEntry &e(
queue[
i]);
2445 if (forced || (e.frameSlotToBeReleasedIn.has_value() && e.frameSlotToBeReleasedIn.value() == frameSlot)) {
2447 case DeferredReleaseEntry::Resource:
2448 resourcePool->remove(e.handle);
2449 if (e.poolForViews && e.viewsStart.isValid() && e.viewCount > 0)
2450 e.poolForViews->release(e.viewsStart, e.viewCount);
2452 case DeferredReleaseEntry::Pipeline:
2453 pipelinePool->remove(e.handle);
2455 case DeferredReleaseEntry::RootSignature:
2456 rootSignaturePool->remove(e.handle);
2458 case DeferredReleaseEntry::Callback:
2459 e.callback(e.callbackUserData);
2461 case DeferredReleaseEntry::ResourceAndAllocation:
2464 e.resourceAndAllocation.first->Release();
2465 if (e.resourceAndAllocation.second)
2466 e.resourceAndAllocation.second->Release();
2468 case DeferredReleaseEntry::DescriptorHeap:
2469 e.descriptorHeap->Release();
2471 case DeferredReleaseEntry::Views:
2472 e.poolForViews->release(e.viewsStart, e.viewCount);
2480void QD3D12ReleaseQueue::releaseAll()
2482 executeDeferredReleases(0,
true);
2485void QD3D12ResourceBarrierGenerator::addTransitionBarrier(
const QD3D12ObjectHandle &resourceHandle,
2486 D3D12_RESOURCE_STATES stateAfter)
2488 if (QD3D12Resource *
res = resourcePool->lookupRef(resourceHandle)) {
2489 if (stateAfter !=
res->state) {
2490 transitionResourceBarriers.append({ resourceHandle,
res->state, stateAfter });
2491 res->state = stateAfter;
2496void QD3D12ResourceBarrierGenerator::enqueueBufferedTransitionBarriers(QD3D12CommandBuffer *cbD)
2498 QVarLengthArray<D3D12_RESOURCE_BARRIER, PREALLOC> barriers;
2499 for (
const TransitionResourceBarrier &trb : transitionResourceBarriers) {
2500 if (QD3D12Resource *
res = resourcePool->lookupRef(trb.resourceHandle)) {
2501 D3D12_RESOURCE_BARRIER barrier = {};
2502 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
2503 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
2504 barrier.Transition.pResource =
res->resource;
2505 barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
2506 barrier.Transition.StateBefore = trb.stateBefore;
2507 barrier.Transition.StateAfter = trb.stateAfter;
2508 barriers.append(barrier);
2511 transitionResourceBarriers.clear();
2512 if (!barriers.isEmpty())
2513 cbD->cmdList->ResourceBarrier(barriers.count(), barriers.constData());
2516void QD3D12ResourceBarrierGenerator::enqueueSubresourceTransitionBarrier(QD3D12CommandBuffer *cbD,
2517 const QD3D12ObjectHandle &resourceHandle,
2519 D3D12_RESOURCE_STATES stateBefore,
2520 D3D12_RESOURCE_STATES stateAfter)
2522 if (QD3D12Resource *
res = resourcePool->lookupRef(resourceHandle)) {
2523 D3D12_RESOURCE_BARRIER barrier = {};
2524 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
2525 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
2526 barrier.Transition.pResource =
res->resource;
2527 barrier.Transition.Subresource = subresource;
2528 barrier.Transition.StateBefore = stateBefore;
2529 barrier.Transition.StateAfter = stateAfter;
2530 cbD->cmdList->ResourceBarrier(1, &barrier);
2534void QD3D12ResourceBarrierGenerator::enqueueUavBarrier(QD3D12CommandBuffer *cbD,
2535 const QD3D12ObjectHandle &resourceHandle)
2537 if (QD3D12Resource *
res = resourcePool->lookupRef(resourceHandle)) {
2538 D3D12_RESOURCE_BARRIER barrier = {};
2539 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
2540 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
2541 barrier.UAV.pResource =
res->resource;
2542 cbD->cmdList->ResourceBarrier(1, &barrier);
2546void QD3D12ShaderBytecodeCache::insertWithCapacityLimit(
const QRhiShaderStage &
key,
const Shader &
s)
2548 if (
data.count() >= QRhiD3D12::MAX_SHADER_CACHE_ENTRIES)
2553bool QD3D12ShaderVisibleDescriptorHeap::create(ID3D12Device *
device,
2554 D3D12_DESCRIPTOR_HEAP_TYPE
type,
2555 quint32 perFrameDescriptorCount)
2557 Q_ASSERT(
type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
2559 quint32 size = perFrameDescriptorCount * QD3D12_FRAMES_IN_FLIGHT;
2562 const quint32 CBV_SRV_UAV_MAX = 1000000;
2563 const quint32 SAMPLER_MAX = 2048;
2564 if (
type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
2566 else if (
type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
2569 if (!heap.create(
device,
size,
type, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)) {
2570 qWarning(
"Failed to create shader-visible descriptor heap of size %u",
size);
2574 perFrameDescriptorCount =
size / QD3D12_FRAMES_IN_FLIGHT;
2575 quint32 currentOffsetInDescriptors = 0;
2576 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
2577 perFrameHeapSlice[
i].createWithExisting(heap, currentOffsetInDescriptors, perFrameDescriptorCount);
2578 currentOffsetInDescriptors += perFrameDescriptorCount;
2584void QD3D12ShaderVisibleDescriptorHeap::destroy()
2589void QD3D12ShaderVisibleDescriptorHeap::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
2591 heap.destroyWithDeferredRelease(releaseQueue);
2597 return { binding, binding };
2609void QD3D12ShaderResourceVisitor::visit()
2611 for (
int bindingIdx = 0, bindingCount = srb->
m_bindings.
count(); bindingIdx != bindingCount; ++bindingIdx) {
2615 for (
int stageIdx = 0; stageIdx < stageCount; ++stageIdx) {
2616 const QD3D12ShaderStageData *sd = &stageData[stageIdx];
2620 if (!bd->stage.testFlag(qd3d12_stageToSrb(sd->stage)))
2626 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2627 if (shaderRegister >= 0 && uniformBuffer)
2628 uniformBuffer(sd->stage, bd->u.ubuf, shaderRegister, bd->binding);
2634 const int textureBaseShaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2635 const int samplerBaseShaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).second;
2636 for (
int i = 0;
i < bd->u.stex.count; ++
i) {
2637 if (textureBaseShaderRegister >= 0 &&
texture)
2638 texture(sd->stage, bd->u.stex.texSamplers[
i], textureBaseShaderRegister +
i);
2639 if (samplerBaseShaderRegister >= 0 &&
sampler)
2640 sampler(sd->stage, bd->u.stex.texSamplers[
i], samplerBaseShaderRegister +
i);
2647 const int baseShaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2648 if (baseShaderRegister >= 0 &&
texture) {
2649 for (
int i = 0;
i < bd->u.stex.count; ++
i)
2650 texture(sd->stage, bd->u.stex.texSamplers[
i], baseShaderRegister +
i);
2657 const int baseShaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2658 if (baseShaderRegister >= 0 &&
sampler) {
2659 for (
int i = 0;
i < bd->u.stex.count; ++
i)
2660 sampler(sd->stage, bd->u.stex.texSamplers[
i], baseShaderRegister +
i);
2666 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2667 if (shaderRegister >= 0 && storageImage)
2668 storageImage(sd->stage, bd->u.simage, Load, shaderRegister);
2673 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2674 if (shaderRegister >= 0 && storageImage)
2675 storageImage(sd->stage, bd->u.simage, Store, shaderRegister);
2680 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2681 if (shaderRegister >= 0 && storageImage)
2682 storageImage(sd->stage, bd->u.simage, LoadStore, shaderRegister);
2687 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2688 if (shaderRegister >= 0 && storageBuffer)
2689 storageBuffer(sd->stage, bd->u.sbuf, Load, shaderRegister);
2694 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2695 if (shaderRegister >= 0 && storageBuffer)
2696 storageBuffer(sd->stage, bd->u.sbuf, Store, shaderRegister);
2701 const int shaderRegister =
mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
2702 if (shaderRegister >= 0 && storageBuffer)
2703 storageBuffer(sd->stage, bd->u.sbuf, LoadStore, shaderRegister);
2711bool QD3D12SamplerManager::create(ID3D12Device *
device)
2714 if (!shaderVisibleSamplerHeap.create(
device,
2715 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
2716 MAX_SAMPLERS / QD3D12_FRAMES_IN_FLIGHT))
2718 qWarning(
"Could not create shader-visible SAMPLER heap");
2726void QD3D12SamplerManager::destroy()
2729 shaderVisibleSamplerHeap.destroy();
2734QD3D12Descriptor QD3D12SamplerManager::getShaderVisibleDescriptor(
const D3D12_SAMPLER_DESC &desc)
2740 QD3D12Descriptor descriptor = shaderVisibleSamplerHeap.heap.get(1);
2741 if (descriptor.isValid()) {
2742 device->CreateSampler(&desc, descriptor.cpuHandle);
2743 gpuMap.insert({
desc}, descriptor);
2745 qWarning(
"Out of shader-visible SAMPLER descriptor heap space,"
2746 " this should not happen, maximum number of unique samplers is %u",
2747 shaderVisibleSamplerHeap.heap.capacity);
2753bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
2757 D3D12_ROOT_PARAMETER1 rootParams[3] = {};
2758 D3D12_DESCRIPTOR_RANGE1 descriptorRanges[2] = {};
2761 rootParams[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
2762 rootParams[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
2763 rootParams[0].Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
2766 descriptorRanges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
2767 descriptorRanges[0].NumDescriptors = 1;
2768 descriptorRanges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
2769 rootParams[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
2770 rootParams[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
2771 rootParams[1].DescriptorTable.NumDescriptorRanges = 1;
2772 rootParams[1].DescriptorTable.pDescriptorRanges = &descriptorRanges[0];
2775 descriptorRanges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
2776 descriptorRanges[1].NumDescriptors = 4;
2777 rootParams[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
2778 rootParams[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
2779 rootParams[2].DescriptorTable.NumDescriptorRanges = 1;
2780 rootParams[2].DescriptorTable.pDescriptorRanges = &descriptorRanges[1];
2783 D3D12_STATIC_SAMPLER_DESC samplerDesc = {};
2784 samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
2785 samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
2786 samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
2787 samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
2788 samplerDesc.MaxLOD = 10000.0f;
2789 samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
2791 D3D12_VERSIONED_ROOT_SIGNATURE_DESC rsDesc = {};
2792 rsDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
2793 rsDesc.Desc_1_1.NumParameters = 3;
2794 rsDesc.Desc_1_1.pParameters = rootParams;
2795 rsDesc.Desc_1_1.NumStaticSamplers = 1;
2796 rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
2799 HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature,
nullptr);
2801 qWarning(
"Failed to serialize root signature: %s",
qPrintable(QSystemError::windowsComString(hr)));
2804 ID3D12RootSignature *rootSig =
nullptr;
2805 hr = rhiD->dev->CreateRootSignature(0,
2808 __uuidof(ID3D12RootSignature),
2809 reinterpret_cast<void **
>(&rootSig));
2812 qWarning(
"Failed to create root signature: %s",
2813 qPrintable(QSystemError::windowsComString(hr)));
2817 rootSigHandle = QD3D12RootSignature::addToPool(&rhiD->rootSignaturePool, rootSig);
2819 D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
2820 psoDesc.pRootSignature = rootSig;
2821 psoDesc.CS.pShaderBytecode = g_csMipmap;
2822 psoDesc.CS.BytecodeLength =
sizeof(g_csMipmap);
2823 ID3D12PipelineState *pso =
nullptr;
2824 hr = rhiD->dev->CreateComputePipelineState(&psoDesc,
2825 __uuidof(ID3D12PipelineState),
2826 reinterpret_cast<void **
>(&pso));
2828 qWarning(
"Failed to create compute pipeline state: %s",
2829 qPrintable(QSystemError::windowsComString(hr)));
2830 rhiD->rootSignaturePool.remove(rootSigHandle);
2835 pipelineHandle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Compute, pso);
2840void QD3D12MipmapGenerator::destroy()
2842 rhiD->pipelinePool.remove(pipelineHandle);
2843 pipelineHandle = {};
2844 rhiD->rootSignaturePool.remove(rootSigHandle);
2848void QD3D12MipmapGenerator::generate(QD3D12CommandBuffer *cbD,
const QD3D12ObjectHandle &textureHandle)
2850 QD3D12Pipeline *pipeline = rhiD->pipelinePool.lookupRef(pipelineHandle);
2853 QD3D12RootSignature *rootSig = rhiD->rootSignaturePool.lookupRef(rootSigHandle);
2856 QD3D12Resource *
res = rhiD->resourcePool.lookupRef(textureHandle);
2860 const quint32 mipLevelCount =
res->desc.MipLevels;
2861 if (mipLevelCount < 2)
2864 if (
res->desc.SampleDesc.Count > 1) {
2865 qWarning(
"Cannot generate mipmaps for MSAA texture");
2869 const bool is1D =
res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D;
2871 qWarning(
"Cannot generate mipmaps for 1D texture");
2875 const bool is3D =
res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D;
2876 const bool isCubeOrArray =
res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
2877 &&
res->desc.DepthOrArraySize > 1;
2878 const quint32 layerCount = isCubeOrArray ?
res->desc.DepthOrArraySize : 1;
2882 qWarning(
"3D texture mipmapping is not implemented for D3D12 atm");
2886 rhiD->barrierGen.addTransitionBarrier(textureHandle, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
2887 rhiD->barrierGen.enqueueBufferedTransitionBarriers(cbD);
2889 cbD->cmdList->SetPipelineState(pipeline->pso);
2890 cbD->cmdList->SetComputeRootSignature(rootSig->rootSig);
2892 const quint32 descriptorByteSize = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].descriptorByteSize;
2901 const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(
sizeof(CBufData), mipLevelCount * layerCount);
2902 std::optional<QD3D12StagingArea> ownStagingArea;
2903 if (rhiD->smallStagingAreas[rhiD->currentFrameSlot].remainingCapacity() < allocSize) {
2904 ownStagingArea = QD3D12StagingArea();
2905 if (!ownStagingArea->create(rhiD, allocSize, D3D12_HEAP_TYPE_UPLOAD)) {
2906 qWarning(
"Could not create staging area for mipmap generation");
2910 QD3D12StagingArea *workArea = ownStagingArea.has_value()
2911 ? &ownStagingArea.value()
2912 : &rhiD->smallStagingAreas[rhiD->currentFrameSlot];
2914 bool gotNewHeap =
false;
2915 if (!rhiD->ensureShaderVisibleDescriptorHeapCapacity(&rhiD->shaderVisibleCbvSrvUavHeap,
2916 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
2917 rhiD->currentFrameSlot,
2918 (1 + 4) * mipLevelCount * layerCount,
2921 qWarning(
"Could not ensure enough space in descriptor heap for mipmap generation");
2925 rhiD->bindShaderVisibleHeaps(cbD);
2929 UINT subresource = calcSubresource(
level,
layer,
res->desc.MipLevels);
2930 rhiD->barrierGen.enqueueSubresourceTransitionBarrier(cbD, textureHandle, subresource,
2931 D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
2932 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
2936 const quint32 dw = levelPlusOneMipWidth == 1 ? levelPlusOneMipHeight : levelPlusOneMipWidth;
2937 const quint32 dh = levelPlusOneMipHeight == 1 ? levelPlusOneMipWidth : levelPlusOneMipHeight;
2941 levelPlusOneMipWidth =
qMax(1u, levelPlusOneMipWidth);
2942 levelPlusOneMipHeight =
qMax(1u, levelPlusOneMipHeight);
2944 CBufData cbufData = {
2947 1.0f / float(levelPlusOneMipWidth),
2948 1.0f / float(levelPlusOneMipHeight)
2951 QD3D12StagingArea::Allocation cbuf = workArea->get(
sizeof(cbufData));
2952 memcpy(cbuf.p, &cbufData,
sizeof(cbufData));
2953 cbD->cmdList->SetComputeRootConstantBufferView(0, cbuf.gpuAddr);
2955 QD3D12Descriptor srv = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].get(1);
2956 D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
2957 srvDesc.Format =
res->desc.Format;
2958 srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
2959 if (isCubeOrArray) {
2960 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
2961 srvDesc.Texture2DArray.MostDetailedMip =
level;
2962 srvDesc.Texture2DArray.MipLevels = 1;
2963 srvDesc.Texture2DArray.FirstArraySlice =
layer;
2964 srvDesc.Texture2DArray.ArraySize = 1;
2966 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
2967 srvDesc.Texture3D.MostDetailedMip =
level;
2968 srvDesc.Texture3D.MipLevels = 1;
2970 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
2971 srvDesc.Texture2D.MostDetailedMip =
level;
2972 srvDesc.Texture2D.MipLevels = 1;
2974 rhiD->dev->CreateShaderResourceView(
res->resource, &srvDesc, srv.cpuHandle);
2975 cbD->cmdList->SetComputeRootDescriptorTable(1, srv.gpuHandle);
2977 QD3D12Descriptor uavStart = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].get(4);
2978 D3D12_CPU_DESCRIPTOR_HANDLE uavCpuHandle = uavStart.cpuHandle;
2980 for (
quint32 uavIdx = 0; uavIdx < 4; ++uavIdx) {
2982 D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
2983 uavDesc.Format =
res->desc.Format;
2984 if (isCubeOrArray) {
2985 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
2986 uavDesc.Texture2DArray.MipSlice = uavMipLevel;
2987 uavDesc.Texture2DArray.FirstArraySlice =
layer;
2988 uavDesc.Texture2DArray.ArraySize = 1;
2990 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
2991 uavDesc.Texture3D.MipSlice = uavMipLevel;
2992 uavDesc.Texture3D.FirstWSlice = 0;
2993 uavDesc.Texture3D.WSize = 1;
2995 uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
2996 uavDesc.Texture2D.MipSlice = uavMipLevel;
2998 rhiD->dev->CreateUnorderedAccessView(
res->resource,
nullptr, &uavDesc, uavCpuHandle);
2999 uavCpuHandle.ptr += descriptorByteSize;
3001 cbD->cmdList->SetComputeRootDescriptorTable(2, uavStart.gpuHandle);
3003 cbD->cmdList->Dispatch(levelPlusOneMipWidth, levelPlusOneMipHeight, 1);
3005 rhiD->barrierGen.enqueueUavBarrier(cbD, textureHandle);
3006 rhiD->barrierGen.enqueueSubresourceTransitionBarrier(cbD, textureHandle, subresource,
3007 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
3008 D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
3010 level += numGenMips;
3014 if (ownStagingArea.has_value())
3015 ownStagingArea->destroyWithDeferredRelease(&rhiD->releaseQueue);
3018bool QD3D12MemoryAllocator::create(ID3D12Device *
device, IDXGIAdapter1 *adapter)
3031 DXGI_ADAPTER_DESC1
desc;
3032 adapter->GetDesc1(&desc);
3036 D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
3037 allocatorDesc.pDevice =
device;
3038 allocatorDesc.pAdapter = adapter;
3041 allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_SINGLETHREADED;
3042 HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
3044 qWarning(
"Failed to initialize D3D12 Memory Allocator: %s",
3045 qPrintable(QSystemError::windowsComString(hr)));
3051void QD3D12MemoryAllocator::destroy()
3054 allocator->Release();
3055 allocator =
nullptr;
3059HRESULT QD3D12MemoryAllocator::createResource(D3D12_HEAP_TYPE heapType,
3060 const D3D12_RESOURCE_DESC *resourceDesc,
3061 D3D12_RESOURCE_STATES initialState,
3062 const D3D12_CLEAR_VALUE *optimizedClearValue,
3063 D3D12MA::Allocation **maybeAllocation,
3064 REFIID riidResource,
3068 D3D12MA::ALLOCATION_DESC allocDesc = {};
3069 allocDesc.HeapType = heapType;
3070 return allocator->CreateResource(&allocDesc,
3073 optimizedClearValue,
3078 *maybeAllocation =
nullptr;
3079 D3D12_HEAP_PROPERTIES heapProps = {};
3080 heapProps.Type = heapType;
3081 return device->CreateCommittedResource(&heapProps,
3082 D3D12_HEAP_FLAG_NONE,
3085 optimizedClearValue,
3091void QD3D12MemoryAllocator::getBudget(D3D12MA::Budget *localBudget, D3D12MA::Budget *nonLocalBudget)
3094 allocator->GetBudget(localBudget, nonLocalBudget);
3097 *nonLocalBudget = {};
3101void QRhiD3D12::waitGpu()
3103 fullFenceCounter += 1u;
3104 if (SUCCEEDED(cmdQueue->Signal(fullFence, fullFenceCounter))) {
3105 if (SUCCEEDED(fullFence->SetEventOnCompletion(fullFenceCounter, fullFenceEvent)))
3106 WaitForSingleObject(fullFenceEvent, INFINITE);
3110DXGI_SAMPLE_DESC QRhiD3D12::effectiveSampleDesc(
int sampleCount, DXGI_FORMAT
format)
const
3112 DXGI_SAMPLE_DESC
desc;
3116 const int s = effectiveSampleCount(sampleCount);
3119 D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msaaInfo = {};
3120 msaaInfo.Format =
format;
3121 msaaInfo.SampleCount = UINT(
s);
3122 if (SUCCEEDED(dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msaaInfo,
sizeof(msaaInfo)))) {
3123 if (msaaInfo.NumQualityLevels > 0) {
3124 desc.Count = UINT(
s);
3125 desc.Quality = msaaInfo.NumQualityLevels - 1;
3127 qWarning(
"No quality levels for multisampling with sample count %d",
s);
3135bool QRhiD3D12::startCommandListForCurrentFrameSlot(ID3D12GraphicsCommandList1 **cmdList)
3137 ID3D12CommandAllocator *cmdAlloc = cmdAllocators[currentFrameSlot];
3139 HRESULT hr = dev->CreateCommandList(0,
3140 D3D12_COMMAND_LIST_TYPE_DIRECT,
3143 __uuidof(ID3D12GraphicsCommandList1),
3144 reinterpret_cast<void **
>(cmdList));
3146 qWarning(
"Failed to create command list: %s",
qPrintable(QSystemError::windowsComString(hr)));
3150 HRESULT hr = (*cmdList)->Reset(cmdAlloc,
nullptr);
3152 qWarning(
"Failed to reset command list: %s",
qPrintable(QSystemError::windowsComString(hr)));
3162 case DXGI_FORMAT_R8G8B8A8_UNORM:
3164 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
3168 case DXGI_FORMAT_B8G8R8A8_UNORM:
3170 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
3174 case DXGI_FORMAT_R16G16B16A16_FLOAT:
3176 case DXGI_FORMAT_R32G32B32A32_FLOAT:
3178 case DXGI_FORMAT_R10G10B10A2_UNORM:
3191 for (
int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
3194 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer, u.buf);
3196 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
3197 if (u.offset == 0 && u.data.size() == bufD->m_size)
3198 bufD->pendingHostWrites[
i].clear();
3199 bufD->pendingHostWrites[
i].append({ u.offset, u.data });
3202 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer, u.buf);
3204 Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
3212 QD3D12StagingArea::Allocation stagingAlloc;
3213 const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(bufD->m_size, 1);
3214 if (smallStagingAreas[currentFrameSlot].remainingCapacity() >= allocSize)
3215 stagingAlloc = smallStagingAreas[currentFrameSlot].get(bufD->m_size);
3217 std::optional<QD3D12StagingArea> ownStagingArea;
3218 if (!stagingAlloc.isValid()) {
3219 ownStagingArea = QD3D12StagingArea();
3220 if (!ownStagingArea->create(
this, allocSize, D3D12_HEAP_TYPE_UPLOAD))
3222 stagingAlloc = ownStagingArea->get(allocSize);
3223 if (!stagingAlloc.isValid()) {
3224 ownStagingArea->destroy();
3229 memcpy(stagingAlloc.p + u.offset, u.data.constData(), u.data.size());
3231 barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_COPY_DEST);
3232 barrierGen.enqueueBufferedTransitionBarriers(cbD);
3234 if (QD3D12Resource *
res = resourcePool.lookupRef(bufD->handles[0])) {
3235 cbD->cmdList->CopyBufferRegion(
res->resource,
3237 stagingAlloc.buffer,
3238 stagingAlloc.bufferOffset + u.offset,
3242 if (ownStagingArea.has_value())
3243 ownStagingArea->destroyWithDeferredRelease(&releaseQueue);
3245 QD3D12Buffer *bufD =
QRHI_RES(QD3D12Buffer, u.buf);
3247 bufD->executeHostWritesForFrameSlot(currentFrameSlot);
3248 if (QD3D12Resource *
res = resourcePool.lookupRef(bufD->handles[currentFrameSlot])) {
3250 u.result->data.resize(u.readSize);
3251 memcpy(u.result->data.data(),
reinterpret_cast<char *
>(
res->cpuMapPtr) + u.offset, u.readSize);
3253 if (u.result->completed)
3254 u.result->completed();
3256 QD3D12Readback readback;
3257 readback.frameSlot = currentFrameSlot;
3258 readback.result = u.result;
3259 readback.byteSize = u.readSize;
3260 const quint32 allocSize =
aligned(u.readSize, QD3D12StagingArea::ALIGNMENT);
3261 if (!readback.staging.create(
this, allocSize, D3D12_HEAP_TYPE_READBACK)) {
3262 if (u.result->completed)
3263 u.result->completed();
3266 QD3D12StagingArea::Allocation stagingAlloc = readback.staging.get(u.readSize);
3267 if (!stagingAlloc.isValid()) {
3268 readback.staging.destroy();
3269 if (u.result->completed)
3270 u.result->completed();
3273 Q_ASSERT(stagingAlloc.bufferOffset == 0);
3274 barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_COPY_SOURCE);
3275 barrierGen.enqueueBufferedTransitionBarriers(cbD);
3276 if (QD3D12Resource *
res = resourcePool.lookupRef(bufD->handles[0])) {
3277 cbD->cmdList->CopyBufferRegion(stagingAlloc.buffer, 0,
res->resource, u.offset, u.readSize);
3278 activeReadbacks.append(readback);
3280 readback.staging.destroy();
3281 if (u.result->completed)
3282 u.result->completed();
3288 for (
int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
3291 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture, u.dst);
3293 QD3D12Resource *
res = resourcePool.lookupRef(texD->handle);
3296 barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_COPY_DEST);
3297 barrierGen.enqueueBufferedTransitionBarriers(cbD);
3298 for (
int layer = 0, maxLayer = u.subresDesc.size();
layer < maxLayer; ++
layer) {
3301 D3D12_SUBRESOURCE_FOOTPRINT footprint = {};
3302 footprint.Format =
res->desc.Format;
3303 footprint.Depth = 1;
3306 const QSize subresSize = subresDesc.sourceSize().
isEmpty() ?
q->sizeForMipLevel(
level, texD->m_pixelSize)
3307 : subresDesc.sourceSize();
3308 const QPoint srcPos = subresDesc.sourceTopLeft();
3309 QPoint dstPos = subresDesc.destinationTopLeft();
3311 if (!subresDesc.image().isNull()) {
3314 footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
3315 totalBytes = footprint.RowPitch *
img.height();
3319 compressedFormatInfo(texD->m_format, subresSize, &bpl,
nullptr, &blockDim);
3320 footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
3321 const int rowCount =
aligned(subresSize.height(), blockDim.height()) / blockDim.height();
3322 totalBytes = footprint.RowPitch * rowCount;
3323 }
else if (!subresDesc.data().isEmpty()) {
3325 if (subresDesc.dataStride())
3326 bpl = subresDesc.dataStride();
3328 textureFormatInfo(texD->m_format, subresSize, &bpl,
nullptr,
nullptr);
3329 footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
3330 totalBytes = footprint.RowPitch * subresSize.height();
3336 const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(totalBytes, 1);
3337 QD3D12StagingArea::Allocation stagingAlloc;
3338 if (smallStagingAreas[currentFrameSlot].remainingCapacity() >= allocSize)
3339 stagingAlloc = smallStagingAreas[currentFrameSlot].get(allocSize);
3341 std::optional<QD3D12StagingArea> ownStagingArea;
3342 if (!stagingAlloc.isValid()) {
3343 ownStagingArea = QD3D12StagingArea();
3344 if (!ownStagingArea->create(
this, allocSize, D3D12_HEAP_TYPE_UPLOAD))
3346 stagingAlloc = ownStagingArea->get(allocSize);
3347 if (!stagingAlloc.isValid()) {
3348 ownStagingArea->destroy();
3353 D3D12_TEXTURE_COPY_LOCATION
dst;
3354 dst.pResource =
res->resource;
3355 dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3356 dst.SubresourceIndex = calcSubresource(UINT(
level), is3D ? 0u : UINT(
layer), texD->mipLevelCount);
3357 D3D12_TEXTURE_COPY_LOCATION
src;
3358 src.pResource = stagingAlloc.buffer;
3359 src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
3360 src.PlacedFootprint.Offset = stagingAlloc.bufferOffset;
3364 if (!subresDesc.image().isNull()) {
3366 const int bpc =
qMax(1,
img.depth() / 8);
3367 const int bpl =
img.bytesPerLine();
3373 footprint.Width =
size.width();
3374 footprint.Height =
size.height();
3378 srcBox.right = UINT(
size.width());
3379 srcBox.bottom = UINT(
size.height());
3383 const uchar *imgPtr =
img.constBits();
3385 for (
int y = 0,
h =
size.height();
y <
h; ++
y) {
3386 memcpy(stagingAlloc.p +
y * footprint.RowPitch,
3387 imgPtr + srcPos.x() * bpc + (
y + srcPos.y()) * bpl,
3393 compressedFormatInfo(texD->m_format, subresSize, &bpl,
nullptr, &blockDim);
3395 dstPos.setX(
aligned(dstPos.x(), blockDim.width()));
3396 dstPos.setY(
aligned(dstPos.y(), blockDim.height()));
3401 srcBox.right =
aligned(subresSize.width(), blockDim.width());
3402 srcBox.bottom =
aligned(subresSize.height(), blockDim.height());
3407 footprint.Width =
aligned(subresSize.width(), blockDim.width());
3408 footprint.Height =
aligned(subresSize.height(), blockDim.height());
3410 const quint32 copyBytes =
qMin(bpl, footprint.RowPitch);
3412 const char *imgPtr = imgData.constData();
3413 const int rowCount =
aligned(subresSize.height(), blockDim.height()) / blockDim.height();
3414 for (
int y = 0;
y < rowCount; ++
y)
3415 memcpy(stagingAlloc.p +
y * footprint.RowPitch, imgPtr +
y * bpl, copyBytes);
3416 }
else if (!subresDesc.data().isEmpty()) {
3419 srcBox.right = subresSize.width();
3420 srcBox.bottom = subresSize.height();
3424 footprint.Width = subresSize.width();
3425 footprint.Height = subresSize.height();
3428 if (subresDesc.dataStride())
3429 bpl = subresDesc.dataStride();
3431 textureFormatInfo(texD->m_format, subresSize, &bpl,
nullptr,
nullptr);
3433 const quint32 copyBytes =
qMin(bpl, footprint.RowPitch);
3435 const char *imgPtr =
data.constData();
3436 for (
int y = 0,
h = subresSize.height();
y <
h; ++
y)
3437 memcpy(stagingAlloc.p +
y * footprint.RowPitch, imgPtr +
y * bpl, copyBytes);
3440 src.PlacedFootprint.Footprint = footprint;
3442 cbD->cmdList->CopyTextureRegion(&
dst,
3445 is3D ? UINT(
layer) : 0u,
3449 if (ownStagingArea.has_value())
3450 ownStagingArea->destroyWithDeferredRelease(&releaseQueue);
3456 QD3D12Texture *srcD =
QRHI_RES(QD3D12Texture, u.src);
3457 QD3D12Texture *dstD =
QRHI_RES(QD3D12Texture, u.dst);
3460 QD3D12Resource *srcRes = resourcePool.lookupRef(srcD->handle);
3461 QD3D12Resource *dstRes = resourcePool.lookupRef(dstD->handle);
3462 if (!srcRes || !dstRes)
3465 barrierGen.addTransitionBarrier(srcD->handle, D3D12_RESOURCE_STATE_COPY_SOURCE);
3466 barrierGen.addTransitionBarrier(dstD->handle, D3D12_RESOURCE_STATE_COPY_DEST);
3467 barrierGen.enqueueBufferedTransitionBarriers(cbD);
3469 const UINT srcSubresource = calcSubresource(UINT(u.desc.sourceLevel()),
3470 srcIs3D ? 0u : UINT(u.
desc.sourceLayer()),
3471 srcD->mipLevelCount);
3472 const UINT dstSubresource = calcSubresource(UINT(u.desc.destinationLevel()),
3473 dstIs3D ? 0u : UINT(u.
desc.destinationLayer()),
3474 dstD->mipLevelCount);
3475 const QPoint dp = u.desc.destinationTopLeft();
3476 const QSize mipSize =
q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
3477 const QSize copySize = u.desc.pixelSize().
isEmpty() ? mipSize : u.desc.pixelSize();
3478 const QPoint sp = u.desc.sourceTopLeft();
3481 srcBox.left = UINT(
sp.x());
3482 srcBox.top = UINT(
sp.y());
3483 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
3485 srcBox.right = srcBox.left + UINT(copySize.width());
3486 srcBox.bottom = srcBox.top + UINT(copySize.height());
3487 srcBox.back = srcBox.front + 1;
3489 D3D12_TEXTURE_COPY_LOCATION
src;
3490 src.pResource = srcRes->resource;
3491 src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3492 src.SubresourceIndex = srcSubresource;
3493 D3D12_TEXTURE_COPY_LOCATION
dst;
3494 dst.pResource = dstRes->resource;
3495 dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3496 dst.SubresourceIndex = dstSubresource;
3498 cbD->cmdList->CopyTextureRegion(&
dst,
3501 dstIs3D ? UINT(u.desc.destinationLayer()) : 0u,
3505 QD3D12Readback readback;
3506 readback.frameSlot = currentFrameSlot;
3507 readback.result = u.result;
3509 QD3D12ObjectHandle srcHandle;
3511 if (u.rb.texture()) {
3512 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture, u.rb.texture());
3513 if (texD->sampleDesc.Count > 1) {
3514 qWarning(
"Multisample texture cannot be read back");
3518 readback.pixelSize =
q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
3519 readback.format = texD->m_format;
3520 srcHandle = texD->handle;
3523 readback.pixelSize = currentSwapChain->pixelSize;
3527 srcHandle = currentSwapChain->colorBuffers[currentSwapChain->currentBackBufferIndex];
3530 textureFormatInfo(readback.format,
3532 &readback.bytesPerLine,
3536 QD3D12Resource *srcRes = resourcePool.lookupRef(srcHandle);
3540 const UINT subresource = calcSubresource(UINT(u.rb.level()),
3541 is3D ? 0u : UINT(u.rb.
layer()),
3542 srcRes->
desc.MipLevels);
3543 D3D12_PLACED_SUBRESOURCE_FOOTPRINT
layout;
3546 UINT64 totalBytes = 0;
3547 dev->GetCopyableFootprints(&srcRes->desc, subresource, 1, 0,
3548 &
layout,
nullptr,
nullptr, &totalBytes);
3549 readback.stagingRowPitch =
layout.Footprint.RowPitch;
3551 const quint32 allocSize = aligned<quint32>(totalBytes, QD3D12StagingArea::ALIGNMENT);
3552 if (!readback.staging.create(
this, allocSize, D3D12_HEAP_TYPE_READBACK)) {
3553 if (u.result->completed)
3554 u.result->completed();
3557 QD3D12StagingArea::Allocation stagingAlloc = readback.staging.get(totalBytes);
3558 if (!stagingAlloc.isValid()) {
3559 readback.staging.destroy();
3560 if (u.result->completed)
3561 u.result->completed();
3564 Q_ASSERT(stagingAlloc.bufferOffset == 0);
3566 barrierGen.addTransitionBarrier(srcHandle, D3D12_RESOURCE_STATE_COPY_SOURCE);
3567 barrierGen.enqueueBufferedTransitionBarriers(cbD);
3569 D3D12_TEXTURE_COPY_LOCATION
dst;
3570 dst.pResource = stagingAlloc.buffer;
3571 dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
3572 dst.PlacedFootprint.Offset = 0;
3573 dst.PlacedFootprint.Footprint =
layout.Footprint;
3575 D3D12_TEXTURE_COPY_LOCATION
src;
3576 src.pResource = srcRes->resource;
3577 src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
3578 src.SubresourceIndex = subresource;
3580 D3D12_BOX srcBox = {};
3582 srcBox.front = UINT(u.rb.layer());
3583 srcBox.back = srcBox.front + 1;
3584 srcBox.right = readback.pixelSize.width();
3585 srcBox.bottom = readback.pixelSize.height();
3587 cbD->cmdList->CopyTextureRegion(&
dst, 0, 0, 0, &
src, is3D ? &srcBox :
nullptr);
3588 activeReadbacks.append(readback);
3590 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture, u.dst);
3592 mipmapGen.generate(cbD, texD->handle);
3599void QRhiD3D12::finishActiveReadbacks(
bool forced)
3603 for (
int i = activeReadbacks.size() - 1;
i >= 0; --
i) {
3604 QD3D12Readback &readback(activeReadbacks[
i]);
3605 if (forced || currentFrameSlot == readback.frameSlot || readback.frameSlot < 0) {
3606 readback.result->format = readback.format;
3607 readback.result->pixelSize = readback.pixelSize;
3608 readback.result->data.resize(
int(readback.byteSize));
3611 quint8 *dstPtr =
reinterpret_cast<quint8 *
>(readback.result->data.data());
3612 const quint8 *srcPtr = readback.staging.mem.p;
3613 const quint32 lineSize =
qMin(readback.bytesPerLine, readback.stagingRowPitch);
3614 for (
int y = 0,
h = readback.pixelSize.height();
y <
h; ++
y)
3615 memcpy(dstPtr +
y * readback.bytesPerLine, srcPtr +
y * readback.stagingRowPitch, lineSize);
3617 memcpy(readback.result->data.data(), readback.staging.mem.p, readback.byteSize);
3620 readback.staging.destroy();
3622 if (readback.result->completed)
3623 completedCallbacks.append(readback.result->completed);
3625 activeReadbacks.removeLast();
3629 for (
auto f : completedCallbacks)
3633bool QRhiD3D12::ensureShaderVisibleDescriptorHeapCapacity(QD3D12ShaderVisibleDescriptorHeap *
h,
3634 D3D12_DESCRIPTOR_HEAP_TYPE
type,
3636 quint32 neededDescriptorCount,
3644 if (
h->perFrameHeapSlice[frameSlot].remainingCapacity() < neededDescriptorCount) {
3645 const quint32 newPerFrameSize =
qMax(
h->perFrameHeapSlice[frameSlot].capacity * 2,
3646 neededDescriptorCount);
3647 QD3D12ShaderVisibleDescriptorHeap newHeap;
3648 if (!newHeap.create(dev,
type, newPerFrameSize)) {
3649 qWarning(
"Could not create new shader-visible descriptor heap");
3652 h->destroyWithDeferredRelease(&releaseQueue);
3659void QRhiD3D12::bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD)
3661 ID3D12DescriptorHeap *heaps[] = {
3662 shaderVisibleCbvSrvUavHeap.heap.heap,
3663 samplerMgr.shaderVisibleSamplerHeap.heap.heap
3665 cbD->cmdList->SetDescriptorHeaps(2, heaps);
3673QD3D12Buffer::~QD3D12Buffer()
3678void QD3D12Buffer::destroy()
3692 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
3694 rhiD->releaseQueue.deferredReleaseResource(handles[
i]);
3696 pendingHostWrites[
i].clear();
3700 rhiD->unregisterResource(
this);
3703bool QD3D12Buffer::create()
3705 if (!handles[0].
isNull())
3709 qWarning(
"UniformBuffer must always be Dynamic");
3714 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3718 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3721 UINT resourceFlags = D3D12_RESOURCE_FLAG_NONE;
3723 resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
3727 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
3728 if (
i == 0 || m_type == Dynamic) {
3729 D3D12_RESOURCE_DESC resourceDesc = {};
3730 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
3731 resourceDesc.Width = roundedSize;
3732 resourceDesc.Height = 1;
3733 resourceDesc.DepthOrArraySize = 1;
3734 resourceDesc.MipLevels = 1;
3735 resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
3736 resourceDesc.SampleDesc = { 1, 0 };
3737 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
3738 resourceDesc.Flags = D3D12_RESOURCE_FLAGS(resourceFlags);
3739 ID3D12Resource *resource =
nullptr;
3742 D3D12_HEAP_TYPE heapType = m_type == Dynamic
3743 ? D3D12_HEAP_TYPE_UPLOAD
3744 : D3D12_HEAP_TYPE_DEFAULT;
3745 D3D12_RESOURCE_STATES resourceState = m_type == Dynamic
3746 ? D3D12_RESOURCE_STATE_GENERIC_READ
3747 : D3D12_RESOURCE_STATE_COMMON;
3748 hr = rhiD->vma.createResource(heapType,
3754 reinterpret_cast<void **
>(&resource));
3757 if (!m_objectName.isEmpty()) {
3759 if (m_type == Dynamic) {
3763 resource->SetName(
reinterpret_cast<LPCWSTR
>(decoratedName.utf16()));
3765 void *cpuMemPtr =
nullptr;
3766 if (m_type == Dynamic) {
3768 hr = resource->Map(0,
nullptr, &cpuMemPtr);
3770 qWarning(
"Map() failed to dynamic buffer");
3771 resource->Release();
3777 handles[
i] = QD3D12Resource::addToPool(&rhiD->resourcePool,
3785 qWarning(
"Failed to create buffer: '%s' Type was %d, size was %u, using D3D12MA was %d.",
3786 qPrintable(QSystemError::windowsComString(hr)),
3789 int(rhiD->vma.isUsingD3D12MA()));
3793 rhiD->registerResource(
this);
3800 Q_ASSERT(
sizeof(
b.objects) /
sizeof(
b.objects[0]) >=
size_t(QD3D12_FRAMES_IN_FLIGHT));
3802 if (m_type == Dynamic) {
3803 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
3804 executeHostWritesForFrameSlot(
i);
3805 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(handles[
i]))
3806 b.objects[
i] =
res->resource;
3808 b.objects[
i] =
nullptr;
3810 b.slotCount = QD3D12_FRAMES_IN_FLIGHT;
3813 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(handles[0]))
3814 b.objects[0] =
res->resource;
3816 b.objects[0] =
nullptr;
3821char *QD3D12Buffer::beginFullDynamicBufferUpdateForCurrentFrame()
3832 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(handles[rhiD->currentFrameSlot]))
3833 return static_cast<char *
>(
res->cpuMapPtr);
3838void QD3D12Buffer::endFullDynamicBufferUpdateForCurrentFrame()
3843void QD3D12Buffer::executeHostWritesForFrameSlot(
int frameSlot)
3845 if (pendingHostWrites[frameSlot].isEmpty())
3850 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(handles[frameSlot])) {
3852 for (
const QD3D12Buffer::HostWrite &u :
std::as_const(pendingHostWrites[frameSlot]))
3855 pendingHostWrites[frameSlot].clear();
3863 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
3865 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
3867 return DXGI_FORMAT_R8_UNORM;
3869 return DXGI_FORMAT_R8G8_UNORM;
3871 return DXGI_FORMAT_R16_UNORM;
3873 return DXGI_FORMAT_R16G16_UNORM;
3875 return DXGI_FORMAT_R8_UNORM;
3878 return DXGI_FORMAT_R16G16B16A16_FLOAT;
3880 return DXGI_FORMAT_R32G32B32A32_FLOAT;
3882 return DXGI_FORMAT_R16_FLOAT;
3884 return DXGI_FORMAT_R32_FLOAT;
3887 return DXGI_FORMAT_R10G10B10A2_UNORM;
3890 return DXGI_FORMAT_R16_TYPELESS;
3892 return DXGI_FORMAT_R24G8_TYPELESS;
3894 return DXGI_FORMAT_R24G8_TYPELESS;
3896 return DXGI_FORMAT_R32_TYPELESS;
3899 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
3901 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
3903 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
3905 return DXGI_FORMAT_BC4_UNORM;
3907 return DXGI_FORMAT_BC5_UNORM;
3909 return DXGI_FORMAT_BC6H_UF16;
3911 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
3916 qWarning(
"QRhiD3D12 does not support ETC2 textures");
3917 return DXGI_FORMAT_R8G8B8A8_UNORM;
3933 qWarning(
"QRhiD3D12 does not support ASTC textures");
3934 return DXGI_FORMAT_R8G8B8A8_UNORM;
3939 return DXGI_FORMAT_R8G8B8A8_UNORM;
3944 const QSize &pixelSize,
3952QD3D12RenderBuffer::~QD3D12RenderBuffer()
3957void QD3D12RenderBuffer::destroy()
3965 rhiD->releaseQueue.deferredReleaseResourceWithViews(
handle, &rhiD->rtvPool, rtv, 1);
3966 else if (dsv.isValid())
3967 rhiD->releaseQueue.deferredReleaseResourceWithViews(
handle, &rhiD->dsvPool, dsv, 1);
3975 rhiD->unregisterResource(
this);
3978bool QD3D12RenderBuffer::create()
3983 if (m_pixelSize.isEmpty())
3992 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
3993 D3D12_RESOURCE_DESC resourceDesc = {};
3994 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
3995 resourceDesc.Width = UINT64(m_pixelSize.width());
3996 resourceDesc.Height = UINT(m_pixelSize.height());
3997 resourceDesc.DepthOrArraySize = 1;
3998 resourceDesc.MipLevels = 1;
3999 resourceDesc.Format = dxgiFormat;
4000 resourceDesc.SampleDesc = sampleDesc;
4001 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
4002 resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
4003 D3D12_CLEAR_VALUE clearValue = {};
4004 clearValue.Format = dxgiFormat;
4006 ID3D12Resource *resource =
nullptr;
4008 HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
4010 D3D12_RESOURCE_STATE_RENDER_TARGET,
4013 __uuidof(ID3D12Resource),
4014 reinterpret_cast<void **
>(&resource));
4016 qWarning(
"Failed to create color buffer: %s",
qPrintable(QSystemError::windowsComString(hr)));
4019 handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_RENDER_TARGET,
allocation);
4020 rtv = rhiD->rtvPool.allocate(1);
4023 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4024 rtvDesc.Format = dxgiFormat;
4025 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS
4026 : D3D12_RTV_DIMENSION_TEXTURE2D;
4027 rhiD->dev->CreateRenderTargetView(resource, &rtvDesc, rtv.cpuHandle);
4032 dxgiFormat = DS_FORMAT;
4033 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
4034 D3D12_RESOURCE_DESC resourceDesc = {};
4035 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
4036 resourceDesc.Width = UINT64(m_pixelSize.width());
4037 resourceDesc.Height = UINT(m_pixelSize.height());
4038 resourceDesc.DepthOrArraySize = 1;
4039 resourceDesc.MipLevels = 1;
4040 resourceDesc.Format = dxgiFormat;
4041 resourceDesc.SampleDesc = sampleDesc;
4042 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
4043 resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
4044 if (m_flags.testFlag(UsedWithSwapChainOnly))
4045 resourceDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
4046 D3D12_CLEAR_VALUE clearValue = {};
4047 clearValue.Format = dxgiFormat;
4048 clearValue.DepthStencil.Depth = 1.0f;
4049 clearValue.DepthStencil.Stencil = 0;
4050 ID3D12Resource *resource =
nullptr;
4052 HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
4054 D3D12_RESOURCE_STATE_DEPTH_WRITE,
4057 __uuidof(ID3D12Resource),
4058 reinterpret_cast<void **
>(&resource));
4060 qWarning(
"Failed to create depth-stencil buffer: %s",
qPrintable(QSystemError::windowsComString(hr)));
4063 handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_DEPTH_WRITE,
allocation);
4064 dsv = rhiD->dsvPool.allocate(1);
4067 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4068 dsvDesc.Format = dxgiFormat;
4069 dsvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS
4070 : D3D12_DSV_DIMENSION_TEXTURE2D;
4071 rhiD->dev->CreateDepthStencilView(resource, &dsvDesc, dsv.cpuHandle);
4076 if (!m_objectName.isEmpty()) {
4077 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(
handle)) {
4079 res->resource->SetName(
reinterpret_cast<LPCWSTR
>(
name.utf16()));
4084 rhiD->registerResource(
this);
4091 return m_backingFormatHint;
4102QD3D12Texture::~QD3D12Texture()
4107void QD3D12Texture::destroy()
4114 rhiD->releaseQueue.deferredReleaseResourceWithViews(
handle, &rhiD->cbvSrvUavPool, srv, 1);
4120 rhiD->unregisterResource(
this);
4127 return DXGI_FORMAT_R16_FLOAT;
4129 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
4131 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
4133 return DXGI_FORMAT_R32_FLOAT;
4137 Q_UNREACHABLE_RETURN(DXGI_FORMAT_R32_FLOAT);
4145 return DXGI_FORMAT_D16_UNORM;
4147 return DXGI_FORMAT_D24_UNORM_S8_UINT;
4149 return DXGI_FORMAT_D24_UNORM_S8_UINT;
4151 return DXGI_FORMAT_D32_FLOAT;
4155 Q_UNREACHABLE_RETURN(DXGI_FORMAT_D32_FLOAT);
4171bool QD3D12Texture::prepareCreate(
QSize *adjustedSize)
4177 const bool isCube = m_flags.testFlag(CubeMap);
4178 const bool is3D = m_flags.testFlag(ThreeDimensional);
4179 const bool isArray = m_flags.testFlag(TextureArray);
4180 const bool hasMipMaps = m_flags.testFlag(MipMapped);
4181 const bool is1D = m_flags.testFlag(OneDimensional);
4184 : (m_pixelSize.isEmpty() ?
QSize(1, 1) : m_pixelSize);
4191 srvFormat = dxgiFormat;
4192 rtFormat = dxgiFormat;
4194 if (m_writeViewFormat.format != UnknownFormat) {
4200 if (m_readViewFormat.format != UnknownFormat) {
4208 mipLevelCount =
uint(hasMipMaps ? rhiD->q->mipLevelsForSize(
size) : 1);
4209 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
4210 if (sampleDesc.Count > 1) {
4212 qWarning(
"Cubemap texture cannot be multisample");
4216 qWarning(
"3D texture cannot be multisample");
4220 qWarning(
"Multisample texture cannot have mipmaps");
4224 if (isDepth && hasMipMaps) {
4225 qWarning(
"Depth texture cannot have mipmaps");
4228 if (isCube && is3D) {
4229 qWarning(
"Texture cannot be both cube and 3D");
4232 if (isArray && is3D) {
4233 qWarning(
"Texture cannot be both array and 3D");
4236 if (isCube && is1D) {
4237 qWarning(
"Texture cannot be both cube and 1D");
4241 qWarning(
"Texture cannot be both 1D and 3D");
4244 if (m_depth > 1 && !is3D) {
4245 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
4248 if (m_arraySize > 0 && !isArray) {
4249 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
4252 if (m_arraySize < 1 && isArray) {
4253 qWarning(
"Texture is an array but array size is %d", m_arraySize);
4258 *adjustedSize =
size;
4263bool QD3D12Texture::finishCreate()
4266 const bool isCube = m_flags.testFlag(CubeMap);
4267 const bool is3D = m_flags.testFlag(ThreeDimensional);
4268 const bool isArray = m_flags.testFlag(TextureArray);
4269 const bool is1D = m_flags.testFlag(OneDimensional);
4271 D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
4272 srvDesc.Format = srvFormat;
4273 srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
4276 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
4277 srvDesc.TextureCube.MipLevels = mipLevelCount;
4281 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
4282 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
4283 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4284 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
4285 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
4287 srvDesc.Texture1DArray.FirstArraySlice = 0;
4288 srvDesc.Texture1DArray.ArraySize = UINT(
qMax(0, m_arraySize));
4291 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
4292 srvDesc.Texture1D.MipLevels = mipLevelCount;
4294 }
else if (isArray) {
4295 if (sampleDesc.Count > 1) {
4296 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
4297 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4298 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
4299 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
4301 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4302 srvDesc.Texture2DMSArray.ArraySize = UINT(
qMax(0, m_arraySize));
4305 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
4306 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
4307 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4308 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
4309 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
4311 srvDesc.Texture2DArray.FirstArraySlice = 0;
4312 srvDesc.Texture2DArray.ArraySize = UINT(
qMax(0, m_arraySize));
4316 if (sampleDesc.Count > 1) {
4317 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
4319 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
4320 srvDesc.Texture3D.MipLevels = mipLevelCount;
4322 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
4323 srvDesc.Texture2D.MipLevels = mipLevelCount;
4328 srv = rhiD->cbvSrvUavPool.allocate(1);
4332 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(
handle)) {
4333 rhiD->dev->CreateShaderResourceView(
res->resource, &srvDesc, srv.cpuHandle);
4334 if (!m_objectName.isEmpty()) {
4336 res->resource->SetName(
reinterpret_cast<LPCWSTR
>(
name.utf16()));
4346bool QD3D12Texture::create()
4349 if (!prepareCreate(&
size))
4353 const bool isCube = m_flags.testFlag(CubeMap);
4354 const bool is3D = m_flags.testFlag(ThreeDimensional);
4355 const bool isArray = m_flags.testFlag(TextureArray);
4356 const bool is1D = m_flags.testFlag(OneDimensional);
4360 bool needsOptimizedClearValueSpecified =
false;
4361 UINT resourceFlags = 0;
4362 if (m_flags.testFlag(RenderTarget) || sampleDesc.Count > 1) {
4364 resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
4366 resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
4367 needsOptimizedClearValueSpecified =
true;
4369 if (m_flags.testFlag(UsedWithGenerateMips)) {
4371 qWarning(
"Depth texture cannot have mipmaps generated");
4374 resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
4376 if (m_flags.testFlag(UsedWithLoadStore))
4377 resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
4379 D3D12_RESOURCE_DESC resourceDesc = {};
4380 resourceDesc.Dimension = is1D ? D3D12_RESOURCE_DIMENSION_TEXTURE1D
4381 : (is3D ? D3D12_RESOURCE_DIMENSION_TEXTURE3D
4382 : D3D12_RESOURCE_DIMENSION_TEXTURE2D);
4383 resourceDesc.Width = UINT64(
size.width());
4384 resourceDesc.Height = UINT(
size.height());
4385 resourceDesc.DepthOrArraySize = isCube ? 6
4386 : (isArray ? UINT(
qMax(0, m_arraySize))
4387 : (is3D ?
qMax(1, m_depth)
4389 resourceDesc.MipLevels = mipLevelCount;
4390 resourceDesc.Format = dxgiFormat;
4391 resourceDesc.SampleDesc = sampleDesc;
4392 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
4393 resourceDesc.Flags = D3D12_RESOURCE_FLAGS(resourceFlags);
4394 D3D12_CLEAR_VALUE clearValue = {};
4395 clearValue.Format = dxgiFormat;
4398 clearValue.DepthStencil.Depth = 1.0f;
4399 clearValue.DepthStencil.Stencil = 0;
4401 ID3D12Resource *resource =
nullptr;
4403 HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
4405 D3D12_RESOURCE_STATE_COMMON,
4406 needsOptimizedClearValueSpecified ? &clearValue :
nullptr,
4408 __uuidof(ID3D12Resource),
4409 reinterpret_cast<
void **>(&resource));
4411 qWarning(
"Failed to create texture: '%s'"
4412 " Dim was %d Size was %ux%u Depth/ArraySize was %u MipLevels was %u Format was %d Sample count was %d",
4413 qPrintable(QSystemError::windowsComString(hr)),
4414 int(resourceDesc.Dimension),
4415 uint(resourceDesc.Width),
4416 uint(resourceDesc.Height),
4417 uint(resourceDesc.DepthOrArraySize),
4418 uint(resourceDesc.MipLevels),
4419 int(resourceDesc.Format),
4420 int(resourceDesc.SampleDesc.Count));
4424 handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_COMMON,
allocation);
4426 if (!finishCreate())
4429 rhiD->registerResource(
this);
4438 if (!prepareCreate())
4441 ID3D12Resource *resource =
reinterpret_cast<ID3D12Resource *
>(
src.object);
4442 D3D12_RESOURCE_STATES
state = D3D12_RESOURCE_STATES(
src.layout);
4445 handle = QD3D12Resource::addNonOwningToPool(&rhiD->resourcePool, resource,
state);
4447 if (!finishCreate())
4450 rhiD->registerResource(
this);
4457 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(
handle))
4463void QD3D12Texture::setNativeLayout(
int layout)
4466 if (QD3D12Resource *
res = rhiD->resourcePool.lookupRef(
handle))
4467 res->state = D3D12_RESOURCE_STATES(
layout);
4470QD3D12Sampler::QD3D12Sampler(
QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
4471 AddressMode u, AddressMode
v, AddressMode
w)
4472 :
QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u,
v,
w)
4476QD3D12Sampler::~QD3D12Sampler()
4481void QD3D12Sampler::destroy()
4483 shaderVisibleDescriptor = {};
4487 rhiD->unregisterResource(
this);
4495 return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR;
4497 return D3D12_FILTER_MIN_MAG_MIP_POINT;
4500 return D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR;
4502 return D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
4507 return D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
4509 return D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT;
4512 return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
4514 return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
4517 Q_UNREACHABLE_RETURN(D3D12_FILTER_MIN_MAG_MIP_LINEAR);
4524 return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
4526 return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
4528 return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
4530 Q_UNREACHABLE_RETURN(D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
4537 return D3D12_COMPARISON_FUNC_NEVER;
4539 return D3D12_COMPARISON_FUNC_LESS;
4541 return D3D12_COMPARISON_FUNC_EQUAL;
4543 return D3D12_COMPARISON_FUNC_LESS_EQUAL;
4545 return D3D12_COMPARISON_FUNC_GREATER;
4547 return D3D12_COMPARISON_FUNC_NOT_EQUAL;
4549 return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
4551 return D3D12_COMPARISON_FUNC_ALWAYS;
4553 Q_UNREACHABLE_RETURN(D3D12_COMPARISON_FUNC_NEVER);
4556bool QD3D12Sampler::create()
4560 if (m_compareOp !=
Never)
4561 desc.Filter = D3D12_FILTER(
desc.Filter | 0x80);
4565 desc.MaxAnisotropy = 1.0f;
4567 desc.MaxLOD = m_mipmapMode ==
None ? 0.0f : 10000.0f;
4570 rhiD->registerResource(
this,
false);
4574QD3D12Descriptor QD3D12Sampler::lookupOrCreateShaderVisibleDescriptor()
4576 if (!shaderVisibleDescriptor.isValid()) {
4578 shaderVisibleDescriptor = rhiD->samplerMgr.getShaderVisibleDescriptor(desc);
4580 return shaderVisibleDescriptor;
4591QD3D12TextureRenderTarget::~QD3D12TextureRenderTarget()
4596void QD3D12TextureRenderTarget::destroy()
4598 if (!rtv[0].isValid() && !dsv.isValid())
4602 if (dsv.isValid()) {
4603 if (ownsDsv && rhiD)
4604 rhiD->releaseQueue.deferredReleaseViews(&rhiD->dsvPool, dsv, 1);
4608 for (
int i = 0;
i < QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS; ++
i) {
4609 if (rtv[
i].isValid()) {
4610 if (ownsRtv[
i] && rhiD)
4611 rhiD->releaseQueue.deferredReleaseViews(&rhiD->rtvPool, rtv[
i], 1);
4617 rhiD->unregisterResource(
this);
4624 QD3D12RenderPassDescriptor *rpD =
new QD3D12RenderPassDescriptor(m_rhi);
4626 rpD->colorAttachmentCount = 0;
4627 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments();
it != itEnd; ++
it) {
4628 QD3D12Texture *texD =
QRHI_RES(QD3D12Texture,
it->texture());
4629 QD3D12RenderBuffer *rbD =
QRHI_RES(QD3D12RenderBuffer,
it->renderBuffer());
4631 rpD->colorFormat[rpD->colorAttachmentCount] = texD->rtFormat;
4633 rpD->colorFormat[rpD->colorAttachmentCount] = rbD->dxgiFormat;
4634 rpD->colorAttachmentCount += 1;
4637 rpD->hasDepthStencil =
false;
4638 if (m_desc.depthStencilBuffer()) {
4639 rpD->hasDepthStencil =
true;
4640 rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
4641 }
else if (m_desc.depthTexture()) {
4642 QD3D12Texture *depthTexD =
QRHI_RES(QD3D12Texture, m_desc.depthTexture());
4643 rpD->hasDepthStencil =
true;
4647 rpD->updateSerializedFormat();
4650 rhiD->registerResource(rpD);
4654bool QD3D12TextureRenderTarget::create()
4656 if (rtv[0].isValid() || dsv.isValid())
4660 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4661 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4662 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4663 d.colorAttCount = 0;
4666 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments();
it != itEnd; ++
it, ++attIndex) {
4667 d.colorAttCount += 1;
4674 QD3D12Resource *
res = rhiD->resourcePool.lookupRef(texD->handle);
4676 qWarning(
"Could not look up texture handle for render target");
4679 const bool isMultiView =
it->multiViewCount() >= 2;
4680 UINT layerCount = isMultiView ? UINT(
it->multiViewCount()) : 1;
4681 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4682 rtvDesc.Format = texD->rtFormat;
4684 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
4685 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4686 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4687 rtvDesc.Texture2DArray.ArraySize = layerCount;
4690 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
4691 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4692 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4693 rtvDesc.Texture1DArray.ArraySize = layerCount;
4695 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1D;
4696 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4699 if (texD->sampleDesc.Count > 1) {
4700 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
4701 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4702 rtvDesc.Texture2DMSArray.ArraySize = layerCount;
4704 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
4705 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4706 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4707 rtvDesc.Texture2DArray.ArraySize = layerCount;
4710 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
4711 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4712 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4713 rtvDesc.Texture3D.WSize = layerCount;
4715 if (texD->sampleDesc.Count > 1) {
4716 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
4718 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
4719 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4722 rtv[attIndex] = rhiD->rtvPool.allocate(1);
4723 if (!rtv[attIndex].isValid()) {
4724 qWarning(
"Failed to allocate RTV for texture render target");
4727 rhiD->dev->CreateRenderTargetView(
res->resource, &rtvDesc, rtv[attIndex].cpuHandle);
4728 ownsRtv[attIndex] =
true;
4729 if (attIndex == 0) {
4730 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4731 d.sampleCount = int(texD->sampleDesc.Count);
4734 QD3D12RenderBuffer *rbD =
QRHI_RES(QD3D12RenderBuffer, rb);
4735 ownsRtv[attIndex] =
false;
4736 rtv[attIndex] = rbD->rtv;
4737 if (attIndex == 0) {
4738 d.pixelSize = rbD->pixelSize();
4739 d.sampleCount = int(rbD->sampleDesc.Count);
4746 if (hasDepthStencil) {
4747 if (m_desc.depthTexture()) {
4749 QD3D12Texture *depthTexD =
QRHI_RES(QD3D12Texture, m_desc.depthTexture());
4750 QD3D12Resource *
res = rhiD->resourcePool.lookupRef(depthTexD->handle);
4752 qWarning(
"Could not look up depth texture handle");
4755 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4756 dsvDesc.Format = depthTexD->rtFormat;
4757 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS
4758 : D3D12_DSV_DIMENSION_TEXTURE2D;
4760 if (depthTexD->sampleDesc.Count > 1) {
4761 dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
4762 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4763 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4764 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4766 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4767 dsvDesc.Texture2DMSArray.ArraySize = UINT(
qMax(0, depthTexD->arraySize()));
4770 dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
4771 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4772 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4773 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4775 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4776 dsvDesc.Texture2DArray.ArraySize = UINT(
qMax(0, depthTexD->arraySize()));
4780 dsv = rhiD->dsvPool.allocate(1);
4781 if (!dsv.isValid()) {
4782 qWarning(
"Failed to allocate DSV for texture render target");
4785 rhiD->dev->CreateDepthStencilView(
res->resource, &dsvDesc, dsv.cpuHandle);
4786 if (
d.colorAttCount == 0) {
4787 d.pixelSize = depthTexD->pixelSize();
4788 d.sampleCount = int(depthTexD->sampleDesc.Count);
4792 QD3D12RenderBuffer *depthRbD =
QRHI_RES(QD3D12RenderBuffer, m_desc.depthStencilBuffer());
4793 dsv = depthRbD->dsv;
4794 if (
d.colorAttCount == 0) {
4795 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4796 d.sampleCount = int(depthRbD->sampleDesc.Count);
4804 D3D12_CPU_DESCRIPTOR_HANDLE nullDescHandle = { 0 };
4805 for (
int i = 0;
i < QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS; ++
i)
4806 d.rtv[
i] =
i <
d.colorAttCount ? rtv[
i].cpuHandle : nullDescHandle;
4807 d.dsv = dsv.cpuHandle;
4808 d.rp =
QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
4810 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D12Texture, QD3D12RenderBuffer>(m_desc, &
d.currentResIdList);
4812 rhiD->registerResource(
this);
4816QSize QD3D12TextureRenderTarget::pixelSize()
const
4818 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D12Texture, QD3D12RenderBuffer>(m_desc,
d.currentResIdList))
4819 const_cast<QD3D12TextureRenderTarget *
>(
this)->
create();
4824float QD3D12TextureRenderTarget::devicePixelRatio()
const
4829int QD3D12TextureRenderTarget::sampleCount()
const
4831 return d.sampleCount;
4839QD3D12ShaderResourceBindings::~QD3D12ShaderResourceBindings()
4844void QD3D12ShaderResourceBindings::destroy()
4848 rhiD->unregisterResource(
this);
4851bool QD3D12ShaderResourceBindings::create()
4854 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4857 rhiD->updateLayoutDesc(
this);
4859 hasDynamicOffset =
false;
4863 hasDynamicOffset =
true;
4877 rhiD->registerResource(
this,
false);
4881void QD3D12ShaderResourceBindings::updateResources(UpdateFlags
flags)
4892void QD3D12ShaderResourceBindings::visitUniformBuffer(QD3D12Stage
s,
4897 D3D12_ROOT_PARAMETER1 rootParam = {};
4898 rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
4899 rootParam.ShaderVisibility = qd3d12_stageToVisibility(
s);
4900 rootParam.Descriptor.ShaderRegister = shaderRegister;
4901 rootParam.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
4902 visitorData.cbParams[
s].append(rootParam);
4905void QD3D12ShaderResourceBindings::visitTexture(QD3D12Stage
s,
4909 D3D12_DESCRIPTOR_RANGE1
range = {};
4910 range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
4911 range.NumDescriptors = 1;
4912 range.BaseShaderRegister = shaderRegister;
4913 range.OffsetInDescriptorsFromTableStart = visitorData.currentSrvRangeOffset[
s];
4914 visitorData.currentSrvRangeOffset[
s] += 1;
4915 visitorData.srvRanges[
s].append(
range);
4916 if (visitorData.srvRanges[
s].count() == 1) {
4917 visitorData.srvTables[
s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4918 visitorData.srvTables[
s].ShaderVisibility = qd3d12_stageToVisibility(
s);
4922void QD3D12ShaderResourceBindings::visitSampler(QD3D12Stage
s,
4929 int &rangeStoreIdx(visitorData.samplerRangeHeads[
s]);
4930 if (rangeStoreIdx == 16) {
4931 qWarning(
"Sampler count in QD3D12Stage %d exceeds the limit of 16, this is disallowed by QRhi",
s);
4934 D3D12_DESCRIPTOR_RANGE1
range = {};
4935 range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
4936 range.NumDescriptors = 1;
4937 range.BaseShaderRegister = shaderRegister;
4938 visitorData.samplerRanges[
s][rangeStoreIdx] =
range;
4939 D3D12_ROOT_PARAMETER1
param = {};
4940 param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4941 param.ShaderVisibility = qd3d12_stageToVisibility(
s);
4942 param.DescriptorTable.NumDescriptorRanges = 1;
4943 param.DescriptorTable.pDescriptorRanges = &visitorData.samplerRanges[
s][rangeStoreIdx];
4945 visitorData.samplerTables[
s].append(
param);
4948void QD3D12ShaderResourceBindings::visitStorageBuffer(QD3D12Stage
s,
4950 QD3D12ShaderResourceVisitor::StorageOp,
4953 D3D12_DESCRIPTOR_RANGE1
range = {};
4954 range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
4955 range.NumDescriptors = 1;
4956 range.BaseShaderRegister = shaderRegister;
4957 range.OffsetInDescriptorsFromTableStart = visitorData.currentUavRangeOffset[
s];
4958 visitorData.currentUavRangeOffset[
s] += 1;
4959 visitorData.uavRanges[
s].append(
range);
4960 if (visitorData.uavRanges[
s].count() == 1) {
4961 visitorData.uavTables[
s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4962 visitorData.uavTables[
s].ShaderVisibility = qd3d12_stageToVisibility(
s);
4966void QD3D12ShaderResourceBindings::visitStorageImage(QD3D12Stage
s,
4968 QD3D12ShaderResourceVisitor::StorageOp,
4971 D3D12_DESCRIPTOR_RANGE1
range = {};
4972 range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
4973 range.NumDescriptors = 1;
4974 range.BaseShaderRegister = shaderRegister;
4975 range.OffsetInDescriptorsFromTableStart = visitorData.currentUavRangeOffset[
s];
4976 visitorData.currentUavRangeOffset[
s] += 1;
4977 visitorData.uavRanges[
s].append(
range);
4978 if (visitorData.uavRanges[
s].count() == 1) {
4979 visitorData.uavTables[
s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4980 visitorData.uavTables[
s].ShaderVisibility = qd3d12_stageToVisibility(
s);
4984QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(
const QD3D12ShaderStageData *stageData,
5001 QD3D12ShaderResourceVisitor visitor(
this, stageData, stageCount);
5005 using namespace std::placeholders;
5006 visitor.uniformBuffer = std::bind(&QD3D12ShaderResourceBindings::visitUniformBuffer,
this, _1, _2, _3, _4);
5007 visitor.texture = std::bind(&QD3D12ShaderResourceBindings::visitTexture,
this, _1, _2, _3);
5008 visitor.sampler = std::bind(&QD3D12ShaderResourceBindings::visitSampler,
this, _1, _2, _3);
5009 visitor.storageBuffer = std::bind(&QD3D12ShaderResourceBindings::visitStorageBuffer,
this, _1, _2, _3, _4);
5010 visitor.storageImage = std::bind(&QD3D12ShaderResourceBindings::visitStorageImage,
this, _1, _2, _3, _4);
5034 QVarLengthArray<D3D12_ROOT_PARAMETER1, 4> rootParams;
5035 for (
int s = 0;
s < 6; ++
s) {
5036 if (!visitorData.cbParams[
s].isEmpty())
5037 rootParams.append(visitorData.cbParams[
s].constData(), visitorData.cbParams[
s].count());
5039 for (
int s = 0;
s < 6; ++
s) {
5040 if (!visitorData.srvRanges[
s].isEmpty()) {
5041 visitorData.srvTables[
s].DescriptorTable.NumDescriptorRanges = visitorData.srvRanges[
s].count();
5042 visitorData.srvTables[
s].DescriptorTable.pDescriptorRanges = visitorData.srvRanges[
s].constData();
5043 rootParams.append(visitorData.srvTables[
s]);
5046 for (
int s = 0;
s < 6; ++
s) {
5047 if (!visitorData.samplerTables[
s].isEmpty())
5048 rootParams.append(visitorData.samplerTables[
s].constData(), visitorData.samplerTables[
s].count());
5050 for (
int s = 0;
s < 6; ++
s) {
5051 if (!visitorData.uavRanges[
s].isEmpty()) {
5052 visitorData.uavTables[
s].DescriptorTable.NumDescriptorRanges = visitorData.uavRanges[
s].count();
5053 visitorData.uavTables[
s].DescriptorTable.pDescriptorRanges = visitorData.uavRanges[
s].constData();
5054 rootParams.append(visitorData.uavTables[
s]);
5058 D3D12_VERSIONED_ROOT_SIGNATURE_DESC rsDesc = {};
5059 rsDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
5060 if (!rootParams.isEmpty()) {
5061 rsDesc.Desc_1_1.NumParameters = rootParams.count();
5062 rsDesc.Desc_1_1.pParameters = rootParams.constData();
5066 for (
int stageIdx = 0; stageIdx < stageCount; ++stageIdx) {
5067 if (stageData[stageIdx].valid && stageData[stageIdx].stage == VS)
5068 rsFlags |= D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
5070 rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
5073 HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature,
nullptr);
5075 qWarning(
"Failed to serialize root signature: %s",
qPrintable(QSystemError::windowsComString(hr)));
5078 ID3D12RootSignature *rootSig =
nullptr;
5079 hr = rhiD->dev->CreateRootSignature(0,
5082 __uuidof(ID3D12RootSignature),
5083 reinterpret_cast<void **
>(&rootSig));
5086 qWarning(
"Failed to create root signature: %s",
qPrintable(QSystemError::windowsComString(hr)));
5090 return QD3D12RootSignature::addToPool(&rhiD->rootSignaturePool, rootSig);
5102static inline void makeHlslTargetString(
char target[7],
const char stage[3],
int version)
5104 const int smMajor = version / 10;
5105 const int smMinor = version % 10;
5109 target[3] =
'0' + smMajor;
5111 target[5] =
'0' + smMinor;
5115enum class HlslCompileFlag
5117 WithDebugInfo = 0x01
5124 qWarning(
"Unable to resolve function D3DCompile()");
5128 ID3DBlob *bytecode =
nullptr;
5129 ID3DBlob *errors =
nullptr;
5130 UINT d3dCompileFlags = 0;
5131 if (
flags &
int(HlslCompileFlag::WithDebugInfo))
5132 d3dCompileFlags |= D3DCOMPILE_DEBUG;
5134 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
5135 nullptr,
nullptr,
nullptr,
5136 hlslSource.entryPoint().constData(),
target, d3dCompileFlags, 0, &bytecode, &errors);
5137 if (FAILED(hr) || !bytecode) {
5138 qWarning(
"HLSL shader compilation failed: 0x%x",
uint(hr));
5141 int(errors->GetBufferSize()));
5149 memcpy(
result.data(), bytecode->GetBufferPointer(),
size_t(
result.size()));
5150 bytecode->Release();
5154#ifdef QRHI_D3D12_HAS_DXC
5157#define DXC_CP_UTF8 65001
5160#ifndef DXC_ARG_DEBUG
5161#define DXC_ARG_DEBUG L"-Zi"
5166 static std::pair<IDxcCompiler *, IDxcLibrary *> dxc = QRhiD3D::createDxcCompiler();
5167 IDxcCompiler *compiler = dxc.first;
5169 qWarning(
"Unable to instantiate IDxcCompiler. Likely no dxcompiler.dll and dxil.dll present. "
5170 "Use windeployqt or try https://github.com/microsoft/DirectXShaderCompiler/releases");
5173 IDxcLibrary *library = dxc.second;
5177 IDxcBlobEncoding *sourceBlob =
nullptr;
5178 HRESULT hr = library->CreateBlobWithEncodingOnHeapCopy(hlslSource.shader().constData(),
5179 UINT32(hlslSource.shader().size()),
5183 qWarning(
"Failed to create source blob for dxc: 0x%x (%s)",
5185 qPrintable(QSystemError::windowsComString(hr)));
5192 QVarLengthArray<LPCWSTR, 4> argPtrs;
5194 if (
flags &
int(HlslCompileFlag::WithDebugInfo)) {
5196 argPtrs.append(
reinterpret_cast<LPCWSTR
>(debugArg.utf16()));
5199 IDxcOperationResult *
result =
nullptr;
5200 hr = compiler->Compile(sourceBlob,
5202 reinterpret_cast<LPCWSTR
>(entryPointStr.utf16()),
5203 reinterpret_cast<LPCWSTR
>(targetStr.utf16()),
5204 argPtrs.data(), argPtrs.count(),
5208 sourceBlob->Release();
5212 qWarning(
"HLSL shader compilation failed: 0x%x (%s)",
5214 qPrintable(QSystemError::windowsComString(hr)));
5216 IDxcBlobEncoding *errorsBlob =
nullptr;
5217 if (SUCCEEDED(
result->GetErrorBuffer(&errorsBlob))) {
5220 int(errorsBlob->GetBufferSize()));
5221 errorsBlob->Release();
5228 IDxcBlob *bytecode =
nullptr;
5229 if FAILED(
result->GetResult(&bytecode)) {
5230 qWarning(
"No result from IDxcCompiler: 0x%x (%s)",
5232 qPrintable(QSystemError::windowsComString(hr)));
5237 ba.
resize(
int(bytecode->GetBufferSize()));
5238 memcpy(
ba.
data(), bytecode->GetBufferPointer(),
size_t(
ba.
size()));
5239 bytecode->Release();
5252 const int shaderModelMax = 67;
5253 for (
int sm = shaderModelMax; sm >= 50; --sm) {
5257 if (!intermediateBytecodeShader.shader().isEmpty()) {
5259 *usedShaderKey =
key;
5260 return intermediateBytecodeShader.shader();
5267 for (
int sm = shaderModelMax; sm >= 50; --sm) {
5270 if (!hlslSource.shader().isEmpty())
5274 if (hlslSource.shader().isEmpty()) {
5275 qWarning() <<
"No HLSL (shader model 6.7..5.0) code found in baked shader" <<
shader;
5280 *usedShaderKey =
key;
5283 switch (
shader.stage()) {
5285 makeHlslTargetString(
target,
"vs",
key.sourceVersion().version());
5288 makeHlslTargetString(
target,
"hs",
key.sourceVersion().version());
5291 makeHlslTargetString(
target,
"ds",
key.sourceVersion().version());
5294 makeHlslTargetString(
target,
"gs",
key.sourceVersion().version());
5297 makeHlslTargetString(
target,
"ps",
key.sourceVersion().version());
5300 makeHlslTargetString(
target,
"cs",
key.sourceVersion().version());
5304 if (
key.sourceVersion().version() >= 60) {
5305#ifdef QRHI_D3D12_HAS_DXC
5308 qWarning(
"Attempted to runtime-compile HLSL source code for shader model >= 6.0 "
5309 "but the Qt build has no support for DXC. "
5310 "Rebuild Qt with a recent Windows SDK or switch to an MSVC build.");
5321 f |= D3D12_COLOR_WRITE_ENABLE_RED;
5323 f |= D3D12_COLOR_WRITE_ENABLE_GREEN;
5325 f |= D3D12_COLOR_WRITE_ENABLE_BLUE;
5327 f |= D3D12_COLOR_WRITE_ENABLE_ALPHA;
5341 return D3D12_BLEND_ZERO;
5343 return D3D12_BLEND_ONE;
5345 return rgb ? D3D12_BLEND_SRC_COLOR : D3D12_BLEND_SRC_ALPHA;
5347 return rgb ? D3D12_BLEND_INV_SRC_COLOR : D3D12_BLEND_INV_SRC_ALPHA;
5349 return rgb ? D3D12_BLEND_DEST_COLOR : D3D12_BLEND_DEST_ALPHA;
5351 return rgb ? D3D12_BLEND_INV_DEST_COLOR : D3D12_BLEND_INV_DEST_ALPHA;
5353 return D3D12_BLEND_SRC_ALPHA;
5355 return D3D12_BLEND_INV_SRC_ALPHA;
5357 return D3D12_BLEND_DEST_ALPHA;
5359 return D3D12_BLEND_INV_DEST_ALPHA;
5362 return D3D12_BLEND_BLEND_FACTOR;
5365 return D3D12_BLEND_INV_BLEND_FACTOR;
5367 return D3D12_BLEND_SRC_ALPHA_SAT;
5369 return rgb ? D3D12_BLEND_SRC1_COLOR : D3D12_BLEND_SRC1_ALPHA;
5371 return rgb ? D3D12_BLEND_INV_SRC1_COLOR : D3D12_BLEND_INV_SRC1_ALPHA;
5373 return D3D12_BLEND_SRC1_ALPHA;
5375 return D3D12_BLEND_INV_SRC1_ALPHA;
5377 Q_UNREACHABLE_RETURN(D3D12_BLEND_ZERO);
5384 return D3D12_BLEND_OP_ADD;
5386 return D3D12_BLEND_OP_SUBTRACT;
5388 return D3D12_BLEND_OP_REV_SUBTRACT;
5390 return D3D12_BLEND_OP_MIN;
5392 return D3D12_BLEND_OP_MAX;
5394 Q_UNREACHABLE_RETURN(D3D12_BLEND_OP_ADD);
5401 return D3D12_CULL_MODE_NONE;
5403 return D3D12_CULL_MODE_FRONT;
5405 return D3D12_CULL_MODE_BACK;
5407 Q_UNREACHABLE_RETURN(D3D12_CULL_MODE_NONE);
5414 return D3D12_FILL_MODE_SOLID;
5416 return D3D12_FILL_MODE_WIREFRAME;
5418 Q_UNREACHABLE_RETURN(D3D12_FILL_MODE_SOLID);
5425 return D3D12_COMPARISON_FUNC_NEVER;
5427 return D3D12_COMPARISON_FUNC_LESS;
5429 return D3D12_COMPARISON_FUNC_EQUAL;
5431 return D3D12_COMPARISON_FUNC_LESS_EQUAL;
5433 return D3D12_COMPARISON_FUNC_GREATER;
5435 return D3D12_COMPARISON_FUNC_NOT_EQUAL;
5437 return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
5439 return D3D12_COMPARISON_FUNC_ALWAYS;
5441 Q_UNREACHABLE_RETURN(D3D12_COMPARISON_FUNC_ALWAYS);
5448 return D3D12_STENCIL_OP_ZERO;
5450 return D3D12_STENCIL_OP_KEEP;
5452 return D3D12_STENCIL_OP_REPLACE;
5454 return D3D12_STENCIL_OP_INCR_SAT;
5456 return D3D12_STENCIL_OP_DECR_SAT;
5458 return D3D12_STENCIL_OP_INVERT;
5460 return D3D12_STENCIL_OP_INCR;
5462 return D3D12_STENCIL_OP_DECR;
5464 Q_UNREACHABLE_RETURN(D3D12_STENCIL_OP_KEEP);
5471 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
5473 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
5475 qWarning(
"Triangle fans are not supported with D3D");
5476 return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
5478 return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
5480 return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
5482 return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
5484 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
5485 return D3D_PRIMITIVE_TOPOLOGY(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
5487 Q_UNREACHABLE_RETURN(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
5496 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
5499 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
5501 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
5503 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
5505 Q_UNREACHABLE_RETURN(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
5512 return DXGI_FORMAT_R32G32B32A32_FLOAT;
5514 return DXGI_FORMAT_R32G32B32_FLOAT;
5516 return DXGI_FORMAT_R32G32_FLOAT;
5518 return DXGI_FORMAT_R32_FLOAT;
5520 return DXGI_FORMAT_R8G8B8A8_UNORM;
5522 return DXGI_FORMAT_R8G8_UNORM;
5524 return DXGI_FORMAT_R8_UNORM;
5526 return DXGI_FORMAT_R32G32B32A32_UINT;
5528 return DXGI_FORMAT_R32G32B32_UINT;
5530 return DXGI_FORMAT_R32G32_UINT;
5532 return DXGI_FORMAT_R32_UINT;
5534 return DXGI_FORMAT_R32G32B32A32_SINT;
5536 return DXGI_FORMAT_R32G32B32_SINT;
5538 return DXGI_FORMAT_R32G32_SINT;
5540 return DXGI_FORMAT_R32_SINT;
5544 return DXGI_FORMAT_R16G16B16A16_FLOAT;
5546 return DXGI_FORMAT_R16G16_FLOAT;
5548 return DXGI_FORMAT_R16_FLOAT;
5552 return DXGI_FORMAT_R16G16B16A16_UINT;
5554 return DXGI_FORMAT_R16G16_UINT;
5556 return DXGI_FORMAT_R16_UINT;
5560 return DXGI_FORMAT_R16G16B16A16_SINT;
5562 return DXGI_FORMAT_R16G16_SINT;
5564 return DXGI_FORMAT_R16_SINT;
5566 Q_UNREACHABLE_RETURN(DXGI_FORMAT_R32G32B32A32_FLOAT);
5574QD3D12GraphicsPipeline::~QD3D12GraphicsPipeline()
5579void QD3D12GraphicsPipeline::destroy()
5586 rhiD->releaseQueue.deferredReleasePipeline(
handle);
5587 rhiD->releaseQueue.deferredReleaseRootSignature(rootSigHandle);
5594 rhiD->unregisterResource(
this);
5597bool QD3D12GraphicsPipeline::create()
5603 if (!rhiD->sanityCheckGraphicsPipeline(
this))
5606 rhiD->pipelineCreationStart();
5610 const QD3D12Stage d3dStage = qd3d12_stage(shaderStage.type());
5611 stageData[d3dStage].valid =
true;
5612 stageData[d3dStage].stage = d3dStage;
5613 auto cacheIt = rhiD->shaderBytecodeCache.data.constFind(shaderStage);
5614 if (cacheIt != rhiD->shaderBytecodeCache.data.constEnd()) {
5615 shaderBytecode[d3dStage] = cacheIt->bytecode;
5616 stageData[d3dStage].nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5620 int compileFlags = 0;
5621 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5622 compileFlags |= int(HlslCompileFlag::WithDebugInfo);
5623 const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(),
5624 shaderStage.shaderVariant(),
5633 shaderBytecode[d3dStage] = bytecode;
5634 stageData[d3dStage].nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5635 rhiD->shaderBytecodeCache.insertWithCapacityLimit(shaderStage,
5636 { bytecode, stageData[d3dStage].nativeResourceBindingMap });
5640 QD3D12ShaderResourceBindings *srbD =
QRHI_RES(QD3D12ShaderResourceBindings, m_shaderResourceBindings);
5642 rootSigHandle = srbD->createRootSignature(stageData.data(), 5);
5643 if (rootSigHandle.isNull()) {
5644 qWarning(
"Failed to create root signature");
5648 ID3D12RootSignature *rootSig =
nullptr;
5649 if (QD3D12RootSignature *rs = rhiD->rootSignaturePool.lookupRef(rootSigHandle))
5650 rootSig = rs->rootSig;
5652 qWarning(
"Cannot create graphics pipeline state without root signature");
5656 QD3D12RenderPassDescriptor *rpD =
QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
5657 const DXGI_SAMPLE_DESC sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, DXGI_FORMAT(rpD->colorFormat[0]));
5660 QD3D12PipelineStateSubObject<ID3D12RootSignature *, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> rootSig;
5661 QD3D12PipelineStateSubObject<D3D12_INPUT_LAYOUT_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT> inputLayout;
5662 QD3D12PipelineStateSubObject<D3D12_PRIMITIVE_TOPOLOGY_TYPE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY> primitiveTopology;
5663 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS> VS;
5664 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS> HS;
5665 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS> DS;
5666 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS> GS;
5667 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> PS;
5668 QD3D12PipelineStateSubObject<D3D12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER> rasterizerState;
5669 QD3D12PipelineStateSubObject<D3D12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL> depthStencilState;
5670 QD3D12PipelineStateSubObject<D3D12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND> blendState;
5671 QD3D12PipelineStateSubObject<D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> rtFormats;
5672 QD3D12PipelineStateSubObject<DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> dsFormat;
5673 QD3D12PipelineStateSubObject<DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC> sampleDesc;
5674 QD3D12PipelineStateSubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK> sampleMask;
5675 QD3D12PipelineStateSubObject<D3D12_VIEW_INSTANCING_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING> viewInstancingDesc;
5678 stream.rootSig.object = rootSig;
5680 QVarLengthArray<D3D12_INPUT_ELEMENT_DESC, 4> inputDescs;
5682 if (!shaderBytecode[VS].isEmpty()) {
5683 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
5686 D3D12_INPUT_ELEMENT_DESC
desc = {};
5691 const int matrixSlice =
it->matrixSlice();
5692 if (matrixSlice < 0) {
5693 desc.SemanticName =
"TEXCOORD";
5694 desc.SemanticIndex = UINT(
it->location());
5699 matrixSliceSemantics.append(
sem);
5700 desc.SemanticName = matrixSliceSemantics.last().constData();
5701 desc.SemanticIndex = UINT(matrixSlice);
5704 desc.InputSlot = UINT(
it->binding());
5705 desc.AlignedByteOffset =
it->offset();
5708 desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
5709 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
5711 desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
5713 inputDescs.append(desc);
5717 stream.inputLayout.object.NumElements = inputDescs.count();
5718 stream.inputLayout.object.pInputElementDescs = inputDescs.isEmpty() ?
nullptr : inputDescs.constData();
5720 stream.primitiveTopology.object = toD3DTopologyType(m_topology);
5721 topology =
toD3DTopology(m_topology, m_patchControlPointCount);
5724 const int d3dStage = qd3d12_stage(shaderStage.type());
5727 stream.VS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
5728 stream.VS.object.BytecodeLength = shaderBytecode[d3dStage].size();
5731 stream.HS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
5732 stream.HS.object.BytecodeLength = shaderBytecode[d3dStage].size();
5735 stream.DS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
5736 stream.DS.object.BytecodeLength = shaderBytecode[d3dStage].size();
5739 stream.GS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
5740 stream.GS.object.BytecodeLength = shaderBytecode[d3dStage].size();
5743 stream.PS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
5744 stream.PS.object.BytecodeLength = shaderBytecode[d3dStage].size();
5754 stream.rasterizerState.object.FrontCounterClockwise = m_frontFace == CCW;
5755 stream.rasterizerState.object.DepthBias = m_depthBias;
5756 stream.rasterizerState.object.SlopeScaledDepthBias = m_slopeScaledDepthBias;
5757 stream.rasterizerState.object.DepthClipEnable = TRUE;
5758 stream.rasterizerState.object.MultisampleEnable = sampleDesc.Count > 1;
5760 stream.depthStencilState.object.DepthEnable = m_depthTest;
5761 stream.depthStencilState.object.DepthWriteMask = m_depthWrite ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
5763 stream.depthStencilState.object.StencilEnable = m_stencilTest;
5764 if (m_stencilTest) {
5765 stream.depthStencilState.object.StencilReadMask = UINT8(m_stencilReadMask);
5766 stream.depthStencilState.object.StencilWriteMask = UINT8(m_stencilWriteMask);
5767 stream.depthStencilState.object.FrontFace.StencilFailOp =
toD3DStencilOp(m_stencilFront.failOp);
5768 stream.depthStencilState.object.FrontFace.StencilDepthFailOp =
toD3DStencilOp(m_stencilFront.depthFailOp);
5769 stream.depthStencilState.object.FrontFace.StencilPassOp =
toD3DStencilOp(m_stencilFront.passOp);
5770 stream.depthStencilState.object.FrontFace.StencilFunc =
toD3DCompareOp(m_stencilFront.compareOp);
5772 stream.depthStencilState.object.BackFace.StencilDepthFailOp =
toD3DStencilOp(m_stencilBack.depthFailOp);
5774 stream.depthStencilState.object.BackFace.StencilFunc =
toD3DCompareOp(m_stencilBack.compareOp);
5777 stream.blendState.object.IndependentBlendEnable = m_targetBlends.count() > 1;
5778 for (
int i = 0, ie = m_targetBlends.count();
i != ie; ++
i) {
5780 D3D12_RENDER_TARGET_BLEND_DESC blend = {};
5781 blend.BlendEnable =
b.enable;
5789 stream.blendState.object.RenderTarget[
i] = blend;
5791 if (m_targetBlends.isEmpty()) {
5792 D3D12_RENDER_TARGET_BLEND_DESC blend = {};
5793 blend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
5794 stream.blendState.object.RenderTarget[0] = blend;
5797 stream.rtFormats.object.NumRenderTargets = rpD->colorAttachmentCount;
5798 for (
int i = 0;
i < rpD->colorAttachmentCount; ++
i)
5799 stream.rtFormats.object.RTFormats[
i] = DXGI_FORMAT(rpD->colorFormat[
i]);
5801 stream.dsFormat.object = rpD->hasDepthStencil ? DXGI_FORMAT(rpD->dsFormat) : DXGI_FORMAT_UNKNOWN;
5803 stream.sampleDesc.object = sampleDesc;
5805 stream.sampleMask.object = 0xFFFFFFFF;
5807 viewInstanceMask = 0;
5808 const bool isMultiView = m_multiViewCount >= 2;
5809 stream.viewInstancingDesc.object.ViewInstanceCount = isMultiView ? m_multiViewCount : 0;
5810 QVarLengthArray<D3D12_VIEW_INSTANCE_LOCATION, 4> viewInstanceLocations;
5812 for (
int i = 0;
i < m_multiViewCount; ++
i) {
5813 viewInstanceMask |= (1 <<
i);
5814 viewInstanceLocations.append({ 0, UINT(
i) });
5816 stream.viewInstancingDesc.object.pViewInstanceLocations = viewInstanceLocations.constData();
5819 const D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {
sizeof(
stream), &
stream };
5821 ID3D12PipelineState *pso =
nullptr;
5822 HRESULT hr = rhiD->dev->CreatePipelineState(&streamDesc, __uuidof(ID3D12PipelineState),
reinterpret_cast<void **
>(&pso));
5824 qWarning(
"Failed to create graphics pipeline state: %s",
5825 qPrintable(QSystemError::windowsComString(hr)));
5826 rhiD->rootSignaturePool.remove(rootSigHandle);
5831 handle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Graphics, pso);
5833 rhiD->pipelineCreationEnd();
5835 rhiD->registerResource(
this);
5844QD3D12ComputePipeline::~QD3D12ComputePipeline()
5849void QD3D12ComputePipeline::destroy()
5856 rhiD->releaseQueue.deferredReleasePipeline(
handle);
5857 rhiD->releaseQueue.deferredReleaseRootSignature(rootSigHandle);
5864 rhiD->unregisterResource(
this);
5867bool QD3D12ComputePipeline::create()
5873 rhiD->pipelineCreationStart();
5875 stageData.valid =
true;
5876 stageData.stage = CS;
5879 auto cacheIt = rhiD->shaderBytecodeCache.
data.constFind(m_shaderStage);
5880 if (cacheIt != rhiD->shaderBytecodeCache.data.constEnd()) {
5881 shaderBytecode = cacheIt->bytecode;
5882 stageData.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5886 int compileFlags = 0;
5887 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5888 compileFlags |= int(HlslCompileFlag::WithDebugInfo);
5889 const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(),
5890 m_shaderStage.shaderVariant(),
5899 shaderBytecode = bytecode;
5900 stageData.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5901 rhiD->shaderBytecodeCache.insertWithCapacityLimit(m_shaderStage, { bytecode,
5902 stageData.nativeResourceBindingMap });
5905 QD3D12ShaderResourceBindings *srbD =
QRHI_RES(QD3D12ShaderResourceBindings, m_shaderResourceBindings);
5907 rootSigHandle = srbD->createRootSignature(&stageData, 1);
5908 if (rootSigHandle.isNull()) {
5909 qWarning(
"Failed to create root signature");
5913 ID3D12RootSignature *rootSig =
nullptr;
5914 if (QD3D12RootSignature *rs = rhiD->rootSignaturePool.lookupRef(rootSigHandle))
5915 rootSig = rs->rootSig;
5917 qWarning(
"Cannot create compute pipeline state without root signature");
5922 QD3D12PipelineStateSubObject<ID3D12RootSignature *, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> rootSig;
5923 QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS> CS;
5925 stream.rootSig.object = rootSig;
5926 stream.CS.object.pShaderBytecode = shaderBytecode.constData();
5927 stream.CS.object.BytecodeLength = shaderBytecode.size();
5928 const D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {
sizeof(
stream), &
stream };
5929 ID3D12PipelineState *pso =
nullptr;
5930 HRESULT hr = rhiD->dev->CreatePipelineState(&streamDesc, __uuidof(ID3D12PipelineState),
reinterpret_cast<void **
>(&pso));
5932 qWarning(
"Failed to create compute pipeline state: %s",
5933 qPrintable(QSystemError::windowsComString(hr)));
5934 rhiD->rootSignaturePool.remove(rootSigHandle);
5939 handle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Compute, pso);
5941 rhiD->pipelineCreationEnd();
5943 rhiD->registerResource(
this);
5953 serializedFormatData.reserve(16);
5956QD3D12RenderPassDescriptor::~QD3D12RenderPassDescriptor()
5961void QD3D12RenderPassDescriptor::destroy()
5965 rhiD->unregisterResource(
this);
5973 const QD3D12RenderPassDescriptor *
o =
QRHI_RES(
const QD3D12RenderPassDescriptor,
other);
5975 if (colorAttachmentCount !=
o->colorAttachmentCount)
5978 if (hasDepthStencil !=
o->hasDepthStencil)
5981 for (
int i = 0;
i < colorAttachmentCount; ++
i) {
5986 if (hasDepthStencil) {
5987 if (dsFormat !=
o->dsFormat)
5994void QD3D12RenderPassDescriptor::updateSerializedFormat()
5996 serializedFormatData.clear();
5997 auto p = std::back_inserter(serializedFormatData);
5999 *
p++ = colorAttachmentCount;
6000 *
p++ = hasDepthStencil;
6001 for (
int i = 0;
i < colorAttachmentCount; ++
i)
6003 *
p++ = hasDepthStencil ? dsFormat : 0;
6008 QD3D12RenderPassDescriptor *rpD =
new QD3D12RenderPassDescriptor(m_rhi);
6009 rpD->colorAttachmentCount = colorAttachmentCount;
6010 rpD->hasDepthStencil = hasDepthStencil;
6012 rpD->dsFormat = dsFormat;
6014 rpD->updateSerializedFormat();
6017 rhiD->registerResource(rpD);
6021QVector<quint32> QD3D12RenderPassDescriptor::serializedFormat()
const
6023 return serializedFormatData;
6032QD3D12CommandBuffer::~QD3D12CommandBuffer()
6037void QD3D12CommandBuffer::destroy()
6044 nativeHandlesStruct.commandList = cmdList;
6045 return &nativeHandlesStruct;
6054QD3D12SwapChainRenderTarget::~QD3D12SwapChainRenderTarget()
6059void QD3D12SwapChainRenderTarget::destroy()
6064QSize QD3D12SwapChainRenderTarget::pixelSize()
const
6069float QD3D12SwapChainRenderTarget::devicePixelRatio()
const
6074int QD3D12SwapChainRenderTarget::sampleCount()
const
6076 return d.sampleCount;
6081 rtWrapper(rhi,
this),
6082 rtWrapperRight(rhi,
this),
6087QD3D12SwapChain::~QD3D12SwapChain()
6092void QD3D12SwapChain::destroy()
6099 swapChain->Release();
6100 swapChain =
nullptr;
6101 sourceSwapChain1->Release();
6102 sourceSwapChain1 =
nullptr;
6104 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
6105 FrameResources &fr(frameRes[
i]);
6107 fr.fence->Release();
6109 CloseHandle(fr.fenceEvent);
6111 fr.cmdList->Release();
6116 dcompVisual->Release();
6117 dcompVisual =
nullptr;
6121 dcompTarget->Release();
6122 dcompTarget =
nullptr;
6127 rhiD->swapchains.remove(
this);
6128 rhiD->unregisterResource(
this);
6132void QD3D12SwapChain::releaseBuffers()
6137 rhiD->resourcePool.remove(colorBuffers[
i]);
6138 rhiD->rtvPool.release(rtvs[
i], 1);
6140 rhiD->rtvPool.release(rtvsRight[
i], 1);
6142 rhiD->resourcePool.remove(msaaBuffers[
i]);
6143 if (msaaRtvs[
i].isValid())
6144 rhiD->rtvPool.release(msaaRtvs[
i], 1);
6148void QD3D12SwapChain::waitCommandCompletionForFrameSlot(
int frameSlot)
6150 FrameResources &fr(frameRes[frameSlot]);
6151 if (fr.fence->GetCompletedValue() < fr.fenceCounter) {
6152 fr.fence->SetEventOnCompletion(fr.fenceCounter, fr.fenceEvent);
6153 WaitForSingleObject(fr.fenceEvent, INFINITE);
6157void QD3D12SwapChain::addCommandCompletionSignalForCurrentFrameSlot()
6160 FrameResources &fr(frameRes[currentFrameSlot]);
6161 fr.fenceCounter += 1u;
6162 rhiD->cmdQueue->Signal(fr.fence, fr.fenceCounter);
6175QRhiRenderTarget *QD3D12SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
6177 return !stereo || targetBuffer == StereoTargetBuffer::LeftBuffer ? &rtWrapper : &rtWrapperRight;
6180QSize QD3D12SwapChain::surfacePixelSize()
6183 return m_window->size() * m_window->devicePixelRatio();
6186bool QD3D12SwapChain::isFormatSupported(
Format f)
6192 qWarning(
"Attempted to call isFormatSupported() without a window set");
6197 DXGI_OUTPUT_DESC1 desc1;
6199 if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
6212 DXGI_OUTPUT_DESC1 hdrOutputDesc;
6215 info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
6216 info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
6229 QD3D12RenderPassDescriptor *rpD =
new QD3D12RenderPassDescriptor(m_rhi);
6230 rpD->colorAttachmentCount = 1;
6231 rpD->hasDepthStencil = m_depthStencil !=
nullptr;
6232 rpD->colorFormat[0] = int(srgbAdjustedColorFormat);
6233 rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
6234 rpD->updateSerializedFormat();
6237 rhiD->registerResource(rpD);
6241bool QRhiD3D12::ensureDirectCompositionDevice()
6246 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
6248 return dcompDevice ? true :
false;
6251static const DXGI_FORMAT
DEFAULT_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM;
6254void QD3D12SwapChain::chooseFormats()
6258 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
6259 DXGI_OUTPUT_DESC1 hdrOutputDesc;
6263 if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
6265 case HDRExtendedSrgbLinear:
6267 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
6272 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
6282 qWarning(
"The output associated with the window is not HDR capable "
6283 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
6286 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount,
colorFormat);
6289bool QD3D12SwapChain::createOrResize()
6295 const bool needsRegistration = !
window ||
window != m_window;
6302 m_currentPixelSize = surfacePixelSize();
6303 pixelSize = m_currentPixelSize;
6305 if (pixelSize.isEmpty())
6308 HWND hwnd =
reinterpret_cast<HWND
>(
window->winId());
6311 stereo = m_window->format().stereo() && rhiD->dxgiFactory->IsWindowedStereoEnabled();
6313 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
6314 if (rhiD->ensureDirectCompositionDevice()) {
6316 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
6318 qWarning(
"Failed to create Direct Composition target for the window: %s",
6319 qPrintable(QSystemError::windowsComString(hr)));
6322 if (dcompTarget && !dcompVisual) {
6323 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
6325 qWarning(
"Failed to create DirectComposition visual: %s",
6326 qPrintable(QSystemError::windowsComString(hr)));
6331 if (
window->requestedFormat().alphaBufferSize() <= 0)
6332 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
6333 "This may lead to problems.");
6338 if (swapInterval == 0 && rhiD->supportsAllowTearing)
6339 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
6344 DXGI_SWAP_CHAIN_DESC1
desc = {};
6345 desc.Width = UINT(pixelSize.width());
6346 desc.Height = UINT(pixelSize.height());
6348 desc.SampleDesc.Count = 1;
6349 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
6351 desc.Flags = swapChainFlags;
6352 desc.Scaling = DXGI_SCALING_NONE;
6353 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
6354 desc.Stereo = stereo;
6360 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
6365 desc.Scaling = DXGI_SCALING_STRETCH;
6369 hr = rhiD->dxgiFactory->CreateSwapChainForComposition(rhiD->cmdQueue, &desc,
nullptr, &sourceSwapChain1);
6371 hr = rhiD->dxgiFactory->CreateSwapChainForHwnd(rhiD->cmdQueue, hwnd, &desc,
nullptr,
nullptr, &sourceSwapChain1);
6376 if (FAILED(hr) && m_format != SDR) {
6380 hr = rhiD->dxgiFactory->CreateSwapChainForComposition(rhiD->cmdQueue, &desc,
nullptr, &sourceSwapChain1);
6382 hr = rhiD->dxgiFactory->CreateSwapChainForHwnd(rhiD->cmdQueue, hwnd, &desc,
nullptr,
nullptr, &sourceSwapChain1);
6385 if (SUCCEEDED(hr)) {
6386 if (FAILED(sourceSwapChain1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<void **
>(&swapChain)))) {
6387 qWarning(
"IDXGISwapChain3 not available");
6390 if (m_format != SDR) {
6391 hr = swapChain->SetColorSpace1(hdrColorSpace);
6393 qWarning(
"Failed to set color space on swapchain: %s",
6394 qPrintable(QSystemError::windowsComString(hr)));
6398 hr = dcompVisual->SetContent(swapChain);
6399 if (SUCCEEDED(hr)) {
6400 hr = dcompTarget->SetRoot(dcompVisual);
6402 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
6403 qPrintable(QSystemError::windowsComString(hr)));
6406 qWarning(
"Failed to set content for Direct Composition visual: %s",
6407 qPrintable(QSystemError::windowsComString(hr)));
6411 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
6415 qWarning(
"Failed to create D3D12 swapchain: %s"
6416 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
6417 qPrintable(QSystemError::windowsComString(hr)),
6419 desc.BufferCount, UINT(
desc.Scaling), UINT(
desc.SwapEffect), UINT(
desc.Stereo));
6423 for (
int i = 0;
i < QD3D12_FRAMES_IN_FLIGHT; ++
i) {
6424 hr = rhiD->dev->CreateFence(0,
6425 D3D12_FENCE_FLAG_NONE,
6426 __uuidof(ID3D12Fence),
6427 reinterpret_cast<void **
>(&frameRes[
i].fence));
6429 qWarning(
"Failed to create fence for swapchain: %s",
6430 qPrintable(QSystemError::windowsComString(hr)));
6433 frameRes[
i].fenceEvent = CreateEvent(
nullptr, FALSE, FALSE,
nullptr);
6435 frameRes[
i].fenceCounter = 0;
6440 UINT(pixelSize.width()),
6441 UINT(pixelSize.height()),
6444 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
6445 qWarning(
"Device loss detected in ResizeBuffers()");
6446 rhiD->deviceLost =
true;
6448 }
else if (FAILED(hr)) {
6449 qWarning(
"Failed to resize D3D12 swapchain: %s",
qPrintable(QSystemError::windowsComString(hr)));
6455 ID3D12Resource *colorBuffer;
6456 hr = swapChain->GetBuffer(
i, __uuidof(ID3D12Resource),
reinterpret_cast<void **
>(&colorBuffer));
6458 qWarning(
"Failed to get buffer %u for D3D12 swapchain: %s",
6459 i,
qPrintable(QSystemError::windowsComString(hr)));
6462 colorBuffers[
i] = QD3D12Resource::addToPool(&rhiD->resourcePool, colorBuffer, D3D12_RESOURCE_STATE_PRESENT);
6463 rtvs[
i] = rhiD->rtvPool.allocate(1);
6464 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
6465 rtvDesc.Format = srgbAdjustedColorFormat;
6466 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
6467 rhiD->dev->CreateRenderTargetView(colorBuffer, &rtvDesc, rtvs[
i].cpuHandle);
6470 rtvsRight[
i] = rhiD->rtvPool.allocate(1);
6471 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
6472 rtvDesc.Format = srgbAdjustedColorFormat;
6473 rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
6474 rtvDesc.Texture2DArray.ArraySize = 1;
6475 rtvDesc.Texture2DArray.FirstArraySlice = 1;
6476 rhiD->dev->CreateRenderTargetView(colorBuffer, &rtvDesc, rtvsRight[
i].cpuHandle);
6480 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
6481 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
6482 m_depthStencil->sampleCount(), m_sampleCount);
6484 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
6486 m_depthStencil->setPixelSize(pixelSize);
6487 if (!m_depthStencil->create())
6488 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
6489 pixelSize.width(), pixelSize.height());
6491 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
6492 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
6493 pixelSize.width(), pixelSize.height());
6497 ds = m_depthStencil ?
QRHI_RES(QD3D12RenderBuffer, m_depthStencil) :
nullptr;
6499 if (sampleDesc.Count > 1) {
6501 D3D12_RESOURCE_DESC resourceDesc = {};
6502 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
6503 resourceDesc.Width = UINT64(pixelSize.width());
6504 resourceDesc.Height = UINT(pixelSize.height());
6505 resourceDesc.DepthOrArraySize = 1;
6506 resourceDesc.MipLevels = 1;
6507 resourceDesc.Format = srgbAdjustedColorFormat;
6508 resourceDesc.SampleDesc = sampleDesc;
6509 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
6510 resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
6511 D3D12_CLEAR_VALUE clearValue = {};
6513 ID3D12Resource *resource =
nullptr;
6515 HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
6517 D3D12_RESOURCE_STATE_RENDER_TARGET,
6520 __uuidof(ID3D12Resource),
6521 reinterpret_cast<void **
>(&resource));
6523 qWarning(
"Failed to create MSAA color buffer: %s",
qPrintable(QSystemError::windowsComString(hr)));
6526 msaaBuffers[
i] = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_RENDER_TARGET,
allocation);
6527 msaaRtvs[
i] = rhiD->rtvPool.allocate(1);
6528 if (!msaaRtvs[
i].isValid())
6530 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
6531 rtvDesc.Format = srgbAdjustedColorFormat;
6532 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS
6533 : D3D12_RTV_DIMENSION_TEXTURE2D;
6534 rhiD->dev->CreateRenderTargetView(resource, &rtvDesc, msaaRtvs[
i].cpuHandle);
6538 currentBackBufferIndex = swapChain->GetCurrentBackBufferIndex();
6539 currentFrameSlot = 0;
6541 rtWrapper.setRenderPassDescriptor(m_renderPassDesc);
6542 QD3D12SwapChainRenderTarget *rtD =
QRHI_RES(QD3D12SwapChainRenderTarget, &rtWrapper);
6543 rtD->d.rp =
QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
6544 rtD->d.pixelSize = pixelSize;
6545 rtD->d.dpr = float(
window->devicePixelRatio());
6546 rtD->d.sampleCount = int(sampleDesc.Count);
6547 rtD->d.colorAttCount = 1;
6548 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
6550 rtWrapperRight.setRenderPassDescriptor(m_renderPassDesc);
6551 QD3D12SwapChainRenderTarget *rtDr =
QRHI_RES(QD3D12SwapChainRenderTarget, &rtWrapperRight);
6552 rtDr->d.rp =
QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
6553 rtDr->d.pixelSize = pixelSize;
6554 rtDr->d.dpr = float(
window->devicePixelRatio());
6555 rtDr->d.sampleCount = int(sampleDesc.Count);
6556 rtDr->d.colorAttCount = 1;
6557 rtDr->d.dsAttCount = m_depthStencil ? 1 : 0;
6559 if (needsRegistration) {
6560 rhiD->swapchains.insert(
this);
6561 rhiD->registerResource(
this);
IOBluetoothDevice * device
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
The QColor class provides colors based on RGB, HSV or CMYK values.
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
const_iterator cend() const
const_iterator constFind(const Key &key) const
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
\inmodule QtCore\reentrant
Type
Specifies storage type of buffer resource.
QPair< int, quint32 > DynamicOffset
Synonym for QPair<int, quint32>.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
IndexFormat
Specifies the index data type.
BlendOp
Specifies the blend operation.
PolygonMode
Specifies the polygon rasterization mode.
BlendFactor
Specifies the blend factor.
CompareOp
Specifies the depth or stencil comparison function.
CullMode
Specifies the culling mode.
Topology
Specifies the primitive topology.
StencilOp
Specifies the stencil operation.
static const QRhiShaderResourceBinding::Data * shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
Type
Specifies the type of the renderbuffer.
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
virtual Type resourceType() const =0
Filter
Specifies the minification, magnification, or mipmap filtering.
AddressMode
Specifies the addressing mode.
CompareOp
Specifies the texture comparison function.
std::array< int, 4 > scissor() const
QVarLengthArray< QRhiShaderResourceBinding, BINDING_PREALLOC > m_bindings
virtual QRhiSwapChainHdrInfo hdrInfo()
\variable QRhiSwapChainHdrInfo::limitsType
@ PreserveDepthStencilContents
Format
Specifies the texture format.
static constexpr int MAX_MIP_LEVELS
ResourceLimit
Describes the resource limit to query.
@ MaxThreadsPerThreadGroup
@ MaxThreadGroupsPerDimension
Feature
Flag values to indicate what features are supported by the backend currently in use.
@ NonDynamicUniformBuffers
@ RenderToNonBaseMipLevel
@ MultisampleRenderBuffer
@ PipelineCacheDataLoadSave
@ ReadBackNonUniformBuffer
@ RenderToOneDimensionalTexture
@ OneDimensionalTextureMipmaps
@ ReadBackNonBaseMipLevel
@ ThreeDimensionalTextureMipmaps
@ NonFourAlignedEffectiveIndexBufferOffset
@ ThreeDimensionalTextures
@ ReadBackAnyTextureFormat
FrameOpResult
Describes the result of operations that can have a soft failure.
const_iterator cend() const noexcept
const_iterator constFind(const T &value) const
QByteArray shader() const
Variant
Describes what kind of shader code an entry contains.
Source
Describes what kind of shader code an entry contains.
@ TessellationEvaluationStage
@ TessellationControlStage
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf16(const char16_t *, qsizetype size=-1)
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
float sdrWhiteLevelInNits(const DXGI_OUTPUT_DESC1 &outputDesc)
pD3DCompile resolveD3DCompile()
bool outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
IDCompositionDevice * createDirectCompositionDevice()
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
Combined button and popup list for selecting options.
constexpr uint qCountTrailingZeroBits(quint32 v) noexcept
ABI::Windows::Storage::Streams::IBuffer NativeBuffer
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
static QT_BEGIN_NAMESPACE const int BUFFER_COUNT
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
const void GLsizei GLsizei stride
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum const GLint * param
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum colorFormat
GLsizeiptr const void GLenum usage
static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static QPair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
Int aligned(Int v, Int byteAlign)
static DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
static const DXGI_FORMAT DEFAULT_FORMAT
static D3D11_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f, bool rgb)
static D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
static D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
static QD3D11RenderTargetData * rtData(QRhiRenderTarget *rt)
static UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
static D3D11_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
static D3D11_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
static DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
static D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
static D3D11_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
static bool isDepthTextureFormat(QRhiTexture::Format format)
static D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
static DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
#define DXGI_ADAPTER_FLAG_SOFTWARE
\variable QRhiD3D11NativeHandles::dev
static QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
static D3D11_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
static DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
std::unique_ptr< ThunkPool::ThunkAllocation > allocation
#define qPrintable(string)
QLatin1StringView QLatin1String
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
unsigned long long quint64
view viewport() -> scroll(dx, dy, deviceRect)
manager head(request, this, [this](QRestReply &reply) { if(reply.isSuccess()) })
[6]
\inmodule QtCore \reentrant
\variable QRhiReadbackResult::completed
qint64 totalPipelineCreationTime