11#include <QtCore/qcryptographichash.h>
12#include <QtCore/qendian.h>
13#include <QtCore/private/qsystemerror_p.h>
20using namespace Qt::StringLiterals;
23
24
25
26
27
28
29
30
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
80
81
82
83
84
88
89
90
91
92
93
94
95
96
97
98
99
102
103
104
105
106
107
108
109
112
113
114
115
116
117
118
121
122
123
124
125
126
127
128
131
132
133
134
135
136
139
140
141
142
143
144
147#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
148#define DXGI_ADAPTER_FLAG_SOFTWARE 2
151#ifndef D3D11_1_UAV_SLOT_COUNT
152#define D3D11_1_UAV_SLOT_COUNT 64
155#ifndef D3D11_VS_INPUT_REGISTER_COUNT
156#define D3D11_VS_INPUT_REGISTER_COUNT 32
165 if (importParams->dev && importParams->context) {
166 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
167 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
168 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
173 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
176 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
177 adapterLuid.LowPart = importParams->adapterLuidLow;
178 adapterLuid.HighPart = importParams->adapterLuidHigh;
185 return (v + byteAlign - 1) & ~(byteAlign - 1);
190 IDXGIFactory1 *result =
nullptr;
191 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
193 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
194 qPrintable(QSystemError::windowsComString(hr)));
206 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
208 dxgiFactory = createDXGIFactory2();
216 IDXGIFactory5 *factory5 =
nullptr;
217 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
218 BOOL allowTearing =
false;
219 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
224 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
225 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
233 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
234 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
239 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
243 if (maxFrameLatency == 0)
244 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
246 activeAdapter =
nullptr;
249 IDXGIAdapter1 *adapter;
250 int requestedAdapterIndex = -1;
251 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
252 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
254 if (requestedRhiAdapter)
255 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
258 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
259 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
260 DXGI_ADAPTER_DESC1 desc;
261 adapter->GetDesc1(&desc);
263 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
264 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
266 requestedAdapterIndex = adapterIndex;
272 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
273 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
274 DXGI_ADAPTER_DESC1 desc;
275 adapter->GetDesc1(&desc);
278 requestedAdapterIndex = adapterIndex;
284 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
285 DXGI_ADAPTER_DESC1 desc;
286 adapter->GetDesc1(&desc);
287 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
288 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
294 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
295 activeAdapter = adapter;
296 adapterLuid = desc.AdapterLuid;
298 qCDebug(QRHI_LOG_INFO,
" using this adapter");
303 if (!activeAdapter) {
304 qWarning(
"No adapter");
310 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
311 bool requestFeatureLevels =
false;
313 requestFeatureLevels =
true;
314 requestedFeatureLevels.append(featureLevel);
317 ID3D11DeviceContext *ctx =
nullptr;
318 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
319 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
320 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
322 &dev, &featureLevel, &ctx);
324 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
325 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
326 "Attempting to create D3D11 device without it.");
327 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
328 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
329 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
330 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
332 &dev, &featureLevel, &ctx);
335 qWarning(
"Failed to create D3D11 device and context: %s",
336 qPrintable(QSystemError::windowsComString(hr)));
340 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
343 qWarning(
"ID3D11DeviceContext1 not supported");
349 ID3D11VertexShader *testShader =
nullptr;
350 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
351 testShader->Release();
353 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
354 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
355 qCDebug(QRHI_LOG_INFO,
"%s", msg);
361 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
362 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
366 if (!features.ConstantBufferOffsetting) {
367 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
368 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
369 qCDebug(QRHI_LOG_INFO,
"%s", msg);
375 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
376 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
377 qCDebug(QRHI_LOG_INFO,
"%s", msg);
383 Q_ASSERT(dev && context);
384 featureLevel = dev->GetFeatureLevel();
385 IDXGIDevice *dxgiDev =
nullptr;
386 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
387 IDXGIAdapter *adapter =
nullptr;
388 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
389 IDXGIAdapter1 *adapter1 =
nullptr;
390 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
391 DXGI_ADAPTER_DESC1 desc;
392 adapter1->GetDesc1(&desc);
393 adapterLuid = desc.AdapterLuid;
395 activeAdapter = adapter1;
401 if (!activeAdapter) {
402 qWarning(
"Failed to query adapter from imported device");
405 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
408 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
410 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
411 annotations =
nullptr;
415 nativeHandlesStruct.dev = dev;
416 nativeHandlesStruct.context = context;
417 nativeHandlesStruct.featureLevel = featureLevel;
418 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
419 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
426 for (
const Shader &s : std::as_const(m_shaderCache))
429 m_shaderCache.clear();
438 if (pushConstantBuffer) {
439 pushConstantBuffer->Release();
440 pushConstantBuffer =
nullptr;
443 if (ofr.tsDisjointQuery) {
444 ofr.tsDisjointQuery->Release();
445 ofr.tsDisjointQuery =
nullptr;
447 for (
int i = 0; i < 2; ++i) {
448 if (ofr.tsQueries[i]) {
449 ofr.tsQueries[i]->Release();
450 ofr.tsQueries[i] =
nullptr;
455 annotations->Release();
456 annotations =
nullptr;
471 dcompDevice->Release();
472 dcompDevice =
nullptr;
476 activeAdapter->Release();
477 activeAdapter =
nullptr;
481 dxgiFactory->Release();
482 dxgiFactory =
nullptr;
485 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
495 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
496 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
501QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
503 LUID requestedLuid = {};
505 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
506 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
507 if (adapterLuid.LowPart || adapterLuid.HighPart)
508 requestedLuid = adapterLuid;
511 IDXGIFactory1 *dxgi = createDXGIFactory2();
515 QRhi::AdapterList list;
516 IDXGIAdapter1 *adapter;
517 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
518 DXGI_ADAPTER_DESC1 desc;
519 adapter->GetDesc1(&desc);
521 if (requestedLuid.LowPart || requestedLuid.HighPart) {
522 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
523 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
528 QD3D11Adapter *a =
new QD3D11Adapter;
529 a->luid = desc.AdapterLuid;
530 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
545 return { 1, 2, 4, 8 };
550 Q_UNUSED(sampleCount);
551 return { QSize(1, 1) };
556 DXGI_SAMPLE_DESC desc;
560 const int s = effectiveSampleCount(sampleCount);
562 desc.Count = UINT(s);
564 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
573 return new QD3D11SwapChain(
this);
576QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
578 return new QD3D11Buffer(
this, type, usage, size);
606 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
607 0.0f, 1.0f, 0.0f, 0.0f,
608 0.0f, 0.0f, 0.5f, 0.5f,
609 0.0f, 0.0f, 0.0f, 1.0f);
617 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
626 case QRhi::MultisampleTexture:
628 case QRhi::MultisampleRenderBuffer:
630 case QRhi::DebugMarkers:
631 return annotations !=
nullptr;
632 case QRhi::Timestamps:
634 case QRhi::Instancing:
636 case QRhi::CustomInstanceStepRate:
638 case QRhi::PrimitiveRestart:
640 case QRhi::NonDynamicUniformBuffers:
642 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
644 case QRhi::NPOTTextureRepeat:
646 case QRhi::RedOrAlpha8IsRed:
648 case QRhi::ElementIndexUint:
653 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
654 case QRhi::WideLines:
656 case QRhi::VertexShaderPointSize:
658 case QRhi::BaseVertex:
660 case QRhi::BaseInstance:
662 case QRhi::TriangleFanTopology:
664 case QRhi::ReadBackNonUniformBuffer:
666 case QRhi::ReadBackNonBaseMipLevel:
668 case QRhi::TexelFetch:
670 case QRhi::RenderToNonBaseMipLevel:
672 case QRhi::IntAttributes:
674 case QRhi::ScreenSpaceDerivatives:
676 case QRhi::ReadBackAnyTextureFormat:
678 case QRhi::PipelineCacheDataLoadSave:
680 case QRhi::ImageDataStride:
682 case QRhi::RenderBufferImport:
684 case QRhi::ThreeDimensionalTextures:
686 case QRhi::RenderTo3DTextureSlice:
688 case QRhi::TextureArrays:
690 case QRhi::Tessellation:
692 case QRhi::GeometryShader:
694 case QRhi::TextureArrayRange:
696 case QRhi::NonFillPolygonMode:
698 case QRhi::OneDimensionalTextures:
700 case QRhi::OneDimensionalTextureMipmaps:
702 case QRhi::HalfAttributes:
704 case QRhi::RenderToOneDimensionalTexture:
706 case QRhi::ThreeDimensionalTextureMipmaps:
708 case QRhi::MultiView:
710 case QRhi::TextureViewFormat:
712 case QRhi::ResolveDepthStencil:
714 case QRhi::VariableRateShading:
716 case QRhi::VariableRateShadingMap:
717 case QRhi::VariableRateShadingMapWithTexture:
719 case QRhi::PerRenderTargetBlending:
720 case QRhi::SampleVariables:
722 case QRhi::InstanceIndexIncludesBaseInstance:
724 case QRhi::DepthClamp:
726 case QRhi::DrawIndirect:
727 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
728 case QRhi::DrawIndirectMulti:
729 case QRhi::ShaderDrawParameters:
731 case QRhi::PushConstants:
733 case QRhi::DrawIndirectCount:
735 case QRhi::DispatchIndirect:
736 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
737 case QRhi::BufferToBufferCopy:
739 case QRhi::StaticBuffersOnGpuTimeline:
750 case QRhi::TextureSizeMin:
752 case QRhi::TextureSizeMax:
753 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
754 case QRhi::MaxColorAttachments:
756 case QRhi::FramesInFlight:
762 case QRhi::MaxAsyncReadbackFrames:
764 case QRhi::MaxThreadGroupsPerDimension:
765 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
766 case QRhi::MaxThreadsPerThreadGroup:
767 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
768 case QRhi::MaxThreadGroupX:
769 return D3D11_CS_THREAD_GROUP_MAX_X;
770 case QRhi::MaxThreadGroupY:
771 return D3D11_CS_THREAD_GROUP_MAX_Y;
772 case QRhi::MaxThreadGroupZ:
773 return D3D11_CS_THREAD_GROUP_MAX_Z;
774 case QRhi::TextureArraySizeMax:
775 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
776 case QRhi::MaxUniformBufferRange:
778 case QRhi::MaxVertexInputs:
780 case QRhi::MaxVertexOutputs:
781 return D3D11_VS_OUTPUT_REGISTER_COUNT;
782 case QRhi::MaxVertexStorageBuffers:
784 case QRhi::MaxPushConstantsSize:
786 return int(MAX_PUSH_CONSTANTS_SIZE);
787 case QRhi::MaxFragmentStorageBuffers:
788 return featureLevel >= D3D_FEATURE_LEVEL_11_1
790 case QRhi::ShadingRateImageTileSize:
800 return &nativeHandlesStruct;
805 return driverInfoStruct;
811 result.totalPipelineCreationTime = totalPipelineCreationTime();
821void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
829 m_bytecodeCache.clear();
849 if (m_bytecodeCache.data.isEmpty())
853 memset(&header, 0,
sizeof(header));
854 header.rhiId = pipelineCacheRhiId();
855 header.arch = quint32(
sizeof(
void*));
856 header.count = m_bytecodeCache.data.count();
858 const size_t dataOffset =
sizeof(header);
860 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
862 QByteArray bytecode = it.value();
864 sizeof(quint32) + key.sourceHash.size()
865 +
sizeof(quint32) + key.target.size()
866 +
sizeof(quint32) + key.entryPoint.size()
868 +
sizeof(quint32) + bytecode.size();
871 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
872 char *p = buf.data() + dataOffset;
873 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
875 QByteArray bytecode = it.value();
877 quint32 i = key.sourceHash.size();
880 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
881 p += key.sourceHash.size();
883 i = key.target.size();
886 memcpy(p, key.target.constData(), key.target.size());
887 p += key.target.size();
889 i = key.entryPoint.size();
892 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
893 p += key.entryPoint.size();
902 memcpy(p, bytecode.constData(), bytecode.size());
903 p += bytecode.size();
905 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
907 header.dataSize = quint32(dataSize);
908 memcpy(buf.data(), &header,
sizeof(header));
919 if (data.size() < qsizetype(headerSize)) {
920 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
923 const size_t dataOffset = headerSize;
925 memcpy(&header, data.constData(), headerSize);
927 const quint32 rhiId = pipelineCacheRhiId();
928 if (header.rhiId != rhiId) {
929 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
930 rhiId, header.rhiId);
933 const quint32 arch = quint32(
sizeof(
void*));
934 if (header.arch != arch) {
935 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
939 if (header.count == 0)
942 if (quint64(data.size()) < quint64(dataOffset) + header.dataSize) {
943 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
947 m_bytecodeCache.clear();
950 for (quint32 i = 0; i < header.count; ++i) {
954 if (!reader.readByteArray(&cacheKey.sourceHash)
955 || !reader.readByteArray(&cacheKey.target)
956 || !reader.readByteArray(&cacheKey.entryPoint)
957 || !reader.readUInt32(&flags)
958 || !reader.readByteArray(&bytecode))
960 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob (truncated or corrupt bytecode data)");
961 m_bytecodeCache.clear();
966 m_bytecodeCache.insertWithCapacityLimit(cacheKey, bytecode);
969 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.data.count()));
972QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
973 int sampleCount, QRhiRenderBuffer::Flags flags,
974 QRhiTexture::Format backingFormatHint)
976 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
980 const QSize &pixelSize,
int depth,
int arraySize,
981 int sampleCount, QRhiTexture::Flags flags)
983 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
987 QRhiSampler::Filter mipmapMode,
988 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
990 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
994 QRhiTextureRenderTarget::Flags flags)
1006 return new QD3D11GraphicsPipeline(
this);
1011 return new QD3D11ComputePipeline(
this);
1016 return new QD3D11ShaderResourceBindings(
this);
1026 if (pipelineChanged) {
1027 cbD->currentGraphicsPipeline = ps;
1028 cbD->currentComputePipeline =
nullptr;
1033 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1034 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1035 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1036 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1037 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1038 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1039 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1040 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1041 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1042 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1057 case QRhiShaderStage::Vertex:
1059 case QRhiShaderStage::TessellationControl:
1061 case QRhiShaderStage::TessellationEvaluation:
1063 case QRhiShaderStage::Geometry:
1064 return RBM_GEOMETRY;
1065 case QRhiShaderStage::Fragment:
1066 return RBM_FRAGMENT;
1067 case QRhiShaderStage::Compute:
1078 const QList<QShaderDescription::PushConstantBlock> blocks = shader.description().pushConstantBlocks();
1079 if (blocks.isEmpty())
1081 *reg = shader.nativeShaderInfo(key).extraBufferBindings.value(QShaderPrivate::HlslPushConstantBufferBinding, -1);
1082 *size = quint32((blocks.first().size + 3) & ~3);
1086 int dynamicOffsetCount,
1087 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1096 srb = gfxPsD->m_shaderResourceBindings;
1098 srb = compPsD->m_shaderResourceBindings;
1103 bool pipelineChanged =
false;
1112 bool srbUpdate =
false;
1113 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1114 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1117 case QRhiShaderResourceBinding::UniformBuffer:
1121 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1122 sanityCheckResourceOwnership(bufD);
1126 if (bufD
->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1128 bd.ubuf.id = bufD->m_id;
1133 case QRhiShaderResourceBinding::SampledTexture:
1134 case QRhiShaderResourceBinding::Texture:
1135 case QRhiShaderResourceBinding::Sampler:
1137 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex;
1138 if (bd.stex.d.size() != data->count()) {
1139 bd.stex.d.resize(data->count());
1142 for (
int elem = 0; elem < data->count(); ++elem) {
1148 Q_ASSERT(texD || samplerD);
1149 sanityCheckResourceOwnership(texD);
1150 sanityCheckResourceOwnership(samplerD);
1151 const quint64 texId = texD ? texD->m_id : 0;
1153 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1154 const uint samplerGen = samplerD ? samplerD
->generation : 0;
1155 if (texGen != bd.stex.d[elem].texGeneration
1156 || texId != bd.stex.d[elem].texId
1157 || samplerGen != bd.stex.d[elem].samplerGeneration
1158 || samplerId != bd.stex.d[elem].samplerId)
1161 bd.stex.d[elem].texId = texId;
1162 bd.stex.d[elem].texGeneration = texGen;
1163 bd.stex.d[elem].samplerId = samplerId;
1164 bd.stex.d[elem].samplerGeneration = samplerGen;
1169 case QRhiShaderResourceBinding::ImageLoad:
1170 case QRhiShaderResourceBinding::ImageStore:
1171 case QRhiShaderResourceBinding::ImageLoadStore:
1174 sanityCheckResourceOwnership(texD);
1175 if (texD
->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1177 bd.simage.id = texD->m_id;
1182 case QRhiShaderResourceBinding::BufferLoad:
1183 case QRhiShaderResourceBinding::BufferStore:
1184 case QRhiShaderResourceBinding::BufferLoadStore:
1187 sanityCheckResourceOwnership(bufD);
1188 if (bufD
->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1190 bd.sbuf.id = bufD->m_id;
1201 if (srbUpdate || pipelineChanged) {
1203 memset(resBindMaps, 0,
sizeof(resBindMaps));
1204 uint pushConstantStages = 0;
1206 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1207 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1208 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1209 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1210 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1211 pushConstantStages = gfxPsD->pushConstants.stages;
1213 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1214 if (compPsD->pushConstants.reg >= 0 && compPsD->pushConstants.size)
1217 updateShaderResourceBindings(srbD, resBindMaps, pushConstantStages);
1220 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1223 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1225 cbD->currentGraphicsSrb = srb;
1226 cbD->currentComputeSrb =
nullptr;
1228 cbD->currentGraphicsSrb =
nullptr;
1229 cbD->currentComputeSrb = srb;
1238 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1239 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1242 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1243 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1244 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1245 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1246 const uint binding = uint(dynOfs.first);
1247 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1248 const quint32 offsetInConstants = dynOfs.second / 16;
1250 *p++ = offsetInConstants;
1253 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1261 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1262 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1267 bool needsBindVBuf =
false;
1268 for (
int i = 0; i < bindingCount; ++i) {
1269 const int inputSlot = startBinding + i;
1271 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1272 if (bufD->m_type == QRhiBuffer::Dynamic)
1275 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1276 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1278 needsBindVBuf =
true;
1279 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1280 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1284 if (needsBindVBuf) {
1287 cmd.args.bindVertexBuffers.startSlot = startBinding;
1289 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1293 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1295 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1296 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1297 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1299 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1300 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1301 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1307 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1308 if (ibufD->m_type == QRhiBuffer::Dynamic)
1311 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1312 : DXGI_FORMAT_R32_UINT;
1313 if (cbD->currentIndexBuffer != ibufD->buffer
1314 || cbD->currentIndexOffset != indexOffset
1315 || cbD->currentIndexFormat != dxgiFormat)
1317 cbD->currentIndexBuffer = ibufD->buffer;
1318 cbD->currentIndexOffset = indexOffset;
1319 cbD->currentIndexFormat = dxgiFormat;
1323 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1324 cmd.args.bindIndexBuffer.offset = indexOffset;
1325 cmd.args.bindIndexBuffer.format = dxgiFormat;
1334 Q_ASSERT(cbD->currentTarget);
1335 const QSize outputSize = cbD->currentTarget->pixelSize();
1339 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1344 cmd.args.viewport.x = x;
1345 cmd.args.viewport.y = y;
1346 cmd.args.viewport.w = w;
1347 cmd.args.viewport.h = h;
1348 cmd.args.viewport.d0 = viewport.minDepth();
1349 cmd.args.viewport.d1 = viewport.maxDepth();
1356 Q_ASSERT(cbD->currentTarget);
1357 const QSize outputSize = cbD->currentTarget->pixelSize();
1361 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1366 cmd.args.scissor.x = x;
1367 cmd.args.scissor.y = y;
1368 cmd.args.scissor.w = w;
1369 cmd.args.scissor.h = h;
1380 cmd.args.blendConstants.c[0] =
float(c.redF());
1381 cmd.args.blendConstants.c[1] =
float(c.greenF());
1382 cmd.args.blendConstants.c[2] =
float(c.blueF());
1383 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1394 cmd.args.stencilRef.ref = refValue;
1403 quint32 blockSize = 0;
1409 reg = psD->pushConstants.reg;
1410 blockSize = psD->pushConstants.size;
1416 reg = psD->pushConstants.reg;
1417 blockSize = psD->pushConstants.size;
1418 stages = psD->pushConstants.stages;
1420 if (reg < 0 || !blockSize || !stages) {
1421 qWarning(
"No pipeline with a push constant block is active; setPushConstants ignored");
1425 if (offset + size > MAX_PUSH_CONSTANTS_SIZE) {
1426 qWarning(
"Push constant data of %u bytes at offset %u exceeds the %u byte maximum; "
1427 "setPushConstants ignored", size, offset, MAX_PUSH_CONSTANTS_SIZE);
1436 const quint32 total = qMin(qMax(blockSize, offset + size), MAX_PUSH_CONSTANTS_SIZE);
1437 if (quint32(cbD->pushConstantData.size()) < total)
1438 cbD->pushConstantData.resize(
int(total), 0);
1439 memcpy(cbD->pushConstantData.data() + offset, data, size);
1441 const quint32 dataOffset = quint32(cbD->pushConstantPool.size());
1442 cbD->pushConstantPool.append(cbD->pushConstantData.constData(), total);
1446 cmd.args.setPushConstants.buffer = pushConstantBuffer;
1447 cmd.args.setPushConstants.dataOffset = dataOffset;
1448 cmd.args.setPushConstants.size = total;
1449 cmd.args.setPushConstants.startSlot = uint(reg);
1450 cmd.args.setPushConstants.stages = stages;
1455 if (pushConstantBuffer)
1458 D3D11_BUFFER_DESC desc = {};
1459 desc.ByteWidth = aligned(MAX_PUSH_CONSTANTS_SIZE, 256u);
1460 desc.Usage = D3D11_USAGE_DYNAMIC;
1461 desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1462 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1463 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &pushConstantBuffer);
1465 qWarning(
"Failed to create push constant buffer: %s",
1466 qPrintable(QSystemError::windowsComString(hr)));
1467 pushConstantBuffer =
nullptr;
1476 Q_UNUSED(coarsePixelSize);
1480 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1487 cmd.args.draw.vertexCount = vertexCount;
1488 cmd.args.draw.instanceCount = instanceCount;
1489 cmd.args.draw.firstVertex = firstVertex;
1490 cmd.args.draw.firstInstance = firstInstance;
1494 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1501 cmd.args.drawIndexed.indexCount = indexCount;
1502 cmd.args.drawIndexed.instanceCount = instanceCount;
1503 cmd.args.drawIndexed.firstIndex = firstIndex;
1504 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1505 cmd.args.drawIndexed.firstInstance = firstInstance;
1509 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1516 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1517 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1518 cmd.args.drawIndirect.drawCount = drawCount;
1519 cmd.args.drawIndirect.stride = stride;
1524 switch (rt->resourceType()) {
1525 case QRhiResource::SwapChainRenderTarget:
1526 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1527 case QRhiResource::TextureRenderTarget:
1528 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1536 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1543 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1544 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1545 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1546 cmd.args.drawIndexedIndirect.stride = stride;
1551 if (!debugMarkers || !annotations)
1557 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1562 if (!debugMarkers || !annotations)
1572 if (!debugMarkers || !annotations)
1578 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1597 Q_ASSERT(cbD->commands.isEmpty());
1599 if (cbD->currentTarget) {
1603 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1618 return QRhi::FrameOpDeviceLost;
1625 if (swapChainD->frameLatencyWaitableObject) {
1628 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1633 swapChainD->cb.resetState();
1635 swapChainD->rt.d.views.setFrom(1,
1636 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1637 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1642 double elapsedSec = 0;
1644 swapChainD->cb.lastGpuTime = elapsedSec;
1653 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1654 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1655 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1656 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1658 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1660 return QRhi::FrameOpSuccess;
1671 cmd.args.endFrame.tsQuery =
nullptr;
1672 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1677 if (swapChainD->sampleDesc.Count > 1) {
1678 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1679 swapChainD->msaaTex[currentFrameSlot], 0,
1680 swapChainD->colorFormat);
1687 if (recordTimestamps) {
1688 context->End(tsEnd);
1689 context->End(tsDisjoint);
1694 if (!flags.testFlag(QRhi::SkipPresent)) {
1695 UINT presentFlags = 0;
1696 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1697 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1698 if (!swapChainD->swapChain) {
1699 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1700 return QRhi::FrameOpError;
1702 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1703 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1704 qWarning(
"Device loss detected in Present()");
1706 return QRhi::FrameOpDeviceLost;
1707 }
else if (FAILED(hr)) {
1708 qWarning(
"Failed to present: %s",
1709 qPrintable(QSystemError::windowsComString(hr)));
1710 return QRhi::FrameOpError;
1713 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1714 dcompDevice->Commit();
1725 return QRhi::FrameOpSuccess;
1733 ofr.cbWrapper.resetState();
1734 *cb = &ofr.cbWrapper;
1736 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1737 D3D11_QUERY_DESC queryDesc = {};
1738 if (!ofr.tsDisjointQuery) {
1739 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1740 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1742 qWarning(
"Failed to create timestamp disjoint query: %s",
1743 qPrintable(QSystemError::windowsComString(hr)));
1744 return QRhi::FrameOpError;
1747 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1748 for (
int i = 0; i < 2; ++i) {
1749 if (!ofr.tsQueries[i]) {
1750 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1752 qWarning(
"Failed to create timestamp query: %s",
1753 qPrintable(QSystemError::windowsComString(hr)));
1754 return QRhi::FrameOpError;
1762 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1763 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1764 cmd.args.beginFrame.swapchainRtv =
nullptr;
1765 cmd.args.beginFrame.swapchainDsv =
nullptr;
1767 return QRhi::FrameOpSuccess;
1777 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1778 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1785 if (ofr.tsQueries[0]) {
1786 quint64 timestamps[2];
1787 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1791 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1792 }
while (hr == S_FALSE);
1795 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1796 }
while (hr == S_FALSE);
1799 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1800 }
while (hr == S_FALSE);
1803 if (!dj.Disjoint && dj.Frequency) {
1804 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1805 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1810 return QRhi::FrameOpSuccess;
1815 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1817 case QRhiTexture::RGBA8:
1818 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1819 case QRhiTexture::BGRA8:
1820 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1821 case QRhiTexture::R8:
1822 return DXGI_FORMAT_R8_UNORM;
1823 case QRhiTexture::R8SI:
1824 return DXGI_FORMAT_R8_SINT;
1825 case QRhiTexture::R8UI:
1826 return DXGI_FORMAT_R8_UINT;
1827 case QRhiTexture::RG8:
1828 return DXGI_FORMAT_R8G8_UNORM;
1829 case QRhiTexture::R16:
1830 return DXGI_FORMAT_R16_UNORM;
1831 case QRhiTexture::RG16:
1832 return DXGI_FORMAT_R16G16_UNORM;
1833 case QRhiTexture::RED_OR_ALPHA8:
1834 return DXGI_FORMAT_R8_UNORM;
1836 case QRhiTexture::RGBA16F:
1837 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1838 case QRhiTexture::RGBA32F:
1839 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1840 case QRhiTexture::R16F:
1841 return DXGI_FORMAT_R16_FLOAT;
1842 case QRhiTexture::R32F:
1843 return DXGI_FORMAT_R32_FLOAT;
1845 case QRhiTexture::RGB10A2:
1846 return DXGI_FORMAT_R10G10B10A2_UNORM;
1848 case QRhiTexture::R32SI:
1849 return DXGI_FORMAT_R32_SINT;
1850 case QRhiTexture::R32UI:
1851 return DXGI_FORMAT_R32_UINT;
1852 case QRhiTexture::RG32SI:
1853 return DXGI_FORMAT_R32G32_SINT;
1854 case QRhiTexture::RG32UI:
1855 return DXGI_FORMAT_R32G32_UINT;
1856 case QRhiTexture::RGBA32SI:
1857 return DXGI_FORMAT_R32G32B32A32_SINT;
1858 case QRhiTexture::RGBA32UI:
1859 return DXGI_FORMAT_R32G32B32A32_UINT;
1861 case QRhiTexture::D16:
1862 return DXGI_FORMAT_R16_TYPELESS;
1863 case QRhiTexture::D24:
1864 return DXGI_FORMAT_R24G8_TYPELESS;
1865 case QRhiTexture::D24S8:
1866 return DXGI_FORMAT_R24G8_TYPELESS;
1867 case QRhiTexture::D32F:
1868 return DXGI_FORMAT_R32_TYPELESS;
1869 case QRhiTexture::D32FS8:
1870 return DXGI_FORMAT_R32G8X24_TYPELESS;
1872 case QRhiTexture::BC1:
1873 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1874 case QRhiTexture::BC2:
1875 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1876 case QRhiTexture::BC3:
1877 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1878 case QRhiTexture::BC4:
1879 return DXGI_FORMAT_BC4_UNORM;
1880 case QRhiTexture::BC5:
1881 return DXGI_FORMAT_BC5_UNORM;
1882 case QRhiTexture::BC6H:
1883 return DXGI_FORMAT_BC6H_UF16;
1884 case QRhiTexture::BC7:
1885 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1887 case QRhiTexture::ETC2_RGB8:
1888 case QRhiTexture::ETC2_RGB8A1:
1889 case QRhiTexture::ETC2_RGBA8:
1890 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1891 return DXGI_FORMAT_R8G8B8A8_UNORM;
1893 case QRhiTexture::ASTC_4x4:
1894 case QRhiTexture::ASTC_5x4:
1895 case QRhiTexture::ASTC_5x5:
1896 case QRhiTexture::ASTC_6x5:
1897 case QRhiTexture::ASTC_6x6:
1898 case QRhiTexture::ASTC_8x5:
1899 case QRhiTexture::ASTC_8x6:
1900 case QRhiTexture::ASTC_8x8:
1901 case QRhiTexture::ASTC_10x5:
1902 case QRhiTexture::ASTC_10x6:
1903 case QRhiTexture::ASTC_10x8:
1904 case QRhiTexture::ASTC_10x10:
1905 case QRhiTexture::ASTC_12x10:
1906 case QRhiTexture::ASTC_12x12:
1907 qWarning(
"QRhiD3D11 does not support ASTC textures");
1908 return DXGI_FORMAT_R8G8B8A8_UNORM;
1912 return DXGI_FORMAT_R8G8B8A8_UNORM;
1919 case DXGI_FORMAT_R8G8B8A8_UNORM:
1920 return QRhiTexture::RGBA8;
1921 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1923 (*flags) |= QRhiTexture::sRGB;
1924 return QRhiTexture::RGBA8;
1925 case DXGI_FORMAT_B8G8R8A8_UNORM:
1926 return QRhiTexture::BGRA8;
1927 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1929 (*flags) |= QRhiTexture::sRGB;
1930 return QRhiTexture::BGRA8;
1931 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1932 return QRhiTexture::RGBA16F;
1933 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1934 return QRhiTexture::RGBA32F;
1935 case DXGI_FORMAT_R10G10B10A2_UNORM:
1936 return QRhiTexture::RGB10A2;
1938 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1941 return QRhiTexture::UnknownFormat;
1947 case QRhiTexture::Format::D16:
1948 case QRhiTexture::Format::D24:
1949 case QRhiTexture::Format::D24S8:
1950 case QRhiTexture::Format::D32F:
1951 case QRhiTexture::Format::D32FS8:
1964 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1966 ofr.cbWrapper.resetCommands();
1977 return QRhi::FrameOpSuccess;
1981 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1983 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1984 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD
->mipLevelCount);
1986 box.front = is3D ? UINT(layer) : 0u;
1988 box.back = box.front + 1;
1991 cmd.args.updateSubRes.dst = texD->textureResource();
1992 cmd.args.updateSubRes.dstSubRes = subres;
1994 const QPoint dp = subresDesc.destinationTopLeft();
1995 if (!subresDesc.image().isNull()) {
1996 QImage img = subresDesc.image();
1997 QSize size = img.size();
1998 int bpl = img.bytesPerLine();
1999 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2000 const QPoint sp = subresDesc.sourceTopLeft();
2001 if (!subresDesc.sourceSize().isEmpty())
2002 size = subresDesc.sourceSize();
2003 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2004 if (img.depth() == 32) {
2005 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
2006 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
2008 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2009 bpl = img.bytesPerLine();
2010 cmd.args.updateSubRes.src = cbD->retainImage(img);
2013 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2014 cmd.args.updateSubRes.src = cbD->retainImage(img);
2016 box.left = UINT(dp.x());
2017 box.top = UINT(dp.y());
2018 box.right = UINT(dp.x() + size.width());
2019 box.bottom = UINT(dp.y() + size.height());
2020 cmd.args.updateSubRes.hasDstBox =
true;
2021 cmd.args.updateSubRes.dstBox = box;
2022 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
2023 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
2024 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2025 : subresDesc.sourceSize();
2028 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
2032 box.left = UINT(aligned(dp.x(), blockDim.width()));
2033 box.top = UINT(aligned(dp.y(), blockDim.height()));
2034 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
2035 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
2036 cmd.args.updateSubRes.hasDstBox =
true;
2037 cmd.args.updateSubRes.dstBox = box;
2038 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2039 cmd.args.updateSubRes.srcRowPitch = bpl;
2040 }
else if (!subresDesc.data().isEmpty()) {
2041 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2042 : subresDesc.sourceSize();
2043 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2044 quint32 bytesPerPixel = 0;
2045 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
2046 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
2047 bytesPerPixel, subresDesc.data().size());
2048 if (size.isEmpty()) {
2049 cbD->commands.unget();
2053 if (subresDesc.dataStride())
2054 bpl = subresDesc.dataStride();
2056 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
2057 box.left = UINT(dp.x());
2058 box.top = UINT(dp.y());
2059 box.right = UINT(dp.x() + size.width());
2060 box.bottom = UINT(dp.y() + size.height());
2061 cmd.args.updateSubRes.hasDstBox =
true;
2062 cmd.args.updateSubRes.dstBox = box;
2063 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2064 cmd.args.updateSubRes.srcRowPitch = bpl;
2066 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
2067 cbD->commands.unget();
2080 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2085 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2086 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
2089 cmd.args.updateSubRes.dst = bufD->buffer;
2090 cmd.args.updateSubRes.dstSubRes = 0;
2091 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
2092 cmd.args.updateSubRes.srcRowPitch = 0;
2097 box.left = u.offset;
2098 box.top = box.front = 0;
2099 box.back = box.bottom = 1;
2100 box.right = u.offset + u
.data.size();
2101 cmd.args.updateSubRes.hasDstBox =
true;
2102 cmd.args.updateSubRes.dstBox = box;
2105 if (bufD->m_type == QRhiBuffer::Dynamic) {
2106 u.result->data.resize(u.readSize);
2107 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
2108 if (u.result->completed)
2109 u.result->completed();
2112 readback.result = u.result;
2113 readback.byteSize = u.readSize;
2115 D3D11_BUFFER_DESC desc = {};
2116 desc.ByteWidth = readback.byteSize;
2117 desc.Usage = D3D11_USAGE_STAGING;
2118 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2119 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
2121 qWarning(
"Failed to create buffer: %s",
2122 qPrintable(QSystemError::windowsComString(hr)));
2128 cmd.args.copySubRes.dst = readback.stagingBuf;
2129 cmd.args.copySubRes.dstSubRes = 0;
2130 cmd.args.copySubRes.dstX = 0;
2131 cmd.args.copySubRes.dstY = 0;
2132 cmd.args.copySubRes.dstZ = 0;
2133 cmd.args.copySubRes.src = bufD->buffer;
2134 cmd.args.copySubRes.srcSubRes = 0;
2135 cmd.args.copySubRes.hasSrcBox =
true;
2137 box.left = u.offset;
2138 box.top = box.front = 0;
2139 box.back = box.bottom = 1;
2140 box.right = u.offset + u.readSize;
2141 cmd.args.copySubRes.srcBox = box;
2143 activeBufferReadbacks.append(readback);
2148 Q_ASSERT(dstD->m_type != QRhiBuffer::Dynamic && srcD->m_type != QRhiBuffer::Dynamic);
2152 cmd.args.copySubRes.dst = dstD->buffer;
2153 cmd.args.copySubRes.dstSubRes = 0;
2154 cmd.args.copySubRes.dstX = u.offset;
2155 cmd.args.copySubRes.dstY = 0;
2156 cmd.args.copySubRes.dstZ = 0;
2157 cmd.args.copySubRes.src = srcD->buffer;
2158 cmd.args.copySubRes.srcSubRes = 0;
2159 cmd.args.copySubRes.hasSrcBox =
true;
2161 box.left = u.srcOffset;
2162 box.top = box.front = 0;
2163 box.back = box.bottom = 1;
2164 box.right = u.srcOffset + u.readSize;
2165 cmd.args.copySubRes.srcBox = box;
2168 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2170 ID3D11UnorderedAccessView *uav = bufD->createClearUnorderedAccessView(u.offset, u.readSize);
2173 cbD->ownedUavs.append(uav);
2177 cmd.args.clearUav.uav = uav;
2178 for (UINT &v : cmd.args.clearUav.values)
2179 v = u.fillValue32();
2186 for (
const auto &subres : u.subresDesc)
2187 enqueueSubresUpload(texD, cbD, subres.layer, subres.level, subres.desc);
2192 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2193 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2194 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD
->mipLevelCount);
2195 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD
->mipLevelCount);
2196 const QPoint dp = u.desc.destinationTopLeft();
2197 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2198 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2199 const QPoint sp = u.desc.sourceTopLeft();
2201 srcBox.left = UINT(sp.x());
2202 srcBox.top = UINT(sp.y());
2203 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2205 srcBox.right = srcBox.left + UINT(copySize.width());
2206 srcBox.bottom = srcBox.top + UINT(copySize.height());
2207 srcBox.back = srcBox.front + 1;
2210 cmd.args.copySubRes.dst = dstD->textureResource();
2211 cmd.args.copySubRes.dstSubRes = dstSubRes;
2212 cmd.args.copySubRes.dstX = UINT(dp.x());
2213 cmd.args.copySubRes.dstY = UINT(dp.y());
2214 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2215 cmd.args.copySubRes.src = srcD->textureResource();
2216 cmd.args.copySubRes.srcSubRes = srcSubRes;
2217 cmd.args.copySubRes.hasSrcBox =
true;
2218 cmd.args.copySubRes.srcBox = srcBox;
2221 readback.desc = u.rb;
2222 readback.result = u.result;
2224 ID3D11Resource *src;
2225 DXGI_FORMAT dxgiFormat;
2229 QRhiTexture::Format format;
2236 if (texD->sampleDesc.Count > 1) {
2237 qWarning(
"Multisample texture cannot be read back");
2240 src = texD->textureResource();
2241 dxgiFormat = texD->dxgiFormat;
2242 format = texD->m_format;
2243 const QRect levelRect(QPoint(0, 0), q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2244 rect = u.rb.rect().isValid() ? u.rb.rect() : levelRect;
2246 if (isDepthTextureFormat(format)) {
2253 rect = rect.intersected(levelRect);
2254 copyRect = levelRect;
2255 cropOrigin = rect.topLeft();
2257 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2258 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD
->mipLevelCount);
2262 if (swapChainD->sampleDesc.Count > 1) {
2267 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2268 rcmd.args.resolveSubRes.dstSubRes = 0;
2270 rcmd.args.resolveSubRes.srcSubRes = 0;
2271 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2273 src = swapChainD->backBufferTex;
2274 dxgiFormat = swapChainD->colorFormat;
2275 if (u.rb.rect().isValid())
2278 rect = QRect({0, 0}, swapChainD->pixelSize);
2280 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2281 if (format == QRhiTexture::UnknownFormat)
2284 quint32 byteSize = 0;
2286 quint32 bytesPerPixel = 0;
2287 textureFormatInfo(format, rect.size(), &bpl, &byteSize, &bytesPerPixel);
2289 D3D11_TEXTURE2D_DESC desc = {};
2290 desc.Width = UINT(copyRect.width());
2291 desc.Height = UINT(copyRect.height());
2294 desc.Format = dxgiFormat;
2295 desc.SampleDesc.Count = 1;
2296 desc.Usage = D3D11_USAGE_STAGING;
2297 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2298 ID3D11Texture2D *stagingTex;
2299 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2301 qWarning(
"Failed to create readback staging texture: %s",
2302 qPrintable(QSystemError::windowsComString(hr)));
2308 cmd.args.copySubRes.dst = stagingTex;
2309 cmd.args.copySubRes.dstSubRes = 0;
2310 cmd.args.copySubRes.dstX = 0;
2311 cmd.args.copySubRes.dstY = 0;
2312 cmd.args.copySubRes.dstZ = 0;
2313 cmd.args.copySubRes.src = src;
2314 cmd.args.copySubRes.srcSubRes = subres;
2316 D3D11_BOX srcBox = {};
2317 srcBox.left = UINT(copyRect.left());
2318 srcBox.top = UINT(copyRect.top());
2319 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2321 srcBox.right = srcBox.left + desc.Width;
2322 srcBox.bottom = srcBox.top + desc.Height;
2323 srcBox.back = srcBox.front + 1;
2325 cmd.args.copySubRes.hasSrcBox = !isDepthTextureFormat(format);
2326 cmd.args.copySubRes.srcBox = srcBox;
2328 readback.stagingTex = stagingTex;
2329 readback.byteSize = byteSize;
2331 readback.pixelSize = rect.size();
2332 readback.format = format;
2333 readback.cropOrigin = cropOrigin;
2334 readback.bytesPerPixel = bytesPerPixel;
2336 activeTextureReadbacks.append(readback);
2338 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2341 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2350 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2352 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2354 readback.result->format = readback.format;
2355 readback.result->pixelSize = readback.pixelSize;
2357 D3D11_MAPPED_SUBRESOURCE mp;
2358 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2359 if (SUCCEEDED(hr)) {
2360 readback.result->data.resize(
int(readback.byteSize));
2363 char *dst = readback.result->data.data();
2364 char *src =
static_cast<
char *>(mp.pData)
2365 + readback.cropOrigin.y() * mp.RowPitch
2366 + readback.cropOrigin.x() * readback.bytesPerPixel;
2367 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2368 memcpy(dst, src, readback.bpl);
2369 dst += readback.bpl;
2372 context->Unmap(readback.stagingTex, 0);
2381 char *p = readback.result->data.data();
2382 if (readback.format == QRhiTexture::D24 || readback.format == QRhiTexture::D24S8) {
2383 const bool hasStencil = readback.format == QRhiTexture::D24S8;
2384 for (qsizetype px = 0, count = readback.result->data.size() / 4; px < count; ++px) {
2385 const quint32 texel = qFromUnaligned<quint32>(p + px * 4);
2386 const quint32 stencil = hasStencil ? texel >> 24 : 0;
2387 qToUnaligned(((texel & 0x00FFFFFFu) << 8) | stencil, p + px * 4);
2389 }
else if (readback.format == QRhiTexture::D32FS8) {
2390 for (qsizetype px = 1, count = readback.result->data.size() / 4; px < count; px += 2)
2391 qToUnaligned(qFromUnaligned<quint32>(p + px * 4) & 0xFFu, p + px * 4);
2394 qWarning(
"Failed to map readback staging texture: %s",
2395 qPrintable(QSystemError::windowsComString(hr)));
2398 readback.stagingTex->Release();
2400 if (readback.result->completed)
2401 completedCallbacks.append(readback.result->completed);
2403 activeTextureReadbacks.removeLast();
2406 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2409 D3D11_MAPPED_SUBRESOURCE mp;
2410 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2411 if (SUCCEEDED(hr)) {
2412 readback.result->data.resize(
int(readback.byteSize));
2413 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2414 context->Unmap(readback.stagingBuf, 0);
2416 qWarning(
"Failed to map readback staging texture: %s",
2417 qPrintable(QSystemError::windowsComString(hr)));
2420 readback.stagingBuf->Release();
2422 if (readback.result->completed)
2423 completedCallbacks.append(readback.result->completed);
2425 activeBufferReadbacks.removeLast();
2428 for (
auto f : completedCallbacks)
2434 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2440 QRhiRenderTarget *rt,
2441 const QColor &colorClearValue,
2442 const QRhiDepthStencilClearValue &depthStencilClearValue,
2443 QRhiResourceUpdateBatch *resourceUpdates,
2449 if (resourceUpdates)
2452 bool wantsColorClear =
true;
2453 bool wantsDsClear =
true;
2455 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2457 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2458 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2459 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2467 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2471 clearCmd.args.clear.rtViews = rtD->views;
2472 clearCmd.args.clear.mask = 0;
2473 if (rtD->views.colorAttCount && wantsColorClear)
2475 if (rtD->views.dsv && wantsDsClear)
2478 clearCmd.args.clear.c[0] = colorClearValue.redF();
2479 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2480 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2481 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2482 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2483 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2486 cbD->currentTarget = rt;
2496 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2498 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2501 const QRhiColorAttachment &colorAtt(*it);
2502 if (!colorAtt.resolveTexture())
2508 Q_ASSERT(srcTexD || srcRbD);
2511 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2512 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2513 UINT(colorAtt.resolveLayer()),
2516 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2517 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2518 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2519 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2520 cbD->commands.unget();
2523 if (srcTexD->sampleDesc.Count <= 1) {
2524 qWarning(
"Cannot resolve a non-multisample texture");
2525 cbD->commands.unget();
2528 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2529 qWarning(
"Resolve source and destination sizes do not match");
2530 cbD->commands.unget();
2534 cmd.args.resolveSubRes.src = srcRbD->tex;
2535 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2536 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2537 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2538 cbD->commands.unget();
2541 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2542 qWarning(
"Resolve source and destination sizes do not match");
2543 cbD->commands.unget();
2547 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2548 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2550 if (rtTex->m_desc.depthResolveTexture())
2551 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2555 cbD->currentTarget =
nullptr;
2557 if (resourceUpdates)
2562 QRhiResourceUpdateBatch *resourceUpdates,
2568 if (resourceUpdates)
2576 fbCmd.args.setRenderTarget.rtViews.reset();
2593 if (resourceUpdates)
2604 if (pipelineChanged) {
2605 cbD->currentGraphicsPipeline =
nullptr;
2606 cbD->currentComputePipeline = psD;
2611 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2622 cmd.args.dispatch.x = UINT(x);
2623 cmd.args.dispatch.y = UINT(y);
2624 cmd.args.dispatch.z = UINT(z);
2628 quint32 indirectBufferOffset)
2635 cmd.args.dispatchIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
2636 cmd.args.dispatchIndirect.indirectBufferOffset = indirectBufferOffset;
2640 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2641 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2642 quint32 maxDrawCount, quint32 stride)
2645 Q_UNUSED(indirectBuffer);
2646 Q_UNUSED(indirectBufferOffset);
2647 Q_UNUSED(countBuffer);
2648 Q_UNUSED(countBufferOffset);
2649 Q_UNUSED(maxDrawCount);
2651 qWarning(
"drawIndirectCount is not supported by the D3D11 backend");
2655 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2656 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2657 quint32 maxDrawCount, quint32 stride)
2660 Q_UNUSED(indirectBuffer);
2661 Q_UNUSED(indirectBufferOffset);
2662 Q_UNUSED(countBuffer);
2663 Q_UNUSED(countBufferOffset);
2664 Q_UNUSED(maxDrawCount);
2666 qWarning(
"drawIndexedIndirectCount is not supported by the D3D11 backend");
2671 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2672 uint pushConstantStages)
2674 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2675 if (!map || map->isEmpty()) {
2683 if (pushConstantStages & (1u << uint(stageIndex)))
2685 return { binding, binding };
2688 auto it = map->constFind(binding);
2689 if (it != map->cend())
2699 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2700 uint pushConstantStages)
2702 srbD->resourceBatches.clear();
2708 ID3D11Buffer *buffer;
2709 uint offsetInConstants;
2710 uint sizeInConstants;
2714 ID3D11ShaderResourceView *srv;
2718 ID3D11SamplerState *sampler;
2722 ID3D11UnorderedAccessView *uav;
2724 QVarLengthArray<Buffer, 8> buffers;
2725 QVarLengthArray<Texture, 8> textures;
2726 QVarLengthArray<Sampler, 8> samplers;
2727 QVarLengthArray<Uav, 8> uavs;
2730 for (
const Buffer &buf : buffers) {
2731 batches.ubufs.feed(buf.breg, buf.buffer);
2732 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2733 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2734 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2740 for (
const Texture &t : textures)
2741 batches.shaderresources.feed(t.treg, t.srv);
2742 for (
const Sampler &s : samplers)
2743 batches.samplers.feed(s.sreg, s.sampler);
2748 for (
const Stage::Uav &u : uavs)
2749 batches.uavs.feed(u.ureg, u.uav);
2754 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2755 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2758 case QRhiShaderResourceBinding::UniformBuffer:
2761 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2762 bd.ubuf.id = bufD->m_id;
2770 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2774 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2775 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2776 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2777 if (nativeBinding.first >= 0)
2778 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2780 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2781 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2782 if (nativeBinding.first >= 0)
2783 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2785 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2786 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2787 if (nativeBinding.first >= 0)
2788 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2790 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2791 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2792 if (nativeBinding.first >= 0)
2793 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2795 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2796 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2797 if (nativeBinding.first >= 0)
2798 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2800 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2801 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2802 if (nativeBinding.first >= 0)
2803 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2807 case QRhiShaderResourceBinding::SampledTexture:
2808 case QRhiShaderResourceBinding::Texture:
2809 case QRhiShaderResourceBinding::Sampler:
2811 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex;
2812 bd.stex.d.resize(data->count());
2813 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2814 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2815 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2816 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2817 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2818 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2822 for (
int elem = 0; elem < data->count(); ++elem) {
2825 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2826 bd.stex.d[elem].texGeneration = texD ? texD
->generation : 0;
2827 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2828 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD
->generation : 0;
2833 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2834 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2835 : (samplerD ? nativeBindingVert.first : -1);
2836 if (nativeBindingVert.first >= 0 && texD)
2837 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2838 if (samplerBinding >= 0)
2839 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2841 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2842 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2843 : (samplerD ? nativeBindingHull.first : -1);
2844 if (nativeBindingHull.first >= 0 && texD)
2845 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2846 if (samplerBinding >= 0)
2847 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2849 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2850 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2851 : (samplerD ? nativeBindingDomain.first : -1);
2852 if (nativeBindingDomain.first >= 0 && texD)
2853 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2854 if (samplerBinding >= 0)
2855 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2857 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2858 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2859 : (samplerD ? nativeBindingGeom.first : -1);
2860 if (nativeBindingGeom.first >= 0 && texD)
2861 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2862 if (samplerBinding >= 0)
2863 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2865 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2866 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2867 : (samplerD ? nativeBindingFrag.first : -1);
2868 if (nativeBindingFrag.first >= 0 && texD)
2869 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2870 if (samplerBinding >= 0)
2871 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2873 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2874 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2875 : (samplerD ? nativeBindingComp.first : -1);
2876 if (nativeBindingComp.first >= 0 && texD)
2877 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2878 if (samplerBinding >= 0)
2879 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2884 case QRhiShaderResourceBinding::ImageLoad:
2885 case QRhiShaderResourceBinding::ImageStore:
2886 case QRhiShaderResourceBinding::ImageLoadStore:
2889 bd.simage.id = texD->m_id;
2891 bool validStage =
false;
2892 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2893 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2894 if (nativeBinding.first >= 0) {
2895 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2897 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2901 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2902 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2903 if (nativeBinding.first >= 0) {
2904 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2906 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2911 qWarning(
"Unordered access only supported at fragment/compute stage");
2914 case QRhiShaderResourceBinding::BufferLoad:
2915 case QRhiShaderResourceBinding::BufferStore:
2916 case QRhiShaderResourceBinding::BufferLoadStore:
2919 bd.sbuf.id = bufD->m_id;
2921 bool validStage =
false;
2922 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2923 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2924 if (nativeBinding.first >= 0) {
2925 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2927 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2931 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2932 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2933 if (nativeBinding.first >= 0) {
2934 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2936 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2941 qWarning(
"Unordered access only supported at fragment/compute stage");
2955 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2956 return a.breg < b.breg;
2958 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2959 return a.treg < b.treg;
2961 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2962 return a.sreg < b.sreg;
2964 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2965 return a.ureg < b.ureg;
2969 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2970 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2971 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2972 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2973 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2974 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2976 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2977 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2978 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2979 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2980 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2981 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2983 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2984 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2992 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2994 D3D11_MAPPED_SUBRESOURCE mp;
2995 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2996 if (SUCCEEDED(hr)) {
2997 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2998 context->Unmap(bufD->buffer, 0);
3000 qWarning(
"Failed to map buffer: %s",
3001 qPrintable(QSystemError::windowsComString(hr)));
3007 const QRhiBatchedBindings<UINT> *originalBindings,
3008 const QRhiBatchedBindings<UINT> *staticOffsets,
3009 const uint *dynOfsPairs,
int dynOfsPairCount)
3011 const int count = staticOffsets->batches[batchIndex].resources.count();
3014 for (
int b = 0; b < count; ++b) {
3015 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
3016 for (
int di = 0; di < dynOfsPairCount; ++di) {
3017 const uint binding = dynOfsPairs[2 * di];
3020 if (binding == originalBindings->batches[batchIndex].resources[b]) {
3021 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
3022 offsets[b] = offsetInConstants;
3031 if (startSlot + countSlots > maxSlots) {
3032 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
3033 resType, countSlots, startSlot, maxSlots);
3034 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
3039#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
3040 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
3041 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
3042 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
3043 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
3044 batches.ubufs.batches[i].resources.count(),
3045 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
3046 #stagePrefixU " cbuf");
3048 if (!dynOfsPairCount) {
3049 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3051 batches.ubufs.batches[i].resources.constData(),
3052 batches.ubufoffsets.batches[i].resources.constData(),
3053 batches.ubufsizes.batches[i].resources.constData());
3055 applyDynamicOffsets(offsets, i,
3056 &batches.ubuforigbindings, &batches.ubufoffsets,
3057 dynOfsPairs, dynOfsPairCount);
3058 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3060 batches.ubufs.batches[i].resources.constData(),
3062 batches.ubufsizes.batches[i].resources.constData());
3068#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
3069 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
3070 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
3071 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3072 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
3074 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
3076 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
3077 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3078 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
3080 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
3081 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
3082 int(batch.startBinding + count) - 1
);
3087#define SETUAVBATCH(stagePrefixL, stagePrefixU)
3088 if (allResourceBatches.stagePrefixL##UavBatches.present) {
3089 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
3090 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3093 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
3095 batch.resources.constData(),
3097 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
3098 int(batch.startBinding + count) - 1
);
3105 const uint *dynOfsPairs,
int dynOfsPairCount,
3106 bool offsetOnlyChange,
3118 if (!offsetOnlyChange) {
3128 if (allResourceBatches.fsUavBatches.present) {
3129 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
3130 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
3132 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
3134 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
3135 context->OMSetRenderTargetsAndUnorderedAccessViews(
3136 UINT(rtUavState->rtViews.colorAttCount),
3137 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
3138 rtUavState->rtViews.dsv,
3139 UINT(batch.startBinding),
3141 batch.resources.constData(),
3144 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
3145 int(batch.startBinding + count) - 1);
3158 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
3164 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
3165 for (
int i = 0; i < count; ++i)
3166 nullbufs[i] =
nullptr;
3167 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
3168 for (
int i = 0; i < count; ++i)
3170 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
3171 for (
int i = 0; i < count; ++i)
3173 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
3183 if (nullsrvCount > 0) {
3184 QVarLengthArray<ID3D11ShaderResourceView *,
3185 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
3186 for (
int i = 0; i < nullsrvs.count(); ++i)
3187 nullsrvs[i] =
nullptr;
3189 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
3193 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
3197 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
3201 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
3205 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
3209 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
3215 rtUavState->update(cbD->currentRenderTargetViews);
3216 context->OMSetRenderTargetsAndUnorderedAccessViews(
3217 UINT(cbD->currentRenderTargetViews.colorAttCount),
3218 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
3219 cbD->currentRenderTargetViews.dsv,
3220 0, 0,
nullptr,
nullptr);
3225 QVarLengthArray<ID3D11UnorderedAccessView *,
3226 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
3227 for (
int i = 0; i < nulluavCount; ++i)
3228 nulluavs[i] =
nullptr;
3229 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
3234#define SETSHADER(StageL, StageU)
3235 if (cmd.args.bindGraphicsPipeline.StageL) {
3236 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
3237 currentShaderMask |= StageU##MaskBit;
3238 } else if (currentShaderMask & StageU##MaskBit) {
3239 context->StageU##SetShader(nullptr, nullptr, 0
);
3240 currentShaderMask &= ~StageU##MaskBit;
3245 quint32 stencilRef = 0;
3246 float blendConstants[] = { 1, 1, 1, 1 };
3247 enum ActiveShaderMask {
3254 int currentShaderMask = 0xFF;
3260 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3263 case QD3D11CommandBuffer::Command::BeginFrame:
3264 if (cmd.args.beginFrame.tsDisjointQuery)
3265 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3266 if (cmd.args.beginFrame.tsQuery) {
3267 if (cmd.args.beginFrame.swapchainRtv) {
3272 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3273 rtUavState.update(cbD->currentRenderTargetViews);
3274 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3276 context->End(cmd.args.beginFrame.tsQuery);
3279 case QD3D11CommandBuffer::Command::EndFrame:
3280 if (cmd.args.endFrame.tsQuery)
3281 context->End(cmd.args.endFrame.tsQuery);
3282 if (cmd.args.endFrame.tsDisjointQuery)
3283 context->End(cmd.args.endFrame.tsDisjointQuery);
3290 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3291 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3292 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3293 context->OMSetRenderTargets(colorAttCount,
3294 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3295 cmd.args.setRenderTarget.rtViews.dsv);
3302 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3303 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3306 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3307 ds |= D3D11_CLEAR_DEPTH;
3308 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3309 ds |= D3D11_CLEAR_STENCIL;
3310 if (ds && cmd.args.clear.rtViews.dsv)
3311 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3317 v.TopLeftX = cmd.args.viewport.x;
3318 v.TopLeftY = cmd.args.viewport.y;
3319 v.Width = cmd.args.viewport.w;
3320 v.Height = cmd.args.viewport.h;
3321 v.MinDepth = cmd.args.viewport.d0;
3322 v.MaxDepth = cmd.args.viewport.d1;
3323 context->RSSetViewports(1, &v);
3329 r.left = cmd.args.scissor.x;
3330 r.top = cmd.args.scissor.y;
3332 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3333 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3334 context->RSSetScissorRects(1, &r);
3340 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3341 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3342 UINT(cmd.args.bindVertexBuffers.slotCount),
3343 cmd.args.bindVertexBuffers.buffers,
3344 cmd.args.bindVertexBuffers.strides,
3345 cmd.args.bindVertexBuffers.offsets);
3349 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3350 cmd.args.bindIndexBuffer.format,
3351 cmd.args.bindIndexBuffer.offset);
3360 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3361 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3362 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3363 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3364 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3369 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex]
,
3370 cmd.args.bindShaderResources.dynamicOffsetPairs
,
3371 cmd.args.bindShaderResources.dynamicOffsetCount
,
3372 cmd.args.bindShaderResources.offsetOnlyChange
,
3380 ID3D11Buffer *buf = cmd.args.setPushConstants.buffer;
3381 D3D11_MAPPED_SUBRESOURCE mp;
3382 HRESULT hr = context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3383 if (SUCCEEDED(hr)) {
3384 memcpy(mp.pData, cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
3385 cmd.args.setPushConstants.size);
3386 context->Unmap(buf, 0);
3388 qWarning(
"Failed to map push constant buffer: %s",
3389 qPrintable(QSystemError::windowsComString(hr)));
3392 const UINT startSlot = cmd.args.setPushConstants.startSlot;
3393 const uint stages = cmd.args.setPushConstants.stages;
3397 if (stages & (1u << uint(RBM_VERTEX)))
3398 context->VSSetConstantBuffers(startSlot, 1, &buf);
3399 if (stages & (1u << uint(RBM_HULL)))
3400 context->HSSetConstantBuffers(startSlot, 1, &buf);
3401 if (stages & (1u << uint(RBM_DOMAIN)))
3402 context->DSSetConstantBuffers(startSlot, 1, &buf);
3403 if (stages & (1u << uint(RBM_GEOMETRY)))
3404 context->GSSetConstantBuffers(startSlot, 1, &buf);
3405 if (stages & (1u << uint(RBM_FRAGMENT)))
3406 context->PSSetConstantBuffers(startSlot, 1, &buf);
3407 if (stages & (1u << uint(RBM_COMPUTE)))
3408 context->CSSetConstantBuffers(startSlot, 1, &buf);
3412 stencilRef = cmd.args.stencilRef.ref;
3413 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3416 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3417 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3419 case QD3D11CommandBuffer::Command::Draw:
3420 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3421 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3423 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3424 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3426 case QD3D11CommandBuffer::Command::DrawIndexed:
3427 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3428 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3429 cmd.args.drawIndexed.vertexOffset);
3431 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3432 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3433 cmd.args.drawIndexed.firstInstance);
3437 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3438 const UINT stride = cmd.args.drawIndirect.stride;
3439 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3440 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3441 alignedByteOffsetForArgs += stride;
3447 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3448 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3449 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3450 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3451 alignedByteOffsetForArgs += stride;
3457 if (cmd.args.updateSubRes.dst) {
3458 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3459 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3460 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3463 case QD3D11CommandBuffer::Command::CopySubRes:
3464 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3465 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3466 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3467 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3469 case QD3D11CommandBuffer::Command::ClearUav:
3470 context->ClearUnorderedAccessViewUint(cmd.args.clearUav.uav, cmd.args.clearUav.values);
3472 case QD3D11CommandBuffer::Command::ResolveSubRes:
3473 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3474 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3475 cmd.args.resolveSubRes.format);
3477 case QD3D11CommandBuffer::Command::GenMip:
3478 context->GenerateMips(cmd.args.genMip.srv);
3480 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3481 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3483 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3484 annotations->EndEvent();
3486 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3487 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3489 case QD3D11CommandBuffer::Command::BindComputePipeline:
3490 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3492 case QD3D11CommandBuffer::Command::Dispatch:
3493 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3495 case QD3D11CommandBuffer::Command::DispatchIndirect:
3496 context->DispatchIndirect(cmd.args.dispatchIndirect.indirectBuffer,
3497 cmd.args.dispatchIndirect.indirectBufferOffset);
3526 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3527 it.value()->Release();
3532 rhiD->unregisterResource(
this);
3538 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3539 u |= D3D11_BIND_VERTEX_BUFFER;
3540 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3541 u |= D3D11_BIND_INDEX_BUFFER;
3542 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3543 u |= D3D11_BIND_CONSTANT_BUFFER;
3544 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3545 u |= D3D11_BIND_UNORDERED_ACCESS;
3554 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3555 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3559 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3560 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3564 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3565 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3569 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3574 const quint32 minSize = m_usage.testFlag(QRhiBuffer::IndirectBuffer) ? 12u : 1u;
3575 const quint32 roundedSize = aligned(qMax(nonZeroSize, minSize),
3576 m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3578 D3D11_BUFFER_DESC desc = {};
3579 desc.ByteWidth = roundedSize;
3580 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3581 desc.BindFlags = toD3DBufferUsage(m_usage);
3582 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3583 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3584 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3585 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3588 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3590 qWarning(
"Failed to create buffer: %s",
3591 qPrintable(QSystemError::windowsComString(hr)));
3595 if (m_type == Dynamic) {
3596 dynBuf =
new char[nonZeroSize];
3600 if (!m_objectName.isEmpty())
3601 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3604 rhiD->registerResource(
this);
3610 if (m_type == Dynamic) {
3614 return { { &buffer }, 1 };
3625 Q_ASSERT(m_type == Dynamic);
3626 D3D11_MAPPED_SUBRESOURCE mp;
3628 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3630 qWarning(
"Failed to map buffer: %s",
3631 qPrintable(QSystemError::windowsComString(hr)));
3634 return static_cast<
char *>(mp.pData);
3640 rhiD->context->Unmap(buffer, 0);
3645 auto it = uavs.find(offset);
3646 if (it != uavs.end())
3650 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3651 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3652 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3653 desc.Buffer.FirstElement = offset / 4u;
3654 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3655 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3658 ID3D11UnorderedAccessView *uav =
nullptr;
3659 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3661 qWarning(
"Failed to create UAV: %s",
3662 qPrintable(QSystemError::windowsComString(hr)));
3675 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3676 desc.Format = DXGI_FORMAT_R32_UINT;
3677 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3678 desc.Buffer.FirstElement = offset / 4u;
3679 desc.Buffer.NumElements = size / 4u;
3682 ID3D11UnorderedAccessView *uav =
nullptr;
3683 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3685 qWarning(
"Failed to create UAV: %s",
3686 qPrintable(QSystemError::windowsComString(hr)));
3694 int sampleCount, QRhiRenderBuffer::Flags flags,
3695 QRhiTexture::Format backingFormatHint)
3725 rhiD->unregisterResource(
this);
3733 if (m_pixelSize.isEmpty())
3737 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3739 D3D11_TEXTURE2D_DESC desc = {};
3740 desc.Width = UINT(m_pixelSize.width());
3741 desc.Height = UINT(m_pixelSize.height());
3744 desc.SampleDesc = sampleDesc;
3745 desc.Usage = D3D11_USAGE_DEFAULT;
3747 if (m_type == Color) {
3748 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3749 : toD3DTextureFormat(m_backingFormatHint, {});
3750 desc.Format = dxgiFormat;
3751 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3752 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3754 qWarning(
"Failed to create color renderbuffer: %s",
3755 qPrintable(QSystemError::windowsComString(hr)));
3758 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3759 rtvDesc.Format = dxgiFormat;
3760 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3761 : D3D11_RTV_DIMENSION_TEXTURE2D;
3762 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3764 qWarning(
"Failed to create rtv: %s",
3765 qPrintable(QSystemError::windowsComString(hr)));
3768 }
else if (m_type == DepthStencil) {
3769 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3770 desc.Format = dxgiFormat;
3771 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3772 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3774 qWarning(
"Failed to create depth-stencil buffer: %s",
3775 qPrintable(QSystemError::windowsComString(hr)));
3778 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3779 dsvDesc.Format = dxgiFormat;
3780 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3781 : D3D11_DSV_DIMENSION_TEXTURE2D;
3782 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3784 qWarning(
"Failed to create dsv: %s",
3785 qPrintable(QSystemError::windowsComString(hr)));
3792 if (!m_objectName.isEmpty())
3793 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3796 rhiD->registerResource(
this);
3802 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3803 return m_backingFormatHint;
3805 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3809 int arraySize,
int sampleCount, Flags flags)
3812 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3813 perLevelViews[i] =
nullptr;
3823 if (!tex && !tex3D && !tex1D)
3831 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3832 if (perLevelViews[i]) {
3833 perLevelViews[i]->Release();
3834 perLevelViews[i] =
nullptr;
3853 rhiD->unregisterResource(
this);
3859 case QRhiTexture::Format::D16:
3860 return DXGI_FORMAT_R16_FLOAT;
3861 case QRhiTexture::Format::D24:
3862 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3863 case QRhiTexture::Format::D24S8:
3864 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3865 case QRhiTexture::Format::D32F:
3866 return DXGI_FORMAT_R32_FLOAT;
3867 case QRhiTexture::Format::D32FS8:
3868 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3871 return DXGI_FORMAT_R32_FLOAT;
3878 case QRhiTexture::Format::D16:
3879 return DXGI_FORMAT_D16_UNORM;
3880 case QRhiTexture::Format::D24:
3881 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3882 case QRhiTexture::Format::D24S8:
3883 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3884 case QRhiTexture::Format::D32F:
3885 return DXGI_FORMAT_D32_FLOAT;
3886 case QRhiTexture::Format::D32FS8:
3887 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3890 return DXGI_FORMAT_D32_FLOAT;
3896 if (tex || tex3D || tex1D)
3900 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3903 const bool isDepth = isDepthTextureFormat(m_format);
3904 const bool isCube = m_flags.testFlag(CubeMap);
3905 const bool is3D = m_flags.testFlag(ThreeDimensional);
3906 const bool isArray = m_flags.testFlag(TextureArray);
3907 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3908 const bool is1D = m_flags.testFlag(OneDimensional);
3910 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3911 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3913 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3914 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3915 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3916 if (sampleDesc.Count > 1) {
3918 qWarning(
"Cubemap texture cannot be multisample");
3922 qWarning(
"3D texture cannot be multisample");
3926 qWarning(
"Multisample texture cannot have mipmaps");
3930 if (isDepth && hasMipMaps) {
3931 qWarning(
"Depth texture cannot have mipmaps");
3934 if (isCube && is3D) {
3935 qWarning(
"Texture cannot be both cube and 3D");
3938 if (isArray && is3D) {
3939 qWarning(
"Texture cannot be both array and 3D");
3942 if (isCube && is1D) {
3943 qWarning(
"Texture cannot be both cube and 1D");
3947 qWarning(
"Texture cannot be both 1D and 3D");
3950 if (m_depth > 1 && !is3D) {
3951 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3954 if (m_arraySize > 0 && !isArray) {
3955 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3958 if (m_arraySize < 1 && isArray) {
3959 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3963 if (!rhiD->textureFormatInfo(m_format, size,
nullptr,
nullptr,
nullptr))
3967 *adjustedSize = size;
3975 const bool isDepth = isDepthTextureFormat(m_format);
3976 const bool isCube = m_flags.testFlag(CubeMap);
3977 const bool is3D = m_flags.testFlag(ThreeDimensional);
3978 const bool isArray = m_flags.testFlag(TextureArray);
3979 const bool is1D = m_flags.testFlag(OneDimensional);
3981 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3982 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3984 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3989 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3991 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3992 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3993 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3995 srvDesc.Texture1DArray.FirstArraySlice = 0;
3996 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3999 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
4002 }
else if (isArray) {
4003 if (sampleDesc.Count > 1) {
4004 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4005 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4006 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
4007 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
4009 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4010 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
4013 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
4015 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4016 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
4017 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
4019 srvDesc.Texture2DArray.FirstArraySlice = 0;
4020 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
4024 if (sampleDesc.Count > 1) {
4025 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
4027 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
4030 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
4036 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
4038 qWarning(
"Failed to create srv: %s",
4039 qPrintable(QSystemError::windowsComString(hr)));
4050 if (!prepareCreate(&size))
4053 const bool isDepth = isDepthTextureFormat(m_format);
4054 const bool isCube = m_flags.testFlag(CubeMap);
4055 const bool is3D = m_flags.testFlag(ThreeDimensional);
4056 const bool isArray = m_flags.testFlag(TextureArray);
4057 const bool is1D = m_flags.testFlag(OneDimensional);
4059 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
4060 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
4061 if (m_flags.testFlag(RenderTarget)) {
4063 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
4065 bindFlags |= D3D11_BIND_RENDER_TARGET;
4067 if (m_flags.testFlag(UsedWithGenerateMips)) {
4069 qWarning(
"Depth texture cannot have mipmaps generated");
4072 bindFlags |= D3D11_BIND_RENDER_TARGET;
4073 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
4075 if (m_flags.testFlag(UsedWithLoadStore))
4076 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
4080 D3D11_TEXTURE1D_DESC desc = {};
4081 desc.Width = UINT(size.width());
4083 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
4084 desc.Format = dxgiFormat;
4085 desc.Usage = D3D11_USAGE_DEFAULT;
4086 desc.BindFlags = bindFlags;
4087 desc.MiscFlags = miscFlags;
4089 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
4091 qWarning(
"Failed to create 1D texture: %s",
4092 qPrintable(QSystemError::windowsComString(hr)));
4095 if (!m_objectName.isEmpty())
4096 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
4097 m_objectName.constData());
4099 D3D11_TEXTURE2D_DESC desc = {};
4100 desc.Width = UINT(size.width());
4101 desc.Height = UINT(size.height());
4103 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
4104 desc.Format = dxgiFormat;
4105 desc.SampleDesc = sampleDesc;
4106 desc.Usage = D3D11_USAGE_DEFAULT;
4107 desc.BindFlags = bindFlags;
4108 desc.MiscFlags = miscFlags;
4110 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
4112 qWarning(
"Failed to create 2D texture: %s",
4113 qPrintable(QSystemError::windowsComString(hr)));
4114 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4118 if (!m_objectName.isEmpty())
4119 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4121 D3D11_TEXTURE3D_DESC desc = {};
4122 desc.Width = UINT(size.width());
4123 desc.Height = UINT(size.height());
4124 desc.Depth = UINT(qMax(1, m_depth));
4126 desc.Format = dxgiFormat;
4127 desc.Usage = D3D11_USAGE_DEFAULT;
4128 desc.BindFlags = bindFlags;
4129 desc.MiscFlags = miscFlags;
4131 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
4133 qWarning(
"Failed to create 3D texture: %s",
4134 qPrintable(QSystemError::windowsComString(hr)));
4135 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4139 if (!m_objectName.isEmpty())
4140 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4147 rhiD->registerResource(
this);
4156 if (!prepareCreate())
4159 if (m_flags.testFlag(ThreeDimensional))
4160 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
4161 else if (m_flags.testFlags(OneDimensional))
4162 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
4164 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
4171 rhiD->registerResource(
this);
4177 return { quint64(textureResource()), 0 };
4182 if (perLevelViews[level])
4183 return perLevelViews[level];
4185 const bool isCube = m_flags.testFlag(CubeMap);
4186 const bool isArray = m_flags.testFlag(TextureArray);
4187 const bool is3D = m_flags.testFlag(ThreeDimensional);
4188 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
4189 desc.Format = dxgiFormat;
4191 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4192 desc.Texture2DArray.MipSlice = UINT(level);
4193 desc.Texture2DArray.FirstArraySlice = 0;
4194 desc.Texture2DArray.ArraySize = 6;
4195 }
else if (isArray) {
4196 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4197 desc.Texture2DArray.MipSlice = UINT(level);
4198 desc.Texture2DArray.FirstArraySlice = 0;
4199 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
4201 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
4202 desc.Texture3D.MipSlice = UINT(level);
4203 desc.Texture3D.WSize = UINT(m_depth);
4205 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
4206 desc.Texture2D.MipSlice = UINT(level);
4210 ID3D11UnorderedAccessView *uav =
nullptr;
4211 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
4213 qWarning(
"Failed to create UAV: %s",
4214 qPrintable(QSystemError::windowsComString(hr)));
4218 perLevelViews[level] = uav;
4223 AddressMode u, AddressMode v, AddressMode w)
4238 samplerState->Release();
4239 samplerState =
nullptr;
4243 rhiD->unregisterResource(
this);
4246static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
4248 if (minFilter == QRhiSampler::Nearest) {
4249 if (magFilter == QRhiSampler::Nearest) {
4250 if (mipFilter == QRhiSampler::Linear)
4251 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
4253 return D3D11_FILTER_MIN_MAG_MIP_POINT;
4255 if (mipFilter == QRhiSampler::Linear)
4256 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
4258 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
4261 if (magFilter == QRhiSampler::Nearest) {
4262 if (mipFilter == QRhiSampler::Linear)
4263 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
4265 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
4267 if (mipFilter == QRhiSampler::Linear)
4268 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4270 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
4275 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4281 case QRhiSampler::Repeat:
4282 return D3D11_TEXTURE_ADDRESS_WRAP;
4283 case QRhiSampler::ClampToEdge:
4284 return D3D11_TEXTURE_ADDRESS_CLAMP;
4285 case QRhiSampler::Mirror:
4286 return D3D11_TEXTURE_ADDRESS_MIRROR;
4289 return D3D11_TEXTURE_ADDRESS_CLAMP;
4296 case QRhiSampler::Never:
4297 return D3D11_COMPARISON_NEVER;
4298 case QRhiSampler::Less:
4299 return D3D11_COMPARISON_LESS;
4300 case QRhiSampler::Equal:
4301 return D3D11_COMPARISON_EQUAL;
4302 case QRhiSampler::LessOrEqual:
4303 return D3D11_COMPARISON_LESS_EQUAL;
4304 case QRhiSampler::Greater:
4305 return D3D11_COMPARISON_GREATER;
4306 case QRhiSampler::NotEqual:
4307 return D3D11_COMPARISON_NOT_EQUAL;
4308 case QRhiSampler::GreaterOrEqual:
4309 return D3D11_COMPARISON_GREATER_EQUAL;
4310 case QRhiSampler::Always:
4311 return D3D11_COMPARISON_ALWAYS;
4314 return D3D11_COMPARISON_NEVER;
4323 D3D11_SAMPLER_DESC desc = {};
4324 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
4325 if (m_compareOp != Never)
4326 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
4327 desc.AddressU = toD3DAddressMode(m_addressU);
4328 desc.AddressV = toD3DAddressMode(m_addressV);
4329 desc.AddressW = toD3DAddressMode(m_addressW);
4330 desc.MaxAnisotropy = 1.0f;
4331 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
4332 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
4335 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
4337 qWarning(
"Failed to create sampler state: %s",
4338 qPrintable(QSystemError::windowsComString(hr)));
4343 rhiD->registerResource(
this);
4362 rhiD->unregisterResource(
this);
4375 rhiD->registerResource(rpD,
false);
4412 return d.sampleCount;
4416 const QRhiTextureRenderTargetDescription &desc,
4434 if (!rtv[0] && !dsv)
4453 rhiD->unregisterResource(
this);
4460 rhiD->registerResource(rpD,
false);
4469 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4470 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4471 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4475 int colorAttCount = 0;
4477 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4479 const QRhiColorAttachment &colorAtt(*it);
4480 QRhiTexture *texture = colorAtt.texture();
4481 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4482 Q_ASSERT(texture || rb);
4485 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4486 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4487 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4488 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4489 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4490 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4491 rtvDesc.Texture2DArray.ArraySize = 1;
4492 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4493 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4494 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4495 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4496 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4497 rtvDesc.Texture1DArray.ArraySize = 1;
4499 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4500 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4502 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4503 if (texD->sampleDesc.Count > 1) {
4504 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4505 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4506 rtvDesc.Texture2DMSArray.ArraySize = 1;
4508 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4509 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4510 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4511 rtvDesc.Texture2DArray.ArraySize = 1;
4513 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4514 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4515 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4516 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4517 rtvDesc.Texture3D.WSize = 1;
4519 if (texD->sampleDesc.Count > 1) {
4520 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4522 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4523 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4526 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4528 qWarning(
"Failed to create rtv: %s",
4529 qPrintable(QSystemError::windowsComString(hr)));
4533 if (attIndex == 0) {
4534 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4535 d.sampleCount =
int(texD->sampleDesc.Count);
4540 rtv[attIndex] = rbD->rtv;
4541 if (attIndex == 0) {
4542 d.pixelSize = rbD->pixelSize();
4543 d.sampleCount =
int(rbD->sampleDesc.Count);
4549 if (hasDepthStencil) {
4550 if (m_desc.depthTexture()) {
4553 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4554 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4555 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4556 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4557 if (isMultisample) {
4558 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4559 if (m_desc.depthLayer() >= 0) {
4560 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4561 dsvDesc.Texture2DMSArray.ArraySize = 1;
4562 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4563 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4564 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4566 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4567 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4570 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4571 if (m_desc.depthLayer() >= 0) {
4572 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4573 dsvDesc.Texture2DArray.ArraySize = 1;
4574 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4575 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4576 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4578 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4579 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4584 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4585 : D3D11_DSV_DIMENSION_TEXTURE2D;
4587 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4589 qWarning(
"Failed to create dsv: %s",
4590 qPrintable(QSystemError::windowsComString(hr)));
4593 if (colorAttCount == 0) {
4594 d.pixelSize = depthTexD->pixelSize();
4595 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4600 dsv = depthRbD->dsv;
4601 if (colorAttCount == 0) {
4602 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4603 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4610 d.views.setFrom(colorAttCount, rtv, dsv);
4612 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4614 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4616 rhiD->registerResource(
this);
4622 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4635 return d.sampleCount;
4650 sortedBindings.clear();
4651 boundResourceData.clear();
4655 rhiD->unregisterResource(
this);
4660 if (!sortedBindings.isEmpty())
4664 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4667 rhiD->updateLayoutDesc(
this);
4669 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4670 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4672 boundResourceData.resize(sortedBindings.count());
4674 for (BoundResourceData &bd : boundResourceData)
4678 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4679 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4680 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4681 hasDynamicOffset =
true;
4687 rhiD->registerResource(
this,
false);
4693 sortedBindings.clear();
4694 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4695 if (!flags.testFlag(BindingsAreSorted))
4696 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4698 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4699 for (BoundResourceData &bd : boundResourceData)
4719 s.shader->Release();
4722 s.nativeResourceBindingMap.clear();
4734 blendState->Release();
4735 blendState =
nullptr;
4739 inputLayout->Release();
4740 inputLayout =
nullptr;
4744 rastState->Release();
4745 rastState =
nullptr;
4748 releasePipelineShader(vs);
4749 releasePipelineShader(hs);
4750 releasePipelineShader(ds);
4751 releasePipelineShader(gs);
4752 releasePipelineShader(fs);
4758 rhiD->unregisterResource(
this);
4764 case QRhiGraphicsPipeline::None:
4765 return D3D11_CULL_NONE;
4766 case QRhiGraphicsPipeline::Front:
4767 return D3D11_CULL_FRONT;
4768 case QRhiGraphicsPipeline::Back:
4769 return D3D11_CULL_BACK;
4772 return D3D11_CULL_NONE;
4779 case QRhiGraphicsPipeline::Fill:
4780 return D3D11_FILL_SOLID;
4781 case QRhiGraphicsPipeline::Line:
4782 return D3D11_FILL_WIREFRAME;
4785 return D3D11_FILL_SOLID;
4792 case QRhiGraphicsPipeline::Never:
4793 return D3D11_COMPARISON_NEVER;
4794 case QRhiGraphicsPipeline::Less:
4795 return D3D11_COMPARISON_LESS;
4796 case QRhiGraphicsPipeline::Equal:
4797 return D3D11_COMPARISON_EQUAL;
4798 case QRhiGraphicsPipeline::LessOrEqual:
4799 return D3D11_COMPARISON_LESS_EQUAL;
4800 case QRhiGraphicsPipeline::Greater:
4801 return D3D11_COMPARISON_GREATER;
4802 case QRhiGraphicsPipeline::NotEqual:
4803 return D3D11_COMPARISON_NOT_EQUAL;
4804 case QRhiGraphicsPipeline::GreaterOrEqual:
4805 return D3D11_COMPARISON_GREATER_EQUAL;
4806 case QRhiGraphicsPipeline::Always:
4807 return D3D11_COMPARISON_ALWAYS;
4810 return D3D11_COMPARISON_ALWAYS;
4817 case QRhiGraphicsPipeline::StencilZero:
4818 return D3D11_STENCIL_OP_ZERO;
4819 case QRhiGraphicsPipeline::Keep:
4820 return D3D11_STENCIL_OP_KEEP;
4821 case QRhiGraphicsPipeline::Replace:
4822 return D3D11_STENCIL_OP_REPLACE;
4823 case QRhiGraphicsPipeline::IncrementAndClamp:
4824 return D3D11_STENCIL_OP_INCR_SAT;
4825 case QRhiGraphicsPipeline::DecrementAndClamp:
4826 return D3D11_STENCIL_OP_DECR_SAT;
4827 case QRhiGraphicsPipeline::Invert:
4828 return D3D11_STENCIL_OP_INVERT;
4829 case QRhiGraphicsPipeline::IncrementAndWrap:
4830 return D3D11_STENCIL_OP_INCR;
4831 case QRhiGraphicsPipeline::DecrementAndWrap:
4832 return D3D11_STENCIL_OP_DECR;
4835 return D3D11_STENCIL_OP_KEEP;
4842 case QRhiVertexInputAttribute::Float4:
4843 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4844 case QRhiVertexInputAttribute::Float3:
4845 return DXGI_FORMAT_R32G32B32_FLOAT;
4846 case QRhiVertexInputAttribute::Float2:
4847 return DXGI_FORMAT_R32G32_FLOAT;
4848 case QRhiVertexInputAttribute::Float:
4849 return DXGI_FORMAT_R32_FLOAT;
4850 case QRhiVertexInputAttribute::UNormByte4:
4851 return DXGI_FORMAT_R8G8B8A8_UNORM;
4852 case QRhiVertexInputAttribute::UNormByte2:
4853 return DXGI_FORMAT_R8G8_UNORM;
4854 case QRhiVertexInputAttribute::UNormByte:
4855 return DXGI_FORMAT_R8_UNORM;
4856 case QRhiVertexInputAttribute::UInt4:
4857 return DXGI_FORMAT_R32G32B32A32_UINT;
4858 case QRhiVertexInputAttribute::UInt3:
4859 return DXGI_FORMAT_R32G32B32_UINT;
4860 case QRhiVertexInputAttribute::UInt2:
4861 return DXGI_FORMAT_R32G32_UINT;
4862 case QRhiVertexInputAttribute::UInt:
4863 return DXGI_FORMAT_R32_UINT;
4864 case QRhiVertexInputAttribute::SInt4:
4865 return DXGI_FORMAT_R32G32B32A32_SINT;
4866 case QRhiVertexInputAttribute::SInt3:
4867 return DXGI_FORMAT_R32G32B32_SINT;
4868 case QRhiVertexInputAttribute::SInt2:
4869 return DXGI_FORMAT_R32G32_SINT;
4870 case QRhiVertexInputAttribute::SInt:
4871 return DXGI_FORMAT_R32_SINT;
4872 case QRhiVertexInputAttribute::Half4:
4874 case QRhiVertexInputAttribute::Half3:
4875 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4876 case QRhiVertexInputAttribute::Half2:
4877 return DXGI_FORMAT_R16G16_FLOAT;
4878 case QRhiVertexInputAttribute::Half:
4879 return DXGI_FORMAT_R16_FLOAT;
4880 case QRhiVertexInputAttribute::UShort4:
4882 case QRhiVertexInputAttribute::UShort3:
4883 return DXGI_FORMAT_R16G16B16A16_UINT;
4884 case QRhiVertexInputAttribute::UShort2:
4885 return DXGI_FORMAT_R16G16_UINT;
4886 case QRhiVertexInputAttribute::UShort:
4887 return DXGI_FORMAT_R16_UINT;
4888 case QRhiVertexInputAttribute::SShort4:
4890 case QRhiVertexInputAttribute::SShort3:
4891 return DXGI_FORMAT_R16G16B16A16_SINT;
4892 case QRhiVertexInputAttribute::SShort2:
4893 return DXGI_FORMAT_R16G16_SINT;
4894 case QRhiVertexInputAttribute::SShort:
4895 return DXGI_FORMAT_R16_SINT;
4898 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4905 case QRhiGraphicsPipeline::Triangles:
4906 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4907 case QRhiGraphicsPipeline::TriangleStrip:
4908 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4909 case QRhiGraphicsPipeline::Lines:
4910 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4911 case QRhiGraphicsPipeline::LineStrip:
4912 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4913 case QRhiGraphicsPipeline::Points:
4914 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4915 case QRhiGraphicsPipeline::Patches:
4916 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4917 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4920 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4927 if (c.testFlag(QRhiGraphicsPipeline::R))
4928 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4929 if (c.testFlag(QRhiGraphicsPipeline::G))
4930 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4931 if (c.testFlag(QRhiGraphicsPipeline::B))
4932 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4933 if (c.testFlag(QRhiGraphicsPipeline::A))
4934 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4947 case QRhiGraphicsPipeline::Zero:
4948 return D3D11_BLEND_ZERO;
4949 case QRhiGraphicsPipeline::One:
4950 return D3D11_BLEND_ONE;
4951 case QRhiGraphicsPipeline::SrcColor:
4952 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4953 case QRhiGraphicsPipeline::OneMinusSrcColor:
4954 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4955 case QRhiGraphicsPipeline::DstColor:
4956 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4957 case QRhiGraphicsPipeline::OneMinusDstColor:
4958 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4959 case QRhiGraphicsPipeline::SrcAlpha:
4960 return D3D11_BLEND_SRC_ALPHA;
4961 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4962 return D3D11_BLEND_INV_SRC_ALPHA;
4963 case QRhiGraphicsPipeline::DstAlpha:
4964 return D3D11_BLEND_DEST_ALPHA;
4965 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4966 return D3D11_BLEND_INV_DEST_ALPHA;
4967 case QRhiGraphicsPipeline::ConstantColor:
4968 case QRhiGraphicsPipeline::ConstantAlpha:
4969 return D3D11_BLEND_BLEND_FACTOR;
4970 case QRhiGraphicsPipeline::OneMinusConstantColor:
4971 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4972 return D3D11_BLEND_INV_BLEND_FACTOR;
4973 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4974 return D3D11_BLEND_SRC_ALPHA_SAT;
4975 case QRhiGraphicsPipeline::Src1Color:
4976 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4977 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4978 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4979 case QRhiGraphicsPipeline::Src1Alpha:
4980 return D3D11_BLEND_SRC1_ALPHA;
4981 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4982 return D3D11_BLEND_INV_SRC1_ALPHA;
4985 return D3D11_BLEND_ZERO;
4992 case QRhiGraphicsPipeline::Add:
4993 return D3D11_BLEND_OP_ADD;
4994 case QRhiGraphicsPipeline::Subtract:
4995 return D3D11_BLEND_OP_SUBTRACT;
4996 case QRhiGraphicsPipeline::ReverseSubtract:
4997 return D3D11_BLEND_OP_REV_SUBTRACT;
4998 case QRhiGraphicsPipeline::Min:
4999 return D3D11_BLEND_OP_MIN;
5000 case QRhiGraphicsPipeline::Max:
5001 return D3D11_BLEND_OP_MAX;
5004 return D3D11_BLEND_OP_ADD;
5011 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
5012 keyBuilder.addData(source);
5013 return keyBuilder.result().toHex();
5017 QString *error, QShaderKey *usedShaderKey)
5019 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
5020 QShaderCode dxbc = shader.shader(key);
5021 if (!dxbc.shader().isEmpty()) {
5023 *usedShaderKey = key;
5024 return dxbc.shader();
5027 key = { QShader::HlslShader, 50, shaderVariant };
5028 QShaderCode hlslSource = shader.shader(key);
5029 if (hlslSource.shader().isEmpty()) {
5030 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
5031 return QByteArray();
5035 *usedShaderKey = key;
5038 switch (shader.stage()) {
5039 case QShader::VertexStage:
5042 case QShader::TessellationControlStage:
5045 case QShader::TessellationEvaluationStage:
5048 case QShader::GeometryStage:
5051 case QShader::FragmentStage:
5054 case QShader::ComputeStage:
5058 qWarning(
"compileHlslShaderSource: Unknown SM 5.0 stage (%d)",
int(shader.stage()));
5059 return QByteArray();
5063 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
5064 cacheKey.sourceHash = sourceHash(hlslSource.shader());
5065 cacheKey.target = target;
5066 cacheKey.entryPoint = hlslSource.entryPoint();
5068 auto cacheIt = m_bytecodeCache.data.constFind(cacheKey);
5069 if (cacheIt != m_bytecodeCache.data.constEnd())
5070 return cacheIt.value();
5073 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
5074 if (d3dCompile ==
nullptr) {
5075 qWarning(
"Unable to resolve function D3DCompile()");
5076 return QByteArray();
5079 ID3DBlob *bytecode =
nullptr;
5080 ID3DBlob *errors =
nullptr;
5081 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
5082 nullptr,
nullptr,
nullptr,
5083 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
5084 if (FAILED(hr) || !bytecode) {
5085 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
5087 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
5088 int(errors->GetBufferSize()));
5091 return QByteArray();
5095 result.resize(
int(bytecode->GetBufferSize()));
5096 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
5097 bytecode->Release();
5099 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
5100 m_bytecodeCache.insertWithCapacityLimit(cacheKey, result);
5111 rhiD->pipelineCreationStart();
5112 if (!rhiD->sanityCheckGraphicsPipeline(
this))
5115 D3D11_RASTERIZER_DESC rastDesc = {};
5116 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
5117 rastDesc.CullMode = toD3DCullMode(m_cullMode);
5118 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
5119 rastDesc.DepthBias = m_depthBias;
5120 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
5121 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
5122 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
5123 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
5124 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
5126 qWarning(
"Failed to create rasterizer state: %s",
5127 qPrintable(QSystemError::windowsComString(hr)));
5131 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
5132 dsDesc.DepthEnable = m_depthTest;
5133 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
5134 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
5135 dsDesc.StencilEnable = m_stencilTest;
5136 if (m_stencilTest) {
5137 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
5138 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
5139 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
5140 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
5141 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
5142 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
5143 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
5144 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
5145 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
5146 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
5148 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
5150 qWarning(
"Failed to create depth-stencil state: %s",
5151 qPrintable(QSystemError::windowsComString(hr)));
5155 D3D11_BLEND_DESC blendDesc = {};
5156 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
5157 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
5158 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
5159 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5160 blend.BlendEnable = b.enable;
5161 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
5162 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
5163 blend.BlendOp = toD3DBlendOp(b.opColor);
5164 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
5165 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
5166 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
5167 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
5168 blendDesc.RenderTarget[i] = blend;
5170 if (m_targetBlends.isEmpty()) {
5171 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5172 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
5173 blendDesc.RenderTarget[0] = blend;
5175 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
5177 qWarning(
"Failed to create blend state: %s",
5178 qPrintable(QSystemError::windowsComString(hr)));
5182 QByteArray vsByteCode;
5183 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
5184 int stagePushConstantRegister = -1;
5185 quint32 stagePushConstantSize = 0;
5186 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
5187 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5188 stagePushConstantRegister = cacheIt->pushConstantRegister;
5189 stagePushConstantSize = cacheIt->pushConstantSize;
5190 switch (shaderStage.type()) {
5191 case QRhiShaderStage::Vertex:
5192 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
5193 vs.shader->AddRef();
5194 vsByteCode = cacheIt->bytecode;
5195 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5197 case QRhiShaderStage::TessellationControl:
5198 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
5199 hs.shader->AddRef();
5200 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5202 case QRhiShaderStage::TessellationEvaluation:
5203 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
5204 ds.shader->AddRef();
5205 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5207 case QRhiShaderStage::Geometry:
5208 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
5209 gs.shader->AddRef();
5210 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5212 case QRhiShaderStage::Fragment:
5213 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
5214 fs.shader->AddRef();
5215 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5222 QShaderKey shaderKey;
5223 UINT compileFlags = 0;
5224 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5225 compileFlags |= D3DCOMPILE_DEBUG;
5227 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
5228 &error, &shaderKey);
5229 if (bytecode.isEmpty()) {
5230 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
5234 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
5236 rhiD->clearShaderCache();
5239 getPushConstantInfo(shaderStage.shader(), shaderKey, &stagePushConstantRegister, &stagePushConstantSize);
5241 switch (shaderStage.type()) {
5242 case QRhiShaderStage::Vertex:
5243 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
5245 qWarning(
"Failed to create vertex shader: %s",
5246 qPrintable(QSystemError::windowsComString(hr)));
5249 vsByteCode = bytecode;
5250 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5251 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap,
5252 stagePushConstantRegister, stagePushConstantSize));
5253 vs.shader->AddRef();
5255 case QRhiShaderStage::TessellationControl:
5256 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
5258 qWarning(
"Failed to create hull shader: %s",
5259 qPrintable(QSystemError::windowsComString(hr)));
5262 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5263 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap,
5264 stagePushConstantRegister, stagePushConstantSize));
5265 hs.shader->AddRef();
5267 case QRhiShaderStage::TessellationEvaluation:
5268 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
5270 qWarning(
"Failed to create domain shader: %s",
5271 qPrintable(QSystemError::windowsComString(hr)));
5274 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5275 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap,
5276 stagePushConstantRegister, stagePushConstantSize));
5277 ds.shader->AddRef();
5279 case QRhiShaderStage::Geometry:
5280 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
5282 qWarning(
"Failed to create geometry shader: %s",
5283 qPrintable(QSystemError::windowsComString(hr)));
5286 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5287 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap,
5288 stagePushConstantRegister, stagePushConstantSize));
5289 gs.shader->AddRef();
5291 case QRhiShaderStage::Fragment:
5292 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
5294 qWarning(
"Failed to create pixel shader: %s",
5295 qPrintable(QSystemError::windowsComString(hr)));
5298 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5299 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap,
5300 stagePushConstantRegister, stagePushConstantSize));
5301 fs.shader->AddRef();
5308 if (stagePushConstantRegister >= 0 && stagePushConstantSize) {
5309 const int stageIndex = rbmStageIndex(shaderStage.type());
5310 if (stageIndex >= 0) {
5311 pushConstants.reg = stagePushConstantRegister;
5312 pushConstants.size = qMax(pushConstants.size, stagePushConstantSize);
5313 pushConstants.stages |= 1u << uint(stageIndex);
5318 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
5320 if (!vsByteCode.isEmpty()) {
5321 QByteArrayList matrixSliceSemantics;
5322 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
5323 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
5326 D3D11_INPUT_ELEMENT_DESC desc = {};
5331 const int matrixSlice = it->matrixSlice();
5332 if (matrixSlice < 0) {
5333 desc.SemanticName =
"TEXCOORD";
5334 desc.SemanticIndex = UINT(it->location());
5338 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
5339 matrixSliceSemantics.append(sem);
5340 desc.SemanticName = matrixSliceSemantics.last().constData();
5341 desc.SemanticIndex = UINT(matrixSlice);
5343 desc.Format = toD3DAttributeFormat(it->format());
5344 desc.InputSlot = UINT(it->binding());
5345 desc.AlignedByteOffset = it->offset();
5346 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
5347 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
5348 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
5349 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
5351 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
5353 inputDescs.append(desc);
5355 if (!inputDescs.isEmpty()) {
5356 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
5357 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
5359 qWarning(
"Failed to create input layout: %s",
5360 qPrintable(QSystemError::windowsComString(hr)));
5366 rhiD->pipelineCreationEnd();
5368 rhiD->registerResource(
this);
5387 cs.shader->Release();
5388 cs.shader =
nullptr;
5389 cs.nativeResourceBindingMap.clear();
5394 rhiD->unregisterResource(
this);
5403 rhiD->pipelineCreationStart();
5405 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5406 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5407 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5408 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5409 pushConstants.reg = cacheIt->pushConstantRegister;
5410 pushConstants.size = cacheIt->pushConstantSize;
5413 QShaderKey shaderKey;
5414 UINT compileFlags = 0;
5415 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5416 compileFlags |= D3DCOMPILE_DEBUG;
5418 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5419 &error, &shaderKey);
5420 if (bytecode.isEmpty()) {
5421 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5425 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5427 qWarning(
"Failed to create compute shader: %s",
5428 qPrintable(QSystemError::windowsComString(hr)));
5432 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5433 getPushConstantInfo(m_shaderStage.shader(), shaderKey, &pushConstants.reg, &pushConstants.size);
5435 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5438 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap,
5439 pushConstants.reg, pushConstants.size));
5442 cs.shader->AddRef();
5444 rhiD->pipelineCreationEnd();
5446 rhiD->registerResource(
this);
5471 D3D11_QUERY_DESC queryDesc = {};
5473 if (!disjointQuery[i]) {
5474 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5475 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5477 qWarning(
"Failed to create timestamp disjoint query: %s",
5478 qPrintable(QSystemError::windowsComString(hr)));
5482 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5483 for (
int j = 0; j < 2; ++j) {
5484 const int idx = 2 * i + j;
5486 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5488 qWarning(
"Failed to create timestamp query: %s",
5489 qPrintable(QSystemError::windowsComString(hr)));
5502 if (disjointQuery[i]) {
5503 disjointQuery[i]->Release();
5504 disjointQuery[i] =
nullptr;
5506 for (
int j = 0; j < 2; ++j) {
5509 query[idx]->Release();
5510 query[idx] =
nullptr;
5518 bool result =
false;
5522 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5523 ID3D11Query *tsStart = query[pairIndex * 2];
5524 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5525 quint64 timestamps[2];
5526 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5529 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5530 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5531 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5534 if (!dj.Disjoint && dj.Frequency) {
5535 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5536 *elapsedSec = elapsedMs / 1000.0;
5539 active[pairIndex] =
false;
5548 backBufferTex =
nullptr;
5549 backBufferRtv =
nullptr;
5551 msaaTex[i] =
nullptr;
5552 msaaRtv[i] =
nullptr;
5563 if (backBufferRtv) {
5564 backBufferRtv->Release();
5565 backBufferRtv =
nullptr;
5567 if (backBufferRtvRight) {
5568 backBufferRtvRight->Release();
5569 backBufferRtvRight =
nullptr;
5571 if (backBufferTex) {
5572 backBufferTex->Release();
5573 backBufferTex =
nullptr;
5577 msaaRtv[i]->Release();
5578 msaaRtv[i] =
nullptr;
5581 msaaTex[i]->Release();
5582 msaaTex[i] =
nullptr;
5594 timestamps.destroy();
5596 swapChain->Release();
5597 swapChain =
nullptr;
5600 dcompVisual->Release();
5601 dcompVisual =
nullptr;
5605 dcompTarget->Release();
5606 dcompTarget =
nullptr;
5609 if (frameLatencyWaitableObject) {
5610 CloseHandle(frameLatencyWaitableObject);
5611 frameLatencyWaitableObject =
nullptr;
5614 QDxgiVSyncService::instance()->unregisterWindow(window);
5618 rhiD->unregisterResource(
this);
5621 rhiD->context->Flush();
5637 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5643 return m_window->size() * m_window->devicePixelRatio();
5652 qWarning(
"Attempted to call isFormatSupported() without a window set");
5657 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5658 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5669 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5678 rhiD->registerResource(rpD,
false);
5683 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5685 D3D11_TEXTURE2D_DESC desc = {};
5686 desc.Width = UINT(size.width());
5687 desc.Height = UINT(size.height());
5690 desc.Format = format;
5691 desc.SampleDesc = sampleDesc;
5692 desc.Usage = D3D11_USAGE_DEFAULT;
5693 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5696 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5698 qWarning(
"Failed to create color buffer texture: %s",
5699 qPrintable(QSystemError::windowsComString(hr)));
5703 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5704 rtvDesc.Format = format;
5705 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5706 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5708 qWarning(
"Failed to create color buffer rtv: %s",
5709 qPrintable(QSystemError::windowsComString(hr)));
5723 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5724 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5725 return dcompDevice ?
true :
false;
5737 const bool needsRegistration = !window || window != m_window;
5738 const bool stereo = m_window->format().stereo();
5741 if (window && window != m_window)
5745 m_currentPixelSize = surfacePixelSize();
5746 pixelSize = m_currentPixelSize;
5748 if (pixelSize.isEmpty())
5751 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5756 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5759 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5761 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5762 qPrintable(QSystemError::windowsComString(hr)));
5765 if (dcompTarget && !dcompVisual) {
5766 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5768 qWarning(
"Failed to create DirectComposition visual: %s",
5769 qPrintable(QSystemError::windowsComString(hr)));
5774 if (
window->requestedFormat().alphaBufferSize() <= 0)
5775 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5776 "This may lead to problems.");
5779 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5786 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5787 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5791 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5792 && swapInterval != 0
5793 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5795 if (useFrameLatencyWaitableObject) {
5797 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5801 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5802 colorFormat = DEFAULT_FORMAT;
5803 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5805 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5806 if (m_format != SDR) {
5807 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5810 case HDRExtendedSrgbLinear:
5811 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5812 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5813 srgbAdjustedColorFormat = colorFormat;
5816 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5817 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5818 srgbAdjustedColorFormat = colorFormat;
5827 qWarning(
"The output associated with the window is not HDR capable "
5828 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5838 DXGI_SWAP_CHAIN_DESC1 desc = {};
5839 desc.Width = UINT(pixelSize.width());
5840 desc.Height = UINT(pixelSize.height());
5841 desc.Format = colorFormat;
5842 desc.SampleDesc.Count = 1;
5843 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5845 desc.Flags = swapChainFlags;
5846 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5847 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5848 desc.Stereo = stereo;
5854 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5859 desc.Scaling = DXGI_SCALING_STRETCH;
5862 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5863 IDXGISwapChain1 *sc1;
5866 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5868 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5873 if (FAILED(hr) && m_format != SDR) {
5874 colorFormat = DEFAULT_FORMAT;
5875 desc.Format = DEFAULT_FORMAT;
5877 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5879 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5882 if (SUCCEEDED(hr)) {
5884 IDXGISwapChain3 *sc3 =
nullptr;
5885 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5886 if (m_format != SDR) {
5887 hr = sc3->SetColorSpace1(hdrColorSpace);
5889 qWarning(
"Failed to set color space on swapchain: %s",
5890 qPrintable(QSystemError::windowsComString(hr)));
5892 if (useFrameLatencyWaitableObject) {
5893 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5894 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5898 if (m_format != SDR)
5899 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5900 if (useFrameLatencyWaitableObject) {
5901 IDXGISwapChain2 *sc2 =
nullptr;
5902 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5903 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5904 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5907 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5912 hr = dcompVisual->SetContent(sc1);
5913 if (SUCCEEDED(hr)) {
5914 hr = dcompTarget->SetRoot(dcompVisual);
5916 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5917 qPrintable(QSystemError::windowsComString(hr)));
5920 qWarning(
"Failed to set content for Direct Composition visual: %s",
5921 qPrintable(QSystemError::windowsComString(hr)));
5925 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5928 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5929 qWarning(
"Device loss detected during swapchain creation");
5932 }
else if (FAILED(hr)) {
5933 qWarning(
"Failed to create D3D11 swapchain: %s"
5934 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5935 qPrintable(QSystemError::windowsComString(hr)),
5936 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5937 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5943 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5944 colorFormat, swapChainFlags);
5945 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5946 qWarning(
"Device loss detected in ResizeBuffers()");
5949 }
else if (FAILED(hr)) {
5950 qWarning(
"Failed to resize D3D11 swapchain: %s",
5951 qPrintable(QSystemError::windowsComString(hr)));
5970 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5972 qWarning(
"Failed to query swapchain backbuffer: %s",
5973 qPrintable(QSystemError::windowsComString(hr)));
5976 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5977 rtvDesc.Format = srgbAdjustedColorFormat;
5978 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5979 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5981 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5982 qPrintable(QSystemError::windowsComString(hr)));
5988 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5989 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5990 rtvDesc.Texture2DArray.ArraySize = 1;
5991 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5993 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5994 qPrintable(QSystemError::windowsComString(hr)));
6001 if (sampleDesc.Count > 1) {
6002 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
6007 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
6008 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
6009 m_depthStencil->sampleCount(), m_sampleCount);
6011 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
6012 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
6013 m_depthStencil->setPixelSize(pixelSize);
6014 if (!m_depthStencil->create())
6015 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
6016 pixelSize.width(), pixelSize.height());
6018 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
6019 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
6020 pixelSize.width(), pixelSize.height());
6027 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
6029 rt.setRenderPassDescriptor(m_renderPassDesc);
6031 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
6032 rtD->d.pixelSize = pixelSize;
6033 rtD->d.dpr =
float(
window->devicePixelRatio());
6034 rtD->d.sampleCount =
int(sampleDesc.Count);
6035 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
6038 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
6039 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
6040 rtD->d.pixelSize = pixelSize;
6041 rtD->d.dpr =
float(
window->devicePixelRatio());
6042 rtD->d.sampleCount =
int(sampleDesc.Count);
6043 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
6046 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
6047 timestamps.prepare(rhiD);
6051 QDxgiVSyncService::instance()->registerWindow(window);
6053 if (needsRegistration)
6054 rhiD->registerResource(
this);
6062 if (rtViews.dsv != currentRtViews.dsv) {
6063 rtViews.dsv = currentRtViews.dsv;
6067 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
6068 rtViews.rtv[i] = currentRtViews.rtv[i];
6070 rtViews.colorAttCount = currentRtViews.colorAttCount;
6072 ret |= rtViews.rtv[i] !=
nullptr;
6073 rtViews.rtv[i] =
nullptr;
6075 for (
int i = 0; i < count; i++) {
6076 ret |= uav[i] != uavs[i];
6080 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
const char * constData() const
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[], uint pushConstantStages)
int gsHighestActiveSrvBinding
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int dsHighestActiveSrvBinding
bool isYUpInNDC() const override
void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
QRhiSwapChain * createSwapChain() override
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
bool isFeatureSupported(QRhi::Feature feature) const override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
bool isDeviceLost() const override
bool vsHasIndexBufferBound
void executeBufferHostWrites(QD3D11Buffer *bufD)
QRhiStats statistics() override
QList< QSize > supportedShadingRates(int sampleCount) const override
QRhiComputePipeline * createComputePipeline() override
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override
QRhi::FrameOpResult finish() override
void setVertexInput(QRhiCommandBuffer *cb, int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat) override
void dispatchIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset) override
QRhiGraphicsPipeline * createGraphicsPipeline() override
void drawIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) override
QRhiShaderResourceBindings * createShaderResourceBindings() override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QList< int > supportedSampleCounts() const override
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags, QString *error, QShaderKey *usedShaderKey)
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
void resetShaderResources(QD3D11CommandBuffer *cbD, QD3D11RenderTargetUavUpdateState *rtUavState)
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
void setPushConstants(QRhiCommandBuffer *cb, quint32 offset, quint32 size, const void *data) override
bool isYUpInFramebuffer() const override
int resourceLimit(QRhi::ResourceLimit limit) const override
void beginExternal(QRhiCommandBuffer *cb) override
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void setPipelineCacheData(const QByteArray &data) override
void executeCommandBuffer(QD3D11CommandBuffer *cbD)
void debugMarkEnd(QRhiCommandBuffer *cb) override
void releaseCachedResources() override
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
bool importedDeviceAndContext
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
bool supportsAllowTearing
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
void endExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
bool ensurePushConstantBuffer()
void drawIndexedIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) override
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
QRhiShadingRateMap * createShadingRateMap() override
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
bool useLegacySwapchainModel
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
bool makeThreadLocalNativeContextCurrent() override
bool create(QRhi::Flags flags) override
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void bindShaderResources(QD3D11CommandBuffer *cbD, const QD3D11ShaderResourceBindings::ResourceBatches &allResourceBatches, const uint *dynOfsPairs, int dynOfsPairCount, bool offsetOnlyChange, QD3D11RenderTargetUavUpdateState *rtUavState)
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
static void applyDynamicOffsets(UINT *offsets, int batchIndex, const QRhiBatchedBindings< UINT > *originalBindings, const QRhiBatchedBindings< UINT > *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount)
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
#define SETUAVBATCH(stagePrefixL, stagePrefixU)
static QByteArray sourceHash(const QByteArray &source)
#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
static const int RBM_HULL
static uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
static const int RBM_FRAGMENT
#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
Int aligned(Int v, Int byteAlign)
\variable QRhiVulkanQueueSubmitParams::waitSemaphoreCount
static DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
static D3D11_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f, bool rgb)
static const int RBM_VERTEX
static D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
#define D3D11_1_UAV_SLOT_COUNT
static const int RBM_DOMAIN
static D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
static std::pair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[], uint pushConstantStages)
static QD3D11RenderTargetData * rtData(QRhiRenderTarget *rt)
static UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
static D3D11_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
void releasePipelineShader(T &s)
static D3D11_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
static int rbmStageIndex(QRhiShaderStage::Type type)
static DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
static void getPushConstantInfo(const QShader &shader, const QShaderKey &key, int *reg, quint32 *size)
static const int RBM_GEOMETRY
static D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
static IDXGIFactory1 * createDXGIFactory2()
static D3D11_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
static bool isDepthTextureFormat(QRhiTexture::Format format)
static const int RBM_COMPUTE
static D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
#define SETSHADER(StageL, StageU)
static DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
static const DXGI_FORMAT DEFAULT_FORMAT
static uint clampedResourceCount(uint startSlot, int countSlots, uint maxSlots, const char *resType)
#define D3D11_VS_INPUT_REGISTER_COUNT
#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)
static const int RBM_SUPPORTED_STAGES
bool hasPendingDynamicUpdates
void endFullDynamicBufferUpdateForCurrentFrame() override
To be called when the entire contents of the buffer data has been updated in the memory block returne...
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
char * beginFullDynamicBufferUpdateForCurrentFrame() override
bool create() override
Creates the corresponding native graphics resources.
ID3D11UnorderedAccessView * createClearUnorderedAccessView(quint32 offset, quint32 size)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiBuffer::NativeBuffer nativeBuffer() override
ID3D11UnorderedAccessView * unorderedAccessView(quint32 offset)
static const int MAX_DYNAMIC_OFFSET_COUNT
static const int MAX_VERTEX_BUFFER_BINDING_COUNT
int retainResourceBatches(const QD3D11ShaderResourceBindings::ResourceBatches &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
uint currentPipelineGeneration
uint currentSrbGeneration
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ComputePipeline(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11GraphicsPipeline(QRhiImplementation *rhi)
~QD3D11GraphicsPipeline()
bool create() override
Creates the corresponding native graphics resources.
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags, QRhiTexture::Format backingFormatHint)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool create() override
Creates the corresponding native graphics resources.
QRhiTexture::Format backingFormat() const override
QD3D11RenderPassDescriptor(QRhiImplementation *rhi)
~QD3D11RenderPassDescriptor()
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool isCompatible(const QRhiRenderPassDescriptor *other) const override
QVector< quint32 > serializedFormat() const override
static const int MAX_COLOR_ATTACHMENTS
bool update(const QD3D11RenderTargetData::Views ¤tRtViews, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
QD3D11GraphicsPipeline * lastUsedGraphicsPipeline
bool create() override
Creates the corresponding resource binding set.
~QD3D11ShaderResourceBindings()
void updateResources(UpdateFlags flags) override
QD3D11ComputePipeline * lastUsedComputePipeline
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
int sampleCount() const override
~QD3D11SwapChainRenderTarget()
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
float devicePixelRatio() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QSize pixelSize() const override
bool prepare(QRhiD3D11 *rhiD)
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
bool active[TIMESTAMP_PAIRS]
static const int TIMESTAMP_PAIRS
QRhiSwapChainHdrInfo hdrInfo() override
\variable QRhiSwapChainHdrInfo::limitsType
int lastFrameLatencyWaitSlot
QRhiRenderTarget * currentFrameRenderTarget() override
QD3D11SwapChain(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
QSize surfacePixelSize() override
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
static const int BUFFER_COUNT
bool isFormatSupported(Format f) override
QRhiCommandBuffer * currentFrameCommandBuffer() override
int currentTimestampPairIndex
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
QSize pixelSize() const override
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
float devicePixelRatio() const override
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
~QD3D11TextureRenderTarget()
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
ID3D11UnorderedAccessView * unorderedAccessViewForLevel(int level)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h