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;
481 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
488 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
489 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
494QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
496 LUID requestedLuid = {};
498 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
499 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
500 if (adapterLuid.LowPart || adapterLuid.HighPart)
501 requestedLuid = adapterLuid;
504 IDXGIFactory1 *dxgi = createDXGIFactory2();
508 QRhi::AdapterList list;
509 IDXGIAdapter1 *adapter;
510 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
511 DXGI_ADAPTER_DESC1 desc;
512 adapter->GetDesc1(&desc);
514 if (requestedLuid.LowPart || requestedLuid.HighPart) {
515 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
516 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
521 QD3D11Adapter *a =
new QD3D11Adapter;
522 a->luid = desc.AdapterLuid;
523 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
538 return { 1, 2, 4, 8 };
543 Q_UNUSED(sampleCount);
544 return { QSize(1, 1) };
549 DXGI_SAMPLE_DESC desc;
553 const int s = effectiveSampleCount(sampleCount);
555 desc.Count = UINT(s);
557 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
566 return new QD3D11SwapChain(
this);
569QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
571 return new QD3D11Buffer(
this, type, usage, size);
599 if (m.isIdentity()) {
601 m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
602 0.0f, 1.0f, 0.0f, 0.0f,
603 0.0f, 0.0f, 0.5f, 0.5f,
604 0.0f, 0.0f, 0.0f, 1.0f);
613 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
622 case QRhi::MultisampleTexture:
624 case QRhi::MultisampleRenderBuffer:
626 case QRhi::DebugMarkers:
627 return annotations !=
nullptr;
628 case QRhi::Timestamps:
630 case QRhi::Instancing:
632 case QRhi::CustomInstanceStepRate:
634 case QRhi::PrimitiveRestart:
636 case QRhi::NonDynamicUniformBuffers:
638 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
640 case QRhi::NPOTTextureRepeat:
642 case QRhi::RedOrAlpha8IsRed:
644 case QRhi::ElementIndexUint:
648 case QRhi::WideLines:
650 case QRhi::VertexShaderPointSize:
652 case QRhi::BaseVertex:
654 case QRhi::BaseInstance:
656 case QRhi::TriangleFanTopology:
658 case QRhi::ReadBackNonUniformBuffer:
660 case QRhi::ReadBackNonBaseMipLevel:
662 case QRhi::TexelFetch:
664 case QRhi::RenderToNonBaseMipLevel:
666 case QRhi::IntAttributes:
668 case QRhi::ScreenSpaceDerivatives:
670 case QRhi::ReadBackAnyTextureFormat:
672 case QRhi::PipelineCacheDataLoadSave:
674 case QRhi::ImageDataStride:
676 case QRhi::RenderBufferImport:
678 case QRhi::ThreeDimensionalTextures:
680 case QRhi::RenderTo3DTextureSlice:
682 case QRhi::TextureArrays:
684 case QRhi::Tessellation:
686 case QRhi::GeometryShader:
688 case QRhi::TextureArrayRange:
690 case QRhi::NonFillPolygonMode:
692 case QRhi::OneDimensionalTextures:
694 case QRhi::OneDimensionalTextureMipmaps:
696 case QRhi::HalfAttributes:
698 case QRhi::RenderToOneDimensionalTexture:
700 case QRhi::ThreeDimensionalTextureMipmaps:
702 case QRhi::MultiView:
704 case QRhi::TextureViewFormat:
706 case QRhi::ResolveDepthStencil:
708 case QRhi::VariableRateShading:
710 case QRhi::VariableRateShadingMap:
711 case QRhi::VariableRateShadingMapWithTexture:
713 case QRhi::PerRenderTargetBlending:
714 case QRhi::SampleVariables:
716 case QRhi::InstanceIndexIncludesBaseInstance:
718 case QRhi::DepthClamp:
720 case QRhi::DrawIndirect:
721 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
722 case QRhi::DrawIndirectMulti:
723 case QRhi::ShaderDrawParameters:
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::ShadingRateImageTileSize:
776 return &nativeHandlesStruct;
781 return driverInfoStruct;
787 result.totalPipelineCreationTime = totalPipelineCreationTime();
797void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
805 m_bytecodeCache.clear();
825 if (m_bytecodeCache.isEmpty())
829 memset(&header, 0,
sizeof(header));
830 header.rhiId = pipelineCacheRhiId();
831 header.arch = quint32(
sizeof(
void*));
832 header.count = m_bytecodeCache.count();
834 const size_t dataOffset =
sizeof(header);
836 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
838 QByteArray bytecode = it.value();
840 sizeof(quint32) + key.sourceHash.size()
841 +
sizeof(quint32) + key.target.size()
842 +
sizeof(quint32) + key.entryPoint.size()
844 +
sizeof(quint32) + bytecode.size();
847 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
848 char *p = buf.data() + dataOffset;
849 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
851 QByteArray bytecode = it.value();
853 quint32 i = key.sourceHash.size();
856 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
857 p += key.sourceHash.size();
859 i = key.target.size();
862 memcpy(p, key.target.constData(), key.target.size());
863 p += key.target.size();
865 i = key.entryPoint.size();
868 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
869 p += key.entryPoint.size();
871 quint32 f = key.compileFlags;
878 memcpy(p, bytecode.constData(), bytecode.size());
879 p += bytecode.size();
881 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
883 header.dataSize = quint32(dataSize);
884 memcpy(buf.data(), &header,
sizeof(header));
895 if (data.size() < qsizetype(headerSize)) {
896 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
899 const size_t dataOffset = headerSize;
901 memcpy(&header, data.constData(), headerSize);
903 const quint32 rhiId = pipelineCacheRhiId();
904 if (header.rhiId != rhiId) {
905 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
906 rhiId, header.rhiId);
909 const quint32 arch = quint32(
sizeof(
void*));
910 if (header.arch != arch) {
911 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
915 if (header.count == 0)
918 if (data.size() < qsizetype(dataOffset + header.dataSize)) {
919 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
923 m_bytecodeCache.clear();
925 const char *p = data.constData() + dataOffset;
926 for (quint32 i = 0; i < header.count; ++i) {
930 QByteArray sourceHash(len, Qt::Uninitialized);
931 memcpy(sourceHash.data(), p, len);
936 QByteArray target(len, Qt::Uninitialized);
937 memcpy(target.data(), p, len);
942 QByteArray entryPoint(len, Qt::Uninitialized);
943 memcpy(entryPoint.data(), p, len);
947 memcpy(&flags, p, 4);
952 QByteArray bytecode(len, Qt::Uninitialized);
953 memcpy(bytecode.data(), p, len);
957 cacheKey.sourceHash = sourceHash;
958 cacheKey.target = target;
959 cacheKey.entryPoint = entryPoint;
960 cacheKey.compileFlags = flags;
962 m_bytecodeCache.insert(cacheKey, bytecode);
965 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
968QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
969 int sampleCount, QRhiRenderBuffer::Flags flags,
970 QRhiTexture::Format backingFormatHint)
972 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
976 const QSize &pixelSize,
int depth,
int arraySize,
977 int sampleCount, QRhiTexture::Flags flags)
979 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
983 QRhiSampler::Filter mipmapMode,
984 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
986 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
990 QRhiTextureRenderTarget::Flags flags)
1002 return new QD3D11GraphicsPipeline(
this);
1007 return new QD3D11ComputePipeline(
this);
1012 return new QD3D11ShaderResourceBindings(
this);
1020 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1022 if (pipelineChanged) {
1023 cbD->currentGraphicsPipeline = ps;
1024 cbD->currentComputePipeline =
nullptr;
1025 cbD->currentPipelineGeneration = psD->generation;
1029 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1030 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1031 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1032 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1033 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1034 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1035 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1036 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1037 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1038 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1051 int dynamicOffsetCount,
1052 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1061 srb = gfxPsD->m_shaderResourceBindings;
1063 srb = compPsD->m_shaderResourceBindings;
1068 bool pipelineChanged =
false;
1077 bool srbUpdate =
false;
1078 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1079 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1082 case QRhiShaderResourceBinding::UniformBuffer:
1086 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1087 sanityCheckResourceOwnership(bufD);
1091 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1093 bd.ubuf.id = bufD->m_id;
1094 bd.ubuf.generation = bufD->generation;
1098 case QRhiShaderResourceBinding::SampledTexture:
1099 case QRhiShaderResourceBinding::Texture:
1100 case QRhiShaderResourceBinding::Sampler:
1102 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1103 if (bd.stex.count != data->count) {
1104 bd.stex.count = data->count;
1107 for (
int elem = 0; elem < data->count; ++elem) {
1113 Q_ASSERT(texD || samplerD);
1114 sanityCheckResourceOwnership(texD);
1115 sanityCheckResourceOwnership(samplerD);
1116 const quint64 texId = texD ? texD->m_id : 0;
1117 const uint texGen = texD ? texD->generation : 0;
1118 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1119 const uint samplerGen = samplerD ? samplerD->generation : 0;
1120 if (texGen != bd.stex.d[elem].texGeneration
1121 || texId != bd.stex.d[elem].texId
1122 || samplerGen != bd.stex.d[elem].samplerGeneration
1123 || samplerId != bd.stex.d[elem].samplerId)
1126 bd.stex.d[elem].texId = texId;
1127 bd.stex.d[elem].texGeneration = texGen;
1128 bd.stex.d[elem].samplerId = samplerId;
1129 bd.stex.d[elem].samplerGeneration = samplerGen;
1134 case QRhiShaderResourceBinding::ImageLoad:
1135 case QRhiShaderResourceBinding::ImageStore:
1136 case QRhiShaderResourceBinding::ImageLoadStore:
1139 sanityCheckResourceOwnership(texD);
1140 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1142 bd.simage.id = texD->m_id;
1143 bd.simage.generation = texD->generation;
1147 case QRhiShaderResourceBinding::BufferLoad:
1148 case QRhiShaderResourceBinding::BufferStore:
1149 case QRhiShaderResourceBinding::BufferLoadStore:
1152 sanityCheckResourceOwnership(bufD);
1153 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1155 bd.sbuf.id = bufD->m_id;
1156 bd.sbuf.generation = bufD->generation;
1166 if (srbUpdate || pipelineChanged) {
1168 memset(resBindMaps, 0,
sizeof(resBindMaps));
1170 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1171 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1172 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1173 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1174 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1176 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1178 updateShaderResourceBindings(srbD, resBindMaps);
1181 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1182 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1184 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1186 cbD->currentGraphicsSrb = srb;
1187 cbD->currentComputeSrb =
nullptr;
1189 cbD->currentGraphicsSrb =
nullptr;
1190 cbD->currentComputeSrb = srb;
1192 cbD->currentSrbGeneration = srbD->generation;
1199 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1200 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1203 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1204 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1205 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1206 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1207 const uint binding = uint(dynOfs.first);
1208 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1209 const quint32 offsetInConstants = dynOfs.second / 16;
1211 *p++ = offsetInConstants;
1214 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1222 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1223 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1228 bool needsBindVBuf =
false;
1229 for (
int i = 0; i < bindingCount; ++i) {
1230 const int inputSlot = startBinding + i;
1232 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1233 if (bufD->m_type == QRhiBuffer::Dynamic)
1236 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1237 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1239 needsBindVBuf =
true;
1240 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1241 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1245 if (needsBindVBuf) {
1248 cmd.args.bindVertexBuffers.startSlot = startBinding;
1250 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1254 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1256 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1257 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1258 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1260 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1261 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1262 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1268 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1269 if (ibufD->m_type == QRhiBuffer::Dynamic)
1272 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1273 : DXGI_FORMAT_R32_UINT;
1274 if (cbD->currentIndexBuffer != ibufD->buffer
1275 || cbD->currentIndexOffset != indexOffset
1276 || cbD->currentIndexFormat != dxgiFormat)
1278 cbD->currentIndexBuffer = ibufD->buffer;
1279 cbD->currentIndexOffset = indexOffset;
1280 cbD->currentIndexFormat = dxgiFormat;
1284 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1285 cmd.args.bindIndexBuffer.offset = indexOffset;
1286 cmd.args.bindIndexBuffer.format = dxgiFormat;
1295 Q_ASSERT(cbD->currentTarget);
1296 const QSize outputSize = cbD->currentTarget->pixelSize();
1300 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1305 cmd.args.viewport.x = x;
1306 cmd.args.viewport.y = y;
1307 cmd.args.viewport.w = w;
1308 cmd.args.viewport.h = h;
1309 cmd.args.viewport.d0 = viewport.minDepth();
1310 cmd.args.viewport.d1 = viewport.maxDepth();
1317 Q_ASSERT(cbD->currentTarget);
1318 const QSize outputSize = cbD->currentTarget->pixelSize();
1322 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1327 cmd.args.scissor.x = x;
1328 cmd.args.scissor.y = y;
1329 cmd.args.scissor.w = w;
1330 cmd.args.scissor.h = h;
1341 cmd.args.blendConstants.c[0] =
float(c.redF());
1342 cmd.args.blendConstants.c[1] =
float(c.greenF());
1343 cmd.args.blendConstants.c[2] =
float(c.blueF());
1344 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1355 cmd.args.stencilRef.ref = refValue;
1361 Q_UNUSED(coarsePixelSize);
1365 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1372 cmd.args.draw.vertexCount = vertexCount;
1373 cmd.args.draw.instanceCount = instanceCount;
1374 cmd.args.draw.firstVertex = firstVertex;
1375 cmd.args.draw.firstInstance = firstInstance;
1379 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1386 cmd.args.drawIndexed.indexCount = indexCount;
1387 cmd.args.drawIndexed.instanceCount = instanceCount;
1388 cmd.args.drawIndexed.firstIndex = firstIndex;
1389 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1390 cmd.args.drawIndexed.firstInstance = firstInstance;
1394 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1401 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1402 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1403 cmd.args.drawIndirect.drawCount = drawCount;
1404 cmd.args.drawIndirect.stride = stride;
1409 switch (rt->resourceType()) {
1410 case QRhiResource::SwapChainRenderTarget:
1411 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1412 case QRhiResource::TextureRenderTarget:
1413 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1421 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1428 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1429 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1430 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1431 cmd.args.drawIndexedIndirect.stride = stride;
1436 if (!debugMarkers || !annotations)
1442 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1447 if (!debugMarkers || !annotations)
1457 if (!debugMarkers || !annotations)
1463 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1482 Q_ASSERT(cbD->commands.isEmpty());
1484 if (cbD->currentTarget) {
1488 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1507 if (swapChainD->frameLatencyWaitableObject) {
1510 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1515 swapChainD->cb.resetState();
1517 swapChainD->rt.d.views.setFrom(1,
1518 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1519 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1524 double elapsedSec = 0;
1526 swapChainD->cb.lastGpuTime = elapsedSec;
1535 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1536 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1537 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1538 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1540 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1542 return QRhi::FrameOpSuccess;
1553 cmd.args.endFrame.tsQuery =
nullptr;
1554 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1559 if (swapChainD->sampleDesc.Count > 1) {
1560 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1561 swapChainD->msaaTex[currentFrameSlot], 0,
1562 swapChainD->colorFormat);
1569 if (recordTimestamps) {
1570 context->End(tsEnd);
1571 context->End(tsDisjoint);
1576 if (!flags.testFlag(QRhi::SkipPresent)) {
1577 UINT presentFlags = 0;
1578 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1579 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1580 if (!swapChainD->swapChain) {
1581 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1582 return QRhi::FrameOpError;
1584 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1585 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1586 qWarning(
"Device loss detected in Present()");
1588 return QRhi::FrameOpDeviceLost;
1589 }
else if (FAILED(hr)) {
1590 qWarning(
"Failed to present: %s",
1591 qPrintable(QSystemError::windowsComString(hr)));
1592 return QRhi::FrameOpError;
1595 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1596 dcompDevice->Commit();
1607 return QRhi::FrameOpSuccess;
1615 ofr.cbWrapper.resetState();
1616 *cb = &ofr.cbWrapper;
1618 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1619 D3D11_QUERY_DESC queryDesc = {};
1620 if (!ofr.tsDisjointQuery) {
1621 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1622 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1624 qWarning(
"Failed to create timestamp disjoint query: %s",
1625 qPrintable(QSystemError::windowsComString(hr)));
1626 return QRhi::FrameOpError;
1629 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1630 for (
int i = 0; i < 2; ++i) {
1631 if (!ofr.tsQueries[i]) {
1632 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1634 qWarning(
"Failed to create timestamp query: %s",
1635 qPrintable(QSystemError::windowsComString(hr)));
1636 return QRhi::FrameOpError;
1644 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1645 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1646 cmd.args.beginFrame.swapchainRtv =
nullptr;
1647 cmd.args.beginFrame.swapchainDsv =
nullptr;
1649 return QRhi::FrameOpSuccess;
1659 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1660 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1667 if (ofr.tsQueries[0]) {
1668 quint64 timestamps[2];
1669 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1673 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1674 }
while (hr == S_FALSE);
1677 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1678 }
while (hr == S_FALSE);
1681 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1682 }
while (hr == S_FALSE);
1685 if (!dj.Disjoint && dj.Frequency) {
1686 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1687 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1692 return QRhi::FrameOpSuccess;
1697 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1699 case QRhiTexture::RGBA8:
1700 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1701 case QRhiTexture::BGRA8:
1702 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1703 case QRhiTexture::R8:
1704 return DXGI_FORMAT_R8_UNORM;
1705 case QRhiTexture::R8SI:
1706 return DXGI_FORMAT_R8_SINT;
1707 case QRhiTexture::R8UI:
1708 return DXGI_FORMAT_R8_UINT;
1709 case QRhiTexture::RG8:
1710 return DXGI_FORMAT_R8G8_UNORM;
1711 case QRhiTexture::R16:
1712 return DXGI_FORMAT_R16_UNORM;
1713 case QRhiTexture::RG16:
1714 return DXGI_FORMAT_R16G16_UNORM;
1715 case QRhiTexture::RED_OR_ALPHA8:
1716 return DXGI_FORMAT_R8_UNORM;
1718 case QRhiTexture::RGBA16F:
1719 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1720 case QRhiTexture::RGBA32F:
1721 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1722 case QRhiTexture::R16F:
1723 return DXGI_FORMAT_R16_FLOAT;
1724 case QRhiTexture::R32F:
1725 return DXGI_FORMAT_R32_FLOAT;
1727 case QRhiTexture::RGB10A2:
1728 return DXGI_FORMAT_R10G10B10A2_UNORM;
1730 case QRhiTexture::R32SI:
1731 return DXGI_FORMAT_R32_SINT;
1732 case QRhiTexture::R32UI:
1733 return DXGI_FORMAT_R32_UINT;
1734 case QRhiTexture::RG32SI:
1735 return DXGI_FORMAT_R32G32_SINT;
1736 case QRhiTexture::RG32UI:
1737 return DXGI_FORMAT_R32G32_UINT;
1738 case QRhiTexture::RGBA32SI:
1739 return DXGI_FORMAT_R32G32B32A32_SINT;
1740 case QRhiTexture::RGBA32UI:
1741 return DXGI_FORMAT_R32G32B32A32_UINT;
1743 case QRhiTexture::D16:
1744 return DXGI_FORMAT_R16_TYPELESS;
1745 case QRhiTexture::D24:
1746 return DXGI_FORMAT_R24G8_TYPELESS;
1747 case QRhiTexture::D24S8:
1748 return DXGI_FORMAT_R24G8_TYPELESS;
1749 case QRhiTexture::D32F:
1750 return DXGI_FORMAT_R32_TYPELESS;
1751 case QRhiTexture::D32FS8:
1752 return DXGI_FORMAT_R32G8X24_TYPELESS;
1754 case QRhiTexture::BC1:
1755 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1756 case QRhiTexture::BC2:
1757 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1758 case QRhiTexture::BC3:
1759 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1760 case QRhiTexture::BC4:
1761 return DXGI_FORMAT_BC4_UNORM;
1762 case QRhiTexture::BC5:
1763 return DXGI_FORMAT_BC5_UNORM;
1764 case QRhiTexture::BC6H:
1765 return DXGI_FORMAT_BC6H_UF16;
1766 case QRhiTexture::BC7:
1767 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1769 case QRhiTexture::ETC2_RGB8:
1770 case QRhiTexture::ETC2_RGB8A1:
1771 case QRhiTexture::ETC2_RGBA8:
1772 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1773 return DXGI_FORMAT_R8G8B8A8_UNORM;
1775 case QRhiTexture::ASTC_4x4:
1776 case QRhiTexture::ASTC_5x4:
1777 case QRhiTexture::ASTC_5x5:
1778 case QRhiTexture::ASTC_6x5:
1779 case QRhiTexture::ASTC_6x6:
1780 case QRhiTexture::ASTC_8x5:
1781 case QRhiTexture::ASTC_8x6:
1782 case QRhiTexture::ASTC_8x8:
1783 case QRhiTexture::ASTC_10x5:
1784 case QRhiTexture::ASTC_10x6:
1785 case QRhiTexture::ASTC_10x8:
1786 case QRhiTexture::ASTC_10x10:
1787 case QRhiTexture::ASTC_12x10:
1788 case QRhiTexture::ASTC_12x12:
1789 qWarning(
"QRhiD3D11 does not support ASTC textures");
1790 return DXGI_FORMAT_R8G8B8A8_UNORM;
1794 return DXGI_FORMAT_R8G8B8A8_UNORM;
1801 case DXGI_FORMAT_R8G8B8A8_UNORM:
1802 return QRhiTexture::RGBA8;
1803 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1805 (*flags) |= QRhiTexture::sRGB;
1806 return QRhiTexture::RGBA8;
1807 case DXGI_FORMAT_B8G8R8A8_UNORM:
1808 return QRhiTexture::BGRA8;
1809 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1811 (*flags) |= QRhiTexture::sRGB;
1812 return QRhiTexture::BGRA8;
1813 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1814 return QRhiTexture::RGBA16F;
1815 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1816 return QRhiTexture::RGBA32F;
1817 case DXGI_FORMAT_R10G10B10A2_UNORM:
1818 return QRhiTexture::RGB10A2;
1820 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1823 return QRhiTexture::UnknownFormat;
1829 case QRhiTexture::Format::D16:
1830 case QRhiTexture::Format::D24:
1831 case QRhiTexture::Format::D24S8:
1832 case QRhiTexture::Format::D32F:
1833 case QRhiTexture::Format::D32FS8:
1846 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1848 ofr.cbWrapper.resetCommands();
1859 return QRhi::FrameOpSuccess;
1863 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1865 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1866 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1868 box.front = is3D ? UINT(layer) : 0u;
1870 box.back = box.front + 1;
1873 cmd.args.updateSubRes.dst = texD->textureResource();
1874 cmd.args.updateSubRes.dstSubRes = subres;
1876 const QPoint dp = subresDesc.destinationTopLeft();
1877 if (!subresDesc.image().isNull()) {
1878 QImage img = subresDesc.image();
1879 QSize size = img.size();
1880 int bpl = img.bytesPerLine();
1881 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1882 const QPoint sp = subresDesc.sourceTopLeft();
1883 if (!subresDesc.sourceSize().isEmpty())
1884 size = subresDesc.sourceSize();
1885 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1886 if (img.depth() == 32) {
1887 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1888 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1890 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1891 bpl = img.bytesPerLine();
1892 cmd.args.updateSubRes.src = cbD->retainImage(img);
1895 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1896 cmd.args.updateSubRes.src = cbD->retainImage(img);
1898 box.left = UINT(dp.x());
1899 box.top = UINT(dp.y());
1900 box.right = UINT(dp.x() + size.width());
1901 box.bottom = UINT(dp.y() + size.height());
1902 cmd.args.updateSubRes.hasDstBox =
true;
1903 cmd.args.updateSubRes.dstBox = box;
1904 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1905 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1906 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1907 : subresDesc.sourceSize();
1910 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1914 box.left = UINT(aligned(dp.x(), blockDim.width()));
1915 box.top = UINT(aligned(dp.y(), blockDim.height()));
1916 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1917 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1918 cmd.args.updateSubRes.hasDstBox =
true;
1919 cmd.args.updateSubRes.dstBox = box;
1920 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1921 cmd.args.updateSubRes.srcRowPitch = bpl;
1922 }
else if (!subresDesc.data().isEmpty()) {
1923 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1924 : subresDesc.sourceSize();
1926 if (subresDesc.dataStride())
1927 bpl = subresDesc.dataStride();
1929 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1930 box.left = UINT(dp.x());
1931 box.top = UINT(dp.y());
1932 box.right = UINT(dp.x() + size.width());
1933 box.bottom = UINT(dp.y() + size.height());
1934 cmd.args.updateSubRes.hasDstBox =
true;
1935 cmd.args.updateSubRes.dstBox = box;
1936 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1937 cmd.args.updateSubRes.srcRowPitch = bpl;
1939 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1940 cbD->commands.unget();
1953 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1958 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1959 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1962 cmd.args.updateSubRes.dst = bufD->buffer;
1963 cmd.args.updateSubRes.dstSubRes = 0;
1964 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1965 cmd.args.updateSubRes.srcRowPitch = 0;
1970 box.left = u.offset;
1971 box.top = box.front = 0;
1972 box.back = box.bottom = 1;
1973 box.right = u.offset + u
.data.size();
1974 cmd.args.updateSubRes.hasDstBox =
true;
1975 cmd.args.updateSubRes.dstBox = box;
1978 if (bufD->m_type == QRhiBuffer::Dynamic) {
1979 u.result->data.resize(u.readSize);
1980 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1981 if (u.result->completed)
1982 u.result->completed();
1985 readback.result = u.result;
1986 readback.byteSize = u.readSize;
1988 D3D11_BUFFER_DESC desc = {};
1989 desc.ByteWidth = readback.byteSize;
1990 desc.Usage = D3D11_USAGE_STAGING;
1991 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1992 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1994 qWarning(
"Failed to create buffer: %s",
1995 qPrintable(QSystemError::windowsComString(hr)));
2001 cmd.args.copySubRes.dst = readback.stagingBuf;
2002 cmd.args.copySubRes.dstSubRes = 0;
2003 cmd.args.copySubRes.dstX = 0;
2004 cmd.args.copySubRes.dstY = 0;
2005 cmd.args.copySubRes.dstZ = 0;
2006 cmd.args.copySubRes.src = bufD->buffer;
2007 cmd.args.copySubRes.srcSubRes = 0;
2008 cmd.args.copySubRes.hasSrcBox =
true;
2010 box.left = u.offset;
2011 box.top = box.front = 0;
2012 box.back = box.bottom = 1;
2013 box.right = u.offset + u.readSize;
2014 cmd.args.copySubRes.srcBox = box;
2016 activeBufferReadbacks.append(readback);
2024 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2025 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2026 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2027 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2034 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2035 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2036 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2037 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2038 const QPoint dp = u.desc.destinationTopLeft();
2039 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2040 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2041 const QPoint sp = u.desc.sourceTopLeft();
2043 srcBox.left = UINT(sp.x());
2044 srcBox.top = UINT(sp.y());
2045 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2047 srcBox.right = srcBox.left + UINT(copySize.width());
2048 srcBox.bottom = srcBox.top + UINT(copySize.height());
2049 srcBox.back = srcBox.front + 1;
2052 cmd.args.copySubRes.dst = dstD->textureResource();
2053 cmd.args.copySubRes.dstSubRes = dstSubRes;
2054 cmd.args.copySubRes.dstX = UINT(dp.x());
2055 cmd.args.copySubRes.dstY = UINT(dp.y());
2056 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2057 cmd.args.copySubRes.src = srcD->textureResource();
2058 cmd.args.copySubRes.srcSubRes = srcSubRes;
2059 cmd.args.copySubRes.hasSrcBox =
true;
2060 cmd.args.copySubRes.srcBox = srcBox;
2063 readback.desc = u.rb;
2064 readback.result = u.result;
2066 ID3D11Resource *src;
2067 DXGI_FORMAT dxgiFormat;
2069 QRhiTexture::Format format;
2076 if (texD->sampleDesc.Count > 1) {
2077 qWarning(
"Multisample texture cannot be read back");
2080 src = texD->textureResource();
2081 dxgiFormat = texD->dxgiFormat;
2082 if (u.rb.rect().isValid())
2085 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2086 format = texD->m_format;
2087 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2088 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2092 if (swapChainD->sampleDesc.Count > 1) {
2097 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2098 rcmd.args.resolveSubRes.dstSubRes = 0;
2100 rcmd.args.resolveSubRes.srcSubRes = 0;
2101 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2103 src = swapChainD->backBufferTex;
2104 dxgiFormat = swapChainD->colorFormat;
2105 if (u.rb.rect().isValid())
2108 rect = QRect({0, 0}, swapChainD->pixelSize);
2109 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2110 if (format == QRhiTexture::UnknownFormat)
2113 quint32 byteSize = 0;
2115 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2117 D3D11_TEXTURE2D_DESC desc = {};
2118 desc.Width = UINT(rect.width());
2119 desc.Height = UINT(rect.height());
2122 desc.Format = dxgiFormat;
2123 desc.SampleDesc.Count = 1;
2124 desc.Usage = D3D11_USAGE_STAGING;
2125 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2126 ID3D11Texture2D *stagingTex;
2127 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2129 qWarning(
"Failed to create readback staging texture: %s",
2130 qPrintable(QSystemError::windowsComString(hr)));
2136 cmd.args.copySubRes.dst = stagingTex;
2137 cmd.args.copySubRes.dstSubRes = 0;
2138 cmd.args.copySubRes.dstX = 0;
2139 cmd.args.copySubRes.dstY = 0;
2140 cmd.args.copySubRes.dstZ = 0;
2141 cmd.args.copySubRes.src = src;
2142 cmd.args.copySubRes.srcSubRes = subres;
2144 D3D11_BOX srcBox = {};
2145 srcBox.left = UINT(rect.left());
2146 srcBox.top = UINT(rect.top());
2147 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2149 srcBox.right = srcBox.left + desc.Width;
2150 srcBox.bottom = srcBox.top + desc.Height;
2151 srcBox.back = srcBox.front + 1;
2152 cmd.args.copySubRes.hasSrcBox =
true;
2153 cmd.args.copySubRes.srcBox = srcBox;
2155 readback.stagingTex = stagingTex;
2156 readback.byteSize = byteSize;
2158 readback.pixelSize = rect.size();
2159 readback.format = format;
2161 activeTextureReadbacks.append(readback);
2163 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2166 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2175 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2177 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2179 readback.result->format = readback.format;
2180 readback.result->pixelSize = readback.pixelSize;
2182 D3D11_MAPPED_SUBRESOURCE mp;
2183 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2184 if (SUCCEEDED(hr)) {
2185 readback.result->data.resize(
int(readback.byteSize));
2188 char *dst = readback.result->data.data();
2189 char *src =
static_cast<
char *>(mp.pData);
2190 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2191 memcpy(dst, src, readback.bpl);
2192 dst += readback.bpl;
2195 context->Unmap(readback.stagingTex, 0);
2197 qWarning(
"Failed to map readback staging texture: %s",
2198 qPrintable(QSystemError::windowsComString(hr)));
2201 readback.stagingTex->Release();
2203 if (readback.result->completed)
2204 completedCallbacks.append(readback.result->completed);
2206 activeTextureReadbacks.removeLast();
2209 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2212 D3D11_MAPPED_SUBRESOURCE mp;
2213 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2214 if (SUCCEEDED(hr)) {
2215 readback.result->data.resize(
int(readback.byteSize));
2216 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2217 context->Unmap(readback.stagingBuf, 0);
2219 qWarning(
"Failed to map readback staging texture: %s",
2220 qPrintable(QSystemError::windowsComString(hr)));
2223 readback.stagingBuf->Release();
2225 if (readback.result->completed)
2226 completedCallbacks.append(readback.result->completed);
2228 activeBufferReadbacks.removeLast();
2231 for (
auto f : completedCallbacks)
2237 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2243 QRhiRenderTarget *rt,
2244 const QColor &colorClearValue,
2245 const QRhiDepthStencilClearValue &depthStencilClearValue,
2246 QRhiResourceUpdateBatch *resourceUpdates,
2252 if (resourceUpdates)
2255 bool wantsColorClear =
true;
2256 bool wantsDsClear =
true;
2258 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2260 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2261 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2262 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2270 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2274 clearCmd.args.clear.rtViews = rtD->views;
2275 clearCmd.args.clear.mask = 0;
2276 if (rtD->views.colorAttCount && wantsColorClear)
2278 if (rtD->views.dsv && wantsDsClear)
2281 clearCmd.args.clear.c[0] = colorClearValue.redF();
2282 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2283 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2284 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2285 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2286 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2289 cbD->currentTarget = rt;
2299 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2301 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2304 const QRhiColorAttachment &colorAtt(*it);
2305 if (!colorAtt.resolveTexture())
2311 Q_ASSERT(srcTexD || srcRbD);
2314 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2315 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2316 UINT(colorAtt.resolveLayer()),
2317 dstTexD->mipLevelCount);
2319 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2320 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2321 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2322 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2323 cbD->commands.unget();
2326 if (srcTexD->sampleDesc.Count <= 1) {
2327 qWarning(
"Cannot resolve a non-multisample texture");
2328 cbD->commands.unget();
2331 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2332 qWarning(
"Resolve source and destination sizes do not match");
2333 cbD->commands.unget();
2337 cmd.args.resolveSubRes.src = srcRbD->tex;
2338 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2339 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2340 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2341 cbD->commands.unget();
2344 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2345 qWarning(
"Resolve source and destination sizes do not match");
2346 cbD->commands.unget();
2350 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2351 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2353 if (rtTex->m_desc.depthResolveTexture())
2354 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2358 cbD->currentTarget =
nullptr;
2360 if (resourceUpdates)
2365 QRhiResourceUpdateBatch *resourceUpdates,
2371 if (resourceUpdates)
2379 fbCmd.args.setRenderTarget.rtViews.reset();
2396 if (resourceUpdates)
2405 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2407 if (pipelineChanged) {
2408 cbD->currentGraphicsPipeline =
nullptr;
2409 cbD->currentComputePipeline = psD;
2410 cbD->currentPipelineGeneration = psD->generation;
2414 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2425 cmd.args.dispatch.x = UINT(x);
2426 cmd.args.dispatch.y = UINT(y);
2427 cmd.args.dispatch.z = UINT(z);
2432 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2434 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2435 if (!map || map->isEmpty())
2436 return { binding, binding };
2438 auto it = map->constFind(binding);
2439 if (it != map->cend())
2449 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2451 srbD->resourceBatches.clear();
2457 ID3D11Buffer *buffer;
2458 uint offsetInConstants;
2459 uint sizeInConstants;
2463 ID3D11ShaderResourceView *srv;
2467 ID3D11SamplerState *sampler;
2471 ID3D11UnorderedAccessView *uav;
2473 QVarLengthArray<Buffer, 8> buffers;
2474 QVarLengthArray<Texture, 8> textures;
2475 QVarLengthArray<Sampler, 8> samplers;
2476 QVarLengthArray<Uav, 8> uavs;
2479 for (
const Buffer &buf : buffers) {
2480 batches.ubufs.feed(buf.breg, buf.buffer);
2481 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2482 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2483 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2489 for (
const Texture &t : textures)
2490 batches.shaderresources.feed(t.treg, t.srv);
2491 for (
const Sampler &s : samplers)
2492 batches.samplers.feed(s.sreg, s.sampler);
2497 for (
const Stage::Uav &u : uavs)
2498 batches.uavs.feed(u.ureg, u.uav);
2503 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2504 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2507 case QRhiShaderResourceBinding::UniformBuffer:
2510 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2511 bd.ubuf.id = bufD->m_id;
2512 bd.ubuf.generation = bufD->generation;
2519 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2523 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2524 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2525 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2526 if (nativeBinding.first >= 0)
2527 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2529 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2530 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2531 if (nativeBinding.first >= 0)
2532 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2534 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2535 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2536 if (nativeBinding.first >= 0)
2537 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2539 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2540 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2541 if (nativeBinding.first >= 0)
2542 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2544 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2545 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2546 if (nativeBinding.first >= 0)
2547 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2549 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2550 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2551 if (nativeBinding.first >= 0)
2552 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2556 case QRhiShaderResourceBinding::SampledTexture:
2557 case QRhiShaderResourceBinding::Texture:
2558 case QRhiShaderResourceBinding::Sampler:
2560 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2561 bd.stex.count = data->count;
2562 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2563 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2564 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2565 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2566 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2567 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2571 for (
int elem = 0; elem < data->count; ++elem) {
2574 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2575 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2576 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2577 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2582 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2583 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2584 : (samplerD ? nativeBindingVert.first : -1);
2585 if (nativeBindingVert.first >= 0 && texD)
2586 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2587 if (samplerBinding >= 0)
2588 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2590 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2591 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2592 : (samplerD ? nativeBindingHull.first : -1);
2593 if (nativeBindingHull.first >= 0 && texD)
2594 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2595 if (samplerBinding >= 0)
2596 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2598 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2599 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2600 : (samplerD ? nativeBindingDomain.first : -1);
2601 if (nativeBindingDomain.first >= 0 && texD)
2602 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2603 if (samplerBinding >= 0)
2604 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2606 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2607 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2608 : (samplerD ? nativeBindingGeom.first : -1);
2609 if (nativeBindingGeom.first >= 0 && texD)
2610 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2611 if (samplerBinding >= 0)
2612 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2614 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2615 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2616 : (samplerD ? nativeBindingFrag.first : -1);
2617 if (nativeBindingFrag.first >= 0 && texD)
2618 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2619 if (samplerBinding >= 0)
2620 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2622 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2623 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2624 : (samplerD ? nativeBindingComp.first : -1);
2625 if (nativeBindingComp.first >= 0 && texD)
2626 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2627 if (samplerBinding >= 0)
2628 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2633 case QRhiShaderResourceBinding::ImageLoad:
2634 case QRhiShaderResourceBinding::ImageStore:
2635 case QRhiShaderResourceBinding::ImageLoadStore:
2638 bd.simage.id = texD->m_id;
2639 bd.simage.generation = texD->generation;
2640 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2641 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2642 if (nativeBinding.first >= 0) {
2643 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2645 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2647 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2648 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2649 if (nativeBinding.first >= 0) {
2650 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2652 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2655 qWarning(
"Unordered access only supported at fragment/compute stage");
2659 case QRhiShaderResourceBinding::BufferLoad:
2660 case QRhiShaderResourceBinding::BufferStore:
2661 case QRhiShaderResourceBinding::BufferLoadStore:
2664 bd.sbuf.id = bufD->m_id;
2665 bd.sbuf.generation = bufD->generation;
2666 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2667 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2668 if (nativeBinding.first >= 0) {
2669 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2671 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2674 qWarning(
"Unordered access only supported at compute stage");
2689 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2690 return a.breg < b.breg;
2692 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2693 return a.treg < b.treg;
2695 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2696 return a.sreg < b.sreg;
2698 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2699 return a.ureg < b.ureg;
2703 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2704 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2705 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2706 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2707 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2708 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2710 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2711 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2712 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2713 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2714 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2715 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2717 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2718 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2726 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2728 D3D11_MAPPED_SUBRESOURCE mp;
2729 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2730 if (SUCCEEDED(hr)) {
2731 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2732 context->Unmap(bufD->buffer, 0);
2734 qWarning(
"Failed to map buffer: %s",
2735 qPrintable(QSystemError::windowsComString(hr)));
2741 const QRhiBatchedBindings<UINT> *originalBindings,
2742 const QRhiBatchedBindings<UINT> *staticOffsets,
2743 const uint *dynOfsPairs,
int dynOfsPairCount)
2745 const int count = staticOffsets->batches[batchIndex].resources.count();
2748 for (
int b = 0; b < count; ++b) {
2749 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2750 for (
int di = 0; di < dynOfsPairCount; ++di) {
2751 const uint binding = dynOfsPairs[2 * di];
2754 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2755 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2756 offsets[b] = offsetInConstants;
2765 if (startSlot + countSlots > maxSlots) {
2766 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2767 resType, countSlots, startSlot, maxSlots);
2768 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2773#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2774 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2775 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2776 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2777 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2778 batches.ubufs.batches[i].resources.count(),
2779 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2780 #stagePrefixU " cbuf");
2782 if (!dynOfsPairCount) {
2783 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2785 batches.ubufs.batches[i].resources.constData(),
2786 batches.ubufoffsets.batches[i].resources.constData(),
2787 batches.ubufsizes.batches[i].resources.constData());
2789 applyDynamicOffsets(offsets, i,
2790 &batches.ubuforigbindings, &batches.ubufoffsets,
2791 dynOfsPairs, dynOfsPairCount);
2792 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2794 batches.ubufs.batches[i].resources.constData(),
2796 batches.ubufsizes.batches[i].resources.constData());
2802#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2803 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2804 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2805 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2806 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2808 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2810 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2811 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2812 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2814 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2815 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2816 int(batch.startBinding + count) - 1
);
2821#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2822 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2823 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2824 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2827 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2829 batch.resources.constData(),
2831 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2832 int(batch.startBinding + count) - 1
);
2839 const uint *dynOfsPairs,
int dynOfsPairCount,
2840 bool offsetOnlyChange,
2852 if (!offsetOnlyChange) {
2862 if (allResourceBatches.fsUavBatches.present) {
2863 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2864 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2866 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2868 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
2869 context->OMSetRenderTargetsAndUnorderedAccessViews(
2870 UINT(rtUavState->rtViews.colorAttCount),
2871 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
2872 rtUavState->rtViews.dsv,
2873 UINT(rtUavState->rtViews.colorAttCount),
2875 batch.resources.constData(),
2878 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2879 int(batch.startBinding + count) - 1);
2892 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2898 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2899 for (
int i = 0; i < count; ++i)
2900 nullbufs[i] =
nullptr;
2901 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2902 for (
int i = 0; i < count; ++i)
2904 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2905 for (
int i = 0; i < count; ++i)
2907 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2917 if (nullsrvCount > 0) {
2918 QVarLengthArray<ID3D11ShaderResourceView *,
2919 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2920 for (
int i = 0; i < nullsrvs.count(); ++i)
2921 nullsrvs[i] =
nullptr;
2923 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2927 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2931 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2935 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2939 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2943 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2949 rtUavState->update(cbD->currentRenderTargetViews);
2950 context->OMSetRenderTargetsAndUnorderedAccessViews(
2951 UINT(cbD->currentRenderTargetViews.colorAttCount),
2952 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
2953 cbD->currentRenderTargetViews.dsv,
2954 0, 0,
nullptr,
nullptr);
2959 QVarLengthArray<ID3D11UnorderedAccessView *,
2960 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2961 for (
int i = 0; i < nulluavCount; ++i)
2962 nulluavs[i] =
nullptr;
2963 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2968#define SETSHADER(StageL, StageU)
2969 if (cmd.args.bindGraphicsPipeline.StageL) {
2970 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
2971 currentShaderMask |= StageU##MaskBit;
2972 } else if (currentShaderMask & StageU##MaskBit) {
2973 context->StageU##SetShader(nullptr, nullptr, 0
);
2974 currentShaderMask &= ~StageU##MaskBit;
2979 quint32 stencilRef = 0;
2980 float blendConstants[] = { 1, 1, 1, 1 };
2981 enum ActiveShaderMask {
2988 int currentShaderMask = 0xFF;
2994 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2997 case QD3D11CommandBuffer::Command::BeginFrame:
2998 if (cmd.args.beginFrame.tsDisjointQuery)
2999 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3000 if (cmd.args.beginFrame.tsQuery) {
3001 if (cmd.args.beginFrame.swapchainRtv) {
3006 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3007 rtUavState.update(cbD->currentRenderTargetViews);
3008 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3010 context->End(cmd.args.beginFrame.tsQuery);
3013 case QD3D11CommandBuffer::Command::EndFrame:
3014 if (cmd.args.endFrame.tsQuery)
3015 context->End(cmd.args.endFrame.tsQuery);
3016 if (cmd.args.endFrame.tsDisjointQuery)
3017 context->End(cmd.args.endFrame.tsDisjointQuery);
3024 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3025 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3026 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3027 context->OMSetRenderTargets(colorAttCount,
3028 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3029 cmd.args.setRenderTarget.rtViews.dsv);
3036 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3037 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3040 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3041 ds |= D3D11_CLEAR_DEPTH;
3042 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3043 ds |= D3D11_CLEAR_STENCIL;
3044 if (ds && cmd.args.clear.rtViews.dsv)
3045 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3051 v.TopLeftX = cmd.args.viewport.x;
3052 v.TopLeftY = cmd.args.viewport.y;
3053 v.Width = cmd.args.viewport.w;
3054 v.Height = cmd.args.viewport.h;
3055 v.MinDepth = cmd.args.viewport.d0;
3056 v.MaxDepth = cmd.args.viewport.d1;
3057 context->RSSetViewports(1, &v);
3063 r.left = cmd.args.scissor.x;
3064 r.top = cmd.args.scissor.y;
3066 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3067 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3068 context->RSSetScissorRects(1, &r);
3074 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3075 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3076 UINT(cmd.args.bindVertexBuffers.slotCount),
3077 cmd.args.bindVertexBuffers.buffers,
3078 cmd.args.bindVertexBuffers.strides,
3079 cmd.args.bindVertexBuffers.offsets);
3083 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3084 cmd.args.bindIndexBuffer.format,
3085 cmd.args.bindIndexBuffer.offset);
3094 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3095 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3096 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3097 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3098 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3101 case QD3D11CommandBuffer::Command::BindShaderResources:
3102 bindShaderResources(cbD,
3103 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3104 cmd.args.bindShaderResources.dynamicOffsetPairs,
3105 cmd.args.bindShaderResources.dynamicOffsetCount,
3106 cmd.args.bindShaderResources.offsetOnlyChange,
3110 stencilRef = cmd.args.stencilRef.ref;
3111 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3114 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3115 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3117 case QD3D11CommandBuffer::Command::Draw:
3118 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3119 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3121 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3122 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3124 case QD3D11CommandBuffer::Command::DrawIndexed:
3125 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3126 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3127 cmd.args.drawIndexed.vertexOffset);
3129 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3130 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3131 cmd.args.drawIndexed.firstInstance);
3135 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3136 const UINT stride = cmd.args.drawIndirect.stride;
3137 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3138 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3139 alignedByteOffsetForArgs += stride;
3145 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3146 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3147 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3148 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3149 alignedByteOffsetForArgs += stride;
3153 case QD3D11CommandBuffer::Command::UpdateSubRes:
3154 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3155 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3156 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3158 case QD3D11CommandBuffer::Command::CopySubRes:
3159 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3160 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3161 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3162 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3164 case QD3D11CommandBuffer::Command::ResolveSubRes:
3165 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3166 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3167 cmd.args.resolveSubRes.format);
3169 case QD3D11CommandBuffer::Command::GenMip:
3170 context->GenerateMips(cmd.args.genMip.srv);
3172 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3173 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3175 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3176 annotations->EndEvent();
3178 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3179 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3181 case QD3D11CommandBuffer::Command::BindComputePipeline:
3182 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3184 case QD3D11CommandBuffer::Command::Dispatch:
3185 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3214 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3215 it.value()->Release();
3220 rhiD->unregisterResource(
this);
3226 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3227 u |= D3D11_BIND_VERTEX_BUFFER;
3228 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3229 u |= D3D11_BIND_INDEX_BUFFER;
3230 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3231 u |= D3D11_BIND_CONSTANT_BUFFER;
3232 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3233 u |= D3D11_BIND_UNORDERED_ACCESS;
3242 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3243 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3247 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3248 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3252 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3253 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3257 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3258 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3260 D3D11_BUFFER_DESC desc = {};
3261 desc.ByteWidth = roundedSize;
3262 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3263 desc.BindFlags = toD3DBufferUsage(m_usage);
3264 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3265 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3266 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3267 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3270 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3272 qWarning(
"Failed to create buffer: %s",
3273 qPrintable(QSystemError::windowsComString(hr)));
3277 if (m_type == Dynamic) {
3278 dynBuf =
new char[nonZeroSize];
3282 if (!m_objectName.isEmpty())
3283 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3286 rhiD->registerResource(
this);
3292 if (m_type == Dynamic) {
3296 return { { &buffer }, 1 };
3307 Q_ASSERT(m_type == Dynamic);
3308 D3D11_MAPPED_SUBRESOURCE mp;
3310 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3312 qWarning(
"Failed to map buffer: %s",
3313 qPrintable(QSystemError::windowsComString(hr)));
3316 return static_cast<
char *>(mp.pData);
3322 rhiD->context->Unmap(buffer, 0);
3327 auto it = uavs.find(offset);
3328 if (it != uavs.end())
3332 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3333 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3334 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3335 desc.Buffer.FirstElement = offset / 4u;
3336 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3337 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3340 ID3D11UnorderedAccessView *uav =
nullptr;
3341 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3343 qWarning(
"Failed to create UAV: %s",
3344 qPrintable(QSystemError::windowsComString(hr)));
3353 int sampleCount, QRhiRenderBuffer::Flags flags,
3354 QRhiTexture::Format backingFormatHint)
3384 rhiD->unregisterResource(
this);
3392 if (m_pixelSize.isEmpty())
3396 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3398 D3D11_TEXTURE2D_DESC desc = {};
3399 desc.Width = UINT(m_pixelSize.width());
3400 desc.Height = UINT(m_pixelSize.height());
3403 desc.SampleDesc = sampleDesc;
3404 desc.Usage = D3D11_USAGE_DEFAULT;
3406 if (m_type == Color) {
3407 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3408 : toD3DTextureFormat(m_backingFormatHint, {});
3409 desc.Format = dxgiFormat;
3410 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3411 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3413 qWarning(
"Failed to create color renderbuffer: %s",
3414 qPrintable(QSystemError::windowsComString(hr)));
3417 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3418 rtvDesc.Format = dxgiFormat;
3419 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3420 : D3D11_RTV_DIMENSION_TEXTURE2D;
3421 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3423 qWarning(
"Failed to create rtv: %s",
3424 qPrintable(QSystemError::windowsComString(hr)));
3427 }
else if (m_type == DepthStencil) {
3428 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3429 desc.Format = dxgiFormat;
3430 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3431 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3433 qWarning(
"Failed to create depth-stencil buffer: %s",
3434 qPrintable(QSystemError::windowsComString(hr)));
3437 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3438 dsvDesc.Format = dxgiFormat;
3439 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3440 : D3D11_DSV_DIMENSION_TEXTURE2D;
3441 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3443 qWarning(
"Failed to create dsv: %s",
3444 qPrintable(QSystemError::windowsComString(hr)));
3451 if (!m_objectName.isEmpty())
3452 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3455 rhiD->registerResource(
this);
3461 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3462 return m_backingFormatHint;
3464 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3468 int arraySize,
int sampleCount, Flags flags)
3471 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3472 perLevelViews[i] =
nullptr;
3482 if (!tex && !tex3D && !tex1D)
3490 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3491 if (perLevelViews[i]) {
3492 perLevelViews[i]->Release();
3493 perLevelViews[i] =
nullptr;
3512 rhiD->unregisterResource(
this);
3518 case QRhiTexture::Format::D16:
3519 return DXGI_FORMAT_R16_FLOAT;
3520 case QRhiTexture::Format::D24:
3521 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3522 case QRhiTexture::Format::D24S8:
3523 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3524 case QRhiTexture::Format::D32F:
3525 return DXGI_FORMAT_R32_FLOAT;
3526 case QRhiTexture::Format::D32FS8:
3527 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3530 return DXGI_FORMAT_R32_FLOAT;
3537 case QRhiTexture::Format::D16:
3538 return DXGI_FORMAT_D16_UNORM;
3539 case QRhiTexture::Format::D24:
3540 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3541 case QRhiTexture::Format::D24S8:
3542 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3543 case QRhiTexture::Format::D32F:
3544 return DXGI_FORMAT_D32_FLOAT;
3545 case QRhiTexture::Format::D32FS8:
3546 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3549 return DXGI_FORMAT_D32_FLOAT;
3555 if (tex || tex3D || tex1D)
3559 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3562 const bool isDepth = isDepthTextureFormat(m_format);
3563 const bool isCube = m_flags.testFlag(CubeMap);
3564 const bool is3D = m_flags.testFlag(ThreeDimensional);
3565 const bool isArray = m_flags.testFlag(TextureArray);
3566 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3567 const bool is1D = m_flags.testFlag(OneDimensional);
3569 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3570 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3572 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3573 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3574 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3575 if (sampleDesc.Count > 1) {
3577 qWarning(
"Cubemap texture cannot be multisample");
3581 qWarning(
"3D texture cannot be multisample");
3585 qWarning(
"Multisample texture cannot have mipmaps");
3589 if (isDepth && hasMipMaps) {
3590 qWarning(
"Depth texture cannot have mipmaps");
3593 if (isCube && is3D) {
3594 qWarning(
"Texture cannot be both cube and 3D");
3597 if (isArray && is3D) {
3598 qWarning(
"Texture cannot be both array and 3D");
3601 if (isCube && is1D) {
3602 qWarning(
"Texture cannot be both cube and 1D");
3606 qWarning(
"Texture cannot be both 1D and 3D");
3609 if (m_depth > 1 && !is3D) {
3610 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3613 if (m_arraySize > 0 && !isArray) {
3614 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3617 if (m_arraySize < 1 && isArray) {
3618 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3623 *adjustedSize = size;
3631 const bool isDepth = isDepthTextureFormat(m_format);
3632 const bool isCube = m_flags.testFlag(CubeMap);
3633 const bool is3D = m_flags.testFlag(ThreeDimensional);
3634 const bool isArray = m_flags.testFlag(TextureArray);
3635 const bool is1D = m_flags.testFlag(OneDimensional);
3637 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3638 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3640 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3641 srvDesc.TextureCube.MipLevels = mipLevelCount;
3645 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3646 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3647 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3648 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3649 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3651 srvDesc.Texture1DArray.FirstArraySlice = 0;
3652 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3655 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3656 srvDesc.Texture1D.MipLevels = mipLevelCount;
3658 }
else if (isArray) {
3659 if (sampleDesc.Count > 1) {
3660 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3661 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3662 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3663 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3665 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3666 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3669 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3670 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3671 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3672 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3673 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3675 srvDesc.Texture2DArray.FirstArraySlice = 0;
3676 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3680 if (sampleDesc.Count > 1) {
3681 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3683 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3684 srvDesc.Texture3D.MipLevels = mipLevelCount;
3686 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3687 srvDesc.Texture2D.MipLevels = mipLevelCount;
3692 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3694 qWarning(
"Failed to create srv: %s",
3695 qPrintable(QSystemError::windowsComString(hr)));
3706 if (!prepareCreate(&size))
3709 const bool isDepth = isDepthTextureFormat(m_format);
3710 const bool isCube = m_flags.testFlag(CubeMap);
3711 const bool is3D = m_flags.testFlag(ThreeDimensional);
3712 const bool isArray = m_flags.testFlag(TextureArray);
3713 const bool is1D = m_flags.testFlag(OneDimensional);
3715 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3716 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3717 if (m_flags.testFlag(RenderTarget)) {
3719 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3721 bindFlags |= D3D11_BIND_RENDER_TARGET;
3723 if (m_flags.testFlag(UsedWithGenerateMips)) {
3725 qWarning(
"Depth texture cannot have mipmaps generated");
3728 bindFlags |= D3D11_BIND_RENDER_TARGET;
3729 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3731 if (m_flags.testFlag(UsedWithLoadStore))
3732 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3736 D3D11_TEXTURE1D_DESC desc = {};
3737 desc.Width = UINT(size.width());
3738 desc.MipLevels = mipLevelCount;
3739 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3740 desc.Format = dxgiFormat;
3741 desc.Usage = D3D11_USAGE_DEFAULT;
3742 desc.BindFlags = bindFlags;
3743 desc.MiscFlags = miscFlags;
3745 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3747 qWarning(
"Failed to create 1D texture: %s",
3748 qPrintable(QSystemError::windowsComString(hr)));
3751 if (!m_objectName.isEmpty())
3752 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3753 m_objectName.constData());
3755 D3D11_TEXTURE2D_DESC desc = {};
3756 desc.Width = UINT(size.width());
3757 desc.Height = UINT(size.height());
3758 desc.MipLevels = mipLevelCount;
3759 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3760 desc.Format = dxgiFormat;
3761 desc.SampleDesc = sampleDesc;
3762 desc.Usage = D3D11_USAGE_DEFAULT;
3763 desc.BindFlags = bindFlags;
3764 desc.MiscFlags = miscFlags;
3766 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3768 qWarning(
"Failed to create 2D texture: %s",
3769 qPrintable(QSystemError::windowsComString(hr)));
3772 if (!m_objectName.isEmpty())
3773 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3775 D3D11_TEXTURE3D_DESC desc = {};
3776 desc.Width = UINT(size.width());
3777 desc.Height = UINT(size.height());
3778 desc.Depth = UINT(qMax(1, m_depth));
3779 desc.MipLevels = mipLevelCount;
3780 desc.Format = dxgiFormat;
3781 desc.Usage = D3D11_USAGE_DEFAULT;
3782 desc.BindFlags = bindFlags;
3783 desc.MiscFlags = miscFlags;
3785 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3787 qWarning(
"Failed to create 3D texture: %s",
3788 qPrintable(QSystemError::windowsComString(hr)));
3791 if (!m_objectName.isEmpty())
3792 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3799 rhiD->registerResource(
this);
3808 if (!prepareCreate())
3811 if (m_flags.testFlag(ThreeDimensional))
3812 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3813 else if (m_flags.testFlags(OneDimensional))
3814 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3816 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3823 rhiD->registerResource(
this);
3829 return { quint64(textureResource()), 0 };
3834 if (perLevelViews[level])
3835 return perLevelViews[level];
3837 const bool isCube = m_flags.testFlag(CubeMap);
3838 const bool isArray = m_flags.testFlag(TextureArray);
3839 const bool is3D = m_flags.testFlag(ThreeDimensional);
3840 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3841 desc.Format = dxgiFormat;
3843 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3844 desc.Texture2DArray.MipSlice = UINT(level);
3845 desc.Texture2DArray.FirstArraySlice = 0;
3846 desc.Texture2DArray.ArraySize = 6;
3847 }
else if (isArray) {
3848 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3849 desc.Texture2DArray.MipSlice = UINT(level);
3850 desc.Texture2DArray.FirstArraySlice = 0;
3851 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3853 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3854 desc.Texture3D.MipSlice = UINT(level);
3855 desc.Texture3D.WSize = UINT(m_depth);
3857 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3858 desc.Texture2D.MipSlice = UINT(level);
3862 ID3D11UnorderedAccessView *uav =
nullptr;
3863 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3865 qWarning(
"Failed to create UAV: %s",
3866 qPrintable(QSystemError::windowsComString(hr)));
3870 perLevelViews[level] = uav;
3875 AddressMode u, AddressMode v, AddressMode w)
3890 samplerState->Release();
3891 samplerState =
nullptr;
3895 rhiD->unregisterResource(
this);
3898static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3900 if (minFilter == QRhiSampler::Nearest) {
3901 if (magFilter == QRhiSampler::Nearest) {
3902 if (mipFilter == QRhiSampler::Linear)
3903 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3905 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3907 if (mipFilter == QRhiSampler::Linear)
3908 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3910 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3913 if (magFilter == QRhiSampler::Nearest) {
3914 if (mipFilter == QRhiSampler::Linear)
3915 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3917 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3919 if (mipFilter == QRhiSampler::Linear)
3920 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3922 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3927 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3933 case QRhiSampler::Repeat:
3934 return D3D11_TEXTURE_ADDRESS_WRAP;
3935 case QRhiSampler::ClampToEdge:
3936 return D3D11_TEXTURE_ADDRESS_CLAMP;
3937 case QRhiSampler::Mirror:
3938 return D3D11_TEXTURE_ADDRESS_MIRROR;
3941 return D3D11_TEXTURE_ADDRESS_CLAMP;
3948 case QRhiSampler::Never:
3949 return D3D11_COMPARISON_NEVER;
3950 case QRhiSampler::Less:
3951 return D3D11_COMPARISON_LESS;
3952 case QRhiSampler::Equal:
3953 return D3D11_COMPARISON_EQUAL;
3954 case QRhiSampler::LessOrEqual:
3955 return D3D11_COMPARISON_LESS_EQUAL;
3956 case QRhiSampler::Greater:
3957 return D3D11_COMPARISON_GREATER;
3958 case QRhiSampler::NotEqual:
3959 return D3D11_COMPARISON_NOT_EQUAL;
3960 case QRhiSampler::GreaterOrEqual:
3961 return D3D11_COMPARISON_GREATER_EQUAL;
3962 case QRhiSampler::Always:
3963 return D3D11_COMPARISON_ALWAYS;
3966 return D3D11_COMPARISON_NEVER;
3975 D3D11_SAMPLER_DESC desc = {};
3976 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3977 if (m_compareOp != Never)
3978 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3979 desc.AddressU = toD3DAddressMode(m_addressU);
3980 desc.AddressV = toD3DAddressMode(m_addressV);
3981 desc.AddressW = toD3DAddressMode(m_addressW);
3982 desc.MaxAnisotropy = 1.0f;
3983 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3984 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3987 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3989 qWarning(
"Failed to create sampler state: %s",
3990 qPrintable(QSystemError::windowsComString(hr)));
3995 rhiD->registerResource(
this);
4014 rhiD->unregisterResource(
this);
4027 rhiD->registerResource(rpD,
false);
4064 return d.sampleCount;
4068 const QRhiTextureRenderTargetDescription &desc,
4086 if (!rtv[0] && !dsv)
4105 rhiD->unregisterResource(
this);
4112 rhiD->registerResource(rpD,
false);
4121 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4122 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4123 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4127 int colorAttCount = 0;
4129 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4131 const QRhiColorAttachment &colorAtt(*it);
4132 QRhiTexture *texture = colorAtt.texture();
4133 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4134 Q_ASSERT(texture || rb);
4137 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4138 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4139 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4140 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4141 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4142 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4143 rtvDesc.Texture2DArray.ArraySize = 1;
4144 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4145 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4146 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4147 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4148 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4149 rtvDesc.Texture1DArray.ArraySize = 1;
4151 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4152 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4154 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4155 if (texD->sampleDesc.Count > 1) {
4156 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4157 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4158 rtvDesc.Texture2DMSArray.ArraySize = 1;
4160 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4161 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4162 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4163 rtvDesc.Texture2DArray.ArraySize = 1;
4165 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4166 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4167 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4168 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4169 rtvDesc.Texture3D.WSize = 1;
4171 if (texD->sampleDesc.Count > 1) {
4172 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4174 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4175 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4178 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4180 qWarning(
"Failed to create rtv: %s",
4181 qPrintable(QSystemError::windowsComString(hr)));
4185 if (attIndex == 0) {
4186 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4187 d.sampleCount =
int(texD->sampleDesc.Count);
4192 rtv[attIndex] = rbD->rtv;
4193 if (attIndex == 0) {
4194 d.pixelSize = rbD->pixelSize();
4195 d.sampleCount =
int(rbD->sampleDesc.Count);
4201 if (hasDepthStencil) {
4202 if (m_desc.depthTexture()) {
4205 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4206 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4207 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4208 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4209 if (isMultisample) {
4210 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4211 if (m_desc.depthLayer() >= 0) {
4212 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4213 dsvDesc.Texture2DMSArray.ArraySize = 1;
4214 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4215 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4216 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4218 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4219 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4222 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4223 if (m_desc.depthLayer() >= 0) {
4224 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4225 dsvDesc.Texture2DArray.ArraySize = 1;
4226 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4227 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4228 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4230 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4231 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4236 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4237 : D3D11_DSV_DIMENSION_TEXTURE2D;
4239 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4241 qWarning(
"Failed to create dsv: %s",
4242 qPrintable(QSystemError::windowsComString(hr)));
4245 if (colorAttCount == 0) {
4246 d.pixelSize = depthTexD->pixelSize();
4247 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4252 dsv = depthRbD->dsv;
4253 if (colorAttCount == 0) {
4254 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4255 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4262 d.views.setFrom(colorAttCount, rtv, dsv);
4264 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4266 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4268 rhiD->registerResource(
this);
4274 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4287 return d.sampleCount;
4302 sortedBindings.clear();
4303 boundResourceData.clear();
4307 rhiD->unregisterResource(
this);
4312 if (!sortedBindings.isEmpty())
4316 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4319 rhiD->updateLayoutDesc(
this);
4321 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4322 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4324 boundResourceData.resize(sortedBindings.count());
4326 for (BoundResourceData &bd : boundResourceData)
4327 memset(&bd, 0,
sizeof(BoundResourceData));
4330 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4331 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4332 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4333 hasDynamicOffset =
true;
4339 rhiD->registerResource(
this,
false);
4345 sortedBindings.clear();
4346 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4347 if (!flags.testFlag(BindingsAreSorted))
4348 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4350 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4351 for (BoundResourceData &bd : boundResourceData)
4352 memset(&bd, 0,
sizeof(BoundResourceData));
4371 s.shader->Release();
4374 s.nativeResourceBindingMap.clear();
4386 blendState->Release();
4387 blendState =
nullptr;
4391 inputLayout->Release();
4392 inputLayout =
nullptr;
4396 rastState->Release();
4397 rastState =
nullptr;
4400 releasePipelineShader(vs);
4401 releasePipelineShader(hs);
4402 releasePipelineShader(ds);
4403 releasePipelineShader(gs);
4404 releasePipelineShader(fs);
4408 rhiD->unregisterResource(
this);
4414 case QRhiGraphicsPipeline::None:
4415 return D3D11_CULL_NONE;
4416 case QRhiGraphicsPipeline::Front:
4417 return D3D11_CULL_FRONT;
4418 case QRhiGraphicsPipeline::Back:
4419 return D3D11_CULL_BACK;
4422 return D3D11_CULL_NONE;
4429 case QRhiGraphicsPipeline::Fill:
4430 return D3D11_FILL_SOLID;
4431 case QRhiGraphicsPipeline::Line:
4432 return D3D11_FILL_WIREFRAME;
4435 return D3D11_FILL_SOLID;
4442 case QRhiGraphicsPipeline::Never:
4443 return D3D11_COMPARISON_NEVER;
4444 case QRhiGraphicsPipeline::Less:
4445 return D3D11_COMPARISON_LESS;
4446 case QRhiGraphicsPipeline::Equal:
4447 return D3D11_COMPARISON_EQUAL;
4448 case QRhiGraphicsPipeline::LessOrEqual:
4449 return D3D11_COMPARISON_LESS_EQUAL;
4450 case QRhiGraphicsPipeline::Greater:
4451 return D3D11_COMPARISON_GREATER;
4452 case QRhiGraphicsPipeline::NotEqual:
4453 return D3D11_COMPARISON_NOT_EQUAL;
4454 case QRhiGraphicsPipeline::GreaterOrEqual:
4455 return D3D11_COMPARISON_GREATER_EQUAL;
4456 case QRhiGraphicsPipeline::Always:
4457 return D3D11_COMPARISON_ALWAYS;
4460 return D3D11_COMPARISON_ALWAYS;
4467 case QRhiGraphicsPipeline::StencilZero:
4468 return D3D11_STENCIL_OP_ZERO;
4469 case QRhiGraphicsPipeline::Keep:
4470 return D3D11_STENCIL_OP_KEEP;
4471 case QRhiGraphicsPipeline::Replace:
4472 return D3D11_STENCIL_OP_REPLACE;
4473 case QRhiGraphicsPipeline::IncrementAndClamp:
4474 return D3D11_STENCIL_OP_INCR_SAT;
4475 case QRhiGraphicsPipeline::DecrementAndClamp:
4476 return D3D11_STENCIL_OP_DECR_SAT;
4477 case QRhiGraphicsPipeline::Invert:
4478 return D3D11_STENCIL_OP_INVERT;
4479 case QRhiGraphicsPipeline::IncrementAndWrap:
4480 return D3D11_STENCIL_OP_INCR;
4481 case QRhiGraphicsPipeline::DecrementAndWrap:
4482 return D3D11_STENCIL_OP_DECR;
4485 return D3D11_STENCIL_OP_KEEP;
4492 case QRhiVertexInputAttribute::Float4:
4493 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4494 case QRhiVertexInputAttribute::Float3:
4495 return DXGI_FORMAT_R32G32B32_FLOAT;
4496 case QRhiVertexInputAttribute::Float2:
4497 return DXGI_FORMAT_R32G32_FLOAT;
4498 case QRhiVertexInputAttribute::Float:
4499 return DXGI_FORMAT_R32_FLOAT;
4500 case QRhiVertexInputAttribute::UNormByte4:
4501 return DXGI_FORMAT_R8G8B8A8_UNORM;
4502 case QRhiVertexInputAttribute::UNormByte2:
4503 return DXGI_FORMAT_R8G8_UNORM;
4504 case QRhiVertexInputAttribute::UNormByte:
4505 return DXGI_FORMAT_R8_UNORM;
4506 case QRhiVertexInputAttribute::UInt4:
4507 return DXGI_FORMAT_R32G32B32A32_UINT;
4508 case QRhiVertexInputAttribute::UInt3:
4509 return DXGI_FORMAT_R32G32B32_UINT;
4510 case QRhiVertexInputAttribute::UInt2:
4511 return DXGI_FORMAT_R32G32_UINT;
4512 case QRhiVertexInputAttribute::UInt:
4513 return DXGI_FORMAT_R32_UINT;
4514 case QRhiVertexInputAttribute::SInt4:
4515 return DXGI_FORMAT_R32G32B32A32_SINT;
4516 case QRhiVertexInputAttribute::SInt3:
4517 return DXGI_FORMAT_R32G32B32_SINT;
4518 case QRhiVertexInputAttribute::SInt2:
4519 return DXGI_FORMAT_R32G32_SINT;
4520 case QRhiVertexInputAttribute::SInt:
4521 return DXGI_FORMAT_R32_SINT;
4522 case QRhiVertexInputAttribute::Half4:
4524 case QRhiVertexInputAttribute::Half3:
4525 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4526 case QRhiVertexInputAttribute::Half2:
4527 return DXGI_FORMAT_R16G16_FLOAT;
4528 case QRhiVertexInputAttribute::Half:
4529 return DXGI_FORMAT_R16_FLOAT;
4530 case QRhiVertexInputAttribute::UShort4:
4532 case QRhiVertexInputAttribute::UShort3:
4533 return DXGI_FORMAT_R16G16B16A16_UINT;
4534 case QRhiVertexInputAttribute::UShort2:
4535 return DXGI_FORMAT_R16G16_UINT;
4536 case QRhiVertexInputAttribute::UShort:
4537 return DXGI_FORMAT_R16_UINT;
4538 case QRhiVertexInputAttribute::SShort4:
4540 case QRhiVertexInputAttribute::SShort3:
4541 return DXGI_FORMAT_R16G16B16A16_SINT;
4542 case QRhiVertexInputAttribute::SShort2:
4543 return DXGI_FORMAT_R16G16_SINT;
4544 case QRhiVertexInputAttribute::SShort:
4545 return DXGI_FORMAT_R16_SINT;
4548 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4555 case QRhiGraphicsPipeline::Triangles:
4556 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4557 case QRhiGraphicsPipeline::TriangleStrip:
4558 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4559 case QRhiGraphicsPipeline::Lines:
4560 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4561 case QRhiGraphicsPipeline::LineStrip:
4562 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4563 case QRhiGraphicsPipeline::Points:
4564 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4565 case QRhiGraphicsPipeline::Patches:
4566 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4567 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4570 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4577 if (c.testFlag(QRhiGraphicsPipeline::R))
4578 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4579 if (c.testFlag(QRhiGraphicsPipeline::G))
4580 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4581 if (c.testFlag(QRhiGraphicsPipeline::B))
4582 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4583 if (c.testFlag(QRhiGraphicsPipeline::A))
4584 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4597 case QRhiGraphicsPipeline::Zero:
4598 return D3D11_BLEND_ZERO;
4599 case QRhiGraphicsPipeline::One:
4600 return D3D11_BLEND_ONE;
4601 case QRhiGraphicsPipeline::SrcColor:
4602 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4603 case QRhiGraphicsPipeline::OneMinusSrcColor:
4604 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4605 case QRhiGraphicsPipeline::DstColor:
4606 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4607 case QRhiGraphicsPipeline::OneMinusDstColor:
4608 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4609 case QRhiGraphicsPipeline::SrcAlpha:
4610 return D3D11_BLEND_SRC_ALPHA;
4611 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4612 return D3D11_BLEND_INV_SRC_ALPHA;
4613 case QRhiGraphicsPipeline::DstAlpha:
4614 return D3D11_BLEND_DEST_ALPHA;
4615 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4616 return D3D11_BLEND_INV_DEST_ALPHA;
4617 case QRhiGraphicsPipeline::ConstantColor:
4618 case QRhiGraphicsPipeline::ConstantAlpha:
4619 return D3D11_BLEND_BLEND_FACTOR;
4620 case QRhiGraphicsPipeline::OneMinusConstantColor:
4621 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4622 return D3D11_BLEND_INV_BLEND_FACTOR;
4623 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4624 return D3D11_BLEND_SRC_ALPHA_SAT;
4625 case QRhiGraphicsPipeline::Src1Color:
4626 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4627 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4628 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4629 case QRhiGraphicsPipeline::Src1Alpha:
4630 return D3D11_BLEND_SRC1_ALPHA;
4631 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4632 return D3D11_BLEND_INV_SRC1_ALPHA;
4635 return D3D11_BLEND_ZERO;
4642 case QRhiGraphicsPipeline::Add:
4643 return D3D11_BLEND_OP_ADD;
4644 case QRhiGraphicsPipeline::Subtract:
4645 return D3D11_BLEND_OP_SUBTRACT;
4646 case QRhiGraphicsPipeline::ReverseSubtract:
4647 return D3D11_BLEND_OP_REV_SUBTRACT;
4648 case QRhiGraphicsPipeline::Min:
4649 return D3D11_BLEND_OP_MIN;
4650 case QRhiGraphicsPipeline::Max:
4651 return D3D11_BLEND_OP_MAX;
4654 return D3D11_BLEND_OP_ADD;
4661 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4662 keyBuilder.addData(source);
4663 return keyBuilder.result().toHex();
4666QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4667 QString *error, QShaderKey *usedShaderKey)
4669 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4670 QShaderCode dxbc = shader.shader(key);
4671 if (!dxbc.shader().isEmpty()) {
4673 *usedShaderKey = key;
4674 return dxbc.shader();
4677 key = { QShader::HlslShader, 50, shaderVariant };
4678 QShaderCode hlslSource = shader.shader(key);
4679 if (hlslSource.shader().isEmpty()) {
4680 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4681 return QByteArray();
4685 *usedShaderKey = key;
4688 switch (shader.stage()) {
4689 case QShader::VertexStage:
4692 case QShader::TessellationControlStage:
4695 case QShader::TessellationEvaluationStage:
4698 case QShader::GeometryStage:
4701 case QShader::FragmentStage:
4704 case QShader::ComputeStage:
4709 return QByteArray();
4713 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4714 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4715 cacheKey.target = target;
4716 cacheKey.entryPoint = hlslSource.entryPoint();
4717 cacheKey.compileFlags = flags;
4718 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4719 if (cacheIt != m_bytecodeCache.constEnd())
4720 return cacheIt.value();
4723 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4724 if (d3dCompile ==
nullptr) {
4725 qWarning(
"Unable to resolve function D3DCompile()");
4726 return QByteArray();
4729 ID3DBlob *bytecode =
nullptr;
4730 ID3DBlob *errors =
nullptr;
4731 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4732 nullptr,
nullptr,
nullptr,
4733 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4734 if (FAILED(hr) || !bytecode) {
4735 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4737 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4738 int(errors->GetBufferSize()));
4741 return QByteArray();
4745 result.resize(
int(bytecode->GetBufferSize()));
4746 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4747 bytecode->Release();
4749 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4750 m_bytecodeCache.insert(cacheKey, result);
4761 rhiD->pipelineCreationStart();
4762 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4765 D3D11_RASTERIZER_DESC rastDesc = {};
4766 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4767 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4768 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4769 rastDesc.DepthBias = m_depthBias;
4770 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4771 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4772 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4773 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4774 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4776 qWarning(
"Failed to create rasterizer state: %s",
4777 qPrintable(QSystemError::windowsComString(hr)));
4781 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4782 dsDesc.DepthEnable = m_depthTest;
4783 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4784 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4785 dsDesc.StencilEnable = m_stencilTest;
4786 if (m_stencilTest) {
4787 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4788 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4789 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4790 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4791 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4792 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4793 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4794 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4795 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4796 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4798 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4800 qWarning(
"Failed to create depth-stencil state: %s",
4801 qPrintable(QSystemError::windowsComString(hr)));
4805 D3D11_BLEND_DESC blendDesc = {};
4806 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4807 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4808 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4809 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4810 blend.BlendEnable = b.enable;
4811 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4812 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4813 blend.BlendOp = toD3DBlendOp(b.opColor);
4814 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4815 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4816 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4817 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4818 blendDesc.RenderTarget[i] = blend;
4820 if (m_targetBlends.isEmpty()) {
4821 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4822 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4823 blendDesc.RenderTarget[0] = blend;
4825 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4827 qWarning(
"Failed to create blend state: %s",
4828 qPrintable(QSystemError::windowsComString(hr)));
4832 QByteArray vsByteCode;
4833 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4834 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4835 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4836 switch (shaderStage.type()) {
4837 case QRhiShaderStage::Vertex:
4838 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4839 vs.shader->AddRef();
4840 vsByteCode = cacheIt->bytecode;
4841 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4843 case QRhiShaderStage::TessellationControl:
4844 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4845 hs.shader->AddRef();
4846 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4848 case QRhiShaderStage::TessellationEvaluation:
4849 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4850 ds.shader->AddRef();
4851 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4853 case QRhiShaderStage::Geometry:
4854 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4855 gs.shader->AddRef();
4856 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4858 case QRhiShaderStage::Fragment:
4859 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4860 fs.shader->AddRef();
4861 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4868 QShaderKey shaderKey;
4869 UINT compileFlags = 0;
4870 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4871 compileFlags |= D3DCOMPILE_DEBUG;
4873 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4874 &error, &shaderKey);
4875 if (bytecode.isEmpty()) {
4876 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4880 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4882 rhiD->clearShaderCache();
4885 switch (shaderStage.type()) {
4886 case QRhiShaderStage::Vertex:
4887 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4889 qWarning(
"Failed to create vertex shader: %s",
4890 qPrintable(QSystemError::windowsComString(hr)));
4893 vsByteCode = bytecode;
4894 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4895 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4896 vs.shader->AddRef();
4898 case QRhiShaderStage::TessellationControl:
4899 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4901 qWarning(
"Failed to create hull shader: %s",
4902 qPrintable(QSystemError::windowsComString(hr)));
4905 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4906 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4907 hs.shader->AddRef();
4909 case QRhiShaderStage::TessellationEvaluation:
4910 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4912 qWarning(
"Failed to create domain shader: %s",
4913 qPrintable(QSystemError::windowsComString(hr)));
4916 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4917 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4918 ds.shader->AddRef();
4920 case QRhiShaderStage::Geometry:
4921 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4923 qWarning(
"Failed to create geometry shader: %s",
4924 qPrintable(QSystemError::windowsComString(hr)));
4927 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4928 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4929 gs.shader->AddRef();
4931 case QRhiShaderStage::Fragment:
4932 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4934 qWarning(
"Failed to create pixel shader: %s",
4935 qPrintable(QSystemError::windowsComString(hr)));
4938 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4939 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4940 fs.shader->AddRef();
4948 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4950 if (!vsByteCode.isEmpty()) {
4951 QByteArrayList matrixSliceSemantics;
4952 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4953 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4956 D3D11_INPUT_ELEMENT_DESC desc = {};
4961 const int matrixSlice = it->matrixSlice();
4962 if (matrixSlice < 0) {
4963 desc.SemanticName =
"TEXCOORD";
4964 desc.SemanticIndex = UINT(it->location());
4968 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4969 matrixSliceSemantics.append(sem);
4970 desc.SemanticName = matrixSliceSemantics.last().constData();
4971 desc.SemanticIndex = UINT(matrixSlice);
4973 desc.Format = toD3DAttributeFormat(it->format());
4974 desc.InputSlot = UINT(it->binding());
4975 desc.AlignedByteOffset = it->offset();
4976 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4977 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4978 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4979 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4981 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4983 inputDescs.append(desc);
4985 if (!inputDescs.isEmpty()) {
4986 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4987 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4989 qWarning(
"Failed to create input layout: %s",
4990 qPrintable(QSystemError::windowsComString(hr)));
4996 rhiD->pipelineCreationEnd();
4998 rhiD->registerResource(
this);
5017 cs.shader->Release();
5018 cs.shader =
nullptr;
5019 cs.nativeResourceBindingMap.clear();
5023 rhiD->unregisterResource(
this);
5032 rhiD->pipelineCreationStart();
5034 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5035 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5036 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5037 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5040 QShaderKey shaderKey;
5041 UINT compileFlags = 0;
5042 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5043 compileFlags |= D3DCOMPILE_DEBUG;
5045 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5046 &error, &shaderKey);
5047 if (bytecode.isEmpty()) {
5048 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5052 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5054 qWarning(
"Failed to create compute shader: %s",
5055 qPrintable(QSystemError::windowsComString(hr)));
5059 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5061 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5064 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5067 cs.shader->AddRef();
5069 rhiD->pipelineCreationEnd();
5071 rhiD->registerResource(
this);
5096 D3D11_QUERY_DESC queryDesc = {};
5098 if (!disjointQuery[i]) {
5099 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5100 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5102 qWarning(
"Failed to create timestamp disjoint query: %s",
5103 qPrintable(QSystemError::windowsComString(hr)));
5107 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5108 for (
int j = 0; j < 2; ++j) {
5109 const int idx = 2 * i + j;
5111 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5113 qWarning(
"Failed to create timestamp query: %s",
5114 qPrintable(QSystemError::windowsComString(hr)));
5127 if (disjointQuery[i]) {
5128 disjointQuery[i]->Release();
5129 disjointQuery[i] =
nullptr;
5131 for (
int j = 0; j < 2; ++j) {
5134 query[idx]->Release();
5135 query[idx] =
nullptr;
5143 bool result =
false;
5147 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5148 ID3D11Query *tsStart = query[pairIndex * 2];
5149 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5150 quint64 timestamps[2];
5151 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5154 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5155 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5156 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5159 if (!dj.Disjoint && dj.Frequency) {
5160 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5161 *elapsedSec = elapsedMs / 1000.0;
5164 active[pairIndex] =
false;
5173 backBufferTex =
nullptr;
5174 backBufferRtv =
nullptr;
5176 msaaTex[i] =
nullptr;
5177 msaaRtv[i] =
nullptr;
5188 if (backBufferRtv) {
5189 backBufferRtv->Release();
5190 backBufferRtv =
nullptr;
5192 if (backBufferRtvRight) {
5193 backBufferRtvRight->Release();
5194 backBufferRtvRight =
nullptr;
5196 if (backBufferTex) {
5197 backBufferTex->Release();
5198 backBufferTex =
nullptr;
5202 msaaRtv[i]->Release();
5203 msaaRtv[i] =
nullptr;
5206 msaaTex[i]->Release();
5207 msaaTex[i] =
nullptr;
5219 timestamps.destroy();
5221 swapChain->Release();
5222 swapChain =
nullptr;
5225 dcompVisual->Release();
5226 dcompVisual =
nullptr;
5230 dcompTarget->Release();
5231 dcompTarget =
nullptr;
5234 if (frameLatencyWaitableObject) {
5235 CloseHandle(frameLatencyWaitableObject);
5236 frameLatencyWaitableObject =
nullptr;
5239 QDxgiVSyncService::instance()->unregisterWindow(window);
5243 rhiD->unregisterResource(
this);
5246 rhiD->context->Flush();
5262 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5268 return m_window->size() * m_window->devicePixelRatio();
5277 qWarning(
"Attempted to call isFormatSupported() without a window set");
5282 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5283 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5294 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5303 rhiD->registerResource(rpD,
false);
5308 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5310 D3D11_TEXTURE2D_DESC desc = {};
5311 desc.Width = UINT(size.width());
5312 desc.Height = UINT(size.height());
5315 desc.Format = format;
5316 desc.SampleDesc = sampleDesc;
5317 desc.Usage = D3D11_USAGE_DEFAULT;
5318 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5321 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5323 qWarning(
"Failed to create color buffer texture: %s",
5324 qPrintable(QSystemError::windowsComString(hr)));
5328 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5329 rtvDesc.Format = format;
5330 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5331 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5333 qWarning(
"Failed to create color buffer rtv: %s",
5334 qPrintable(QSystemError::windowsComString(hr)));
5348 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5349 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5350 return dcompDevice ?
true :
false;
5362 const bool needsRegistration = !window || window != m_window;
5363 const bool stereo = m_window->format().stereo();
5366 if (window && window != m_window)
5370 m_currentPixelSize = surfacePixelSize();
5371 pixelSize = m_currentPixelSize;
5373 if (pixelSize.isEmpty())
5376 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5381 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5384 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5386 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5387 qPrintable(QSystemError::windowsComString(hr)));
5390 if (dcompTarget && !dcompVisual) {
5391 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5393 qWarning(
"Failed to create DirectComposition visual: %s",
5394 qPrintable(QSystemError::windowsComString(hr)));
5399 if (
window->requestedFormat().alphaBufferSize() <= 0)
5400 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5401 "This may lead to problems.");
5404 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5411 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5412 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5416 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5417 && swapInterval != 0
5418 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5420 if (useFrameLatencyWaitableObject) {
5422 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5426 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5427 colorFormat = DEFAULT_FORMAT;
5428 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5430 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5431 if (m_format != SDR) {
5432 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5435 case HDRExtendedSrgbLinear:
5436 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5437 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5438 srgbAdjustedColorFormat = colorFormat;
5441 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5442 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5443 srgbAdjustedColorFormat = colorFormat;
5452 qWarning(
"The output associated with the window is not HDR capable "
5453 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5463 DXGI_SWAP_CHAIN_DESC1 desc = {};
5464 desc.Width = UINT(pixelSize.width());
5465 desc.Height = UINT(pixelSize.height());
5466 desc.Format = colorFormat;
5467 desc.SampleDesc.Count = 1;
5468 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5470 desc.Flags = swapChainFlags;
5471 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5472 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5473 desc.Stereo = stereo;
5479 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5484 desc.Scaling = DXGI_SCALING_STRETCH;
5487 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5488 IDXGISwapChain1 *sc1;
5491 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5493 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5498 if (FAILED(hr) && m_format != SDR) {
5499 colorFormat = DEFAULT_FORMAT;
5500 desc.Format = DEFAULT_FORMAT;
5502 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5504 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5507 if (SUCCEEDED(hr)) {
5509 IDXGISwapChain3 *sc3 =
nullptr;
5510 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5511 if (m_format != SDR) {
5512 hr = sc3->SetColorSpace1(hdrColorSpace);
5514 qWarning(
"Failed to set color space on swapchain: %s",
5515 qPrintable(QSystemError::windowsComString(hr)));
5517 if (useFrameLatencyWaitableObject) {
5518 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5519 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5523 if (m_format != SDR)
5524 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5525 if (useFrameLatencyWaitableObject) {
5526 IDXGISwapChain2 *sc2 =
nullptr;
5527 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5528 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5529 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5532 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5537 hr = dcompVisual->SetContent(sc1);
5538 if (SUCCEEDED(hr)) {
5539 hr = dcompTarget->SetRoot(dcompVisual);
5541 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5542 qPrintable(QSystemError::windowsComString(hr)));
5545 qWarning(
"Failed to set content for Direct Composition visual: %s",
5546 qPrintable(QSystemError::windowsComString(hr)));
5550 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5553 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5554 qWarning(
"Device loss detected during swapchain creation");
5557 }
else if (FAILED(hr)) {
5558 qWarning(
"Failed to create D3D11 swapchain: %s"
5559 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5560 qPrintable(QSystemError::windowsComString(hr)),
5561 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5562 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5568 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5569 colorFormat, swapChainFlags);
5570 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5571 qWarning(
"Device loss detected in ResizeBuffers()");
5574 }
else if (FAILED(hr)) {
5575 qWarning(
"Failed to resize D3D11 swapchain: %s",
5576 qPrintable(QSystemError::windowsComString(hr)));
5595 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5597 qWarning(
"Failed to query swapchain backbuffer: %s",
5598 qPrintable(QSystemError::windowsComString(hr)));
5601 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5602 rtvDesc.Format = srgbAdjustedColorFormat;
5603 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5604 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5606 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5607 qPrintable(QSystemError::windowsComString(hr)));
5613 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5614 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5615 rtvDesc.Texture2DArray.ArraySize = 1;
5616 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5618 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5619 qPrintable(QSystemError::windowsComString(hr)));
5626 if (sampleDesc.Count > 1) {
5627 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5632 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5633 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5634 m_depthStencil->sampleCount(), m_sampleCount);
5636 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5637 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5638 m_depthStencil->setPixelSize(pixelSize);
5639 if (!m_depthStencil->create())
5640 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5641 pixelSize.width(), pixelSize.height());
5643 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5644 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5645 pixelSize.width(), pixelSize.height());
5652 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5654 rt.setRenderPassDescriptor(m_renderPassDesc);
5656 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5657 rtD->d.pixelSize = pixelSize;
5658 rtD->d.dpr =
float(
window->devicePixelRatio());
5659 rtD->d.sampleCount =
int(sampleDesc.Count);
5660 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5663 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5664 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5665 rtD->d.pixelSize = pixelSize;
5666 rtD->d.dpr =
float(
window->devicePixelRatio());
5667 rtD->d.sampleCount =
int(sampleDesc.Count);
5668 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
5671 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5672 timestamps.prepare(rhiD);
5676 QDxgiVSyncService::instance()->registerWindow(window);
5678 if (needsRegistration)
5679 rhiD->registerResource(
this);
5687 if (rtViews.dsv != currentRtViews.dsv) {
5688 rtViews.dsv = currentRtViews.dsv;
5692 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
5693 rtViews.rtv[i] = currentRtViews.rtv[i];
5696 ret |= rtViews.rtv[i] !=
nullptr;
5697 rtViews.rtv[i] =
nullptr;
5699 for (
int i = 0; i < count; i++) {
5700 ret |= uav[i] != uavs[i];
5704 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
QRhiGraphicsPipeline * createGraphicsPipeline() override
QRhiShaderResourceBindings * createShaderResourceBindings() override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QList< int > supportedSampleCounts() const override
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
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 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