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 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
600 0.0f, 1.0f, 0.0f, 0.0f,
601 0.0f, 0.0f, 0.5f, 0.5f,
602 0.0f, 0.0f, 0.0f, 1.0f);
610 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
619 case QRhi::MultisampleTexture:
621 case QRhi::MultisampleRenderBuffer:
623 case QRhi::DebugMarkers:
624 return annotations !=
nullptr;
625 case QRhi::Timestamps:
627 case QRhi::Instancing:
629 case QRhi::CustomInstanceStepRate:
631 case QRhi::PrimitiveRestart:
633 case QRhi::NonDynamicUniformBuffers:
635 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
637 case QRhi::NPOTTextureRepeat:
639 case QRhi::RedOrAlpha8IsRed:
641 case QRhi::ElementIndexUint:
645 case QRhi::WideLines:
647 case QRhi::VertexShaderPointSize:
649 case QRhi::BaseVertex:
651 case QRhi::BaseInstance:
653 case QRhi::TriangleFanTopology:
655 case QRhi::ReadBackNonUniformBuffer:
657 case QRhi::ReadBackNonBaseMipLevel:
659 case QRhi::TexelFetch:
661 case QRhi::RenderToNonBaseMipLevel:
663 case QRhi::IntAttributes:
665 case QRhi::ScreenSpaceDerivatives:
667 case QRhi::ReadBackAnyTextureFormat:
669 case QRhi::PipelineCacheDataLoadSave:
671 case QRhi::ImageDataStride:
673 case QRhi::RenderBufferImport:
675 case QRhi::ThreeDimensionalTextures:
677 case QRhi::RenderTo3DTextureSlice:
679 case QRhi::TextureArrays:
681 case QRhi::Tessellation:
683 case QRhi::GeometryShader:
685 case QRhi::TextureArrayRange:
687 case QRhi::NonFillPolygonMode:
689 case QRhi::OneDimensionalTextures:
691 case QRhi::OneDimensionalTextureMipmaps:
693 case QRhi::HalfAttributes:
695 case QRhi::RenderToOneDimensionalTexture:
697 case QRhi::ThreeDimensionalTextureMipmaps:
699 case QRhi::MultiView:
701 case QRhi::TextureViewFormat:
703 case QRhi::ResolveDepthStencil:
705 case QRhi::VariableRateShading:
707 case QRhi::VariableRateShadingMap:
708 case QRhi::VariableRateShadingMapWithTexture:
710 case QRhi::PerRenderTargetBlending:
711 case QRhi::SampleVariables:
713 case QRhi::InstanceIndexIncludesBaseInstance:
715 case QRhi::DepthClamp:
717 case QRhi::DrawIndirect:
718 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
719 case QRhi::DrawIndirectMulti:
720 case QRhi::ShaderDrawParameters:
731 case QRhi::TextureSizeMin:
733 case QRhi::TextureSizeMax:
734 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
735 case QRhi::MaxColorAttachments:
737 case QRhi::FramesInFlight:
743 case QRhi::MaxAsyncReadbackFrames:
745 case QRhi::MaxThreadGroupsPerDimension:
746 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
747 case QRhi::MaxThreadsPerThreadGroup:
748 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
749 case QRhi::MaxThreadGroupX:
750 return D3D11_CS_THREAD_GROUP_MAX_X;
751 case QRhi::MaxThreadGroupY:
752 return D3D11_CS_THREAD_GROUP_MAX_Y;
753 case QRhi::MaxThreadGroupZ:
754 return D3D11_CS_THREAD_GROUP_MAX_Z;
755 case QRhi::TextureArraySizeMax:
756 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
757 case QRhi::MaxUniformBufferRange:
759 case QRhi::MaxVertexInputs:
761 case QRhi::MaxVertexOutputs:
762 return D3D11_VS_OUTPUT_REGISTER_COUNT;
763 case QRhi::ShadingRateImageTileSize:
773 return &nativeHandlesStruct;
778 return driverInfoStruct;
784 result.totalPipelineCreationTime = totalPipelineCreationTime();
794void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
802 m_bytecodeCache.clear();
822 if (m_bytecodeCache.isEmpty())
826 memset(&header, 0,
sizeof(header));
827 header.rhiId = pipelineCacheRhiId();
828 header.arch = quint32(
sizeof(
void*));
829 header.count = m_bytecodeCache.count();
831 const size_t dataOffset =
sizeof(header);
833 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
835 QByteArray bytecode = it.value();
837 sizeof(quint32) + key.sourceHash.size()
838 +
sizeof(quint32) + key.target.size()
839 +
sizeof(quint32) + key.entryPoint.size()
841 +
sizeof(quint32) + bytecode.size();
844 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
845 char *p = buf.data() + dataOffset;
846 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
848 QByteArray bytecode = it.value();
850 quint32 i = key.sourceHash.size();
853 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
854 p += key.sourceHash.size();
856 i = key.target.size();
859 memcpy(p, key.target.constData(), key.target.size());
860 p += key.target.size();
862 i = key.entryPoint.size();
865 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
866 p += key.entryPoint.size();
868 quint32 f = key.compileFlags;
875 memcpy(p, bytecode.constData(), bytecode.size());
876 p += bytecode.size();
878 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
880 header.dataSize = quint32(dataSize);
881 memcpy(buf.data(), &header,
sizeof(header));
892 if (data.size() < qsizetype(headerSize)) {
893 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
896 const size_t dataOffset = headerSize;
898 memcpy(&header, data.constData(), headerSize);
900 const quint32 rhiId = pipelineCacheRhiId();
901 if (header.rhiId != rhiId) {
902 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
903 rhiId, header.rhiId);
906 const quint32 arch = quint32(
sizeof(
void*));
907 if (header.arch != arch) {
908 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
912 if (header.count == 0)
915 if (data.size() < qsizetype(dataOffset + header.dataSize)) {
916 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
920 m_bytecodeCache.clear();
922 const char *p = data.constData() + dataOffset;
923 for (quint32 i = 0; i < header.count; ++i) {
927 QByteArray sourceHash(len, Qt::Uninitialized);
928 memcpy(sourceHash.data(), p, len);
933 QByteArray target(len, Qt::Uninitialized);
934 memcpy(target.data(), p, len);
939 QByteArray entryPoint(len, Qt::Uninitialized);
940 memcpy(entryPoint.data(), p, len);
944 memcpy(&flags, p, 4);
949 QByteArray bytecode(len, Qt::Uninitialized);
950 memcpy(bytecode.data(), p, len);
954 cacheKey.sourceHash = sourceHash;
955 cacheKey.target = target;
956 cacheKey.entryPoint = entryPoint;
957 cacheKey.compileFlags = flags;
959 m_bytecodeCache.insert(cacheKey, bytecode);
962 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
965QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
966 int sampleCount, QRhiRenderBuffer::Flags flags,
967 QRhiTexture::Format backingFormatHint)
969 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
973 const QSize &pixelSize,
int depth,
int arraySize,
974 int sampleCount, QRhiTexture::Flags flags)
976 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
980 QRhiSampler::Filter mipmapMode,
981 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
983 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
987 QRhiTextureRenderTarget::Flags flags)
999 return new QD3D11GraphicsPipeline(
this);
1004 return new QD3D11ComputePipeline(
this);
1009 return new QD3D11ShaderResourceBindings(
this);
1017 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1019 if (pipelineChanged) {
1020 cbD->currentGraphicsPipeline = ps;
1021 cbD->currentComputePipeline =
nullptr;
1022 cbD->currentPipelineGeneration = psD->generation;
1026 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1027 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1028 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1029 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1030 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1031 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1032 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1033 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1034 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1035 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1048 int dynamicOffsetCount,
1049 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1058 srb = gfxPsD->m_shaderResourceBindings;
1060 srb = compPsD->m_shaderResourceBindings;
1065 bool pipelineChanged =
false;
1074 bool srbUpdate =
false;
1075 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1076 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1079 case QRhiShaderResourceBinding::UniformBuffer:
1083 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1084 sanityCheckResourceOwnership(bufD);
1088 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1090 bd.ubuf.id = bufD->m_id;
1091 bd.ubuf.generation = bufD->generation;
1095 case QRhiShaderResourceBinding::SampledTexture:
1096 case QRhiShaderResourceBinding::Texture:
1097 case QRhiShaderResourceBinding::Sampler:
1099 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1100 if (bd.stex.count != data->count) {
1101 bd.stex.count = data->count;
1104 for (
int elem = 0; elem < data->count; ++elem) {
1110 Q_ASSERT(texD || samplerD);
1111 sanityCheckResourceOwnership(texD);
1112 sanityCheckResourceOwnership(samplerD);
1113 const quint64 texId = texD ? texD->m_id : 0;
1114 const uint texGen = texD ? texD->generation : 0;
1115 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1116 const uint samplerGen = samplerD ? samplerD->generation : 0;
1117 if (texGen != bd.stex.d[elem].texGeneration
1118 || texId != bd.stex.d[elem].texId
1119 || samplerGen != bd.stex.d[elem].samplerGeneration
1120 || samplerId != bd.stex.d[elem].samplerId)
1123 bd.stex.d[elem].texId = texId;
1124 bd.stex.d[elem].texGeneration = texGen;
1125 bd.stex.d[elem].samplerId = samplerId;
1126 bd.stex.d[elem].samplerGeneration = samplerGen;
1131 case QRhiShaderResourceBinding::ImageLoad:
1132 case QRhiShaderResourceBinding::ImageStore:
1133 case QRhiShaderResourceBinding::ImageLoadStore:
1136 sanityCheckResourceOwnership(texD);
1137 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1139 bd.simage.id = texD->m_id;
1140 bd.simage.generation = texD->generation;
1144 case QRhiShaderResourceBinding::BufferLoad:
1145 case QRhiShaderResourceBinding::BufferStore:
1146 case QRhiShaderResourceBinding::BufferLoadStore:
1149 sanityCheckResourceOwnership(bufD);
1150 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1152 bd.sbuf.id = bufD->m_id;
1153 bd.sbuf.generation = bufD->generation;
1163 if (srbUpdate || pipelineChanged) {
1165 memset(resBindMaps, 0,
sizeof(resBindMaps));
1167 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1168 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1169 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1170 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1171 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1173 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1175 updateShaderResourceBindings(srbD, resBindMaps);
1178 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1179 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1181 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1183 cbD->currentGraphicsSrb = srb;
1184 cbD->currentComputeSrb =
nullptr;
1186 cbD->currentGraphicsSrb =
nullptr;
1187 cbD->currentComputeSrb = srb;
1189 cbD->currentSrbGeneration = srbD->generation;
1196 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1197 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1200 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1201 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1202 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1203 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1204 const uint binding = uint(dynOfs.first);
1205 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1206 const quint32 offsetInConstants = dynOfs.second / 16;
1208 *p++ = offsetInConstants;
1211 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1219 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1220 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1225 bool needsBindVBuf =
false;
1226 for (
int i = 0; i < bindingCount; ++i) {
1227 const int inputSlot = startBinding + i;
1229 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1230 if (bufD->m_type == QRhiBuffer::Dynamic)
1233 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1234 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1236 needsBindVBuf =
true;
1237 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1238 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1242 if (needsBindVBuf) {
1245 cmd.args.bindVertexBuffers.startSlot = startBinding;
1247 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1251 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1253 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1254 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1255 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1257 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1258 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1259 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1265 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1266 if (ibufD->m_type == QRhiBuffer::Dynamic)
1269 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1270 : DXGI_FORMAT_R32_UINT;
1271 if (cbD->currentIndexBuffer != ibufD->buffer
1272 || cbD->currentIndexOffset != indexOffset
1273 || cbD->currentIndexFormat != dxgiFormat)
1275 cbD->currentIndexBuffer = ibufD->buffer;
1276 cbD->currentIndexOffset = indexOffset;
1277 cbD->currentIndexFormat = dxgiFormat;
1281 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1282 cmd.args.bindIndexBuffer.offset = indexOffset;
1283 cmd.args.bindIndexBuffer.format = dxgiFormat;
1292 Q_ASSERT(cbD->currentTarget);
1293 const QSize outputSize = cbD->currentTarget->pixelSize();
1297 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1302 cmd.args.viewport.x = x;
1303 cmd.args.viewport.y = y;
1304 cmd.args.viewport.w = w;
1305 cmd.args.viewport.h = h;
1306 cmd.args.viewport.d0 = viewport.minDepth();
1307 cmd.args.viewport.d1 = viewport.maxDepth();
1314 Q_ASSERT(cbD->currentTarget);
1315 const QSize outputSize = cbD->currentTarget->pixelSize();
1319 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1324 cmd.args.scissor.x = x;
1325 cmd.args.scissor.y = y;
1326 cmd.args.scissor.w = w;
1327 cmd.args.scissor.h = h;
1338 cmd.args.blendConstants.c[0] =
float(c.redF());
1339 cmd.args.blendConstants.c[1] =
float(c.greenF());
1340 cmd.args.blendConstants.c[2] =
float(c.blueF());
1341 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1352 cmd.args.stencilRef.ref = refValue;
1358 Q_UNUSED(coarsePixelSize);
1362 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1369 cmd.args.draw.vertexCount = vertexCount;
1370 cmd.args.draw.instanceCount = instanceCount;
1371 cmd.args.draw.firstVertex = firstVertex;
1372 cmd.args.draw.firstInstance = firstInstance;
1376 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1383 cmd.args.drawIndexed.indexCount = indexCount;
1384 cmd.args.drawIndexed.instanceCount = instanceCount;
1385 cmd.args.drawIndexed.firstIndex = firstIndex;
1386 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1387 cmd.args.drawIndexed.firstInstance = firstInstance;
1391 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1398 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1399 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1400 cmd.args.drawIndirect.drawCount = drawCount;
1401 cmd.args.drawIndirect.stride = stride;
1406 switch (rt->resourceType()) {
1407 case QRhiResource::SwapChainRenderTarget:
1408 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1409 case QRhiResource::TextureRenderTarget:
1410 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1418 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1425 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1426 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1427 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1428 cmd.args.drawIndexedIndirect.stride = stride;
1433 if (!debugMarkers || !annotations)
1439 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1444 if (!debugMarkers || !annotations)
1454 if (!debugMarkers || !annotations)
1460 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1479 Q_ASSERT(cbD->commands.isEmpty());
1481 if (cbD->currentTarget) {
1485 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1504 if (swapChainD->frameLatencyWaitableObject) {
1507 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1512 swapChainD->cb.resetState();
1514 swapChainD->rt.d.views.setFrom(1,
1515 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1516 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1521 double elapsedSec = 0;
1523 swapChainD->cb.lastGpuTime = elapsedSec;
1532 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1533 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1534 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1535 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1537 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1539 return QRhi::FrameOpSuccess;
1550 cmd.args.endFrame.tsQuery =
nullptr;
1551 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1556 if (swapChainD->sampleDesc.Count > 1) {
1557 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1558 swapChainD->msaaTex[currentFrameSlot], 0,
1559 swapChainD->colorFormat);
1566 if (recordTimestamps) {
1567 context->End(tsEnd);
1568 context->End(tsDisjoint);
1573 if (!flags.testFlag(QRhi::SkipPresent)) {
1574 UINT presentFlags = 0;
1575 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1576 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1577 if (!swapChainD->swapChain) {
1578 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1579 return QRhi::FrameOpError;
1581 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1582 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1583 qWarning(
"Device loss detected in Present()");
1585 return QRhi::FrameOpDeviceLost;
1586 }
else if (FAILED(hr)) {
1587 qWarning(
"Failed to present: %s",
1588 qPrintable(QSystemError::windowsComString(hr)));
1589 return QRhi::FrameOpError;
1592 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1593 dcompDevice->Commit();
1604 return QRhi::FrameOpSuccess;
1612 ofr.cbWrapper.resetState();
1613 *cb = &ofr.cbWrapper;
1615 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1616 D3D11_QUERY_DESC queryDesc = {};
1617 if (!ofr.tsDisjointQuery) {
1618 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1619 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1621 qWarning(
"Failed to create timestamp disjoint query: %s",
1622 qPrintable(QSystemError::windowsComString(hr)));
1623 return QRhi::FrameOpError;
1626 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1627 for (
int i = 0; i < 2; ++i) {
1628 if (!ofr.tsQueries[i]) {
1629 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1631 qWarning(
"Failed to create timestamp query: %s",
1632 qPrintable(QSystemError::windowsComString(hr)));
1633 return QRhi::FrameOpError;
1641 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1642 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1643 cmd.args.beginFrame.swapchainRtv =
nullptr;
1644 cmd.args.beginFrame.swapchainDsv =
nullptr;
1646 return QRhi::FrameOpSuccess;
1656 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1657 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1664 if (ofr.tsQueries[0]) {
1665 quint64 timestamps[2];
1666 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1670 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1671 }
while (hr == S_FALSE);
1674 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1675 }
while (hr == S_FALSE);
1678 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1679 }
while (hr == S_FALSE);
1682 if (!dj.Disjoint && dj.Frequency) {
1683 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1684 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1689 return QRhi::FrameOpSuccess;
1694 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1696 case QRhiTexture::RGBA8:
1697 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1698 case QRhiTexture::BGRA8:
1699 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1700 case QRhiTexture::R8:
1701 return DXGI_FORMAT_R8_UNORM;
1702 case QRhiTexture::R8SI:
1703 return DXGI_FORMAT_R8_SINT;
1704 case QRhiTexture::R8UI:
1705 return DXGI_FORMAT_R8_UINT;
1706 case QRhiTexture::RG8:
1707 return DXGI_FORMAT_R8G8_UNORM;
1708 case QRhiTexture::R16:
1709 return DXGI_FORMAT_R16_UNORM;
1710 case QRhiTexture::RG16:
1711 return DXGI_FORMAT_R16G16_UNORM;
1712 case QRhiTexture::RED_OR_ALPHA8:
1713 return DXGI_FORMAT_R8_UNORM;
1715 case QRhiTexture::RGBA16F:
1716 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1717 case QRhiTexture::RGBA32F:
1718 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1719 case QRhiTexture::R16F:
1720 return DXGI_FORMAT_R16_FLOAT;
1721 case QRhiTexture::R32F:
1722 return DXGI_FORMAT_R32_FLOAT;
1724 case QRhiTexture::RGB10A2:
1725 return DXGI_FORMAT_R10G10B10A2_UNORM;
1727 case QRhiTexture::R32SI:
1728 return DXGI_FORMAT_R32_SINT;
1729 case QRhiTexture::R32UI:
1730 return DXGI_FORMAT_R32_UINT;
1731 case QRhiTexture::RG32SI:
1732 return DXGI_FORMAT_R32G32_SINT;
1733 case QRhiTexture::RG32UI:
1734 return DXGI_FORMAT_R32G32_UINT;
1735 case QRhiTexture::RGBA32SI:
1736 return DXGI_FORMAT_R32G32B32A32_SINT;
1737 case QRhiTexture::RGBA32UI:
1738 return DXGI_FORMAT_R32G32B32A32_UINT;
1740 case QRhiTexture::D16:
1741 return DXGI_FORMAT_R16_TYPELESS;
1742 case QRhiTexture::D24:
1743 return DXGI_FORMAT_R24G8_TYPELESS;
1744 case QRhiTexture::D24S8:
1745 return DXGI_FORMAT_R24G8_TYPELESS;
1746 case QRhiTexture::D32F:
1747 return DXGI_FORMAT_R32_TYPELESS;
1748 case QRhiTexture::D32FS8:
1749 return DXGI_FORMAT_R32G8X24_TYPELESS;
1751 case QRhiTexture::BC1:
1752 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1753 case QRhiTexture::BC2:
1754 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1755 case QRhiTexture::BC3:
1756 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1757 case QRhiTexture::BC4:
1758 return DXGI_FORMAT_BC4_UNORM;
1759 case QRhiTexture::BC5:
1760 return DXGI_FORMAT_BC5_UNORM;
1761 case QRhiTexture::BC6H:
1762 return DXGI_FORMAT_BC6H_UF16;
1763 case QRhiTexture::BC7:
1764 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1766 case QRhiTexture::ETC2_RGB8:
1767 case QRhiTexture::ETC2_RGB8A1:
1768 case QRhiTexture::ETC2_RGBA8:
1769 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1770 return DXGI_FORMAT_R8G8B8A8_UNORM;
1772 case QRhiTexture::ASTC_4x4:
1773 case QRhiTexture::ASTC_5x4:
1774 case QRhiTexture::ASTC_5x5:
1775 case QRhiTexture::ASTC_6x5:
1776 case QRhiTexture::ASTC_6x6:
1777 case QRhiTexture::ASTC_8x5:
1778 case QRhiTexture::ASTC_8x6:
1779 case QRhiTexture::ASTC_8x8:
1780 case QRhiTexture::ASTC_10x5:
1781 case QRhiTexture::ASTC_10x6:
1782 case QRhiTexture::ASTC_10x8:
1783 case QRhiTexture::ASTC_10x10:
1784 case QRhiTexture::ASTC_12x10:
1785 case QRhiTexture::ASTC_12x12:
1786 qWarning(
"QRhiD3D11 does not support ASTC textures");
1787 return DXGI_FORMAT_R8G8B8A8_UNORM;
1791 return DXGI_FORMAT_R8G8B8A8_UNORM;
1798 case DXGI_FORMAT_R8G8B8A8_UNORM:
1799 return QRhiTexture::RGBA8;
1800 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1802 (*flags) |= QRhiTexture::sRGB;
1803 return QRhiTexture::RGBA8;
1804 case DXGI_FORMAT_B8G8R8A8_UNORM:
1805 return QRhiTexture::BGRA8;
1806 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1808 (*flags) |= QRhiTexture::sRGB;
1809 return QRhiTexture::BGRA8;
1810 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1811 return QRhiTexture::RGBA16F;
1812 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1813 return QRhiTexture::RGBA32F;
1814 case DXGI_FORMAT_R10G10B10A2_UNORM:
1815 return QRhiTexture::RGB10A2;
1817 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1820 return QRhiTexture::UnknownFormat;
1826 case QRhiTexture::Format::D16:
1827 case QRhiTexture::Format::D24:
1828 case QRhiTexture::Format::D24S8:
1829 case QRhiTexture::Format::D32F:
1830 case QRhiTexture::Format::D32FS8:
1843 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1845 ofr.cbWrapper.resetCommands();
1856 return QRhi::FrameOpSuccess;
1860 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1862 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1863 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1865 box.front = is3D ? UINT(layer) : 0u;
1867 box.back = box.front + 1;
1870 cmd.args.updateSubRes.dst = texD->textureResource();
1871 cmd.args.updateSubRes.dstSubRes = subres;
1873 const QPoint dp = subresDesc.destinationTopLeft();
1874 if (!subresDesc.image().isNull()) {
1875 QImage img = subresDesc.image();
1876 QSize size = img.size();
1877 int bpl = img.bytesPerLine();
1878 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1879 const QPoint sp = subresDesc.sourceTopLeft();
1880 if (!subresDesc.sourceSize().isEmpty())
1881 size = subresDesc.sourceSize();
1882 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1883 if (img.depth() == 32) {
1884 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1885 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1887 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1888 bpl = img.bytesPerLine();
1889 cmd.args.updateSubRes.src = cbD->retainImage(img);
1892 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1893 cmd.args.updateSubRes.src = cbD->retainImage(img);
1895 box.left = UINT(dp.x());
1896 box.top = UINT(dp.y());
1897 box.right = UINT(dp.x() + size.width());
1898 box.bottom = UINT(dp.y() + size.height());
1899 cmd.args.updateSubRes.hasDstBox =
true;
1900 cmd.args.updateSubRes.dstBox = box;
1901 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1902 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1903 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1904 : subresDesc.sourceSize();
1907 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1911 box.left = UINT(aligned(dp.x(), blockDim.width()));
1912 box.top = UINT(aligned(dp.y(), blockDim.height()));
1913 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1914 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1915 cmd.args.updateSubRes.hasDstBox =
true;
1916 cmd.args.updateSubRes.dstBox = box;
1917 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1918 cmd.args.updateSubRes.srcRowPitch = bpl;
1919 }
else if (!subresDesc.data().isEmpty()) {
1920 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1921 : subresDesc.sourceSize();
1923 if (subresDesc.dataStride())
1924 bpl = subresDesc.dataStride();
1926 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1927 box.left = UINT(dp.x());
1928 box.top = UINT(dp.y());
1929 box.right = UINT(dp.x() + size.width());
1930 box.bottom = UINT(dp.y() + size.height());
1931 cmd.args.updateSubRes.hasDstBox =
true;
1932 cmd.args.updateSubRes.dstBox = box;
1933 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1934 cmd.args.updateSubRes.srcRowPitch = bpl;
1936 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1937 cbD->commands.unget();
1950 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1955 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1956 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1959 cmd.args.updateSubRes.dst = bufD->buffer;
1960 cmd.args.updateSubRes.dstSubRes = 0;
1961 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1962 cmd.args.updateSubRes.srcRowPitch = 0;
1967 box.left = u.offset;
1968 box.top = box.front = 0;
1969 box.back = box.bottom = 1;
1970 box.right = u.offset + u
.data.size();
1971 cmd.args.updateSubRes.hasDstBox =
true;
1972 cmd.args.updateSubRes.dstBox = box;
1975 if (bufD->m_type == QRhiBuffer::Dynamic) {
1976 u.result->data.resize(u.readSize);
1977 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1978 if (u.result->completed)
1979 u.result->completed();
1982 readback.result = u.result;
1983 readback.byteSize = u.readSize;
1985 D3D11_BUFFER_DESC desc = {};
1986 desc.ByteWidth = readback.byteSize;
1987 desc.Usage = D3D11_USAGE_STAGING;
1988 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1989 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1991 qWarning(
"Failed to create buffer: %s",
1992 qPrintable(QSystemError::windowsComString(hr)));
1998 cmd.args.copySubRes.dst = readback.stagingBuf;
1999 cmd.args.copySubRes.dstSubRes = 0;
2000 cmd.args.copySubRes.dstX = 0;
2001 cmd.args.copySubRes.dstY = 0;
2002 cmd.args.copySubRes.dstZ = 0;
2003 cmd.args.copySubRes.src = bufD->buffer;
2004 cmd.args.copySubRes.srcSubRes = 0;
2005 cmd.args.copySubRes.hasSrcBox =
true;
2007 box.left = u.offset;
2008 box.top = box.front = 0;
2009 box.back = box.bottom = 1;
2010 box.right = u.offset + u.readSize;
2011 cmd.args.copySubRes.srcBox = box;
2013 activeBufferReadbacks.append(readback);
2021 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2022 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2023 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2024 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2031 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2032 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2033 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2034 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2035 const QPoint dp = u.desc.destinationTopLeft();
2036 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2037 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2038 const QPoint sp = u.desc.sourceTopLeft();
2040 srcBox.left = UINT(sp.x());
2041 srcBox.top = UINT(sp.y());
2042 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2044 srcBox.right = srcBox.left + UINT(copySize.width());
2045 srcBox.bottom = srcBox.top + UINT(copySize.height());
2046 srcBox.back = srcBox.front + 1;
2049 cmd.args.copySubRes.dst = dstD->textureResource();
2050 cmd.args.copySubRes.dstSubRes = dstSubRes;
2051 cmd.args.copySubRes.dstX = UINT(dp.x());
2052 cmd.args.copySubRes.dstY = UINT(dp.y());
2053 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2054 cmd.args.copySubRes.src = srcD->textureResource();
2055 cmd.args.copySubRes.srcSubRes = srcSubRes;
2056 cmd.args.copySubRes.hasSrcBox =
true;
2057 cmd.args.copySubRes.srcBox = srcBox;
2060 readback.desc = u.rb;
2061 readback.result = u.result;
2063 ID3D11Resource *src;
2064 DXGI_FORMAT dxgiFormat;
2066 QRhiTexture::Format format;
2073 if (texD->sampleDesc.Count > 1) {
2074 qWarning(
"Multisample texture cannot be read back");
2077 src = texD->textureResource();
2078 dxgiFormat = texD->dxgiFormat;
2079 if (u.rb.rect().isValid())
2082 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2083 format = texD->m_format;
2084 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2085 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2089 if (swapChainD->sampleDesc.Count > 1) {
2094 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2095 rcmd.args.resolveSubRes.dstSubRes = 0;
2097 rcmd.args.resolveSubRes.srcSubRes = 0;
2098 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2100 src = swapChainD->backBufferTex;
2101 dxgiFormat = swapChainD->colorFormat;
2102 if (u.rb.rect().isValid())
2105 rect = QRect({0, 0}, swapChainD->pixelSize);
2106 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2107 if (format == QRhiTexture::UnknownFormat)
2110 quint32 byteSize = 0;
2112 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2114 D3D11_TEXTURE2D_DESC desc = {};
2115 desc.Width = UINT(rect.width());
2116 desc.Height = UINT(rect.height());
2119 desc.Format = dxgiFormat;
2120 desc.SampleDesc.Count = 1;
2121 desc.Usage = D3D11_USAGE_STAGING;
2122 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2123 ID3D11Texture2D *stagingTex;
2124 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2126 qWarning(
"Failed to create readback staging texture: %s",
2127 qPrintable(QSystemError::windowsComString(hr)));
2133 cmd.args.copySubRes.dst = stagingTex;
2134 cmd.args.copySubRes.dstSubRes = 0;
2135 cmd.args.copySubRes.dstX = 0;
2136 cmd.args.copySubRes.dstY = 0;
2137 cmd.args.copySubRes.dstZ = 0;
2138 cmd.args.copySubRes.src = src;
2139 cmd.args.copySubRes.srcSubRes = subres;
2141 D3D11_BOX srcBox = {};
2142 srcBox.left = UINT(rect.left());
2143 srcBox.top = UINT(rect.top());
2144 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2146 srcBox.right = srcBox.left + desc.Width;
2147 srcBox.bottom = srcBox.top + desc.Height;
2148 srcBox.back = srcBox.front + 1;
2149 cmd.args.copySubRes.hasSrcBox =
true;
2150 cmd.args.copySubRes.srcBox = srcBox;
2152 readback.stagingTex = stagingTex;
2153 readback.byteSize = byteSize;
2155 readback.pixelSize = rect.size();
2156 readback.format = format;
2158 activeTextureReadbacks.append(readback);
2160 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2163 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2172 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2174 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2176 readback.result->format = readback.format;
2177 readback.result->pixelSize = readback.pixelSize;
2179 D3D11_MAPPED_SUBRESOURCE mp;
2180 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2181 if (SUCCEEDED(hr)) {
2182 readback.result->data.resize(
int(readback.byteSize));
2185 char *dst = readback.result->data.data();
2186 char *src =
static_cast<
char *>(mp.pData);
2187 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2188 memcpy(dst, src, readback.bpl);
2189 dst += readback.bpl;
2192 context->Unmap(readback.stagingTex, 0);
2194 qWarning(
"Failed to map readback staging texture: %s",
2195 qPrintable(QSystemError::windowsComString(hr)));
2198 readback.stagingTex->Release();
2200 if (readback.result->completed)
2201 completedCallbacks.append(readback.result->completed);
2203 activeTextureReadbacks.removeLast();
2206 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2209 D3D11_MAPPED_SUBRESOURCE mp;
2210 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2211 if (SUCCEEDED(hr)) {
2212 readback.result->data.resize(
int(readback.byteSize));
2213 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2214 context->Unmap(readback.stagingBuf, 0);
2216 qWarning(
"Failed to map readback staging texture: %s",
2217 qPrintable(QSystemError::windowsComString(hr)));
2220 readback.stagingBuf->Release();
2222 if (readback.result->completed)
2223 completedCallbacks.append(readback.result->completed);
2225 activeBufferReadbacks.removeLast();
2228 for (
auto f : completedCallbacks)
2234 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2240 QRhiRenderTarget *rt,
2241 const QColor &colorClearValue,
2242 const QRhiDepthStencilClearValue &depthStencilClearValue,
2243 QRhiResourceUpdateBatch *resourceUpdates,
2249 if (resourceUpdates)
2252 bool wantsColorClear =
true;
2253 bool wantsDsClear =
true;
2255 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2257 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2258 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2259 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2267 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2271 clearCmd.args.clear.rtViews = rtD->views;
2272 clearCmd.args.clear.mask = 0;
2273 if (rtD->views.colorAttCount && wantsColorClear)
2275 if (rtD->views.dsv && wantsDsClear)
2278 clearCmd.args.clear.c[0] = colorClearValue.redF();
2279 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2280 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2281 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2282 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2283 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2286 cbD->currentTarget = rt;
2296 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2298 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2301 const QRhiColorAttachment &colorAtt(*it);
2302 if (!colorAtt.resolveTexture())
2308 Q_ASSERT(srcTexD || srcRbD);
2311 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2312 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2313 UINT(colorAtt.resolveLayer()),
2314 dstTexD->mipLevelCount);
2316 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2317 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2318 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2319 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2320 cbD->commands.unget();
2323 if (srcTexD->sampleDesc.Count <= 1) {
2324 qWarning(
"Cannot resolve a non-multisample texture");
2325 cbD->commands.unget();
2328 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2329 qWarning(
"Resolve source and destination sizes do not match");
2330 cbD->commands.unget();
2334 cmd.args.resolveSubRes.src = srcRbD->tex;
2335 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2336 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2337 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2338 cbD->commands.unget();
2341 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2342 qWarning(
"Resolve source and destination sizes do not match");
2343 cbD->commands.unget();
2347 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2348 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2350 if (rtTex->m_desc.depthResolveTexture())
2351 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2355 cbD->currentTarget =
nullptr;
2357 if (resourceUpdates)
2362 QRhiResourceUpdateBatch *resourceUpdates,
2368 if (resourceUpdates)
2376 fbCmd.args.setRenderTarget.rtViews.reset();
2393 if (resourceUpdates)
2402 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2404 if (pipelineChanged) {
2405 cbD->currentGraphicsPipeline =
nullptr;
2406 cbD->currentComputePipeline = psD;
2407 cbD->currentPipelineGeneration = psD->generation;
2411 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2422 cmd.args.dispatch.x = UINT(x);
2423 cmd.args.dispatch.y = UINT(y);
2424 cmd.args.dispatch.z = UINT(z);
2429 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2431 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2432 if (!map || map->isEmpty())
2433 return { binding, binding };
2435 auto it = map->constFind(binding);
2436 if (it != map->cend())
2446 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2448 srbD->resourceBatches.clear();
2454 ID3D11Buffer *buffer;
2455 uint offsetInConstants;
2456 uint sizeInConstants;
2460 ID3D11ShaderResourceView *srv;
2464 ID3D11SamplerState *sampler;
2468 ID3D11UnorderedAccessView *uav;
2470 QVarLengthArray<Buffer, 8> buffers;
2471 QVarLengthArray<Texture, 8> textures;
2472 QVarLengthArray<Sampler, 8> samplers;
2473 QVarLengthArray<Uav, 8> uavs;
2476 for (
const Buffer &buf : buffers) {
2477 batches.ubufs.feed(buf.breg, buf.buffer);
2478 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2479 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2480 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2486 for (
const Texture &t : textures)
2487 batches.shaderresources.feed(t.treg, t.srv);
2488 for (
const Sampler &s : samplers)
2489 batches.samplers.feed(s.sreg, s.sampler);
2494 for (
const Stage::Uav &u : uavs)
2495 batches.uavs.feed(u.ureg, u.uav);
2500 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2501 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2504 case QRhiShaderResourceBinding::UniformBuffer:
2507 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2508 bd.ubuf.id = bufD->m_id;
2509 bd.ubuf.generation = bufD->generation;
2516 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2520 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2521 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2522 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2523 if (nativeBinding.first >= 0)
2524 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2526 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2527 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2528 if (nativeBinding.first >= 0)
2529 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2531 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2532 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2533 if (nativeBinding.first >= 0)
2534 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2536 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2537 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2538 if (nativeBinding.first >= 0)
2539 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2541 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2542 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2543 if (nativeBinding.first >= 0)
2544 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2546 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2547 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2548 if (nativeBinding.first >= 0)
2549 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2553 case QRhiShaderResourceBinding::SampledTexture:
2554 case QRhiShaderResourceBinding::Texture:
2555 case QRhiShaderResourceBinding::Sampler:
2557 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2558 bd.stex.count = data->count;
2559 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2560 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2561 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2562 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2563 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2564 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2568 for (
int elem = 0; elem < data->count; ++elem) {
2571 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2572 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2573 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2574 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2579 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2580 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2581 : (samplerD ? nativeBindingVert.first : -1);
2582 if (nativeBindingVert.first >= 0 && texD)
2583 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2584 if (samplerBinding >= 0)
2585 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2587 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2588 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2589 : (samplerD ? nativeBindingHull.first : -1);
2590 if (nativeBindingHull.first >= 0 && texD)
2591 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2592 if (samplerBinding >= 0)
2593 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2595 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2596 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2597 : (samplerD ? nativeBindingDomain.first : -1);
2598 if (nativeBindingDomain.first >= 0 && texD)
2599 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2600 if (samplerBinding >= 0)
2601 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2603 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2604 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2605 : (samplerD ? nativeBindingGeom.first : -1);
2606 if (nativeBindingGeom.first >= 0 && texD)
2607 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2608 if (samplerBinding >= 0)
2609 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2611 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2612 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2613 : (samplerD ? nativeBindingFrag.first : -1);
2614 if (nativeBindingFrag.first >= 0 && texD)
2615 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2616 if (samplerBinding >= 0)
2617 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2619 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2620 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2621 : (samplerD ? nativeBindingComp.first : -1);
2622 if (nativeBindingComp.first >= 0 && texD)
2623 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2624 if (samplerBinding >= 0)
2625 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2630 case QRhiShaderResourceBinding::ImageLoad:
2631 case QRhiShaderResourceBinding::ImageStore:
2632 case QRhiShaderResourceBinding::ImageLoadStore:
2635 bd.simage.id = texD->m_id;
2636 bd.simage.generation = texD->generation;
2637 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2638 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2639 if (nativeBinding.first >= 0) {
2640 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2642 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2644 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2645 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2646 if (nativeBinding.first >= 0) {
2647 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2649 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2652 qWarning(
"Unordered access only supported at fragment/compute stage");
2656 case QRhiShaderResourceBinding::BufferLoad:
2657 case QRhiShaderResourceBinding::BufferStore:
2658 case QRhiShaderResourceBinding::BufferLoadStore:
2661 bd.sbuf.id = bufD->m_id;
2662 bd.sbuf.generation = bufD->generation;
2663 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2664 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2665 if (nativeBinding.first >= 0) {
2666 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2668 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2671 qWarning(
"Unordered access only supported at compute stage");
2686 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2687 return a.breg < b.breg;
2689 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2690 return a.treg < b.treg;
2692 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2693 return a.sreg < b.sreg;
2695 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2696 return a.ureg < b.ureg;
2700 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2701 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2702 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2703 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2704 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2705 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2707 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2708 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2709 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2710 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2711 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2712 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2714 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2715 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2723 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2725 D3D11_MAPPED_SUBRESOURCE mp;
2726 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2727 if (SUCCEEDED(hr)) {
2728 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2729 context->Unmap(bufD->buffer, 0);
2731 qWarning(
"Failed to map buffer: %s",
2732 qPrintable(QSystemError::windowsComString(hr)));
2738 const QRhiBatchedBindings<UINT> *originalBindings,
2739 const QRhiBatchedBindings<UINT> *staticOffsets,
2740 const uint *dynOfsPairs,
int dynOfsPairCount)
2742 const int count = staticOffsets->batches[batchIndex].resources.count();
2745 for (
int b = 0; b < count; ++b) {
2746 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2747 for (
int di = 0; di < dynOfsPairCount; ++di) {
2748 const uint binding = dynOfsPairs[2 * di];
2751 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2752 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2753 offsets[b] = offsetInConstants;
2762 if (startSlot + countSlots > maxSlots) {
2763 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2764 resType, countSlots, startSlot, maxSlots);
2765 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2770#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2771 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2772 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2773 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2774 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2775 batches.ubufs.batches[i].resources.count(),
2776 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2777 #stagePrefixU " cbuf");
2779 if (!dynOfsPairCount) {
2780 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2782 batches.ubufs.batches[i].resources.constData(),
2783 batches.ubufoffsets.batches[i].resources.constData(),
2784 batches.ubufsizes.batches[i].resources.constData());
2786 applyDynamicOffsets(offsets, i,
2787 &batches.ubuforigbindings, &batches.ubufoffsets,
2788 dynOfsPairs, dynOfsPairCount);
2789 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2791 batches.ubufs.batches[i].resources.constData(),
2793 batches.ubufsizes.batches[i].resources.constData());
2799#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2800 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2801 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2802 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2803 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2805 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2807 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2808 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2809 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2811 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2812 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2813 int(batch.startBinding + count) - 1
);
2818#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2819 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2820 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2821 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2824 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2826 batch.resources.constData(),
2828 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2829 int(batch.startBinding + count) - 1
);
2836 const uint *dynOfsPairs,
int dynOfsPairCount,
2837 bool offsetOnlyChange,
2849 if (!offsetOnlyChange) {
2859 if (allResourceBatches.fsUavBatches.present) {
2860 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2861 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2863 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2865 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
2866 context->OMSetRenderTargetsAndUnorderedAccessViews(
2867 UINT(rtUavState->rtViews.colorAttCount),
2868 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
2869 rtUavState->rtViews.dsv,
2870 UINT(batch.startBinding),
2872 batch.resources.constData(),
2875 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2876 int(batch.startBinding + count) - 1);
2889 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2895 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2896 for (
int i = 0; i < count; ++i)
2897 nullbufs[i] =
nullptr;
2898 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2899 for (
int i = 0; i < count; ++i)
2901 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2902 for (
int i = 0; i < count; ++i)
2904 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2914 if (nullsrvCount > 0) {
2915 QVarLengthArray<ID3D11ShaderResourceView *,
2916 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2917 for (
int i = 0; i < nullsrvs.count(); ++i)
2918 nullsrvs[i] =
nullptr;
2920 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2924 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2928 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2932 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2936 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2940 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2946 rtUavState->update(cbD->currentRenderTargetViews);
2947 context->OMSetRenderTargetsAndUnorderedAccessViews(
2948 UINT(cbD->currentRenderTargetViews.colorAttCount),
2949 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
2950 cbD->currentRenderTargetViews.dsv,
2951 0, 0,
nullptr,
nullptr);
2956 QVarLengthArray<ID3D11UnorderedAccessView *,
2957 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2958 for (
int i = 0; i < nulluavCount; ++i)
2959 nulluavs[i] =
nullptr;
2960 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2965#define SETSHADER(StageL, StageU)
2966 if (cmd.args.bindGraphicsPipeline.StageL) {
2967 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
2968 currentShaderMask |= StageU##MaskBit;
2969 } else if (currentShaderMask & StageU##MaskBit) {
2970 context->StageU##SetShader(nullptr, nullptr, 0
);
2971 currentShaderMask &= ~StageU##MaskBit;
2976 quint32 stencilRef = 0;
2977 float blendConstants[] = { 1, 1, 1, 1 };
2978 enum ActiveShaderMask {
2985 int currentShaderMask = 0xFF;
2991 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2994 case QD3D11CommandBuffer::Command::BeginFrame:
2995 if (cmd.args.beginFrame.tsDisjointQuery)
2996 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2997 if (cmd.args.beginFrame.tsQuery) {
2998 if (cmd.args.beginFrame.swapchainRtv) {
3003 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3004 rtUavState.update(cbD->currentRenderTargetViews);
3005 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3007 context->End(cmd.args.beginFrame.tsQuery);
3010 case QD3D11CommandBuffer::Command::EndFrame:
3011 if (cmd.args.endFrame.tsQuery)
3012 context->End(cmd.args.endFrame.tsQuery);
3013 if (cmd.args.endFrame.tsDisjointQuery)
3014 context->End(cmd.args.endFrame.tsDisjointQuery);
3021 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3022 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3023 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3024 context->OMSetRenderTargets(colorAttCount,
3025 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3026 cmd.args.setRenderTarget.rtViews.dsv);
3033 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3034 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3037 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3038 ds |= D3D11_CLEAR_DEPTH;
3039 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3040 ds |= D3D11_CLEAR_STENCIL;
3041 if (ds && cmd.args.clear.rtViews.dsv)
3042 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3048 v.TopLeftX = cmd.args.viewport.x;
3049 v.TopLeftY = cmd.args.viewport.y;
3050 v.Width = cmd.args.viewport.w;
3051 v.Height = cmd.args.viewport.h;
3052 v.MinDepth = cmd.args.viewport.d0;
3053 v.MaxDepth = cmd.args.viewport.d1;
3054 context->RSSetViewports(1, &v);
3060 r.left = cmd.args.scissor.x;
3061 r.top = cmd.args.scissor.y;
3063 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3064 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3065 context->RSSetScissorRects(1, &r);
3071 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3072 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3073 UINT(cmd.args.bindVertexBuffers.slotCount),
3074 cmd.args.bindVertexBuffers.buffers,
3075 cmd.args.bindVertexBuffers.strides,
3076 cmd.args.bindVertexBuffers.offsets);
3080 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3081 cmd.args.bindIndexBuffer.format,
3082 cmd.args.bindIndexBuffer.offset);
3091 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3092 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3093 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3094 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3095 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3098 case QD3D11CommandBuffer::Command::BindShaderResources:
3099 bindShaderResources(cbD,
3100 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3101 cmd.args.bindShaderResources.dynamicOffsetPairs,
3102 cmd.args.bindShaderResources.dynamicOffsetCount,
3103 cmd.args.bindShaderResources.offsetOnlyChange,
3107 stencilRef = cmd.args.stencilRef.ref;
3108 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3111 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3112 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3114 case QD3D11CommandBuffer::Command::Draw:
3115 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3116 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3118 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3119 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3121 case QD3D11CommandBuffer::Command::DrawIndexed:
3122 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3123 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3124 cmd.args.drawIndexed.vertexOffset);
3126 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3127 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3128 cmd.args.drawIndexed.firstInstance);
3132 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3133 const UINT stride = cmd.args.drawIndirect.stride;
3134 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3135 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3136 alignedByteOffsetForArgs += stride;
3142 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3143 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3144 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3145 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3146 alignedByteOffsetForArgs += stride;
3150 case QD3D11CommandBuffer::Command::UpdateSubRes:
3151 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3152 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3153 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3155 case QD3D11CommandBuffer::Command::CopySubRes:
3156 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3157 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3158 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3159 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3161 case QD3D11CommandBuffer::Command::ResolveSubRes:
3162 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3163 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3164 cmd.args.resolveSubRes.format);
3166 case QD3D11CommandBuffer::Command::GenMip:
3167 context->GenerateMips(cmd.args.genMip.srv);
3169 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3170 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3172 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3173 annotations->EndEvent();
3175 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3176 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3178 case QD3D11CommandBuffer::Command::BindComputePipeline:
3179 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3181 case QD3D11CommandBuffer::Command::Dispatch:
3182 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3211 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3212 it.value()->Release();
3217 rhiD->unregisterResource(
this);
3223 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3224 u |= D3D11_BIND_VERTEX_BUFFER;
3225 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3226 u |= D3D11_BIND_INDEX_BUFFER;
3227 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3228 u |= D3D11_BIND_CONSTANT_BUFFER;
3229 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3230 u |= D3D11_BIND_UNORDERED_ACCESS;
3239 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3240 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3244 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3245 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3249 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3250 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3254 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3255 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3257 D3D11_BUFFER_DESC desc = {};
3258 desc.ByteWidth = roundedSize;
3259 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3260 desc.BindFlags = toD3DBufferUsage(m_usage);
3261 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3262 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3263 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3264 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3267 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3269 qWarning(
"Failed to create buffer: %s",
3270 qPrintable(QSystemError::windowsComString(hr)));
3274 if (m_type == Dynamic) {
3275 dynBuf =
new char[nonZeroSize];
3279 if (!m_objectName.isEmpty())
3280 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3283 rhiD->registerResource(
this);
3289 if (m_type == Dynamic) {
3293 return { { &buffer }, 1 };
3304 Q_ASSERT(m_type == Dynamic);
3305 D3D11_MAPPED_SUBRESOURCE mp;
3307 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3309 qWarning(
"Failed to map buffer: %s",
3310 qPrintable(QSystemError::windowsComString(hr)));
3313 return static_cast<
char *>(mp.pData);
3319 rhiD->context->Unmap(buffer, 0);
3324 auto it = uavs.find(offset);
3325 if (it != uavs.end())
3329 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3330 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3331 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3332 desc.Buffer.FirstElement = offset / 4u;
3333 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3334 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3337 ID3D11UnorderedAccessView *uav =
nullptr;
3338 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3340 qWarning(
"Failed to create UAV: %s",
3341 qPrintable(QSystemError::windowsComString(hr)));
3350 int sampleCount, QRhiRenderBuffer::Flags flags,
3351 QRhiTexture::Format backingFormatHint)
3381 rhiD->unregisterResource(
this);
3389 if (m_pixelSize.isEmpty())
3393 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3395 D3D11_TEXTURE2D_DESC desc = {};
3396 desc.Width = UINT(m_pixelSize.width());
3397 desc.Height = UINT(m_pixelSize.height());
3400 desc.SampleDesc = sampleDesc;
3401 desc.Usage = D3D11_USAGE_DEFAULT;
3403 if (m_type == Color) {
3404 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3405 : toD3DTextureFormat(m_backingFormatHint, {});
3406 desc.Format = dxgiFormat;
3407 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3408 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3410 qWarning(
"Failed to create color renderbuffer: %s",
3411 qPrintable(QSystemError::windowsComString(hr)));
3414 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3415 rtvDesc.Format = dxgiFormat;
3416 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3417 : D3D11_RTV_DIMENSION_TEXTURE2D;
3418 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3420 qWarning(
"Failed to create rtv: %s",
3421 qPrintable(QSystemError::windowsComString(hr)));
3424 }
else if (m_type == DepthStencil) {
3425 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3426 desc.Format = dxgiFormat;
3427 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3428 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3430 qWarning(
"Failed to create depth-stencil buffer: %s",
3431 qPrintable(QSystemError::windowsComString(hr)));
3434 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3435 dsvDesc.Format = dxgiFormat;
3436 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3437 : D3D11_DSV_DIMENSION_TEXTURE2D;
3438 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3440 qWarning(
"Failed to create dsv: %s",
3441 qPrintable(QSystemError::windowsComString(hr)));
3448 if (!m_objectName.isEmpty())
3449 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3452 rhiD->registerResource(
this);
3458 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3459 return m_backingFormatHint;
3461 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3465 int arraySize,
int sampleCount, Flags flags)
3468 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3469 perLevelViews[i] =
nullptr;
3479 if (!tex && !tex3D && !tex1D)
3487 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3488 if (perLevelViews[i]) {
3489 perLevelViews[i]->Release();
3490 perLevelViews[i] =
nullptr;
3509 rhiD->unregisterResource(
this);
3515 case QRhiTexture::Format::D16:
3516 return DXGI_FORMAT_R16_FLOAT;
3517 case QRhiTexture::Format::D24:
3518 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3519 case QRhiTexture::Format::D24S8:
3520 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3521 case QRhiTexture::Format::D32F:
3522 return DXGI_FORMAT_R32_FLOAT;
3523 case QRhiTexture::Format::D32FS8:
3524 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3527 return DXGI_FORMAT_R32_FLOAT;
3534 case QRhiTexture::Format::D16:
3535 return DXGI_FORMAT_D16_UNORM;
3536 case QRhiTexture::Format::D24:
3537 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3538 case QRhiTexture::Format::D24S8:
3539 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3540 case QRhiTexture::Format::D32F:
3541 return DXGI_FORMAT_D32_FLOAT;
3542 case QRhiTexture::Format::D32FS8:
3543 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3546 return DXGI_FORMAT_D32_FLOAT;
3552 if (tex || tex3D || tex1D)
3556 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3559 const bool isDepth = isDepthTextureFormat(m_format);
3560 const bool isCube = m_flags.testFlag(CubeMap);
3561 const bool is3D = m_flags.testFlag(ThreeDimensional);
3562 const bool isArray = m_flags.testFlag(TextureArray);
3563 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3564 const bool is1D = m_flags.testFlag(OneDimensional);
3566 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3567 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3569 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3570 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3571 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3572 if (sampleDesc.Count > 1) {
3574 qWarning(
"Cubemap texture cannot be multisample");
3578 qWarning(
"3D texture cannot be multisample");
3582 qWarning(
"Multisample texture cannot have mipmaps");
3586 if (isDepth && hasMipMaps) {
3587 qWarning(
"Depth texture cannot have mipmaps");
3590 if (isCube && is3D) {
3591 qWarning(
"Texture cannot be both cube and 3D");
3594 if (isArray && is3D) {
3595 qWarning(
"Texture cannot be both array and 3D");
3598 if (isCube && is1D) {
3599 qWarning(
"Texture cannot be both cube and 1D");
3603 qWarning(
"Texture cannot be both 1D and 3D");
3606 if (m_depth > 1 && !is3D) {
3607 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3610 if (m_arraySize > 0 && !isArray) {
3611 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3614 if (m_arraySize < 1 && isArray) {
3615 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3620 *adjustedSize = size;
3628 const bool isDepth = isDepthTextureFormat(m_format);
3629 const bool isCube = m_flags.testFlag(CubeMap);
3630 const bool is3D = m_flags.testFlag(ThreeDimensional);
3631 const bool isArray = m_flags.testFlag(TextureArray);
3632 const bool is1D = m_flags.testFlag(OneDimensional);
3634 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3635 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3637 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3638 srvDesc.TextureCube.MipLevels = mipLevelCount;
3642 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3643 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3644 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3645 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3646 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3648 srvDesc.Texture1DArray.FirstArraySlice = 0;
3649 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3652 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3653 srvDesc.Texture1D.MipLevels = mipLevelCount;
3655 }
else if (isArray) {
3656 if (sampleDesc.Count > 1) {
3657 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3658 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3659 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3660 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3662 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3663 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3666 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3667 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3668 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3669 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3670 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3672 srvDesc.Texture2DArray.FirstArraySlice = 0;
3673 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3677 if (sampleDesc.Count > 1) {
3678 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3680 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3681 srvDesc.Texture3D.MipLevels = mipLevelCount;
3683 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3684 srvDesc.Texture2D.MipLevels = mipLevelCount;
3689 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3691 qWarning(
"Failed to create srv: %s",
3692 qPrintable(QSystemError::windowsComString(hr)));
3703 if (!prepareCreate(&size))
3706 const bool isDepth = isDepthTextureFormat(m_format);
3707 const bool isCube = m_flags.testFlag(CubeMap);
3708 const bool is3D = m_flags.testFlag(ThreeDimensional);
3709 const bool isArray = m_flags.testFlag(TextureArray);
3710 const bool is1D = m_flags.testFlag(OneDimensional);
3712 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3713 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3714 if (m_flags.testFlag(RenderTarget)) {
3716 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3718 bindFlags |= D3D11_BIND_RENDER_TARGET;
3720 if (m_flags.testFlag(UsedWithGenerateMips)) {
3722 qWarning(
"Depth texture cannot have mipmaps generated");
3725 bindFlags |= D3D11_BIND_RENDER_TARGET;
3726 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3728 if (m_flags.testFlag(UsedWithLoadStore))
3729 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3733 D3D11_TEXTURE1D_DESC desc = {};
3734 desc.Width = UINT(size.width());
3735 desc.MipLevels = mipLevelCount;
3736 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3737 desc.Format = dxgiFormat;
3738 desc.Usage = D3D11_USAGE_DEFAULT;
3739 desc.BindFlags = bindFlags;
3740 desc.MiscFlags = miscFlags;
3742 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3744 qWarning(
"Failed to create 1D texture: %s",
3745 qPrintable(QSystemError::windowsComString(hr)));
3748 if (!m_objectName.isEmpty())
3749 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3750 m_objectName.constData());
3752 D3D11_TEXTURE2D_DESC desc = {};
3753 desc.Width = UINT(size.width());
3754 desc.Height = UINT(size.height());
3755 desc.MipLevels = mipLevelCount;
3756 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3757 desc.Format = dxgiFormat;
3758 desc.SampleDesc = sampleDesc;
3759 desc.Usage = D3D11_USAGE_DEFAULT;
3760 desc.BindFlags = bindFlags;
3761 desc.MiscFlags = miscFlags;
3763 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3765 qWarning(
"Failed to create 2D texture: %s",
3766 qPrintable(QSystemError::windowsComString(hr)));
3769 if (!m_objectName.isEmpty())
3770 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3772 D3D11_TEXTURE3D_DESC desc = {};
3773 desc.Width = UINT(size.width());
3774 desc.Height = UINT(size.height());
3775 desc.Depth = UINT(qMax(1, m_depth));
3776 desc.MipLevels = mipLevelCount;
3777 desc.Format = dxgiFormat;
3778 desc.Usage = D3D11_USAGE_DEFAULT;
3779 desc.BindFlags = bindFlags;
3780 desc.MiscFlags = miscFlags;
3782 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3784 qWarning(
"Failed to create 3D texture: %s",
3785 qPrintable(QSystemError::windowsComString(hr)));
3788 if (!m_objectName.isEmpty())
3789 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3796 rhiD->registerResource(
this);
3805 if (!prepareCreate())
3808 if (m_flags.testFlag(ThreeDimensional))
3809 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3810 else if (m_flags.testFlags(OneDimensional))
3811 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3813 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3820 rhiD->registerResource(
this);
3826 return { quint64(textureResource()), 0 };
3831 if (perLevelViews[level])
3832 return perLevelViews[level];
3834 const bool isCube = m_flags.testFlag(CubeMap);
3835 const bool isArray = m_flags.testFlag(TextureArray);
3836 const bool is3D = m_flags.testFlag(ThreeDimensional);
3837 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3838 desc.Format = dxgiFormat;
3840 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3841 desc.Texture2DArray.MipSlice = UINT(level);
3842 desc.Texture2DArray.FirstArraySlice = 0;
3843 desc.Texture2DArray.ArraySize = 6;
3844 }
else if (isArray) {
3845 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3846 desc.Texture2DArray.MipSlice = UINT(level);
3847 desc.Texture2DArray.FirstArraySlice = 0;
3848 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3850 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3851 desc.Texture3D.MipSlice = UINT(level);
3852 desc.Texture3D.WSize = UINT(m_depth);
3854 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3855 desc.Texture2D.MipSlice = UINT(level);
3859 ID3D11UnorderedAccessView *uav =
nullptr;
3860 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3862 qWarning(
"Failed to create UAV: %s",
3863 qPrintable(QSystemError::windowsComString(hr)));
3867 perLevelViews[level] = uav;
3872 AddressMode u, AddressMode v, AddressMode w)
3887 samplerState->Release();
3888 samplerState =
nullptr;
3892 rhiD->unregisterResource(
this);
3895static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3897 if (minFilter == QRhiSampler::Nearest) {
3898 if (magFilter == QRhiSampler::Nearest) {
3899 if (mipFilter == QRhiSampler::Linear)
3900 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3902 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3904 if (mipFilter == QRhiSampler::Linear)
3905 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3907 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3910 if (magFilter == QRhiSampler::Nearest) {
3911 if (mipFilter == QRhiSampler::Linear)
3912 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3914 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3916 if (mipFilter == QRhiSampler::Linear)
3917 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3919 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3924 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3930 case QRhiSampler::Repeat:
3931 return D3D11_TEXTURE_ADDRESS_WRAP;
3932 case QRhiSampler::ClampToEdge:
3933 return D3D11_TEXTURE_ADDRESS_CLAMP;
3934 case QRhiSampler::Mirror:
3935 return D3D11_TEXTURE_ADDRESS_MIRROR;
3938 return D3D11_TEXTURE_ADDRESS_CLAMP;
3945 case QRhiSampler::Never:
3946 return D3D11_COMPARISON_NEVER;
3947 case QRhiSampler::Less:
3948 return D3D11_COMPARISON_LESS;
3949 case QRhiSampler::Equal:
3950 return D3D11_COMPARISON_EQUAL;
3951 case QRhiSampler::LessOrEqual:
3952 return D3D11_COMPARISON_LESS_EQUAL;
3953 case QRhiSampler::Greater:
3954 return D3D11_COMPARISON_GREATER;
3955 case QRhiSampler::NotEqual:
3956 return D3D11_COMPARISON_NOT_EQUAL;
3957 case QRhiSampler::GreaterOrEqual:
3958 return D3D11_COMPARISON_GREATER_EQUAL;
3959 case QRhiSampler::Always:
3960 return D3D11_COMPARISON_ALWAYS;
3963 return D3D11_COMPARISON_NEVER;
3972 D3D11_SAMPLER_DESC desc = {};
3973 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3974 if (m_compareOp != Never)
3975 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3976 desc.AddressU = toD3DAddressMode(m_addressU);
3977 desc.AddressV = toD3DAddressMode(m_addressV);
3978 desc.AddressW = toD3DAddressMode(m_addressW);
3979 desc.MaxAnisotropy = 1.0f;
3980 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3981 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3984 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3986 qWarning(
"Failed to create sampler state: %s",
3987 qPrintable(QSystemError::windowsComString(hr)));
3992 rhiD->registerResource(
this);
4011 rhiD->unregisterResource(
this);
4024 rhiD->registerResource(rpD,
false);
4061 return d.sampleCount;
4065 const QRhiTextureRenderTargetDescription &desc,
4083 if (!rtv[0] && !dsv)
4102 rhiD->unregisterResource(
this);
4109 rhiD->registerResource(rpD,
false);
4118 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4119 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4120 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4124 int colorAttCount = 0;
4126 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4128 const QRhiColorAttachment &colorAtt(*it);
4129 QRhiTexture *texture = colorAtt.texture();
4130 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4131 Q_ASSERT(texture || rb);
4134 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4135 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4136 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4137 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4138 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4139 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4140 rtvDesc.Texture2DArray.ArraySize = 1;
4141 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4142 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4143 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4144 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4145 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4146 rtvDesc.Texture1DArray.ArraySize = 1;
4148 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4149 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4151 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4152 if (texD->sampleDesc.Count > 1) {
4153 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4154 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4155 rtvDesc.Texture2DMSArray.ArraySize = 1;
4157 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4158 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4159 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4160 rtvDesc.Texture2DArray.ArraySize = 1;
4162 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4163 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4164 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4165 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4166 rtvDesc.Texture3D.WSize = 1;
4168 if (texD->sampleDesc.Count > 1) {
4169 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4171 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4172 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4175 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4177 qWarning(
"Failed to create rtv: %s",
4178 qPrintable(QSystemError::windowsComString(hr)));
4182 if (attIndex == 0) {
4183 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4184 d.sampleCount =
int(texD->sampleDesc.Count);
4189 rtv[attIndex] = rbD->rtv;
4190 if (attIndex == 0) {
4191 d.pixelSize = rbD->pixelSize();
4192 d.sampleCount =
int(rbD->sampleDesc.Count);
4198 if (hasDepthStencil) {
4199 if (m_desc.depthTexture()) {
4202 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4203 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4204 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4205 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4206 if (isMultisample) {
4207 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4208 if (m_desc.depthLayer() >= 0) {
4209 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4210 dsvDesc.Texture2DMSArray.ArraySize = 1;
4211 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4212 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4213 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4215 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4216 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4219 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4220 if (m_desc.depthLayer() >= 0) {
4221 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4222 dsvDesc.Texture2DArray.ArraySize = 1;
4223 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4224 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4225 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4227 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4228 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4233 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4234 : D3D11_DSV_DIMENSION_TEXTURE2D;
4236 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4238 qWarning(
"Failed to create dsv: %s",
4239 qPrintable(QSystemError::windowsComString(hr)));
4242 if (colorAttCount == 0) {
4243 d.pixelSize = depthTexD->pixelSize();
4244 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4249 dsv = depthRbD->dsv;
4250 if (colorAttCount == 0) {
4251 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4252 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4259 d.views.setFrom(colorAttCount, rtv, dsv);
4261 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4263 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4265 rhiD->registerResource(
this);
4271 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4284 return d.sampleCount;
4299 sortedBindings.clear();
4300 boundResourceData.clear();
4304 rhiD->unregisterResource(
this);
4309 if (!sortedBindings.isEmpty())
4313 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4316 rhiD->updateLayoutDesc(
this);
4318 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4319 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4321 boundResourceData.resize(sortedBindings.count());
4323 for (BoundResourceData &bd : boundResourceData)
4324 memset(&bd, 0,
sizeof(BoundResourceData));
4327 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4328 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4329 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4330 hasDynamicOffset =
true;
4336 rhiD->registerResource(
this,
false);
4342 sortedBindings.clear();
4343 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4344 if (!flags.testFlag(BindingsAreSorted))
4345 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4347 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4348 for (BoundResourceData &bd : boundResourceData)
4349 memset(&bd, 0,
sizeof(BoundResourceData));
4368 s.shader->Release();
4371 s.nativeResourceBindingMap.clear();
4383 blendState->Release();
4384 blendState =
nullptr;
4388 inputLayout->Release();
4389 inputLayout =
nullptr;
4393 rastState->Release();
4394 rastState =
nullptr;
4397 releasePipelineShader(vs);
4398 releasePipelineShader(hs);
4399 releasePipelineShader(ds);
4400 releasePipelineShader(gs);
4401 releasePipelineShader(fs);
4405 rhiD->unregisterResource(
this);
4411 case QRhiGraphicsPipeline::None:
4412 return D3D11_CULL_NONE;
4413 case QRhiGraphicsPipeline::Front:
4414 return D3D11_CULL_FRONT;
4415 case QRhiGraphicsPipeline::Back:
4416 return D3D11_CULL_BACK;
4419 return D3D11_CULL_NONE;
4426 case QRhiGraphicsPipeline::Fill:
4427 return D3D11_FILL_SOLID;
4428 case QRhiGraphicsPipeline::Line:
4429 return D3D11_FILL_WIREFRAME;
4432 return D3D11_FILL_SOLID;
4439 case QRhiGraphicsPipeline::Never:
4440 return D3D11_COMPARISON_NEVER;
4441 case QRhiGraphicsPipeline::Less:
4442 return D3D11_COMPARISON_LESS;
4443 case QRhiGraphicsPipeline::Equal:
4444 return D3D11_COMPARISON_EQUAL;
4445 case QRhiGraphicsPipeline::LessOrEqual:
4446 return D3D11_COMPARISON_LESS_EQUAL;
4447 case QRhiGraphicsPipeline::Greater:
4448 return D3D11_COMPARISON_GREATER;
4449 case QRhiGraphicsPipeline::NotEqual:
4450 return D3D11_COMPARISON_NOT_EQUAL;
4451 case QRhiGraphicsPipeline::GreaterOrEqual:
4452 return D3D11_COMPARISON_GREATER_EQUAL;
4453 case QRhiGraphicsPipeline::Always:
4454 return D3D11_COMPARISON_ALWAYS;
4457 return D3D11_COMPARISON_ALWAYS;
4464 case QRhiGraphicsPipeline::StencilZero:
4465 return D3D11_STENCIL_OP_ZERO;
4466 case QRhiGraphicsPipeline::Keep:
4467 return D3D11_STENCIL_OP_KEEP;
4468 case QRhiGraphicsPipeline::Replace:
4469 return D3D11_STENCIL_OP_REPLACE;
4470 case QRhiGraphicsPipeline::IncrementAndClamp:
4471 return D3D11_STENCIL_OP_INCR_SAT;
4472 case QRhiGraphicsPipeline::DecrementAndClamp:
4473 return D3D11_STENCIL_OP_DECR_SAT;
4474 case QRhiGraphicsPipeline::Invert:
4475 return D3D11_STENCIL_OP_INVERT;
4476 case QRhiGraphicsPipeline::IncrementAndWrap:
4477 return D3D11_STENCIL_OP_INCR;
4478 case QRhiGraphicsPipeline::DecrementAndWrap:
4479 return D3D11_STENCIL_OP_DECR;
4482 return D3D11_STENCIL_OP_KEEP;
4489 case QRhiVertexInputAttribute::Float4:
4490 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4491 case QRhiVertexInputAttribute::Float3:
4492 return DXGI_FORMAT_R32G32B32_FLOAT;
4493 case QRhiVertexInputAttribute::Float2:
4494 return DXGI_FORMAT_R32G32_FLOAT;
4495 case QRhiVertexInputAttribute::Float:
4496 return DXGI_FORMAT_R32_FLOAT;
4497 case QRhiVertexInputAttribute::UNormByte4:
4498 return DXGI_FORMAT_R8G8B8A8_UNORM;
4499 case QRhiVertexInputAttribute::UNormByte2:
4500 return DXGI_FORMAT_R8G8_UNORM;
4501 case QRhiVertexInputAttribute::UNormByte:
4502 return DXGI_FORMAT_R8_UNORM;
4503 case QRhiVertexInputAttribute::UInt4:
4504 return DXGI_FORMAT_R32G32B32A32_UINT;
4505 case QRhiVertexInputAttribute::UInt3:
4506 return DXGI_FORMAT_R32G32B32_UINT;
4507 case QRhiVertexInputAttribute::UInt2:
4508 return DXGI_FORMAT_R32G32_UINT;
4509 case QRhiVertexInputAttribute::UInt:
4510 return DXGI_FORMAT_R32_UINT;
4511 case QRhiVertexInputAttribute::SInt4:
4512 return DXGI_FORMAT_R32G32B32A32_SINT;
4513 case QRhiVertexInputAttribute::SInt3:
4514 return DXGI_FORMAT_R32G32B32_SINT;
4515 case QRhiVertexInputAttribute::SInt2:
4516 return DXGI_FORMAT_R32G32_SINT;
4517 case QRhiVertexInputAttribute::SInt:
4518 return DXGI_FORMAT_R32_SINT;
4519 case QRhiVertexInputAttribute::Half4:
4521 case QRhiVertexInputAttribute::Half3:
4522 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4523 case QRhiVertexInputAttribute::Half2:
4524 return DXGI_FORMAT_R16G16_FLOAT;
4525 case QRhiVertexInputAttribute::Half:
4526 return DXGI_FORMAT_R16_FLOAT;
4527 case QRhiVertexInputAttribute::UShort4:
4529 case QRhiVertexInputAttribute::UShort3:
4530 return DXGI_FORMAT_R16G16B16A16_UINT;
4531 case QRhiVertexInputAttribute::UShort2:
4532 return DXGI_FORMAT_R16G16_UINT;
4533 case QRhiVertexInputAttribute::UShort:
4534 return DXGI_FORMAT_R16_UINT;
4535 case QRhiVertexInputAttribute::SShort4:
4537 case QRhiVertexInputAttribute::SShort3:
4538 return DXGI_FORMAT_R16G16B16A16_SINT;
4539 case QRhiVertexInputAttribute::SShort2:
4540 return DXGI_FORMAT_R16G16_SINT;
4541 case QRhiVertexInputAttribute::SShort:
4542 return DXGI_FORMAT_R16_SINT;
4545 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4552 case QRhiGraphicsPipeline::Triangles:
4553 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4554 case QRhiGraphicsPipeline::TriangleStrip:
4555 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4556 case QRhiGraphicsPipeline::Lines:
4557 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4558 case QRhiGraphicsPipeline::LineStrip:
4559 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4560 case QRhiGraphicsPipeline::Points:
4561 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4562 case QRhiGraphicsPipeline::Patches:
4563 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4564 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4567 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4574 if (c.testFlag(QRhiGraphicsPipeline::R))
4575 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4576 if (c.testFlag(QRhiGraphicsPipeline::G))
4577 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4578 if (c.testFlag(QRhiGraphicsPipeline::B))
4579 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4580 if (c.testFlag(QRhiGraphicsPipeline::A))
4581 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4594 case QRhiGraphicsPipeline::Zero:
4595 return D3D11_BLEND_ZERO;
4596 case QRhiGraphicsPipeline::One:
4597 return D3D11_BLEND_ONE;
4598 case QRhiGraphicsPipeline::SrcColor:
4599 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4600 case QRhiGraphicsPipeline::OneMinusSrcColor:
4601 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4602 case QRhiGraphicsPipeline::DstColor:
4603 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4604 case QRhiGraphicsPipeline::OneMinusDstColor:
4605 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4606 case QRhiGraphicsPipeline::SrcAlpha:
4607 return D3D11_BLEND_SRC_ALPHA;
4608 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4609 return D3D11_BLEND_INV_SRC_ALPHA;
4610 case QRhiGraphicsPipeline::DstAlpha:
4611 return D3D11_BLEND_DEST_ALPHA;
4612 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4613 return D3D11_BLEND_INV_DEST_ALPHA;
4614 case QRhiGraphicsPipeline::ConstantColor:
4615 case QRhiGraphicsPipeline::ConstantAlpha:
4616 return D3D11_BLEND_BLEND_FACTOR;
4617 case QRhiGraphicsPipeline::OneMinusConstantColor:
4618 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4619 return D3D11_BLEND_INV_BLEND_FACTOR;
4620 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4621 return D3D11_BLEND_SRC_ALPHA_SAT;
4622 case QRhiGraphicsPipeline::Src1Color:
4623 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4624 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4625 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4626 case QRhiGraphicsPipeline::Src1Alpha:
4627 return D3D11_BLEND_SRC1_ALPHA;
4628 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4629 return D3D11_BLEND_INV_SRC1_ALPHA;
4632 return D3D11_BLEND_ZERO;
4639 case QRhiGraphicsPipeline::Add:
4640 return D3D11_BLEND_OP_ADD;
4641 case QRhiGraphicsPipeline::Subtract:
4642 return D3D11_BLEND_OP_SUBTRACT;
4643 case QRhiGraphicsPipeline::ReverseSubtract:
4644 return D3D11_BLEND_OP_REV_SUBTRACT;
4645 case QRhiGraphicsPipeline::Min:
4646 return D3D11_BLEND_OP_MIN;
4647 case QRhiGraphicsPipeline::Max:
4648 return D3D11_BLEND_OP_MAX;
4651 return D3D11_BLEND_OP_ADD;
4658 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4659 keyBuilder.addData(source);
4660 return keyBuilder.result().toHex();
4663QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4664 QString *error, QShaderKey *usedShaderKey)
4666 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4667 QShaderCode dxbc = shader.shader(key);
4668 if (!dxbc.shader().isEmpty()) {
4670 *usedShaderKey = key;
4671 return dxbc.shader();
4674 key = { QShader::HlslShader, 50, shaderVariant };
4675 QShaderCode hlslSource = shader.shader(key);
4676 if (hlslSource.shader().isEmpty()) {
4677 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4678 return QByteArray();
4682 *usedShaderKey = key;
4685 switch (shader.stage()) {
4686 case QShader::VertexStage:
4689 case QShader::TessellationControlStage:
4692 case QShader::TessellationEvaluationStage:
4695 case QShader::GeometryStage:
4698 case QShader::FragmentStage:
4701 case QShader::ComputeStage:
4706 return QByteArray();
4710 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4711 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4712 cacheKey.target = target;
4713 cacheKey.entryPoint = hlslSource.entryPoint();
4714 cacheKey.compileFlags = flags;
4715 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4716 if (cacheIt != m_bytecodeCache.constEnd())
4717 return cacheIt.value();
4720 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4721 if (d3dCompile ==
nullptr) {
4722 qWarning(
"Unable to resolve function D3DCompile()");
4723 return QByteArray();
4726 ID3DBlob *bytecode =
nullptr;
4727 ID3DBlob *errors =
nullptr;
4728 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4729 nullptr,
nullptr,
nullptr,
4730 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4731 if (FAILED(hr) || !bytecode) {
4732 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4734 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4735 int(errors->GetBufferSize()));
4738 return QByteArray();
4742 result.resize(
int(bytecode->GetBufferSize()));
4743 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4744 bytecode->Release();
4746 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4747 m_bytecodeCache.insert(cacheKey, result);
4758 rhiD->pipelineCreationStart();
4759 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4762 D3D11_RASTERIZER_DESC rastDesc = {};
4763 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4764 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4765 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4766 rastDesc.DepthBias = m_depthBias;
4767 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4768 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4769 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4770 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4771 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4773 qWarning(
"Failed to create rasterizer state: %s",
4774 qPrintable(QSystemError::windowsComString(hr)));
4778 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4779 dsDesc.DepthEnable = m_depthTest;
4780 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4781 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4782 dsDesc.StencilEnable = m_stencilTest;
4783 if (m_stencilTest) {
4784 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4785 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4786 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4787 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4788 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4789 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4790 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4791 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4792 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4793 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4795 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4797 qWarning(
"Failed to create depth-stencil state: %s",
4798 qPrintable(QSystemError::windowsComString(hr)));
4802 D3D11_BLEND_DESC blendDesc = {};
4803 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4804 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4805 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4806 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4807 blend.BlendEnable = b.enable;
4808 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4809 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4810 blend.BlendOp = toD3DBlendOp(b.opColor);
4811 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4812 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4813 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4814 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4815 blendDesc.RenderTarget[i] = blend;
4817 if (m_targetBlends.isEmpty()) {
4818 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4819 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4820 blendDesc.RenderTarget[0] = blend;
4822 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4824 qWarning(
"Failed to create blend state: %s",
4825 qPrintable(QSystemError::windowsComString(hr)));
4829 QByteArray vsByteCode;
4830 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4831 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4832 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4833 switch (shaderStage.type()) {
4834 case QRhiShaderStage::Vertex:
4835 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4836 vs.shader->AddRef();
4837 vsByteCode = cacheIt->bytecode;
4838 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4840 case QRhiShaderStage::TessellationControl:
4841 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4842 hs.shader->AddRef();
4843 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4845 case QRhiShaderStage::TessellationEvaluation:
4846 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4847 ds.shader->AddRef();
4848 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4850 case QRhiShaderStage::Geometry:
4851 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4852 gs.shader->AddRef();
4853 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4855 case QRhiShaderStage::Fragment:
4856 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4857 fs.shader->AddRef();
4858 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4865 QShaderKey shaderKey;
4866 UINT compileFlags = 0;
4867 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4868 compileFlags |= D3DCOMPILE_DEBUG;
4870 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4871 &error, &shaderKey);
4872 if (bytecode.isEmpty()) {
4873 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4877 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4879 rhiD->clearShaderCache();
4882 switch (shaderStage.type()) {
4883 case QRhiShaderStage::Vertex:
4884 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4886 qWarning(
"Failed to create vertex shader: %s",
4887 qPrintable(QSystemError::windowsComString(hr)));
4890 vsByteCode = bytecode;
4891 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4892 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4893 vs.shader->AddRef();
4895 case QRhiShaderStage::TessellationControl:
4896 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4898 qWarning(
"Failed to create hull shader: %s",
4899 qPrintable(QSystemError::windowsComString(hr)));
4902 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4903 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4904 hs.shader->AddRef();
4906 case QRhiShaderStage::TessellationEvaluation:
4907 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4909 qWarning(
"Failed to create domain shader: %s",
4910 qPrintable(QSystemError::windowsComString(hr)));
4913 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4914 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4915 ds.shader->AddRef();
4917 case QRhiShaderStage::Geometry:
4918 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4920 qWarning(
"Failed to create geometry shader: %s",
4921 qPrintable(QSystemError::windowsComString(hr)));
4924 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4925 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4926 gs.shader->AddRef();
4928 case QRhiShaderStage::Fragment:
4929 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4931 qWarning(
"Failed to create pixel shader: %s",
4932 qPrintable(QSystemError::windowsComString(hr)));
4935 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4936 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4937 fs.shader->AddRef();
4945 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4947 if (!vsByteCode.isEmpty()) {
4948 QByteArrayList matrixSliceSemantics;
4949 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4950 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4953 D3D11_INPUT_ELEMENT_DESC desc = {};
4958 const int matrixSlice = it->matrixSlice();
4959 if (matrixSlice < 0) {
4960 desc.SemanticName =
"TEXCOORD";
4961 desc.SemanticIndex = UINT(it->location());
4965 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4966 matrixSliceSemantics.append(sem);
4967 desc.SemanticName = matrixSliceSemantics.last().constData();
4968 desc.SemanticIndex = UINT(matrixSlice);
4970 desc.Format = toD3DAttributeFormat(it->format());
4971 desc.InputSlot = UINT(it->binding());
4972 desc.AlignedByteOffset = it->offset();
4973 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4974 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4975 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4976 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4978 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4980 inputDescs.append(desc);
4982 if (!inputDescs.isEmpty()) {
4983 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4984 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4986 qWarning(
"Failed to create input layout: %s",
4987 qPrintable(QSystemError::windowsComString(hr)));
4993 rhiD->pipelineCreationEnd();
4995 rhiD->registerResource(
this);
5014 cs.shader->Release();
5015 cs.shader =
nullptr;
5016 cs.nativeResourceBindingMap.clear();
5020 rhiD->unregisterResource(
this);
5029 rhiD->pipelineCreationStart();
5031 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5032 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5033 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5034 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5037 QShaderKey shaderKey;
5038 UINT compileFlags = 0;
5039 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5040 compileFlags |= D3DCOMPILE_DEBUG;
5042 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5043 &error, &shaderKey);
5044 if (bytecode.isEmpty()) {
5045 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5049 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5051 qWarning(
"Failed to create compute shader: %s",
5052 qPrintable(QSystemError::windowsComString(hr)));
5056 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5058 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5061 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5064 cs.shader->AddRef();
5066 rhiD->pipelineCreationEnd();
5068 rhiD->registerResource(
this);
5093 D3D11_QUERY_DESC queryDesc = {};
5095 if (!disjointQuery[i]) {
5096 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5097 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5099 qWarning(
"Failed to create timestamp disjoint query: %s",
5100 qPrintable(QSystemError::windowsComString(hr)));
5104 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5105 for (
int j = 0; j < 2; ++j) {
5106 const int idx = 2 * i + j;
5108 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5110 qWarning(
"Failed to create timestamp query: %s",
5111 qPrintable(QSystemError::windowsComString(hr)));
5124 if (disjointQuery[i]) {
5125 disjointQuery[i]->Release();
5126 disjointQuery[i] =
nullptr;
5128 for (
int j = 0; j < 2; ++j) {
5131 query[idx]->Release();
5132 query[idx] =
nullptr;
5140 bool result =
false;
5144 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5145 ID3D11Query *tsStart = query[pairIndex * 2];
5146 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5147 quint64 timestamps[2];
5148 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5151 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5152 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5153 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5156 if (!dj.Disjoint && dj.Frequency) {
5157 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5158 *elapsedSec = elapsedMs / 1000.0;
5161 active[pairIndex] =
false;
5170 backBufferTex =
nullptr;
5171 backBufferRtv =
nullptr;
5173 msaaTex[i] =
nullptr;
5174 msaaRtv[i] =
nullptr;
5185 if (backBufferRtv) {
5186 backBufferRtv->Release();
5187 backBufferRtv =
nullptr;
5189 if (backBufferRtvRight) {
5190 backBufferRtvRight->Release();
5191 backBufferRtvRight =
nullptr;
5193 if (backBufferTex) {
5194 backBufferTex->Release();
5195 backBufferTex =
nullptr;
5199 msaaRtv[i]->Release();
5200 msaaRtv[i] =
nullptr;
5203 msaaTex[i]->Release();
5204 msaaTex[i] =
nullptr;
5216 timestamps.destroy();
5218 swapChain->Release();
5219 swapChain =
nullptr;
5222 dcompVisual->Release();
5223 dcompVisual =
nullptr;
5227 dcompTarget->Release();
5228 dcompTarget =
nullptr;
5231 if (frameLatencyWaitableObject) {
5232 CloseHandle(frameLatencyWaitableObject);
5233 frameLatencyWaitableObject =
nullptr;
5236 QDxgiVSyncService::instance()->unregisterWindow(window);
5240 rhiD->unregisterResource(
this);
5243 rhiD->context->Flush();
5259 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5265 return m_window->size() * m_window->devicePixelRatio();
5274 qWarning(
"Attempted to call isFormatSupported() without a window set");
5279 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5280 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5291 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5300 rhiD->registerResource(rpD,
false);
5305 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5307 D3D11_TEXTURE2D_DESC desc = {};
5308 desc.Width = UINT(size.width());
5309 desc.Height = UINT(size.height());
5312 desc.Format = format;
5313 desc.SampleDesc = sampleDesc;
5314 desc.Usage = D3D11_USAGE_DEFAULT;
5315 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5318 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5320 qWarning(
"Failed to create color buffer texture: %s",
5321 qPrintable(QSystemError::windowsComString(hr)));
5325 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5326 rtvDesc.Format = format;
5327 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5328 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5330 qWarning(
"Failed to create color buffer rtv: %s",
5331 qPrintable(QSystemError::windowsComString(hr)));
5345 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5346 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5347 return dcompDevice ?
true :
false;
5359 const bool needsRegistration = !window || window != m_window;
5360 const bool stereo = m_window->format().stereo();
5363 if (window && window != m_window)
5367 m_currentPixelSize = surfacePixelSize();
5368 pixelSize = m_currentPixelSize;
5370 if (pixelSize.isEmpty())
5373 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5378 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5381 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5383 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5384 qPrintable(QSystemError::windowsComString(hr)));
5387 if (dcompTarget && !dcompVisual) {
5388 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5390 qWarning(
"Failed to create DirectComposition visual: %s",
5391 qPrintable(QSystemError::windowsComString(hr)));
5396 if (
window->requestedFormat().alphaBufferSize() <= 0)
5397 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5398 "This may lead to problems.");
5401 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5408 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5409 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5413 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5414 && swapInterval != 0
5415 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5417 if (useFrameLatencyWaitableObject) {
5419 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5423 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5424 colorFormat = DEFAULT_FORMAT;
5425 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5427 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5428 if (m_format != SDR) {
5429 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5432 case HDRExtendedSrgbLinear:
5433 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5434 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5435 srgbAdjustedColorFormat = colorFormat;
5438 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5439 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5440 srgbAdjustedColorFormat = colorFormat;
5449 qWarning(
"The output associated with the window is not HDR capable "
5450 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5460 DXGI_SWAP_CHAIN_DESC1 desc = {};
5461 desc.Width = UINT(pixelSize.width());
5462 desc.Height = UINT(pixelSize.height());
5463 desc.Format = colorFormat;
5464 desc.SampleDesc.Count = 1;
5465 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5467 desc.Flags = swapChainFlags;
5468 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5469 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5470 desc.Stereo = stereo;
5476 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5481 desc.Scaling = DXGI_SCALING_STRETCH;
5484 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5485 IDXGISwapChain1 *sc1;
5488 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5490 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5495 if (FAILED(hr) && m_format != SDR) {
5496 colorFormat = DEFAULT_FORMAT;
5497 desc.Format = DEFAULT_FORMAT;
5499 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5501 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5504 if (SUCCEEDED(hr)) {
5506 IDXGISwapChain3 *sc3 =
nullptr;
5507 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5508 if (m_format != SDR) {
5509 hr = sc3->SetColorSpace1(hdrColorSpace);
5511 qWarning(
"Failed to set color space on swapchain: %s",
5512 qPrintable(QSystemError::windowsComString(hr)));
5514 if (useFrameLatencyWaitableObject) {
5515 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5516 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5520 if (m_format != SDR)
5521 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5522 if (useFrameLatencyWaitableObject) {
5523 IDXGISwapChain2 *sc2 =
nullptr;
5524 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5525 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5526 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5529 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5534 hr = dcompVisual->SetContent(sc1);
5535 if (SUCCEEDED(hr)) {
5536 hr = dcompTarget->SetRoot(dcompVisual);
5538 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5539 qPrintable(QSystemError::windowsComString(hr)));
5542 qWarning(
"Failed to set content for Direct Composition visual: %s",
5543 qPrintable(QSystemError::windowsComString(hr)));
5547 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5550 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5551 qWarning(
"Device loss detected during swapchain creation");
5554 }
else if (FAILED(hr)) {
5555 qWarning(
"Failed to create D3D11 swapchain: %s"
5556 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5557 qPrintable(QSystemError::windowsComString(hr)),
5558 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5559 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5565 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5566 colorFormat, swapChainFlags);
5567 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5568 qWarning(
"Device loss detected in ResizeBuffers()");
5571 }
else if (FAILED(hr)) {
5572 qWarning(
"Failed to resize D3D11 swapchain: %s",
5573 qPrintable(QSystemError::windowsComString(hr)));
5592 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5594 qWarning(
"Failed to query swapchain backbuffer: %s",
5595 qPrintable(QSystemError::windowsComString(hr)));
5598 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5599 rtvDesc.Format = srgbAdjustedColorFormat;
5600 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5601 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5603 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5604 qPrintable(QSystemError::windowsComString(hr)));
5610 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5611 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5612 rtvDesc.Texture2DArray.ArraySize = 1;
5613 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5615 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5616 qPrintable(QSystemError::windowsComString(hr)));
5623 if (sampleDesc.Count > 1) {
5624 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5629 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5630 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5631 m_depthStencil->sampleCount(), m_sampleCount);
5633 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5634 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5635 m_depthStencil->setPixelSize(pixelSize);
5636 if (!m_depthStencil->create())
5637 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5638 pixelSize.width(), pixelSize.height());
5640 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5641 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5642 pixelSize.width(), pixelSize.height());
5649 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5651 rt.setRenderPassDescriptor(m_renderPassDesc);
5653 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5654 rtD->d.pixelSize = pixelSize;
5655 rtD->d.dpr =
float(
window->devicePixelRatio());
5656 rtD->d.sampleCount =
int(sampleDesc.Count);
5657 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5660 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5661 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5662 rtD->d.pixelSize = pixelSize;
5663 rtD->d.dpr =
float(
window->devicePixelRatio());
5664 rtD->d.sampleCount =
int(sampleDesc.Count);
5665 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
5668 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5669 timestamps.prepare(rhiD);
5673 QDxgiVSyncService::instance()->registerWindow(window);
5675 if (needsRegistration)
5676 rhiD->registerResource(
this);
5684 if (rtViews.dsv != currentRtViews.dsv) {
5685 rtViews.dsv = currentRtViews.dsv;
5689 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
5690 rtViews.rtv[i] = currentRtViews.rtv[i];
5692 rtViews.colorAttCount = currentRtViews.colorAttCount;
5694 ret |= rtViews.rtv[i] !=
nullptr;
5695 rtViews.rtv[i] =
nullptr;
5697 for (
int i = 0; i < count; i++) {
5698 ret |= uav[i] != uavs[i];
5702 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