10#include <QtCore/qcryptographichash.h>
11#include <QtCore/private/qsystemerror_p.h>
18using namespace Qt::StringLiterals;
21
22
23
24
25
26
27
28
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
78
79
80
81
82
86
87
88
89
90
91
92
93
94
95
96
97
100
101
102
103
104
105
106
107
110
111
112
113
114
115
116
119
120
121
122
123
124
125
126
129
130
131
132
133
134
137
138
139
140
141
142
145#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
146#define DXGI_ADAPTER_FLAG_SOFTWARE 2
149#ifndef D3D11_1_UAV_SLOT_COUNT
150#define D3D11_1_UAV_SLOT_COUNT 64
153#ifndef D3D11_VS_INPUT_REGISTER_COUNT
154#define D3D11_VS_INPUT_REGISTER_COUNT 32
163 if (importParams->dev && importParams->context) {
164 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
165 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
166 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
171 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
174 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
175 adapterLuid.LowPart = importParams->adapterLuidLow;
176 adapterLuid.HighPart = importParams->adapterLuidHigh;
183 return (v + byteAlign - 1) & ~(byteAlign - 1);
188 IDXGIFactory1 *result =
nullptr;
189 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
191 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
192 qPrintable(QSystemError::windowsComString(hr)));
204 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
206 dxgiFactory = createDXGIFactory2();
214 IDXGIFactory5 *factory5 =
nullptr;
215 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
216 BOOL allowTearing =
false;
217 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
222 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
223 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
231 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
232 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
237 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
241 if (maxFrameLatency == 0)
242 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
244 activeAdapter =
nullptr;
247 IDXGIAdapter1 *adapter;
248 int requestedAdapterIndex = -1;
249 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
250 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
252 if (requestedRhiAdapter)
253 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
256 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
257 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
258 DXGI_ADAPTER_DESC1 desc;
259 adapter->GetDesc1(&desc);
261 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
262 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
264 requestedAdapterIndex = adapterIndex;
270 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
271 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
272 DXGI_ADAPTER_DESC1 desc;
273 adapter->GetDesc1(&desc);
276 requestedAdapterIndex = adapterIndex;
282 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
283 DXGI_ADAPTER_DESC1 desc;
284 adapter->GetDesc1(&desc);
285 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
286 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
292 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
293 activeAdapter = adapter;
294 adapterLuid = desc.AdapterLuid;
296 qCDebug(QRHI_LOG_INFO,
" using this adapter");
301 if (!activeAdapter) {
302 qWarning(
"No adapter");
308 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
309 bool requestFeatureLevels =
false;
311 requestFeatureLevels =
true;
312 requestedFeatureLevels.append(featureLevel);
315 ID3D11DeviceContext *ctx =
nullptr;
316 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
317 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
318 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
320 &dev, &featureLevel, &ctx);
322 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
323 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
324 "Attempting to create D3D11 device without it.");
325 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
326 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
327 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
328 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
330 &dev, &featureLevel, &ctx);
333 qWarning(
"Failed to create D3D11 device and context: %s",
334 qPrintable(QSystemError::windowsComString(hr)));
338 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
341 qWarning(
"ID3D11DeviceContext1 not supported");
347 ID3D11VertexShader *testShader =
nullptr;
348 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
349 testShader->Release();
351 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
352 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
353 qCDebug(QRHI_LOG_INFO,
"%s", msg);
359 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
360 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
364 if (!features.ConstantBufferOffsetting) {
365 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
366 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
367 qCDebug(QRHI_LOG_INFO,
"%s", msg);
373 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
374 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
375 qCDebug(QRHI_LOG_INFO,
"%s", msg);
381 Q_ASSERT(dev && context);
382 featureLevel = dev->GetFeatureLevel();
383 IDXGIDevice *dxgiDev =
nullptr;
384 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
385 IDXGIAdapter *adapter =
nullptr;
386 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
387 IDXGIAdapter1 *adapter1 =
nullptr;
388 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
389 DXGI_ADAPTER_DESC1 desc;
390 adapter1->GetDesc1(&desc);
391 adapterLuid = desc.AdapterLuid;
393 activeAdapter = adapter1;
399 if (!activeAdapter) {
400 qWarning(
"Failed to query adapter from imported device");
403 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
406 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
408 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
409 annotations =
nullptr;
413 nativeHandlesStruct.dev = dev;
414 nativeHandlesStruct.context = context;
415 nativeHandlesStruct.featureLevel = featureLevel;
416 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
417 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
424 for (
const Shader &s : std::as_const(m_shaderCache))
427 m_shaderCache.clear();
436 if (ofr.tsDisjointQuery) {
437 ofr.tsDisjointQuery->Release();
438 ofr.tsDisjointQuery =
nullptr;
440 for (
int i = 0; i < 2; ++i) {
441 if (ofr.tsQueries[i]) {
442 ofr.tsQueries[i]->Release();
443 ofr.tsQueries[i] =
nullptr;
448 annotations->Release();
449 annotations =
nullptr;
464 dcompDevice->Release();
465 dcompDevice =
nullptr;
469 activeAdapter->Release();
470 activeAdapter =
nullptr;
474 dxgiFactory->Release();
475 dxgiFactory =
nullptr;
478 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
488 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
489 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
494QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
496 LUID requestedLuid = {};
498 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
499 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
500 if (adapterLuid.LowPart || adapterLuid.HighPart)
501 requestedLuid = adapterLuid;
504 IDXGIFactory1 *dxgi = createDXGIFactory2();
508 QRhi::AdapterList list;
509 IDXGIAdapter1 *adapter;
510 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
511 DXGI_ADAPTER_DESC1 desc;
512 adapter->GetDesc1(&desc);
514 if (requestedLuid.LowPart || requestedLuid.HighPart) {
515 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
516 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
521 QD3D11Adapter *a =
new QD3D11Adapter;
522 a->luid = desc.AdapterLuid;
523 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
538 return { 1, 2, 4, 8 };
543 Q_UNUSED(sampleCount);
544 return { QSize(1, 1) };
549 DXGI_SAMPLE_DESC desc;
553 const int s = effectiveSampleCount(sampleCount);
555 desc.Count = UINT(s);
557 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
566 return new QD3D11SwapChain(
this);
569QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
571 return new QD3D11Buffer(
this, type, usage, size);
599 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
600 0.0f, 1.0f, 0.0f, 0.0f,
601 0.0f, 0.0f, 0.5f, 0.5f,
602 0.0f, 0.0f, 0.0f, 1.0f);
610 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
619 case QRhi::MultisampleTexture:
621 case QRhi::MultisampleRenderBuffer:
623 case QRhi::DebugMarkers:
624 return annotations !=
nullptr;
625 case QRhi::Timestamps:
627 case QRhi::Instancing:
629 case QRhi::CustomInstanceStepRate:
631 case QRhi::PrimitiveRestart:
633 case QRhi::NonDynamicUniformBuffers:
635 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
637 case QRhi::NPOTTextureRepeat:
639 case QRhi::RedOrAlpha8IsRed:
641 case QRhi::ElementIndexUint:
645 case QRhi::WideLines:
647 case QRhi::VertexShaderPointSize:
649 case QRhi::BaseVertex:
651 case QRhi::BaseInstance:
653 case QRhi::TriangleFanTopology:
655 case QRhi::ReadBackNonUniformBuffer:
657 case QRhi::ReadBackNonBaseMipLevel:
659 case QRhi::TexelFetch:
661 case QRhi::RenderToNonBaseMipLevel:
663 case QRhi::IntAttributes:
665 case QRhi::ScreenSpaceDerivatives:
667 case QRhi::ReadBackAnyTextureFormat:
669 case QRhi::PipelineCacheDataLoadSave:
671 case QRhi::ImageDataStride:
673 case QRhi::RenderBufferImport:
675 case QRhi::ThreeDimensionalTextures:
677 case QRhi::RenderTo3DTextureSlice:
679 case QRhi::TextureArrays:
681 case QRhi::Tessellation:
683 case QRhi::GeometryShader:
685 case QRhi::TextureArrayRange:
687 case QRhi::NonFillPolygonMode:
689 case QRhi::OneDimensionalTextures:
691 case QRhi::OneDimensionalTextureMipmaps:
693 case QRhi::HalfAttributes:
695 case QRhi::RenderToOneDimensionalTexture:
697 case QRhi::ThreeDimensionalTextureMipmaps:
699 case QRhi::MultiView:
701 case QRhi::TextureViewFormat:
703 case QRhi::ResolveDepthStencil:
705 case QRhi::VariableRateShading:
707 case QRhi::VariableRateShadingMap:
708 case QRhi::VariableRateShadingMapWithTexture:
710 case QRhi::PerRenderTargetBlending:
711 case QRhi::SampleVariables:
713 case QRhi::InstanceIndexIncludesBaseInstance:
715 case QRhi::DepthClamp:
717 case QRhi::DrawIndirect:
718 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
719 case QRhi::DrawIndirectMulti:
720 case QRhi::ShaderDrawParameters:
721 case QRhi::DrawIndirectCount:
723 case QRhi::DispatchIndirect:
724 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
734 case QRhi::TextureSizeMin:
736 case QRhi::TextureSizeMax:
737 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
738 case QRhi::MaxColorAttachments:
740 case QRhi::FramesInFlight:
746 case QRhi::MaxAsyncReadbackFrames:
748 case QRhi::MaxThreadGroupsPerDimension:
749 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
750 case QRhi::MaxThreadsPerThreadGroup:
751 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
752 case QRhi::MaxThreadGroupX:
753 return D3D11_CS_THREAD_GROUP_MAX_X;
754 case QRhi::MaxThreadGroupY:
755 return D3D11_CS_THREAD_GROUP_MAX_Y;
756 case QRhi::MaxThreadGroupZ:
757 return D3D11_CS_THREAD_GROUP_MAX_Z;
758 case QRhi::TextureArraySizeMax:
759 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
760 case QRhi::MaxUniformBufferRange:
762 case QRhi::MaxVertexInputs:
764 case QRhi::MaxVertexOutputs:
765 return D3D11_VS_OUTPUT_REGISTER_COUNT;
766 case QRhi::MaxVertexStorageBuffers:
768 case QRhi::MaxFragmentStorageBuffers:
769 return featureLevel >= D3D_FEATURE_LEVEL_11_1
771 case QRhi::ShadingRateImageTileSize:
781 return &nativeHandlesStruct;
786 return driverInfoStruct;
792 result.totalPipelineCreationTime = totalPipelineCreationTime();
802void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
810 m_bytecodeCache.clear();
830 if (m_bytecodeCache.isEmpty())
834 memset(&header, 0,
sizeof(header));
835 header.rhiId = pipelineCacheRhiId();
836 header.arch = quint32(
sizeof(
void*));
837 header.count = m_bytecodeCache.count();
839 const size_t dataOffset =
sizeof(header);
841 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
843 QByteArray bytecode = it.value();
845 sizeof(quint32) + key.sourceHash.size()
846 +
sizeof(quint32) + key.target.size()
847 +
sizeof(quint32) + key.entryPoint.size()
849 +
sizeof(quint32) + bytecode.size();
852 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
853 char *p = buf.data() + dataOffset;
854 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
856 QByteArray bytecode = it.value();
858 quint32 i = key.sourceHash.size();
861 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
862 p += key.sourceHash.size();
864 i = key.target.size();
867 memcpy(p, key.target.constData(), key.target.size());
868 p += key.target.size();
870 i = key.entryPoint.size();
873 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
874 p += key.entryPoint.size();
876 quint32 f = key.compileFlags;
883 memcpy(p, bytecode.constData(), bytecode.size());
884 p += bytecode.size();
886 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
888 header.dataSize = quint32(dataSize);
889 memcpy(buf.data(), &header,
sizeof(header));
900 if (data.size() < qsizetype(headerSize)) {
901 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
904 const size_t dataOffset = headerSize;
906 memcpy(&header, data.constData(), headerSize);
908 const quint32 rhiId = pipelineCacheRhiId();
909 if (header.rhiId != rhiId) {
910 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
911 rhiId, header.rhiId);
914 const quint32 arch = quint32(
sizeof(
void*));
915 if (header.arch != arch) {
916 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
920 if (header.count == 0)
923 if (quint64(data.size()) < quint64(dataOffset) + header.dataSize) {
924 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
928 m_bytecodeCache.clear();
931 for (quint32 i = 0; i < header.count; ++i) {
935 if (!reader.readByteArray(&cacheKey.sourceHash)
936 || !reader.readByteArray(&cacheKey.target)
937 || !reader.readByteArray(&cacheKey.entryPoint)
938 || !reader.readUInt32(&flags)
939 || !reader.readByteArray(&bytecode))
941 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob (truncated or corrupt bytecode data)");
942 m_bytecodeCache.clear();
945 cacheKey.compileFlags = flags;
947 m_bytecodeCache.insert(cacheKey, bytecode);
950 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
953QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
954 int sampleCount, QRhiRenderBuffer::Flags flags,
955 QRhiTexture::Format backingFormatHint)
957 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
961 const QSize &pixelSize,
int depth,
int arraySize,
962 int sampleCount, QRhiTexture::Flags flags)
964 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
968 QRhiSampler::Filter mipmapMode,
969 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
971 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
975 QRhiTextureRenderTarget::Flags flags)
987 return new QD3D11GraphicsPipeline(
this);
992 return new QD3D11ComputePipeline(
this);
997 return new QD3D11ShaderResourceBindings(
this);
1005 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1007 if (pipelineChanged) {
1008 cbD->currentGraphicsPipeline = ps;
1009 cbD->currentComputePipeline =
nullptr;
1010 cbD->currentPipelineGeneration = psD->generation;
1014 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1015 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1016 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1017 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1018 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1019 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1020 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1021 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1022 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1023 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1036 int dynamicOffsetCount,
1037 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1046 srb = gfxPsD->m_shaderResourceBindings;
1048 srb = compPsD->m_shaderResourceBindings;
1053 bool pipelineChanged =
false;
1062 bool srbUpdate =
false;
1063 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1064 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1067 case QRhiShaderResourceBinding::UniformBuffer:
1071 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1072 sanityCheckResourceOwnership(bufD);
1076 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1078 bd.ubuf.id = bufD->m_id;
1079 bd.ubuf.generation = bufD->generation;
1083 case QRhiShaderResourceBinding::SampledTexture:
1084 case QRhiShaderResourceBinding::Texture:
1085 case QRhiShaderResourceBinding::Sampler:
1087 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1088 if (bd.stex.count != data->count) {
1089 bd.stex.count = data->count;
1092 for (
int elem = 0; elem < data->count; ++elem) {
1098 Q_ASSERT(texD || samplerD);
1099 sanityCheckResourceOwnership(texD);
1100 sanityCheckResourceOwnership(samplerD);
1101 const quint64 texId = texD ? texD->m_id : 0;
1102 const uint texGen = texD ? texD->generation : 0;
1103 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1104 const uint samplerGen = samplerD ? samplerD->generation : 0;
1105 if (texGen != bd.stex.d[elem].texGeneration
1106 || texId != bd.stex.d[elem].texId
1107 || samplerGen != bd.stex.d[elem].samplerGeneration
1108 || samplerId != bd.stex.d[elem].samplerId)
1111 bd.stex.d[elem].texId = texId;
1112 bd.stex.d[elem].texGeneration = texGen;
1113 bd.stex.d[elem].samplerId = samplerId;
1114 bd.stex.d[elem].samplerGeneration = samplerGen;
1119 case QRhiShaderResourceBinding::ImageLoad:
1120 case QRhiShaderResourceBinding::ImageStore:
1121 case QRhiShaderResourceBinding::ImageLoadStore:
1124 sanityCheckResourceOwnership(texD);
1125 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1127 bd.simage.id = texD->m_id;
1128 bd.simage.generation = texD->generation;
1132 case QRhiShaderResourceBinding::BufferLoad:
1133 case QRhiShaderResourceBinding::BufferStore:
1134 case QRhiShaderResourceBinding::BufferLoadStore:
1137 sanityCheckResourceOwnership(bufD);
1138 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1140 bd.sbuf.id = bufD->m_id;
1141 bd.sbuf.generation = bufD->generation;
1151 if (srbUpdate || pipelineChanged) {
1153 memset(resBindMaps, 0,
sizeof(resBindMaps));
1155 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1156 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1157 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1158 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1159 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1161 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1163 updateShaderResourceBindings(srbD, resBindMaps);
1166 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1167 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1169 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1171 cbD->currentGraphicsSrb = srb;
1172 cbD->currentComputeSrb =
nullptr;
1174 cbD->currentGraphicsSrb =
nullptr;
1175 cbD->currentComputeSrb = srb;
1177 cbD->currentSrbGeneration = srbD->generation;
1184 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1185 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1188 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1189 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1190 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1191 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1192 const uint binding = uint(dynOfs.first);
1193 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1194 const quint32 offsetInConstants = dynOfs.second / 16;
1196 *p++ = offsetInConstants;
1199 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1207 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1208 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1213 bool needsBindVBuf =
false;
1214 for (
int i = 0; i < bindingCount; ++i) {
1215 const int inputSlot = startBinding + i;
1217 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1218 if (bufD->m_type == QRhiBuffer::Dynamic)
1221 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1222 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1224 needsBindVBuf =
true;
1225 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1226 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1230 if (needsBindVBuf) {
1233 cmd.args.bindVertexBuffers.startSlot = startBinding;
1235 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1239 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1241 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1242 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1243 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1245 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1246 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1247 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1253 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1254 if (ibufD->m_type == QRhiBuffer::Dynamic)
1257 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1258 : DXGI_FORMAT_R32_UINT;
1259 if (cbD->currentIndexBuffer != ibufD->buffer
1260 || cbD->currentIndexOffset != indexOffset
1261 || cbD->currentIndexFormat != dxgiFormat)
1263 cbD->currentIndexBuffer = ibufD->buffer;
1264 cbD->currentIndexOffset = indexOffset;
1265 cbD->currentIndexFormat = dxgiFormat;
1269 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1270 cmd.args.bindIndexBuffer.offset = indexOffset;
1271 cmd.args.bindIndexBuffer.format = dxgiFormat;
1280 Q_ASSERT(cbD->currentTarget);
1281 const QSize outputSize = cbD->currentTarget->pixelSize();
1285 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1290 cmd.args.viewport.x = x;
1291 cmd.args.viewport.y = y;
1292 cmd.args.viewport.w = w;
1293 cmd.args.viewport.h = h;
1294 cmd.args.viewport.d0 = viewport.minDepth();
1295 cmd.args.viewport.d1 = viewport.maxDepth();
1302 Q_ASSERT(cbD->currentTarget);
1303 const QSize outputSize = cbD->currentTarget->pixelSize();
1307 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1312 cmd.args.scissor.x = x;
1313 cmd.args.scissor.y = y;
1314 cmd.args.scissor.w = w;
1315 cmd.args.scissor.h = h;
1326 cmd.args.blendConstants.c[0] =
float(c.redF());
1327 cmd.args.blendConstants.c[1] =
float(c.greenF());
1328 cmd.args.blendConstants.c[2] =
float(c.blueF());
1329 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1340 cmd.args.stencilRef.ref = refValue;
1346 Q_UNUSED(coarsePixelSize);
1350 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1357 cmd.args.draw.vertexCount = vertexCount;
1358 cmd.args.draw.instanceCount = instanceCount;
1359 cmd.args.draw.firstVertex = firstVertex;
1360 cmd.args.draw.firstInstance = firstInstance;
1364 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1371 cmd.args.drawIndexed.indexCount = indexCount;
1372 cmd.args.drawIndexed.instanceCount = instanceCount;
1373 cmd.args.drawIndexed.firstIndex = firstIndex;
1374 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1375 cmd.args.drawIndexed.firstInstance = firstInstance;
1379 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1386 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1387 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1388 cmd.args.drawIndirect.drawCount = drawCount;
1389 cmd.args.drawIndirect.stride = stride;
1394 switch (rt->resourceType()) {
1395 case QRhiResource::SwapChainRenderTarget:
1396 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1397 case QRhiResource::TextureRenderTarget:
1398 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1406 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1413 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1414 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1415 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1416 cmd.args.drawIndexedIndirect.stride = stride;
1421 if (!debugMarkers || !annotations)
1427 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1432 if (!debugMarkers || !annotations)
1442 if (!debugMarkers || !annotations)
1448 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1467 Q_ASSERT(cbD->commands.isEmpty());
1469 if (cbD->currentTarget) {
1473 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1488 return QRhi::FrameOpDeviceLost;
1495 if (swapChainD->frameLatencyWaitableObject) {
1498 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1503 swapChainD->cb.resetState();
1505 swapChainD->rt.d.views.setFrom(1,
1506 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1507 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1512 double elapsedSec = 0;
1514 swapChainD->cb.lastGpuTime = elapsedSec;
1523 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1524 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1525 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1526 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1528 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1530 return QRhi::FrameOpSuccess;
1541 cmd.args.endFrame.tsQuery =
nullptr;
1542 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1547 if (swapChainD->sampleDesc.Count > 1) {
1548 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1549 swapChainD->msaaTex[currentFrameSlot], 0,
1550 swapChainD->colorFormat);
1557 if (recordTimestamps) {
1558 context->End(tsEnd);
1559 context->End(tsDisjoint);
1564 if (!flags.testFlag(QRhi::SkipPresent)) {
1565 UINT presentFlags = 0;
1566 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1567 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1568 if (!swapChainD->swapChain) {
1569 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1570 return QRhi::FrameOpError;
1572 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1573 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1574 qWarning(
"Device loss detected in Present()");
1576 return QRhi::FrameOpDeviceLost;
1577 }
else if (FAILED(hr)) {
1578 qWarning(
"Failed to present: %s",
1579 qPrintable(QSystemError::windowsComString(hr)));
1580 return QRhi::FrameOpError;
1583 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1584 dcompDevice->Commit();
1595 return QRhi::FrameOpSuccess;
1603 ofr.cbWrapper.resetState();
1604 *cb = &ofr.cbWrapper;
1606 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1607 D3D11_QUERY_DESC queryDesc = {};
1608 if (!ofr.tsDisjointQuery) {
1609 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1610 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1612 qWarning(
"Failed to create timestamp disjoint query: %s",
1613 qPrintable(QSystemError::windowsComString(hr)));
1614 return QRhi::FrameOpError;
1617 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1618 for (
int i = 0; i < 2; ++i) {
1619 if (!ofr.tsQueries[i]) {
1620 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1622 qWarning(
"Failed to create timestamp query: %s",
1623 qPrintable(QSystemError::windowsComString(hr)));
1624 return QRhi::FrameOpError;
1632 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1633 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1634 cmd.args.beginFrame.swapchainRtv =
nullptr;
1635 cmd.args.beginFrame.swapchainDsv =
nullptr;
1637 return QRhi::FrameOpSuccess;
1647 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1648 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1655 if (ofr.tsQueries[0]) {
1656 quint64 timestamps[2];
1657 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1661 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1662 }
while (hr == S_FALSE);
1665 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1666 }
while (hr == S_FALSE);
1669 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1670 }
while (hr == S_FALSE);
1673 if (!dj.Disjoint && dj.Frequency) {
1674 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1675 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1680 return QRhi::FrameOpSuccess;
1685 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1687 case QRhiTexture::RGBA8:
1688 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1689 case QRhiTexture::BGRA8:
1690 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1691 case QRhiTexture::R8:
1692 return DXGI_FORMAT_R8_UNORM;
1693 case QRhiTexture::R8SI:
1694 return DXGI_FORMAT_R8_SINT;
1695 case QRhiTexture::R8UI:
1696 return DXGI_FORMAT_R8_UINT;
1697 case QRhiTexture::RG8:
1698 return DXGI_FORMAT_R8G8_UNORM;
1699 case QRhiTexture::R16:
1700 return DXGI_FORMAT_R16_UNORM;
1701 case QRhiTexture::RG16:
1702 return DXGI_FORMAT_R16G16_UNORM;
1703 case QRhiTexture::RED_OR_ALPHA8:
1704 return DXGI_FORMAT_R8_UNORM;
1706 case QRhiTexture::RGBA16F:
1707 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1708 case QRhiTexture::RGBA32F:
1709 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1710 case QRhiTexture::R16F:
1711 return DXGI_FORMAT_R16_FLOAT;
1712 case QRhiTexture::R32F:
1713 return DXGI_FORMAT_R32_FLOAT;
1715 case QRhiTexture::RGB10A2:
1716 return DXGI_FORMAT_R10G10B10A2_UNORM;
1718 case QRhiTexture::R32SI:
1719 return DXGI_FORMAT_R32_SINT;
1720 case QRhiTexture::R32UI:
1721 return DXGI_FORMAT_R32_UINT;
1722 case QRhiTexture::RG32SI:
1723 return DXGI_FORMAT_R32G32_SINT;
1724 case QRhiTexture::RG32UI:
1725 return DXGI_FORMAT_R32G32_UINT;
1726 case QRhiTexture::RGBA32SI:
1727 return DXGI_FORMAT_R32G32B32A32_SINT;
1728 case QRhiTexture::RGBA32UI:
1729 return DXGI_FORMAT_R32G32B32A32_UINT;
1731 case QRhiTexture::D16:
1732 return DXGI_FORMAT_R16_TYPELESS;
1733 case QRhiTexture::D24:
1734 return DXGI_FORMAT_R24G8_TYPELESS;
1735 case QRhiTexture::D24S8:
1736 return DXGI_FORMAT_R24G8_TYPELESS;
1737 case QRhiTexture::D32F:
1738 return DXGI_FORMAT_R32_TYPELESS;
1739 case QRhiTexture::D32FS8:
1740 return DXGI_FORMAT_R32G8X24_TYPELESS;
1742 case QRhiTexture::BC1:
1743 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1744 case QRhiTexture::BC2:
1745 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1746 case QRhiTexture::BC3:
1747 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1748 case QRhiTexture::BC4:
1749 return DXGI_FORMAT_BC4_UNORM;
1750 case QRhiTexture::BC5:
1751 return DXGI_FORMAT_BC5_UNORM;
1752 case QRhiTexture::BC6H:
1753 return DXGI_FORMAT_BC6H_UF16;
1754 case QRhiTexture::BC7:
1755 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1757 case QRhiTexture::ETC2_RGB8:
1758 case QRhiTexture::ETC2_RGB8A1:
1759 case QRhiTexture::ETC2_RGBA8:
1760 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1761 return DXGI_FORMAT_R8G8B8A8_UNORM;
1763 case QRhiTexture::ASTC_4x4:
1764 case QRhiTexture::ASTC_5x4:
1765 case QRhiTexture::ASTC_5x5:
1766 case QRhiTexture::ASTC_6x5:
1767 case QRhiTexture::ASTC_6x6:
1768 case QRhiTexture::ASTC_8x5:
1769 case QRhiTexture::ASTC_8x6:
1770 case QRhiTexture::ASTC_8x8:
1771 case QRhiTexture::ASTC_10x5:
1772 case QRhiTexture::ASTC_10x6:
1773 case QRhiTexture::ASTC_10x8:
1774 case QRhiTexture::ASTC_10x10:
1775 case QRhiTexture::ASTC_12x10:
1776 case QRhiTexture::ASTC_12x12:
1777 qWarning(
"QRhiD3D11 does not support ASTC textures");
1778 return DXGI_FORMAT_R8G8B8A8_UNORM;
1782 return DXGI_FORMAT_R8G8B8A8_UNORM;
1789 case DXGI_FORMAT_R8G8B8A8_UNORM:
1790 return QRhiTexture::RGBA8;
1791 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1793 (*flags) |= QRhiTexture::sRGB;
1794 return QRhiTexture::RGBA8;
1795 case DXGI_FORMAT_B8G8R8A8_UNORM:
1796 return QRhiTexture::BGRA8;
1797 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1799 (*flags) |= QRhiTexture::sRGB;
1800 return QRhiTexture::BGRA8;
1801 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1802 return QRhiTexture::RGBA16F;
1803 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1804 return QRhiTexture::RGBA32F;
1805 case DXGI_FORMAT_R10G10B10A2_UNORM:
1806 return QRhiTexture::RGB10A2;
1808 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1811 return QRhiTexture::UnknownFormat;
1817 case QRhiTexture::Format::D16:
1818 case QRhiTexture::Format::D24:
1819 case QRhiTexture::Format::D24S8:
1820 case QRhiTexture::Format::D32F:
1821 case QRhiTexture::Format::D32FS8:
1834 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1836 ofr.cbWrapper.resetCommands();
1847 return QRhi::FrameOpSuccess;
1851 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1853 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1854 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1856 box.front = is3D ? UINT(layer) : 0u;
1858 box.back = box.front + 1;
1861 cmd.args.updateSubRes.dst = texD->textureResource();
1862 cmd.args.updateSubRes.dstSubRes = subres;
1864 const QPoint dp = subresDesc.destinationTopLeft();
1865 if (!subresDesc.image().isNull()) {
1866 QImage img = subresDesc.image();
1867 QSize size = img.size();
1868 int bpl = img.bytesPerLine();
1869 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1870 const QPoint sp = subresDesc.sourceTopLeft();
1871 if (!subresDesc.sourceSize().isEmpty())
1872 size = subresDesc.sourceSize();
1873 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1874 if (img.depth() == 32) {
1875 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1876 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1878 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1879 bpl = img.bytesPerLine();
1880 cmd.args.updateSubRes.src = cbD->retainImage(img);
1883 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1884 cmd.args.updateSubRes.src = cbD->retainImage(img);
1886 box.left = UINT(dp.x());
1887 box.top = UINT(dp.y());
1888 box.right = UINT(dp.x() + size.width());
1889 box.bottom = UINT(dp.y() + size.height());
1890 cmd.args.updateSubRes.hasDstBox =
true;
1891 cmd.args.updateSubRes.dstBox = box;
1892 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1893 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1894 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1895 : subresDesc.sourceSize();
1898 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1902 box.left = UINT(aligned(dp.x(), blockDim.width()));
1903 box.top = UINT(aligned(dp.y(), blockDim.height()));
1904 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1905 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1906 cmd.args.updateSubRes.hasDstBox =
true;
1907 cmd.args.updateSubRes.dstBox = box;
1908 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1909 cmd.args.updateSubRes.srcRowPitch = bpl;
1910 }
else if (!subresDesc.data().isEmpty()) {
1911 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1912 : subresDesc.sourceSize();
1913 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1914 quint32 bytesPerPixel = 0;
1915 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
1916 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
1917 bytesPerPixel, subresDesc.data().size());
1918 if (size.isEmpty()) {
1919 cbD->commands.unget();
1923 if (subresDesc.dataStride())
1924 bpl = subresDesc.dataStride();
1926 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1927 box.left = UINT(dp.x());
1928 box.top = UINT(dp.y());
1929 box.right = UINT(dp.x() + size.width());
1930 box.bottom = UINT(dp.y() + size.height());
1931 cmd.args.updateSubRes.hasDstBox =
true;
1932 cmd.args.updateSubRes.dstBox = box;
1933 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1934 cmd.args.updateSubRes.srcRowPitch = bpl;
1936 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1937 cbD->commands.unget();
1950 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1955 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1956 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1959 cmd.args.updateSubRes.dst = bufD->buffer;
1960 cmd.args.updateSubRes.dstSubRes = 0;
1961 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1962 cmd.args.updateSubRes.srcRowPitch = 0;
1967 box.left = u.offset;
1968 box.top = box.front = 0;
1969 box.back = box.bottom = 1;
1970 box.right = u.offset + u
.data.size();
1971 cmd.args.updateSubRes.hasDstBox =
true;
1972 cmd.args.updateSubRes.dstBox = box;
1975 if (bufD->m_type == QRhiBuffer::Dynamic) {
1976 u.result->data.resize(u.readSize);
1977 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1978 if (u.result->completed)
1979 u.result->completed();
1982 readback.result = u.result;
1983 readback.byteSize = u.readSize;
1985 D3D11_BUFFER_DESC desc = {};
1986 desc.ByteWidth = readback.byteSize;
1987 desc.Usage = D3D11_USAGE_STAGING;
1988 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1989 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1991 qWarning(
"Failed to create buffer: %s",
1992 qPrintable(QSystemError::windowsComString(hr)));
1998 cmd.args.copySubRes.dst = readback.stagingBuf;
1999 cmd.args.copySubRes.dstSubRes = 0;
2000 cmd.args.copySubRes.dstX = 0;
2001 cmd.args.copySubRes.dstY = 0;
2002 cmd.args.copySubRes.dstZ = 0;
2003 cmd.args.copySubRes.src = bufD->buffer;
2004 cmd.args.copySubRes.srcSubRes = 0;
2005 cmd.args.copySubRes.hasSrcBox =
true;
2007 box.left = u.offset;
2008 box.top = box.front = 0;
2009 box.back = box.bottom = 1;
2010 box.right = u.offset + u.readSize;
2011 cmd.args.copySubRes.srcBox = box;
2013 activeBufferReadbacks.append(readback);
2021 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2022 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2023 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2024 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2031 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2032 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2033 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2034 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2035 const QPoint dp = u.desc.destinationTopLeft();
2036 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2037 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2038 const QPoint sp = u.desc.sourceTopLeft();
2040 srcBox.left = UINT(sp.x());
2041 srcBox.top = UINT(sp.y());
2042 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2044 srcBox.right = srcBox.left + UINT(copySize.width());
2045 srcBox.bottom = srcBox.top + UINT(copySize.height());
2046 srcBox.back = srcBox.front + 1;
2049 cmd.args.copySubRes.dst = dstD->textureResource();
2050 cmd.args.copySubRes.dstSubRes = dstSubRes;
2051 cmd.args.copySubRes.dstX = UINT(dp.x());
2052 cmd.args.copySubRes.dstY = UINT(dp.y());
2053 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2054 cmd.args.copySubRes.src = srcD->textureResource();
2055 cmd.args.copySubRes.srcSubRes = srcSubRes;
2056 cmd.args.copySubRes.hasSrcBox =
true;
2057 cmd.args.copySubRes.srcBox = srcBox;
2060 readback.desc = u.rb;
2061 readback.result = u.result;
2063 ID3D11Resource *src;
2064 DXGI_FORMAT dxgiFormat;
2066 QRhiTexture::Format format;
2073 if (texD->sampleDesc.Count > 1) {
2074 qWarning(
"Multisample texture cannot be read back");
2077 src = texD->textureResource();
2078 dxgiFormat = texD->dxgiFormat;
2079 if (u.rb.rect().isValid())
2082 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2083 format = texD->m_format;
2084 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2085 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2089 if (swapChainD->sampleDesc.Count > 1) {
2094 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2095 rcmd.args.resolveSubRes.dstSubRes = 0;
2097 rcmd.args.resolveSubRes.srcSubRes = 0;
2098 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2100 src = swapChainD->backBufferTex;
2101 dxgiFormat = swapChainD->colorFormat;
2102 if (u.rb.rect().isValid())
2105 rect = QRect({0, 0}, swapChainD->pixelSize);
2106 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2107 if (format == QRhiTexture::UnknownFormat)
2110 quint32 byteSize = 0;
2112 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2114 D3D11_TEXTURE2D_DESC desc = {};
2115 desc.Width = UINT(rect.width());
2116 desc.Height = UINT(rect.height());
2119 desc.Format = dxgiFormat;
2120 desc.SampleDesc.Count = 1;
2121 desc.Usage = D3D11_USAGE_STAGING;
2122 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2123 ID3D11Texture2D *stagingTex;
2124 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2126 qWarning(
"Failed to create readback staging texture: %s",
2127 qPrintable(QSystemError::windowsComString(hr)));
2133 cmd.args.copySubRes.dst = stagingTex;
2134 cmd.args.copySubRes.dstSubRes = 0;
2135 cmd.args.copySubRes.dstX = 0;
2136 cmd.args.copySubRes.dstY = 0;
2137 cmd.args.copySubRes.dstZ = 0;
2138 cmd.args.copySubRes.src = src;
2139 cmd.args.copySubRes.srcSubRes = subres;
2141 D3D11_BOX srcBox = {};
2142 srcBox.left = UINT(rect.left());
2143 srcBox.top = UINT(rect.top());
2144 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2146 srcBox.right = srcBox.left + desc.Width;
2147 srcBox.bottom = srcBox.top + desc.Height;
2148 srcBox.back = srcBox.front + 1;
2149 cmd.args.copySubRes.hasSrcBox =
true;
2150 cmd.args.copySubRes.srcBox = srcBox;
2152 readback.stagingTex = stagingTex;
2153 readback.byteSize = byteSize;
2155 readback.pixelSize = rect.size();
2156 readback.format = format;
2158 activeTextureReadbacks.append(readback);
2160 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2163 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2172 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2174 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2176 readback.result->format = readback.format;
2177 readback.result->pixelSize = readback.pixelSize;
2179 D3D11_MAPPED_SUBRESOURCE mp;
2180 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2181 if (SUCCEEDED(hr)) {
2182 readback.result->data.resize(
int(readback.byteSize));
2185 char *dst = readback.result->data.data();
2186 char *src =
static_cast<
char *>(mp.pData);
2187 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2188 memcpy(dst, src, readback.bpl);
2189 dst += readback.bpl;
2192 context->Unmap(readback.stagingTex, 0);
2194 qWarning(
"Failed to map readback staging texture: %s",
2195 qPrintable(QSystemError::windowsComString(hr)));
2198 readback.stagingTex->Release();
2200 if (readback.result->completed)
2201 completedCallbacks.append(readback.result->completed);
2203 activeTextureReadbacks.removeLast();
2206 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2209 D3D11_MAPPED_SUBRESOURCE mp;
2210 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2211 if (SUCCEEDED(hr)) {
2212 readback.result->data.resize(
int(readback.byteSize));
2213 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2214 context->Unmap(readback.stagingBuf, 0);
2216 qWarning(
"Failed to map readback staging texture: %s",
2217 qPrintable(QSystemError::windowsComString(hr)));
2220 readback.stagingBuf->Release();
2222 if (readback.result->completed)
2223 completedCallbacks.append(readback.result->completed);
2225 activeBufferReadbacks.removeLast();
2228 for (
auto f : completedCallbacks)
2234 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2240 QRhiRenderTarget *rt,
2241 const QColor &colorClearValue,
2242 const QRhiDepthStencilClearValue &depthStencilClearValue,
2243 QRhiResourceUpdateBatch *resourceUpdates,
2249 if (resourceUpdates)
2252 bool wantsColorClear =
true;
2253 bool wantsDsClear =
true;
2255 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2257 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2258 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2259 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2267 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2271 clearCmd.args.clear.rtViews = rtD->views;
2272 clearCmd.args.clear.mask = 0;
2273 if (rtD->views.colorAttCount && wantsColorClear)
2275 if (rtD->views.dsv && wantsDsClear)
2278 clearCmd.args.clear.c[0] = colorClearValue.redF();
2279 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2280 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2281 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2282 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2283 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2286 cbD->currentTarget = rt;
2296 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2298 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2301 const QRhiColorAttachment &colorAtt(*it);
2302 if (!colorAtt.resolveTexture())
2308 Q_ASSERT(srcTexD || srcRbD);
2311 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2312 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2313 UINT(colorAtt.resolveLayer()),
2314 dstTexD->mipLevelCount);
2316 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2317 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2318 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2319 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2320 cbD->commands.unget();
2323 if (srcTexD->sampleDesc.Count <= 1) {
2324 qWarning(
"Cannot resolve a non-multisample texture");
2325 cbD->commands.unget();
2328 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2329 qWarning(
"Resolve source and destination sizes do not match");
2330 cbD->commands.unget();
2334 cmd.args.resolveSubRes.src = srcRbD->tex;
2335 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2336 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2337 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2338 cbD->commands.unget();
2341 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2342 qWarning(
"Resolve source and destination sizes do not match");
2343 cbD->commands.unget();
2347 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2348 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2350 if (rtTex->m_desc.depthResolveTexture())
2351 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2355 cbD->currentTarget =
nullptr;
2357 if (resourceUpdates)
2362 QRhiResourceUpdateBatch *resourceUpdates,
2368 if (resourceUpdates)
2376 fbCmd.args.setRenderTarget.rtViews.reset();
2393 if (resourceUpdates)
2402 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2404 if (pipelineChanged) {
2405 cbD->currentGraphicsPipeline =
nullptr;
2406 cbD->currentComputePipeline = psD;
2407 cbD->currentPipelineGeneration = psD->generation;
2411 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2422 cmd.args.dispatch.x = UINT(x);
2423 cmd.args.dispatch.y = UINT(y);
2424 cmd.args.dispatch.z = UINT(z);
2428 quint32 indirectBufferOffset)
2435 cmd.args.dispatchIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
2436 cmd.args.dispatchIndirect.indirectBufferOffset = indirectBufferOffset;
2440 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2441 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2442 quint32 maxDrawCount, quint32 stride)
2445 Q_UNUSED(indirectBuffer);
2446 Q_UNUSED(indirectBufferOffset);
2447 Q_UNUSED(countBuffer);
2448 Q_UNUSED(countBufferOffset);
2449 Q_UNUSED(maxDrawCount);
2451 qWarning(
"drawIndirectCount is not supported by the D3D11 backend");
2455 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2456 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2457 quint32 maxDrawCount, quint32 stride)
2460 Q_UNUSED(indirectBuffer);
2461 Q_UNUSED(indirectBufferOffset);
2462 Q_UNUSED(countBuffer);
2463 Q_UNUSED(countBufferOffset);
2464 Q_UNUSED(maxDrawCount);
2466 qWarning(
"drawIndexedIndirectCount is not supported by the D3D11 backend");
2471 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2473 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2474 if (!map || map->isEmpty())
2475 return { binding, binding };
2477 auto it = map->constFind(binding);
2478 if (it != map->cend())
2488 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2490 srbD->resourceBatches.clear();
2496 ID3D11Buffer *buffer;
2497 uint offsetInConstants;
2498 uint sizeInConstants;
2502 ID3D11ShaderResourceView *srv;
2506 ID3D11SamplerState *sampler;
2510 ID3D11UnorderedAccessView *uav;
2512 QVarLengthArray<Buffer, 8> buffers;
2513 QVarLengthArray<Texture, 8> textures;
2514 QVarLengthArray<Sampler, 8> samplers;
2515 QVarLengthArray<Uav, 8> uavs;
2518 for (
const Buffer &buf : buffers) {
2519 batches.ubufs.feed(buf.breg, buf.buffer);
2520 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2521 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2522 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2528 for (
const Texture &t : textures)
2529 batches.shaderresources.feed(t.treg, t.srv);
2530 for (
const Sampler &s : samplers)
2531 batches.samplers.feed(s.sreg, s.sampler);
2536 for (
const Stage::Uav &u : uavs)
2537 batches.uavs.feed(u.ureg, u.uav);
2542 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2543 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2546 case QRhiShaderResourceBinding::UniformBuffer:
2549 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2550 bd.ubuf.id = bufD->m_id;
2551 bd.ubuf.generation = bufD->generation;
2558 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2562 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2563 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2564 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2565 if (nativeBinding.first >= 0)
2566 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2568 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2569 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2570 if (nativeBinding.first >= 0)
2571 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2573 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2574 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2575 if (nativeBinding.first >= 0)
2576 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2578 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2579 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2580 if (nativeBinding.first >= 0)
2581 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2583 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2584 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2585 if (nativeBinding.first >= 0)
2586 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2588 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2589 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2590 if (nativeBinding.first >= 0)
2591 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2595 case QRhiShaderResourceBinding::SampledTexture:
2596 case QRhiShaderResourceBinding::Texture:
2597 case QRhiShaderResourceBinding::Sampler:
2599 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2600 bd.stex.count = data->count;
2601 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2602 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2603 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2604 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2605 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2606 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2610 for (
int elem = 0; elem < data->count; ++elem) {
2613 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2614 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2615 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2616 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2621 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2622 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2623 : (samplerD ? nativeBindingVert.first : -1);
2624 if (nativeBindingVert.first >= 0 && texD)
2625 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2626 if (samplerBinding >= 0)
2627 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2629 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2630 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2631 : (samplerD ? nativeBindingHull.first : -1);
2632 if (nativeBindingHull.first >= 0 && texD)
2633 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2634 if (samplerBinding >= 0)
2635 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2637 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2638 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2639 : (samplerD ? nativeBindingDomain.first : -1);
2640 if (nativeBindingDomain.first >= 0 && texD)
2641 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2642 if (samplerBinding >= 0)
2643 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2645 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2646 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2647 : (samplerD ? nativeBindingGeom.first : -1);
2648 if (nativeBindingGeom.first >= 0 && texD)
2649 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2650 if (samplerBinding >= 0)
2651 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2653 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2654 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2655 : (samplerD ? nativeBindingFrag.first : -1);
2656 if (nativeBindingFrag.first >= 0 && texD)
2657 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2658 if (samplerBinding >= 0)
2659 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2661 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2662 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2663 : (samplerD ? nativeBindingComp.first : -1);
2664 if (nativeBindingComp.first >= 0 && texD)
2665 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2666 if (samplerBinding >= 0)
2667 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2672 case QRhiShaderResourceBinding::ImageLoad:
2673 case QRhiShaderResourceBinding::ImageStore:
2674 case QRhiShaderResourceBinding::ImageLoadStore:
2677 bd.simage.id = texD->m_id;
2678 bd.simage.generation = texD->generation;
2679 bool validStage =
false;
2680 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2681 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2682 if (nativeBinding.first >= 0) {
2683 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2685 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2689 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2690 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2691 if (nativeBinding.first >= 0) {
2692 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2694 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2699 qWarning(
"Unordered access only supported at fragment/compute stage");
2702 case QRhiShaderResourceBinding::BufferLoad:
2703 case QRhiShaderResourceBinding::BufferStore:
2704 case QRhiShaderResourceBinding::BufferLoadStore:
2707 bd.sbuf.id = bufD->m_id;
2708 bd.sbuf.generation = bufD->generation;
2709 bool validStage =
false;
2710 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2711 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2712 if (nativeBinding.first >= 0) {
2713 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2715 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2719 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2720 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2721 if (nativeBinding.first >= 0) {
2722 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2724 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2729 qWarning(
"Unordered access only supported at fragment/compute stage");
2743 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2744 return a.breg < b.breg;
2746 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2747 return a.treg < b.treg;
2749 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2750 return a.sreg < b.sreg;
2752 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2753 return a.ureg < b.ureg;
2757 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2758 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2759 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2760 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2761 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2762 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2764 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2765 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2766 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2767 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2768 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2769 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2771 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2772 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2780 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2782 D3D11_MAPPED_SUBRESOURCE mp;
2783 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2784 if (SUCCEEDED(hr)) {
2785 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2786 context->Unmap(bufD->buffer, 0);
2788 qWarning(
"Failed to map buffer: %s",
2789 qPrintable(QSystemError::windowsComString(hr)));
2795 const QRhiBatchedBindings<UINT> *originalBindings,
2796 const QRhiBatchedBindings<UINT> *staticOffsets,
2797 const uint *dynOfsPairs,
int dynOfsPairCount)
2799 const int count = staticOffsets->batches[batchIndex].resources.count();
2802 for (
int b = 0; b < count; ++b) {
2803 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2804 for (
int di = 0; di < dynOfsPairCount; ++di) {
2805 const uint binding = dynOfsPairs[2 * di];
2808 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2809 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2810 offsets[b] = offsetInConstants;
2819 if (startSlot + countSlots > maxSlots) {
2820 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2821 resType, countSlots, startSlot, maxSlots);
2822 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2827#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2828 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2829 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2830 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2831 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2832 batches.ubufs.batches[i].resources.count(),
2833 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2834 #stagePrefixU " cbuf");
2836 if (!dynOfsPairCount) {
2837 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2839 batches.ubufs.batches[i].resources.constData(),
2840 batches.ubufoffsets.batches[i].resources.constData(),
2841 batches.ubufsizes.batches[i].resources.constData());
2843 applyDynamicOffsets(offsets, i,
2844 &batches.ubuforigbindings, &batches.ubufoffsets,
2845 dynOfsPairs, dynOfsPairCount);
2846 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2848 batches.ubufs.batches[i].resources.constData(),
2850 batches.ubufsizes.batches[i].resources.constData());
2856#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2857 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2858 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2859 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2860 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2862 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2864 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2865 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2866 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2868 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2869 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2870 int(batch.startBinding + count) - 1
);
2875#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2876 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2877 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2878 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2881 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2883 batch.resources.constData(),
2885 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2886 int(batch.startBinding + count) - 1
);
2893 const uint *dynOfsPairs,
int dynOfsPairCount,
2894 bool offsetOnlyChange,
2906 if (!offsetOnlyChange) {
2916 if (allResourceBatches.fsUavBatches.present) {
2917 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2918 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2920 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2922 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
2923 context->OMSetRenderTargetsAndUnorderedAccessViews(
2924 UINT(rtUavState->rtViews.colorAttCount),
2925 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
2926 rtUavState->rtViews.dsv,
2927 UINT(batch.startBinding),
2929 batch.resources.constData(),
2932 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2933 int(batch.startBinding + count) - 1);
2946 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2952 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2953 for (
int i = 0; i < count; ++i)
2954 nullbufs[i] =
nullptr;
2955 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2956 for (
int i = 0; i < count; ++i)
2958 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2959 for (
int i = 0; i < count; ++i)
2961 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2971 if (nullsrvCount > 0) {
2972 QVarLengthArray<ID3D11ShaderResourceView *,
2973 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2974 for (
int i = 0; i < nullsrvs.count(); ++i)
2975 nullsrvs[i] =
nullptr;
2977 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2981 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2985 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2989 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2993 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2997 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
3003 rtUavState->update(cbD->currentRenderTargetViews);
3004 context->OMSetRenderTargetsAndUnorderedAccessViews(
3005 UINT(cbD->currentRenderTargetViews.colorAttCount),
3006 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
3007 cbD->currentRenderTargetViews.dsv,
3008 0, 0,
nullptr,
nullptr);
3013 QVarLengthArray<ID3D11UnorderedAccessView *,
3014 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
3015 for (
int i = 0; i < nulluavCount; ++i)
3016 nulluavs[i] =
nullptr;
3017 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
3022#define SETSHADER(StageL, StageU)
3023 if (cmd.args.bindGraphicsPipeline.StageL) {
3024 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
3025 currentShaderMask |= StageU##MaskBit;
3026 } else if (currentShaderMask & StageU##MaskBit) {
3027 context->StageU##SetShader(nullptr, nullptr, 0
);
3028 currentShaderMask &= ~StageU##MaskBit;
3033 quint32 stencilRef = 0;
3034 float blendConstants[] = { 1, 1, 1, 1 };
3035 enum ActiveShaderMask {
3042 int currentShaderMask = 0xFF;
3048 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3051 case QD3D11CommandBuffer::Command::BeginFrame:
3052 if (cmd.args.beginFrame.tsDisjointQuery)
3053 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3054 if (cmd.args.beginFrame.tsQuery) {
3055 if (cmd.args.beginFrame.swapchainRtv) {
3060 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3061 rtUavState.update(cbD->currentRenderTargetViews);
3062 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3064 context->End(cmd.args.beginFrame.tsQuery);
3067 case QD3D11CommandBuffer::Command::EndFrame:
3068 if (cmd.args.endFrame.tsQuery)
3069 context->End(cmd.args.endFrame.tsQuery);
3070 if (cmd.args.endFrame.tsDisjointQuery)
3071 context->End(cmd.args.endFrame.tsDisjointQuery);
3078 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3079 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3080 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3081 context->OMSetRenderTargets(colorAttCount,
3082 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3083 cmd.args.setRenderTarget.rtViews.dsv);
3090 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3091 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3094 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3095 ds |= D3D11_CLEAR_DEPTH;
3096 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3097 ds |= D3D11_CLEAR_STENCIL;
3098 if (ds && cmd.args.clear.rtViews.dsv)
3099 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3105 v.TopLeftX = cmd.args.viewport.x;
3106 v.TopLeftY = cmd.args.viewport.y;
3107 v.Width = cmd.args.viewport.w;
3108 v.Height = cmd.args.viewport.h;
3109 v.MinDepth = cmd.args.viewport.d0;
3110 v.MaxDepth = cmd.args.viewport.d1;
3111 context->RSSetViewports(1, &v);
3117 r.left = cmd.args.scissor.x;
3118 r.top = cmd.args.scissor.y;
3120 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3121 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3122 context->RSSetScissorRects(1, &r);
3128 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3129 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3130 UINT(cmd.args.bindVertexBuffers.slotCount),
3131 cmd.args.bindVertexBuffers.buffers,
3132 cmd.args.bindVertexBuffers.strides,
3133 cmd.args.bindVertexBuffers.offsets);
3137 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3138 cmd.args.bindIndexBuffer.format,
3139 cmd.args.bindIndexBuffer.offset);
3148 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3149 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3150 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3151 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3152 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3155 case QD3D11CommandBuffer::Command::BindShaderResources:
3156 bindShaderResources(cbD,
3157 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3158 cmd.args.bindShaderResources.dynamicOffsetPairs,
3159 cmd.args.bindShaderResources.dynamicOffsetCount,
3160 cmd.args.bindShaderResources.offsetOnlyChange,
3164 stencilRef = cmd.args.stencilRef.ref;
3165 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3168 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3169 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3171 case QD3D11CommandBuffer::Command::Draw:
3172 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3173 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3175 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3176 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3178 case QD3D11CommandBuffer::Command::DrawIndexed:
3179 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3180 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3181 cmd.args.drawIndexed.vertexOffset);
3183 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3184 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3185 cmd.args.drawIndexed.firstInstance);
3189 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3190 const UINT stride = cmd.args.drawIndirect.stride;
3191 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3192 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3193 alignedByteOffsetForArgs += stride;
3199 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3200 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3201 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3202 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3203 alignedByteOffsetForArgs += stride;
3209 if (cmd.args.updateSubRes.dst) {
3210 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3211 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3212 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3215 case QD3D11CommandBuffer::Command::CopySubRes:
3216 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3217 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3218 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3219 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3221 case QD3D11CommandBuffer::Command::ResolveSubRes:
3222 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3223 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3224 cmd.args.resolveSubRes.format);
3226 case QD3D11CommandBuffer::Command::GenMip:
3227 context->GenerateMips(cmd.args.genMip.srv);
3229 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3230 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3232 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3233 annotations->EndEvent();
3235 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3236 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3238 case QD3D11CommandBuffer::Command::BindComputePipeline:
3239 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3241 case QD3D11CommandBuffer::Command::Dispatch:
3242 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3244 case QD3D11CommandBuffer::Command::DispatchIndirect:
3245 context->DispatchIndirect(cmd.args.dispatchIndirect.indirectBuffer,
3246 cmd.args.dispatchIndirect.indirectBufferOffset);
3275 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3276 it.value()->Release();
3281 rhiD->unregisterResource(
this);
3287 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3288 u |= D3D11_BIND_VERTEX_BUFFER;
3289 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3290 u |= D3D11_BIND_INDEX_BUFFER;
3291 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3292 u |= D3D11_BIND_CONSTANT_BUFFER;
3293 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3294 u |= D3D11_BIND_UNORDERED_ACCESS;
3303 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3304 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3308 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3309 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3313 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3314 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3318 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3323 const quint32 minSize = m_usage.testFlag(QRhiBuffer::IndirectBuffer) ? 12u : 1u;
3324 const quint32 roundedSize = aligned(qMax(nonZeroSize, minSize),
3325 m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3327 D3D11_BUFFER_DESC desc = {};
3328 desc.ByteWidth = roundedSize;
3329 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3330 desc.BindFlags = toD3DBufferUsage(m_usage);
3331 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3332 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3333 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3334 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3337 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3339 qWarning(
"Failed to create buffer: %s",
3340 qPrintable(QSystemError::windowsComString(hr)));
3344 if (m_type == Dynamic) {
3345 dynBuf =
new char[nonZeroSize];
3349 if (!m_objectName.isEmpty())
3350 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3353 rhiD->registerResource(
this);
3359 if (m_type == Dynamic) {
3363 return { { &buffer }, 1 };
3374 Q_ASSERT(m_type == Dynamic);
3375 D3D11_MAPPED_SUBRESOURCE mp;
3377 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3379 qWarning(
"Failed to map buffer: %s",
3380 qPrintable(QSystemError::windowsComString(hr)));
3383 return static_cast<
char *>(mp.pData);
3389 rhiD->context->Unmap(buffer, 0);
3394 auto it = uavs.find(offset);
3395 if (it != uavs.end())
3399 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3400 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3401 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3402 desc.Buffer.FirstElement = offset / 4u;
3403 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3404 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3407 ID3D11UnorderedAccessView *uav =
nullptr;
3408 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3410 qWarning(
"Failed to create UAV: %s",
3411 qPrintable(QSystemError::windowsComString(hr)));
3420 int sampleCount, QRhiRenderBuffer::Flags flags,
3421 QRhiTexture::Format backingFormatHint)
3451 rhiD->unregisterResource(
this);
3459 if (m_pixelSize.isEmpty())
3463 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3465 D3D11_TEXTURE2D_DESC desc = {};
3466 desc.Width = UINT(m_pixelSize.width());
3467 desc.Height = UINT(m_pixelSize.height());
3470 desc.SampleDesc = sampleDesc;
3471 desc.Usage = D3D11_USAGE_DEFAULT;
3473 if (m_type == Color) {
3474 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3475 : toD3DTextureFormat(m_backingFormatHint, {});
3476 desc.Format = dxgiFormat;
3477 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3478 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3480 qWarning(
"Failed to create color renderbuffer: %s",
3481 qPrintable(QSystemError::windowsComString(hr)));
3484 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3485 rtvDesc.Format = dxgiFormat;
3486 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3487 : D3D11_RTV_DIMENSION_TEXTURE2D;
3488 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3490 qWarning(
"Failed to create rtv: %s",
3491 qPrintable(QSystemError::windowsComString(hr)));
3494 }
else if (m_type == DepthStencil) {
3495 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3496 desc.Format = dxgiFormat;
3497 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3498 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3500 qWarning(
"Failed to create depth-stencil buffer: %s",
3501 qPrintable(QSystemError::windowsComString(hr)));
3504 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3505 dsvDesc.Format = dxgiFormat;
3506 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3507 : D3D11_DSV_DIMENSION_TEXTURE2D;
3508 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3510 qWarning(
"Failed to create dsv: %s",
3511 qPrintable(QSystemError::windowsComString(hr)));
3518 if (!m_objectName.isEmpty())
3519 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3522 rhiD->registerResource(
this);
3528 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3529 return m_backingFormatHint;
3531 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3535 int arraySize,
int sampleCount, Flags flags)
3538 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3539 perLevelViews[i] =
nullptr;
3549 if (!tex && !tex3D && !tex1D)
3557 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3558 if (perLevelViews[i]) {
3559 perLevelViews[i]->Release();
3560 perLevelViews[i] =
nullptr;
3579 rhiD->unregisterResource(
this);
3585 case QRhiTexture::Format::D16:
3586 return DXGI_FORMAT_R16_FLOAT;
3587 case QRhiTexture::Format::D24:
3588 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3589 case QRhiTexture::Format::D24S8:
3590 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3591 case QRhiTexture::Format::D32F:
3592 return DXGI_FORMAT_R32_FLOAT;
3593 case QRhiTexture::Format::D32FS8:
3594 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3597 return DXGI_FORMAT_R32_FLOAT;
3604 case QRhiTexture::Format::D16:
3605 return DXGI_FORMAT_D16_UNORM;
3606 case QRhiTexture::Format::D24:
3607 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3608 case QRhiTexture::Format::D24S8:
3609 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3610 case QRhiTexture::Format::D32F:
3611 return DXGI_FORMAT_D32_FLOAT;
3612 case QRhiTexture::Format::D32FS8:
3613 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3616 return DXGI_FORMAT_D32_FLOAT;
3622 if (tex || tex3D || tex1D)
3626 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3629 const bool isDepth = isDepthTextureFormat(m_format);
3630 const bool isCube = m_flags.testFlag(CubeMap);
3631 const bool is3D = m_flags.testFlag(ThreeDimensional);
3632 const bool isArray = m_flags.testFlag(TextureArray);
3633 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3634 const bool is1D = m_flags.testFlag(OneDimensional);
3636 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3637 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3639 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3640 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3641 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3642 if (sampleDesc.Count > 1) {
3644 qWarning(
"Cubemap texture cannot be multisample");
3648 qWarning(
"3D texture cannot be multisample");
3652 qWarning(
"Multisample texture cannot have mipmaps");
3656 if (isDepth && hasMipMaps) {
3657 qWarning(
"Depth texture cannot have mipmaps");
3660 if (isCube && is3D) {
3661 qWarning(
"Texture cannot be both cube and 3D");
3664 if (isArray && is3D) {
3665 qWarning(
"Texture cannot be both array and 3D");
3668 if (isCube && is1D) {
3669 qWarning(
"Texture cannot be both cube and 1D");
3673 qWarning(
"Texture cannot be both 1D and 3D");
3676 if (m_depth > 1 && !is3D) {
3677 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3680 if (m_arraySize > 0 && !isArray) {
3681 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3684 if (m_arraySize < 1 && isArray) {
3685 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3689 if (!rhiD->textureFormatInfo(m_format, size,
nullptr,
nullptr,
nullptr))
3693 *adjustedSize = size;
3701 const bool isDepth = isDepthTextureFormat(m_format);
3702 const bool isCube = m_flags.testFlag(CubeMap);
3703 const bool is3D = m_flags.testFlag(ThreeDimensional);
3704 const bool isArray = m_flags.testFlag(TextureArray);
3705 const bool is1D = m_flags.testFlag(OneDimensional);
3707 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3708 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3710 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3711 srvDesc.TextureCube.MipLevels = mipLevelCount;
3715 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3716 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3717 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3718 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3719 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3721 srvDesc.Texture1DArray.FirstArraySlice = 0;
3722 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3725 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3726 srvDesc.Texture1D.MipLevels = mipLevelCount;
3728 }
else if (isArray) {
3729 if (sampleDesc.Count > 1) {
3730 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3731 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3732 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3733 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3735 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3736 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3739 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3740 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3741 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3742 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3743 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3745 srvDesc.Texture2DArray.FirstArraySlice = 0;
3746 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3750 if (sampleDesc.Count > 1) {
3751 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3753 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3754 srvDesc.Texture3D.MipLevels = mipLevelCount;
3756 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3757 srvDesc.Texture2D.MipLevels = mipLevelCount;
3762 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3764 qWarning(
"Failed to create srv: %s",
3765 qPrintable(QSystemError::windowsComString(hr)));
3776 if (!prepareCreate(&size))
3779 const bool isDepth = isDepthTextureFormat(m_format);
3780 const bool isCube = m_flags.testFlag(CubeMap);
3781 const bool is3D = m_flags.testFlag(ThreeDimensional);
3782 const bool isArray = m_flags.testFlag(TextureArray);
3783 const bool is1D = m_flags.testFlag(OneDimensional);
3785 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3786 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3787 if (m_flags.testFlag(RenderTarget)) {
3789 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3791 bindFlags |= D3D11_BIND_RENDER_TARGET;
3793 if (m_flags.testFlag(UsedWithGenerateMips)) {
3795 qWarning(
"Depth texture cannot have mipmaps generated");
3798 bindFlags |= D3D11_BIND_RENDER_TARGET;
3799 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3801 if (m_flags.testFlag(UsedWithLoadStore))
3802 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3806 D3D11_TEXTURE1D_DESC desc = {};
3807 desc.Width = UINT(size.width());
3808 desc.MipLevels = mipLevelCount;
3809 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3810 desc.Format = dxgiFormat;
3811 desc.Usage = D3D11_USAGE_DEFAULT;
3812 desc.BindFlags = bindFlags;
3813 desc.MiscFlags = miscFlags;
3815 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3817 qWarning(
"Failed to create 1D texture: %s",
3818 qPrintable(QSystemError::windowsComString(hr)));
3821 if (!m_objectName.isEmpty())
3822 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3823 m_objectName.constData());
3825 D3D11_TEXTURE2D_DESC desc = {};
3826 desc.Width = UINT(size.width());
3827 desc.Height = UINT(size.height());
3828 desc.MipLevels = mipLevelCount;
3829 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3830 desc.Format = dxgiFormat;
3831 desc.SampleDesc = sampleDesc;
3832 desc.Usage = D3D11_USAGE_DEFAULT;
3833 desc.BindFlags = bindFlags;
3834 desc.MiscFlags = miscFlags;
3836 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3838 qWarning(
"Failed to create 2D texture: %s",
3839 qPrintable(QSystemError::windowsComString(hr)));
3840 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
3844 if (!m_objectName.isEmpty())
3845 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3847 D3D11_TEXTURE3D_DESC desc = {};
3848 desc.Width = UINT(size.width());
3849 desc.Height = UINT(size.height());
3850 desc.Depth = UINT(qMax(1, m_depth));
3851 desc.MipLevels = mipLevelCount;
3852 desc.Format = dxgiFormat;
3853 desc.Usage = D3D11_USAGE_DEFAULT;
3854 desc.BindFlags = bindFlags;
3855 desc.MiscFlags = miscFlags;
3857 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3859 qWarning(
"Failed to create 3D texture: %s",
3860 qPrintable(QSystemError::windowsComString(hr)));
3861 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
3865 if (!m_objectName.isEmpty())
3866 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3873 rhiD->registerResource(
this);
3882 if (!prepareCreate())
3885 if (m_flags.testFlag(ThreeDimensional))
3886 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3887 else if (m_flags.testFlags(OneDimensional))
3888 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3890 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3897 rhiD->registerResource(
this);
3903 return { quint64(textureResource()), 0 };
3908 if (perLevelViews[level])
3909 return perLevelViews[level];
3911 const bool isCube = m_flags.testFlag(CubeMap);
3912 const bool isArray = m_flags.testFlag(TextureArray);
3913 const bool is3D = m_flags.testFlag(ThreeDimensional);
3914 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3915 desc.Format = dxgiFormat;
3917 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3918 desc.Texture2DArray.MipSlice = UINT(level);
3919 desc.Texture2DArray.FirstArraySlice = 0;
3920 desc.Texture2DArray.ArraySize = 6;
3921 }
else if (isArray) {
3922 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3923 desc.Texture2DArray.MipSlice = UINT(level);
3924 desc.Texture2DArray.FirstArraySlice = 0;
3925 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3927 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3928 desc.Texture3D.MipSlice = UINT(level);
3929 desc.Texture3D.WSize = UINT(m_depth);
3931 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3932 desc.Texture2D.MipSlice = UINT(level);
3936 ID3D11UnorderedAccessView *uav =
nullptr;
3937 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3939 qWarning(
"Failed to create UAV: %s",
3940 qPrintable(QSystemError::windowsComString(hr)));
3944 perLevelViews[level] = uav;
3949 AddressMode u, AddressMode v, AddressMode w)
3964 samplerState->Release();
3965 samplerState =
nullptr;
3969 rhiD->unregisterResource(
this);
3972static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3974 if (minFilter == QRhiSampler::Nearest) {
3975 if (magFilter == QRhiSampler::Nearest) {
3976 if (mipFilter == QRhiSampler::Linear)
3977 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3979 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3981 if (mipFilter == QRhiSampler::Linear)
3982 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3984 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3987 if (magFilter == QRhiSampler::Nearest) {
3988 if (mipFilter == QRhiSampler::Linear)
3989 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3991 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3993 if (mipFilter == QRhiSampler::Linear)
3994 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3996 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
4001 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4007 case QRhiSampler::Repeat:
4008 return D3D11_TEXTURE_ADDRESS_WRAP;
4009 case QRhiSampler::ClampToEdge:
4010 return D3D11_TEXTURE_ADDRESS_CLAMP;
4011 case QRhiSampler::Mirror:
4012 return D3D11_TEXTURE_ADDRESS_MIRROR;
4015 return D3D11_TEXTURE_ADDRESS_CLAMP;
4022 case QRhiSampler::Never:
4023 return D3D11_COMPARISON_NEVER;
4024 case QRhiSampler::Less:
4025 return D3D11_COMPARISON_LESS;
4026 case QRhiSampler::Equal:
4027 return D3D11_COMPARISON_EQUAL;
4028 case QRhiSampler::LessOrEqual:
4029 return D3D11_COMPARISON_LESS_EQUAL;
4030 case QRhiSampler::Greater:
4031 return D3D11_COMPARISON_GREATER;
4032 case QRhiSampler::NotEqual:
4033 return D3D11_COMPARISON_NOT_EQUAL;
4034 case QRhiSampler::GreaterOrEqual:
4035 return D3D11_COMPARISON_GREATER_EQUAL;
4036 case QRhiSampler::Always:
4037 return D3D11_COMPARISON_ALWAYS;
4040 return D3D11_COMPARISON_NEVER;
4049 D3D11_SAMPLER_DESC desc = {};
4050 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
4051 if (m_compareOp != Never)
4052 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
4053 desc.AddressU = toD3DAddressMode(m_addressU);
4054 desc.AddressV = toD3DAddressMode(m_addressV);
4055 desc.AddressW = toD3DAddressMode(m_addressW);
4056 desc.MaxAnisotropy = 1.0f;
4057 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
4058 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
4061 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
4063 qWarning(
"Failed to create sampler state: %s",
4064 qPrintable(QSystemError::windowsComString(hr)));
4069 rhiD->registerResource(
this);
4088 rhiD->unregisterResource(
this);
4101 rhiD->registerResource(rpD,
false);
4138 return d.sampleCount;
4142 const QRhiTextureRenderTargetDescription &desc,
4160 if (!rtv[0] && !dsv)
4179 rhiD->unregisterResource(
this);
4186 rhiD->registerResource(rpD,
false);
4195 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4196 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4197 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4201 int colorAttCount = 0;
4203 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4205 const QRhiColorAttachment &colorAtt(*it);
4206 QRhiTexture *texture = colorAtt.texture();
4207 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4208 Q_ASSERT(texture || rb);
4211 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4212 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4213 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4214 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4215 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4216 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4217 rtvDesc.Texture2DArray.ArraySize = 1;
4218 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4219 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4220 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4221 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4222 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4223 rtvDesc.Texture1DArray.ArraySize = 1;
4225 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4226 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4228 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4229 if (texD->sampleDesc.Count > 1) {
4230 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4231 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4232 rtvDesc.Texture2DMSArray.ArraySize = 1;
4234 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4235 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4236 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4237 rtvDesc.Texture2DArray.ArraySize = 1;
4239 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4240 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4241 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4242 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4243 rtvDesc.Texture3D.WSize = 1;
4245 if (texD->sampleDesc.Count > 1) {
4246 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4248 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4249 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4252 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4254 qWarning(
"Failed to create rtv: %s",
4255 qPrintable(QSystemError::windowsComString(hr)));
4259 if (attIndex == 0) {
4260 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4261 d.sampleCount =
int(texD->sampleDesc.Count);
4266 rtv[attIndex] = rbD->rtv;
4267 if (attIndex == 0) {
4268 d.pixelSize = rbD->pixelSize();
4269 d.sampleCount =
int(rbD->sampleDesc.Count);
4275 if (hasDepthStencil) {
4276 if (m_desc.depthTexture()) {
4279 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4280 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4281 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4282 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4283 if (isMultisample) {
4284 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4285 if (m_desc.depthLayer() >= 0) {
4286 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4287 dsvDesc.Texture2DMSArray.ArraySize = 1;
4288 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4289 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4290 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4292 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4293 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4296 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4297 if (m_desc.depthLayer() >= 0) {
4298 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4299 dsvDesc.Texture2DArray.ArraySize = 1;
4300 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4301 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4302 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4304 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4305 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4310 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4311 : D3D11_DSV_DIMENSION_TEXTURE2D;
4313 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4315 qWarning(
"Failed to create dsv: %s",
4316 qPrintable(QSystemError::windowsComString(hr)));
4319 if (colorAttCount == 0) {
4320 d.pixelSize = depthTexD->pixelSize();
4321 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4326 dsv = depthRbD->dsv;
4327 if (colorAttCount == 0) {
4328 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4329 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4336 d.views.setFrom(colorAttCount, rtv, dsv);
4338 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4340 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4342 rhiD->registerResource(
this);
4348 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4361 return d.sampleCount;
4376 sortedBindings.clear();
4377 boundResourceData.clear();
4381 rhiD->unregisterResource(
this);
4386 if (!sortedBindings.isEmpty())
4390 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4393 rhiD->updateLayoutDesc(
this);
4395 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4396 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4398 boundResourceData.resize(sortedBindings.count());
4400 for (BoundResourceData &bd : boundResourceData)
4401 memset(&bd, 0,
sizeof(BoundResourceData));
4404 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4405 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4406 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4407 hasDynamicOffset =
true;
4413 rhiD->registerResource(
this,
false);
4419 sortedBindings.clear();
4420 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4421 if (!flags.testFlag(BindingsAreSorted))
4422 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4424 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4425 for (BoundResourceData &bd : boundResourceData)
4426 memset(&bd, 0,
sizeof(BoundResourceData));
4445 s.shader->Release();
4448 s.nativeResourceBindingMap.clear();
4460 blendState->Release();
4461 blendState =
nullptr;
4465 inputLayout->Release();
4466 inputLayout =
nullptr;
4470 rastState->Release();
4471 rastState =
nullptr;
4474 releasePipelineShader(vs);
4475 releasePipelineShader(hs);
4476 releasePipelineShader(ds);
4477 releasePipelineShader(gs);
4478 releasePipelineShader(fs);
4482 rhiD->unregisterResource(
this);
4488 case QRhiGraphicsPipeline::None:
4489 return D3D11_CULL_NONE;
4490 case QRhiGraphicsPipeline::Front:
4491 return D3D11_CULL_FRONT;
4492 case QRhiGraphicsPipeline::Back:
4493 return D3D11_CULL_BACK;
4496 return D3D11_CULL_NONE;
4503 case QRhiGraphicsPipeline::Fill:
4504 return D3D11_FILL_SOLID;
4505 case QRhiGraphicsPipeline::Line:
4506 return D3D11_FILL_WIREFRAME;
4509 return D3D11_FILL_SOLID;
4516 case QRhiGraphicsPipeline::Never:
4517 return D3D11_COMPARISON_NEVER;
4518 case QRhiGraphicsPipeline::Less:
4519 return D3D11_COMPARISON_LESS;
4520 case QRhiGraphicsPipeline::Equal:
4521 return D3D11_COMPARISON_EQUAL;
4522 case QRhiGraphicsPipeline::LessOrEqual:
4523 return D3D11_COMPARISON_LESS_EQUAL;
4524 case QRhiGraphicsPipeline::Greater:
4525 return D3D11_COMPARISON_GREATER;
4526 case QRhiGraphicsPipeline::NotEqual:
4527 return D3D11_COMPARISON_NOT_EQUAL;
4528 case QRhiGraphicsPipeline::GreaterOrEqual:
4529 return D3D11_COMPARISON_GREATER_EQUAL;
4530 case QRhiGraphicsPipeline::Always:
4531 return D3D11_COMPARISON_ALWAYS;
4534 return D3D11_COMPARISON_ALWAYS;
4541 case QRhiGraphicsPipeline::StencilZero:
4542 return D3D11_STENCIL_OP_ZERO;
4543 case QRhiGraphicsPipeline::Keep:
4544 return D3D11_STENCIL_OP_KEEP;
4545 case QRhiGraphicsPipeline::Replace:
4546 return D3D11_STENCIL_OP_REPLACE;
4547 case QRhiGraphicsPipeline::IncrementAndClamp:
4548 return D3D11_STENCIL_OP_INCR_SAT;
4549 case QRhiGraphicsPipeline::DecrementAndClamp:
4550 return D3D11_STENCIL_OP_DECR_SAT;
4551 case QRhiGraphicsPipeline::Invert:
4552 return D3D11_STENCIL_OP_INVERT;
4553 case QRhiGraphicsPipeline::IncrementAndWrap:
4554 return D3D11_STENCIL_OP_INCR;
4555 case QRhiGraphicsPipeline::DecrementAndWrap:
4556 return D3D11_STENCIL_OP_DECR;
4559 return D3D11_STENCIL_OP_KEEP;
4566 case QRhiVertexInputAttribute::Float4:
4567 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4568 case QRhiVertexInputAttribute::Float3:
4569 return DXGI_FORMAT_R32G32B32_FLOAT;
4570 case QRhiVertexInputAttribute::Float2:
4571 return DXGI_FORMAT_R32G32_FLOAT;
4572 case QRhiVertexInputAttribute::Float:
4573 return DXGI_FORMAT_R32_FLOAT;
4574 case QRhiVertexInputAttribute::UNormByte4:
4575 return DXGI_FORMAT_R8G8B8A8_UNORM;
4576 case QRhiVertexInputAttribute::UNormByte2:
4577 return DXGI_FORMAT_R8G8_UNORM;
4578 case QRhiVertexInputAttribute::UNormByte:
4579 return DXGI_FORMAT_R8_UNORM;
4580 case QRhiVertexInputAttribute::UInt4:
4581 return DXGI_FORMAT_R32G32B32A32_UINT;
4582 case QRhiVertexInputAttribute::UInt3:
4583 return DXGI_FORMAT_R32G32B32_UINT;
4584 case QRhiVertexInputAttribute::UInt2:
4585 return DXGI_FORMAT_R32G32_UINT;
4586 case QRhiVertexInputAttribute::UInt:
4587 return DXGI_FORMAT_R32_UINT;
4588 case QRhiVertexInputAttribute::SInt4:
4589 return DXGI_FORMAT_R32G32B32A32_SINT;
4590 case QRhiVertexInputAttribute::SInt3:
4591 return DXGI_FORMAT_R32G32B32_SINT;
4592 case QRhiVertexInputAttribute::SInt2:
4593 return DXGI_FORMAT_R32G32_SINT;
4594 case QRhiVertexInputAttribute::SInt:
4595 return DXGI_FORMAT_R32_SINT;
4596 case QRhiVertexInputAttribute::Half4:
4598 case QRhiVertexInputAttribute::Half3:
4599 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4600 case QRhiVertexInputAttribute::Half2:
4601 return DXGI_FORMAT_R16G16_FLOAT;
4602 case QRhiVertexInputAttribute::Half:
4603 return DXGI_FORMAT_R16_FLOAT;
4604 case QRhiVertexInputAttribute::UShort4:
4606 case QRhiVertexInputAttribute::UShort3:
4607 return DXGI_FORMAT_R16G16B16A16_UINT;
4608 case QRhiVertexInputAttribute::UShort2:
4609 return DXGI_FORMAT_R16G16_UINT;
4610 case QRhiVertexInputAttribute::UShort:
4611 return DXGI_FORMAT_R16_UINT;
4612 case QRhiVertexInputAttribute::SShort4:
4614 case QRhiVertexInputAttribute::SShort3:
4615 return DXGI_FORMAT_R16G16B16A16_SINT;
4616 case QRhiVertexInputAttribute::SShort2:
4617 return DXGI_FORMAT_R16G16_SINT;
4618 case QRhiVertexInputAttribute::SShort:
4619 return DXGI_FORMAT_R16_SINT;
4622 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4629 case QRhiGraphicsPipeline::Triangles:
4630 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4631 case QRhiGraphicsPipeline::TriangleStrip:
4632 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4633 case QRhiGraphicsPipeline::Lines:
4634 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4635 case QRhiGraphicsPipeline::LineStrip:
4636 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4637 case QRhiGraphicsPipeline::Points:
4638 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4639 case QRhiGraphicsPipeline::Patches:
4640 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4641 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4644 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4651 if (c.testFlag(QRhiGraphicsPipeline::R))
4652 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4653 if (c.testFlag(QRhiGraphicsPipeline::G))
4654 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4655 if (c.testFlag(QRhiGraphicsPipeline::B))
4656 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4657 if (c.testFlag(QRhiGraphicsPipeline::A))
4658 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4671 case QRhiGraphicsPipeline::Zero:
4672 return D3D11_BLEND_ZERO;
4673 case QRhiGraphicsPipeline::One:
4674 return D3D11_BLEND_ONE;
4675 case QRhiGraphicsPipeline::SrcColor:
4676 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4677 case QRhiGraphicsPipeline::OneMinusSrcColor:
4678 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4679 case QRhiGraphicsPipeline::DstColor:
4680 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4681 case QRhiGraphicsPipeline::OneMinusDstColor:
4682 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4683 case QRhiGraphicsPipeline::SrcAlpha:
4684 return D3D11_BLEND_SRC_ALPHA;
4685 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4686 return D3D11_BLEND_INV_SRC_ALPHA;
4687 case QRhiGraphicsPipeline::DstAlpha:
4688 return D3D11_BLEND_DEST_ALPHA;
4689 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4690 return D3D11_BLEND_INV_DEST_ALPHA;
4691 case QRhiGraphicsPipeline::ConstantColor:
4692 case QRhiGraphicsPipeline::ConstantAlpha:
4693 return D3D11_BLEND_BLEND_FACTOR;
4694 case QRhiGraphicsPipeline::OneMinusConstantColor:
4695 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4696 return D3D11_BLEND_INV_BLEND_FACTOR;
4697 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4698 return D3D11_BLEND_SRC_ALPHA_SAT;
4699 case QRhiGraphicsPipeline::Src1Color:
4700 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4701 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4702 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4703 case QRhiGraphicsPipeline::Src1Alpha:
4704 return D3D11_BLEND_SRC1_ALPHA;
4705 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4706 return D3D11_BLEND_INV_SRC1_ALPHA;
4709 return D3D11_BLEND_ZERO;
4716 case QRhiGraphicsPipeline::Add:
4717 return D3D11_BLEND_OP_ADD;
4718 case QRhiGraphicsPipeline::Subtract:
4719 return D3D11_BLEND_OP_SUBTRACT;
4720 case QRhiGraphicsPipeline::ReverseSubtract:
4721 return D3D11_BLEND_OP_REV_SUBTRACT;
4722 case QRhiGraphicsPipeline::Min:
4723 return D3D11_BLEND_OP_MIN;
4724 case QRhiGraphicsPipeline::Max:
4725 return D3D11_BLEND_OP_MAX;
4728 return D3D11_BLEND_OP_ADD;
4735 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4736 keyBuilder.addData(source);
4737 return keyBuilder.result().toHex();
4740QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4741 QString *error, QShaderKey *usedShaderKey)
4743 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4744 QShaderCode dxbc = shader.shader(key);
4745 if (!dxbc.shader().isEmpty()) {
4747 *usedShaderKey = key;
4748 return dxbc.shader();
4751 key = { QShader::HlslShader, 50, shaderVariant };
4752 QShaderCode hlslSource = shader.shader(key);
4753 if (hlslSource.shader().isEmpty()) {
4754 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4755 return QByteArray();
4759 *usedShaderKey = key;
4762 switch (shader.stage()) {
4763 case QShader::VertexStage:
4766 case QShader::TessellationControlStage:
4769 case QShader::TessellationEvaluationStage:
4772 case QShader::GeometryStage:
4775 case QShader::FragmentStage:
4778 case QShader::ComputeStage:
4782 qWarning(
"compileHlslShaderSource: Unknown SM 5.0 stage (%d)",
int(shader.stage()));
4783 return QByteArray();
4787 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4788 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4789 cacheKey.target = target;
4790 cacheKey.entryPoint = hlslSource.entryPoint();
4791 cacheKey.compileFlags = flags;
4792 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4793 if (cacheIt != m_bytecodeCache.constEnd())
4794 return cacheIt.value();
4797 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4798 if (d3dCompile ==
nullptr) {
4799 qWarning(
"Unable to resolve function D3DCompile()");
4800 return QByteArray();
4803 ID3DBlob *bytecode =
nullptr;
4804 ID3DBlob *errors =
nullptr;
4805 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4806 nullptr,
nullptr,
nullptr,
4807 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4808 if (FAILED(hr) || !bytecode) {
4809 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4811 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4812 int(errors->GetBufferSize()));
4815 return QByteArray();
4819 result.resize(
int(bytecode->GetBufferSize()));
4820 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4821 bytecode->Release();
4823 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4824 m_bytecodeCache.insert(cacheKey, result);
4835 rhiD->pipelineCreationStart();
4836 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4839 D3D11_RASTERIZER_DESC rastDesc = {};
4840 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4841 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4842 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4843 rastDesc.DepthBias = m_depthBias;
4844 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4845 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4846 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4847 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4848 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4850 qWarning(
"Failed to create rasterizer state: %s",
4851 qPrintable(QSystemError::windowsComString(hr)));
4855 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4856 dsDesc.DepthEnable = m_depthTest;
4857 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4858 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4859 dsDesc.StencilEnable = m_stencilTest;
4860 if (m_stencilTest) {
4861 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4862 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4863 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4864 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4865 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4866 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4867 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4868 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4869 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4870 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4872 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4874 qWarning(
"Failed to create depth-stencil state: %s",
4875 qPrintable(QSystemError::windowsComString(hr)));
4879 D3D11_BLEND_DESC blendDesc = {};
4880 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4881 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4882 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4883 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4884 blend.BlendEnable = b.enable;
4885 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4886 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4887 blend.BlendOp = toD3DBlendOp(b.opColor);
4888 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4889 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4890 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4891 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4892 blendDesc.RenderTarget[i] = blend;
4894 if (m_targetBlends.isEmpty()) {
4895 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4896 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4897 blendDesc.RenderTarget[0] = blend;
4899 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4901 qWarning(
"Failed to create blend state: %s",
4902 qPrintable(QSystemError::windowsComString(hr)));
4906 QByteArray vsByteCode;
4907 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4908 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4909 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4910 switch (shaderStage.type()) {
4911 case QRhiShaderStage::Vertex:
4912 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4913 vs.shader->AddRef();
4914 vsByteCode = cacheIt->bytecode;
4915 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4917 case QRhiShaderStage::TessellationControl:
4918 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4919 hs.shader->AddRef();
4920 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4922 case QRhiShaderStage::TessellationEvaluation:
4923 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4924 ds.shader->AddRef();
4925 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4927 case QRhiShaderStage::Geometry:
4928 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4929 gs.shader->AddRef();
4930 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4932 case QRhiShaderStage::Fragment:
4933 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4934 fs.shader->AddRef();
4935 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4942 QShaderKey shaderKey;
4943 UINT compileFlags = 0;
4944 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4945 compileFlags |= D3DCOMPILE_DEBUG;
4947 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4948 &error, &shaderKey);
4949 if (bytecode.isEmpty()) {
4950 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4954 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4956 rhiD->clearShaderCache();
4959 switch (shaderStage.type()) {
4960 case QRhiShaderStage::Vertex:
4961 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4963 qWarning(
"Failed to create vertex shader: %s",
4964 qPrintable(QSystemError::windowsComString(hr)));
4967 vsByteCode = bytecode;
4968 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4969 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4970 vs.shader->AddRef();
4972 case QRhiShaderStage::TessellationControl:
4973 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4975 qWarning(
"Failed to create hull shader: %s",
4976 qPrintable(QSystemError::windowsComString(hr)));
4979 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4980 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4981 hs.shader->AddRef();
4983 case QRhiShaderStage::TessellationEvaluation:
4984 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4986 qWarning(
"Failed to create domain shader: %s",
4987 qPrintable(QSystemError::windowsComString(hr)));
4990 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4991 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4992 ds.shader->AddRef();
4994 case QRhiShaderStage::Geometry:
4995 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4997 qWarning(
"Failed to create geometry shader: %s",
4998 qPrintable(QSystemError::windowsComString(hr)));
5001 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5002 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
5003 gs.shader->AddRef();
5005 case QRhiShaderStage::Fragment:
5006 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
5008 qWarning(
"Failed to create pixel shader: %s",
5009 qPrintable(QSystemError::windowsComString(hr)));
5012 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5013 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
5014 fs.shader->AddRef();
5022 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
5024 if (!vsByteCode.isEmpty()) {
5025 QByteArrayList matrixSliceSemantics;
5026 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
5027 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
5030 D3D11_INPUT_ELEMENT_DESC desc = {};
5035 const int matrixSlice = it->matrixSlice();
5036 if (matrixSlice < 0) {
5037 desc.SemanticName =
"TEXCOORD";
5038 desc.SemanticIndex = UINT(it->location());
5042 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
5043 matrixSliceSemantics.append(sem);
5044 desc.SemanticName = matrixSliceSemantics.last().constData();
5045 desc.SemanticIndex = UINT(matrixSlice);
5047 desc.Format = toD3DAttributeFormat(it->format());
5048 desc.InputSlot = UINT(it->binding());
5049 desc.AlignedByteOffset = it->offset();
5050 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
5051 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
5052 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
5053 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
5055 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
5057 inputDescs.append(desc);
5059 if (!inputDescs.isEmpty()) {
5060 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
5061 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
5063 qWarning(
"Failed to create input layout: %s",
5064 qPrintable(QSystemError::windowsComString(hr)));
5070 rhiD->pipelineCreationEnd();
5072 rhiD->registerResource(
this);
5091 cs.shader->Release();
5092 cs.shader =
nullptr;
5093 cs.nativeResourceBindingMap.clear();
5097 rhiD->unregisterResource(
this);
5106 rhiD->pipelineCreationStart();
5108 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5109 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5110 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5111 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5114 QShaderKey shaderKey;
5115 UINT compileFlags = 0;
5116 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5117 compileFlags |= D3DCOMPILE_DEBUG;
5119 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5120 &error, &shaderKey);
5121 if (bytecode.isEmpty()) {
5122 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5126 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5128 qWarning(
"Failed to create compute shader: %s",
5129 qPrintable(QSystemError::windowsComString(hr)));
5133 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5135 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5138 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5141 cs.shader->AddRef();
5143 rhiD->pipelineCreationEnd();
5145 rhiD->registerResource(
this);
5170 D3D11_QUERY_DESC queryDesc = {};
5172 if (!disjointQuery[i]) {
5173 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5174 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5176 qWarning(
"Failed to create timestamp disjoint query: %s",
5177 qPrintable(QSystemError::windowsComString(hr)));
5181 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5182 for (
int j = 0; j < 2; ++j) {
5183 const int idx = 2 * i + j;
5185 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5187 qWarning(
"Failed to create timestamp query: %s",
5188 qPrintable(QSystemError::windowsComString(hr)));
5201 if (disjointQuery[i]) {
5202 disjointQuery[i]->Release();
5203 disjointQuery[i] =
nullptr;
5205 for (
int j = 0; j < 2; ++j) {
5208 query[idx]->Release();
5209 query[idx] =
nullptr;
5217 bool result =
false;
5221 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5222 ID3D11Query *tsStart = query[pairIndex * 2];
5223 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5224 quint64 timestamps[2];
5225 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5228 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5229 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5230 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5233 if (!dj.Disjoint && dj.Frequency) {
5234 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5235 *elapsedSec = elapsedMs / 1000.0;
5238 active[pairIndex] =
false;
5247 backBufferTex =
nullptr;
5248 backBufferRtv =
nullptr;
5250 msaaTex[i] =
nullptr;
5251 msaaRtv[i] =
nullptr;
5262 if (backBufferRtv) {
5263 backBufferRtv->Release();
5264 backBufferRtv =
nullptr;
5266 if (backBufferRtvRight) {
5267 backBufferRtvRight->Release();
5268 backBufferRtvRight =
nullptr;
5270 if (backBufferTex) {
5271 backBufferTex->Release();
5272 backBufferTex =
nullptr;
5276 msaaRtv[i]->Release();
5277 msaaRtv[i] =
nullptr;
5280 msaaTex[i]->Release();
5281 msaaTex[i] =
nullptr;
5293 timestamps.destroy();
5295 swapChain->Release();
5296 swapChain =
nullptr;
5299 dcompVisual->Release();
5300 dcompVisual =
nullptr;
5304 dcompTarget->Release();
5305 dcompTarget =
nullptr;
5308 if (frameLatencyWaitableObject) {
5309 CloseHandle(frameLatencyWaitableObject);
5310 frameLatencyWaitableObject =
nullptr;
5313 QDxgiVSyncService::instance()->unregisterWindow(window);
5317 rhiD->unregisterResource(
this);
5320 rhiD->context->Flush();
5336 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5342 return m_window->size() * m_window->devicePixelRatio();
5351 qWarning(
"Attempted to call isFormatSupported() without a window set");
5356 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5357 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5368 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5377 rhiD->registerResource(rpD,
false);
5382 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5384 D3D11_TEXTURE2D_DESC desc = {};
5385 desc.Width = UINT(size.width());
5386 desc.Height = UINT(size.height());
5389 desc.Format = format;
5390 desc.SampleDesc = sampleDesc;
5391 desc.Usage = D3D11_USAGE_DEFAULT;
5392 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5395 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5397 qWarning(
"Failed to create color buffer texture: %s",
5398 qPrintable(QSystemError::windowsComString(hr)));
5402 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5403 rtvDesc.Format = format;
5404 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5405 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5407 qWarning(
"Failed to create color buffer rtv: %s",
5408 qPrintable(QSystemError::windowsComString(hr)));
5422 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5423 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5424 return dcompDevice ?
true :
false;
5436 const bool needsRegistration = !window || window != m_window;
5437 const bool stereo = m_window->format().stereo();
5440 if (window && window != m_window)
5444 m_currentPixelSize = surfacePixelSize();
5445 pixelSize = m_currentPixelSize;
5447 if (pixelSize.isEmpty())
5450 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5455 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5458 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5460 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5461 qPrintable(QSystemError::windowsComString(hr)));
5464 if (dcompTarget && !dcompVisual) {
5465 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5467 qWarning(
"Failed to create DirectComposition visual: %s",
5468 qPrintable(QSystemError::windowsComString(hr)));
5473 if (
window->requestedFormat().alphaBufferSize() <= 0)
5474 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5475 "This may lead to problems.");
5478 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5485 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5486 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5490 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5491 && swapInterval != 0
5492 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5494 if (useFrameLatencyWaitableObject) {
5496 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5500 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5501 colorFormat = DEFAULT_FORMAT;
5502 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5504 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5505 if (m_format != SDR) {
5506 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5509 case HDRExtendedSrgbLinear:
5510 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5511 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5512 srgbAdjustedColorFormat = colorFormat;
5515 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5516 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5517 srgbAdjustedColorFormat = colorFormat;
5526 qWarning(
"The output associated with the window is not HDR capable "
5527 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5537 DXGI_SWAP_CHAIN_DESC1 desc = {};
5538 desc.Width = UINT(pixelSize.width());
5539 desc.Height = UINT(pixelSize.height());
5540 desc.Format = colorFormat;
5541 desc.SampleDesc.Count = 1;
5542 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5544 desc.Flags = swapChainFlags;
5545 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5546 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5547 desc.Stereo = stereo;
5553 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5558 desc.Scaling = DXGI_SCALING_STRETCH;
5561 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5562 IDXGISwapChain1 *sc1;
5565 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5567 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5572 if (FAILED(hr) && m_format != SDR) {
5573 colorFormat = DEFAULT_FORMAT;
5574 desc.Format = DEFAULT_FORMAT;
5576 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5578 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5581 if (SUCCEEDED(hr)) {
5583 IDXGISwapChain3 *sc3 =
nullptr;
5584 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5585 if (m_format != SDR) {
5586 hr = sc3->SetColorSpace1(hdrColorSpace);
5588 qWarning(
"Failed to set color space on swapchain: %s",
5589 qPrintable(QSystemError::windowsComString(hr)));
5591 if (useFrameLatencyWaitableObject) {
5592 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5593 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5597 if (m_format != SDR)
5598 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5599 if (useFrameLatencyWaitableObject) {
5600 IDXGISwapChain2 *sc2 =
nullptr;
5601 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5602 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5603 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5606 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5611 hr = dcompVisual->SetContent(sc1);
5612 if (SUCCEEDED(hr)) {
5613 hr = dcompTarget->SetRoot(dcompVisual);
5615 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5616 qPrintable(QSystemError::windowsComString(hr)));
5619 qWarning(
"Failed to set content for Direct Composition visual: %s",
5620 qPrintable(QSystemError::windowsComString(hr)));
5624 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5627 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5628 qWarning(
"Device loss detected during swapchain creation");
5631 }
else if (FAILED(hr)) {
5632 qWarning(
"Failed to create D3D11 swapchain: %s"
5633 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5634 qPrintable(QSystemError::windowsComString(hr)),
5635 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5636 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5642 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5643 colorFormat, swapChainFlags);
5644 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5645 qWarning(
"Device loss detected in ResizeBuffers()");
5648 }
else if (FAILED(hr)) {
5649 qWarning(
"Failed to resize D3D11 swapchain: %s",
5650 qPrintable(QSystemError::windowsComString(hr)));
5669 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5671 qWarning(
"Failed to query swapchain backbuffer: %s",
5672 qPrintable(QSystemError::windowsComString(hr)));
5675 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5676 rtvDesc.Format = srgbAdjustedColorFormat;
5677 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5678 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5680 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5681 qPrintable(QSystemError::windowsComString(hr)));
5687 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5688 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5689 rtvDesc.Texture2DArray.ArraySize = 1;
5690 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5692 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5693 qPrintable(QSystemError::windowsComString(hr)));
5700 if (sampleDesc.Count > 1) {
5701 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5706 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5707 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5708 m_depthStencil->sampleCount(), m_sampleCount);
5710 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5711 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5712 m_depthStencil->setPixelSize(pixelSize);
5713 if (!m_depthStencil->create())
5714 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5715 pixelSize.width(), pixelSize.height());
5717 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5718 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5719 pixelSize.width(), pixelSize.height());
5726 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5728 rt.setRenderPassDescriptor(m_renderPassDesc);
5730 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5731 rtD->d.pixelSize = pixelSize;
5732 rtD->d.dpr =
float(
window->devicePixelRatio());
5733 rtD->d.sampleCount =
int(sampleDesc.Count);
5734 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5737 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5738 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5739 rtD->d.pixelSize = pixelSize;
5740 rtD->d.dpr =
float(
window->devicePixelRatio());
5741 rtD->d.sampleCount =
int(sampleDesc.Count);
5742 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
5745 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5746 timestamps.prepare(rhiD);
5750 QDxgiVSyncService::instance()->registerWindow(window);
5752 if (needsRegistration)
5753 rhiD->registerResource(
this);
5761 if (rtViews.dsv != currentRtViews.dsv) {
5762 rtViews.dsv = currentRtViews.dsv;
5766 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
5767 rtViews.rtv[i] = currentRtViews.rtv[i];
5769 rtViews.colorAttCount = currentRtViews.colorAttCount;
5771 ret |= rtViews.rtv[i] !=
nullptr;
5772 rtViews.rtv[i] =
nullptr;
5774 for (
int i = 0; i < count; i++) {
5775 ret |= uav[i] != uavs[i];
5779 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
void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
QRhiSwapChain * createSwapChain() override
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
bool isFeatureSupported(QRhi::Feature feature) const override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
bool isDeviceLost() const override
bool vsHasIndexBufferBound
void executeBufferHostWrites(QD3D11Buffer *bufD)
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
void dispatchIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset) override
QRhiGraphicsPipeline * createGraphicsPipeline() override
void drawIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) override
QRhiShaderResourceBindings * createShaderResourceBindings() override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QList< int > supportedSampleCounts() const override
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
void resetShaderResources(QD3D11CommandBuffer *cbD, QD3D11RenderTargetUavUpdateState *rtUavState)
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
bool isYUpInFramebuffer() const override
int resourceLimit(QRhi::ResourceLimit limit) const override
void beginExternal(QRhiCommandBuffer *cb) override
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void setPipelineCacheData(const QByteArray &data) override
void executeCommandBuffer(QD3D11CommandBuffer *cbD)
void debugMarkEnd(QRhiCommandBuffer *cb) override
void releaseCachedResources() override
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
bool importedDeviceAndContext
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
bool supportsAllowTearing
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
void endExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
void drawIndexedIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) override
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
QRhiShadingRateMap * createShadingRateMap() override
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
bool useLegacySwapchainModel
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
bool makeThreadLocalNativeContextCurrent() override
bool create(QRhi::Flags flags) override
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
static void applyDynamicOffsets(UINT *offsets, int batchIndex, const QRhiBatchedBindings< UINT > *originalBindings, const QRhiBatchedBindings< UINT > *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount)
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
#define SETUAVBATCH(stagePrefixL, stagePrefixU)
static QByteArray sourceHash(const QByteArray &source)
#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
static const int RBM_HULL
static uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
static 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)
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
bool update(const QD3D11RenderTargetData::Views ¤tRtViews, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
QD3D11GraphicsPipeline * lastUsedGraphicsPipeline
bool create() override
Creates the corresponding resource binding set.
~QD3D11ShaderResourceBindings()
void updateResources(UpdateFlags flags) override
QD3D11ComputePipeline * lastUsedComputePipeline
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
int sampleCount() const override
~QD3D11SwapChainRenderTarget()
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
float devicePixelRatio() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QSize pixelSize() const override
bool prepare(QRhiD3D11 *rhiD)
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
bool active[TIMESTAMP_PAIRS]
static const int TIMESTAMP_PAIRS
QRhiSwapChainHdrInfo hdrInfo() override
\variable QRhiSwapChainHdrInfo::limitsType
int lastFrameLatencyWaitSlot
QRhiRenderTarget * currentFrameRenderTarget() override
QD3D11SwapChain(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
QSize surfacePixelSize() override
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
static const int BUFFER_COUNT
bool isFormatSupported(Format f) override
QRhiCommandBuffer * currentFrameCommandBuffer() override
int currentTimestampPairIndex
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
QSize pixelSize() const override
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
float devicePixelRatio() const override
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
~QD3D11TextureRenderTarget()
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
ID3D11UnorderedAccessView * unorderedAccessViewForLevel(int level)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h