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",
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;
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;
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;
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;
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);
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 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1835 if (img.depth() == 32) {
1836 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1837 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1839 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1840 bpl = img.bytesPerLine();
1841 cmd.args.updateSubRes.src = cbD->retainImage(img);
1844 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1845 cmd.args.updateSubRes.src = cbD->retainImage(img);
1847 box.left = UINT(dp.x());
1848 box.top = UINT(dp.y());
1849 box.right = UINT(dp.x() + size.width());
1850 box.bottom = UINT(dp.y() + size.height());
1851 cmd.args.updateSubRes.hasDstBox =
true;
1852 cmd.args.updateSubRes.dstBox = box;
1853 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1854 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1855 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1856 : subresDesc.sourceSize();
1859 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1863 box.left = UINT(aligned(dp.x(), blockDim.width()));
1864 box.top = UINT(aligned(dp.y(), blockDim.height()));
1865 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1866 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1867 cmd.args.updateSubRes.hasDstBox =
true;
1868 cmd.args.updateSubRes.dstBox = box;
1869 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1870 cmd.args.updateSubRes.srcRowPitch = bpl;
1871 }
else if (!subresDesc.data().isEmpty()) {
1872 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1873 : subresDesc.sourceSize();
1875 if (subresDesc.dataStride())
1876 bpl = subresDesc.dataStride();
1878 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1879 box.left = UINT(dp.x());
1880 box.top = UINT(dp.y());
1881 box.right = UINT(dp.x() + size.width());
1882 box.bottom = UINT(dp.y() + size.height());
1883 cmd.args.updateSubRes.hasDstBox =
true;
1884 cmd.args.updateSubRes.dstBox = box;
1885 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1886 cmd.args.updateSubRes.srcRowPitch = bpl;
1888 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1889 cbD->commands.unget();
1902 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1907 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1908 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1911 cmd.args.updateSubRes.dst = bufD->buffer;
1912 cmd.args.updateSubRes.dstSubRes = 0;
1913 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1914 cmd.args.updateSubRes.srcRowPitch = 0;
1919 box.left = u.offset;
1920 box.top = box.front = 0;
1921 box.back = box.bottom = 1;
1922 box.right = u.offset + u
.data.size();
1923 cmd.args.updateSubRes.hasDstBox =
true;
1924 cmd.args.updateSubRes.dstBox = box;
1927 if (bufD->m_type == QRhiBuffer::Dynamic) {
1928 u.result->data.resize(u.readSize);
1929 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1930 if (u.result->completed)
1931 u.result->completed();
1934 readback.result = u.result;
1935 readback.byteSize = u.readSize;
1937 D3D11_BUFFER_DESC desc = {};
1938 desc.ByteWidth = readback.byteSize;
1939 desc.Usage = D3D11_USAGE_STAGING;
1940 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1941 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1943 qWarning(
"Failed to create buffer: %s",
1944 qPrintable(QSystemError::windowsComString(hr)));
1950 cmd.args.copySubRes.dst = readback.stagingBuf;
1951 cmd.args.copySubRes.dstSubRes = 0;
1952 cmd.args.copySubRes.dstX = 0;
1953 cmd.args.copySubRes.dstY = 0;
1954 cmd.args.copySubRes.dstZ = 0;
1955 cmd.args.copySubRes.src = bufD->buffer;
1956 cmd.args.copySubRes.srcSubRes = 0;
1957 cmd.args.copySubRes.hasSrcBox =
true;
1959 box.left = u.offset;
1960 box.top = box.front = 0;
1961 box.back = box.bottom = 1;
1962 box.right = u.offset + u.readSize;
1963 cmd.args.copySubRes.srcBox = box;
1965 activeBufferReadbacks.append(readback);
1973 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
1974 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
1975 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
1976 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
1983 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1984 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1985 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
1986 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
1987 const QPoint dp = u.desc.destinationTopLeft();
1988 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
1989 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
1990 const QPoint sp = u.desc.sourceTopLeft();
1992 srcBox.left = UINT(sp.x());
1993 srcBox.top = UINT(sp.y());
1994 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
1996 srcBox.right = srcBox.left + UINT(copySize.width());
1997 srcBox.bottom = srcBox.top + UINT(copySize.height());
1998 srcBox.back = srcBox.front + 1;
2001 cmd.args.copySubRes.dst = dstD->textureResource();
2002 cmd.args.copySubRes.dstSubRes = dstSubRes;
2003 cmd.args.copySubRes.dstX = UINT(dp.x());
2004 cmd.args.copySubRes.dstY = UINT(dp.y());
2005 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2006 cmd.args.copySubRes.src = srcD->textureResource();
2007 cmd.args.copySubRes.srcSubRes = srcSubRes;
2008 cmd.args.copySubRes.hasSrcBox =
true;
2009 cmd.args.copySubRes.srcBox = srcBox;
2012 readback.desc = u.rb;
2013 readback.result = u.result;
2015 ID3D11Resource *src;
2016 DXGI_FORMAT dxgiFormat;
2018 QRhiTexture::Format format;
2025 if (texD->sampleDesc.Count > 1) {
2026 qWarning(
"Multisample texture cannot be read back");
2029 src = texD->textureResource();
2030 dxgiFormat = texD->dxgiFormat;
2031 if (u.rb.rect().isValid())
2034 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2035 format = texD->m_format;
2036 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2037 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2041 if (swapChainD->sampleDesc.Count > 1) {
2046 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2047 rcmd.args.resolveSubRes.dstSubRes = 0;
2049 rcmd.args.resolveSubRes.srcSubRes = 0;
2050 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2052 src = swapChainD->backBufferTex;
2053 dxgiFormat = swapChainD->colorFormat;
2054 if (u.rb.rect().isValid())
2057 rect = QRect({0, 0}, swapChainD->pixelSize);
2058 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2059 if (format == QRhiTexture::UnknownFormat)
2062 quint32 byteSize = 0;
2064 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2066 D3D11_TEXTURE2D_DESC desc = {};
2067 desc.Width = UINT(rect.width());
2068 desc.Height = UINT(rect.height());
2071 desc.Format = dxgiFormat;
2072 desc.SampleDesc.Count = 1;
2073 desc.Usage = D3D11_USAGE_STAGING;
2074 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2075 ID3D11Texture2D *stagingTex;
2076 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2078 qWarning(
"Failed to create readback staging texture: %s",
2079 qPrintable(QSystemError::windowsComString(hr)));
2085 cmd.args.copySubRes.dst = stagingTex;
2086 cmd.args.copySubRes.dstSubRes = 0;
2087 cmd.args.copySubRes.dstX = 0;
2088 cmd.args.copySubRes.dstY = 0;
2089 cmd.args.copySubRes.dstZ = 0;
2090 cmd.args.copySubRes.src = src;
2091 cmd.args.copySubRes.srcSubRes = subres;
2093 D3D11_BOX srcBox = {};
2094 srcBox.left = UINT(rect.left());
2095 srcBox.top = UINT(rect.top());
2096 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2098 srcBox.right = srcBox.left + desc.Width;
2099 srcBox.bottom = srcBox.top + desc.Height;
2100 srcBox.back = srcBox.front + 1;
2101 cmd.args.copySubRes.hasSrcBox =
true;
2102 cmd.args.copySubRes.srcBox = srcBox;
2104 readback.stagingTex = stagingTex;
2105 readback.byteSize = byteSize;
2107 readback.pixelSize = rect.size();
2108 readback.format = format;
2110 activeTextureReadbacks.append(readback);
2112 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2115 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2124 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2126 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2128 readback.result->format = readback.format;
2129 readback.result->pixelSize = readback.pixelSize;
2131 D3D11_MAPPED_SUBRESOURCE mp;
2132 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2133 if (SUCCEEDED(hr)) {
2134 readback.result->data.resize(
int(readback.byteSize));
2137 char *dst = readback.result->data.data();
2138 char *src =
static_cast<
char *>(mp.pData);
2139 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2140 memcpy(dst, src, readback.bpl);
2141 dst += readback.bpl;
2144 context->Unmap(readback.stagingTex, 0);
2146 qWarning(
"Failed to map readback staging texture: %s",
2147 qPrintable(QSystemError::windowsComString(hr)));
2150 readback.stagingTex->Release();
2152 if (readback.result->completed)
2153 completedCallbacks.append(readback.result->completed);
2155 activeTextureReadbacks.removeLast();
2158 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2161 D3D11_MAPPED_SUBRESOURCE mp;
2162 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2163 if (SUCCEEDED(hr)) {
2164 readback.result->data.resize(
int(readback.byteSize));
2165 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2166 context->Unmap(readback.stagingBuf, 0);
2168 qWarning(
"Failed to map readback staging texture: %s",
2169 qPrintable(QSystemError::windowsComString(hr)));
2172 readback.stagingBuf->Release();
2174 if (readback.result->completed)
2175 completedCallbacks.append(readback.result->completed);
2177 activeBufferReadbacks.removeLast();
2180 for (
auto f : completedCallbacks)
2186 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2192 QRhiRenderTarget *rt,
2193 const QColor &colorClearValue,
2194 const QRhiDepthStencilClearValue &depthStencilClearValue,
2195 QRhiResourceUpdateBatch *resourceUpdates,
2201 if (resourceUpdates)
2204 bool wantsColorClear =
true;
2205 bool wantsDsClear =
true;
2207 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2209 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2210 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2211 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2219 fbCmd.args.setRenderTarget.rt = rt;
2223 clearCmd.args.clear.rt = rt;
2224 clearCmd.args.clear.mask = 0;
2230 clearCmd.args.clear.c[0] = colorClearValue.redF();
2231 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2232 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2233 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2234 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2235 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2238 cbD->currentTarget = rt;
2248 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2250 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2253 const QRhiColorAttachment &colorAtt(*it);
2254 if (!colorAtt.resolveTexture())
2260 Q_ASSERT(srcTexD || srcRbD);
2263 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2264 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2265 UINT(colorAtt.resolveLayer()),
2266 dstTexD->mipLevelCount);
2268 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2269 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2270 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2271 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2272 cbD->commands.unget();
2275 if (srcTexD->sampleDesc.Count <= 1) {
2276 qWarning(
"Cannot resolve a non-multisample texture");
2277 cbD->commands.unget();
2280 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2281 qWarning(
"Resolve source and destination sizes do not match");
2282 cbD->commands.unget();
2286 cmd.args.resolveSubRes.src = srcRbD->tex;
2287 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2288 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2289 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2290 cbD->commands.unget();
2293 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2294 qWarning(
"Resolve source and destination sizes do not match");
2295 cbD->commands.unget();
2299 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2300 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2302 if (rtTex->m_desc.depthResolveTexture())
2303 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2307 cbD->currentTarget =
nullptr;
2309 if (resourceUpdates)
2314 QRhiResourceUpdateBatch *resourceUpdates,
2320 if (resourceUpdates)
2338 if (resourceUpdates)
2347 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2349 if (pipelineChanged) {
2350 cbD->currentGraphicsPipeline =
nullptr;
2351 cbD->currentComputePipeline = psD;
2352 cbD->currentPipelineGeneration = psD->generation;
2356 cmd.args.bindComputePipeline.ps = psD;
2367 cmd.args.dispatch.x = UINT(x);
2368 cmd.args.dispatch.y = UINT(y);
2369 cmd.args.dispatch.z = UINT(z);
2374 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2376 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2377 if (!map || map->isEmpty())
2378 return { binding, binding };
2380 auto it = map->constFind(binding);
2381 if (it != map->cend())
2391 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2393 srbD->resourceBatches.clear();
2399 ID3D11Buffer *buffer;
2400 uint offsetInConstants;
2401 uint sizeInConstants;
2405 ID3D11ShaderResourceView *srv;
2409 ID3D11SamplerState *sampler;
2413 ID3D11UnorderedAccessView *uav;
2415 QVarLengthArray<Buffer, 8> buffers;
2416 QVarLengthArray<Texture, 8> textures;
2417 QVarLengthArray<Sampler, 8> samplers;
2418 QVarLengthArray<Uav, 8> uavs;
2421 for (
const Buffer &buf : buffers) {
2422 batches.ubufs.feed(buf.breg, buf.buffer);
2423 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2424 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2425 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2431 for (
const Texture &t : textures)
2432 batches.shaderresources.feed(t.treg, t.srv);
2433 for (
const Sampler &s : samplers)
2434 batches.samplers.feed(s.sreg, s.sampler);
2439 for (
const Stage::Uav &u : uavs)
2440 batches.uavs.feed(u.ureg, u.uav);
2445 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2446 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2449 case QRhiShaderResourceBinding::UniformBuffer:
2452 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2453 bd.ubuf.id = bufD->m_id;
2454 bd.ubuf.generation = bufD->generation;
2461 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2465 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2466 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2467 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2468 if (nativeBinding.first >= 0)
2469 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2471 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2472 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2473 if (nativeBinding.first >= 0)
2474 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2476 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2477 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2478 if (nativeBinding.first >= 0)
2479 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2481 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2482 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2483 if (nativeBinding.first >= 0)
2484 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2486 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2487 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2488 if (nativeBinding.first >= 0)
2489 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2491 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2492 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2493 if (nativeBinding.first >= 0)
2494 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2498 case QRhiShaderResourceBinding::SampledTexture:
2499 case QRhiShaderResourceBinding::Texture:
2500 case QRhiShaderResourceBinding::Sampler:
2502 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2503 bd.stex.count = data->count;
2504 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2505 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2506 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2507 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2508 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2509 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2513 for (
int elem = 0; elem < data->count; ++elem) {
2516 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2517 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2518 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2519 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2524 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2525 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2526 : (samplerD ? nativeBindingVert.first : -1);
2527 if (nativeBindingVert.first >= 0 && texD)
2528 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2529 if (samplerBinding >= 0)
2530 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2532 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2533 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2534 : (samplerD ? nativeBindingHull.first : -1);
2535 if (nativeBindingHull.first >= 0 && texD)
2536 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2537 if (samplerBinding >= 0)
2538 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2540 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2541 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2542 : (samplerD ? nativeBindingDomain.first : -1);
2543 if (nativeBindingDomain.first >= 0 && texD)
2544 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2545 if (samplerBinding >= 0)
2546 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2548 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2549 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2550 : (samplerD ? nativeBindingGeom.first : -1);
2551 if (nativeBindingGeom.first >= 0 && texD)
2552 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2553 if (samplerBinding >= 0)
2554 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2556 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2557 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2558 : (samplerD ? nativeBindingFrag.first : -1);
2559 if (nativeBindingFrag.first >= 0 && texD)
2560 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2561 if (samplerBinding >= 0)
2562 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2564 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2565 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2566 : (samplerD ? nativeBindingComp.first : -1);
2567 if (nativeBindingComp.first >= 0 && texD)
2568 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2569 if (samplerBinding >= 0)
2570 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2575 case QRhiShaderResourceBinding::ImageLoad:
2576 case QRhiShaderResourceBinding::ImageStore:
2577 case QRhiShaderResourceBinding::ImageLoadStore:
2580 bd.simage.id = texD->m_id;
2581 bd.simage.generation = texD->generation;
2582 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2583 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2584 if (nativeBinding.first >= 0) {
2585 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2587 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2589 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2590 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2591 if (nativeBinding.first >= 0) {
2592 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2594 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2597 qWarning(
"Unordered access only supported at fragment/compute stage");
2601 case QRhiShaderResourceBinding::BufferLoad:
2602 case QRhiShaderResourceBinding::BufferStore:
2603 case QRhiShaderResourceBinding::BufferLoadStore:
2606 bd.sbuf.id = bufD->m_id;
2607 bd.sbuf.generation = bufD->generation;
2608 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2609 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2610 if (nativeBinding.first >= 0) {
2611 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2613 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2616 qWarning(
"Unordered access only supported at compute stage");
2631 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2632 return a.breg < b.breg;
2634 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2635 return a.treg < b.treg;
2637 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2638 return a.sreg < b.sreg;
2640 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2641 return a.ureg < b.ureg;
2645 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2646 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2647 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2648 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2649 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2650 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2652 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2653 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2654 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2655 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2656 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2657 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2659 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2660 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2668 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2670 D3D11_MAPPED_SUBRESOURCE mp;
2671 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2672 if (SUCCEEDED(hr)) {
2673 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2674 context->Unmap(bufD->buffer, 0);
2676 qWarning(
"Failed to map buffer: %s",
2677 qPrintable(QSystemError::windowsComString(hr)));
2683 const QRhiBatchedBindings<UINT> *originalBindings,
2684 const QRhiBatchedBindings<UINT> *staticOffsets,
2685 const uint *dynOfsPairs,
int dynOfsPairCount)
2687 const int count = staticOffsets->batches[batchIndex].resources.count();
2690 for (
int b = 0; b < count; ++b) {
2691 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2692 for (
int di = 0; di < dynOfsPairCount; ++di) {
2693 const uint binding = dynOfsPairs[2 * di];
2696 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2697 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2698 offsets[b] = offsetInConstants;
2707 if (startSlot + countSlots > maxSlots) {
2708 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2709 resType, countSlots, startSlot, maxSlots);
2710 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2715#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2716 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2717 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2718 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2719 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2720 batches.ubufs.batches[i].resources.count(),
2721 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2722 #stagePrefixU " cbuf");
2724 if (!dynOfsPairCount) {
2725 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2727 batches.ubufs.batches[i].resources.constData(),
2728 batches.ubufoffsets.batches[i].resources.constData(),
2729 batches.ubufsizes.batches[i].resources.constData());
2731 applyDynamicOffsets(offsets, i,
2732 &batches.ubuforigbindings, &batches.ubufoffsets,
2733 dynOfsPairs, dynOfsPairCount);
2734 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2736 batches.ubufs.batches[i].resources.constData(),
2738 batches.ubufsizes.batches[i].resources.constData());
2744#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2745 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2746 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2747 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2748 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2750 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2752 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2753 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2754 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2756 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2757 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2758 int(batch.startBinding + count) - 1
);
2763#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2764 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2765 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2766 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2769 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2771 batch.resources.constData(),
2773 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2774 int(batch.startBinding + count) - 1
);
2780 const uint *dynOfsPairs,
int dynOfsPairCount,
2781 bool offsetOnlyChange,
2794 if (!offsetOnlyChange) {
2804 if (allResourceBatches.fsUavBatches.present) {
2805 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2806 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2808 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2810 if (rtUavState.update(rtD, batch.resources.constData(), count)) {
2811 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv,
2812 UINT(rtD->colorAttCount), count, batch.resources.constData(),
nullptr);
2814 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2815 int(batch.startBinding + count) - 1);
2828 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2834 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2835 for (
int i = 0; i < count; ++i)
2836 nullbufs[i] =
nullptr;
2837 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2838 for (
int i = 0; i < count; ++i)
2840 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2841 for (
int i = 0; i < count; ++i)
2843 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2853 if (nullsrvCount > 0) {
2854 QVarLengthArray<ID3D11ShaderResourceView *,
2855 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2856 for (
int i = 0; i < nullsrvs.count(); ++i)
2857 nullsrvs[i] =
nullptr;
2859 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2863 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2867 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2871 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2875 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2879 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2885 rtUavState.update(rtD);
2886 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv, 0, 0,
nullptr,
nullptr);
2891 QVarLengthArray<ID3D11UnorderedAccessView *,
2892 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2893 for (
int i = 0; i < nulluavCount; ++i)
2894 nulluavs[i] =
nullptr;
2895 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2900#define SETSHADER(StageL, StageU)
2901 if (psD->StageL.shader) {
2902 context->StageU##SetShader(psD->StageL.shader, nullptr, 0
);
2903 currentShaderMask |= StageU##MaskBit;
2904 } else if (currentShaderMask & StageU##MaskBit) {
2905 context->StageU##SetShader(nullptr, nullptr, 0
);
2906 currentShaderMask &= ~StageU##MaskBit;
2911 quint32 stencilRef = 0;
2912 float blendConstants[] = { 1, 1, 1, 1 };
2913 enum ActiveShaderMask {
2920 int currentShaderMask = 0xFF;
2926 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2929 case QD3D11CommandBuffer::Command::BeginFrame:
2930 if (cmd.args.beginFrame.tsDisjointQuery)
2931 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2932 if (cmd.args.beginFrame.tsQuery) {
2933 if (cmd.args.beginFrame.swapchainData) {
2939 rtUavState.update(rtD);
2940 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2943 context->End(cmd.args.beginFrame.tsQuery);
2946 case QD3D11CommandBuffer::Command::EndFrame:
2947 if (cmd.args.endFrame.tsQuery)
2948 context->End(cmd.args.endFrame.tsQuery);
2949 if (cmd.args.endFrame.tsDisjointQuery)
2950 context->End(cmd.args.endFrame.tsDisjointQuery);
2958 if (rtUavState.update(rtD))
2959 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2967 for (
int i = 0; i < rtD->colorAttCount; ++i)
2968 context->ClearRenderTargetView(rtD->rtv[i], cmd.args.clear.c);
2971 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
2972 ds |= D3D11_CLEAR_DEPTH;
2973 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
2974 ds |= D3D11_CLEAR_STENCIL;
2976 context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
2982 v.TopLeftX = cmd.args.viewport.x;
2983 v.TopLeftY = cmd.args.viewport.y;
2984 v.Width = cmd.args.viewport.w;
2985 v.Height = cmd.args.viewport.h;
2986 v.MinDepth = cmd.args.viewport.d0;
2987 v.MaxDepth = cmd.args.viewport.d1;
2988 context->RSSetViewports(1, &v);
2994 r.left = cmd.args.scissor.x;
2995 r.top = cmd.args.scissor.y;
2997 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
2998 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
2999 context->RSSetScissorRects(1, &r);
3005 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3006 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3007 UINT(cmd.args.bindVertexBuffers.slotCount),
3008 cmd.args.bindVertexBuffers.buffers,
3009 cmd.args.bindVertexBuffers.strides,
3010 cmd.args.bindVertexBuffers.offsets);
3014 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3015 cmd.args.bindIndexBuffer.format,
3016 cmd.args.bindIndexBuffer.offset);
3026 context->IASetPrimitiveTopology(psD->d3dTopology);
3027 context->IASetInputLayout(psD->inputLayout);
3028 context->OMSetDepthStencilState(psD->dsState, stencilRef);
3029 context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
3030 context->RSSetState(psD->rastState);
3033 case QD3D11CommandBuffer::Command::BindShaderResources:
3034 bindShaderResources(cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3035 cmd.args.bindShaderResources.dynamicOffsetPairs,
3036 cmd.args.bindShaderResources.dynamicOffsetCount,
3037 cmd.args.bindShaderResources.offsetOnlyChange,
3042 stencilRef = cmd.args.stencilRef.ref;
3043 context->OMSetDepthStencilState(cmd.args.stencilRef.ps->dsState, stencilRef);
3046 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3047 context->OMSetBlendState(cmd.args.blendConstants.ps->blendState, blendConstants, 0xffffffff);
3050 if (cmd.args.draw.ps) {
3051 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3052 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3054 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3055 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3057 qWarning(
"No graphics pipeline active for draw; ignored");
3061 if (cmd.args.drawIndexed.ps) {
3062 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3063 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3064 cmd.args.drawIndexed.vertexOffset);
3066 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3067 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3068 cmd.args.drawIndexed.firstInstance);
3070 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3073 case QD3D11CommandBuffer::Command::UpdateSubRes:
3074 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3075 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3076 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3078 case QD3D11CommandBuffer::Command::CopySubRes:
3079 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3080 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3081 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3082 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3084 case QD3D11CommandBuffer::Command::ResolveSubRes:
3085 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3086 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3087 cmd.args.resolveSubRes.format);
3089 case QD3D11CommandBuffer::Command::GenMip:
3090 context->GenerateMips(cmd.args.genMip.srv);
3092 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3093 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3095 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3096 annotations->EndEvent();
3098 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3099 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3101 case QD3D11CommandBuffer::Command::BindComputePipeline:
3102 context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader,
nullptr, 0);
3104 case QD3D11CommandBuffer::Command::Dispatch:
3105 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3134 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3135 it.value()->Release();
3140 rhiD->unregisterResource(
this);
3146 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3147 u |= D3D11_BIND_VERTEX_BUFFER;
3148 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3149 u |= D3D11_BIND_INDEX_BUFFER;
3150 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3151 u |= D3D11_BIND_CONSTANT_BUFFER;
3152 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3153 u |= D3D11_BIND_UNORDERED_ACCESS;
3162 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3163 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3167 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3168 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3172 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3173 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3175 D3D11_BUFFER_DESC desc = {};
3176 desc.ByteWidth = roundedSize;
3177 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3178 desc.BindFlags = toD3DBufferUsage(m_usage);
3179 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3180 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3183 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3185 qWarning(
"Failed to create buffer: %s",
3186 qPrintable(QSystemError::windowsComString(hr)));
3190 if (m_type == Dynamic) {
3191 dynBuf =
new char[nonZeroSize];
3195 if (!m_objectName.isEmpty())
3196 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3199 rhiD->registerResource(
this);
3205 if (m_type == Dynamic) {
3209 return { { &buffer }, 1 };
3220 Q_ASSERT(m_type == Dynamic);
3221 D3D11_MAPPED_SUBRESOURCE mp;
3223 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3225 qWarning(
"Failed to map buffer: %s",
3226 qPrintable(QSystemError::windowsComString(hr)));
3229 return static_cast<
char *>(mp.pData);
3235 rhiD->context->Unmap(buffer, 0);
3240 auto it = uavs.find(offset);
3241 if (it != uavs.end())
3245 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3246 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3247 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3248 desc.Buffer.FirstElement = offset / 4u;
3249 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3250 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3253 ID3D11UnorderedAccessView *uav =
nullptr;
3254 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3256 qWarning(
"Failed to create UAV: %s",
3257 qPrintable(QSystemError::windowsComString(hr)));
3266 int sampleCount, QRhiRenderBuffer::Flags flags,
3267 QRhiTexture::Format backingFormatHint)
3297 rhiD->unregisterResource(
this);
3305 if (m_pixelSize.isEmpty())
3309 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3311 D3D11_TEXTURE2D_DESC desc = {};
3312 desc.Width = UINT(m_pixelSize.width());
3313 desc.Height = UINT(m_pixelSize.height());
3316 desc.SampleDesc = sampleDesc;
3317 desc.Usage = D3D11_USAGE_DEFAULT;
3319 if (m_type == Color) {
3320 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3321 : toD3DTextureFormat(m_backingFormatHint, {});
3322 desc.Format = dxgiFormat;
3323 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3324 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3326 qWarning(
"Failed to create color renderbuffer: %s",
3327 qPrintable(QSystemError::windowsComString(hr)));
3330 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3331 rtvDesc.Format = dxgiFormat;
3332 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3333 : D3D11_RTV_DIMENSION_TEXTURE2D;
3334 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3336 qWarning(
"Failed to create rtv: %s",
3337 qPrintable(QSystemError::windowsComString(hr)));
3340 }
else if (m_type == DepthStencil) {
3341 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3342 desc.Format = dxgiFormat;
3343 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3344 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3346 qWarning(
"Failed to create depth-stencil buffer: %s",
3347 qPrintable(QSystemError::windowsComString(hr)));
3350 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3351 dsvDesc.Format = dxgiFormat;
3352 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3353 : D3D11_DSV_DIMENSION_TEXTURE2D;
3354 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3356 qWarning(
"Failed to create dsv: %s",
3357 qPrintable(QSystemError::windowsComString(hr)));
3364 if (!m_objectName.isEmpty())
3365 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3368 rhiD->registerResource(
this);
3374 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3375 return m_backingFormatHint;
3377 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3381 int arraySize,
int sampleCount, Flags flags)
3384 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3385 perLevelViews[i] =
nullptr;
3395 if (!tex && !tex3D && !tex1D)
3403 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3404 if (perLevelViews[i]) {
3405 perLevelViews[i]->Release();
3406 perLevelViews[i] =
nullptr;
3425 rhiD->unregisterResource(
this);
3431 case QRhiTexture::Format::D16:
3432 return DXGI_FORMAT_R16_FLOAT;
3433 case QRhiTexture::Format::D24:
3434 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3435 case QRhiTexture::Format::D24S8:
3436 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3437 case QRhiTexture::Format::D32F:
3438 return DXGI_FORMAT_R32_FLOAT;
3439 case QRhiTexture::Format::D32FS8:
3440 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3443 return DXGI_FORMAT_R32_FLOAT;
3450 case QRhiTexture::Format::D16:
3451 return DXGI_FORMAT_D16_UNORM;
3452 case QRhiTexture::Format::D24:
3453 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3454 case QRhiTexture::Format::D24S8:
3455 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3456 case QRhiTexture::Format::D32F:
3457 return DXGI_FORMAT_D32_FLOAT;
3458 case QRhiTexture::Format::D32FS8:
3459 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3462 return DXGI_FORMAT_D32_FLOAT;
3468 if (tex || tex3D || tex1D)
3472 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3475 const bool isDepth = isDepthTextureFormat(m_format);
3476 const bool isCube = m_flags.testFlag(CubeMap);
3477 const bool is3D = m_flags.testFlag(ThreeDimensional);
3478 const bool isArray = m_flags.testFlag(TextureArray);
3479 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3480 const bool is1D = m_flags.testFlag(OneDimensional);
3482 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3483 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3485 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3486 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3487 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3488 if (sampleDesc.Count > 1) {
3490 qWarning(
"Cubemap texture cannot be multisample");
3494 qWarning(
"3D texture cannot be multisample");
3498 qWarning(
"Multisample texture cannot have mipmaps");
3502 if (isDepth && hasMipMaps) {
3503 qWarning(
"Depth texture cannot have mipmaps");
3506 if (isCube && is3D) {
3507 qWarning(
"Texture cannot be both cube and 3D");
3510 if (isArray && is3D) {
3511 qWarning(
"Texture cannot be both array and 3D");
3514 if (isCube && is1D) {
3515 qWarning(
"Texture cannot be both cube and 1D");
3519 qWarning(
"Texture cannot be both 1D and 3D");
3522 if (m_depth > 1 && !is3D) {
3523 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3526 if (m_arraySize > 0 && !isArray) {
3527 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3530 if (m_arraySize < 1 && isArray) {
3531 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3536 *adjustedSize = size;
3544 const bool isDepth = isDepthTextureFormat(m_format);
3545 const bool isCube = m_flags.testFlag(CubeMap);
3546 const bool is3D = m_flags.testFlag(ThreeDimensional);
3547 const bool isArray = m_flags.testFlag(TextureArray);
3548 const bool is1D = m_flags.testFlag(OneDimensional);
3550 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3551 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3553 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3554 srvDesc.TextureCube.MipLevels = mipLevelCount;
3558 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3559 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3560 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3561 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3562 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3564 srvDesc.Texture1DArray.FirstArraySlice = 0;
3565 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3568 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3569 srvDesc.Texture1D.MipLevels = mipLevelCount;
3571 }
else if (isArray) {
3572 if (sampleDesc.Count > 1) {
3573 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3574 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3575 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3576 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3578 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3579 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3582 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3583 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3584 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3585 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3586 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3588 srvDesc.Texture2DArray.FirstArraySlice = 0;
3589 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3593 if (sampleDesc.Count > 1) {
3594 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3596 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3597 srvDesc.Texture3D.MipLevels = mipLevelCount;
3599 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3600 srvDesc.Texture2D.MipLevels = mipLevelCount;
3605 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3607 qWarning(
"Failed to create srv: %s",
3608 qPrintable(QSystemError::windowsComString(hr)));
3619 if (!prepareCreate(&size))
3622 const bool isDepth = isDepthTextureFormat(m_format);
3623 const bool isCube = m_flags.testFlag(CubeMap);
3624 const bool is3D = m_flags.testFlag(ThreeDimensional);
3625 const bool isArray = m_flags.testFlag(TextureArray);
3626 const bool is1D = m_flags.testFlag(OneDimensional);
3628 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3629 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3630 if (m_flags.testFlag(RenderTarget)) {
3632 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3634 bindFlags |= D3D11_BIND_RENDER_TARGET;
3636 if (m_flags.testFlag(UsedWithGenerateMips)) {
3638 qWarning(
"Depth texture cannot have mipmaps generated");
3641 bindFlags |= D3D11_BIND_RENDER_TARGET;
3642 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3644 if (m_flags.testFlag(UsedWithLoadStore))
3645 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3649 D3D11_TEXTURE1D_DESC desc = {};
3650 desc.Width = UINT(size.width());
3651 desc.MipLevels = mipLevelCount;
3652 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3653 desc.Format = dxgiFormat;
3654 desc.Usage = D3D11_USAGE_DEFAULT;
3655 desc.BindFlags = bindFlags;
3656 desc.MiscFlags = miscFlags;
3658 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3660 qWarning(
"Failed to create 1D texture: %s",
3661 qPrintable(QSystemError::windowsComString(hr)));
3664 if (!m_objectName.isEmpty())
3665 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3666 m_objectName.constData());
3668 D3D11_TEXTURE2D_DESC desc = {};
3669 desc.Width = UINT(size.width());
3670 desc.Height = UINT(size.height());
3671 desc.MipLevels = mipLevelCount;
3672 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3673 desc.Format = dxgiFormat;
3674 desc.SampleDesc = sampleDesc;
3675 desc.Usage = D3D11_USAGE_DEFAULT;
3676 desc.BindFlags = bindFlags;
3677 desc.MiscFlags = miscFlags;
3679 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3681 qWarning(
"Failed to create 2D texture: %s",
3682 qPrintable(QSystemError::windowsComString(hr)));
3685 if (!m_objectName.isEmpty())
3686 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3688 D3D11_TEXTURE3D_DESC desc = {};
3689 desc.Width = UINT(size.width());
3690 desc.Height = UINT(size.height());
3691 desc.Depth = UINT(qMax(1, m_depth));
3692 desc.MipLevels = mipLevelCount;
3693 desc.Format = dxgiFormat;
3694 desc.Usage = D3D11_USAGE_DEFAULT;
3695 desc.BindFlags = bindFlags;
3696 desc.MiscFlags = miscFlags;
3698 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3700 qWarning(
"Failed to create 3D texture: %s",
3701 qPrintable(QSystemError::windowsComString(hr)));
3704 if (!m_objectName.isEmpty())
3705 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3712 rhiD->registerResource(
this);
3721 if (!prepareCreate())
3724 if (m_flags.testFlag(ThreeDimensional))
3725 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3726 else if (m_flags.testFlags(OneDimensional))
3727 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3729 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3736 rhiD->registerResource(
this);
3742 return { quint64(textureResource()), 0 };
3747 if (perLevelViews[level])
3748 return perLevelViews[level];
3750 const bool isCube = m_flags.testFlag(CubeMap);
3751 const bool isArray = m_flags.testFlag(TextureArray);
3752 const bool is3D = m_flags.testFlag(ThreeDimensional);
3753 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3754 desc.Format = dxgiFormat;
3756 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3757 desc.Texture2DArray.MipSlice = UINT(level);
3758 desc.Texture2DArray.FirstArraySlice = 0;
3759 desc.Texture2DArray.ArraySize = 6;
3760 }
else if (isArray) {
3761 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3762 desc.Texture2DArray.MipSlice = UINT(level);
3763 desc.Texture2DArray.FirstArraySlice = 0;
3764 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3766 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3767 desc.Texture3D.MipSlice = UINT(level);
3768 desc.Texture3D.WSize = UINT(m_depth);
3770 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3771 desc.Texture2D.MipSlice = UINT(level);
3775 ID3D11UnorderedAccessView *uav =
nullptr;
3776 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3778 qWarning(
"Failed to create UAV: %s",
3779 qPrintable(QSystemError::windowsComString(hr)));
3783 perLevelViews[level] = uav;
3788 AddressMode u, AddressMode v, AddressMode w)
3803 samplerState->Release();
3804 samplerState =
nullptr;
3808 rhiD->unregisterResource(
this);
3811static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3813 if (minFilter == QRhiSampler::Nearest) {
3814 if (magFilter == QRhiSampler::Nearest) {
3815 if (mipFilter == QRhiSampler::Linear)
3816 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3818 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3820 if (mipFilter == QRhiSampler::Linear)
3821 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3823 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3826 if (magFilter == QRhiSampler::Nearest) {
3827 if (mipFilter == QRhiSampler::Linear)
3828 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3830 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3832 if (mipFilter == QRhiSampler::Linear)
3833 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3835 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3840 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3846 case QRhiSampler::Repeat:
3847 return D3D11_TEXTURE_ADDRESS_WRAP;
3848 case QRhiSampler::ClampToEdge:
3849 return D3D11_TEXTURE_ADDRESS_CLAMP;
3850 case QRhiSampler::Mirror:
3851 return D3D11_TEXTURE_ADDRESS_MIRROR;
3854 return D3D11_TEXTURE_ADDRESS_CLAMP;
3861 case QRhiSampler::Never:
3862 return D3D11_COMPARISON_NEVER;
3863 case QRhiSampler::Less:
3864 return D3D11_COMPARISON_LESS;
3865 case QRhiSampler::Equal:
3866 return D3D11_COMPARISON_EQUAL;
3867 case QRhiSampler::LessOrEqual:
3868 return D3D11_COMPARISON_LESS_EQUAL;
3869 case QRhiSampler::Greater:
3870 return D3D11_COMPARISON_GREATER;
3871 case QRhiSampler::NotEqual:
3872 return D3D11_COMPARISON_NOT_EQUAL;
3873 case QRhiSampler::GreaterOrEqual:
3874 return D3D11_COMPARISON_GREATER_EQUAL;
3875 case QRhiSampler::Always:
3876 return D3D11_COMPARISON_ALWAYS;
3879 return D3D11_COMPARISON_NEVER;
3888 D3D11_SAMPLER_DESC desc = {};
3889 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3890 if (m_compareOp != Never)
3891 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3892 desc.AddressU = toD3DAddressMode(m_addressU);
3893 desc.AddressV = toD3DAddressMode(m_addressV);
3894 desc.AddressW = toD3DAddressMode(m_addressW);
3895 desc.MaxAnisotropy = 1.0f;
3896 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3897 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3900 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3902 qWarning(
"Failed to create sampler state: %s",
3903 qPrintable(QSystemError::windowsComString(hr)));
3908 rhiD->registerResource(
this);
3927 rhiD->unregisterResource(
this);
3940 rhiD->registerResource(rpD,
false);
3977 return d.sampleCount;
3981 const QRhiTextureRenderTargetDescription &desc,
3999 if (!rtv[0] && !dsv)
4018 rhiD->unregisterResource(
this);
4025 rhiD->registerResource(rpD,
false);
4034 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4035 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4036 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4040 d.colorAttCount = 0;
4042 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4043 d.colorAttCount += 1;
4044 const QRhiColorAttachment &colorAtt(*it);
4045 QRhiTexture *texture = colorAtt.texture();
4046 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4047 Q_ASSERT(texture || rb);
4050 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4051 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4052 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4053 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4054 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4055 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4056 rtvDesc.Texture2DArray.ArraySize = 1;
4057 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4058 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4059 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4060 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4061 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4062 rtvDesc.Texture1DArray.ArraySize = 1;
4064 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4065 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4067 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4068 if (texD->sampleDesc.Count > 1) {
4069 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4070 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4071 rtvDesc.Texture2DMSArray.ArraySize = 1;
4073 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4074 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4075 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4076 rtvDesc.Texture2DArray.ArraySize = 1;
4078 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4079 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4080 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4081 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4082 rtvDesc.Texture3D.WSize = 1;
4084 if (texD->sampleDesc.Count > 1) {
4085 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4087 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4088 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4091 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4093 qWarning(
"Failed to create rtv: %s",
4094 qPrintable(QSystemError::windowsComString(hr)));
4098 if (attIndex == 0) {
4099 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4100 d.sampleCount =
int(texD->sampleDesc.Count);
4105 rtv[attIndex] = rbD->rtv;
4106 if (attIndex == 0) {
4107 d.pixelSize = rbD->pixelSize();
4108 d.sampleCount =
int(rbD->sampleDesc.Count);
4114 if (hasDepthStencil) {
4115 if (m_desc.depthTexture()) {
4118 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4119 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4120 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4121 : D3D11_DSV_DIMENSION_TEXTURE2D;
4122 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4123 if (depthTexD->sampleDesc.Count > 1) {
4124 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4125 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4126 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4127 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4129 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4130 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4133 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4134 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4135 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4136 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4138 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4139 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4143 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4145 qWarning(
"Failed to create dsv: %s",
4146 qPrintable(QSystemError::windowsComString(hr)));
4149 if (d.colorAttCount == 0) {
4150 d.pixelSize = depthTexD->pixelSize();
4151 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4156 dsv = depthRbD->dsv;
4157 if (d.colorAttCount == 0) {
4158 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4159 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4167 for (
int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
4168 d.rtv[i] = i < d.colorAttCount ? rtv[i] :
nullptr;
4171 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4173 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4175 rhiD->registerResource(
this);
4181 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4194 return d.sampleCount;
4209 sortedBindings.clear();
4210 boundResourceData.clear();
4214 rhiD->unregisterResource(
this);
4219 if (!sortedBindings.isEmpty())
4223 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4226 rhiD->updateLayoutDesc(
this);
4228 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4229 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4231 boundResourceData.resize(sortedBindings.count());
4233 for (BoundResourceData &bd : boundResourceData)
4234 memset(&bd, 0,
sizeof(BoundResourceData));
4237 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4238 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4239 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4240 hasDynamicOffset =
true;
4246 rhiD->registerResource(
this,
false);
4252 sortedBindings.clear();
4253 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4254 if (!flags.testFlag(BindingsAreSorted))
4255 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4257 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4258 for (BoundResourceData &bd : boundResourceData)
4259 memset(&bd, 0,
sizeof(BoundResourceData));
4278 s.shader->Release();
4281 s.nativeResourceBindingMap.clear();
4293 blendState->Release();
4294 blendState =
nullptr;
4298 inputLayout->Release();
4299 inputLayout =
nullptr;
4303 rastState->Release();
4304 rastState =
nullptr;
4307 releasePipelineShader(vs);
4308 releasePipelineShader(hs);
4309 releasePipelineShader(ds);
4310 releasePipelineShader(gs);
4311 releasePipelineShader(fs);
4315 rhiD->unregisterResource(
this);
4321 case QRhiGraphicsPipeline::None:
4322 return D3D11_CULL_NONE;
4323 case QRhiGraphicsPipeline::Front:
4324 return D3D11_CULL_FRONT;
4325 case QRhiGraphicsPipeline::Back:
4326 return D3D11_CULL_BACK;
4329 return D3D11_CULL_NONE;
4336 case QRhiGraphicsPipeline::Fill:
4337 return D3D11_FILL_SOLID;
4338 case QRhiGraphicsPipeline::Line:
4339 return D3D11_FILL_WIREFRAME;
4342 return D3D11_FILL_SOLID;
4349 case QRhiGraphicsPipeline::Never:
4350 return D3D11_COMPARISON_NEVER;
4351 case QRhiGraphicsPipeline::Less:
4352 return D3D11_COMPARISON_LESS;
4353 case QRhiGraphicsPipeline::Equal:
4354 return D3D11_COMPARISON_EQUAL;
4355 case QRhiGraphicsPipeline::LessOrEqual:
4356 return D3D11_COMPARISON_LESS_EQUAL;
4357 case QRhiGraphicsPipeline::Greater:
4358 return D3D11_COMPARISON_GREATER;
4359 case QRhiGraphicsPipeline::NotEqual:
4360 return D3D11_COMPARISON_NOT_EQUAL;
4361 case QRhiGraphicsPipeline::GreaterOrEqual:
4362 return D3D11_COMPARISON_GREATER_EQUAL;
4363 case QRhiGraphicsPipeline::Always:
4364 return D3D11_COMPARISON_ALWAYS;
4367 return D3D11_COMPARISON_ALWAYS;
4374 case QRhiGraphicsPipeline::StencilZero:
4375 return D3D11_STENCIL_OP_ZERO;
4376 case QRhiGraphicsPipeline::Keep:
4377 return D3D11_STENCIL_OP_KEEP;
4378 case QRhiGraphicsPipeline::Replace:
4379 return D3D11_STENCIL_OP_REPLACE;
4380 case QRhiGraphicsPipeline::IncrementAndClamp:
4381 return D3D11_STENCIL_OP_INCR_SAT;
4382 case QRhiGraphicsPipeline::DecrementAndClamp:
4383 return D3D11_STENCIL_OP_DECR_SAT;
4384 case QRhiGraphicsPipeline::Invert:
4385 return D3D11_STENCIL_OP_INVERT;
4386 case QRhiGraphicsPipeline::IncrementAndWrap:
4387 return D3D11_STENCIL_OP_INCR;
4388 case QRhiGraphicsPipeline::DecrementAndWrap:
4389 return D3D11_STENCIL_OP_DECR;
4392 return D3D11_STENCIL_OP_KEEP;
4399 case QRhiVertexInputAttribute::Float4:
4400 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4401 case QRhiVertexInputAttribute::Float3:
4402 return DXGI_FORMAT_R32G32B32_FLOAT;
4403 case QRhiVertexInputAttribute::Float2:
4404 return DXGI_FORMAT_R32G32_FLOAT;
4405 case QRhiVertexInputAttribute::Float:
4406 return DXGI_FORMAT_R32_FLOAT;
4407 case QRhiVertexInputAttribute::UNormByte4:
4408 return DXGI_FORMAT_R8G8B8A8_UNORM;
4409 case QRhiVertexInputAttribute::UNormByte2:
4410 return DXGI_FORMAT_R8G8_UNORM;
4411 case QRhiVertexInputAttribute::UNormByte:
4412 return DXGI_FORMAT_R8_UNORM;
4413 case QRhiVertexInputAttribute::UInt4:
4414 return DXGI_FORMAT_R32G32B32A32_UINT;
4415 case QRhiVertexInputAttribute::UInt3:
4416 return DXGI_FORMAT_R32G32B32_UINT;
4417 case QRhiVertexInputAttribute::UInt2:
4418 return DXGI_FORMAT_R32G32_UINT;
4419 case QRhiVertexInputAttribute::UInt:
4420 return DXGI_FORMAT_R32_UINT;
4421 case QRhiVertexInputAttribute::SInt4:
4422 return DXGI_FORMAT_R32G32B32A32_SINT;
4423 case QRhiVertexInputAttribute::SInt3:
4424 return DXGI_FORMAT_R32G32B32_SINT;
4425 case QRhiVertexInputAttribute::SInt2:
4426 return DXGI_FORMAT_R32G32_SINT;
4427 case QRhiVertexInputAttribute::SInt:
4428 return DXGI_FORMAT_R32_SINT;
4429 case QRhiVertexInputAttribute::Half4:
4431 case QRhiVertexInputAttribute::Half3:
4432 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4433 case QRhiVertexInputAttribute::Half2:
4434 return DXGI_FORMAT_R16G16_FLOAT;
4435 case QRhiVertexInputAttribute::Half:
4436 return DXGI_FORMAT_R16_FLOAT;
4437 case QRhiVertexInputAttribute::UShort4:
4439 case QRhiVertexInputAttribute::UShort3:
4440 return DXGI_FORMAT_R16G16B16A16_UINT;
4441 case QRhiVertexInputAttribute::UShort2:
4442 return DXGI_FORMAT_R16G16_UINT;
4443 case QRhiVertexInputAttribute::UShort:
4444 return DXGI_FORMAT_R16_UINT;
4445 case QRhiVertexInputAttribute::SShort4:
4447 case QRhiVertexInputAttribute::SShort3:
4448 return DXGI_FORMAT_R16G16B16A16_SINT;
4449 case QRhiVertexInputAttribute::SShort2:
4450 return DXGI_FORMAT_R16G16_SINT;
4451 case QRhiVertexInputAttribute::SShort:
4452 return DXGI_FORMAT_R16_SINT;
4455 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4462 case QRhiGraphicsPipeline::Triangles:
4463 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4464 case QRhiGraphicsPipeline::TriangleStrip:
4465 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4466 case QRhiGraphicsPipeline::Lines:
4467 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4468 case QRhiGraphicsPipeline::LineStrip:
4469 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4470 case QRhiGraphicsPipeline::Points:
4471 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4472 case QRhiGraphicsPipeline::Patches:
4473 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4474 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4477 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4484 if (c.testFlag(QRhiGraphicsPipeline::R))
4485 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4486 if (c.testFlag(QRhiGraphicsPipeline::G))
4487 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4488 if (c.testFlag(QRhiGraphicsPipeline::B))
4489 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4490 if (c.testFlag(QRhiGraphicsPipeline::A))
4491 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4504 case QRhiGraphicsPipeline::Zero:
4505 return D3D11_BLEND_ZERO;
4506 case QRhiGraphicsPipeline::One:
4507 return D3D11_BLEND_ONE;
4508 case QRhiGraphicsPipeline::SrcColor:
4509 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4510 case QRhiGraphicsPipeline::OneMinusSrcColor:
4511 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4512 case QRhiGraphicsPipeline::DstColor:
4513 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4514 case QRhiGraphicsPipeline::OneMinusDstColor:
4515 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4516 case QRhiGraphicsPipeline::SrcAlpha:
4517 return D3D11_BLEND_SRC_ALPHA;
4518 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4519 return D3D11_BLEND_INV_SRC_ALPHA;
4520 case QRhiGraphicsPipeline::DstAlpha:
4521 return D3D11_BLEND_DEST_ALPHA;
4522 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4523 return D3D11_BLEND_INV_DEST_ALPHA;
4524 case QRhiGraphicsPipeline::ConstantColor:
4525 case QRhiGraphicsPipeline::ConstantAlpha:
4526 return D3D11_BLEND_BLEND_FACTOR;
4527 case QRhiGraphicsPipeline::OneMinusConstantColor:
4528 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4529 return D3D11_BLEND_INV_BLEND_FACTOR;
4530 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4531 return D3D11_BLEND_SRC_ALPHA_SAT;
4532 case QRhiGraphicsPipeline::Src1Color:
4533 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4534 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4535 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4536 case QRhiGraphicsPipeline::Src1Alpha:
4537 return D3D11_BLEND_SRC1_ALPHA;
4538 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4539 return D3D11_BLEND_INV_SRC1_ALPHA;
4542 return D3D11_BLEND_ZERO;
4549 case QRhiGraphicsPipeline::Add:
4550 return D3D11_BLEND_OP_ADD;
4551 case QRhiGraphicsPipeline::Subtract:
4552 return D3D11_BLEND_OP_SUBTRACT;
4553 case QRhiGraphicsPipeline::ReverseSubtract:
4554 return D3D11_BLEND_OP_REV_SUBTRACT;
4555 case QRhiGraphicsPipeline::Min:
4556 return D3D11_BLEND_OP_MIN;
4557 case QRhiGraphicsPipeline::Max:
4558 return D3D11_BLEND_OP_MAX;
4561 return D3D11_BLEND_OP_ADD;
4568 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4569 keyBuilder.addData(source);
4570 return keyBuilder.result().toHex();
4573QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4574 QString *error, QShaderKey *usedShaderKey)
4576 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4577 QShaderCode dxbc = shader.shader(key);
4578 if (!dxbc.shader().isEmpty()) {
4580 *usedShaderKey = key;
4581 return dxbc.shader();
4584 key = { QShader::HlslShader, 50, shaderVariant };
4585 QShaderCode hlslSource = shader.shader(key);
4586 if (hlslSource.shader().isEmpty()) {
4587 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4588 return QByteArray();
4592 *usedShaderKey = key;
4595 switch (shader.stage()) {
4596 case QShader::VertexStage:
4599 case QShader::TessellationControlStage:
4602 case QShader::TessellationEvaluationStage:
4605 case QShader::GeometryStage:
4608 case QShader::FragmentStage:
4611 case QShader::ComputeStage:
4616 return QByteArray();
4620 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4621 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4622 cacheKey.target = target;
4623 cacheKey.entryPoint = hlslSource.entryPoint();
4624 cacheKey.compileFlags = flags;
4625 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4626 if (cacheIt != m_bytecodeCache.constEnd())
4627 return cacheIt.value();
4630 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4631 if (d3dCompile ==
nullptr) {
4632 qWarning(
"Unable to resolve function D3DCompile()");
4633 return QByteArray();
4636 ID3DBlob *bytecode =
nullptr;
4637 ID3DBlob *errors =
nullptr;
4638 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4639 nullptr,
nullptr,
nullptr,
4640 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4641 if (FAILED(hr) || !bytecode) {
4642 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4644 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4645 int(errors->GetBufferSize()));
4648 return QByteArray();
4652 result.resize(
int(bytecode->GetBufferSize()));
4653 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4654 bytecode->Release();
4656 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4657 m_bytecodeCache.insert(cacheKey, result);
4668 rhiD->pipelineCreationStart();
4669 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4672 D3D11_RASTERIZER_DESC rastDesc = {};
4673 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4674 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4675 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4676 rastDesc.DepthBias = m_depthBias;
4677 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4678 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4679 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4680 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4681 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4683 qWarning(
"Failed to create rasterizer state: %s",
4684 qPrintable(QSystemError::windowsComString(hr)));
4688 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4689 dsDesc.DepthEnable = m_depthTest;
4690 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4691 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4692 dsDesc.StencilEnable = m_stencilTest;
4693 if (m_stencilTest) {
4694 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4695 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4696 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4697 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4698 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4699 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4700 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4701 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4702 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4703 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4705 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4707 qWarning(
"Failed to create depth-stencil state: %s",
4708 qPrintable(QSystemError::windowsComString(hr)));
4712 D3D11_BLEND_DESC blendDesc = {};
4713 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4714 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4715 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4716 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4717 blend.BlendEnable = b.enable;
4718 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4719 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4720 blend.BlendOp = toD3DBlendOp(b.opColor);
4721 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4722 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4723 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4724 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4725 blendDesc.RenderTarget[i] = blend;
4727 if (m_targetBlends.isEmpty()) {
4728 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4729 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4730 blendDesc.RenderTarget[0] = blend;
4732 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4734 qWarning(
"Failed to create blend state: %s",
4735 qPrintable(QSystemError::windowsComString(hr)));
4739 QByteArray vsByteCode;
4740 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4741 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4742 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4743 switch (shaderStage.type()) {
4744 case QRhiShaderStage::Vertex:
4745 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4746 vs.shader->AddRef();
4747 vsByteCode = cacheIt->bytecode;
4748 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4750 case QRhiShaderStage::TessellationControl:
4751 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4752 hs.shader->AddRef();
4753 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4755 case QRhiShaderStage::TessellationEvaluation:
4756 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4757 ds.shader->AddRef();
4758 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4760 case QRhiShaderStage::Geometry:
4761 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4762 gs.shader->AddRef();
4763 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4765 case QRhiShaderStage::Fragment:
4766 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4767 fs.shader->AddRef();
4768 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4775 QShaderKey shaderKey;
4776 UINT compileFlags = 0;
4777 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4778 compileFlags |= D3DCOMPILE_DEBUG;
4780 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4781 &error, &shaderKey);
4782 if (bytecode.isEmpty()) {
4783 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4787 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4789 rhiD->clearShaderCache();
4792 switch (shaderStage.type()) {
4793 case QRhiShaderStage::Vertex:
4794 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4796 qWarning(
"Failed to create vertex shader: %s",
4797 qPrintable(QSystemError::windowsComString(hr)));
4800 vsByteCode = bytecode;
4801 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4802 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4803 vs.shader->AddRef();
4805 case QRhiShaderStage::TessellationControl:
4806 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4808 qWarning(
"Failed to create hull shader: %s",
4809 qPrintable(QSystemError::windowsComString(hr)));
4812 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4813 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4814 hs.shader->AddRef();
4816 case QRhiShaderStage::TessellationEvaluation:
4817 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4819 qWarning(
"Failed to create domain shader: %s",
4820 qPrintable(QSystemError::windowsComString(hr)));
4823 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4824 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4825 ds.shader->AddRef();
4827 case QRhiShaderStage::Geometry:
4828 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4830 qWarning(
"Failed to create geometry shader: %s",
4831 qPrintable(QSystemError::windowsComString(hr)));
4834 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4835 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4836 gs.shader->AddRef();
4838 case QRhiShaderStage::Fragment:
4839 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4841 qWarning(
"Failed to create pixel shader: %s",
4842 qPrintable(QSystemError::windowsComString(hr)));
4845 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4846 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4847 fs.shader->AddRef();
4855 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4857 if (!vsByteCode.isEmpty()) {
4858 QByteArrayList matrixSliceSemantics;
4859 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4860 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4863 D3D11_INPUT_ELEMENT_DESC desc = {};
4868 const int matrixSlice = it->matrixSlice();
4869 if (matrixSlice < 0) {
4870 desc.SemanticName =
"TEXCOORD";
4871 desc.SemanticIndex = UINT(it->location());
4875 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4876 matrixSliceSemantics.append(sem);
4877 desc.SemanticName = matrixSliceSemantics.last().constData();
4878 desc.SemanticIndex = UINT(matrixSlice);
4880 desc.Format = toD3DAttributeFormat(it->format());
4881 desc.InputSlot = UINT(it->binding());
4882 desc.AlignedByteOffset = it->offset();
4883 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4884 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4885 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4886 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4888 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4890 inputDescs.append(desc);
4892 if (!inputDescs.isEmpty()) {
4893 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4894 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4896 qWarning(
"Failed to create input layout: %s",
4897 qPrintable(QSystemError::windowsComString(hr)));
4903 rhiD->pipelineCreationEnd();
4905 rhiD->registerResource(
this);
4924 cs.shader->Release();
4925 cs.shader =
nullptr;
4926 cs.nativeResourceBindingMap.clear();
4930 rhiD->unregisterResource(
this);
4939 rhiD->pipelineCreationStart();
4941 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
4942 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4943 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
4944 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4947 QShaderKey shaderKey;
4948 UINT compileFlags = 0;
4949 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4950 compileFlags |= D3DCOMPILE_DEBUG;
4952 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
4953 &error, &shaderKey);
4954 if (bytecode.isEmpty()) {
4955 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
4959 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
4961 qWarning(
"Failed to create compute shader: %s",
4962 qPrintable(QSystemError::windowsComString(hr)));
4966 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
4968 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
4971 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
4974 cs.shader->AddRef();
4976 rhiD->pipelineCreationEnd();
4978 rhiD->registerResource(
this);
5003 D3D11_QUERY_DESC queryDesc = {};
5005 if (!disjointQuery[i]) {
5006 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5007 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5009 qWarning(
"Failed to create timestamp disjoint query: %s",
5010 qPrintable(QSystemError::windowsComString(hr)));
5014 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5015 for (
int j = 0; j < 2; ++j) {
5016 const int idx = 2 * i + j;
5018 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5020 qWarning(
"Failed to create timestamp query: %s",
5021 qPrintable(QSystemError::windowsComString(hr)));
5034 if (disjointQuery[i]) {
5035 disjointQuery[i]->Release();
5036 disjointQuery[i] =
nullptr;
5038 for (
int j = 0; j < 2; ++j) {
5041 query[idx]->Release();
5042 query[idx] =
nullptr;
5050 bool result =
false;
5054 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5055 ID3D11Query *tsStart = query[pairIndex * 2];
5056 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5057 quint64 timestamps[2];
5058 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5061 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5062 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5063 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5066 if (!dj.Disjoint && dj.Frequency) {
5067 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5068 *elapsedSec = elapsedMs / 1000.0;
5071 active[pairIndex] =
false;
5080 backBufferTex =
nullptr;
5081 backBufferRtv =
nullptr;
5083 msaaTex[i] =
nullptr;
5084 msaaRtv[i] =
nullptr;
5095 if (backBufferRtv) {
5096 backBufferRtv->Release();
5097 backBufferRtv =
nullptr;
5099 if (backBufferRtvRight) {
5100 backBufferRtvRight->Release();
5101 backBufferRtvRight =
nullptr;
5103 if (backBufferTex) {
5104 backBufferTex->Release();
5105 backBufferTex =
nullptr;
5109 msaaRtv[i]->Release();
5110 msaaRtv[i] =
nullptr;
5113 msaaTex[i]->Release();
5114 msaaTex[i] =
nullptr;
5126 timestamps.destroy();
5128 swapChain->Release();
5129 swapChain =
nullptr;
5132 dcompVisual->Release();
5133 dcompVisual =
nullptr;
5137 dcompTarget->Release();
5138 dcompTarget =
nullptr;
5141 if (frameLatencyWaitableObject) {
5142 CloseHandle(frameLatencyWaitableObject);
5143 frameLatencyWaitableObject =
nullptr;
5146 QDxgiVSyncService::instance()->unregisterWindow(window);
5150 rhiD->unregisterResource(
this);
5153 rhiD->context->Flush();
5169 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5175 return m_window->size() * m_window->devicePixelRatio();
5184 qWarning(
"Attempted to call isFormatSupported() without a window set");
5189 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5190 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5201 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5210 rhiD->registerResource(rpD,
false);
5215 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5217 D3D11_TEXTURE2D_DESC desc = {};
5218 desc.Width = UINT(size.width());
5219 desc.Height = UINT(size.height());
5222 desc.Format = format;
5223 desc.SampleDesc = sampleDesc;
5224 desc.Usage = D3D11_USAGE_DEFAULT;
5225 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5228 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5230 qWarning(
"Failed to create color buffer texture: %s",
5231 qPrintable(QSystemError::windowsComString(hr)));
5235 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5236 rtvDesc.Format = format;
5237 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5238 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5240 qWarning(
"Failed to create color buffer rtv: %s",
5241 qPrintable(QSystemError::windowsComString(hr)));
5255 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5256 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5257 return dcompDevice ?
true :
false;
5269 const bool needsRegistration = !window || window != m_window;
5270 const bool stereo = m_window->format().stereo();
5273 if (window && window != m_window)
5277 m_currentPixelSize = surfacePixelSize();
5278 pixelSize = m_currentPixelSize;
5280 if (pixelSize.isEmpty())
5283 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5288 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5291 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5293 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5294 qPrintable(QSystemError::windowsComString(hr)));
5297 if (dcompTarget && !dcompVisual) {
5298 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5300 qWarning(
"Failed to create DirectComposition visual: %s",
5301 qPrintable(QSystemError::windowsComString(hr)));
5306 if (
window->requestedFormat().alphaBufferSize() <= 0)
5307 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5308 "This may lead to problems.");
5311 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5318 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5319 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5323 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5324 && swapInterval != 0
5325 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5327 if (useFrameLatencyWaitableObject) {
5329 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5333 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5334 colorFormat = DEFAULT_FORMAT;
5335 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5337 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5338 if (m_format != SDR) {
5339 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5342 case HDRExtendedSrgbLinear:
5343 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5344 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5345 srgbAdjustedColorFormat = colorFormat;
5348 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5349 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5350 srgbAdjustedColorFormat = colorFormat;
5359 qWarning(
"The output associated with the window is not HDR capable "
5360 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5370 DXGI_SWAP_CHAIN_DESC1 desc = {};
5371 desc.Width = UINT(pixelSize.width());
5372 desc.Height = UINT(pixelSize.height());
5373 desc.Format = colorFormat;
5374 desc.SampleDesc.Count = 1;
5375 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5377 desc.Flags = swapChainFlags;
5378 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5379 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5380 desc.Stereo = stereo;
5386 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5391 desc.Scaling = DXGI_SCALING_STRETCH;
5394 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5395 IDXGISwapChain1 *sc1;
5398 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5400 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5405 if (FAILED(hr) && m_format != SDR) {
5406 colorFormat = DEFAULT_FORMAT;
5407 desc.Format = DEFAULT_FORMAT;
5409 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5411 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5414 if (SUCCEEDED(hr)) {
5416 IDXGISwapChain3 *sc3 =
nullptr;
5417 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5418 if (m_format != SDR) {
5419 hr = sc3->SetColorSpace1(hdrColorSpace);
5421 qWarning(
"Failed to set color space on swapchain: %s",
5422 qPrintable(QSystemError::windowsComString(hr)));
5424 if (useFrameLatencyWaitableObject) {
5425 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5426 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5430 if (m_format != SDR)
5431 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5432 if (useFrameLatencyWaitableObject) {
5433 IDXGISwapChain2 *sc2 =
nullptr;
5434 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5435 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5436 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5439 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5444 hr = dcompVisual->SetContent(sc1);
5445 if (SUCCEEDED(hr)) {
5446 hr = dcompTarget->SetRoot(dcompVisual);
5448 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5449 qPrintable(QSystemError::windowsComString(hr)));
5452 qWarning(
"Failed to set content for Direct Composition visual: %s",
5453 qPrintable(QSystemError::windowsComString(hr)));
5457 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5461 qWarning(
"Failed to create D3D11 swapchain: %s"
5462 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5463 qPrintable(QSystemError::windowsComString(hr)),
5464 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5465 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5471 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5472 colorFormat, swapChainFlags);
5473 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5474 qWarning(
"Device loss detected in ResizeBuffers()");
5477 }
else if (FAILED(hr)) {
5478 qWarning(
"Failed to resize D3D11 swapchain: %s",
5479 qPrintable(QSystemError::windowsComString(hr)));
5498 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5500 qWarning(
"Failed to query swapchain backbuffer: %s",
5501 qPrintable(QSystemError::windowsComString(hr)));
5504 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5505 rtvDesc.Format = srgbAdjustedColorFormat;
5506 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5507 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5509 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5510 qPrintable(QSystemError::windowsComString(hr)));
5516 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5517 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5518 rtvDesc.Texture2DArray.ArraySize = 1;
5519 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5521 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5522 qPrintable(QSystemError::windowsComString(hr)));
5529 if (sampleDesc.Count > 1) {
5530 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5535 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5536 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5537 m_depthStencil->sampleCount(), m_sampleCount);
5539 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5540 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5541 m_depthStencil->setPixelSize(pixelSize);
5542 if (!m_depthStencil->create())
5543 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5544 pixelSize.width(), pixelSize.height());
5546 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5547 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5548 pixelSize.width(), pixelSize.height());
5555 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5557 rt.setRenderPassDescriptor(m_renderPassDesc);
5559 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5560 rtD->d.pixelSize = pixelSize;
5561 rtD->d.dpr =
float(
window->devicePixelRatio());
5562 rtD->d.sampleCount =
int(sampleDesc.Count);
5563 rtD->d.colorAttCount = 1;
5564 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5567 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5568 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5569 rtD->d.pixelSize = pixelSize;
5570 rtD->d.dpr =
float(
window->devicePixelRatio());
5571 rtD->d.sampleCount =
int(sampleDesc.Count);
5572 rtD->d.colorAttCount = 1;
5573 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5574 rtD->d.rtv[0] = backBufferRtvRight;
5575 rtD->d.dsv =
ds ?
ds->dsv :
nullptr;
5578 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5579 timestamps.prepare(rhiD);
5583 QDxgiVSyncService::instance()->registerWindow(window);
5585 if (needsRegistration)
5586 rhiD->registerResource(
this);
5594 if (dsv != data->dsv) {
5599 ret |= rtv[i] != data->rtv[i];
5600 rtv[i] = data->rtv[i];
5603 ret |= rtv[i] !=
nullptr;
5606 for (
int i = 0; i < count; i++) {
5607 ret |= uav[i] != uavs[i];
5611 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
const char * constData() const
int gsHighestActiveSrvBinding
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int dsHighestActiveSrvBinding
bool isYUpInNDC() const override
QRhiSwapChain * createSwapChain() override
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
bool isFeatureSupported(QRhi::Feature feature) const override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
bool isDeviceLost() const override
bool vsHasIndexBufferBound
void executeBufferHostWrites(QD3D11Buffer *bufD)
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
QRhiStats statistics() override
QList< QSize > supportedShadingRates(int sampleCount) const override
QRhiComputePipeline * createComputePipeline() override
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override
QRhi::FrameOpResult finish() override
void setVertexInput(QRhiCommandBuffer *cb, int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat) override
QRhiGraphicsPipeline * createGraphicsPipeline() override
QRhiShaderResourceBindings * createShaderResourceBindings() override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QList< int > supportedSampleCounts() const override
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
bool isYUpInFramebuffer() const override
int resourceLimit(QRhi::ResourceLimit limit) const override
void beginExternal(QRhiCommandBuffer *cb) override
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void setPipelineCacheData(const QByteArray &data) override
void executeCommandBuffer(QD3D11CommandBuffer *cbD)
void debugMarkEnd(QRhiCommandBuffer *cb) override
void releaseCachedResources() override
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
bool importedDeviceAndContext
void resetShaderResources(QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState)
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
bool supportsAllowTearing
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
void endExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
QRhiShadingRateMap * createShadingRateMap() override
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
bool useLegacySwapchainModel
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
bool makeThreadLocalNativeContextCurrent() override
bool create(QRhi::Flags flags) override
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
static void applyDynamicOffsets(UINT *offsets, int batchIndex, const QRhiBatchedBindings< UINT > *originalBindings, const QRhiBatchedBindings< UINT > *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount)
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
#define SETUAVBATCH(stagePrefixL, stagePrefixU)
static QByteArray sourceHash(const QByteArray &source)
#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
static const int RBM_HULL
static uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
static std::pair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
static const int RBM_FRAGMENT
#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
Int aligned(Int v, Int byteAlign)
\variable QRhiVulkanQueueSubmitParams::waitSemaphoreCount
static DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
static D3D11_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f, bool rgb)
static const int RBM_VERTEX
static D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
#define D3D11_1_UAV_SLOT_COUNT
static const int RBM_DOMAIN
static D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
static QD3D11RenderTargetData * rtData(QRhiRenderTarget *rt)
static UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
static D3D11_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
void releasePipelineShader(T &s)
static D3D11_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
static DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
static const int RBM_GEOMETRY
static D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
static IDXGIFactory1 * createDXGIFactory2()
static D3D11_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
static bool isDepthTextureFormat(QRhiTexture::Format format)
static const int RBM_COMPUTE
static D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
#define SETSHADER(StageL, StageU)
static DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
static const DXGI_FORMAT DEFAULT_FORMAT
static uint clampedResourceCount(uint startSlot, int countSlots, uint maxSlots, const char *resType)
#define D3D11_VS_INPUT_REGISTER_COUNT
#define DXGI_ADAPTER_FLAG_SOFTWARE
\variable QRhiD3D11NativeHandles::dev
static QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
static D3D11_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
static DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
static const int RBM_SUPPORTED_STAGES
bool hasPendingDynamicUpdates
void endFullDynamicBufferUpdateForCurrentFrame() override
To be called when the entire contents of the buffer data has been updated in the memory block returne...
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
char * beginFullDynamicBufferUpdateForCurrentFrame() override
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiBuffer::NativeBuffer nativeBuffer() override
ID3D11UnorderedAccessView * unorderedAccessView(quint32 offset)
QD3D11RenderTargetData * prevRtD
static const int MAX_DYNAMIC_OFFSET_COUNT
static const int MAX_VERTEX_BUFFER_BINDING_COUNT
int retainResourceBatches(const QD3D11ShaderResourceBindings::ResourceBatches &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ComputePipeline(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11GraphicsPipeline(QRhiImplementation *rhi)
~QD3D11GraphicsPipeline()
bool create() override
Creates the corresponding native graphics resources.
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags, QRhiTexture::Format backingFormatHint)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool create() override
Creates the corresponding native graphics resources.
QRhiTexture::Format backingFormat() const override
QD3D11RenderPassDescriptor(QRhiImplementation *rhi)
~QD3D11RenderPassDescriptor()
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool isCompatible(const QRhiRenderPassDescriptor *other) const override
QVector< quint32 > serializedFormat() const override
static const int MAX_COLOR_ATTACHMENTS
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
QD3D11GraphicsPipeline * lastUsedGraphicsPipeline
bool create() override
Creates the corresponding resource binding set.
~QD3D11ShaderResourceBindings()
void updateResources(UpdateFlags flags) override
QD3D11ComputePipeline * lastUsedComputePipeline
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
int sampleCount() const override
~QD3D11SwapChainRenderTarget()
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
float devicePixelRatio() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QSize pixelSize() const override
bool prepare(QRhiD3D11 *rhiD)
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
bool active[TIMESTAMP_PAIRS]
static const int TIMESTAMP_PAIRS
QRhiSwapChainHdrInfo hdrInfo() override
\variable QRhiSwapChainHdrInfo::limitsType
int lastFrameLatencyWaitSlot
QRhiRenderTarget * currentFrameRenderTarget() override
QD3D11SwapChain(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
QSize surfacePixelSize() override
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
static const int BUFFER_COUNT
bool isFormatSupported(Format f) override
QRhiCommandBuffer * currentFrameCommandBuffer() override
int currentTimestampPairIndex
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
QSize pixelSize() const override
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
float devicePixelRatio() const override
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
~QD3D11TextureRenderTarget()
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
ID3D11UnorderedAccessView * unorderedAccessViewForLevel(int level)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool update(QD3D11RenderTargetData *data, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)