9#include <QtCore/qcryptographichash.h>
10#include <QtCore/private/qsystemerror_p.h>
17using namespace Qt::StringLiterals;
20
21
22
23
24
25
26
27
31
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
77
78
79
80
81
85
86
87
88
89
90
91
92
93
94
95
96
99
100
101
102
103
104
105
106
109
110
111
112
113
114
115
118
119
120
121
122
123
124
125
128
129
130
131
132
133
136
137
138
139
140
141
144#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
145#define DXGI_ADAPTER_FLAG_SOFTWARE 2
148#ifndef D3D11_1_UAV_SLOT_COUNT
149#define D3D11_1_UAV_SLOT_COUNT 64
152#ifndef D3D11_VS_INPUT_REGISTER_COUNT
153#define D3D11_VS_INPUT_REGISTER_COUNT 32
162 if (importParams->dev && importParams->context) {
163 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
164 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
165 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
170 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
173 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
174 adapterLuid.LowPart = importParams->adapterLuidLow;
175 adapterLuid.HighPart = importParams->adapterLuidHigh;
182 return (v + byteAlign - 1) & ~(byteAlign - 1);
187 IDXGIFactory1 *result =
nullptr;
188 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
190 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
191 qPrintable(QSystemError::windowsComString(hr)));
203 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
205 dxgiFactory = createDXGIFactory2();
213 IDXGIFactory5 *factory5 =
nullptr;
214 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
215 BOOL allowTearing =
false;
216 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
221 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
222 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
230 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
231 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
236 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
237 supportsAllowTearing ?
"true" :
"false",
238 useLegacySwapchainModel ?
"true" :
"false",
240 if (maxFrameLatency == 0)
241 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
243 activeAdapter =
nullptr;
246 IDXGIAdapter1 *adapter;
247 int requestedAdapterIndex = -1;
248 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
249 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
251 if (requestedRhiAdapter)
252 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
255 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
256 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
257 DXGI_ADAPTER_DESC1 desc;
258 adapter->GetDesc1(&desc);
260 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
261 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
263 requestedAdapterIndex = adapterIndex;
269 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
270 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
271 DXGI_ADAPTER_DESC1 desc;
272 adapter->GetDesc1(&desc);
275 requestedAdapterIndex = adapterIndex;
281 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
282 DXGI_ADAPTER_DESC1 desc;
283 adapter->GetDesc1(&desc);
284 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
285 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
291 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
292 activeAdapter = adapter;
293 adapterLuid = desc.AdapterLuid;
294 QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
295 qCDebug(QRHI_LOG_INFO,
" using this adapter");
300 if (!activeAdapter) {
301 qWarning(
"No adapter");
307 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
308 bool requestFeatureLevels =
false;
310 requestFeatureLevels =
true;
311 requestedFeatureLevels.append(featureLevel);
314 ID3D11DeviceContext *ctx =
nullptr;
315 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
316 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
317 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
319 &dev, &featureLevel, &ctx);
321 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
322 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
323 "Attempting to create D3D11 device without it.");
324 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
325 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
326 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
327 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
329 &dev, &featureLevel, &ctx);
332 qWarning(
"Failed to create D3D11 device and context: %s",
333 qPrintable(QSystemError::windowsComString(hr)));
337 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
340 qWarning(
"ID3D11DeviceContext1 not supported");
346 ID3D11VertexShader *testShader =
nullptr;
347 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
348 testShader->Release();
350 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
351 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
352 qCDebug(QRHI_LOG_INFO,
"%s", msg);
358 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
359 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
363 if (!features.ConstantBufferOffsetting) {
364 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
365 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
366 qCDebug(QRHI_LOG_INFO,
"%s", msg);
372 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
373 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
374 qCDebug(QRHI_LOG_INFO,
"%s", msg);
380 Q_ASSERT(dev && context);
381 featureLevel = dev->GetFeatureLevel();
382 IDXGIDevice *dxgiDev =
nullptr;
383 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
384 IDXGIAdapter *adapter =
nullptr;
385 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
386 IDXGIAdapter1 *adapter1 =
nullptr;
387 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
388 DXGI_ADAPTER_DESC1 desc;
389 adapter1->GetDesc1(&desc);
390 adapterLuid = desc.AdapterLuid;
391 QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
392 activeAdapter = adapter1;
398 if (!activeAdapter) {
399 qWarning(
"Failed to query adapter from imported device");
402 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
405 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
407 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
408 annotations =
nullptr;
412 nativeHandlesStruct.dev = dev;
413 nativeHandlesStruct.context = context;
414 nativeHandlesStruct.featureLevel = featureLevel;
415 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
416 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
423 for (Shader &s : m_shaderCache)
426 m_shaderCache.clear();
435 if (ofr.tsDisjointQuery) {
436 ofr.tsDisjointQuery->Release();
437 ofr.tsDisjointQuery =
nullptr;
439 for (
int i = 0; i < 2; ++i) {
440 if (ofr.tsQueries[i]) {
441 ofr.tsQueries[i]->Release();
442 ofr.tsQueries[i] =
nullptr;
447 annotations->Release();
448 annotations =
nullptr;
463 dcompDevice->Release();
464 dcompDevice =
nullptr;
468 activeAdapter->Release();
469 activeAdapter =
nullptr;
473 dxgiFactory->Release();
474 dxgiFactory =
nullptr;
480 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
487 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
488 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
493QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
495 LUID requestedLuid = {};
497 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
498 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
499 if (adapterLuid.LowPart || adapterLuid.HighPart)
500 requestedLuid = adapterLuid;
503 IDXGIFactory1 *dxgi = createDXGIFactory2();
507 QRhi::AdapterList list;
508 IDXGIAdapter1 *adapter;
509 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
510 DXGI_ADAPTER_DESC1 desc;
511 adapter->GetDesc1(&desc);
513 if (requestedLuid.LowPart || requestedLuid.HighPart) {
514 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
515 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
520 QD3D11Adapter *a =
new QD3D11Adapter;
521 a->luid = desc.AdapterLuid;
522 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
537 return { 1, 2, 4, 8 };
542 Q_UNUSED(sampleCount);
543 return { QSize(1, 1) };
548 DXGI_SAMPLE_DESC desc;
552 const int s = effectiveSampleCount(sampleCount);
554 desc.Count = UINT(s);
556 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
565 return new QD3D11SwapChain(
this);
568QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
570 return new QD3D11Buffer(
this, type, usage, size);
598 if (m.isIdentity()) {
600 m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
601 0.0f, 1.0f, 0.0f, 0.0f,
602 0.0f, 0.0f, 0.5f, 0.5f,
603 0.0f, 0.0f, 0.0f, 1.0f);
612 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
621 case QRhi::MultisampleTexture:
623 case QRhi::MultisampleRenderBuffer:
625 case QRhi::DebugMarkers:
626 return annotations !=
nullptr;
627 case QRhi::Timestamps:
629 case QRhi::Instancing:
631 case QRhi::CustomInstanceStepRate:
633 case QRhi::PrimitiveRestart:
635 case QRhi::NonDynamicUniformBuffers:
637 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
639 case QRhi::NPOTTextureRepeat:
641 case QRhi::RedOrAlpha8IsRed:
643 case QRhi::ElementIndexUint:
647 case QRhi::WideLines:
649 case QRhi::VertexShaderPointSize:
651 case QRhi::BaseVertex:
653 case QRhi::BaseInstance:
655 case QRhi::TriangleFanTopology:
657 case QRhi::ReadBackNonUniformBuffer:
659 case QRhi::ReadBackNonBaseMipLevel:
661 case QRhi::TexelFetch:
663 case QRhi::RenderToNonBaseMipLevel:
665 case QRhi::IntAttributes:
667 case QRhi::ScreenSpaceDerivatives:
669 case QRhi::ReadBackAnyTextureFormat:
671 case QRhi::PipelineCacheDataLoadSave:
673 case QRhi::ImageDataStride:
675 case QRhi::RenderBufferImport:
677 case QRhi::ThreeDimensionalTextures:
679 case QRhi::RenderTo3DTextureSlice:
681 case QRhi::TextureArrays:
683 case QRhi::Tessellation:
685 case QRhi::GeometryShader:
687 case QRhi::TextureArrayRange:
689 case QRhi::NonFillPolygonMode:
691 case QRhi::OneDimensionalTextures:
693 case QRhi::OneDimensionalTextureMipmaps:
695 case QRhi::HalfAttributes:
697 case QRhi::RenderToOneDimensionalTexture:
699 case QRhi::ThreeDimensionalTextureMipmaps:
701 case QRhi::MultiView:
703 case QRhi::TextureViewFormat:
705 case QRhi::ResolveDepthStencil:
707 case QRhi::VariableRateShading:
709 case QRhi::VariableRateShadingMap:
710 case QRhi::VariableRateShadingMapWithTexture:
712 case QRhi::PerRenderTargetBlending:
713 case QRhi::SampleVariables:
715 case QRhi::InstanceIndexIncludesBaseInstance:
726 case QRhi::TextureSizeMin:
728 case QRhi::TextureSizeMax:
729 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
730 case QRhi::MaxColorAttachments:
732 case QRhi::FramesInFlight:
738 case QRhi::MaxAsyncReadbackFrames:
740 case QRhi::MaxThreadGroupsPerDimension:
741 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
742 case QRhi::MaxThreadsPerThreadGroup:
743 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
744 case QRhi::MaxThreadGroupX:
745 return D3D11_CS_THREAD_GROUP_MAX_X;
746 case QRhi::MaxThreadGroupY:
747 return D3D11_CS_THREAD_GROUP_MAX_Y;
748 case QRhi::MaxThreadGroupZ:
749 return D3D11_CS_THREAD_GROUP_MAX_Z;
750 case QRhi::TextureArraySizeMax:
751 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
752 case QRhi::MaxUniformBufferRange:
754 case QRhi::MaxVertexInputs:
756 case QRhi::MaxVertexOutputs:
757 return D3D11_VS_OUTPUT_REGISTER_COUNT;
758 case QRhi::ShadingRateImageTileSize:
768 return &nativeHandlesStruct;
773 return driverInfoStruct;
779 result.totalPipelineCreationTime = totalPipelineCreationTime();
789void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
797 m_bytecodeCache.clear();
817 if (m_bytecodeCache.isEmpty())
821 memset(&header, 0,
sizeof(header));
822 header.rhiId = pipelineCacheRhiId();
823 header.arch = quint32(
sizeof(
void*));
824 header.count = m_bytecodeCache.count();
826 const size_t dataOffset =
sizeof(header);
828 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
830 QByteArray bytecode = it.value();
832 sizeof(quint32) + key.sourceHash.size()
833 +
sizeof(quint32) + key.target.size()
834 +
sizeof(quint32) + key.entryPoint.size()
836 +
sizeof(quint32) + bytecode.size();
839 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
840 char *p = buf.data() + dataOffset;
841 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
843 QByteArray bytecode = it.value();
845 quint32 i = key.sourceHash.size();
848 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
849 p += key.sourceHash.size();
851 i = key.target.size();
854 memcpy(p, key.target.constData(), key.target.size());
855 p += key.target.size();
857 i = key.entryPoint.size();
860 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
861 p += key.entryPoint.size();
863 quint32 f = key.compileFlags;
870 memcpy(p, bytecode.constData(), bytecode.size());
871 p += bytecode.size();
873 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
875 header.dataSize = quint32(dataSize);
876 memcpy(buf.data(), &header,
sizeof(header));
887 if (data.size() < qsizetype(headerSize)) {
888 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
891 const size_t dataOffset = headerSize;
893 memcpy(&header, data.constData(), headerSize);
895 const quint32 rhiId = pipelineCacheRhiId();
896 if (header.rhiId != rhiId) {
897 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
898 rhiId, header.rhiId);
901 const quint32 arch = quint32(
sizeof(
void*));
902 if (header.arch != arch) {
903 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
907 if (header.count == 0)
910 if (data.size() < qsizetype(dataOffset + header.dataSize)) {
911 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
915 m_bytecodeCache.clear();
917 const char *p = data.constData() + dataOffset;
918 for (quint32 i = 0; i < header.count; ++i) {
922 QByteArray sourceHash(len, Qt::Uninitialized);
923 memcpy(sourceHash.data(), p, len);
928 QByteArray target(len, Qt::Uninitialized);
929 memcpy(target.data(), p, len);
934 QByteArray entryPoint(len, Qt::Uninitialized);
935 memcpy(entryPoint.data(), p, len);
939 memcpy(&flags, p, 4);
944 QByteArray bytecode(len, Qt::Uninitialized);
945 memcpy(bytecode.data(), p, len);
949 cacheKey.sourceHash = sourceHash;
950 cacheKey.target = target;
951 cacheKey.entryPoint = entryPoint;
952 cacheKey.compileFlags = flags;
954 m_bytecodeCache.insert(cacheKey, bytecode);
957 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
960QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
961 int sampleCount, QRhiRenderBuffer::Flags flags,
962 QRhiTexture::Format backingFormatHint)
964 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
968 const QSize &pixelSize,
int depth,
int arraySize,
969 int sampleCount, QRhiTexture::Flags flags)
971 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
975 QRhiSampler::Filter mipmapMode,
976 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
978 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
982 QRhiTextureRenderTarget::Flags flags)
994 return new QD3D11GraphicsPipeline(
this);
999 return new QD3D11ComputePipeline(
this);
1004 return new QD3D11ShaderResourceBindings(
this);
1012 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1014 if (pipelineChanged) {
1015 cbD->currentGraphicsPipeline = ps;
1016 cbD->currentComputePipeline =
nullptr;
1017 cbD->currentPipelineGeneration = psD->generation;
1021 cmd.args.bindGraphicsPipeline.ps = psD;
1034 int dynamicOffsetCount,
1035 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1044 srb = gfxPsD->m_shaderResourceBindings;
1046 srb = compPsD->m_shaderResourceBindings;
1051 bool pipelineChanged =
false;
1060 bool srbUpdate =
false;
1061 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1062 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1065 case QRhiShaderResourceBinding::UniformBuffer:
1069 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1073 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1075 bd.ubuf.id = bufD->m_id;
1076 bd.ubuf.generation = bufD->generation;
1080 case QRhiShaderResourceBinding::SampledTexture:
1081 case QRhiShaderResourceBinding::Texture:
1082 case QRhiShaderResourceBinding::Sampler:
1084 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1085 if (bd.stex.count != data->count) {
1086 bd.stex.count = data->count;
1089 for (
int elem = 0; elem < data->count; ++elem) {
1095 Q_ASSERT(texD || samplerD);
1096 const quint64 texId = texD ? texD->m_id : 0;
1097 const uint texGen = texD ? texD->generation : 0;
1098 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1099 const uint samplerGen = samplerD ? samplerD->generation : 0;
1100 if (texGen != bd.stex.d[elem].texGeneration
1101 || texId != bd.stex.d[elem].texId
1102 || samplerGen != bd.stex.d[elem].samplerGeneration
1103 || samplerId != bd.stex.d[elem].samplerId)
1106 bd.stex.d[elem].texId = texId;
1107 bd.stex.d[elem].texGeneration = texGen;
1108 bd.stex.d[elem].samplerId = samplerId;
1109 bd.stex.d[elem].samplerGeneration = samplerGen;
1114 case QRhiShaderResourceBinding::ImageLoad:
1115 case QRhiShaderResourceBinding::ImageStore:
1116 case QRhiShaderResourceBinding::ImageLoadStore:
1119 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1121 bd.simage.id = texD->m_id;
1122 bd.simage.generation = texD->generation;
1126 case QRhiShaderResourceBinding::BufferLoad:
1127 case QRhiShaderResourceBinding::BufferStore:
1128 case QRhiShaderResourceBinding::BufferLoadStore:
1131 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1133 bd.sbuf.id = bufD->m_id;
1134 bd.sbuf.generation = bufD->generation;
1144 if (srbUpdate || pipelineChanged) {
1146 memset(resBindMaps, 0,
sizeof(resBindMaps));
1148 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1149 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1150 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1151 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1152 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1154 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1156 updateShaderResourceBindings(srbD, resBindMaps);
1159 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1160 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1162 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1164 cbD->currentGraphicsSrb = srb;
1165 cbD->currentComputeSrb =
nullptr;
1167 cbD->currentGraphicsSrb =
nullptr;
1168 cbD->currentComputeSrb = srb;
1170 cbD->currentSrbGeneration = srbD->generation;
1177 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1178 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1181 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1182 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1183 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1184 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1185 const uint binding = uint(dynOfs.first);
1186 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1187 const quint32 offsetInConstants = dynOfs.second / 16;
1189 *p++ = offsetInConstants;
1192 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1200 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1201 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1206 bool needsBindVBuf =
false;
1207 for (
int i = 0; i < bindingCount; ++i) {
1208 const int inputSlot = startBinding + i;
1210 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1211 if (bufD->m_type == QRhiBuffer::Dynamic)
1214 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1215 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1217 needsBindVBuf =
true;
1218 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1219 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1223 if (needsBindVBuf) {
1226 cmd.args.bindVertexBuffers.startSlot = startBinding;
1228 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1232 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1234 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1235 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1236 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1238 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1239 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1240 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1246 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1247 if (ibufD->m_type == QRhiBuffer::Dynamic)
1250 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1251 : DXGI_FORMAT_R32_UINT;
1252 if (cbD->currentIndexBuffer != ibufD->buffer
1253 || cbD->currentIndexOffset != indexOffset
1254 || cbD->currentIndexFormat != dxgiFormat)
1256 cbD->currentIndexBuffer = ibufD->buffer;
1257 cbD->currentIndexOffset = indexOffset;
1258 cbD->currentIndexFormat = dxgiFormat;
1262 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1263 cmd.args.bindIndexBuffer.offset = indexOffset;
1264 cmd.args.bindIndexBuffer.format = dxgiFormat;
1273 Q_ASSERT(cbD->currentTarget);
1274 const QSize outputSize = cbD->currentTarget->pixelSize();
1278 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1283 cmd.args.viewport.x = x;
1284 cmd.args.viewport.y = y;
1285 cmd.args.viewport.w = w;
1286 cmd.args.viewport.h = h;
1287 cmd.args.viewport.d0 = viewport.minDepth();
1288 cmd.args.viewport.d1 = viewport.maxDepth();
1295 Q_ASSERT(cbD->currentTarget);
1296 const QSize outputSize = cbD->currentTarget->pixelSize();
1300 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1305 cmd.args.scissor.x = x;
1306 cmd.args.scissor.y = y;
1307 cmd.args.scissor.w = w;
1308 cmd.args.scissor.h = h;
1319 cmd.args.blendConstants.c[0] =
float(c.redF());
1320 cmd.args.blendConstants.c[1] =
float(c.greenF());
1321 cmd.args.blendConstants.c[2] =
float(c.blueF());
1322 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1333 cmd.args.stencilRef.ref = refValue;
1339 Q_UNUSED(coarsePixelSize);
1343 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1351 cmd.args.draw.vertexCount = vertexCount;
1352 cmd.args.draw.instanceCount = instanceCount;
1353 cmd.args.draw.firstVertex = firstVertex;
1354 cmd.args.draw.firstInstance = firstInstance;
1358 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1366 cmd.args.drawIndexed.indexCount = indexCount;
1367 cmd.args.drawIndexed.instanceCount = instanceCount;
1368 cmd.args.drawIndexed.firstIndex = firstIndex;
1369 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1370 cmd.args.drawIndexed.firstInstance = firstInstance;
1375 if (!debugMarkers || !annotations)
1381 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1386 if (!debugMarkers || !annotations)
1396 if (!debugMarkers || !annotations)
1402 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1421 Q_ASSERT(cbD->commands.isEmpty());
1423 if (cbD->currentTarget) {
1426 fbCmd.args.setRenderTarget.rt = cbD->currentTarget;
1438 switch (rt->resourceType()) {
1439 case QRhiResource::SwapChainRenderTarget:
1440 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1441 case QRhiResource::TextureRenderTarget:
1442 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1458 if (swapChainD->frameLatencyWaitableObject) {
1461 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1466 swapChainD->cb.resetState();
1468 swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
1469 swapChainD->msaaRtv[currentFrameSlot] : swapChainD->backBufferRtv;
1470 swapChainD->rt.d.dsv = swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr;
1475 double elapsedSec = 0;
1476 if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, context, &elapsedSec))
1477 swapChainD->cb.lastGpuTime = elapsedSec;
1486 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1487 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1488 cmd.args.beginFrame.swapchainData =
rtData(&swapChainD->rt
);
1490 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1492 return QRhi::FrameOpSuccess;
1503 cmd.args.endFrame.tsQuery =
nullptr;
1504 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1509 if (swapChainD->sampleDesc.Count > 1) {
1510 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1511 swapChainD->msaaTex[currentFrameSlot], 0,
1512 swapChainD->colorFormat);
1519 if (recordTimestamps) {
1520 context->End(tsEnd);
1521 context->End(tsDisjoint);
1526 if (!flags.testFlag(QRhi::SkipPresent)) {
1527 UINT presentFlags = 0;
1528 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1529 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1530 if (!swapChainD->swapChain) {
1531 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1532 return QRhi::FrameOpError;
1534 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1535 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1536 qWarning(
"Device loss detected in Present()");
1538 return QRhi::FrameOpDeviceLost;
1539 }
else if (FAILED(hr)) {
1540 qWarning(
"Failed to present: %s",
1541 qPrintable(QSystemError::windowsComString(hr)));
1542 return QRhi::FrameOpError;
1545 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1546 dcompDevice->Commit();
1557 return QRhi::FrameOpSuccess;
1565 ofr.cbWrapper.resetState();
1566 *cb = &ofr.cbWrapper;
1568 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1569 D3D11_QUERY_DESC queryDesc = {};
1570 if (!ofr.tsDisjointQuery) {
1571 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1572 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1574 qWarning(
"Failed to create timestamp disjoint query: %s",
1575 qPrintable(QSystemError::windowsComString(hr)));
1576 return QRhi::FrameOpError;
1579 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1580 for (
int i = 0; i < 2; ++i) {
1581 if (!ofr.tsQueries[i]) {
1582 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1584 qWarning(
"Failed to create timestamp query: %s",
1585 qPrintable(QSystemError::windowsComString(hr)));
1586 return QRhi::FrameOpError;
1594 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1595 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1596 cmd.args.beginFrame.swapchainData =
nullptr;
1598 return QRhi::FrameOpSuccess;
1608 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1609 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1611 executeCommandBuffer(&ofr.cbWrapper);
1616 if (ofr.tsQueries[0]) {
1617 quint64 timestamps[2];
1618 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1622 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1623 }
while (hr == S_FALSE);
1626 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1627 }
while (hr == S_FALSE);
1630 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1631 }
while (hr == S_FALSE);
1634 if (!dj.Disjoint && dj.Frequency) {
1635 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1636 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1641 return QRhi::FrameOpSuccess;
1646 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1648 case QRhiTexture::RGBA8:
1649 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1650 case QRhiTexture::BGRA8:
1651 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1652 case QRhiTexture::R8:
1653 return DXGI_FORMAT_R8_UNORM;
1654 case QRhiTexture::R8SI:
1655 return DXGI_FORMAT_R8_SINT;
1656 case QRhiTexture::R8UI:
1657 return DXGI_FORMAT_R8_UINT;
1658 case QRhiTexture::RG8:
1659 return DXGI_FORMAT_R8G8_UNORM;
1660 case QRhiTexture::R16:
1661 return DXGI_FORMAT_R16_UNORM;
1662 case QRhiTexture::RG16:
1663 return DXGI_FORMAT_R16G16_UNORM;
1664 case QRhiTexture::RED_OR_ALPHA8:
1665 return DXGI_FORMAT_R8_UNORM;
1667 case QRhiTexture::RGBA16F:
1668 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1669 case QRhiTexture::RGBA32F:
1670 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1671 case QRhiTexture::R16F:
1672 return DXGI_FORMAT_R16_FLOAT;
1673 case QRhiTexture::R32F:
1674 return DXGI_FORMAT_R32_FLOAT;
1676 case QRhiTexture::RGB10A2:
1677 return DXGI_FORMAT_R10G10B10A2_UNORM;
1679 case QRhiTexture::R32SI:
1680 return DXGI_FORMAT_R32_SINT;
1681 case QRhiTexture::R32UI:
1682 return DXGI_FORMAT_R32_UINT;
1683 case QRhiTexture::RG32SI:
1684 return DXGI_FORMAT_R32G32_SINT;
1685 case QRhiTexture::RG32UI:
1686 return DXGI_FORMAT_R32G32_UINT;
1687 case QRhiTexture::RGBA32SI:
1688 return DXGI_FORMAT_R32G32B32A32_SINT;
1689 case QRhiTexture::RGBA32UI:
1690 return DXGI_FORMAT_R32G32B32A32_UINT;
1692 case QRhiTexture::D16:
1693 return DXGI_FORMAT_R16_TYPELESS;
1694 case QRhiTexture::D24:
1695 return DXGI_FORMAT_R24G8_TYPELESS;
1696 case QRhiTexture::D24S8:
1697 return DXGI_FORMAT_R24G8_TYPELESS;
1698 case QRhiTexture::D32F:
1699 return DXGI_FORMAT_R32_TYPELESS;
1700 case QRhiTexture::D32FS8:
1701 return DXGI_FORMAT_R32G8X24_TYPELESS;
1703 case QRhiTexture::BC1:
1704 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1705 case QRhiTexture::BC2:
1706 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1707 case QRhiTexture::BC3:
1708 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1709 case QRhiTexture::BC4:
1710 return DXGI_FORMAT_BC4_UNORM;
1711 case QRhiTexture::BC5:
1712 return DXGI_FORMAT_BC5_UNORM;
1713 case QRhiTexture::BC6H:
1714 return DXGI_FORMAT_BC6H_UF16;
1715 case QRhiTexture::BC7:
1716 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1718 case QRhiTexture::ETC2_RGB8:
1719 case QRhiTexture::ETC2_RGB8A1:
1720 case QRhiTexture::ETC2_RGBA8:
1721 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1722 return DXGI_FORMAT_R8G8B8A8_UNORM;
1724 case QRhiTexture::ASTC_4x4:
1725 case QRhiTexture::ASTC_5x4:
1726 case QRhiTexture::ASTC_5x5:
1727 case QRhiTexture::ASTC_6x5:
1728 case QRhiTexture::ASTC_6x6:
1729 case QRhiTexture::ASTC_8x5:
1730 case QRhiTexture::ASTC_8x6:
1731 case QRhiTexture::ASTC_8x8:
1732 case QRhiTexture::ASTC_10x5:
1733 case QRhiTexture::ASTC_10x6:
1734 case QRhiTexture::ASTC_10x8:
1735 case QRhiTexture::ASTC_10x10:
1736 case QRhiTexture::ASTC_12x10:
1737 case QRhiTexture::ASTC_12x12:
1738 qWarning(
"QRhiD3D11 does not support ASTC textures");
1739 return DXGI_FORMAT_R8G8B8A8_UNORM;
1743 return DXGI_FORMAT_R8G8B8A8_UNORM;
1750 case DXGI_FORMAT_R8G8B8A8_UNORM:
1751 return QRhiTexture::RGBA8;
1752 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1754 (*flags) |= QRhiTexture::sRGB;
1755 return QRhiTexture::RGBA8;
1756 case DXGI_FORMAT_B8G8R8A8_UNORM:
1757 return QRhiTexture::BGRA8;
1758 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1760 (*flags) |= QRhiTexture::sRGB;
1761 return QRhiTexture::BGRA8;
1762 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1763 return QRhiTexture::RGBA16F;
1764 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1765 return QRhiTexture::RGBA32F;
1766 case DXGI_FORMAT_R10G10B10A2_UNORM:
1767 return QRhiTexture::RGB10A2;
1769 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1772 return QRhiTexture::UnknownFormat;
1778 case QRhiTexture::Format::D16:
1779 case QRhiTexture::Format::D24:
1780 case QRhiTexture::Format::D24S8:
1781 case QRhiTexture::Format::D32F:
1782 case QRhiTexture::Format::D32FS8:
1795 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1796 executeCommandBuffer(&ofr.cbWrapper);
1797 ofr.cbWrapper.resetCommands();
1808 return QRhi::FrameOpSuccess;
1812 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1814 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1815 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1817 box.front = is3D ? UINT(layer) : 0u;
1819 box.back = box.front + 1;
1822 cmd.args.updateSubRes.dst = texD->textureResource();
1823 cmd.args.updateSubRes.dstSubRes = subres;
1825 const QPoint dp = subresDesc.destinationTopLeft();
1826 if (!subresDesc.image().isNull()) {
1827 QImage img = subresDesc.image();
1828 QSize size = img.size();
1829 int bpl = img.bytesPerLine();
1830 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1831 const QPoint sp = subresDesc.sourceTopLeft();
1832 if (!subresDesc.sourceSize().isEmpty())
1833 size = subresDesc.sourceSize();
1834 if (img.depth() == 32) {
1835 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1836 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1838 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1839 bpl = img.bytesPerLine();
1840 cmd.args.updateSubRes.src = cbD->retainImage(img);
1843 cmd.args.updateSubRes.src = cbD->retainImage(img);
1845 box.left = UINT(dp.x());
1846 box.top = UINT(dp.y());
1847 box.right = UINT(dp.x() + size.width());
1848 box.bottom = UINT(dp.y() + size.height());
1849 cmd.args.updateSubRes.hasDstBox =
true;
1850 cmd.args.updateSubRes.dstBox = box;
1851 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1852 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1853 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1854 : subresDesc.sourceSize();
1857 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1861 box.left = UINT(aligned(dp.x(), blockDim.width()));
1862 box.top = UINT(aligned(dp.y(), blockDim.height()));
1863 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1864 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1865 cmd.args.updateSubRes.hasDstBox =
true;
1866 cmd.args.updateSubRes.dstBox = box;
1867 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1868 cmd.args.updateSubRes.srcRowPitch = bpl;
1869 }
else if (!subresDesc.data().isEmpty()) {
1870 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1871 : subresDesc.sourceSize();
1873 if (subresDesc.dataStride())
1874 bpl = subresDesc.dataStride();
1876 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1877 box.left = UINT(dp.x());
1878 box.top = UINT(dp.y());
1879 box.right = UINT(dp.x() + size.width());
1880 box.bottom = UINT(dp.y() + size.height());
1881 cmd.args.updateSubRes.hasDstBox =
true;
1882 cmd.args.updateSubRes.dstBox = box;
1883 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1884 cmd.args.updateSubRes.srcRowPitch = bpl;
1886 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1887 cbD->commands.unget();
1900 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1905 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1906 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1909 cmd.args.updateSubRes.dst = bufD->buffer;
1910 cmd.args.updateSubRes.dstSubRes = 0;
1911 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1912 cmd.args.updateSubRes.srcRowPitch = 0;
1917 box.left = u.offset;
1918 box.top = box.front = 0;
1919 box.back = box.bottom = 1;
1920 box.right = u.offset + u
.data.size();
1921 cmd.args.updateSubRes.hasDstBox =
true;
1922 cmd.args.updateSubRes.dstBox = box;
1925 if (bufD->m_type == QRhiBuffer::Dynamic) {
1926 u.result->data.resize(u.readSize);
1927 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1928 if (u.result->completed)
1929 u.result->completed();
1932 readback.result = u.result;
1933 readback.byteSize = u.readSize;
1935 D3D11_BUFFER_DESC desc = {};
1936 desc.ByteWidth = readback.byteSize;
1937 desc.Usage = D3D11_USAGE_STAGING;
1938 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1939 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1941 qWarning(
"Failed to create buffer: %s",
1942 qPrintable(QSystemError::windowsComString(hr)));
1948 cmd.args.copySubRes.dst = readback.stagingBuf;
1949 cmd.args.copySubRes.dstSubRes = 0;
1950 cmd.args.copySubRes.dstX = 0;
1951 cmd.args.copySubRes.dstY = 0;
1952 cmd.args.copySubRes.dstZ = 0;
1953 cmd.args.copySubRes.src = bufD->buffer;
1954 cmd.args.copySubRes.srcSubRes = 0;
1955 cmd.args.copySubRes.hasSrcBox =
true;
1957 box.left = u.offset;
1958 box.top = box.front = 0;
1959 box.back = box.bottom = 1;
1960 box.right = u.offset + u.readSize;
1961 cmd.args.copySubRes.srcBox = box;
1963 activeBufferReadbacks.append(readback);
1971 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
1972 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
1973 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
1974 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
1981 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1982 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1983 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
1984 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
1985 const QPoint dp = u.desc.destinationTopLeft();
1986 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
1987 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
1988 const QPoint sp = u.desc.sourceTopLeft();
1990 srcBox.left = UINT(sp.x());
1991 srcBox.top = UINT(sp.y());
1992 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
1994 srcBox.right = srcBox.left + UINT(copySize.width());
1995 srcBox.bottom = srcBox.top + UINT(copySize.height());
1996 srcBox.back = srcBox.front + 1;
1999 cmd.args.copySubRes.dst = dstD->textureResource();
2000 cmd.args.copySubRes.dstSubRes = dstSubRes;
2001 cmd.args.copySubRes.dstX = UINT(dp.x());
2002 cmd.args.copySubRes.dstY = UINT(dp.y());
2003 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2004 cmd.args.copySubRes.src = srcD->textureResource();
2005 cmd.args.copySubRes.srcSubRes = srcSubRes;
2006 cmd.args.copySubRes.hasSrcBox =
true;
2007 cmd.args.copySubRes.srcBox = srcBox;
2010 readback.desc = u.rb;
2011 readback.result = u.result;
2013 ID3D11Resource *src;
2014 DXGI_FORMAT dxgiFormat;
2016 QRhiTexture::Format format;
2023 if (texD->sampleDesc.Count > 1) {
2024 qWarning(
"Multisample texture cannot be read back");
2027 src = texD->textureResource();
2028 dxgiFormat = texD->dxgiFormat;
2029 if (u.rb.rect().isValid())
2032 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2033 format = texD->m_format;
2034 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2035 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2039 if (swapChainD->sampleDesc.Count > 1) {
2044 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2045 rcmd.args.resolveSubRes.dstSubRes = 0;
2047 rcmd.args.resolveSubRes.srcSubRes = 0;
2048 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2050 src = swapChainD->backBufferTex;
2051 dxgiFormat = swapChainD->colorFormat;
2052 if (u.rb.rect().isValid())
2055 rect = QRect({0, 0}, swapChainD->pixelSize);
2056 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2057 if (format == QRhiTexture::UnknownFormat)
2060 quint32 byteSize = 0;
2062 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2064 D3D11_TEXTURE2D_DESC desc = {};
2065 desc.Width = UINT(rect.width());
2066 desc.Height = UINT(rect.height());
2069 desc.Format = dxgiFormat;
2070 desc.SampleDesc.Count = 1;
2071 desc.Usage = D3D11_USAGE_STAGING;
2072 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2073 ID3D11Texture2D *stagingTex;
2074 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2076 qWarning(
"Failed to create readback staging texture: %s",
2077 qPrintable(QSystemError::windowsComString(hr)));
2083 cmd.args.copySubRes.dst = stagingTex;
2084 cmd.args.copySubRes.dstSubRes = 0;
2085 cmd.args.copySubRes.dstX = 0;
2086 cmd.args.copySubRes.dstY = 0;
2087 cmd.args.copySubRes.dstZ = 0;
2088 cmd.args.copySubRes.src = src;
2089 cmd.args.copySubRes.srcSubRes = subres;
2091 D3D11_BOX srcBox = {};
2092 srcBox.left = UINT(rect.left());
2093 srcBox.top = UINT(rect.top());
2094 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2096 srcBox.right = srcBox.left + desc.Width;
2097 srcBox.bottom = srcBox.top + desc.Height;
2098 srcBox.back = srcBox.front + 1;
2099 cmd.args.copySubRes.hasSrcBox =
true;
2100 cmd.args.copySubRes.srcBox = srcBox;
2102 readback.stagingTex = stagingTex;
2103 readback.byteSize = byteSize;
2105 readback.pixelSize = rect.size();
2106 readback.format = format;
2108 activeTextureReadbacks.append(readback);
2110 Q_ASSERT(u.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2113 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2122 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2124 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2126 readback.result->format = readback.format;
2127 readback.result->pixelSize = readback.pixelSize;
2129 D3D11_MAPPED_SUBRESOURCE mp;
2130 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2131 if (SUCCEEDED(hr)) {
2132 readback.result->data.resize(
int(readback.byteSize));
2135 char *dst = readback.result->data.data();
2136 char *src =
static_cast<
char *>(mp.pData);
2137 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2138 memcpy(dst, src, readback.bpl);
2139 dst += readback.bpl;
2142 context->Unmap(readback.stagingTex, 0);
2144 qWarning(
"Failed to map readback staging texture: %s",
2145 qPrintable(QSystemError::windowsComString(hr)));
2148 readback.stagingTex->Release();
2150 if (readback.result->completed)
2151 completedCallbacks.append(readback.result->completed);
2153 activeTextureReadbacks.removeLast();
2156 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2159 D3D11_MAPPED_SUBRESOURCE mp;
2160 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2161 if (SUCCEEDED(hr)) {
2162 readback.result->data.resize(
int(readback.byteSize));
2163 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2164 context->Unmap(readback.stagingBuf, 0);
2166 qWarning(
"Failed to map readback staging texture: %s",
2167 qPrintable(QSystemError::windowsComString(hr)));
2170 readback.stagingBuf->Release();
2172 if (readback.result->completed)
2173 completedCallbacks.append(readback.result->completed);
2175 activeBufferReadbacks.removeLast();
2178 for (
auto f : completedCallbacks)
2184 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2190 QRhiRenderTarget *rt,
2191 const QColor &colorClearValue,
2192 const QRhiDepthStencilClearValue &depthStencilClearValue,
2193 QRhiResourceUpdateBatch *resourceUpdates,
2199 if (resourceUpdates)
2202 bool wantsColorClear =
true;
2203 bool wantsDsClear =
true;
2205 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2207 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2208 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2209 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2217 fbCmd.args.setRenderTarget.rt = rt;
2221 clearCmd.args.clear.rt = rt;
2222 clearCmd.args.clear.mask = 0;
2228 clearCmd.args.clear.c[0] = colorClearValue.redF();
2229 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2230 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2231 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2232 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2233 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2236 cbD->currentTarget = rt;
2246 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2248 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2251 const QRhiColorAttachment &colorAtt(*it);
2252 if (!colorAtt.resolveTexture())
2258 Q_ASSERT(srcTexD || srcRbD);
2261 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2262 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2263 UINT(colorAtt.resolveLayer()),
2264 dstTexD->mipLevelCount);
2266 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2267 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2268 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2269 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2270 cbD->commands.unget();
2273 if (srcTexD->sampleDesc.Count <= 1) {
2274 qWarning(
"Cannot resolve a non-multisample texture");
2275 cbD->commands.unget();
2278 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2279 qWarning(
"Resolve source and destination sizes do not match");
2280 cbD->commands.unget();
2284 cmd.args.resolveSubRes.src = srcRbD->tex;
2285 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2286 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2287 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2288 cbD->commands.unget();
2291 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2292 qWarning(
"Resolve source and destination sizes do not match");
2293 cbD->commands.unget();
2297 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2298 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2300 if (rtTex->m_desc.depthResolveTexture())
2301 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2305 cbD->currentTarget =
nullptr;
2307 if (resourceUpdates)
2312 QRhiResourceUpdateBatch *resourceUpdates,
2318 if (resourceUpdates)
2336 if (resourceUpdates)
2345 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2347 if (pipelineChanged) {
2348 cbD->currentGraphicsPipeline =
nullptr;
2349 cbD->currentComputePipeline = psD;
2350 cbD->currentPipelineGeneration = psD->generation;
2354 cmd.args.bindComputePipeline.ps = psD;
2365 cmd.args.dispatch.x = UINT(x);
2366 cmd.args.dispatch.y = UINT(y);
2367 cmd.args.dispatch.z = UINT(z);
2372 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2374 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2375 if (!map || map->isEmpty())
2376 return { binding, binding };
2378 auto it = map->constFind(binding);
2379 if (it != map->cend())
2389 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2391 srbD->resourceBatches.clear();
2397 ID3D11Buffer *buffer;
2398 uint offsetInConstants;
2399 uint sizeInConstants;
2403 ID3D11ShaderResourceView *srv;
2407 ID3D11SamplerState *sampler;
2411 ID3D11UnorderedAccessView *uav;
2413 QVarLengthArray<Buffer, 8> buffers;
2414 QVarLengthArray<Texture, 8> textures;
2415 QVarLengthArray<Sampler, 8> samplers;
2416 QVarLengthArray<Uav, 8> uavs;
2419 for (
const Buffer &buf : buffers) {
2420 batches.ubufs.feed(buf.breg, buf.buffer);
2421 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2422 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2423 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2429 for (
const Texture &t : textures)
2430 batches.shaderresources.feed(t.treg, t.srv);
2431 for (
const Sampler &s : samplers)
2432 batches.samplers.feed(s.sreg, s.sampler);
2437 for (
const Stage::Uav &u : uavs)
2438 batches.uavs.feed(u.ureg, u.uav);
2443 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2444 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2447 case QRhiShaderResourceBinding::UniformBuffer:
2450 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2451 bd.ubuf.id = bufD->m_id;
2452 bd.ubuf.generation = bufD->generation;
2459 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2463 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2464 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2465 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2466 if (nativeBinding.first >= 0)
2467 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2469 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2470 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2471 if (nativeBinding.first >= 0)
2472 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2474 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2475 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2476 if (nativeBinding.first >= 0)
2477 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2479 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2480 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2481 if (nativeBinding.first >= 0)
2482 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2484 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2485 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2486 if (nativeBinding.first >= 0)
2487 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2489 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2490 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2491 if (nativeBinding.first >= 0)
2492 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2496 case QRhiShaderResourceBinding::SampledTexture:
2497 case QRhiShaderResourceBinding::Texture:
2498 case QRhiShaderResourceBinding::Sampler:
2500 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2501 bd.stex.count = data->count;
2502 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2503 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2504 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2505 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2506 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2507 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2511 for (
int elem = 0; elem < data->count; ++elem) {
2514 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2515 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2516 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2517 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2522 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2523 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2524 : (samplerD ? nativeBindingVert.first : -1);
2525 if (nativeBindingVert.first >= 0 && texD)
2526 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2527 if (samplerBinding >= 0)
2528 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2530 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2531 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2532 : (samplerD ? nativeBindingHull.first : -1);
2533 if (nativeBindingHull.first >= 0 && texD)
2534 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2535 if (samplerBinding >= 0)
2536 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2538 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2539 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2540 : (samplerD ? nativeBindingDomain.first : -1);
2541 if (nativeBindingDomain.first >= 0 && texD)
2542 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2543 if (samplerBinding >= 0)
2544 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2546 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2547 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2548 : (samplerD ? nativeBindingGeom.first : -1);
2549 if (nativeBindingGeom.first >= 0 && texD)
2550 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2551 if (samplerBinding >= 0)
2552 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2554 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2555 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2556 : (samplerD ? nativeBindingFrag.first : -1);
2557 if (nativeBindingFrag.first >= 0 && texD)
2558 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2559 if (samplerBinding >= 0)
2560 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2562 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2563 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2564 : (samplerD ? nativeBindingComp.first : -1);
2565 if (nativeBindingComp.first >= 0 && texD)
2566 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2567 if (samplerBinding >= 0)
2568 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2573 case QRhiShaderResourceBinding::ImageLoad:
2574 case QRhiShaderResourceBinding::ImageStore:
2575 case QRhiShaderResourceBinding::ImageLoadStore:
2578 bd.simage.id = texD->m_id;
2579 bd.simage.generation = texD->generation;
2580 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2581 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2582 if (nativeBinding.first >= 0) {
2583 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2585 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2587 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2588 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2589 if (nativeBinding.first >= 0) {
2590 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2592 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2595 qWarning(
"Unordered access only supported at fragment/compute stage");
2599 case QRhiShaderResourceBinding::BufferLoad:
2600 case QRhiShaderResourceBinding::BufferStore:
2601 case QRhiShaderResourceBinding::BufferLoadStore:
2604 bd.sbuf.id = bufD->m_id;
2605 bd.sbuf.generation = bufD->generation;
2606 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2607 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2608 if (nativeBinding.first >= 0) {
2609 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2611 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2614 qWarning(
"Unordered access only supported at compute stage");
2629 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2630 return a.breg < b.breg;
2632 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2633 return a.treg < b.treg;
2635 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2636 return a.sreg < b.sreg;
2638 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2639 return a.ureg < b.ureg;
2643 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2644 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2645 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2646 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2647 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2648 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2650 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2651 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2652 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2653 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2654 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2655 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2657 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2658 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2666 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2668 D3D11_MAPPED_SUBRESOURCE mp;
2669 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2670 if (SUCCEEDED(hr)) {
2671 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2672 context->Unmap(bufD->buffer, 0);
2674 qWarning(
"Failed to map buffer: %s",
2675 qPrintable(QSystemError::windowsComString(hr)));
2681 const QRhiBatchedBindings<UINT> *originalBindings,
2682 const QRhiBatchedBindings<UINT> *staticOffsets,
2683 const uint *dynOfsPairs,
int dynOfsPairCount)
2685 const int count = staticOffsets->batches[batchIndex].resources.count();
2688 for (
int b = 0; b < count; ++b) {
2689 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2690 for (
int di = 0; di < dynOfsPairCount; ++di) {
2691 const uint binding = dynOfsPairs[2 * di];
2694 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2695 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2696 offsets[b] = offsetInConstants;
2705 if (startSlot + countSlots > maxSlots) {
2706 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2707 resType, countSlots, startSlot, maxSlots);
2708 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2713#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2714 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2715 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2716 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2717 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2718 batches.ubufs.batches[i].resources.count(),
2719 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2720 #stagePrefixU " cbuf");
2722 if (!dynOfsPairCount) {
2723 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2725 batches.ubufs.batches[i].resources.constData(),
2726 batches.ubufoffsets.batches[i].resources.constData(),
2727 batches.ubufsizes.batches[i].resources.constData());
2729 applyDynamicOffsets(offsets, i,
2730 &batches.ubuforigbindings, &batches.ubufoffsets,
2731 dynOfsPairs, dynOfsPairCount);
2732 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2734 batches.ubufs.batches[i].resources.constData(),
2736 batches.ubufsizes.batches[i].resources.constData());
2742#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2743 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2744 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2745 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2746 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2748 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2750 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2751 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2752 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2754 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2755 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2756 int(batch.startBinding + count) - 1
);
2761#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2762 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2763 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2764 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2767 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2769 batch.resources.constData(),
2771 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2772 int(batch.startBinding + count) - 1
);
2778 const uint *dynOfsPairs,
int dynOfsPairCount,
2779 bool offsetOnlyChange,
2792 if (!offsetOnlyChange) {
2802 if (allResourceBatches.fsUavBatches.present) {
2803 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2804 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2806 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2808 if (rtUavState.update(rtD, batch.resources.constData(), count)) {
2809 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv,
2810 UINT(rtD->colorAttCount), count, batch.resources.constData(),
nullptr);
2812 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2813 int(batch.startBinding + count) - 1);
2826 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2832 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2833 for (
int i = 0; i < count; ++i)
2834 nullbufs[i] =
nullptr;
2835 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2836 for (
int i = 0; i < count; ++i)
2838 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2839 for (
int i = 0; i < count; ++i)
2841 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2851 if (nullsrvCount > 0) {
2852 QVarLengthArray<ID3D11ShaderResourceView *,
2853 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2854 for (
int i = 0; i < nullsrvs.count(); ++i)
2855 nullsrvs[i] =
nullptr;
2857 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2861 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2865 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2869 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2873 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2877 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2883 rtUavState.update(rtD);
2884 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv, 0, 0,
nullptr,
nullptr);
2889 QVarLengthArray<ID3D11UnorderedAccessView *,
2890 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2891 for (
int i = 0; i < nulluavCount; ++i)
2892 nulluavs[i] =
nullptr;
2893 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2898#define SETSHADER(StageL, StageU)
2899 if (psD->StageL.shader) {
2900 context->StageU##SetShader(psD->StageL.shader, nullptr, 0
);
2901 currentShaderMask |= StageU##MaskBit;
2902 } else if (currentShaderMask & StageU##MaskBit) {
2903 context->StageU##SetShader(nullptr, nullptr, 0
);
2904 currentShaderMask &= ~StageU##MaskBit;
2909 quint32 stencilRef = 0;
2910 float blendConstants[] = { 1, 1, 1, 1 };
2911 enum ActiveShaderMask {
2918 int currentShaderMask = 0xFF;
2924 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2927 case QD3D11CommandBuffer::Command::BeginFrame:
2928 if (cmd.args.beginFrame.tsDisjointQuery)
2929 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2930 if (cmd.args.beginFrame.tsQuery) {
2931 if (cmd.args.beginFrame.swapchainData) {
2937 rtUavState.update(rtD);
2938 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2941 context->End(cmd.args.beginFrame.tsQuery);
2944 case QD3D11CommandBuffer::Command::EndFrame:
2945 if (cmd.args.endFrame.tsQuery)
2946 context->End(cmd.args.endFrame.tsQuery);
2947 if (cmd.args.endFrame.tsDisjointQuery)
2948 context->End(cmd.args.endFrame.tsDisjointQuery);
2956 if (rtUavState.update(rtD))
2957 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2965 for (
int i = 0; i < rtD->colorAttCount; ++i)
2966 context->ClearRenderTargetView(rtD->rtv[i], cmd.args.clear.c);
2969 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
2970 ds |= D3D11_CLEAR_DEPTH;
2971 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
2972 ds |= D3D11_CLEAR_STENCIL;
2974 context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
2980 v.TopLeftX = cmd.args.viewport.x;
2981 v.TopLeftY = cmd.args.viewport.y;
2982 v.Width = cmd.args.viewport.w;
2983 v.Height = cmd.args.viewport.h;
2984 v.MinDepth = cmd.args.viewport.d0;
2985 v.MaxDepth = cmd.args.viewport.d1;
2986 context->RSSetViewports(1, &v);
2992 r.left = cmd.args.scissor.x;
2993 r.top = cmd.args.scissor.y;
2995 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
2996 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
2997 context->RSSetScissorRects(1, &r);
3003 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3004 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3005 UINT(cmd.args.bindVertexBuffers.slotCount),
3006 cmd.args.bindVertexBuffers.buffers,
3007 cmd.args.bindVertexBuffers.strides,
3008 cmd.args.bindVertexBuffers.offsets);
3012 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3013 cmd.args.bindIndexBuffer.format,
3014 cmd.args.bindIndexBuffer.offset);
3024 context->IASetPrimitiveTopology(psD->d3dTopology);
3025 context->IASetInputLayout(psD->inputLayout);
3026 context->OMSetDepthStencilState(psD->dsState, stencilRef);
3027 context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
3028 context->RSSetState(psD->rastState);
3031 case QD3D11CommandBuffer::Command::BindShaderResources:
3032 bindShaderResources(cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3033 cmd.args.bindShaderResources.dynamicOffsetPairs,
3034 cmd.args.bindShaderResources.dynamicOffsetCount,
3035 cmd.args.bindShaderResources.offsetOnlyChange,
3040 stencilRef = cmd.args.stencilRef.ref;
3041 context->OMSetDepthStencilState(cmd.args.stencilRef.ps->dsState, stencilRef);
3044 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3045 context->OMSetBlendState(cmd.args.blendConstants.ps->blendState, blendConstants, 0xffffffff);
3048 if (cmd.args.draw.ps) {
3049 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3050 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3052 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3053 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3055 qWarning(
"No graphics pipeline active for draw; ignored");
3059 if (cmd.args.drawIndexed.ps) {
3060 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3061 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3062 cmd.args.drawIndexed.vertexOffset);
3064 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3065 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3066 cmd.args.drawIndexed.firstInstance);
3068 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3071 case QD3D11CommandBuffer::Command::UpdateSubRes:
3072 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3073 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3074 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3076 case QD3D11CommandBuffer::Command::CopySubRes:
3077 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3078 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3079 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3080 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3082 case QD3D11CommandBuffer::Command::ResolveSubRes:
3083 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3084 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3085 cmd.args.resolveSubRes.format);
3087 case QD3D11CommandBuffer::Command::GenMip:
3088 context->GenerateMips(cmd.args.genMip.srv);
3090 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3091 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3093 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3094 annotations->EndEvent();
3096 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3097 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3099 case QD3D11CommandBuffer::Command::BindComputePipeline:
3100 context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader,
nullptr, 0);
3102 case QD3D11CommandBuffer::Command::Dispatch:
3103 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3132 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3133 it.value()->Release();
3138 rhiD->unregisterResource(
this);
3144 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3145 u |= D3D11_BIND_VERTEX_BUFFER;
3146 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3147 u |= D3D11_BIND_INDEX_BUFFER;
3148 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3149 u |= D3D11_BIND_CONSTANT_BUFFER;
3150 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3151 u |= D3D11_BIND_UNORDERED_ACCESS;
3160 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3161 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3165 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3166 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3170 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3171 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3173 D3D11_BUFFER_DESC desc = {};
3174 desc.ByteWidth = roundedSize;
3175 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3176 desc.BindFlags = toD3DBufferUsage(m_usage);
3177 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3178 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3181 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3183 qWarning(
"Failed to create buffer: %s",
3184 qPrintable(QSystemError::windowsComString(hr)));
3188 if (m_type == Dynamic) {
3189 dynBuf =
new char[nonZeroSize];
3193 if (!m_objectName.isEmpty())
3194 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3197 rhiD->registerResource(
this);
3203 if (m_type == Dynamic) {
3207 return { { &buffer }, 1 };
3218 Q_ASSERT(m_type == Dynamic);
3219 D3D11_MAPPED_SUBRESOURCE mp;
3221 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3223 qWarning(
"Failed to map buffer: %s",
3224 qPrintable(QSystemError::windowsComString(hr)));
3227 return static_cast<
char *>(mp.pData);
3233 rhiD->context->Unmap(buffer, 0);
3238 auto it = uavs.find(offset);
3239 if (it != uavs.end())
3243 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3244 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3245 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3246 desc.Buffer.FirstElement = offset / 4u;
3247 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3248 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3251 ID3D11UnorderedAccessView *uav =
nullptr;
3252 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3254 qWarning(
"Failed to create UAV: %s",
3255 qPrintable(QSystemError::windowsComString(hr)));
3264 int sampleCount, QRhiRenderBuffer::Flags flags,
3265 QRhiTexture::Format backingFormatHint)
3295 rhiD->unregisterResource(
this);
3303 if (m_pixelSize.isEmpty())
3307 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3309 D3D11_TEXTURE2D_DESC desc = {};
3310 desc.Width = UINT(m_pixelSize.width());
3311 desc.Height = UINT(m_pixelSize.height());
3314 desc.SampleDesc = sampleDesc;
3315 desc.Usage = D3D11_USAGE_DEFAULT;
3317 if (m_type == Color) {
3318 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3319 : toD3DTextureFormat(m_backingFormatHint, {});
3320 desc.Format = dxgiFormat;
3321 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3322 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3324 qWarning(
"Failed to create color renderbuffer: %s",
3325 qPrintable(QSystemError::windowsComString(hr)));
3328 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3329 rtvDesc.Format = dxgiFormat;
3330 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3331 : D3D11_RTV_DIMENSION_TEXTURE2D;
3332 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3334 qWarning(
"Failed to create rtv: %s",
3335 qPrintable(QSystemError::windowsComString(hr)));
3338 }
else if (m_type == DepthStencil) {
3339 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3340 desc.Format = dxgiFormat;
3341 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3342 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3344 qWarning(
"Failed to create depth-stencil buffer: %s",
3345 qPrintable(QSystemError::windowsComString(hr)));
3348 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3349 dsvDesc.Format = dxgiFormat;
3350 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3351 : D3D11_DSV_DIMENSION_TEXTURE2D;
3352 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3354 qWarning(
"Failed to create dsv: %s",
3355 qPrintable(QSystemError::windowsComString(hr)));
3362 if (!m_objectName.isEmpty())
3363 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3366 rhiD->registerResource(
this);
3372 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3373 return m_backingFormatHint;
3375 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3379 int arraySize,
int sampleCount, Flags flags)
3382 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3383 perLevelViews[i] =
nullptr;
3393 if (!tex && !tex3D && !tex1D)
3401 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3402 if (perLevelViews[i]) {
3403 perLevelViews[i]->Release();
3404 perLevelViews[i] =
nullptr;
3423 rhiD->unregisterResource(
this);
3429 case QRhiTexture::Format::D16:
3430 return DXGI_FORMAT_R16_FLOAT;
3431 case QRhiTexture::Format::D24:
3432 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3433 case QRhiTexture::Format::D24S8:
3434 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3435 case QRhiTexture::Format::D32F:
3436 return DXGI_FORMAT_R32_FLOAT;
3437 case QRhiTexture::Format::D32FS8:
3438 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3441 return DXGI_FORMAT_R32_FLOAT;
3448 case QRhiTexture::Format::D16:
3449 return DXGI_FORMAT_D16_UNORM;
3450 case QRhiTexture::Format::D24:
3451 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3452 case QRhiTexture::Format::D24S8:
3453 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3454 case QRhiTexture::Format::D32F:
3455 return DXGI_FORMAT_D32_FLOAT;
3456 case QRhiTexture::Format::D32FS8:
3457 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3460 return DXGI_FORMAT_D32_FLOAT;
3466 if (tex || tex3D || tex1D)
3470 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3473 const bool isDepth = isDepthTextureFormat(m_format);
3474 const bool isCube = m_flags.testFlag(CubeMap);
3475 const bool is3D = m_flags.testFlag(ThreeDimensional);
3476 const bool isArray = m_flags.testFlag(TextureArray);
3477 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3478 const bool is1D = m_flags.testFlag(OneDimensional);
3480 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3481 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3483 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3484 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3485 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3486 if (sampleDesc.Count > 1) {
3488 qWarning(
"Cubemap texture cannot be multisample");
3492 qWarning(
"3D texture cannot be multisample");
3496 qWarning(
"Multisample texture cannot have mipmaps");
3500 if (isDepth && hasMipMaps) {
3501 qWarning(
"Depth texture cannot have mipmaps");
3504 if (isCube && is3D) {
3505 qWarning(
"Texture cannot be both cube and 3D");
3508 if (isArray && is3D) {
3509 qWarning(
"Texture cannot be both array and 3D");
3512 if (isCube && is1D) {
3513 qWarning(
"Texture cannot be both cube and 1D");
3517 qWarning(
"Texture cannot be both 1D and 3D");
3520 if (m_depth > 1 && !is3D) {
3521 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3524 if (m_arraySize > 0 && !isArray) {
3525 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3528 if (m_arraySize < 1 && isArray) {
3529 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3534 *adjustedSize = size;
3542 const bool isDepth = isDepthTextureFormat(m_format);
3543 const bool isCube = m_flags.testFlag(CubeMap);
3544 const bool is3D = m_flags.testFlag(ThreeDimensional);
3545 const bool isArray = m_flags.testFlag(TextureArray);
3546 const bool is1D = m_flags.testFlag(OneDimensional);
3548 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3549 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3551 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3552 srvDesc.TextureCube.MipLevels = mipLevelCount;
3556 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3557 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3558 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3559 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3560 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3562 srvDesc.Texture1DArray.FirstArraySlice = 0;
3563 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3566 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3567 srvDesc.Texture1D.MipLevels = mipLevelCount;
3569 }
else if (isArray) {
3570 if (sampleDesc.Count > 1) {
3571 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3572 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3573 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3574 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3576 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3577 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3580 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3581 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3582 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3583 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3584 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3586 srvDesc.Texture2DArray.FirstArraySlice = 0;
3587 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3591 if (sampleDesc.Count > 1) {
3592 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3594 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3595 srvDesc.Texture3D.MipLevels = mipLevelCount;
3597 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3598 srvDesc.Texture2D.MipLevels = mipLevelCount;
3603 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3605 qWarning(
"Failed to create srv: %s",
3606 qPrintable(QSystemError::windowsComString(hr)));
3617 if (!prepareCreate(&size))
3620 const bool isDepth = isDepthTextureFormat(m_format);
3621 const bool isCube = m_flags.testFlag(CubeMap);
3622 const bool is3D = m_flags.testFlag(ThreeDimensional);
3623 const bool isArray = m_flags.testFlag(TextureArray);
3624 const bool is1D = m_flags.testFlag(OneDimensional);
3626 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3627 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3628 if (m_flags.testFlag(RenderTarget)) {
3630 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3632 bindFlags |= D3D11_BIND_RENDER_TARGET;
3634 if (m_flags.testFlag(UsedWithGenerateMips)) {
3636 qWarning(
"Depth texture cannot have mipmaps generated");
3639 bindFlags |= D3D11_BIND_RENDER_TARGET;
3640 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3642 if (m_flags.testFlag(UsedWithLoadStore))
3643 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3647 D3D11_TEXTURE1D_DESC desc = {};
3648 desc.Width = UINT(size.width());
3649 desc.MipLevels = mipLevelCount;
3650 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3651 desc.Format = dxgiFormat;
3652 desc.Usage = D3D11_USAGE_DEFAULT;
3653 desc.BindFlags = bindFlags;
3654 desc.MiscFlags = miscFlags;
3656 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3658 qWarning(
"Failed to create 1D texture: %s",
3659 qPrintable(QSystemError::windowsComString(hr)));
3662 if (!m_objectName.isEmpty())
3663 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3664 m_objectName.constData());
3666 D3D11_TEXTURE2D_DESC desc = {};
3667 desc.Width = UINT(size.width());
3668 desc.Height = UINT(size.height());
3669 desc.MipLevels = mipLevelCount;
3670 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3671 desc.Format = dxgiFormat;
3672 desc.SampleDesc = sampleDesc;
3673 desc.Usage = D3D11_USAGE_DEFAULT;
3674 desc.BindFlags = bindFlags;
3675 desc.MiscFlags = miscFlags;
3677 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3679 qWarning(
"Failed to create 2D texture: %s",
3680 qPrintable(QSystemError::windowsComString(hr)));
3683 if (!m_objectName.isEmpty())
3684 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3686 D3D11_TEXTURE3D_DESC desc = {};
3687 desc.Width = UINT(size.width());
3688 desc.Height = UINT(size.height());
3689 desc.Depth = UINT(qMax(1, m_depth));
3690 desc.MipLevels = mipLevelCount;
3691 desc.Format = dxgiFormat;
3692 desc.Usage = D3D11_USAGE_DEFAULT;
3693 desc.BindFlags = bindFlags;
3694 desc.MiscFlags = miscFlags;
3696 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3698 qWarning(
"Failed to create 3D texture: %s",
3699 qPrintable(QSystemError::windowsComString(hr)));
3702 if (!m_objectName.isEmpty())
3703 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3710 rhiD->registerResource(
this);
3719 if (!prepareCreate())
3722 if (m_flags.testFlag(ThreeDimensional))
3723 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3724 else if (m_flags.testFlags(OneDimensional))
3725 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3727 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3734 rhiD->registerResource(
this);
3740 return { quint64(textureResource()), 0 };
3745 if (perLevelViews[level])
3746 return perLevelViews[level];
3748 const bool isCube = m_flags.testFlag(CubeMap);
3749 const bool isArray = m_flags.testFlag(TextureArray);
3750 const bool is3D = m_flags.testFlag(ThreeDimensional);
3751 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3752 desc.Format = dxgiFormat;
3754 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3755 desc.Texture2DArray.MipSlice = UINT(level);
3756 desc.Texture2DArray.FirstArraySlice = 0;
3757 desc.Texture2DArray.ArraySize = 6;
3758 }
else if (isArray) {
3759 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3760 desc.Texture2DArray.MipSlice = UINT(level);
3761 desc.Texture2DArray.FirstArraySlice = 0;
3762 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3764 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3765 desc.Texture3D.MipSlice = UINT(level);
3766 desc.Texture3D.WSize = UINT(m_depth);
3768 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3769 desc.Texture2D.MipSlice = UINT(level);
3773 ID3D11UnorderedAccessView *uav =
nullptr;
3774 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3776 qWarning(
"Failed to create UAV: %s",
3777 qPrintable(QSystemError::windowsComString(hr)));
3781 perLevelViews[level] = uav;
3786 AddressMode u, AddressMode v, AddressMode w)
3801 samplerState->Release();
3802 samplerState =
nullptr;
3806 rhiD->unregisterResource(
this);
3809static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3811 if (minFilter == QRhiSampler::Nearest) {
3812 if (magFilter == QRhiSampler::Nearest) {
3813 if (mipFilter == QRhiSampler::Linear)
3814 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3816 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3818 if (mipFilter == QRhiSampler::Linear)
3819 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3821 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3824 if (magFilter == QRhiSampler::Nearest) {
3825 if (mipFilter == QRhiSampler::Linear)
3826 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3828 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3830 if (mipFilter == QRhiSampler::Linear)
3831 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3833 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3838 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3844 case QRhiSampler::Repeat:
3845 return D3D11_TEXTURE_ADDRESS_WRAP;
3846 case QRhiSampler::ClampToEdge:
3847 return D3D11_TEXTURE_ADDRESS_CLAMP;
3848 case QRhiSampler::Mirror:
3849 return D3D11_TEXTURE_ADDRESS_MIRROR;
3852 return D3D11_TEXTURE_ADDRESS_CLAMP;
3859 case QRhiSampler::Never:
3860 return D3D11_COMPARISON_NEVER;
3861 case QRhiSampler::Less:
3862 return D3D11_COMPARISON_LESS;
3863 case QRhiSampler::Equal:
3864 return D3D11_COMPARISON_EQUAL;
3865 case QRhiSampler::LessOrEqual:
3866 return D3D11_COMPARISON_LESS_EQUAL;
3867 case QRhiSampler::Greater:
3868 return D3D11_COMPARISON_GREATER;
3869 case QRhiSampler::NotEqual:
3870 return D3D11_COMPARISON_NOT_EQUAL;
3871 case QRhiSampler::GreaterOrEqual:
3872 return D3D11_COMPARISON_GREATER_EQUAL;
3873 case QRhiSampler::Always:
3874 return D3D11_COMPARISON_ALWAYS;
3877 return D3D11_COMPARISON_NEVER;
3886 D3D11_SAMPLER_DESC desc = {};
3887 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3888 if (m_compareOp != Never)
3889 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3890 desc.AddressU = toD3DAddressMode(m_addressU);
3891 desc.AddressV = toD3DAddressMode(m_addressV);
3892 desc.AddressW = toD3DAddressMode(m_addressW);
3893 desc.MaxAnisotropy = 1.0f;
3894 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3895 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3898 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3900 qWarning(
"Failed to create sampler state: %s",
3901 qPrintable(QSystemError::windowsComString(hr)));
3906 rhiD->registerResource(
this);
3925 rhiD->unregisterResource(
this);
3938 rhiD->registerResource(rpD,
false);
3975 return d.sampleCount;
3979 const QRhiTextureRenderTargetDescription &desc,
3997 if (!rtv[0] && !dsv)
4016 rhiD->unregisterResource(
this);
4023 rhiD->registerResource(rpD,
false);
4032 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4033 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4034 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4038 d.colorAttCount = 0;
4040 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4041 d.colorAttCount += 1;
4042 const QRhiColorAttachment &colorAtt(*it);
4043 QRhiTexture *texture = colorAtt.texture();
4044 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4045 Q_ASSERT(texture || rb);
4048 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4049 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4050 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4051 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4052 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4053 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4054 rtvDesc.Texture2DArray.ArraySize = 1;
4055 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4056 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4057 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4058 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4059 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4060 rtvDesc.Texture1DArray.ArraySize = 1;
4062 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4063 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4065 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4066 if (texD->sampleDesc.Count > 1) {
4067 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4068 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4069 rtvDesc.Texture2DMSArray.ArraySize = 1;
4071 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4072 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4073 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4074 rtvDesc.Texture2DArray.ArraySize = 1;
4076 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4077 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4078 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4079 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4080 rtvDesc.Texture3D.WSize = 1;
4082 if (texD->sampleDesc.Count > 1) {
4083 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4085 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4086 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4089 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4091 qWarning(
"Failed to create rtv: %s",
4092 qPrintable(QSystemError::windowsComString(hr)));
4096 if (attIndex == 0) {
4097 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4098 d.sampleCount =
int(texD->sampleDesc.Count);
4103 rtv[attIndex] = rbD->rtv;
4104 if (attIndex == 0) {
4105 d.pixelSize = rbD->pixelSize();
4106 d.sampleCount =
int(rbD->sampleDesc.Count);
4112 if (hasDepthStencil) {
4113 if (m_desc.depthTexture()) {
4116 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4117 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4118 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4119 : D3D11_DSV_DIMENSION_TEXTURE2D;
4120 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4121 if (depthTexD->sampleDesc.Count > 1) {
4122 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4123 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4124 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4125 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4127 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4128 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4131 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4132 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4133 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4134 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4136 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4137 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4141 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4143 qWarning(
"Failed to create dsv: %s",
4144 qPrintable(QSystemError::windowsComString(hr)));
4147 if (d.colorAttCount == 0) {
4148 d.pixelSize = depthTexD->pixelSize();
4149 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4154 dsv = depthRbD->dsv;
4155 if (d.colorAttCount == 0) {
4156 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4157 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4165 for (
int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
4166 d.rtv[i] = i < d.colorAttCount ? rtv[i] :
nullptr;
4169 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4171 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4173 rhiD->registerResource(
this);
4179 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4192 return d.sampleCount;
4207 sortedBindings.clear();
4208 boundResourceData.clear();
4212 rhiD->unregisterResource(
this);
4217 if (!sortedBindings.isEmpty())
4221 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4224 rhiD->updateLayoutDesc(
this);
4226 std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
4227 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4229 boundResourceData.resize(sortedBindings.count());
4231 for (BoundResourceData &bd : boundResourceData)
4232 memset(&bd, 0,
sizeof(BoundResourceData));
4235 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4236 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4237 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4238 hasDynamicOffset =
true;
4244 rhiD->registerResource(
this,
false);
4250 sortedBindings.clear();
4251 std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
4252 if (!flags.testFlag(BindingsAreSorted))
4253 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4255 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4256 for (BoundResourceData &bd : boundResourceData)
4257 memset(&bd, 0,
sizeof(BoundResourceData));
4276 s.shader->Release();
4279 s.nativeResourceBindingMap.clear();
4291 blendState->Release();
4292 blendState =
nullptr;
4296 inputLayout->Release();
4297 inputLayout =
nullptr;
4301 rastState->Release();
4302 rastState =
nullptr;
4305 releasePipelineShader(vs);
4306 releasePipelineShader(hs);
4307 releasePipelineShader(ds);
4308 releasePipelineShader(gs);
4309 releasePipelineShader(fs);
4313 rhiD->unregisterResource(
this);
4319 case QRhiGraphicsPipeline::None:
4320 return D3D11_CULL_NONE;
4321 case QRhiGraphicsPipeline::Front:
4322 return D3D11_CULL_FRONT;
4323 case QRhiGraphicsPipeline::Back:
4324 return D3D11_CULL_BACK;
4327 return D3D11_CULL_NONE;
4334 case QRhiGraphicsPipeline::Fill:
4335 return D3D11_FILL_SOLID;
4336 case QRhiGraphicsPipeline::Line:
4337 return D3D11_FILL_WIREFRAME;
4340 return D3D11_FILL_SOLID;
4347 case QRhiGraphicsPipeline::Never:
4348 return D3D11_COMPARISON_NEVER;
4349 case QRhiGraphicsPipeline::Less:
4350 return D3D11_COMPARISON_LESS;
4351 case QRhiGraphicsPipeline::Equal:
4352 return D3D11_COMPARISON_EQUAL;
4353 case QRhiGraphicsPipeline::LessOrEqual:
4354 return D3D11_COMPARISON_LESS_EQUAL;
4355 case QRhiGraphicsPipeline::Greater:
4356 return D3D11_COMPARISON_GREATER;
4357 case QRhiGraphicsPipeline::NotEqual:
4358 return D3D11_COMPARISON_NOT_EQUAL;
4359 case QRhiGraphicsPipeline::GreaterOrEqual:
4360 return D3D11_COMPARISON_GREATER_EQUAL;
4361 case QRhiGraphicsPipeline::Always:
4362 return D3D11_COMPARISON_ALWAYS;
4365 return D3D11_COMPARISON_ALWAYS;
4372 case QRhiGraphicsPipeline::StencilZero:
4373 return D3D11_STENCIL_OP_ZERO;
4374 case QRhiGraphicsPipeline::Keep:
4375 return D3D11_STENCIL_OP_KEEP;
4376 case QRhiGraphicsPipeline::Replace:
4377 return D3D11_STENCIL_OP_REPLACE;
4378 case QRhiGraphicsPipeline::IncrementAndClamp:
4379 return D3D11_STENCIL_OP_INCR_SAT;
4380 case QRhiGraphicsPipeline::DecrementAndClamp:
4381 return D3D11_STENCIL_OP_DECR_SAT;
4382 case QRhiGraphicsPipeline::Invert:
4383 return D3D11_STENCIL_OP_INVERT;
4384 case QRhiGraphicsPipeline::IncrementAndWrap:
4385 return D3D11_STENCIL_OP_INCR;
4386 case QRhiGraphicsPipeline::DecrementAndWrap:
4387 return D3D11_STENCIL_OP_DECR;
4390 return D3D11_STENCIL_OP_KEEP;
4397 case QRhiVertexInputAttribute::Float4:
4398 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4399 case QRhiVertexInputAttribute::Float3:
4400 return DXGI_FORMAT_R32G32B32_FLOAT;
4401 case QRhiVertexInputAttribute::Float2:
4402 return DXGI_FORMAT_R32G32_FLOAT;
4403 case QRhiVertexInputAttribute::Float:
4404 return DXGI_FORMAT_R32_FLOAT;
4405 case QRhiVertexInputAttribute::UNormByte4:
4406 return DXGI_FORMAT_R8G8B8A8_UNORM;
4407 case QRhiVertexInputAttribute::UNormByte2:
4408 return DXGI_FORMAT_R8G8_UNORM;
4409 case QRhiVertexInputAttribute::UNormByte:
4410 return DXGI_FORMAT_R8_UNORM;
4411 case QRhiVertexInputAttribute::UInt4:
4412 return DXGI_FORMAT_R32G32B32A32_UINT;
4413 case QRhiVertexInputAttribute::UInt3:
4414 return DXGI_FORMAT_R32G32B32_UINT;
4415 case QRhiVertexInputAttribute::UInt2:
4416 return DXGI_FORMAT_R32G32_UINT;
4417 case QRhiVertexInputAttribute::UInt:
4418 return DXGI_FORMAT_R32_UINT;
4419 case QRhiVertexInputAttribute::SInt4:
4420 return DXGI_FORMAT_R32G32B32A32_SINT;
4421 case QRhiVertexInputAttribute::SInt3:
4422 return DXGI_FORMAT_R32G32B32_SINT;
4423 case QRhiVertexInputAttribute::SInt2:
4424 return DXGI_FORMAT_R32G32_SINT;
4425 case QRhiVertexInputAttribute::SInt:
4426 return DXGI_FORMAT_R32_SINT;
4427 case QRhiVertexInputAttribute::Half4:
4429 case QRhiVertexInputAttribute::Half3:
4430 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4431 case QRhiVertexInputAttribute::Half2:
4432 return DXGI_FORMAT_R16G16_FLOAT;
4433 case QRhiVertexInputAttribute::Half:
4434 return DXGI_FORMAT_R16_FLOAT;
4435 case QRhiVertexInputAttribute::UShort4:
4437 case QRhiVertexInputAttribute::UShort3:
4438 return DXGI_FORMAT_R16G16B16A16_UINT;
4439 case QRhiVertexInputAttribute::UShort2:
4440 return DXGI_FORMAT_R16G16_UINT;
4441 case QRhiVertexInputAttribute::UShort:
4442 return DXGI_FORMAT_R16_UINT;
4443 case QRhiVertexInputAttribute::SShort4:
4445 case QRhiVertexInputAttribute::SShort3:
4446 return DXGI_FORMAT_R16G16B16A16_SINT;
4447 case QRhiVertexInputAttribute::SShort2:
4448 return DXGI_FORMAT_R16G16_SINT;
4449 case QRhiVertexInputAttribute::SShort:
4450 return DXGI_FORMAT_R16_SINT;
4453 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4460 case QRhiGraphicsPipeline::Triangles:
4461 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4462 case QRhiGraphicsPipeline::TriangleStrip:
4463 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4464 case QRhiGraphicsPipeline::Lines:
4465 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4466 case QRhiGraphicsPipeline::LineStrip:
4467 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4468 case QRhiGraphicsPipeline::Points:
4469 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4470 case QRhiGraphicsPipeline::Patches:
4471 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4472 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4475 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4482 if (c.testFlag(QRhiGraphicsPipeline::R))
4483 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4484 if (c.testFlag(QRhiGraphicsPipeline::G))
4485 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4486 if (c.testFlag(QRhiGraphicsPipeline::B))
4487 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4488 if (c.testFlag(QRhiGraphicsPipeline::A))
4489 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4502 case QRhiGraphicsPipeline::Zero:
4503 return D3D11_BLEND_ZERO;
4504 case QRhiGraphicsPipeline::One:
4505 return D3D11_BLEND_ONE;
4506 case QRhiGraphicsPipeline::SrcColor:
4507 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4508 case QRhiGraphicsPipeline::OneMinusSrcColor:
4509 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4510 case QRhiGraphicsPipeline::DstColor:
4511 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4512 case QRhiGraphicsPipeline::OneMinusDstColor:
4513 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4514 case QRhiGraphicsPipeline::SrcAlpha:
4515 return D3D11_BLEND_SRC_ALPHA;
4516 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4517 return D3D11_BLEND_INV_SRC_ALPHA;
4518 case QRhiGraphicsPipeline::DstAlpha:
4519 return D3D11_BLEND_DEST_ALPHA;
4520 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4521 return D3D11_BLEND_INV_DEST_ALPHA;
4522 case QRhiGraphicsPipeline::ConstantColor:
4523 case QRhiGraphicsPipeline::ConstantAlpha:
4524 return D3D11_BLEND_BLEND_FACTOR;
4525 case QRhiGraphicsPipeline::OneMinusConstantColor:
4526 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4527 return D3D11_BLEND_INV_BLEND_FACTOR;
4528 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4529 return D3D11_BLEND_SRC_ALPHA_SAT;
4530 case QRhiGraphicsPipeline::Src1Color:
4531 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4532 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4533 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4534 case QRhiGraphicsPipeline::Src1Alpha:
4535 return D3D11_BLEND_SRC1_ALPHA;
4536 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4537 return D3D11_BLEND_INV_SRC1_ALPHA;
4540 return D3D11_BLEND_ZERO;
4547 case QRhiGraphicsPipeline::Add:
4548 return D3D11_BLEND_OP_ADD;
4549 case QRhiGraphicsPipeline::Subtract:
4550 return D3D11_BLEND_OP_SUBTRACT;
4551 case QRhiGraphicsPipeline::ReverseSubtract:
4552 return D3D11_BLEND_OP_REV_SUBTRACT;
4553 case QRhiGraphicsPipeline::Min:
4554 return D3D11_BLEND_OP_MIN;
4555 case QRhiGraphicsPipeline::Max:
4556 return D3D11_BLEND_OP_MAX;
4559 return D3D11_BLEND_OP_ADD;
4566 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4567 keyBuilder.addData(source);
4568 return keyBuilder.result().toHex();
4571QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4572 QString *error, QShaderKey *usedShaderKey)
4574 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4575 QShaderCode dxbc = shader.shader(key);
4576 if (!dxbc.shader().isEmpty()) {
4578 *usedShaderKey = key;
4579 return dxbc.shader();
4582 key = { QShader::HlslShader, 50, shaderVariant };
4583 QShaderCode hlslSource = shader.shader(key);
4584 if (hlslSource.shader().isEmpty()) {
4585 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4586 return QByteArray();
4590 *usedShaderKey = key;
4593 switch (shader.stage()) {
4594 case QShader::VertexStage:
4597 case QShader::TessellationControlStage:
4600 case QShader::TessellationEvaluationStage:
4603 case QShader::GeometryStage:
4606 case QShader::FragmentStage:
4609 case QShader::ComputeStage:
4614 return QByteArray();
4618 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4619 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4620 cacheKey.target = target;
4621 cacheKey.entryPoint = hlslSource.entryPoint();
4622 cacheKey.compileFlags = flags;
4623 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4624 if (cacheIt != m_bytecodeCache.constEnd())
4625 return cacheIt.value();
4628 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4629 if (d3dCompile ==
nullptr) {
4630 qWarning(
"Unable to resolve function D3DCompile()");
4631 return QByteArray();
4634 ID3DBlob *bytecode =
nullptr;
4635 ID3DBlob *errors =
nullptr;
4636 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4637 nullptr,
nullptr,
nullptr,
4638 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4639 if (FAILED(hr) || !bytecode) {
4640 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4642 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4643 int(errors->GetBufferSize()));
4646 return QByteArray();
4650 result.resize(
int(bytecode->GetBufferSize()));
4651 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4652 bytecode->Release();
4654 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4655 m_bytecodeCache.insert(cacheKey, result);
4666 rhiD->pipelineCreationStart();
4667 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4670 D3D11_RASTERIZER_DESC rastDesc = {};
4671 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4672 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4673 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4674 rastDesc.DepthBias = m_depthBias;
4675 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4676 rastDesc.DepthClipEnable =
true;
4677 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4678 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4679 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4681 qWarning(
"Failed to create rasterizer state: %s",
4682 qPrintable(QSystemError::windowsComString(hr)));
4686 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4687 dsDesc.DepthEnable = m_depthTest;
4688 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4689 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4690 dsDesc.StencilEnable = m_stencilTest;
4691 if (m_stencilTest) {
4692 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4693 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4694 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4695 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4696 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4697 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4698 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4699 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4700 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4701 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4703 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4705 qWarning(
"Failed to create depth-stencil state: %s",
4706 qPrintable(QSystemError::windowsComString(hr)));
4710 D3D11_BLEND_DESC blendDesc = {};
4711 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4712 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4713 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4714 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4715 blend.BlendEnable = b.enable;
4716 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4717 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4718 blend.BlendOp = toD3DBlendOp(b.opColor);
4719 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4720 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4721 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4722 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4723 blendDesc.RenderTarget[i] = blend;
4725 if (m_targetBlends.isEmpty()) {
4726 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4727 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4728 blendDesc.RenderTarget[0] = blend;
4730 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4732 qWarning(
"Failed to create blend state: %s",
4733 qPrintable(QSystemError::windowsComString(hr)));
4737 QByteArray vsByteCode;
4738 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4739 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4740 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4741 switch (shaderStage.type()) {
4742 case QRhiShaderStage::Vertex:
4743 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4744 vs.shader->AddRef();
4745 vsByteCode = cacheIt->bytecode;
4746 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4748 case QRhiShaderStage::TessellationControl:
4749 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4750 hs.shader->AddRef();
4751 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4753 case QRhiShaderStage::TessellationEvaluation:
4754 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4755 ds.shader->AddRef();
4756 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4758 case QRhiShaderStage::Geometry:
4759 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4760 gs.shader->AddRef();
4761 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4763 case QRhiShaderStage::Fragment:
4764 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4765 fs.shader->AddRef();
4766 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4773 QShaderKey shaderKey;
4774 UINT compileFlags = 0;
4775 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4776 compileFlags |= D3DCOMPILE_DEBUG;
4778 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4779 &error, &shaderKey);
4780 if (bytecode.isEmpty()) {
4781 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4785 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4787 rhiD->clearShaderCache();
4790 switch (shaderStage.type()) {
4791 case QRhiShaderStage::Vertex:
4792 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4794 qWarning(
"Failed to create vertex shader: %s",
4795 qPrintable(QSystemError::windowsComString(hr)));
4798 vsByteCode = bytecode;
4799 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4800 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4801 vs.shader->AddRef();
4803 case QRhiShaderStage::TessellationControl:
4804 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4806 qWarning(
"Failed to create hull shader: %s",
4807 qPrintable(QSystemError::windowsComString(hr)));
4810 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4811 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4812 hs.shader->AddRef();
4814 case QRhiShaderStage::TessellationEvaluation:
4815 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4817 qWarning(
"Failed to create domain shader: %s",
4818 qPrintable(QSystemError::windowsComString(hr)));
4821 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4822 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4823 ds.shader->AddRef();
4825 case QRhiShaderStage::Geometry:
4826 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4828 qWarning(
"Failed to create geometry shader: %s",
4829 qPrintable(QSystemError::windowsComString(hr)));
4832 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4833 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4834 gs.shader->AddRef();
4836 case QRhiShaderStage::Fragment:
4837 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4839 qWarning(
"Failed to create pixel shader: %s",
4840 qPrintable(QSystemError::windowsComString(hr)));
4843 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4844 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4845 fs.shader->AddRef();
4853 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4855 if (!vsByteCode.isEmpty()) {
4856 QByteArrayList matrixSliceSemantics;
4857 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4858 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4861 D3D11_INPUT_ELEMENT_DESC desc = {};
4866 const int matrixSlice = it->matrixSlice();
4867 if (matrixSlice < 0) {
4868 desc.SemanticName =
"TEXCOORD";
4869 desc.SemanticIndex = UINT(it->location());
4873 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4874 matrixSliceSemantics.append(sem);
4875 desc.SemanticName = matrixSliceSemantics.last().constData();
4876 desc.SemanticIndex = UINT(matrixSlice);
4878 desc.Format = toD3DAttributeFormat(it->format());
4879 desc.InputSlot = UINT(it->binding());
4880 desc.AlignedByteOffset = it->offset();
4881 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4882 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4883 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4884 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4886 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4888 inputDescs.append(desc);
4890 if (!inputDescs.isEmpty()) {
4891 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4892 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4894 qWarning(
"Failed to create input layout: %s",
4895 qPrintable(QSystemError::windowsComString(hr)));
4901 rhiD->pipelineCreationEnd();
4903 rhiD->registerResource(
this);
4922 cs.shader->Release();
4923 cs.shader =
nullptr;
4924 cs.nativeResourceBindingMap.clear();
4928 rhiD->unregisterResource(
this);
4937 rhiD->pipelineCreationStart();
4939 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
4940 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4941 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
4942 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4945 QShaderKey shaderKey;
4946 UINT compileFlags = 0;
4947 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4948 compileFlags |= D3DCOMPILE_DEBUG;
4950 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
4951 &error, &shaderKey);
4952 if (bytecode.isEmpty()) {
4953 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
4957 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
4959 qWarning(
"Failed to create compute shader: %s",
4960 qPrintable(QSystemError::windowsComString(hr)));
4964 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
4966 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
4969 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
4972 cs.shader->AddRef();
4974 rhiD->pipelineCreationEnd();
4976 rhiD->registerResource(
this);
5001 D3D11_QUERY_DESC queryDesc = {};
5003 if (!disjointQuery[i]) {
5004 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5005 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5007 qWarning(
"Failed to create timestamp disjoint query: %s",
5008 qPrintable(QSystemError::windowsComString(hr)));
5012 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5013 for (
int j = 0; j < 2; ++j) {
5014 const int idx = 2 * i + j;
5016 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5018 qWarning(
"Failed to create timestamp query: %s",
5019 qPrintable(QSystemError::windowsComString(hr)));
5032 if (disjointQuery[i]) {
5033 disjointQuery[i]->Release();
5034 disjointQuery[i] =
nullptr;
5036 for (
int j = 0; j < 2; ++j) {
5039 query[idx]->Release();
5040 query[idx] =
nullptr;
5048 bool result =
false;
5052 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5053 ID3D11Query *tsStart = query[pairIndex * 2];
5054 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5055 quint64 timestamps[2];
5056 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5059 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5060 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5061 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5064 if (!dj.Disjoint && dj.Frequency) {
5065 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5066 *elapsedSec = elapsedMs / 1000.0;
5069 active[pairIndex] =
false;
5078 backBufferTex =
nullptr;
5079 backBufferRtv =
nullptr;
5081 msaaTex[i] =
nullptr;
5082 msaaRtv[i] =
nullptr;
5093 if (backBufferRtv) {
5094 backBufferRtv->Release();
5095 backBufferRtv =
nullptr;
5097 if (backBufferRtvRight) {
5098 backBufferRtvRight->Release();
5099 backBufferRtvRight =
nullptr;
5101 if (backBufferTex) {
5102 backBufferTex->Release();
5103 backBufferTex =
nullptr;
5107 msaaRtv[i]->Release();
5108 msaaRtv[i] =
nullptr;
5111 msaaTex[i]->Release();
5112 msaaTex[i] =
nullptr;
5124 timestamps.destroy();
5126 swapChain->Release();
5127 swapChain =
nullptr;
5130 dcompVisual->Release();
5131 dcompVisual =
nullptr;
5135 dcompTarget->Release();
5136 dcompTarget =
nullptr;
5139 if (frameLatencyWaitableObject) {
5140 CloseHandle(frameLatencyWaitableObject);
5141 frameLatencyWaitableObject =
nullptr;
5144 QDxgiVSyncService::instance()->unregisterWindow(window);
5148 rhiD->unregisterResource(
this);
5151 rhiD->context->Flush();
5167 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5173 return m_window->size() * m_window->devicePixelRatio();
5182 qWarning(
"Attempted to call isFormatSupported() without a window set");
5187 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5188 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5199 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5208 rhiD->registerResource(rpD,
false);
5213 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5215 D3D11_TEXTURE2D_DESC desc = {};
5216 desc.Width = UINT(size.width());
5217 desc.Height = UINT(size.height());
5220 desc.Format = format;
5221 desc.SampleDesc = sampleDesc;
5222 desc.Usage = D3D11_USAGE_DEFAULT;
5223 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5226 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5228 qWarning(
"Failed to create color buffer texture: %s",
5229 qPrintable(QSystemError::windowsComString(hr)));
5233 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5234 rtvDesc.Format = format;
5235 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5236 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5238 qWarning(
"Failed to create color buffer rtv: %s",
5239 qPrintable(QSystemError::windowsComString(hr)));
5253 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5254 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5255 return dcompDevice ?
true :
false;
5267 const bool needsRegistration = !window || window != m_window;
5268 const bool stereo = m_window->format().stereo();
5271 if (window && window != m_window)
5275 m_currentPixelSize = surfacePixelSize();
5276 pixelSize = m_currentPixelSize;
5278 if (pixelSize.isEmpty())
5281 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5286 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5289 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5291 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5292 qPrintable(QSystemError::windowsComString(hr)));
5295 if (dcompTarget && !dcompVisual) {
5296 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5298 qWarning(
"Failed to create DirectComposition visual: %s",
5299 qPrintable(QSystemError::windowsComString(hr)));
5304 if (
window->requestedFormat().alphaBufferSize() <= 0)
5305 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5306 "This may lead to problems.");
5309 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5316 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5317 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5321 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5322 && swapInterval != 0
5323 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5325 if (useFrameLatencyWaitableObject) {
5327 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5331 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5332 colorFormat = DEFAULT_FORMAT;
5333 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5335 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5336 if (m_format != SDR) {
5337 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5340 case HDRExtendedSrgbLinear:
5341 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5342 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5343 srgbAdjustedColorFormat = colorFormat;
5346 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5347 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5348 srgbAdjustedColorFormat = colorFormat;
5357 qWarning(
"The output associated with the window is not HDR capable "
5358 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5368 DXGI_SWAP_CHAIN_DESC1 desc = {};
5369 desc.Width = UINT(pixelSize.width());
5370 desc.Height = UINT(pixelSize.height());
5371 desc.Format = colorFormat;
5372 desc.SampleDesc.Count = 1;
5373 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5375 desc.Flags = swapChainFlags;
5376 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5377 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5378 desc.Stereo = stereo;
5384 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5389 desc.Scaling = DXGI_SCALING_STRETCH;
5392 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5393 IDXGISwapChain1 *sc1;
5396 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5398 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5403 if (FAILED(hr) && m_format != SDR) {
5404 colorFormat = DEFAULT_FORMAT;
5405 desc.Format = DEFAULT_FORMAT;
5407 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5409 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5412 if (SUCCEEDED(hr)) {
5414 IDXGISwapChain3 *sc3 =
nullptr;
5415 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5416 if (m_format != SDR) {
5417 hr = sc3->SetColorSpace1(hdrColorSpace);
5419 qWarning(
"Failed to set color space on swapchain: %s",
5420 qPrintable(QSystemError::windowsComString(hr)));
5422 if (useFrameLatencyWaitableObject) {
5423 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5424 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5428 if (m_format != SDR)
5429 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5430 if (useFrameLatencyWaitableObject) {
5431 IDXGISwapChain2 *sc2 =
nullptr;
5432 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5433 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5434 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5437 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5442 hr = dcompVisual->SetContent(sc1);
5443 if (SUCCEEDED(hr)) {
5444 hr = dcompTarget->SetRoot(dcompVisual);
5446 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5447 qPrintable(QSystemError::windowsComString(hr)));
5450 qWarning(
"Failed to set content for Direct Composition visual: %s",
5451 qPrintable(QSystemError::windowsComString(hr)));
5455 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5459 qWarning(
"Failed to create D3D11 swapchain: %s"
5460 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5461 qPrintable(QSystemError::windowsComString(hr)),
5462 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5463 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5469 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5470 colorFormat, swapChainFlags);
5471 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5472 qWarning(
"Device loss detected in ResizeBuffers()");
5475 }
else if (FAILED(hr)) {
5476 qWarning(
"Failed to resize D3D11 swapchain: %s",
5477 qPrintable(QSystemError::windowsComString(hr)));
5496 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5498 qWarning(
"Failed to query swapchain backbuffer: %s",
5499 qPrintable(QSystemError::windowsComString(hr)));
5502 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5503 rtvDesc.Format = srgbAdjustedColorFormat;
5504 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5505 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5507 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5508 qPrintable(QSystemError::windowsComString(hr)));
5514 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5515 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5516 rtvDesc.Texture2DArray.ArraySize = 1;
5517 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5519 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5520 qPrintable(QSystemError::windowsComString(hr)));
5527 if (sampleDesc.Count > 1) {
5528 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5533 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5534 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5535 m_depthStencil->sampleCount(), m_sampleCount);
5537 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5538 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5539 m_depthStencil->setPixelSize(pixelSize);
5540 if (!m_depthStencil->create())
5541 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5542 pixelSize.width(), pixelSize.height());
5544 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5545 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5546 pixelSize.width(), pixelSize.height());
5553 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5555 rt.setRenderPassDescriptor(m_renderPassDesc);
5557 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5558 rtD->d.pixelSize = pixelSize;
5559 rtD->d.dpr =
float(
window->devicePixelRatio());
5560 rtD->d.sampleCount =
int(sampleDesc.Count);
5561 rtD->d.colorAttCount = 1;
5562 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5565 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5566 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5567 rtD->d.pixelSize = pixelSize;
5568 rtD->d.dpr =
float(
window->devicePixelRatio());
5569 rtD->d.sampleCount =
int(sampleDesc.Count);
5570 rtD->d.colorAttCount = 1;
5571 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5572 rtD->d.rtv[0] = backBufferRtvRight;
5573 rtD->d.dsv =
ds ?
ds->dsv :
nullptr;
5576 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5577 timestamps.prepare(rhiD);
5581 QDxgiVSyncService::instance()->registerWindow(window);
5583 if (needsRegistration)
5584 rhiD->registerResource(
this);
5592 if (dsv != data->dsv) {
5597 ret |= rtv[i] != data->rtv[i];
5598 rtv[i] = data->rtv[i];
5601 ret |= rtv[i] !=
nullptr;
5604 for (
int i = 0; i < count; i++) {
5605 ret |= uav[i] != uavs[i];
5609 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)
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)