10#include <QtCore/qcryptographichash.h>
11#include <QtCore/private/qsystemerror_p.h>
18using namespace Qt::StringLiterals;
21
22
23
24
25
26
27
28
32
33
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
78
79
80
81
82
86
87
88
89
90
91
92
93
94
95
96
97
100
101
102
103
104
105
106
107
110
111
112
113
114
115
116
119
120
121
122
123
124
125
126
129
130
131
132
133
134
137
138
139
140
141
142
145#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
146#define DXGI_ADAPTER_FLAG_SOFTWARE 2
149#ifndef D3D11_1_UAV_SLOT_COUNT
150#define D3D11_1_UAV_SLOT_COUNT 64
153#ifndef D3D11_VS_INPUT_REGISTER_COUNT
154#define D3D11_VS_INPUT_REGISTER_COUNT 32
163 if (importParams->dev && importParams->context) {
164 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
165 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
166 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
171 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
174 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
175 adapterLuid.LowPart = importParams->adapterLuidLow;
176 adapterLuid.HighPart = importParams->adapterLuidHigh;
183 return (v + byteAlign - 1) & ~(byteAlign - 1);
188 IDXGIFactory1 *result =
nullptr;
189 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
191 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
192 qPrintable(QSystemError::windowsComString(hr)));
204 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
206 dxgiFactory = createDXGIFactory2();
214 IDXGIFactory5 *factory5 =
nullptr;
215 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
216 BOOL allowTearing =
false;
217 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
222 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
223 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
231 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
232 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
237 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
241 if (maxFrameLatency == 0)
242 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
244 activeAdapter =
nullptr;
247 IDXGIAdapter1 *adapter;
248 int requestedAdapterIndex = -1;
249 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
250 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
252 if (requestedRhiAdapter)
253 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
256 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
257 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
258 DXGI_ADAPTER_DESC1 desc;
259 adapter->GetDesc1(&desc);
261 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
262 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
264 requestedAdapterIndex = adapterIndex;
270 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
271 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
272 DXGI_ADAPTER_DESC1 desc;
273 adapter->GetDesc1(&desc);
276 requestedAdapterIndex = adapterIndex;
282 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
283 DXGI_ADAPTER_DESC1 desc;
284 adapter->GetDesc1(&desc);
285 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
286 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
292 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
293 activeAdapter = adapter;
294 adapterLuid = desc.AdapterLuid;
296 qCDebug(QRHI_LOG_INFO,
" using this adapter");
301 if (!activeAdapter) {
302 qWarning(
"No adapter");
308 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
309 bool requestFeatureLevels =
false;
311 requestFeatureLevels =
true;
312 requestedFeatureLevels.append(featureLevel);
315 ID3D11DeviceContext *ctx =
nullptr;
316 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
317 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
318 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
320 &dev, &featureLevel, &ctx);
322 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
323 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
324 "Attempting to create D3D11 device without it.");
325 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
326 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
327 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
328 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
330 &dev, &featureLevel, &ctx);
333 qWarning(
"Failed to create D3D11 device and context: %s",
334 qPrintable(QSystemError::windowsComString(hr)));
338 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
341 qWarning(
"ID3D11DeviceContext1 not supported");
347 ID3D11VertexShader *testShader =
nullptr;
348 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
349 testShader->Release();
351 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
352 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
353 qCDebug(QRHI_LOG_INFO,
"%s", msg);
359 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
360 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
364 if (!features.ConstantBufferOffsetting) {
365 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
366 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
367 qCDebug(QRHI_LOG_INFO,
"%s", msg);
373 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
374 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
375 qCDebug(QRHI_LOG_INFO,
"%s", msg);
381 Q_ASSERT(dev && context);
382 featureLevel = dev->GetFeatureLevel();
383 IDXGIDevice *dxgiDev =
nullptr;
384 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
385 IDXGIAdapter *adapter =
nullptr;
386 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
387 IDXGIAdapter1 *adapter1 =
nullptr;
388 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
389 DXGI_ADAPTER_DESC1 desc;
390 adapter1->GetDesc1(&desc);
391 adapterLuid = desc.AdapterLuid;
393 activeAdapter = adapter1;
399 if (!activeAdapter) {
400 qWarning(
"Failed to query adapter from imported device");
403 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
406 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
408 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
409 annotations =
nullptr;
413 nativeHandlesStruct.dev = dev;
414 nativeHandlesStruct.context = context;
415 nativeHandlesStruct.featureLevel = featureLevel;
416 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
417 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
424 for (Shader &s : m_shaderCache)
427 m_shaderCache.clear();
436 if (ofr.tsDisjointQuery) {
437 ofr.tsDisjointQuery->Release();
438 ofr.tsDisjointQuery =
nullptr;
440 for (
int i = 0; i < 2; ++i) {
441 if (ofr.tsQueries[i]) {
442 ofr.tsQueries[i]->Release();
443 ofr.tsQueries[i] =
nullptr;
448 annotations->Release();
449 annotations =
nullptr;
464 dcompDevice->Release();
465 dcompDevice =
nullptr;
469 activeAdapter->Release();
470 activeAdapter =
nullptr;
474 dxgiFactory->Release();
475 dxgiFactory =
nullptr;
481 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
488 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
489 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
494QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
496 LUID requestedLuid = {};
498 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
499 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
500 if (adapterLuid.LowPart || adapterLuid.HighPart)
501 requestedLuid = adapterLuid;
504 IDXGIFactory1 *dxgi = createDXGIFactory2();
508 QRhi::AdapterList list;
509 IDXGIAdapter1 *adapter;
510 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
511 DXGI_ADAPTER_DESC1 desc;
512 adapter->GetDesc1(&desc);
514 if (requestedLuid.LowPart || requestedLuid.HighPart) {
515 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
516 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
521 QD3D11Adapter *a =
new QD3D11Adapter;
522 a->luid = desc.AdapterLuid;
523 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
538 return { 1, 2, 4, 8 };
543 Q_UNUSED(sampleCount);
544 return { QSize(1, 1) };
549 DXGI_SAMPLE_DESC desc;
553 const int s = effectiveSampleCount(sampleCount);
555 desc.Count = UINT(s);
557 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
566 return new QD3D11SwapChain(
this);
569QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
571 return new QD3D11Buffer(
this, type, usage, size);
599 if (m.isIdentity()) {
601 m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
602 0.0f, 1.0f, 0.0f, 0.0f,
603 0.0f, 0.0f, 0.5f, 0.5f,
604 0.0f, 0.0f, 0.0f, 1.0f);
613 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
622 case QRhi::MultisampleTexture:
624 case QRhi::MultisampleRenderBuffer:
626 case QRhi::DebugMarkers:
627 return annotations !=
nullptr;
628 case QRhi::Timestamps:
630 case QRhi::Instancing:
632 case QRhi::CustomInstanceStepRate:
634 case QRhi::PrimitiveRestart:
636 case QRhi::NonDynamicUniformBuffers:
638 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
640 case QRhi::NPOTTextureRepeat:
642 case QRhi::RedOrAlpha8IsRed:
644 case QRhi::ElementIndexUint:
648 case QRhi::WideLines:
650 case QRhi::VertexShaderPointSize:
652 case QRhi::BaseVertex:
654 case QRhi::BaseInstance:
656 case QRhi::TriangleFanTopology:
658 case QRhi::ReadBackNonUniformBuffer:
660 case QRhi::ReadBackNonBaseMipLevel:
662 case QRhi::TexelFetch:
664 case QRhi::RenderToNonBaseMipLevel:
666 case QRhi::IntAttributes:
668 case QRhi::ScreenSpaceDerivatives:
670 case QRhi::ReadBackAnyTextureFormat:
672 case QRhi::PipelineCacheDataLoadSave:
674 case QRhi::ImageDataStride:
676 case QRhi::RenderBufferImport:
678 case QRhi::ThreeDimensionalTextures:
680 case QRhi::RenderTo3DTextureSlice:
682 case QRhi::TextureArrays:
684 case QRhi::Tessellation:
686 case QRhi::GeometryShader:
688 case QRhi::TextureArrayRange:
690 case QRhi::NonFillPolygonMode:
692 case QRhi::OneDimensionalTextures:
694 case QRhi::OneDimensionalTextureMipmaps:
696 case QRhi::HalfAttributes:
698 case QRhi::RenderToOneDimensionalTexture:
700 case QRhi::ThreeDimensionalTextureMipmaps:
702 case QRhi::MultiView:
704 case QRhi::TextureViewFormat:
706 case QRhi::ResolveDepthStencil:
708 case QRhi::VariableRateShading:
710 case QRhi::VariableRateShadingMap:
711 case QRhi::VariableRateShadingMapWithTexture:
713 case QRhi::PerRenderTargetBlending:
714 case QRhi::SampleVariables:
716 case QRhi::InstanceIndexIncludesBaseInstance:
718 case QRhi::DepthClamp:
729 case QRhi::TextureSizeMin:
731 case QRhi::TextureSizeMax:
732 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
733 case QRhi::MaxColorAttachments:
735 case QRhi::FramesInFlight:
741 case QRhi::MaxAsyncReadbackFrames:
743 case QRhi::MaxThreadGroupsPerDimension:
744 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
745 case QRhi::MaxThreadsPerThreadGroup:
746 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
747 case QRhi::MaxThreadGroupX:
748 return D3D11_CS_THREAD_GROUP_MAX_X;
749 case QRhi::MaxThreadGroupY:
750 return D3D11_CS_THREAD_GROUP_MAX_Y;
751 case QRhi::MaxThreadGroupZ:
752 return D3D11_CS_THREAD_GROUP_MAX_Z;
753 case QRhi::TextureArraySizeMax:
754 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
755 case QRhi::MaxUniformBufferRange:
757 case QRhi::MaxVertexInputs:
759 case QRhi::MaxVertexOutputs:
760 return D3D11_VS_OUTPUT_REGISTER_COUNT;
761 case QRhi::ShadingRateImageTileSize:
771 return &nativeHandlesStruct;
776 return driverInfoStruct;
782 result.totalPipelineCreationTime = totalPipelineCreationTime();
792void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
800 m_bytecodeCache.clear();
820 if (m_bytecodeCache.isEmpty())
824 memset(&header, 0,
sizeof(header));
825 header.rhiId = pipelineCacheRhiId();
826 header.arch = quint32(
sizeof(
void*));
827 header.count = m_bytecodeCache.count();
829 const size_t dataOffset =
sizeof(header);
831 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
833 QByteArray bytecode = it.value();
835 sizeof(quint32) + key.sourceHash.size()
836 +
sizeof(quint32) + key.target.size()
837 +
sizeof(quint32) + key.entryPoint.size()
839 +
sizeof(quint32) + bytecode.size();
842 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
843 char *p = buf.data() + dataOffset;
844 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
846 QByteArray bytecode = it.value();
848 quint32 i = key.sourceHash.size();
851 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
852 p += key.sourceHash.size();
854 i = key.target.size();
857 memcpy(p, key.target.constData(), key.target.size());
858 p += key.target.size();
860 i = key.entryPoint.size();
863 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
864 p += key.entryPoint.size();
866 quint32 f = key.compileFlags;
873 memcpy(p, bytecode.constData(), bytecode.size());
874 p += bytecode.size();
876 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
878 header.dataSize = quint32(dataSize);
879 memcpy(buf.data(), &header,
sizeof(header));
890 if (data.size() < qsizetype(headerSize)) {
891 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
894 const size_t dataOffset = headerSize;
896 memcpy(&header, data.constData(), headerSize);
898 const quint32 rhiId = pipelineCacheRhiId();
899 if (header.rhiId != rhiId) {
900 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
901 rhiId, header.rhiId);
904 const quint32 arch = quint32(
sizeof(
void*));
905 if (header.arch != arch) {
906 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
910 if (header.count == 0)
913 if (data.size() < qsizetype(dataOffset + header.dataSize)) {
914 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
918 m_bytecodeCache.clear();
920 const char *p = data.constData() + dataOffset;
921 for (quint32 i = 0; i < header.count; ++i) {
925 QByteArray sourceHash(len, Qt::Uninitialized);
926 memcpy(sourceHash.data(), p, len);
931 QByteArray target(len, Qt::Uninitialized);
932 memcpy(target.data(), p, len);
937 QByteArray entryPoint(len, Qt::Uninitialized);
938 memcpy(entryPoint.data(), p, len);
942 memcpy(&flags, p, 4);
947 QByteArray bytecode(len, Qt::Uninitialized);
948 memcpy(bytecode.data(), p, len);
952 cacheKey.sourceHash = sourceHash;
953 cacheKey.target = target;
954 cacheKey.entryPoint = entryPoint;
955 cacheKey.compileFlags = flags;
957 m_bytecodeCache.insert(cacheKey, bytecode);
960 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
963QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
964 int sampleCount, QRhiRenderBuffer::Flags flags,
965 QRhiTexture::Format backingFormatHint)
967 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
971 const QSize &pixelSize,
int depth,
int arraySize,
972 int sampleCount, QRhiTexture::Flags flags)
974 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
978 QRhiSampler::Filter mipmapMode,
979 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
981 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
985 QRhiTextureRenderTarget::Flags flags)
997 return new QD3D11GraphicsPipeline(
this);
1002 return new QD3D11ComputePipeline(
this);
1007 return new QD3D11ShaderResourceBindings(
this);
1015 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1017 if (pipelineChanged) {
1018 cbD->currentGraphicsPipeline = ps;
1019 cbD->currentComputePipeline =
nullptr;
1020 cbD->currentPipelineGeneration = psD->generation;
1024 cmd.args.bindGraphicsPipeline.ps = psD;
1037 int dynamicOffsetCount,
1038 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1047 srb = gfxPsD->m_shaderResourceBindings;
1049 srb = compPsD->m_shaderResourceBindings;
1054 bool pipelineChanged =
false;
1063 bool srbUpdate =
false;
1064 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1065 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1068 case QRhiShaderResourceBinding::UniformBuffer:
1072 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1076 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1078 bd.ubuf.id = bufD->m_id;
1079 bd.ubuf.generation = bufD->generation;
1083 case QRhiShaderResourceBinding::SampledTexture:
1084 case QRhiShaderResourceBinding::Texture:
1085 case QRhiShaderResourceBinding::Sampler:
1087 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1088 if (bd.stex.count != data->count) {
1089 bd.stex.count = data->count;
1092 for (
int elem = 0; elem < data->count; ++elem) {
1098 Q_ASSERT(texD || samplerD);
1099 const quint64 texId = texD ? texD->m_id : 0;
1100 const uint texGen = texD ? texD->generation : 0;
1101 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1102 const uint samplerGen = samplerD ? samplerD->generation : 0;
1103 if (texGen != bd.stex.d[elem].texGeneration
1104 || texId != bd.stex.d[elem].texId
1105 || samplerGen != bd.stex.d[elem].samplerGeneration
1106 || samplerId != bd.stex.d[elem].samplerId)
1109 bd.stex.d[elem].texId = texId;
1110 bd.stex.d[elem].texGeneration = texGen;
1111 bd.stex.d[elem].samplerId = samplerId;
1112 bd.stex.d[elem].samplerGeneration = samplerGen;
1117 case QRhiShaderResourceBinding::ImageLoad:
1118 case QRhiShaderResourceBinding::ImageStore:
1119 case QRhiShaderResourceBinding::ImageLoadStore:
1122 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1124 bd.simage.id = texD->m_id;
1125 bd.simage.generation = texD->generation;
1129 case QRhiShaderResourceBinding::BufferLoad:
1130 case QRhiShaderResourceBinding::BufferStore:
1131 case QRhiShaderResourceBinding::BufferLoadStore:
1134 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1136 bd.sbuf.id = bufD->m_id;
1137 bd.sbuf.generation = bufD->generation;
1147 if (srbUpdate || pipelineChanged) {
1149 memset(resBindMaps, 0,
sizeof(resBindMaps));
1151 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1152 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1153 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1154 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1155 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1157 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1159 updateShaderResourceBindings(srbD, resBindMaps);
1162 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1163 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1165 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1167 cbD->currentGraphicsSrb = srb;
1168 cbD->currentComputeSrb =
nullptr;
1170 cbD->currentGraphicsSrb =
nullptr;
1171 cbD->currentComputeSrb = srb;
1173 cbD->currentSrbGeneration = srbD->generation;
1180 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1181 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1184 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1185 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1186 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1187 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1188 const uint binding = uint(dynOfs.first);
1189 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1190 const quint32 offsetInConstants = dynOfs.second / 16;
1192 *p++ = offsetInConstants;
1195 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1203 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1204 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1209 bool needsBindVBuf =
false;
1210 for (
int i = 0; i < bindingCount; ++i) {
1211 const int inputSlot = startBinding + i;
1213 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1214 if (bufD->m_type == QRhiBuffer::Dynamic)
1217 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1218 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1220 needsBindVBuf =
true;
1221 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1222 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1226 if (needsBindVBuf) {
1229 cmd.args.bindVertexBuffers.startSlot = startBinding;
1231 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1235 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1237 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1238 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1239 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1241 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1242 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1243 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1249 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1250 if (ibufD->m_type == QRhiBuffer::Dynamic)
1253 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1254 : DXGI_FORMAT_R32_UINT;
1255 if (cbD->currentIndexBuffer != ibufD->buffer
1256 || cbD->currentIndexOffset != indexOffset
1257 || cbD->currentIndexFormat != dxgiFormat)
1259 cbD->currentIndexBuffer = ibufD->buffer;
1260 cbD->currentIndexOffset = indexOffset;
1261 cbD->currentIndexFormat = dxgiFormat;
1265 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1266 cmd.args.bindIndexBuffer.offset = indexOffset;
1267 cmd.args.bindIndexBuffer.format = dxgiFormat;
1276 Q_ASSERT(cbD->currentTarget);
1277 const QSize outputSize = cbD->currentTarget->pixelSize();
1281 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1286 cmd.args.viewport.x = x;
1287 cmd.args.viewport.y = y;
1288 cmd.args.viewport.w = w;
1289 cmd.args.viewport.h = h;
1290 cmd.args.viewport.d0 = viewport.minDepth();
1291 cmd.args.viewport.d1 = viewport.maxDepth();
1298 Q_ASSERT(cbD->currentTarget);
1299 const QSize outputSize = cbD->currentTarget->pixelSize();
1303 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1308 cmd.args.scissor.x = x;
1309 cmd.args.scissor.y = y;
1310 cmd.args.scissor.w = w;
1311 cmd.args.scissor.h = h;
1322 cmd.args.blendConstants.c[0] =
float(c.redF());
1323 cmd.args.blendConstants.c[1] =
float(c.greenF());
1324 cmd.args.blendConstants.c[2] =
float(c.blueF());
1325 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1336 cmd.args.stencilRef.ref = refValue;
1342 Q_UNUSED(coarsePixelSize);
1346 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1354 cmd.args.draw.vertexCount = vertexCount;
1355 cmd.args.draw.instanceCount = instanceCount;
1356 cmd.args.draw.firstVertex = firstVertex;
1357 cmd.args.draw.firstInstance = firstInstance;
1361 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1369 cmd.args.drawIndexed.indexCount = indexCount;
1370 cmd.args.drawIndexed.instanceCount = instanceCount;
1371 cmd.args.drawIndexed.firstIndex = firstIndex;
1372 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1373 cmd.args.drawIndexed.firstInstance = firstInstance;
1378 if (!debugMarkers || !annotations)
1384 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1389 if (!debugMarkers || !annotations)
1399 if (!debugMarkers || !annotations)
1405 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1424 Q_ASSERT(cbD->commands.isEmpty());
1426 if (cbD->currentTarget) {
1429 fbCmd.args.setRenderTarget.rt = cbD->currentTarget;
1441 switch (rt->resourceType()) {
1442 case QRhiResource::SwapChainRenderTarget:
1443 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1444 case QRhiResource::TextureRenderTarget:
1445 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1461 if (swapChainD->frameLatencyWaitableObject) {
1464 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1469 swapChainD->cb.resetState();
1471 swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
1472 swapChainD->msaaRtv[currentFrameSlot] : swapChainD->backBufferRtv;
1473 swapChainD->rt.d.dsv = swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr;
1478 double elapsedSec = 0;
1480 swapChainD->cb.lastGpuTime = elapsedSec;
1489 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1490 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1491 cmd.args.beginFrame.swapchainData =
rtData(&swapChainD->rt
);
1493 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1495 return QRhi::FrameOpSuccess;
1506 cmd.args.endFrame.tsQuery =
nullptr;
1507 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1512 if (swapChainD->sampleDesc.Count > 1) {
1513 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1514 swapChainD->msaaTex[currentFrameSlot], 0,
1515 swapChainD->colorFormat);
1522 if (recordTimestamps) {
1523 context->End(tsEnd);
1524 context->End(tsDisjoint);
1529 if (!flags.testFlag(QRhi::SkipPresent)) {
1530 UINT presentFlags = 0;
1531 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1532 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1533 if (!swapChainD->swapChain) {
1534 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1535 return QRhi::FrameOpError;
1537 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1538 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1539 qWarning(
"Device loss detected in Present()");
1541 return QRhi::FrameOpDeviceLost;
1542 }
else if (FAILED(hr)) {
1543 qWarning(
"Failed to present: %s",
1544 qPrintable(QSystemError::windowsComString(hr)));
1545 return QRhi::FrameOpError;
1548 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1549 dcompDevice->Commit();
1560 return QRhi::FrameOpSuccess;
1568 ofr.cbWrapper.resetState();
1569 *cb = &ofr.cbWrapper;
1571 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1572 D3D11_QUERY_DESC queryDesc = {};
1573 if (!ofr.tsDisjointQuery) {
1574 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1575 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1577 qWarning(
"Failed to create timestamp disjoint query: %s",
1578 qPrintable(QSystemError::windowsComString(hr)));
1579 return QRhi::FrameOpError;
1582 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1583 for (
int i = 0; i < 2; ++i) {
1584 if (!ofr.tsQueries[i]) {
1585 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1587 qWarning(
"Failed to create timestamp query: %s",
1588 qPrintable(QSystemError::windowsComString(hr)));
1589 return QRhi::FrameOpError;
1597 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1598 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1599 cmd.args.beginFrame.swapchainData =
nullptr;
1601 return QRhi::FrameOpSuccess;
1611 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1612 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1619 if (ofr.tsQueries[0]) {
1620 quint64 timestamps[2];
1621 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1625 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1626 }
while (hr == S_FALSE);
1629 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1630 }
while (hr == S_FALSE);
1633 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1634 }
while (hr == S_FALSE);
1637 if (!dj.Disjoint && dj.Frequency) {
1638 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1639 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1644 return QRhi::FrameOpSuccess;
1649 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1651 case QRhiTexture::RGBA8:
1652 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1653 case QRhiTexture::BGRA8:
1654 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1655 case QRhiTexture::R8:
1656 return DXGI_FORMAT_R8_UNORM;
1657 case QRhiTexture::R8SI:
1658 return DXGI_FORMAT_R8_SINT;
1659 case QRhiTexture::R8UI:
1660 return DXGI_FORMAT_R8_UINT;
1661 case QRhiTexture::RG8:
1662 return DXGI_FORMAT_R8G8_UNORM;
1663 case QRhiTexture::R16:
1664 return DXGI_FORMAT_R16_UNORM;
1665 case QRhiTexture::RG16:
1666 return DXGI_FORMAT_R16G16_UNORM;
1667 case QRhiTexture::RED_OR_ALPHA8:
1668 return DXGI_FORMAT_R8_UNORM;
1670 case QRhiTexture::RGBA16F:
1671 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1672 case QRhiTexture::RGBA32F:
1673 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1674 case QRhiTexture::R16F:
1675 return DXGI_FORMAT_R16_FLOAT;
1676 case QRhiTexture::R32F:
1677 return DXGI_FORMAT_R32_FLOAT;
1679 case QRhiTexture::RGB10A2:
1680 return DXGI_FORMAT_R10G10B10A2_UNORM;
1682 case QRhiTexture::R32SI:
1683 return DXGI_FORMAT_R32_SINT;
1684 case QRhiTexture::R32UI:
1685 return DXGI_FORMAT_R32_UINT;
1686 case QRhiTexture::RG32SI:
1687 return DXGI_FORMAT_R32G32_SINT;
1688 case QRhiTexture::RG32UI:
1689 return DXGI_FORMAT_R32G32_UINT;
1690 case QRhiTexture::RGBA32SI:
1691 return DXGI_FORMAT_R32G32B32A32_SINT;
1692 case QRhiTexture::RGBA32UI:
1693 return DXGI_FORMAT_R32G32B32A32_UINT;
1695 case QRhiTexture::D16:
1696 return DXGI_FORMAT_R16_TYPELESS;
1697 case QRhiTexture::D24:
1698 return DXGI_FORMAT_R24G8_TYPELESS;
1699 case QRhiTexture::D24S8:
1700 return DXGI_FORMAT_R24G8_TYPELESS;
1701 case QRhiTexture::D32F:
1702 return DXGI_FORMAT_R32_TYPELESS;
1703 case QRhiTexture::D32FS8:
1704 return DXGI_FORMAT_R32G8X24_TYPELESS;
1706 case QRhiTexture::BC1:
1707 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1708 case QRhiTexture::BC2:
1709 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1710 case QRhiTexture::BC3:
1711 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1712 case QRhiTexture::BC4:
1713 return DXGI_FORMAT_BC4_UNORM;
1714 case QRhiTexture::BC5:
1715 return DXGI_FORMAT_BC5_UNORM;
1716 case QRhiTexture::BC6H:
1717 return DXGI_FORMAT_BC6H_UF16;
1718 case QRhiTexture::BC7:
1719 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1721 case QRhiTexture::ETC2_RGB8:
1722 case QRhiTexture::ETC2_RGB8A1:
1723 case QRhiTexture::ETC2_RGBA8:
1724 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1725 return DXGI_FORMAT_R8G8B8A8_UNORM;
1727 case QRhiTexture::ASTC_4x4:
1728 case QRhiTexture::ASTC_5x4:
1729 case QRhiTexture::ASTC_5x5:
1730 case QRhiTexture::ASTC_6x5:
1731 case QRhiTexture::ASTC_6x6:
1732 case QRhiTexture::ASTC_8x5:
1733 case QRhiTexture::ASTC_8x6:
1734 case QRhiTexture::ASTC_8x8:
1735 case QRhiTexture::ASTC_10x5:
1736 case QRhiTexture::ASTC_10x6:
1737 case QRhiTexture::ASTC_10x8:
1738 case QRhiTexture::ASTC_10x10:
1739 case QRhiTexture::ASTC_12x10:
1740 case QRhiTexture::ASTC_12x12:
1741 qWarning(
"QRhiD3D11 does not support ASTC textures");
1742 return DXGI_FORMAT_R8G8B8A8_UNORM;
1746 return DXGI_FORMAT_R8G8B8A8_UNORM;
1753 case DXGI_FORMAT_R8G8B8A8_UNORM:
1754 return QRhiTexture::RGBA8;
1755 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1757 (*flags) |= QRhiTexture::sRGB;
1758 return QRhiTexture::RGBA8;
1759 case DXGI_FORMAT_B8G8R8A8_UNORM:
1760 return QRhiTexture::BGRA8;
1761 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1763 (*flags) |= QRhiTexture::sRGB;
1764 return QRhiTexture::BGRA8;
1765 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1766 return QRhiTexture::RGBA16F;
1767 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1768 return QRhiTexture::RGBA32F;
1769 case DXGI_FORMAT_R10G10B10A2_UNORM:
1770 return QRhiTexture::RGB10A2;
1772 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1775 return QRhiTexture::UnknownFormat;
1781 case QRhiTexture::Format::D16:
1782 case QRhiTexture::Format::D24:
1783 case QRhiTexture::Format::D24S8:
1784 case QRhiTexture::Format::D32F:
1785 case QRhiTexture::Format::D32FS8:
1798 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1800 ofr.cbWrapper.resetCommands();
1811 return QRhi::FrameOpSuccess;
1815 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1817 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1818 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1820 box.front = is3D ? UINT(layer) : 0u;
1822 box.back = box.front + 1;
1825 cmd.args.updateSubRes.dst = texD->textureResource();
1826 cmd.args.updateSubRes.dstSubRes = subres;
1828 const QPoint dp = subresDesc.destinationTopLeft();
1829 if (!subresDesc.image().isNull()) {
1830 QImage img = subresDesc.image();
1831 QSize size = img.size();
1832 int bpl = img.bytesPerLine();
1833 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1834 const QPoint sp = subresDesc.sourceTopLeft();
1835 if (!subresDesc.sourceSize().isEmpty())
1836 size = subresDesc.sourceSize();
1837 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1838 if (img.depth() == 32) {
1839 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1840 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1842 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1843 bpl = img.bytesPerLine();
1844 cmd.args.updateSubRes.src = cbD->retainImage(img);
1847 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1848 cmd.args.updateSubRes.src = cbD->retainImage(img);
1850 box.left = UINT(dp.x());
1851 box.top = UINT(dp.y());
1852 box.right = UINT(dp.x() + size.width());
1853 box.bottom = UINT(dp.y() + size.height());
1854 cmd.args.updateSubRes.hasDstBox =
true;
1855 cmd.args.updateSubRes.dstBox = box;
1856 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1857 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1858 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1859 : subresDesc.sourceSize();
1862 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1866 box.left = UINT(aligned(dp.x(), blockDim.width()));
1867 box.top = UINT(aligned(dp.y(), blockDim.height()));
1868 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1869 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1870 cmd.args.updateSubRes.hasDstBox =
true;
1871 cmd.args.updateSubRes.dstBox = box;
1872 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1873 cmd.args.updateSubRes.srcRowPitch = bpl;
1874 }
else if (!subresDesc.data().isEmpty()) {
1875 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1876 : subresDesc.sourceSize();
1878 if (subresDesc.dataStride())
1879 bpl = subresDesc.dataStride();
1881 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1882 box.left = UINT(dp.x());
1883 box.top = UINT(dp.y());
1884 box.right = UINT(dp.x() + size.width());
1885 box.bottom = UINT(dp.y() + size.height());
1886 cmd.args.updateSubRes.hasDstBox =
true;
1887 cmd.args.updateSubRes.dstBox = box;
1888 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1889 cmd.args.updateSubRes.srcRowPitch = bpl;
1891 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1892 cbD->commands.unget();
1905 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1910 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1911 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1914 cmd.args.updateSubRes.dst = bufD->buffer;
1915 cmd.args.updateSubRes.dstSubRes = 0;
1916 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1917 cmd.args.updateSubRes.srcRowPitch = 0;
1922 box.left = u.offset;
1923 box.top = box.front = 0;
1924 box.back = box.bottom = 1;
1925 box.right = u.offset + u
.data.size();
1926 cmd.args.updateSubRes.hasDstBox =
true;
1927 cmd.args.updateSubRes.dstBox = box;
1930 if (bufD->m_type == QRhiBuffer::Dynamic) {
1931 u.result->data.resize(u.readSize);
1932 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1933 if (u.result->completed)
1934 u.result->completed();
1937 readback.result = u.result;
1938 readback.byteSize = u.readSize;
1940 D3D11_BUFFER_DESC desc = {};
1941 desc.ByteWidth = readback.byteSize;
1942 desc.Usage = D3D11_USAGE_STAGING;
1943 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1944 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1946 qWarning(
"Failed to create buffer: %s",
1947 qPrintable(QSystemError::windowsComString(hr)));
1953 cmd.args.copySubRes.dst = readback.stagingBuf;
1954 cmd.args.copySubRes.dstSubRes = 0;
1955 cmd.args.copySubRes.dstX = 0;
1956 cmd.args.copySubRes.dstY = 0;
1957 cmd.args.copySubRes.dstZ = 0;
1958 cmd.args.copySubRes.src = bufD->buffer;
1959 cmd.args.copySubRes.srcSubRes = 0;
1960 cmd.args.copySubRes.hasSrcBox =
true;
1962 box.left = u.offset;
1963 box.top = box.front = 0;
1964 box.back = box.bottom = 1;
1965 box.right = u.offset + u.readSize;
1966 cmd.args.copySubRes.srcBox = box;
1968 activeBufferReadbacks.append(readback);
1976 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
1977 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
1978 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
1979 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
1986 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1987 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1988 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
1989 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
1990 const QPoint dp = u.desc.destinationTopLeft();
1991 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
1992 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
1993 const QPoint sp = u.desc.sourceTopLeft();
1995 srcBox.left = UINT(sp.x());
1996 srcBox.top = UINT(sp.y());
1997 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
1999 srcBox.right = srcBox.left + UINT(copySize.width());
2000 srcBox.bottom = srcBox.top + UINT(copySize.height());
2001 srcBox.back = srcBox.front + 1;
2004 cmd.args.copySubRes.dst = dstD->textureResource();
2005 cmd.args.copySubRes.dstSubRes = dstSubRes;
2006 cmd.args.copySubRes.dstX = UINT(dp.x());
2007 cmd.args.copySubRes.dstY = UINT(dp.y());
2008 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2009 cmd.args.copySubRes.src = srcD->textureResource();
2010 cmd.args.copySubRes.srcSubRes = srcSubRes;
2011 cmd.args.copySubRes.hasSrcBox =
true;
2012 cmd.args.copySubRes.srcBox = srcBox;
2015 readback.desc = u.rb;
2016 readback.result = u.result;
2018 ID3D11Resource *src;
2019 DXGI_FORMAT dxgiFormat;
2021 QRhiTexture::Format format;
2028 if (texD->sampleDesc.Count > 1) {
2029 qWarning(
"Multisample texture cannot be read back");
2032 src = texD->textureResource();
2033 dxgiFormat = texD->dxgiFormat;
2034 if (u.rb.rect().isValid())
2037 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2038 format = texD->m_format;
2039 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2040 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2044 if (swapChainD->sampleDesc.Count > 1) {
2049 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2050 rcmd.args.resolveSubRes.dstSubRes = 0;
2052 rcmd.args.resolveSubRes.srcSubRes = 0;
2053 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2055 src = swapChainD->backBufferTex;
2056 dxgiFormat = swapChainD->colorFormat;
2057 if (u.rb.rect().isValid())
2060 rect = QRect({0, 0}, swapChainD->pixelSize);
2061 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2062 if (format == QRhiTexture::UnknownFormat)
2065 quint32 byteSize = 0;
2067 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2069 D3D11_TEXTURE2D_DESC desc = {};
2070 desc.Width = UINT(rect.width());
2071 desc.Height = UINT(rect.height());
2074 desc.Format = dxgiFormat;
2075 desc.SampleDesc.Count = 1;
2076 desc.Usage = D3D11_USAGE_STAGING;
2077 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2078 ID3D11Texture2D *stagingTex;
2079 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2081 qWarning(
"Failed to create readback staging texture: %s",
2082 qPrintable(QSystemError::windowsComString(hr)));
2088 cmd.args.copySubRes.dst = stagingTex;
2089 cmd.args.copySubRes.dstSubRes = 0;
2090 cmd.args.copySubRes.dstX = 0;
2091 cmd.args.copySubRes.dstY = 0;
2092 cmd.args.copySubRes.dstZ = 0;
2093 cmd.args.copySubRes.src = src;
2094 cmd.args.copySubRes.srcSubRes = subres;
2096 D3D11_BOX srcBox = {};
2097 srcBox.left = UINT(rect.left());
2098 srcBox.top = UINT(rect.top());
2099 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2101 srcBox.right = srcBox.left + desc.Width;
2102 srcBox.bottom = srcBox.top + desc.Height;
2103 srcBox.back = srcBox.front + 1;
2104 cmd.args.copySubRes.hasSrcBox =
true;
2105 cmd.args.copySubRes.srcBox = srcBox;
2107 readback.stagingTex = stagingTex;
2108 readback.byteSize = byteSize;
2110 readback.pixelSize = rect.size();
2111 readback.format = format;
2113 activeTextureReadbacks.append(readback);
2115 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2118 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2127 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2129 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2131 readback.result->format = readback.format;
2132 readback.result->pixelSize = readback.pixelSize;
2134 D3D11_MAPPED_SUBRESOURCE mp;
2135 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2136 if (SUCCEEDED(hr)) {
2137 readback.result->data.resize(
int(readback.byteSize));
2140 char *dst = readback.result->data.data();
2141 char *src =
static_cast<
char *>(mp.pData);
2142 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2143 memcpy(dst, src, readback.bpl);
2144 dst += readback.bpl;
2147 context->Unmap(readback.stagingTex, 0);
2149 qWarning(
"Failed to map readback staging texture: %s",
2150 qPrintable(QSystemError::windowsComString(hr)));
2153 readback.stagingTex->Release();
2155 if (readback.result->completed)
2156 completedCallbacks.append(readback.result->completed);
2158 activeTextureReadbacks.removeLast();
2161 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2164 D3D11_MAPPED_SUBRESOURCE mp;
2165 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2166 if (SUCCEEDED(hr)) {
2167 readback.result->data.resize(
int(readback.byteSize));
2168 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2169 context->Unmap(readback.stagingBuf, 0);
2171 qWarning(
"Failed to map readback staging texture: %s",
2172 qPrintable(QSystemError::windowsComString(hr)));
2175 readback.stagingBuf->Release();
2177 if (readback.result->completed)
2178 completedCallbacks.append(readback.result->completed);
2180 activeBufferReadbacks.removeLast();
2183 for (
auto f : completedCallbacks)
2189 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2195 QRhiRenderTarget *rt,
2196 const QColor &colorClearValue,
2197 const QRhiDepthStencilClearValue &depthStencilClearValue,
2198 QRhiResourceUpdateBatch *resourceUpdates,
2204 if (resourceUpdates)
2207 bool wantsColorClear =
true;
2208 bool wantsDsClear =
true;
2210 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2212 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2213 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2214 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2222 fbCmd.args.setRenderTarget.rt = rt;
2226 clearCmd.args.clear.rt = rt;
2227 clearCmd.args.clear.mask = 0;
2233 clearCmd.args.clear.c[0] = colorClearValue.redF();
2234 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2235 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2236 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2237 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2238 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2241 cbD->currentTarget = rt;
2251 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2253 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2256 const QRhiColorAttachment &colorAtt(*it);
2257 if (!colorAtt.resolveTexture())
2263 Q_ASSERT(srcTexD || srcRbD);
2266 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2267 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2268 UINT(colorAtt.resolveLayer()),
2269 dstTexD->mipLevelCount);
2271 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2272 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2273 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2274 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2275 cbD->commands.unget();
2278 if (srcTexD->sampleDesc.Count <= 1) {
2279 qWarning(
"Cannot resolve a non-multisample texture");
2280 cbD->commands.unget();
2283 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2284 qWarning(
"Resolve source and destination sizes do not match");
2285 cbD->commands.unget();
2289 cmd.args.resolveSubRes.src = srcRbD->tex;
2290 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2291 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2292 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2293 cbD->commands.unget();
2296 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2297 qWarning(
"Resolve source and destination sizes do not match");
2298 cbD->commands.unget();
2302 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2303 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2305 if (rtTex->m_desc.depthResolveTexture())
2306 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2310 cbD->currentTarget =
nullptr;
2312 if (resourceUpdates)
2317 QRhiResourceUpdateBatch *resourceUpdates,
2323 if (resourceUpdates)
2341 if (resourceUpdates)
2350 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2352 if (pipelineChanged) {
2353 cbD->currentGraphicsPipeline =
nullptr;
2354 cbD->currentComputePipeline = psD;
2355 cbD->currentPipelineGeneration = psD->generation;
2359 cmd.args.bindComputePipeline.ps = psD;
2370 cmd.args.dispatch.x = UINT(x);
2371 cmd.args.dispatch.y = UINT(y);
2372 cmd.args.dispatch.z = UINT(z);
2377 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2379 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2380 if (!map || map->isEmpty())
2381 return { binding, binding };
2383 auto it = map->constFind(binding);
2384 if (it != map->cend())
2394 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2396 srbD->resourceBatches.clear();
2402 ID3D11Buffer *buffer;
2403 uint offsetInConstants;
2404 uint sizeInConstants;
2408 ID3D11ShaderResourceView *srv;
2412 ID3D11SamplerState *sampler;
2416 ID3D11UnorderedAccessView *uav;
2418 QVarLengthArray<Buffer, 8> buffers;
2419 QVarLengthArray<Texture, 8> textures;
2420 QVarLengthArray<Sampler, 8> samplers;
2421 QVarLengthArray<Uav, 8> uavs;
2424 for (
const Buffer &buf : buffers) {
2425 batches.ubufs.feed(buf.breg, buf.buffer);
2426 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2427 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2428 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2434 for (
const Texture &t : textures)
2435 batches.shaderresources.feed(t.treg, t.srv);
2436 for (
const Sampler &s : samplers)
2437 batches.samplers.feed(s.sreg, s.sampler);
2442 for (
const Stage::Uav &u : uavs)
2443 batches.uavs.feed(u.ureg, u.uav);
2448 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2449 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2452 case QRhiShaderResourceBinding::UniformBuffer:
2455 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2456 bd.ubuf.id = bufD->m_id;
2457 bd.ubuf.generation = bufD->generation;
2464 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2468 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2469 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2470 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2471 if (nativeBinding.first >= 0)
2472 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2474 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2475 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2476 if (nativeBinding.first >= 0)
2477 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2479 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2480 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2481 if (nativeBinding.first >= 0)
2482 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2484 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2485 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2486 if (nativeBinding.first >= 0)
2487 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2489 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2490 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2491 if (nativeBinding.first >= 0)
2492 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2494 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2495 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2496 if (nativeBinding.first >= 0)
2497 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2501 case QRhiShaderResourceBinding::SampledTexture:
2502 case QRhiShaderResourceBinding::Texture:
2503 case QRhiShaderResourceBinding::Sampler:
2505 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2506 bd.stex.count = data->count;
2507 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2508 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2509 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2510 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2511 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2512 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2516 for (
int elem = 0; elem < data->count; ++elem) {
2519 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2520 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2521 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2522 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2527 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2528 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2529 : (samplerD ? nativeBindingVert.first : -1);
2530 if (nativeBindingVert.first >= 0 && texD)
2531 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2532 if (samplerBinding >= 0)
2533 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2535 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2536 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2537 : (samplerD ? nativeBindingHull.first : -1);
2538 if (nativeBindingHull.first >= 0 && texD)
2539 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2540 if (samplerBinding >= 0)
2541 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2543 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2544 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2545 : (samplerD ? nativeBindingDomain.first : -1);
2546 if (nativeBindingDomain.first >= 0 && texD)
2547 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2548 if (samplerBinding >= 0)
2549 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2551 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2552 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2553 : (samplerD ? nativeBindingGeom.first : -1);
2554 if (nativeBindingGeom.first >= 0 && texD)
2555 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2556 if (samplerBinding >= 0)
2557 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2559 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2560 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2561 : (samplerD ? nativeBindingFrag.first : -1);
2562 if (nativeBindingFrag.first >= 0 && texD)
2563 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2564 if (samplerBinding >= 0)
2565 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2567 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2568 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2569 : (samplerD ? nativeBindingComp.first : -1);
2570 if (nativeBindingComp.first >= 0 && texD)
2571 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2572 if (samplerBinding >= 0)
2573 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2578 case QRhiShaderResourceBinding::ImageLoad:
2579 case QRhiShaderResourceBinding::ImageStore:
2580 case QRhiShaderResourceBinding::ImageLoadStore:
2583 bd.simage.id = texD->m_id;
2584 bd.simage.generation = texD->generation;
2585 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2586 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2587 if (nativeBinding.first >= 0) {
2588 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2590 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2592 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2593 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2594 if (nativeBinding.first >= 0) {
2595 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2597 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2600 qWarning(
"Unordered access only supported at fragment/compute stage");
2604 case QRhiShaderResourceBinding::BufferLoad:
2605 case QRhiShaderResourceBinding::BufferStore:
2606 case QRhiShaderResourceBinding::BufferLoadStore:
2609 bd.sbuf.id = bufD->m_id;
2610 bd.sbuf.generation = bufD->generation;
2611 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2612 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2613 if (nativeBinding.first >= 0) {
2614 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2616 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2619 qWarning(
"Unordered access only supported at compute stage");
2634 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2635 return a.breg < b.breg;
2637 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2638 return a.treg < b.treg;
2640 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2641 return a.sreg < b.sreg;
2643 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2644 return a.ureg < b.ureg;
2648 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2649 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2650 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2651 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2652 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2653 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2655 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2656 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2657 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2658 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2659 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2660 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2662 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2663 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2671 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2673 D3D11_MAPPED_SUBRESOURCE mp;
2674 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2675 if (SUCCEEDED(hr)) {
2676 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2677 context->Unmap(bufD->buffer, 0);
2679 qWarning(
"Failed to map buffer: %s",
2680 qPrintable(QSystemError::windowsComString(hr)));
2686 const QRhiBatchedBindings<UINT> *originalBindings,
2687 const QRhiBatchedBindings<UINT> *staticOffsets,
2688 const uint *dynOfsPairs,
int dynOfsPairCount)
2690 const int count = staticOffsets->batches[batchIndex].resources.count();
2693 for (
int b = 0; b < count; ++b) {
2694 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2695 for (
int di = 0; di < dynOfsPairCount; ++di) {
2696 const uint binding = dynOfsPairs[2 * di];
2699 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2700 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2701 offsets[b] = offsetInConstants;
2710 if (startSlot + countSlots > maxSlots) {
2711 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2712 resType, countSlots, startSlot, maxSlots);
2713 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2718#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2719 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2720 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2721 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2722 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2723 batches.ubufs.batches[i].resources.count(),
2724 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2725 #stagePrefixU " cbuf");
2727 if (!dynOfsPairCount) {
2728 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2730 batches.ubufs.batches[i].resources.constData(),
2731 batches.ubufoffsets.batches[i].resources.constData(),
2732 batches.ubufsizes.batches[i].resources.constData());
2734 applyDynamicOffsets(offsets, i,
2735 &batches.ubuforigbindings, &batches.ubufoffsets,
2736 dynOfsPairs, dynOfsPairCount);
2737 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2739 batches.ubufs.batches[i].resources.constData(),
2741 batches.ubufsizes.batches[i].resources.constData());
2747#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2748 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2749 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2750 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2751 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2753 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2755 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2756 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2757 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2759 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2760 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2761 int(batch.startBinding + count) - 1
);
2766#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2767 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2768 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2769 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2772 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2774 batch.resources.constData(),
2776 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2777 int(batch.startBinding + count) - 1
);
2783 const uint *dynOfsPairs,
int dynOfsPairCount,
2784 bool offsetOnlyChange,
2797 if (!offsetOnlyChange) {
2807 if (allResourceBatches.fsUavBatches.present) {
2808 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2809 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2811 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2813 if (rtUavState.update(rtD, batch.resources.constData(), count)) {
2814 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv,
2815 UINT(rtD->colorAttCount), count, batch.resources.constData(),
nullptr);
2817 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2818 int(batch.startBinding + count) - 1);
2831 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2837 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2838 for (
int i = 0; i < count; ++i)
2839 nullbufs[i] =
nullptr;
2840 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2841 for (
int i = 0; i < count; ++i)
2843 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2844 for (
int i = 0; i < count; ++i)
2846 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2856 if (nullsrvCount > 0) {
2857 QVarLengthArray<ID3D11ShaderResourceView *,
2858 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2859 for (
int i = 0; i < nullsrvs.count(); ++i)
2860 nullsrvs[i] =
nullptr;
2862 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2866 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2870 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2874 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2878 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2882 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2888 rtUavState.update(rtD);
2889 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv, 0, 0,
nullptr,
nullptr);
2894 QVarLengthArray<ID3D11UnorderedAccessView *,
2895 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2896 for (
int i = 0; i < nulluavCount; ++i)
2897 nulluavs[i] =
nullptr;
2898 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2903#define SETSHADER(StageL, StageU)
2904 if (psD->StageL.shader) {
2905 context->StageU##SetShader(psD->StageL.shader, nullptr, 0
);
2906 currentShaderMask |= StageU##MaskBit;
2907 } else if (currentShaderMask & StageU##MaskBit) {
2908 context->StageU##SetShader(nullptr, nullptr, 0
);
2909 currentShaderMask &= ~StageU##MaskBit;
2914 quint32 stencilRef = 0;
2915 float blendConstants[] = { 1, 1, 1, 1 };
2916 enum ActiveShaderMask {
2923 int currentShaderMask = 0xFF;
2929 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2932 case QD3D11CommandBuffer::Command::BeginFrame:
2933 if (cmd.args.beginFrame.tsDisjointQuery)
2934 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2935 if (cmd.args.beginFrame.tsQuery) {
2936 if (cmd.args.beginFrame.swapchainData) {
2942 rtUavState.update(rtD);
2943 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2946 context->End(cmd.args.beginFrame.tsQuery);
2949 case QD3D11CommandBuffer::Command::EndFrame:
2950 if (cmd.args.endFrame.tsQuery)
2951 context->End(cmd.args.endFrame.tsQuery);
2952 if (cmd.args.endFrame.tsDisjointQuery)
2953 context->End(cmd.args.endFrame.tsDisjointQuery);
2961 if (rtUavState.update(rtD))
2962 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2970 for (
int i = 0; i < rtD->colorAttCount; ++i)
2971 context->ClearRenderTargetView(rtD->rtv[i], cmd.args.clear.c);
2974 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
2975 ds |= D3D11_CLEAR_DEPTH;
2976 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
2977 ds |= D3D11_CLEAR_STENCIL;
2979 context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
2985 v.TopLeftX = cmd.args.viewport.x;
2986 v.TopLeftY = cmd.args.viewport.y;
2987 v.Width = cmd.args.viewport.w;
2988 v.Height = cmd.args.viewport.h;
2989 v.MinDepth = cmd.args.viewport.d0;
2990 v.MaxDepth = cmd.args.viewport.d1;
2991 context->RSSetViewports(1, &v);
2997 r.left = cmd.args.scissor.x;
2998 r.top = cmd.args.scissor.y;
3000 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3001 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3002 context->RSSetScissorRects(1, &r);
3008 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3009 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3010 UINT(cmd.args.bindVertexBuffers.slotCount),
3011 cmd.args.bindVertexBuffers.buffers,
3012 cmd.args.bindVertexBuffers.strides,
3013 cmd.args.bindVertexBuffers.offsets);
3017 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3018 cmd.args.bindIndexBuffer.format,
3019 cmd.args.bindIndexBuffer.offset);
3029 context->IASetPrimitiveTopology(psD->d3dTopology);
3030 context->IASetInputLayout(psD->inputLayout);
3031 context->OMSetDepthStencilState(psD->dsState, stencilRef);
3032 context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
3033 context->RSSetState(psD->rastState);
3036 case QD3D11CommandBuffer::Command::BindShaderResources:
3037 bindShaderResources(cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3038 cmd.args.bindShaderResources.dynamicOffsetPairs,
3039 cmd.args.bindShaderResources.dynamicOffsetCount,
3040 cmd.args.bindShaderResources.offsetOnlyChange,
3045 stencilRef = cmd.args.stencilRef.ref;
3046 context->OMSetDepthStencilState(cmd.args.stencilRef.ps->dsState, stencilRef);
3049 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3050 context->OMSetBlendState(cmd.args.blendConstants.ps->blendState, blendConstants, 0xffffffff);
3053 if (cmd.args.draw.ps) {
3054 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3055 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3057 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3058 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3060 qWarning(
"No graphics pipeline active for draw; ignored");
3064 if (cmd.args.drawIndexed.ps) {
3065 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3066 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3067 cmd.args.drawIndexed.vertexOffset);
3069 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3070 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3071 cmd.args.drawIndexed.firstInstance);
3073 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3076 case QD3D11CommandBuffer::Command::UpdateSubRes:
3077 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3078 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3079 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3081 case QD3D11CommandBuffer::Command::CopySubRes:
3082 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3083 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3084 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3085 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3087 case QD3D11CommandBuffer::Command::ResolveSubRes:
3088 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3089 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3090 cmd.args.resolveSubRes.format);
3092 case QD3D11CommandBuffer::Command::GenMip:
3093 context->GenerateMips(cmd.args.genMip.srv);
3095 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3096 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3098 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3099 annotations->EndEvent();
3101 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3102 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3104 case QD3D11CommandBuffer::Command::BindComputePipeline:
3105 context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader,
nullptr, 0);
3107 case QD3D11CommandBuffer::Command::Dispatch:
3108 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3137 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3138 it.value()->Release();
3143 rhiD->unregisterResource(
this);
3149 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3150 u |= D3D11_BIND_VERTEX_BUFFER;
3151 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3152 u |= D3D11_BIND_INDEX_BUFFER;
3153 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3154 u |= D3D11_BIND_CONSTANT_BUFFER;
3155 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3156 u |= D3D11_BIND_UNORDERED_ACCESS;
3165 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3166 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3170 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3171 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3175 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3176 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3178 D3D11_BUFFER_DESC desc = {};
3179 desc.ByteWidth = roundedSize;
3180 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3181 desc.BindFlags = toD3DBufferUsage(m_usage);
3182 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3183 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3186 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3188 qWarning(
"Failed to create buffer: %s",
3189 qPrintable(QSystemError::windowsComString(hr)));
3193 if (m_type == Dynamic) {
3194 dynBuf =
new char[nonZeroSize];
3198 if (!m_objectName.isEmpty())
3199 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3202 rhiD->registerResource(
this);
3208 if (m_type == Dynamic) {
3212 return { { &buffer }, 1 };
3223 Q_ASSERT(m_type == Dynamic);
3224 D3D11_MAPPED_SUBRESOURCE mp;
3226 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3228 qWarning(
"Failed to map buffer: %s",
3229 qPrintable(QSystemError::windowsComString(hr)));
3232 return static_cast<
char *>(mp.pData);
3238 rhiD->context->Unmap(buffer, 0);
3243 auto it = uavs.find(offset);
3244 if (it != uavs.end())
3248 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3249 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3250 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3251 desc.Buffer.FirstElement = offset / 4u;
3252 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3253 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3256 ID3D11UnorderedAccessView *uav =
nullptr;
3257 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3259 qWarning(
"Failed to create UAV: %s",
3260 qPrintable(QSystemError::windowsComString(hr)));
3269 int sampleCount, QRhiRenderBuffer::Flags flags,
3270 QRhiTexture::Format backingFormatHint)
3300 rhiD->unregisterResource(
this);
3308 if (m_pixelSize.isEmpty())
3312 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3314 D3D11_TEXTURE2D_DESC desc = {};
3315 desc.Width = UINT(m_pixelSize.width());
3316 desc.Height = UINT(m_pixelSize.height());
3319 desc.SampleDesc = sampleDesc;
3320 desc.Usage = D3D11_USAGE_DEFAULT;
3322 if (m_type == Color) {
3323 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3324 : toD3DTextureFormat(m_backingFormatHint, {});
3325 desc.Format = dxgiFormat;
3326 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3327 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3329 qWarning(
"Failed to create color renderbuffer: %s",
3330 qPrintable(QSystemError::windowsComString(hr)));
3333 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3334 rtvDesc.Format = dxgiFormat;
3335 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3336 : D3D11_RTV_DIMENSION_TEXTURE2D;
3337 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3339 qWarning(
"Failed to create rtv: %s",
3340 qPrintable(QSystemError::windowsComString(hr)));
3343 }
else if (m_type == DepthStencil) {
3344 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3345 desc.Format = dxgiFormat;
3346 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3347 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3349 qWarning(
"Failed to create depth-stencil buffer: %s",
3350 qPrintable(QSystemError::windowsComString(hr)));
3353 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3354 dsvDesc.Format = dxgiFormat;
3355 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3356 : D3D11_DSV_DIMENSION_TEXTURE2D;
3357 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3359 qWarning(
"Failed to create dsv: %s",
3360 qPrintable(QSystemError::windowsComString(hr)));
3367 if (!m_objectName.isEmpty())
3368 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3371 rhiD->registerResource(
this);
3377 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3378 return m_backingFormatHint;
3380 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3384 int arraySize,
int sampleCount, Flags flags)
3387 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3388 perLevelViews[i] =
nullptr;
3398 if (!tex && !tex3D && !tex1D)
3406 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3407 if (perLevelViews[i]) {
3408 perLevelViews[i]->Release();
3409 perLevelViews[i] =
nullptr;
3428 rhiD->unregisterResource(
this);
3434 case QRhiTexture::Format::D16:
3435 return DXGI_FORMAT_R16_FLOAT;
3436 case QRhiTexture::Format::D24:
3437 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3438 case QRhiTexture::Format::D24S8:
3439 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3440 case QRhiTexture::Format::D32F:
3441 return DXGI_FORMAT_R32_FLOAT;
3442 case QRhiTexture::Format::D32FS8:
3443 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3446 return DXGI_FORMAT_R32_FLOAT;
3453 case QRhiTexture::Format::D16:
3454 return DXGI_FORMAT_D16_UNORM;
3455 case QRhiTexture::Format::D24:
3456 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3457 case QRhiTexture::Format::D24S8:
3458 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3459 case QRhiTexture::Format::D32F:
3460 return DXGI_FORMAT_D32_FLOAT;
3461 case QRhiTexture::Format::D32FS8:
3462 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3465 return DXGI_FORMAT_D32_FLOAT;
3471 if (tex || tex3D || tex1D)
3475 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3478 const bool isDepth = isDepthTextureFormat(m_format);
3479 const bool isCube = m_flags.testFlag(CubeMap);
3480 const bool is3D = m_flags.testFlag(ThreeDimensional);
3481 const bool isArray = m_flags.testFlag(TextureArray);
3482 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3483 const bool is1D = m_flags.testFlag(OneDimensional);
3485 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3486 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3488 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3489 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3490 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3491 if (sampleDesc.Count > 1) {
3493 qWarning(
"Cubemap texture cannot be multisample");
3497 qWarning(
"3D texture cannot be multisample");
3501 qWarning(
"Multisample texture cannot have mipmaps");
3505 if (isDepth && hasMipMaps) {
3506 qWarning(
"Depth texture cannot have mipmaps");
3509 if (isCube && is3D) {
3510 qWarning(
"Texture cannot be both cube and 3D");
3513 if (isArray && is3D) {
3514 qWarning(
"Texture cannot be both array and 3D");
3517 if (isCube && is1D) {
3518 qWarning(
"Texture cannot be both cube and 1D");
3522 qWarning(
"Texture cannot be both 1D and 3D");
3525 if (m_depth > 1 && !is3D) {
3526 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3529 if (m_arraySize > 0 && !isArray) {
3530 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3533 if (m_arraySize < 1 && isArray) {
3534 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3539 *adjustedSize = size;
3547 const bool isDepth = isDepthTextureFormat(m_format);
3548 const bool isCube = m_flags.testFlag(CubeMap);
3549 const bool is3D = m_flags.testFlag(ThreeDimensional);
3550 const bool isArray = m_flags.testFlag(TextureArray);
3551 const bool is1D = m_flags.testFlag(OneDimensional);
3553 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3554 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3556 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3557 srvDesc.TextureCube.MipLevels = mipLevelCount;
3561 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3562 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3563 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3564 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3565 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3567 srvDesc.Texture1DArray.FirstArraySlice = 0;
3568 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3571 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3572 srvDesc.Texture1D.MipLevels = mipLevelCount;
3574 }
else if (isArray) {
3575 if (sampleDesc.Count > 1) {
3576 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3577 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3578 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3579 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3581 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3582 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3585 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3586 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3587 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3588 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3589 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3591 srvDesc.Texture2DArray.FirstArraySlice = 0;
3592 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3596 if (sampleDesc.Count > 1) {
3597 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3599 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3600 srvDesc.Texture3D.MipLevels = mipLevelCount;
3602 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3603 srvDesc.Texture2D.MipLevels = mipLevelCount;
3608 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3610 qWarning(
"Failed to create srv: %s",
3611 qPrintable(QSystemError::windowsComString(hr)));
3622 if (!prepareCreate(&size))
3625 const bool isDepth = isDepthTextureFormat(m_format);
3626 const bool isCube = m_flags.testFlag(CubeMap);
3627 const bool is3D = m_flags.testFlag(ThreeDimensional);
3628 const bool isArray = m_flags.testFlag(TextureArray);
3629 const bool is1D = m_flags.testFlag(OneDimensional);
3631 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3632 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3633 if (m_flags.testFlag(RenderTarget)) {
3635 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3637 bindFlags |= D3D11_BIND_RENDER_TARGET;
3639 if (m_flags.testFlag(UsedWithGenerateMips)) {
3641 qWarning(
"Depth texture cannot have mipmaps generated");
3644 bindFlags |= D3D11_BIND_RENDER_TARGET;
3645 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3647 if (m_flags.testFlag(UsedWithLoadStore))
3648 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3652 D3D11_TEXTURE1D_DESC desc = {};
3653 desc.Width = UINT(size.width());
3654 desc.MipLevels = mipLevelCount;
3655 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3656 desc.Format = dxgiFormat;
3657 desc.Usage = D3D11_USAGE_DEFAULT;
3658 desc.BindFlags = bindFlags;
3659 desc.MiscFlags = miscFlags;
3661 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3663 qWarning(
"Failed to create 1D texture: %s",
3664 qPrintable(QSystemError::windowsComString(hr)));
3667 if (!m_objectName.isEmpty())
3668 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3669 m_objectName.constData());
3671 D3D11_TEXTURE2D_DESC desc = {};
3672 desc.Width = UINT(size.width());
3673 desc.Height = UINT(size.height());
3674 desc.MipLevels = mipLevelCount;
3675 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3676 desc.Format = dxgiFormat;
3677 desc.SampleDesc = sampleDesc;
3678 desc.Usage = D3D11_USAGE_DEFAULT;
3679 desc.BindFlags = bindFlags;
3680 desc.MiscFlags = miscFlags;
3682 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3684 qWarning(
"Failed to create 2D texture: %s",
3685 qPrintable(QSystemError::windowsComString(hr)));
3688 if (!m_objectName.isEmpty())
3689 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3691 D3D11_TEXTURE3D_DESC desc = {};
3692 desc.Width = UINT(size.width());
3693 desc.Height = UINT(size.height());
3694 desc.Depth = UINT(qMax(1, m_depth));
3695 desc.MipLevels = mipLevelCount;
3696 desc.Format = dxgiFormat;
3697 desc.Usage = D3D11_USAGE_DEFAULT;
3698 desc.BindFlags = bindFlags;
3699 desc.MiscFlags = miscFlags;
3701 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3703 qWarning(
"Failed to create 3D texture: %s",
3704 qPrintable(QSystemError::windowsComString(hr)));
3707 if (!m_objectName.isEmpty())
3708 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3715 rhiD->registerResource(
this);
3724 if (!prepareCreate())
3727 if (m_flags.testFlag(ThreeDimensional))
3728 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3729 else if (m_flags.testFlags(OneDimensional))
3730 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3732 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3739 rhiD->registerResource(
this);
3745 return { quint64(textureResource()), 0 };
3750 if (perLevelViews[level])
3751 return perLevelViews[level];
3753 const bool isCube = m_flags.testFlag(CubeMap);
3754 const bool isArray = m_flags.testFlag(TextureArray);
3755 const bool is3D = m_flags.testFlag(ThreeDimensional);
3756 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3757 desc.Format = dxgiFormat;
3759 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3760 desc.Texture2DArray.MipSlice = UINT(level);
3761 desc.Texture2DArray.FirstArraySlice = 0;
3762 desc.Texture2DArray.ArraySize = 6;
3763 }
else if (isArray) {
3764 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3765 desc.Texture2DArray.MipSlice = UINT(level);
3766 desc.Texture2DArray.FirstArraySlice = 0;
3767 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3769 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3770 desc.Texture3D.MipSlice = UINT(level);
3771 desc.Texture3D.WSize = UINT(m_depth);
3773 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3774 desc.Texture2D.MipSlice = UINT(level);
3778 ID3D11UnorderedAccessView *uav =
nullptr;
3779 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3781 qWarning(
"Failed to create UAV: %s",
3782 qPrintable(QSystemError::windowsComString(hr)));
3786 perLevelViews[level] = uav;
3791 AddressMode u, AddressMode v, AddressMode w)
3806 samplerState->Release();
3807 samplerState =
nullptr;
3811 rhiD->unregisterResource(
this);
3814static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3816 if (minFilter == QRhiSampler::Nearest) {
3817 if (magFilter == QRhiSampler::Nearest) {
3818 if (mipFilter == QRhiSampler::Linear)
3819 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3821 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3823 if (mipFilter == QRhiSampler::Linear)
3824 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3826 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3829 if (magFilter == QRhiSampler::Nearest) {
3830 if (mipFilter == QRhiSampler::Linear)
3831 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3833 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3835 if (mipFilter == QRhiSampler::Linear)
3836 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3838 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3843 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3849 case QRhiSampler::Repeat:
3850 return D3D11_TEXTURE_ADDRESS_WRAP;
3851 case QRhiSampler::ClampToEdge:
3852 return D3D11_TEXTURE_ADDRESS_CLAMP;
3853 case QRhiSampler::Mirror:
3854 return D3D11_TEXTURE_ADDRESS_MIRROR;
3857 return D3D11_TEXTURE_ADDRESS_CLAMP;
3864 case QRhiSampler::Never:
3865 return D3D11_COMPARISON_NEVER;
3866 case QRhiSampler::Less:
3867 return D3D11_COMPARISON_LESS;
3868 case QRhiSampler::Equal:
3869 return D3D11_COMPARISON_EQUAL;
3870 case QRhiSampler::LessOrEqual:
3871 return D3D11_COMPARISON_LESS_EQUAL;
3872 case QRhiSampler::Greater:
3873 return D3D11_COMPARISON_GREATER;
3874 case QRhiSampler::NotEqual:
3875 return D3D11_COMPARISON_NOT_EQUAL;
3876 case QRhiSampler::GreaterOrEqual:
3877 return D3D11_COMPARISON_GREATER_EQUAL;
3878 case QRhiSampler::Always:
3879 return D3D11_COMPARISON_ALWAYS;
3882 return D3D11_COMPARISON_NEVER;
3891 D3D11_SAMPLER_DESC desc = {};
3892 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3893 if (m_compareOp != Never)
3894 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3895 desc.AddressU = toD3DAddressMode(m_addressU);
3896 desc.AddressV = toD3DAddressMode(m_addressV);
3897 desc.AddressW = toD3DAddressMode(m_addressW);
3898 desc.MaxAnisotropy = 1.0f;
3899 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3900 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3903 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3905 qWarning(
"Failed to create sampler state: %s",
3906 qPrintable(QSystemError::windowsComString(hr)));
3911 rhiD->registerResource(
this);
3930 rhiD->unregisterResource(
this);
3943 rhiD->registerResource(rpD,
false);
3980 return d.sampleCount;
3984 const QRhiTextureRenderTargetDescription &desc,
4002 if (!rtv[0] && !dsv)
4021 rhiD->unregisterResource(
this);
4028 rhiD->registerResource(rpD,
false);
4037 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4038 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4039 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4043 d.colorAttCount = 0;
4045 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4046 d.colorAttCount += 1;
4047 const QRhiColorAttachment &colorAtt(*it);
4048 QRhiTexture *texture = colorAtt.texture();
4049 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4050 Q_ASSERT(texture || rb);
4053 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4054 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4055 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4056 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4057 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4058 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4059 rtvDesc.Texture2DArray.ArraySize = 1;
4060 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4061 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4062 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4063 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4064 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4065 rtvDesc.Texture1DArray.ArraySize = 1;
4067 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4068 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4070 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4071 if (texD->sampleDesc.Count > 1) {
4072 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4073 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4074 rtvDesc.Texture2DMSArray.ArraySize = 1;
4076 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4077 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4078 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4079 rtvDesc.Texture2DArray.ArraySize = 1;
4081 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4082 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4083 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4084 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4085 rtvDesc.Texture3D.WSize = 1;
4087 if (texD->sampleDesc.Count > 1) {
4088 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4090 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4091 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4094 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4096 qWarning(
"Failed to create rtv: %s",
4097 qPrintable(QSystemError::windowsComString(hr)));
4101 if (attIndex == 0) {
4102 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4103 d.sampleCount =
int(texD->sampleDesc.Count);
4108 rtv[attIndex] = rbD->rtv;
4109 if (attIndex == 0) {
4110 d.pixelSize = rbD->pixelSize();
4111 d.sampleCount =
int(rbD->sampleDesc.Count);
4117 if (hasDepthStencil) {
4118 if (m_desc.depthTexture()) {
4121 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4122 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4123 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4124 : D3D11_DSV_DIMENSION_TEXTURE2D;
4125 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4126 if (depthTexD->sampleDesc.Count > 1) {
4127 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4128 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4129 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4130 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4132 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4133 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4136 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4137 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4138 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4139 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4141 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4142 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4146 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4148 qWarning(
"Failed to create dsv: %s",
4149 qPrintable(QSystemError::windowsComString(hr)));
4152 if (d.colorAttCount == 0) {
4153 d.pixelSize = depthTexD->pixelSize();
4154 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4159 dsv = depthRbD->dsv;
4160 if (d.colorAttCount == 0) {
4161 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4162 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4170 for (
int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
4171 d.rtv[i] = i < d.colorAttCount ? rtv[i] :
nullptr;
4174 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4176 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4178 rhiD->registerResource(
this);
4184 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4197 return d.sampleCount;
4212 sortedBindings.clear();
4213 boundResourceData.clear();
4217 rhiD->unregisterResource(
this);
4222 if (!sortedBindings.isEmpty())
4226 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4229 rhiD->updateLayoutDesc(
this);
4231 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4232 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4234 boundResourceData.resize(sortedBindings.count());
4236 for (BoundResourceData &bd : boundResourceData)
4237 memset(&bd, 0,
sizeof(BoundResourceData));
4240 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4241 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4242 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4243 hasDynamicOffset =
true;
4249 rhiD->registerResource(
this,
false);
4255 sortedBindings.clear();
4256 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4257 if (!flags.testFlag(BindingsAreSorted))
4258 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4260 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4261 for (BoundResourceData &bd : boundResourceData)
4262 memset(&bd, 0,
sizeof(BoundResourceData));
4281 s.shader->Release();
4284 s.nativeResourceBindingMap.clear();
4296 blendState->Release();
4297 blendState =
nullptr;
4301 inputLayout->Release();
4302 inputLayout =
nullptr;
4306 rastState->Release();
4307 rastState =
nullptr;
4310 releasePipelineShader(vs);
4311 releasePipelineShader(hs);
4312 releasePipelineShader(ds);
4313 releasePipelineShader(gs);
4314 releasePipelineShader(fs);
4318 rhiD->unregisterResource(
this);
4324 case QRhiGraphicsPipeline::None:
4325 return D3D11_CULL_NONE;
4326 case QRhiGraphicsPipeline::Front:
4327 return D3D11_CULL_FRONT;
4328 case QRhiGraphicsPipeline::Back:
4329 return D3D11_CULL_BACK;
4332 return D3D11_CULL_NONE;
4339 case QRhiGraphicsPipeline::Fill:
4340 return D3D11_FILL_SOLID;
4341 case QRhiGraphicsPipeline::Line:
4342 return D3D11_FILL_WIREFRAME;
4345 return D3D11_FILL_SOLID;
4352 case QRhiGraphicsPipeline::Never:
4353 return D3D11_COMPARISON_NEVER;
4354 case QRhiGraphicsPipeline::Less:
4355 return D3D11_COMPARISON_LESS;
4356 case QRhiGraphicsPipeline::Equal:
4357 return D3D11_COMPARISON_EQUAL;
4358 case QRhiGraphicsPipeline::LessOrEqual:
4359 return D3D11_COMPARISON_LESS_EQUAL;
4360 case QRhiGraphicsPipeline::Greater:
4361 return D3D11_COMPARISON_GREATER;
4362 case QRhiGraphicsPipeline::NotEqual:
4363 return D3D11_COMPARISON_NOT_EQUAL;
4364 case QRhiGraphicsPipeline::GreaterOrEqual:
4365 return D3D11_COMPARISON_GREATER_EQUAL;
4366 case QRhiGraphicsPipeline::Always:
4367 return D3D11_COMPARISON_ALWAYS;
4370 return D3D11_COMPARISON_ALWAYS;
4377 case QRhiGraphicsPipeline::StencilZero:
4378 return D3D11_STENCIL_OP_ZERO;
4379 case QRhiGraphicsPipeline::Keep:
4380 return D3D11_STENCIL_OP_KEEP;
4381 case QRhiGraphicsPipeline::Replace:
4382 return D3D11_STENCIL_OP_REPLACE;
4383 case QRhiGraphicsPipeline::IncrementAndClamp:
4384 return D3D11_STENCIL_OP_INCR_SAT;
4385 case QRhiGraphicsPipeline::DecrementAndClamp:
4386 return D3D11_STENCIL_OP_DECR_SAT;
4387 case QRhiGraphicsPipeline::Invert:
4388 return D3D11_STENCIL_OP_INVERT;
4389 case QRhiGraphicsPipeline::IncrementAndWrap:
4390 return D3D11_STENCIL_OP_INCR;
4391 case QRhiGraphicsPipeline::DecrementAndWrap:
4392 return D3D11_STENCIL_OP_DECR;
4395 return D3D11_STENCIL_OP_KEEP;
4402 case QRhiVertexInputAttribute::Float4:
4403 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4404 case QRhiVertexInputAttribute::Float3:
4405 return DXGI_FORMAT_R32G32B32_FLOAT;
4406 case QRhiVertexInputAttribute::Float2:
4407 return DXGI_FORMAT_R32G32_FLOAT;
4408 case QRhiVertexInputAttribute::Float:
4409 return DXGI_FORMAT_R32_FLOAT;
4410 case QRhiVertexInputAttribute::UNormByte4:
4411 return DXGI_FORMAT_R8G8B8A8_UNORM;
4412 case QRhiVertexInputAttribute::UNormByte2:
4413 return DXGI_FORMAT_R8G8_UNORM;
4414 case QRhiVertexInputAttribute::UNormByte:
4415 return DXGI_FORMAT_R8_UNORM;
4416 case QRhiVertexInputAttribute::UInt4:
4417 return DXGI_FORMAT_R32G32B32A32_UINT;
4418 case QRhiVertexInputAttribute::UInt3:
4419 return DXGI_FORMAT_R32G32B32_UINT;
4420 case QRhiVertexInputAttribute::UInt2:
4421 return DXGI_FORMAT_R32G32_UINT;
4422 case QRhiVertexInputAttribute::UInt:
4423 return DXGI_FORMAT_R32_UINT;
4424 case QRhiVertexInputAttribute::SInt4:
4425 return DXGI_FORMAT_R32G32B32A32_SINT;
4426 case QRhiVertexInputAttribute::SInt3:
4427 return DXGI_FORMAT_R32G32B32_SINT;
4428 case QRhiVertexInputAttribute::SInt2:
4429 return DXGI_FORMAT_R32G32_SINT;
4430 case QRhiVertexInputAttribute::SInt:
4431 return DXGI_FORMAT_R32_SINT;
4432 case QRhiVertexInputAttribute::Half4:
4434 case QRhiVertexInputAttribute::Half3:
4435 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4436 case QRhiVertexInputAttribute::Half2:
4437 return DXGI_FORMAT_R16G16_FLOAT;
4438 case QRhiVertexInputAttribute::Half:
4439 return DXGI_FORMAT_R16_FLOAT;
4440 case QRhiVertexInputAttribute::UShort4:
4442 case QRhiVertexInputAttribute::UShort3:
4443 return DXGI_FORMAT_R16G16B16A16_UINT;
4444 case QRhiVertexInputAttribute::UShort2:
4445 return DXGI_FORMAT_R16G16_UINT;
4446 case QRhiVertexInputAttribute::UShort:
4447 return DXGI_FORMAT_R16_UINT;
4448 case QRhiVertexInputAttribute::SShort4:
4450 case QRhiVertexInputAttribute::SShort3:
4451 return DXGI_FORMAT_R16G16B16A16_SINT;
4452 case QRhiVertexInputAttribute::SShort2:
4453 return DXGI_FORMAT_R16G16_SINT;
4454 case QRhiVertexInputAttribute::SShort:
4455 return DXGI_FORMAT_R16_SINT;
4458 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4465 case QRhiGraphicsPipeline::Triangles:
4466 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4467 case QRhiGraphicsPipeline::TriangleStrip:
4468 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4469 case QRhiGraphicsPipeline::Lines:
4470 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4471 case QRhiGraphicsPipeline::LineStrip:
4472 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4473 case QRhiGraphicsPipeline::Points:
4474 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4475 case QRhiGraphicsPipeline::Patches:
4476 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4477 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4480 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4487 if (c.testFlag(QRhiGraphicsPipeline::R))
4488 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4489 if (c.testFlag(QRhiGraphicsPipeline::G))
4490 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4491 if (c.testFlag(QRhiGraphicsPipeline::B))
4492 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4493 if (c.testFlag(QRhiGraphicsPipeline::A))
4494 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4507 case QRhiGraphicsPipeline::Zero:
4508 return D3D11_BLEND_ZERO;
4509 case QRhiGraphicsPipeline::One:
4510 return D3D11_BLEND_ONE;
4511 case QRhiGraphicsPipeline::SrcColor:
4512 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4513 case QRhiGraphicsPipeline::OneMinusSrcColor:
4514 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4515 case QRhiGraphicsPipeline::DstColor:
4516 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4517 case QRhiGraphicsPipeline::OneMinusDstColor:
4518 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4519 case QRhiGraphicsPipeline::SrcAlpha:
4520 return D3D11_BLEND_SRC_ALPHA;
4521 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4522 return D3D11_BLEND_INV_SRC_ALPHA;
4523 case QRhiGraphicsPipeline::DstAlpha:
4524 return D3D11_BLEND_DEST_ALPHA;
4525 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4526 return D3D11_BLEND_INV_DEST_ALPHA;
4527 case QRhiGraphicsPipeline::ConstantColor:
4528 case QRhiGraphicsPipeline::ConstantAlpha:
4529 return D3D11_BLEND_BLEND_FACTOR;
4530 case QRhiGraphicsPipeline::OneMinusConstantColor:
4531 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4532 return D3D11_BLEND_INV_BLEND_FACTOR;
4533 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4534 return D3D11_BLEND_SRC_ALPHA_SAT;
4535 case QRhiGraphicsPipeline::Src1Color:
4536 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4537 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4538 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4539 case QRhiGraphicsPipeline::Src1Alpha:
4540 return D3D11_BLEND_SRC1_ALPHA;
4541 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4542 return D3D11_BLEND_INV_SRC1_ALPHA;
4545 return D3D11_BLEND_ZERO;
4552 case QRhiGraphicsPipeline::Add:
4553 return D3D11_BLEND_OP_ADD;
4554 case QRhiGraphicsPipeline::Subtract:
4555 return D3D11_BLEND_OP_SUBTRACT;
4556 case QRhiGraphicsPipeline::ReverseSubtract:
4557 return D3D11_BLEND_OP_REV_SUBTRACT;
4558 case QRhiGraphicsPipeline::Min:
4559 return D3D11_BLEND_OP_MIN;
4560 case QRhiGraphicsPipeline::Max:
4561 return D3D11_BLEND_OP_MAX;
4564 return D3D11_BLEND_OP_ADD;
4571 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4572 keyBuilder.addData(source);
4573 return keyBuilder.result().toHex();
4576QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4577 QString *error, QShaderKey *usedShaderKey)
4579 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4580 QShaderCode dxbc = shader.shader(key);
4581 if (!dxbc.shader().isEmpty()) {
4583 *usedShaderKey = key;
4584 return dxbc.shader();
4587 key = { QShader::HlslShader, 50, shaderVariant };
4588 QShaderCode hlslSource = shader.shader(key);
4589 if (hlslSource.shader().isEmpty()) {
4590 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4591 return QByteArray();
4595 *usedShaderKey = key;
4598 switch (shader.stage()) {
4599 case QShader::VertexStage:
4602 case QShader::TessellationControlStage:
4605 case QShader::TessellationEvaluationStage:
4608 case QShader::GeometryStage:
4611 case QShader::FragmentStage:
4614 case QShader::ComputeStage:
4619 return QByteArray();
4623 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4624 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4625 cacheKey.target = target;
4626 cacheKey.entryPoint = hlslSource.entryPoint();
4627 cacheKey.compileFlags = flags;
4628 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4629 if (cacheIt != m_bytecodeCache.constEnd())
4630 return cacheIt.value();
4633 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4634 if (d3dCompile ==
nullptr) {
4635 qWarning(
"Unable to resolve function D3DCompile()");
4636 return QByteArray();
4639 ID3DBlob *bytecode =
nullptr;
4640 ID3DBlob *errors =
nullptr;
4641 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4642 nullptr,
nullptr,
nullptr,
4643 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4644 if (FAILED(hr) || !bytecode) {
4645 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4647 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4648 int(errors->GetBufferSize()));
4651 return QByteArray();
4655 result.resize(
int(bytecode->GetBufferSize()));
4656 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4657 bytecode->Release();
4659 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4660 m_bytecodeCache.insert(cacheKey, result);
4671 rhiD->pipelineCreationStart();
4672 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4675 D3D11_RASTERIZER_DESC rastDesc = {};
4676 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4677 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4678 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4679 rastDesc.DepthBias = m_depthBias;
4680 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4681 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4682 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4683 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4684 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4686 qWarning(
"Failed to create rasterizer state: %s",
4687 qPrintable(QSystemError::windowsComString(hr)));
4691 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4692 dsDesc.DepthEnable = m_depthTest;
4693 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4694 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4695 dsDesc.StencilEnable = m_stencilTest;
4696 if (m_stencilTest) {
4697 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4698 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4699 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4700 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4701 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4702 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4703 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4704 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4705 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4706 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4708 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4710 qWarning(
"Failed to create depth-stencil state: %s",
4711 qPrintable(QSystemError::windowsComString(hr)));
4715 D3D11_BLEND_DESC blendDesc = {};
4716 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4717 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4718 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4719 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4720 blend.BlendEnable = b.enable;
4721 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4722 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4723 blend.BlendOp = toD3DBlendOp(b.opColor);
4724 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4725 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4726 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4727 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4728 blendDesc.RenderTarget[i] = blend;
4730 if (m_targetBlends.isEmpty()) {
4731 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4732 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4733 blendDesc.RenderTarget[0] = blend;
4735 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4737 qWarning(
"Failed to create blend state: %s",
4738 qPrintable(QSystemError::windowsComString(hr)));
4742 QByteArray vsByteCode;
4743 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4744 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4745 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4746 switch (shaderStage.type()) {
4747 case QRhiShaderStage::Vertex:
4748 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4749 vs.shader->AddRef();
4750 vsByteCode = cacheIt->bytecode;
4751 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4753 case QRhiShaderStage::TessellationControl:
4754 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4755 hs.shader->AddRef();
4756 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4758 case QRhiShaderStage::TessellationEvaluation:
4759 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4760 ds.shader->AddRef();
4761 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4763 case QRhiShaderStage::Geometry:
4764 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4765 gs.shader->AddRef();
4766 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4768 case QRhiShaderStage::Fragment:
4769 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4770 fs.shader->AddRef();
4771 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4778 QShaderKey shaderKey;
4779 UINT compileFlags = 0;
4780 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4781 compileFlags |= D3DCOMPILE_DEBUG;
4783 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4784 &error, &shaderKey);
4785 if (bytecode.isEmpty()) {
4786 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4790 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4792 rhiD->clearShaderCache();
4795 switch (shaderStage.type()) {
4796 case QRhiShaderStage::Vertex:
4797 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4799 qWarning(
"Failed to create vertex shader: %s",
4800 qPrintable(QSystemError::windowsComString(hr)));
4803 vsByteCode = bytecode;
4804 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4805 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4806 vs.shader->AddRef();
4808 case QRhiShaderStage::TessellationControl:
4809 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4811 qWarning(
"Failed to create hull shader: %s",
4812 qPrintable(QSystemError::windowsComString(hr)));
4815 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4816 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4817 hs.shader->AddRef();
4819 case QRhiShaderStage::TessellationEvaluation:
4820 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4822 qWarning(
"Failed to create domain shader: %s",
4823 qPrintable(QSystemError::windowsComString(hr)));
4826 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4827 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4828 ds.shader->AddRef();
4830 case QRhiShaderStage::Geometry:
4831 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4833 qWarning(
"Failed to create geometry shader: %s",
4834 qPrintable(QSystemError::windowsComString(hr)));
4837 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4838 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4839 gs.shader->AddRef();
4841 case QRhiShaderStage::Fragment:
4842 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4844 qWarning(
"Failed to create pixel shader: %s",
4845 qPrintable(QSystemError::windowsComString(hr)));
4848 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4849 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4850 fs.shader->AddRef();
4858 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4860 if (!vsByteCode.isEmpty()) {
4861 QByteArrayList matrixSliceSemantics;
4862 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4863 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4866 D3D11_INPUT_ELEMENT_DESC desc = {};
4871 const int matrixSlice = it->matrixSlice();
4872 if (matrixSlice < 0) {
4873 desc.SemanticName =
"TEXCOORD";
4874 desc.SemanticIndex = UINT(it->location());
4878 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4879 matrixSliceSemantics.append(sem);
4880 desc.SemanticName = matrixSliceSemantics.last().constData();
4881 desc.SemanticIndex = UINT(matrixSlice);
4883 desc.Format = toD3DAttributeFormat(it->format());
4884 desc.InputSlot = UINT(it->binding());
4885 desc.AlignedByteOffset = it->offset();
4886 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4887 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4888 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4889 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4891 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4893 inputDescs.append(desc);
4895 if (!inputDescs.isEmpty()) {
4896 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4897 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4899 qWarning(
"Failed to create input layout: %s",
4900 qPrintable(QSystemError::windowsComString(hr)));
4906 rhiD->pipelineCreationEnd();
4908 rhiD->registerResource(
this);
4927 cs.shader->Release();
4928 cs.shader =
nullptr;
4929 cs.nativeResourceBindingMap.clear();
4933 rhiD->unregisterResource(
this);
4942 rhiD->pipelineCreationStart();
4944 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
4945 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4946 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
4947 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4950 QShaderKey shaderKey;
4951 UINT compileFlags = 0;
4952 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4953 compileFlags |= D3DCOMPILE_DEBUG;
4955 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
4956 &error, &shaderKey);
4957 if (bytecode.isEmpty()) {
4958 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
4962 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
4964 qWarning(
"Failed to create compute shader: %s",
4965 qPrintable(QSystemError::windowsComString(hr)));
4969 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
4971 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
4974 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
4977 cs.shader->AddRef();
4979 rhiD->pipelineCreationEnd();
4981 rhiD->registerResource(
this);
5006 D3D11_QUERY_DESC queryDesc = {};
5008 if (!disjointQuery[i]) {
5009 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5010 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5012 qWarning(
"Failed to create timestamp disjoint query: %s",
5013 qPrintable(QSystemError::windowsComString(hr)));
5017 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5018 for (
int j = 0; j < 2; ++j) {
5019 const int idx = 2 * i + j;
5021 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5023 qWarning(
"Failed to create timestamp query: %s",
5024 qPrintable(QSystemError::windowsComString(hr)));
5037 if (disjointQuery[i]) {
5038 disjointQuery[i]->Release();
5039 disjointQuery[i] =
nullptr;
5041 for (
int j = 0; j < 2; ++j) {
5044 query[idx]->Release();
5045 query[idx] =
nullptr;
5053 bool result =
false;
5057 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5058 ID3D11Query *tsStart = query[pairIndex * 2];
5059 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5060 quint64 timestamps[2];
5061 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5064 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5065 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5066 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5069 if (!dj.Disjoint && dj.Frequency) {
5070 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5071 *elapsedSec = elapsedMs / 1000.0;
5074 active[pairIndex] =
false;
5083 backBufferTex =
nullptr;
5084 backBufferRtv =
nullptr;
5086 msaaTex[i] =
nullptr;
5087 msaaRtv[i] =
nullptr;
5098 if (backBufferRtv) {
5099 backBufferRtv->Release();
5100 backBufferRtv =
nullptr;
5102 if (backBufferRtvRight) {
5103 backBufferRtvRight->Release();
5104 backBufferRtvRight =
nullptr;
5106 if (backBufferTex) {
5107 backBufferTex->Release();
5108 backBufferTex =
nullptr;
5112 msaaRtv[i]->Release();
5113 msaaRtv[i] =
nullptr;
5116 msaaTex[i]->Release();
5117 msaaTex[i] =
nullptr;
5129 timestamps.destroy();
5131 swapChain->Release();
5132 swapChain =
nullptr;
5135 dcompVisual->Release();
5136 dcompVisual =
nullptr;
5140 dcompTarget->Release();
5141 dcompTarget =
nullptr;
5144 if (frameLatencyWaitableObject) {
5145 CloseHandle(frameLatencyWaitableObject);
5146 frameLatencyWaitableObject =
nullptr;
5149 QDxgiVSyncService::instance()->unregisterWindow(window);
5153 rhiD->unregisterResource(
this);
5156 rhiD->context->Flush();
5172 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5178 return m_window->size() * m_window->devicePixelRatio();
5187 qWarning(
"Attempted to call isFormatSupported() without a window set");
5192 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5193 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5204 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5213 rhiD->registerResource(rpD,
false);
5218 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5220 D3D11_TEXTURE2D_DESC desc = {};
5221 desc.Width = UINT(size.width());
5222 desc.Height = UINT(size.height());
5225 desc.Format = format;
5226 desc.SampleDesc = sampleDesc;
5227 desc.Usage = D3D11_USAGE_DEFAULT;
5228 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5231 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5233 qWarning(
"Failed to create color buffer texture: %s",
5234 qPrintable(QSystemError::windowsComString(hr)));
5238 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5239 rtvDesc.Format = format;
5240 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5241 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5243 qWarning(
"Failed to create color buffer rtv: %s",
5244 qPrintable(QSystemError::windowsComString(hr)));
5258 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5259 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5260 return dcompDevice ?
true :
false;
5272 const bool needsRegistration = !window || window != m_window;
5273 const bool stereo = m_window->format().stereo();
5276 if (window && window != m_window)
5280 m_currentPixelSize = surfacePixelSize();
5281 pixelSize = m_currentPixelSize;
5283 if (pixelSize.isEmpty())
5286 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5291 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5294 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5296 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5297 qPrintable(QSystemError::windowsComString(hr)));
5300 if (dcompTarget && !dcompVisual) {
5301 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5303 qWarning(
"Failed to create DirectComposition visual: %s",
5304 qPrintable(QSystemError::windowsComString(hr)));
5309 if (
window->requestedFormat().alphaBufferSize() <= 0)
5310 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5311 "This may lead to problems.");
5314 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5321 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5322 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5326 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5327 && swapInterval != 0
5328 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5330 if (useFrameLatencyWaitableObject) {
5332 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5336 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5337 colorFormat = DEFAULT_FORMAT;
5338 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5340 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5341 if (m_format != SDR) {
5342 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5345 case HDRExtendedSrgbLinear:
5346 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5347 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5348 srgbAdjustedColorFormat = colorFormat;
5351 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5352 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5353 srgbAdjustedColorFormat = colorFormat;
5362 qWarning(
"The output associated with the window is not HDR capable "
5363 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5373 DXGI_SWAP_CHAIN_DESC1 desc = {};
5374 desc.Width = UINT(pixelSize.width());
5375 desc.Height = UINT(pixelSize.height());
5376 desc.Format = colorFormat;
5377 desc.SampleDesc.Count = 1;
5378 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5380 desc.Flags = swapChainFlags;
5381 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5382 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5383 desc.Stereo = stereo;
5389 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5394 desc.Scaling = DXGI_SCALING_STRETCH;
5397 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5398 IDXGISwapChain1 *sc1;
5401 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5403 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5408 if (FAILED(hr) && m_format != SDR) {
5409 colorFormat = DEFAULT_FORMAT;
5410 desc.Format = DEFAULT_FORMAT;
5412 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5414 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5417 if (SUCCEEDED(hr)) {
5419 IDXGISwapChain3 *sc3 =
nullptr;
5420 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5421 if (m_format != SDR) {
5422 hr = sc3->SetColorSpace1(hdrColorSpace);
5424 qWarning(
"Failed to set color space on swapchain: %s",
5425 qPrintable(QSystemError::windowsComString(hr)));
5427 if (useFrameLatencyWaitableObject) {
5428 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5429 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5433 if (m_format != SDR)
5434 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5435 if (useFrameLatencyWaitableObject) {
5436 IDXGISwapChain2 *sc2 =
nullptr;
5437 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5438 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5439 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5442 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5447 hr = dcompVisual->SetContent(sc1);
5448 if (SUCCEEDED(hr)) {
5449 hr = dcompTarget->SetRoot(dcompVisual);
5451 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5452 qPrintable(QSystemError::windowsComString(hr)));
5455 qWarning(
"Failed to set content for Direct Composition visual: %s",
5456 qPrintable(QSystemError::windowsComString(hr)));
5460 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5464 qWarning(
"Failed to create D3D11 swapchain: %s"
5465 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5466 qPrintable(QSystemError::windowsComString(hr)),
5467 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5468 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5474 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5475 colorFormat, swapChainFlags);
5476 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5477 qWarning(
"Device loss detected in ResizeBuffers()");
5480 }
else if (FAILED(hr)) {
5481 qWarning(
"Failed to resize D3D11 swapchain: %s",
5482 qPrintable(QSystemError::windowsComString(hr)));
5501 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5503 qWarning(
"Failed to query swapchain backbuffer: %s",
5504 qPrintable(QSystemError::windowsComString(hr)));
5507 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5508 rtvDesc.Format = srgbAdjustedColorFormat;
5509 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5510 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5512 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5513 qPrintable(QSystemError::windowsComString(hr)));
5519 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5520 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5521 rtvDesc.Texture2DArray.ArraySize = 1;
5522 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5524 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5525 qPrintable(QSystemError::windowsComString(hr)));
5532 if (sampleDesc.Count > 1) {
5533 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5538 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5539 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5540 m_depthStencil->sampleCount(), m_sampleCount);
5542 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5543 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5544 m_depthStencil->setPixelSize(pixelSize);
5545 if (!m_depthStencil->create())
5546 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5547 pixelSize.width(), pixelSize.height());
5549 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5550 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5551 pixelSize.width(), pixelSize.height());
5558 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5560 rt.setRenderPassDescriptor(m_renderPassDesc);
5562 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5563 rtD->d.pixelSize = pixelSize;
5564 rtD->d.dpr =
float(
window->devicePixelRatio());
5565 rtD->d.sampleCount =
int(sampleDesc.Count);
5566 rtD->d.colorAttCount = 1;
5567 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5570 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5571 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5572 rtD->d.pixelSize = pixelSize;
5573 rtD->d.dpr =
float(
window->devicePixelRatio());
5574 rtD->d.sampleCount =
int(sampleDesc.Count);
5575 rtD->d.colorAttCount = 1;
5576 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5577 rtD->d.rtv[0] = backBufferRtvRight;
5578 rtD->d.dsv =
ds ?
ds->dsv :
nullptr;
5581 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5582 timestamps.prepare(rhiD);
5586 QDxgiVSyncService::instance()->registerWindow(window);
5588 if (needsRegistration)
5589 rhiD->registerResource(
this);
5597 if (dsv != data->dsv) {
5602 ret |= rtv[i] != data->rtv[i];
5603 rtv[i] = data->rtv[i];
5606 ret |= rtv[i] !=
nullptr;
5609 for (
int i = 0; i < count; i++) {
5610 ret |= uav[i] != uavs[i];
5614 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
const char * constData() const
int gsHighestActiveSrvBinding
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int dsHighestActiveSrvBinding
bool isYUpInNDC() const 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)
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
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
QRhiGraphicsPipeline * createGraphicsPipeline() 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
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
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
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
void resetShaderResources(QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState)
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
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 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
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 std::pair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
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 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 DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
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.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiBuffer::NativeBuffer nativeBuffer() override
ID3D11UnorderedAccessView * unorderedAccessView(quint32 offset)
QD3D11RenderTargetData * prevRtD
static const int MAX_DYNAMIC_OFFSET_COUNT
static const int MAX_VERTEX_BUFFER_BINDING_COUNT
int retainResourceBatches(const QD3D11ShaderResourceBindings::ResourceBatches &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
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
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
bool update(QD3D11RenderTargetData *data, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)