10#include <QtCore/qcryptographichash.h>
11#include <QtCore/private/qsystemerror_p.h>
18using namespace Qt::StringLiterals;
21
22
23
24
25
26
27
28
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
78
79
80
81
82
86
87
88
89
90
91
92
93
94
95
96
97
100
101
102
103
104
105
106
107
110
111
112
113
114
115
116
119
120
121
122
123
124
125
126
129
130
131
132
133
134
137
138
139
140
141
142
145#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
146#define DXGI_ADAPTER_FLAG_SOFTWARE 2
149#ifndef D3D11_1_UAV_SLOT_COUNT
150#define D3D11_1_UAV_SLOT_COUNT 64
153#ifndef D3D11_VS_INPUT_REGISTER_COUNT
154#define D3D11_VS_INPUT_REGISTER_COUNT 32
163 if (importParams->dev && importParams->context) {
164 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
165 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
166 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
171 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
174 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
175 adapterLuid.LowPart = importParams->adapterLuidLow;
176 adapterLuid.HighPart = importParams->adapterLuidHigh;
183 return (v + byteAlign - 1) & ~(byteAlign - 1);
188 IDXGIFactory1 *result =
nullptr;
189 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
191 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
192 qPrintable(QSystemError::windowsComString(hr)));
204 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
206 dxgiFactory = createDXGIFactory2();
214 IDXGIFactory5 *factory5 =
nullptr;
215 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
216 BOOL allowTearing =
false;
217 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
222 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
223 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
231 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
232 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
237 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
241 if (maxFrameLatency == 0)
242 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
244 activeAdapter =
nullptr;
247 IDXGIAdapter1 *adapter;
248 int requestedAdapterIndex = -1;
249 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
250 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
252 if (requestedRhiAdapter)
253 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
256 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
257 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
258 DXGI_ADAPTER_DESC1 desc;
259 adapter->GetDesc1(&desc);
261 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
262 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
264 requestedAdapterIndex = adapterIndex;
270 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
271 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
272 DXGI_ADAPTER_DESC1 desc;
273 adapter->GetDesc1(&desc);
276 requestedAdapterIndex = adapterIndex;
282 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
283 DXGI_ADAPTER_DESC1 desc;
284 adapter->GetDesc1(&desc);
285 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
286 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
292 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
293 activeAdapter = adapter;
294 adapterLuid = desc.AdapterLuid;
296 qCDebug(QRHI_LOG_INFO,
" using this adapter");
301 if (!activeAdapter) {
302 qWarning(
"No adapter");
308 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
309 bool requestFeatureLevels =
false;
311 requestFeatureLevels =
true;
312 requestedFeatureLevels.append(featureLevel);
315 ID3D11DeviceContext *ctx =
nullptr;
316 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
317 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
318 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
320 &dev, &featureLevel, &ctx);
322 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
323 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
324 "Attempting to create D3D11 device without it.");
325 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
326 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
327 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
328 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
330 &dev, &featureLevel, &ctx);
333 qWarning(
"Failed to create D3D11 device and context: %s",
334 qPrintable(QSystemError::windowsComString(hr)));
338 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
341 qWarning(
"ID3D11DeviceContext1 not supported");
347 ID3D11VertexShader *testShader =
nullptr;
348 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
349 testShader->Release();
351 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
352 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
353 qCDebug(QRHI_LOG_INFO,
"%s", msg);
359 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
360 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
364 if (!features.ConstantBufferOffsetting) {
365 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
366 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
367 qCDebug(QRHI_LOG_INFO,
"%s", msg);
373 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
374 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
375 qCDebug(QRHI_LOG_INFO,
"%s", msg);
381 Q_ASSERT(dev && context);
382 featureLevel = dev->GetFeatureLevel();
383 IDXGIDevice *dxgiDev =
nullptr;
384 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
385 IDXGIAdapter *adapter =
nullptr;
386 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
387 IDXGIAdapter1 *adapter1 =
nullptr;
388 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
389 DXGI_ADAPTER_DESC1 desc;
390 adapter1->GetDesc1(&desc);
391 adapterLuid = desc.AdapterLuid;
393 activeAdapter = adapter1;
399 if (!activeAdapter) {
400 qWarning(
"Failed to query adapter from imported device");
403 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
406 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
408 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
409 annotations =
nullptr;
413 nativeHandlesStruct.dev = dev;
414 nativeHandlesStruct.context = context;
415 nativeHandlesStruct.featureLevel = featureLevel;
416 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
417 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
424 for (
const Shader &s : std::as_const(m_shaderCache))
427 m_shaderCache.clear();
436 if (ofr.tsDisjointQuery) {
437 ofr.tsDisjointQuery->Release();
438 ofr.tsDisjointQuery =
nullptr;
440 for (
int i = 0; i < 2; ++i) {
441 if (ofr.tsQueries[i]) {
442 ofr.tsQueries[i]->Release();
443 ofr.tsQueries[i] =
nullptr;
448 annotations->Release();
449 annotations =
nullptr;
464 dcompDevice->Release();
465 dcompDevice =
nullptr;
469 activeAdapter->Release();
470 activeAdapter =
nullptr;
474 dxgiFactory->Release();
475 dxgiFactory =
nullptr;
481 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
488 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
489 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
494QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
496 LUID requestedLuid = {};
498 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
499 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
500 if (adapterLuid.LowPart || adapterLuid.HighPart)
501 requestedLuid = adapterLuid;
504 IDXGIFactory1 *dxgi = createDXGIFactory2();
508 QRhi::AdapterList list;
509 IDXGIAdapter1 *adapter;
510 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
511 DXGI_ADAPTER_DESC1 desc;
512 adapter->GetDesc1(&desc);
514 if (requestedLuid.LowPart || requestedLuid.HighPart) {
515 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
516 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
521 QD3D11Adapter *a =
new QD3D11Adapter;
522 a->luid = desc.AdapterLuid;
523 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
538 return { 1, 2, 4, 8 };
543 Q_UNUSED(sampleCount);
544 return { QSize(1, 1) };
549 DXGI_SAMPLE_DESC desc;
553 const int s = effectiveSampleCount(sampleCount);
555 desc.Count = UINT(s);
557 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
566 return new QD3D11SwapChain(
this);
569QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
571 return new QD3D11Buffer(
this, type, usage, size);
599 if (m.isIdentity()) {
601 m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
602 0.0f, 1.0f, 0.0f, 0.0f,
603 0.0f, 0.0f, 0.5f, 0.5f,
604 0.0f, 0.0f, 0.0f, 1.0f);
613 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
622 case QRhi::MultisampleTexture:
624 case QRhi::MultisampleRenderBuffer:
626 case QRhi::DebugMarkers:
627 return annotations !=
nullptr;
628 case QRhi::Timestamps:
630 case QRhi::Instancing:
632 case QRhi::CustomInstanceStepRate:
634 case QRhi::PrimitiveRestart:
636 case QRhi::NonDynamicUniformBuffers:
638 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
640 case QRhi::NPOTTextureRepeat:
642 case QRhi::RedOrAlpha8IsRed:
644 case QRhi::ElementIndexUint:
648 case QRhi::WideLines:
650 case QRhi::VertexShaderPointSize:
652 case QRhi::BaseVertex:
654 case QRhi::BaseInstance:
656 case QRhi::TriangleFanTopology:
658 case QRhi::ReadBackNonUniformBuffer:
660 case QRhi::ReadBackNonBaseMipLevel:
662 case QRhi::TexelFetch:
664 case QRhi::RenderToNonBaseMipLevel:
666 case QRhi::IntAttributes:
668 case QRhi::ScreenSpaceDerivatives:
670 case QRhi::ReadBackAnyTextureFormat:
672 case QRhi::PipelineCacheDataLoadSave:
674 case QRhi::ImageDataStride:
676 case QRhi::RenderBufferImport:
678 case QRhi::ThreeDimensionalTextures:
680 case QRhi::RenderTo3DTextureSlice:
682 case QRhi::TextureArrays:
684 case QRhi::Tessellation:
686 case QRhi::GeometryShader:
688 case QRhi::TextureArrayRange:
690 case QRhi::NonFillPolygonMode:
692 case QRhi::OneDimensionalTextures:
694 case QRhi::OneDimensionalTextureMipmaps:
696 case QRhi::HalfAttributes:
698 case QRhi::RenderToOneDimensionalTexture:
700 case QRhi::ThreeDimensionalTextureMipmaps:
702 case QRhi::MultiView:
704 case QRhi::TextureViewFormat:
706 case QRhi::ResolveDepthStencil:
708 case QRhi::VariableRateShading:
710 case QRhi::VariableRateShadingMap:
711 case QRhi::VariableRateShadingMapWithTexture:
713 case QRhi::PerRenderTargetBlending:
714 case QRhi::SampleVariables:
716 case QRhi::InstanceIndexIncludesBaseInstance:
718 case QRhi::DepthClamp:
720 case QRhi::DrawIndirect:
721 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
722 case QRhi::DrawIndirectMulti:
733 case QRhi::TextureSizeMin:
735 case QRhi::TextureSizeMax:
736 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
737 case QRhi::MaxColorAttachments:
739 case QRhi::FramesInFlight:
745 case QRhi::MaxAsyncReadbackFrames:
747 case QRhi::MaxThreadGroupsPerDimension:
748 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
749 case QRhi::MaxThreadsPerThreadGroup:
750 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
751 case QRhi::MaxThreadGroupX:
752 return D3D11_CS_THREAD_GROUP_MAX_X;
753 case QRhi::MaxThreadGroupY:
754 return D3D11_CS_THREAD_GROUP_MAX_Y;
755 case QRhi::MaxThreadGroupZ:
756 return D3D11_CS_THREAD_GROUP_MAX_Z;
757 case QRhi::TextureArraySizeMax:
758 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
759 case QRhi::MaxUniformBufferRange:
761 case QRhi::MaxVertexInputs:
763 case QRhi::MaxVertexOutputs:
764 return D3D11_VS_OUTPUT_REGISTER_COUNT;
765 case QRhi::ShadingRateImageTileSize:
775 return &nativeHandlesStruct;
780 return driverInfoStruct;
786 result.totalPipelineCreationTime = totalPipelineCreationTime();
796void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
804 m_bytecodeCache.clear();
824 if (m_bytecodeCache.isEmpty())
828 memset(&header, 0,
sizeof(header));
829 header.rhiId = pipelineCacheRhiId();
830 header.arch = quint32(
sizeof(
void*));
831 header.count = m_bytecodeCache.count();
833 const size_t dataOffset =
sizeof(header);
835 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
837 QByteArray bytecode = it.value();
839 sizeof(quint32) + key.sourceHash.size()
840 +
sizeof(quint32) + key.target.size()
841 +
sizeof(quint32) + key.entryPoint.size()
843 +
sizeof(quint32) + bytecode.size();
846 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
847 char *p = buf.data() + dataOffset;
848 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
850 QByteArray bytecode = it.value();
852 quint32 i = key.sourceHash.size();
855 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
856 p += key.sourceHash.size();
858 i = key.target.size();
861 memcpy(p, key.target.constData(), key.target.size());
862 p += key.target.size();
864 i = key.entryPoint.size();
867 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
868 p += key.entryPoint.size();
870 quint32 f = key.compileFlags;
877 memcpy(p, bytecode.constData(), bytecode.size());
878 p += bytecode.size();
880 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
882 header.dataSize = quint32(dataSize);
883 memcpy(buf.data(), &header,
sizeof(header));
894 if (data.size() < qsizetype(headerSize)) {
895 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
898 const size_t dataOffset = headerSize;
900 memcpy(&header, data.constData(), headerSize);
902 const quint32 rhiId = pipelineCacheRhiId();
903 if (header.rhiId != rhiId) {
904 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
905 rhiId, header.rhiId);
908 const quint32 arch = quint32(
sizeof(
void*));
909 if (header.arch != arch) {
910 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
914 if (header.count == 0)
917 if (data.size() < qsizetype(dataOffset + header.dataSize)) {
918 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
922 m_bytecodeCache.clear();
924 const char *p = data.constData() + dataOffset;
925 for (quint32 i = 0; i < header.count; ++i) {
929 QByteArray sourceHash(len, Qt::Uninitialized);
930 memcpy(sourceHash.data(), p, len);
935 QByteArray target(len, Qt::Uninitialized);
936 memcpy(target.data(), p, len);
941 QByteArray entryPoint(len, Qt::Uninitialized);
942 memcpy(entryPoint.data(), p, len);
946 memcpy(&flags, p, 4);
951 QByteArray bytecode(len, Qt::Uninitialized);
952 memcpy(bytecode.data(), p, len);
956 cacheKey.sourceHash = sourceHash;
957 cacheKey.target = target;
958 cacheKey.entryPoint = entryPoint;
959 cacheKey.compileFlags = flags;
961 m_bytecodeCache.insert(cacheKey, bytecode);
964 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
967QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
968 int sampleCount, QRhiRenderBuffer::Flags flags,
969 QRhiTexture::Format backingFormatHint)
971 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
975 const QSize &pixelSize,
int depth,
int arraySize,
976 int sampleCount, QRhiTexture::Flags flags)
978 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
982 QRhiSampler::Filter mipmapMode,
983 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
985 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
989 QRhiTextureRenderTarget::Flags flags)
1001 return new QD3D11GraphicsPipeline(
this);
1006 return new QD3D11ComputePipeline(
this);
1011 return new QD3D11ShaderResourceBindings(
this);
1019 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
1021 if (pipelineChanged) {
1022 cbD->currentGraphicsPipeline = ps;
1023 cbD->currentComputePipeline =
nullptr;
1024 cbD->currentPipelineGeneration = psD->generation;
1028 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1029 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1030 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1031 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1032 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1033 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1034 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1035 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1036 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1037 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1050 int dynamicOffsetCount,
1051 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1060 srb = gfxPsD->m_shaderResourceBindings;
1062 srb = compPsD->m_shaderResourceBindings;
1067 bool pipelineChanged =
false;
1076 bool srbUpdate =
false;
1077 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1078 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1081 case QRhiShaderResourceBinding::UniformBuffer:
1085 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1086 sanityCheckResourceOwnership(bufD);
1090 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1092 bd.ubuf.id = bufD->m_id;
1093 bd.ubuf.generation = bufD->generation;
1097 case QRhiShaderResourceBinding::SampledTexture:
1098 case QRhiShaderResourceBinding::Texture:
1099 case QRhiShaderResourceBinding::Sampler:
1101 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1102 if (bd.stex.count != data->count) {
1103 bd.stex.count = data->count;
1106 for (
int elem = 0; elem < data->count; ++elem) {
1112 Q_ASSERT(texD || samplerD);
1113 sanityCheckResourceOwnership(texD);
1114 sanityCheckResourceOwnership(samplerD);
1115 const quint64 texId = texD ? texD->m_id : 0;
1116 const uint texGen = texD ? texD->generation : 0;
1117 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1118 const uint samplerGen = samplerD ? samplerD->generation : 0;
1119 if (texGen != bd.stex.d[elem].texGeneration
1120 || texId != bd.stex.d[elem].texId
1121 || samplerGen != bd.stex.d[elem].samplerGeneration
1122 || samplerId != bd.stex.d[elem].samplerId)
1125 bd.stex.d[elem].texId = texId;
1126 bd.stex.d[elem].texGeneration = texGen;
1127 bd.stex.d[elem].samplerId = samplerId;
1128 bd.stex.d[elem].samplerGeneration = samplerGen;
1133 case QRhiShaderResourceBinding::ImageLoad:
1134 case QRhiShaderResourceBinding::ImageStore:
1135 case QRhiShaderResourceBinding::ImageLoadStore:
1138 sanityCheckResourceOwnership(texD);
1139 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1141 bd.simage.id = texD->m_id;
1142 bd.simage.generation = texD->generation;
1146 case QRhiShaderResourceBinding::BufferLoad:
1147 case QRhiShaderResourceBinding::BufferStore:
1148 case QRhiShaderResourceBinding::BufferLoadStore:
1151 sanityCheckResourceOwnership(bufD);
1152 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1154 bd.sbuf.id = bufD->m_id;
1155 bd.sbuf.generation = bufD->generation;
1165 if (srbUpdate || pipelineChanged) {
1167 memset(resBindMaps, 0,
sizeof(resBindMaps));
1169 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1170 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1171 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1172 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1173 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1175 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1177 updateShaderResourceBindings(srbD, resBindMaps);
1180 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1181 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1183 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1185 cbD->currentGraphicsSrb = srb;
1186 cbD->currentComputeSrb =
nullptr;
1188 cbD->currentGraphicsSrb =
nullptr;
1189 cbD->currentComputeSrb = srb;
1191 cbD->currentSrbGeneration = srbD->generation;
1198 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1199 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1202 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1203 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1204 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1205 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1206 const uint binding = uint(dynOfs.first);
1207 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1208 const quint32 offsetInConstants = dynOfs.second / 16;
1210 *p++ = offsetInConstants;
1213 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1221 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1222 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1227 bool needsBindVBuf =
false;
1228 for (
int i = 0; i < bindingCount; ++i) {
1229 const int inputSlot = startBinding + i;
1231 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1232 if (bufD->m_type == QRhiBuffer::Dynamic)
1235 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1236 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1238 needsBindVBuf =
true;
1239 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1240 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1244 if (needsBindVBuf) {
1247 cmd.args.bindVertexBuffers.startSlot = startBinding;
1249 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1253 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1255 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1256 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1257 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1259 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1260 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1261 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1267 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1268 if (ibufD->m_type == QRhiBuffer::Dynamic)
1271 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1272 : DXGI_FORMAT_R32_UINT;
1273 if (cbD->currentIndexBuffer != ibufD->buffer
1274 || cbD->currentIndexOffset != indexOffset
1275 || cbD->currentIndexFormat != dxgiFormat)
1277 cbD->currentIndexBuffer = ibufD->buffer;
1278 cbD->currentIndexOffset = indexOffset;
1279 cbD->currentIndexFormat = dxgiFormat;
1283 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1284 cmd.args.bindIndexBuffer.offset = indexOffset;
1285 cmd.args.bindIndexBuffer.format = dxgiFormat;
1294 Q_ASSERT(cbD->currentTarget);
1295 const QSize outputSize = cbD->currentTarget->pixelSize();
1299 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1304 cmd.args.viewport.x = x;
1305 cmd.args.viewport.y = y;
1306 cmd.args.viewport.w = w;
1307 cmd.args.viewport.h = h;
1308 cmd.args.viewport.d0 = viewport.minDepth();
1309 cmd.args.viewport.d1 = viewport.maxDepth();
1316 Q_ASSERT(cbD->currentTarget);
1317 const QSize outputSize = cbD->currentTarget->pixelSize();
1321 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1326 cmd.args.scissor.x = x;
1327 cmd.args.scissor.y = y;
1328 cmd.args.scissor.w = w;
1329 cmd.args.scissor.h = h;
1340 cmd.args.blendConstants.c[0] =
float(c.redF());
1341 cmd.args.blendConstants.c[1] =
float(c.greenF());
1342 cmd.args.blendConstants.c[2] =
float(c.blueF());
1343 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1354 cmd.args.stencilRef.ref = refValue;
1360 Q_UNUSED(coarsePixelSize);
1364 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1371 cmd.args.draw.vertexCount = vertexCount;
1372 cmd.args.draw.instanceCount = instanceCount;
1373 cmd.args.draw.firstVertex = firstVertex;
1374 cmd.args.draw.firstInstance = firstInstance;
1378 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1385 cmd.args.drawIndexed.indexCount = indexCount;
1386 cmd.args.drawIndexed.instanceCount = instanceCount;
1387 cmd.args.drawIndexed.firstIndex = firstIndex;
1388 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1389 cmd.args.drawIndexed.firstInstance = firstInstance;
1393 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1400 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1401 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1402 cmd.args.drawIndirect.drawCount = drawCount;
1403 cmd.args.drawIndirect.stride = stride;
1408 switch (rt->resourceType()) {
1409 case QRhiResource::SwapChainRenderTarget:
1410 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1411 case QRhiResource::TextureRenderTarget:
1412 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1420 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1427 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1428 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1429 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1430 cmd.args.drawIndexedIndirect.stride = stride;
1435 if (!debugMarkers || !annotations)
1441 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1446 if (!debugMarkers || !annotations)
1456 if (!debugMarkers || !annotations)
1462 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1481 Q_ASSERT(cbD->commands.isEmpty());
1483 if (cbD->currentTarget) {
1487 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1506 if (swapChainD->frameLatencyWaitableObject) {
1509 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1514 swapChainD->cb.resetState();
1516 swapChainD->rt.d.views.setFrom(1,
1517 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1518 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1523 double elapsedSec = 0;
1525 swapChainD->cb.lastGpuTime = elapsedSec;
1534 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1535 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1536 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1537 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1539 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1541 return QRhi::FrameOpSuccess;
1552 cmd.args.endFrame.tsQuery =
nullptr;
1553 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1558 if (swapChainD->sampleDesc.Count > 1) {
1559 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1560 swapChainD->msaaTex[currentFrameSlot], 0,
1561 swapChainD->colorFormat);
1568 if (recordTimestamps) {
1569 context->End(tsEnd);
1570 context->End(tsDisjoint);
1575 if (!flags.testFlag(QRhi::SkipPresent)) {
1576 UINT presentFlags = 0;
1577 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1578 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1579 if (!swapChainD->swapChain) {
1580 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1581 return QRhi::FrameOpError;
1583 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1584 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1585 qWarning(
"Device loss detected in Present()");
1587 return QRhi::FrameOpDeviceLost;
1588 }
else if (FAILED(hr)) {
1589 qWarning(
"Failed to present: %s",
1590 qPrintable(QSystemError::windowsComString(hr)));
1591 return QRhi::FrameOpError;
1594 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1595 dcompDevice->Commit();
1606 return QRhi::FrameOpSuccess;
1614 ofr.cbWrapper.resetState();
1615 *cb = &ofr.cbWrapper;
1617 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1618 D3D11_QUERY_DESC queryDesc = {};
1619 if (!ofr.tsDisjointQuery) {
1620 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1621 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1623 qWarning(
"Failed to create timestamp disjoint query: %s",
1624 qPrintable(QSystemError::windowsComString(hr)));
1625 return QRhi::FrameOpError;
1628 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1629 for (
int i = 0; i < 2; ++i) {
1630 if (!ofr.tsQueries[i]) {
1631 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1633 qWarning(
"Failed to create timestamp query: %s",
1634 qPrintable(QSystemError::windowsComString(hr)));
1635 return QRhi::FrameOpError;
1643 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1644 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1645 cmd.args.beginFrame.swapchainRtv =
nullptr;
1646 cmd.args.beginFrame.swapchainDsv =
nullptr;
1648 return QRhi::FrameOpSuccess;
1658 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1659 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1666 if (ofr.tsQueries[0]) {
1667 quint64 timestamps[2];
1668 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1672 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1673 }
while (hr == S_FALSE);
1676 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1677 }
while (hr == S_FALSE);
1680 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1681 }
while (hr == S_FALSE);
1684 if (!dj.Disjoint && dj.Frequency) {
1685 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1686 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1691 return QRhi::FrameOpSuccess;
1696 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1698 case QRhiTexture::RGBA8:
1699 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1700 case QRhiTexture::BGRA8:
1701 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1702 case QRhiTexture::R8:
1703 return DXGI_FORMAT_R8_UNORM;
1704 case QRhiTexture::R8SI:
1705 return DXGI_FORMAT_R8_SINT;
1706 case QRhiTexture::R8UI:
1707 return DXGI_FORMAT_R8_UINT;
1708 case QRhiTexture::RG8:
1709 return DXGI_FORMAT_R8G8_UNORM;
1710 case QRhiTexture::R16:
1711 return DXGI_FORMAT_R16_UNORM;
1712 case QRhiTexture::RG16:
1713 return DXGI_FORMAT_R16G16_UNORM;
1714 case QRhiTexture::RED_OR_ALPHA8:
1715 return DXGI_FORMAT_R8_UNORM;
1717 case QRhiTexture::RGBA16F:
1718 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1719 case QRhiTexture::RGBA32F:
1720 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1721 case QRhiTexture::R16F:
1722 return DXGI_FORMAT_R16_FLOAT;
1723 case QRhiTexture::R32F:
1724 return DXGI_FORMAT_R32_FLOAT;
1726 case QRhiTexture::RGB10A2:
1727 return DXGI_FORMAT_R10G10B10A2_UNORM;
1729 case QRhiTexture::R32SI:
1730 return DXGI_FORMAT_R32_SINT;
1731 case QRhiTexture::R32UI:
1732 return DXGI_FORMAT_R32_UINT;
1733 case QRhiTexture::RG32SI:
1734 return DXGI_FORMAT_R32G32_SINT;
1735 case QRhiTexture::RG32UI:
1736 return DXGI_FORMAT_R32G32_UINT;
1737 case QRhiTexture::RGBA32SI:
1738 return DXGI_FORMAT_R32G32B32A32_SINT;
1739 case QRhiTexture::RGBA32UI:
1740 return DXGI_FORMAT_R32G32B32A32_UINT;
1742 case QRhiTexture::D16:
1743 return DXGI_FORMAT_R16_TYPELESS;
1744 case QRhiTexture::D24:
1745 return DXGI_FORMAT_R24G8_TYPELESS;
1746 case QRhiTexture::D24S8:
1747 return DXGI_FORMAT_R24G8_TYPELESS;
1748 case QRhiTexture::D32F:
1749 return DXGI_FORMAT_R32_TYPELESS;
1750 case QRhiTexture::D32FS8:
1751 return DXGI_FORMAT_R32G8X24_TYPELESS;
1753 case QRhiTexture::BC1:
1754 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1755 case QRhiTexture::BC2:
1756 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1757 case QRhiTexture::BC3:
1758 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1759 case QRhiTexture::BC4:
1760 return DXGI_FORMAT_BC4_UNORM;
1761 case QRhiTexture::BC5:
1762 return DXGI_FORMAT_BC5_UNORM;
1763 case QRhiTexture::BC6H:
1764 return DXGI_FORMAT_BC6H_UF16;
1765 case QRhiTexture::BC7:
1766 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1768 case QRhiTexture::ETC2_RGB8:
1769 case QRhiTexture::ETC2_RGB8A1:
1770 case QRhiTexture::ETC2_RGBA8:
1771 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1772 return DXGI_FORMAT_R8G8B8A8_UNORM;
1774 case QRhiTexture::ASTC_4x4:
1775 case QRhiTexture::ASTC_5x4:
1776 case QRhiTexture::ASTC_5x5:
1777 case QRhiTexture::ASTC_6x5:
1778 case QRhiTexture::ASTC_6x6:
1779 case QRhiTexture::ASTC_8x5:
1780 case QRhiTexture::ASTC_8x6:
1781 case QRhiTexture::ASTC_8x8:
1782 case QRhiTexture::ASTC_10x5:
1783 case QRhiTexture::ASTC_10x6:
1784 case QRhiTexture::ASTC_10x8:
1785 case QRhiTexture::ASTC_10x10:
1786 case QRhiTexture::ASTC_12x10:
1787 case QRhiTexture::ASTC_12x12:
1788 qWarning(
"QRhiD3D11 does not support ASTC textures");
1789 return DXGI_FORMAT_R8G8B8A8_UNORM;
1793 return DXGI_FORMAT_R8G8B8A8_UNORM;
1800 case DXGI_FORMAT_R8G8B8A8_UNORM:
1801 return QRhiTexture::RGBA8;
1802 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1804 (*flags) |= QRhiTexture::sRGB;
1805 return QRhiTexture::RGBA8;
1806 case DXGI_FORMAT_B8G8R8A8_UNORM:
1807 return QRhiTexture::BGRA8;
1808 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1810 (*flags) |= QRhiTexture::sRGB;
1811 return QRhiTexture::BGRA8;
1812 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1813 return QRhiTexture::RGBA16F;
1814 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1815 return QRhiTexture::RGBA32F;
1816 case DXGI_FORMAT_R10G10B10A2_UNORM:
1817 return QRhiTexture::RGB10A2;
1819 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1822 return QRhiTexture::UnknownFormat;
1828 case QRhiTexture::Format::D16:
1829 case QRhiTexture::Format::D24:
1830 case QRhiTexture::Format::D24S8:
1831 case QRhiTexture::Format::D32F:
1832 case QRhiTexture::Format::D32FS8:
1845 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1847 ofr.cbWrapper.resetCommands();
1858 return QRhi::FrameOpSuccess;
1862 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1864 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1865 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1867 box.front = is3D ? UINT(layer) : 0u;
1869 box.back = box.front + 1;
1872 cmd.args.updateSubRes.dst = texD->textureResource();
1873 cmd.args.updateSubRes.dstSubRes = subres;
1875 const QPoint dp = subresDesc.destinationTopLeft();
1876 if (!subresDesc.image().isNull()) {
1877 QImage img = subresDesc.image();
1878 QSize size = img.size();
1879 int bpl = img.bytesPerLine();
1880 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1881 const QPoint sp = subresDesc.sourceTopLeft();
1882 if (!subresDesc.sourceSize().isEmpty())
1883 size = subresDesc.sourceSize();
1884 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1885 if (img.depth() == 32) {
1886 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1887 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1889 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1890 bpl = img.bytesPerLine();
1891 cmd.args.updateSubRes.src = cbD->retainImage(img);
1894 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1895 cmd.args.updateSubRes.src = cbD->retainImage(img);
1897 box.left = UINT(dp.x());
1898 box.top = UINT(dp.y());
1899 box.right = UINT(dp.x() + size.width());
1900 box.bottom = UINT(dp.y() + size.height());
1901 cmd.args.updateSubRes.hasDstBox =
true;
1902 cmd.args.updateSubRes.dstBox = box;
1903 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1904 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1905 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1906 : subresDesc.sourceSize();
1909 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1913 box.left = UINT(aligned(dp.x(), blockDim.width()));
1914 box.top = UINT(aligned(dp.y(), blockDim.height()));
1915 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1916 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1917 cmd.args.updateSubRes.hasDstBox =
true;
1918 cmd.args.updateSubRes.dstBox = box;
1919 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1920 cmd.args.updateSubRes.srcRowPitch = bpl;
1921 }
else if (!subresDesc.data().isEmpty()) {
1922 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1923 : subresDesc.sourceSize();
1925 if (subresDesc.dataStride())
1926 bpl = subresDesc.dataStride();
1928 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1929 box.left = UINT(dp.x());
1930 box.top = UINT(dp.y());
1931 box.right = UINT(dp.x() + size.width());
1932 box.bottom = UINT(dp.y() + size.height());
1933 cmd.args.updateSubRes.hasDstBox =
true;
1934 cmd.args.updateSubRes.dstBox = box;
1935 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1936 cmd.args.updateSubRes.srcRowPitch = bpl;
1938 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1939 cbD->commands.unget();
1952 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1957 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1958 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1961 cmd.args.updateSubRes.dst = bufD->buffer;
1962 cmd.args.updateSubRes.dstSubRes = 0;
1963 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1964 cmd.args.updateSubRes.srcRowPitch = 0;
1969 box.left = u.offset;
1970 box.top = box.front = 0;
1971 box.back = box.bottom = 1;
1972 box.right = u.offset + u
.data.size();
1973 cmd.args.updateSubRes.hasDstBox =
true;
1974 cmd.args.updateSubRes.dstBox = box;
1977 if (bufD->m_type == QRhiBuffer::Dynamic) {
1978 u.result->data.resize(u.readSize);
1979 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1980 if (u.result->completed)
1981 u.result->completed();
1984 readback.result = u.result;
1985 readback.byteSize = u.readSize;
1987 D3D11_BUFFER_DESC desc = {};
1988 desc.ByteWidth = readback.byteSize;
1989 desc.Usage = D3D11_USAGE_STAGING;
1990 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1991 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1993 qWarning(
"Failed to create buffer: %s",
1994 qPrintable(QSystemError::windowsComString(hr)));
2000 cmd.args.copySubRes.dst = readback.stagingBuf;
2001 cmd.args.copySubRes.dstSubRes = 0;
2002 cmd.args.copySubRes.dstX = 0;
2003 cmd.args.copySubRes.dstY = 0;
2004 cmd.args.copySubRes.dstZ = 0;
2005 cmd.args.copySubRes.src = bufD->buffer;
2006 cmd.args.copySubRes.srcSubRes = 0;
2007 cmd.args.copySubRes.hasSrcBox =
true;
2009 box.left = u.offset;
2010 box.top = box.front = 0;
2011 box.back = box.bottom = 1;
2012 box.right = u.offset + u.readSize;
2013 cmd.args.copySubRes.srcBox = box;
2015 activeBufferReadbacks.append(readback);
2023 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2024 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2025 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2026 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2033 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2034 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2035 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2036 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2037 const QPoint dp = u.desc.destinationTopLeft();
2038 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2039 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2040 const QPoint sp = u.desc.sourceTopLeft();
2042 srcBox.left = UINT(sp.x());
2043 srcBox.top = UINT(sp.y());
2044 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2046 srcBox.right = srcBox.left + UINT(copySize.width());
2047 srcBox.bottom = srcBox.top + UINT(copySize.height());
2048 srcBox.back = srcBox.front + 1;
2051 cmd.args.copySubRes.dst = dstD->textureResource();
2052 cmd.args.copySubRes.dstSubRes = dstSubRes;
2053 cmd.args.copySubRes.dstX = UINT(dp.x());
2054 cmd.args.copySubRes.dstY = UINT(dp.y());
2055 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2056 cmd.args.copySubRes.src = srcD->textureResource();
2057 cmd.args.copySubRes.srcSubRes = srcSubRes;
2058 cmd.args.copySubRes.hasSrcBox =
true;
2059 cmd.args.copySubRes.srcBox = srcBox;
2062 readback.desc = u.rb;
2063 readback.result = u.result;
2065 ID3D11Resource *src;
2066 DXGI_FORMAT dxgiFormat;
2068 QRhiTexture::Format format;
2075 if (texD->sampleDesc.Count > 1) {
2076 qWarning(
"Multisample texture cannot be read back");
2079 src = texD->textureResource();
2080 dxgiFormat = texD->dxgiFormat;
2081 if (u.rb.rect().isValid())
2084 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2085 format = texD->m_format;
2086 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2087 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2091 if (swapChainD->sampleDesc.Count > 1) {
2096 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2097 rcmd.args.resolveSubRes.dstSubRes = 0;
2099 rcmd.args.resolveSubRes.srcSubRes = 0;
2100 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2102 src = swapChainD->backBufferTex;
2103 dxgiFormat = swapChainD->colorFormat;
2104 if (u.rb.rect().isValid())
2107 rect = QRect({0, 0}, swapChainD->pixelSize);
2108 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2109 if (format == QRhiTexture::UnknownFormat)
2112 quint32 byteSize = 0;
2114 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2116 D3D11_TEXTURE2D_DESC desc = {};
2117 desc.Width = UINT(rect.width());
2118 desc.Height = UINT(rect.height());
2121 desc.Format = dxgiFormat;
2122 desc.SampleDesc.Count = 1;
2123 desc.Usage = D3D11_USAGE_STAGING;
2124 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2125 ID3D11Texture2D *stagingTex;
2126 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2128 qWarning(
"Failed to create readback staging texture: %s",
2129 qPrintable(QSystemError::windowsComString(hr)));
2135 cmd.args.copySubRes.dst = stagingTex;
2136 cmd.args.copySubRes.dstSubRes = 0;
2137 cmd.args.copySubRes.dstX = 0;
2138 cmd.args.copySubRes.dstY = 0;
2139 cmd.args.copySubRes.dstZ = 0;
2140 cmd.args.copySubRes.src = src;
2141 cmd.args.copySubRes.srcSubRes = subres;
2143 D3D11_BOX srcBox = {};
2144 srcBox.left = UINT(rect.left());
2145 srcBox.top = UINT(rect.top());
2146 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2148 srcBox.right = srcBox.left + desc.Width;
2149 srcBox.bottom = srcBox.top + desc.Height;
2150 srcBox.back = srcBox.front + 1;
2151 cmd.args.copySubRes.hasSrcBox =
true;
2152 cmd.args.copySubRes.srcBox = srcBox;
2154 readback.stagingTex = stagingTex;
2155 readback.byteSize = byteSize;
2157 readback.pixelSize = rect.size();
2158 readback.format = format;
2160 activeTextureReadbacks.append(readback);
2162 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2165 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2174 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2176 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2178 readback.result->format = readback.format;
2179 readback.result->pixelSize = readback.pixelSize;
2181 D3D11_MAPPED_SUBRESOURCE mp;
2182 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2183 if (SUCCEEDED(hr)) {
2184 readback.result->data.resize(
int(readback.byteSize));
2187 char *dst = readback.result->data.data();
2188 char *src =
static_cast<
char *>(mp.pData);
2189 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2190 memcpy(dst, src, readback.bpl);
2191 dst += readback.bpl;
2194 context->Unmap(readback.stagingTex, 0);
2196 qWarning(
"Failed to map readback staging texture: %s",
2197 qPrintable(QSystemError::windowsComString(hr)));
2200 readback.stagingTex->Release();
2202 if (readback.result->completed)
2203 completedCallbacks.append(readback.result->completed);
2205 activeTextureReadbacks.removeLast();
2208 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2211 D3D11_MAPPED_SUBRESOURCE mp;
2212 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2213 if (SUCCEEDED(hr)) {
2214 readback.result->data.resize(
int(readback.byteSize));
2215 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2216 context->Unmap(readback.stagingBuf, 0);
2218 qWarning(
"Failed to map readback staging texture: %s",
2219 qPrintable(QSystemError::windowsComString(hr)));
2222 readback.stagingBuf->Release();
2224 if (readback.result->completed)
2225 completedCallbacks.append(readback.result->completed);
2227 activeBufferReadbacks.removeLast();
2230 for (
auto f : completedCallbacks)
2236 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2242 QRhiRenderTarget *rt,
2243 const QColor &colorClearValue,
2244 const QRhiDepthStencilClearValue &depthStencilClearValue,
2245 QRhiResourceUpdateBatch *resourceUpdates,
2251 if (resourceUpdates)
2254 bool wantsColorClear =
true;
2255 bool wantsDsClear =
true;
2257 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2259 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2260 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2261 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2269 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2273 clearCmd.args.clear.rtViews = rtD->views;
2274 clearCmd.args.clear.mask = 0;
2275 if (rtD->views.colorAttCount && wantsColorClear)
2277 if (rtD->views.dsv && wantsDsClear)
2280 clearCmd.args.clear.c[0] = colorClearValue.redF();
2281 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2282 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2283 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2284 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2285 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2288 cbD->currentTarget = rt;
2298 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2300 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2303 const QRhiColorAttachment &colorAtt(*it);
2304 if (!colorAtt.resolveTexture())
2310 Q_ASSERT(srcTexD || srcRbD);
2313 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2314 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2315 UINT(colorAtt.resolveLayer()),
2316 dstTexD->mipLevelCount);
2318 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2319 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2320 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2321 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2322 cbD->commands.unget();
2325 if (srcTexD->sampleDesc.Count <= 1) {
2326 qWarning(
"Cannot resolve a non-multisample texture");
2327 cbD->commands.unget();
2330 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2331 qWarning(
"Resolve source and destination sizes do not match");
2332 cbD->commands.unget();
2336 cmd.args.resolveSubRes.src = srcRbD->tex;
2337 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2338 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2339 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2340 cbD->commands.unget();
2343 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2344 qWarning(
"Resolve source and destination sizes do not match");
2345 cbD->commands.unget();
2349 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2350 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2352 if (rtTex->m_desc.depthResolveTexture())
2353 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2357 cbD->currentTarget =
nullptr;
2359 if (resourceUpdates)
2364 QRhiResourceUpdateBatch *resourceUpdates,
2370 if (resourceUpdates)
2388 if (resourceUpdates)
2397 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2399 if (pipelineChanged) {
2400 cbD->currentGraphicsPipeline =
nullptr;
2401 cbD->currentComputePipeline = psD;
2402 cbD->currentPipelineGeneration = psD->generation;
2406 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2417 cmd.args.dispatch.x = UINT(x);
2418 cmd.args.dispatch.y = UINT(y);
2419 cmd.args.dispatch.z = UINT(z);
2424 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2426 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2427 if (!map || map->isEmpty())
2428 return { binding, binding };
2430 auto it = map->constFind(binding);
2431 if (it != map->cend())
2441 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2443 srbD->resourceBatches.clear();
2449 ID3D11Buffer *buffer;
2450 uint offsetInConstants;
2451 uint sizeInConstants;
2455 ID3D11ShaderResourceView *srv;
2459 ID3D11SamplerState *sampler;
2463 ID3D11UnorderedAccessView *uav;
2465 QVarLengthArray<Buffer, 8> buffers;
2466 QVarLengthArray<Texture, 8> textures;
2467 QVarLengthArray<Sampler, 8> samplers;
2468 QVarLengthArray<Uav, 8> uavs;
2471 for (
const Buffer &buf : buffers) {
2472 batches.ubufs.feed(buf.breg, buf.buffer);
2473 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2474 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2475 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2481 for (
const Texture &t : textures)
2482 batches.shaderresources.feed(t.treg, t.srv);
2483 for (
const Sampler &s : samplers)
2484 batches.samplers.feed(s.sreg, s.sampler);
2489 for (
const Stage::Uav &u : uavs)
2490 batches.uavs.feed(u.ureg, u.uav);
2495 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2496 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2499 case QRhiShaderResourceBinding::UniformBuffer:
2502 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2503 bd.ubuf.id = bufD->m_id;
2504 bd.ubuf.generation = bufD->generation;
2511 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2515 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2516 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2517 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2518 if (nativeBinding.first >= 0)
2519 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2521 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2522 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2523 if (nativeBinding.first >= 0)
2524 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2526 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2527 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2528 if (nativeBinding.first >= 0)
2529 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2531 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2532 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2533 if (nativeBinding.first >= 0)
2534 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2536 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2537 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2538 if (nativeBinding.first >= 0)
2539 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2541 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2542 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2543 if (nativeBinding.first >= 0)
2544 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2548 case QRhiShaderResourceBinding::SampledTexture:
2549 case QRhiShaderResourceBinding::Texture:
2550 case QRhiShaderResourceBinding::Sampler:
2552 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2553 bd.stex.count = data->count;
2554 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2555 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2556 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2557 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2558 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2559 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2563 for (
int elem = 0; elem < data->count; ++elem) {
2566 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2567 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2568 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2569 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2574 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2575 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2576 : (samplerD ? nativeBindingVert.first : -1);
2577 if (nativeBindingVert.first >= 0 && texD)
2578 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2579 if (samplerBinding >= 0)
2580 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2582 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2583 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2584 : (samplerD ? nativeBindingHull.first : -1);
2585 if (nativeBindingHull.first >= 0 && texD)
2586 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2587 if (samplerBinding >= 0)
2588 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2590 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2591 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2592 : (samplerD ? nativeBindingDomain.first : -1);
2593 if (nativeBindingDomain.first >= 0 && texD)
2594 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2595 if (samplerBinding >= 0)
2596 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2598 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2599 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2600 : (samplerD ? nativeBindingGeom.first : -1);
2601 if (nativeBindingGeom.first >= 0 && texD)
2602 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2603 if (samplerBinding >= 0)
2604 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2606 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2607 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2608 : (samplerD ? nativeBindingFrag.first : -1);
2609 if (nativeBindingFrag.first >= 0 && texD)
2610 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2611 if (samplerBinding >= 0)
2612 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2614 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2615 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2616 : (samplerD ? nativeBindingComp.first : -1);
2617 if (nativeBindingComp.first >= 0 && texD)
2618 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2619 if (samplerBinding >= 0)
2620 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2625 case QRhiShaderResourceBinding::ImageLoad:
2626 case QRhiShaderResourceBinding::ImageStore:
2627 case QRhiShaderResourceBinding::ImageLoadStore:
2630 bd.simage.id = texD->m_id;
2631 bd.simage.generation = texD->generation;
2632 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2633 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2634 if (nativeBinding.first >= 0) {
2635 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2637 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2639 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2640 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2641 if (nativeBinding.first >= 0) {
2642 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2644 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2647 qWarning(
"Unordered access only supported at fragment/compute stage");
2651 case QRhiShaderResourceBinding::BufferLoad:
2652 case QRhiShaderResourceBinding::BufferStore:
2653 case QRhiShaderResourceBinding::BufferLoadStore:
2656 bd.sbuf.id = bufD->m_id;
2657 bd.sbuf.generation = bufD->generation;
2658 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2659 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2660 if (nativeBinding.first >= 0) {
2661 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2663 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2666 qWarning(
"Unordered access only supported at compute stage");
2681 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2682 return a.breg < b.breg;
2684 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2685 return a.treg < b.treg;
2687 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2688 return a.sreg < b.sreg;
2690 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2691 return a.ureg < b.ureg;
2695 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2696 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2697 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2698 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2699 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2700 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2702 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2703 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2704 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2705 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2706 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2707 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2709 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2710 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2718 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2720 D3D11_MAPPED_SUBRESOURCE mp;
2721 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2722 if (SUCCEEDED(hr)) {
2723 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2724 context->Unmap(bufD->buffer, 0);
2726 qWarning(
"Failed to map buffer: %s",
2727 qPrintable(QSystemError::windowsComString(hr)));
2733 const QRhiBatchedBindings<UINT> *originalBindings,
2734 const QRhiBatchedBindings<UINT> *staticOffsets,
2735 const uint *dynOfsPairs,
int dynOfsPairCount)
2737 const int count = staticOffsets->batches[batchIndex].resources.count();
2740 for (
int b = 0; b < count; ++b) {
2741 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2742 for (
int di = 0; di < dynOfsPairCount; ++di) {
2743 const uint binding = dynOfsPairs[2 * di];
2746 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2747 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2748 offsets[b] = offsetInConstants;
2757 if (startSlot + countSlots > maxSlots) {
2758 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2759 resType, countSlots, startSlot, maxSlots);
2760 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2765#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2766 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2767 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2768 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2769 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2770 batches.ubufs.batches[i].resources.count(),
2771 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2772 #stagePrefixU " cbuf");
2774 if (!dynOfsPairCount) {
2775 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2777 batches.ubufs.batches[i].resources.constData(),
2778 batches.ubufoffsets.batches[i].resources.constData(),
2779 batches.ubufsizes.batches[i].resources.constData());
2781 applyDynamicOffsets(offsets, i,
2782 &batches.ubuforigbindings, &batches.ubufoffsets,
2783 dynOfsPairs, dynOfsPairCount);
2784 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2786 batches.ubufs.batches[i].resources.constData(),
2788 batches.ubufsizes.batches[i].resources.constData());
2794#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2795 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2796 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2797 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2798 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2800 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2802 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2803 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2804 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2806 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2807 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2808 int(batch.startBinding + count) - 1
);
2813#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2814 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2815 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2816 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2819 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2821 batch.resources.constData(),
2823 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2824 int(batch.startBinding + count) - 1
);
2831 const uint *dynOfsPairs,
int dynOfsPairCount,
2832 bool offsetOnlyChange,
2844 if (!offsetOnlyChange) {
2854 if (allResourceBatches.fsUavBatches.present) {
2855 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2856 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2858 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2860 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
2861 context->OMSetRenderTargetsAndUnorderedAccessViews(
2862 UINT(rtUavState->rtViews.colorAttCount),
2863 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
2864 rtUavState->rtViews.dsv,
2865 UINT(rtUavState->rtViews.colorAttCount),
2867 batch.resources.constData(),
2870 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2871 int(batch.startBinding + count) - 1);
2884 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2890 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2891 for (
int i = 0; i < count; ++i)
2892 nullbufs[i] =
nullptr;
2893 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2894 for (
int i = 0; i < count; ++i)
2896 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2897 for (
int i = 0; i < count; ++i)
2899 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2909 if (nullsrvCount > 0) {
2910 QVarLengthArray<ID3D11ShaderResourceView *,
2911 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2912 for (
int i = 0; i < nullsrvs.count(); ++i)
2913 nullsrvs[i] =
nullptr;
2915 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2919 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2923 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2927 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2931 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2935 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2941 rtUavState->update(cbD->currentRenderTargetViews);
2942 context->OMSetRenderTargetsAndUnorderedAccessViews(
2943 UINT(cbD->currentRenderTargetViews.colorAttCount),
2944 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
2945 cbD->currentRenderTargetViews.dsv,
2946 0, 0,
nullptr,
nullptr);
2951 QVarLengthArray<ID3D11UnorderedAccessView *,
2952 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2953 for (
int i = 0; i < nulluavCount; ++i)
2954 nulluavs[i] =
nullptr;
2955 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2960#define SETSHADER(StageL, StageU)
2961 if (cmd.args.bindGraphicsPipeline.StageL) {
2962 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
2963 currentShaderMask |= StageU##MaskBit;
2964 } else if (currentShaderMask & StageU##MaskBit) {
2965 context->StageU##SetShader(nullptr, nullptr, 0
);
2966 currentShaderMask &= ~StageU##MaskBit;
2971 quint32 stencilRef = 0;
2972 float blendConstants[] = { 1, 1, 1, 1 };
2973 enum ActiveShaderMask {
2980 int currentShaderMask = 0xFF;
2986 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2989 case QD3D11CommandBuffer::Command::BeginFrame:
2990 if (cmd.args.beginFrame.tsDisjointQuery)
2991 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2992 if (cmd.args.beginFrame.tsQuery) {
2993 if (cmd.args.beginFrame.swapchainRtv) {
2998 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
2999 rtUavState.update(cbD->currentRenderTargetViews);
3000 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3002 context->End(cmd.args.beginFrame.tsQuery);
3005 case QD3D11CommandBuffer::Command::EndFrame:
3006 if (cmd.args.endFrame.tsQuery)
3007 context->End(cmd.args.endFrame.tsQuery);
3008 if (cmd.args.endFrame.tsDisjointQuery)
3009 context->End(cmd.args.endFrame.tsDisjointQuery);
3016 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3017 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3018 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3019 context->OMSetRenderTargets(colorAttCount,
3020 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3021 cmd.args.setRenderTarget.rtViews.dsv);
3028 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3029 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3032 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3033 ds |= D3D11_CLEAR_DEPTH;
3034 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3035 ds |= D3D11_CLEAR_STENCIL;
3036 if (ds && cmd.args.clear.rtViews.dsv)
3037 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3043 v.TopLeftX = cmd.args.viewport.x;
3044 v.TopLeftY = cmd.args.viewport.y;
3045 v.Width = cmd.args.viewport.w;
3046 v.Height = cmd.args.viewport.h;
3047 v.MinDepth = cmd.args.viewport.d0;
3048 v.MaxDepth = cmd.args.viewport.d1;
3049 context->RSSetViewports(1, &v);
3055 r.left = cmd.args.scissor.x;
3056 r.top = cmd.args.scissor.y;
3058 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3059 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3060 context->RSSetScissorRects(1, &r);
3066 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3067 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3068 UINT(cmd.args.bindVertexBuffers.slotCount),
3069 cmd.args.bindVertexBuffers.buffers,
3070 cmd.args.bindVertexBuffers.strides,
3071 cmd.args.bindVertexBuffers.offsets);
3075 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3076 cmd.args.bindIndexBuffer.format,
3077 cmd.args.bindIndexBuffer.offset);
3086 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3087 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3088 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3089 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3090 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3093 case QD3D11CommandBuffer::Command::BindShaderResources:
3094 bindShaderResources(cbD,
3095 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3096 cmd.args.bindShaderResources.dynamicOffsetPairs,
3097 cmd.args.bindShaderResources.dynamicOffsetCount,
3098 cmd.args.bindShaderResources.offsetOnlyChange,
3102 stencilRef = cmd.args.stencilRef.ref;
3103 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3106 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3107 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3109 case QD3D11CommandBuffer::Command::Draw:
3110 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3111 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3113 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3114 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3116 case QD3D11CommandBuffer::Command::DrawIndexed:
3117 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3118 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3119 cmd.args.drawIndexed.vertexOffset);
3121 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3122 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3123 cmd.args.drawIndexed.firstInstance);
3127 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3128 const UINT stride = cmd.args.drawIndirect.stride;
3129 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3130 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3131 alignedByteOffsetForArgs += stride;
3137 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3138 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3139 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3140 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3141 alignedByteOffsetForArgs += stride;
3145 case QD3D11CommandBuffer::Command::UpdateSubRes:
3146 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3147 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3148 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3150 case QD3D11CommandBuffer::Command::CopySubRes:
3151 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3152 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3153 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3154 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3156 case QD3D11CommandBuffer::Command::ResolveSubRes:
3157 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3158 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3159 cmd.args.resolveSubRes.format);
3161 case QD3D11CommandBuffer::Command::GenMip:
3162 context->GenerateMips(cmd.args.genMip.srv);
3164 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3165 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3167 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3168 annotations->EndEvent();
3170 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3171 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3173 case QD3D11CommandBuffer::Command::BindComputePipeline:
3174 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3176 case QD3D11CommandBuffer::Command::Dispatch:
3177 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3206 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3207 it.value()->Release();
3212 rhiD->unregisterResource(
this);
3218 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3219 u |= D3D11_BIND_VERTEX_BUFFER;
3220 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3221 u |= D3D11_BIND_INDEX_BUFFER;
3222 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3223 u |= D3D11_BIND_CONSTANT_BUFFER;
3224 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3225 u |= D3D11_BIND_UNORDERED_ACCESS;
3234 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3235 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3239 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3240 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3244 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3245 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3249 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3250 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3252 D3D11_BUFFER_DESC desc = {};
3253 desc.ByteWidth = roundedSize;
3254 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3255 desc.BindFlags = toD3DBufferUsage(m_usage);
3256 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3257 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3258 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3259 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3262 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3264 qWarning(
"Failed to create buffer: %s",
3265 qPrintable(QSystemError::windowsComString(hr)));
3269 if (m_type == Dynamic) {
3270 dynBuf =
new char[nonZeroSize];
3274 if (!m_objectName.isEmpty())
3275 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3278 rhiD->registerResource(
this);
3284 if (m_type == Dynamic) {
3288 return { { &buffer }, 1 };
3299 Q_ASSERT(m_type == Dynamic);
3300 D3D11_MAPPED_SUBRESOURCE mp;
3302 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3304 qWarning(
"Failed to map buffer: %s",
3305 qPrintable(QSystemError::windowsComString(hr)));
3308 return static_cast<
char *>(mp.pData);
3314 rhiD->context->Unmap(buffer, 0);
3319 auto it = uavs.find(offset);
3320 if (it != uavs.end())
3324 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3325 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3326 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3327 desc.Buffer.FirstElement = offset / 4u;
3328 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3329 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3332 ID3D11UnorderedAccessView *uav =
nullptr;
3333 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3335 qWarning(
"Failed to create UAV: %s",
3336 qPrintable(QSystemError::windowsComString(hr)));
3345 int sampleCount, QRhiRenderBuffer::Flags flags,
3346 QRhiTexture::Format backingFormatHint)
3376 rhiD->unregisterResource(
this);
3384 if (m_pixelSize.isEmpty())
3388 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3390 D3D11_TEXTURE2D_DESC desc = {};
3391 desc.Width = UINT(m_pixelSize.width());
3392 desc.Height = UINT(m_pixelSize.height());
3395 desc.SampleDesc = sampleDesc;
3396 desc.Usage = D3D11_USAGE_DEFAULT;
3398 if (m_type == Color) {
3399 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3400 : toD3DTextureFormat(m_backingFormatHint, {});
3401 desc.Format = dxgiFormat;
3402 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3403 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3405 qWarning(
"Failed to create color renderbuffer: %s",
3406 qPrintable(QSystemError::windowsComString(hr)));
3409 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3410 rtvDesc.Format = dxgiFormat;
3411 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3412 : D3D11_RTV_DIMENSION_TEXTURE2D;
3413 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3415 qWarning(
"Failed to create rtv: %s",
3416 qPrintable(QSystemError::windowsComString(hr)));
3419 }
else if (m_type == DepthStencil) {
3420 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3421 desc.Format = dxgiFormat;
3422 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3423 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3425 qWarning(
"Failed to create depth-stencil buffer: %s",
3426 qPrintable(QSystemError::windowsComString(hr)));
3429 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3430 dsvDesc.Format = dxgiFormat;
3431 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3432 : D3D11_DSV_DIMENSION_TEXTURE2D;
3433 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3435 qWarning(
"Failed to create dsv: %s",
3436 qPrintable(QSystemError::windowsComString(hr)));
3443 if (!m_objectName.isEmpty())
3444 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3447 rhiD->registerResource(
this);
3453 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3454 return m_backingFormatHint;
3456 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3460 int arraySize,
int sampleCount, Flags flags)
3463 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3464 perLevelViews[i] =
nullptr;
3474 if (!tex && !tex3D && !tex1D)
3482 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3483 if (perLevelViews[i]) {
3484 perLevelViews[i]->Release();
3485 perLevelViews[i] =
nullptr;
3504 rhiD->unregisterResource(
this);
3510 case QRhiTexture::Format::D16:
3511 return DXGI_FORMAT_R16_FLOAT;
3512 case QRhiTexture::Format::D24:
3513 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3514 case QRhiTexture::Format::D24S8:
3515 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3516 case QRhiTexture::Format::D32F:
3517 return DXGI_FORMAT_R32_FLOAT;
3518 case QRhiTexture::Format::D32FS8:
3519 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3522 return DXGI_FORMAT_R32_FLOAT;
3529 case QRhiTexture::Format::D16:
3530 return DXGI_FORMAT_D16_UNORM;
3531 case QRhiTexture::Format::D24:
3532 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3533 case QRhiTexture::Format::D24S8:
3534 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3535 case QRhiTexture::Format::D32F:
3536 return DXGI_FORMAT_D32_FLOAT;
3537 case QRhiTexture::Format::D32FS8:
3538 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3541 return DXGI_FORMAT_D32_FLOAT;
3547 if (tex || tex3D || tex1D)
3551 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3554 const bool isDepth = isDepthTextureFormat(m_format);
3555 const bool isCube = m_flags.testFlag(CubeMap);
3556 const bool is3D = m_flags.testFlag(ThreeDimensional);
3557 const bool isArray = m_flags.testFlag(TextureArray);
3558 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3559 const bool is1D = m_flags.testFlag(OneDimensional);
3561 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3562 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3564 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3565 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3566 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3567 if (sampleDesc.Count > 1) {
3569 qWarning(
"Cubemap texture cannot be multisample");
3573 qWarning(
"3D texture cannot be multisample");
3577 qWarning(
"Multisample texture cannot have mipmaps");
3581 if (isDepth && hasMipMaps) {
3582 qWarning(
"Depth texture cannot have mipmaps");
3585 if (isCube && is3D) {
3586 qWarning(
"Texture cannot be both cube and 3D");
3589 if (isArray && is3D) {
3590 qWarning(
"Texture cannot be both array and 3D");
3593 if (isCube && is1D) {
3594 qWarning(
"Texture cannot be both cube and 1D");
3598 qWarning(
"Texture cannot be both 1D and 3D");
3601 if (m_depth > 1 && !is3D) {
3602 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3605 if (m_arraySize > 0 && !isArray) {
3606 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3609 if (m_arraySize < 1 && isArray) {
3610 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3615 *adjustedSize = size;
3623 const bool isDepth = isDepthTextureFormat(m_format);
3624 const bool isCube = m_flags.testFlag(CubeMap);
3625 const bool is3D = m_flags.testFlag(ThreeDimensional);
3626 const bool isArray = m_flags.testFlag(TextureArray);
3627 const bool is1D = m_flags.testFlag(OneDimensional);
3629 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3630 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3632 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3633 srvDesc.TextureCube.MipLevels = mipLevelCount;
3637 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3638 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3639 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3640 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3641 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3643 srvDesc.Texture1DArray.FirstArraySlice = 0;
3644 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3647 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3648 srvDesc.Texture1D.MipLevels = mipLevelCount;
3650 }
else if (isArray) {
3651 if (sampleDesc.Count > 1) {
3652 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3653 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3654 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3655 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3657 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3658 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3661 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3662 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3663 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3664 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3665 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3667 srvDesc.Texture2DArray.FirstArraySlice = 0;
3668 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3672 if (sampleDesc.Count > 1) {
3673 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3675 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3676 srvDesc.Texture3D.MipLevels = mipLevelCount;
3678 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3679 srvDesc.Texture2D.MipLevels = mipLevelCount;
3684 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3686 qWarning(
"Failed to create srv: %s",
3687 qPrintable(QSystemError::windowsComString(hr)));
3698 if (!prepareCreate(&size))
3701 const bool isDepth = isDepthTextureFormat(m_format);
3702 const bool isCube = m_flags.testFlag(CubeMap);
3703 const bool is3D = m_flags.testFlag(ThreeDimensional);
3704 const bool isArray = m_flags.testFlag(TextureArray);
3705 const bool is1D = m_flags.testFlag(OneDimensional);
3707 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3708 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3709 if (m_flags.testFlag(RenderTarget)) {
3711 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3713 bindFlags |= D3D11_BIND_RENDER_TARGET;
3715 if (m_flags.testFlag(UsedWithGenerateMips)) {
3717 qWarning(
"Depth texture cannot have mipmaps generated");
3720 bindFlags |= D3D11_BIND_RENDER_TARGET;
3721 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3723 if (m_flags.testFlag(UsedWithLoadStore))
3724 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3728 D3D11_TEXTURE1D_DESC desc = {};
3729 desc.Width = UINT(size.width());
3730 desc.MipLevels = mipLevelCount;
3731 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3732 desc.Format = dxgiFormat;
3733 desc.Usage = D3D11_USAGE_DEFAULT;
3734 desc.BindFlags = bindFlags;
3735 desc.MiscFlags = miscFlags;
3737 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3739 qWarning(
"Failed to create 1D texture: %s",
3740 qPrintable(QSystemError::windowsComString(hr)));
3743 if (!m_objectName.isEmpty())
3744 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3745 m_objectName.constData());
3747 D3D11_TEXTURE2D_DESC desc = {};
3748 desc.Width = UINT(size.width());
3749 desc.Height = UINT(size.height());
3750 desc.MipLevels = mipLevelCount;
3751 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3752 desc.Format = dxgiFormat;
3753 desc.SampleDesc = sampleDesc;
3754 desc.Usage = D3D11_USAGE_DEFAULT;
3755 desc.BindFlags = bindFlags;
3756 desc.MiscFlags = miscFlags;
3758 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3760 qWarning(
"Failed to create 2D texture: %s",
3761 qPrintable(QSystemError::windowsComString(hr)));
3764 if (!m_objectName.isEmpty())
3765 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3767 D3D11_TEXTURE3D_DESC desc = {};
3768 desc.Width = UINT(size.width());
3769 desc.Height = UINT(size.height());
3770 desc.Depth = UINT(qMax(1, m_depth));
3771 desc.MipLevels = mipLevelCount;
3772 desc.Format = dxgiFormat;
3773 desc.Usage = D3D11_USAGE_DEFAULT;
3774 desc.BindFlags = bindFlags;
3775 desc.MiscFlags = miscFlags;
3777 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3779 qWarning(
"Failed to create 3D texture: %s",
3780 qPrintable(QSystemError::windowsComString(hr)));
3783 if (!m_objectName.isEmpty())
3784 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3791 rhiD->registerResource(
this);
3800 if (!prepareCreate())
3803 if (m_flags.testFlag(ThreeDimensional))
3804 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3805 else if (m_flags.testFlags(OneDimensional))
3806 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3808 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3815 rhiD->registerResource(
this);
3821 return { quint64(textureResource()), 0 };
3826 if (perLevelViews[level])
3827 return perLevelViews[level];
3829 const bool isCube = m_flags.testFlag(CubeMap);
3830 const bool isArray = m_flags.testFlag(TextureArray);
3831 const bool is3D = m_flags.testFlag(ThreeDimensional);
3832 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3833 desc.Format = dxgiFormat;
3835 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3836 desc.Texture2DArray.MipSlice = UINT(level);
3837 desc.Texture2DArray.FirstArraySlice = 0;
3838 desc.Texture2DArray.ArraySize = 6;
3839 }
else if (isArray) {
3840 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3841 desc.Texture2DArray.MipSlice = UINT(level);
3842 desc.Texture2DArray.FirstArraySlice = 0;
3843 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3845 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3846 desc.Texture3D.MipSlice = UINT(level);
3847 desc.Texture3D.WSize = UINT(m_depth);
3849 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3850 desc.Texture2D.MipSlice = UINT(level);
3854 ID3D11UnorderedAccessView *uav =
nullptr;
3855 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3857 qWarning(
"Failed to create UAV: %s",
3858 qPrintable(QSystemError::windowsComString(hr)));
3862 perLevelViews[level] = uav;
3867 AddressMode u, AddressMode v, AddressMode w)
3882 samplerState->Release();
3883 samplerState =
nullptr;
3887 rhiD->unregisterResource(
this);
3890static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3892 if (minFilter == QRhiSampler::Nearest) {
3893 if (magFilter == QRhiSampler::Nearest) {
3894 if (mipFilter == QRhiSampler::Linear)
3895 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3897 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3899 if (mipFilter == QRhiSampler::Linear)
3900 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3902 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3905 if (magFilter == QRhiSampler::Nearest) {
3906 if (mipFilter == QRhiSampler::Linear)
3907 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3909 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3911 if (mipFilter == QRhiSampler::Linear)
3912 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3914 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3919 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3925 case QRhiSampler::Repeat:
3926 return D3D11_TEXTURE_ADDRESS_WRAP;
3927 case QRhiSampler::ClampToEdge:
3928 return D3D11_TEXTURE_ADDRESS_CLAMP;
3929 case QRhiSampler::Mirror:
3930 return D3D11_TEXTURE_ADDRESS_MIRROR;
3933 return D3D11_TEXTURE_ADDRESS_CLAMP;
3940 case QRhiSampler::Never:
3941 return D3D11_COMPARISON_NEVER;
3942 case QRhiSampler::Less:
3943 return D3D11_COMPARISON_LESS;
3944 case QRhiSampler::Equal:
3945 return D3D11_COMPARISON_EQUAL;
3946 case QRhiSampler::LessOrEqual:
3947 return D3D11_COMPARISON_LESS_EQUAL;
3948 case QRhiSampler::Greater:
3949 return D3D11_COMPARISON_GREATER;
3950 case QRhiSampler::NotEqual:
3951 return D3D11_COMPARISON_NOT_EQUAL;
3952 case QRhiSampler::GreaterOrEqual:
3953 return D3D11_COMPARISON_GREATER_EQUAL;
3954 case QRhiSampler::Always:
3955 return D3D11_COMPARISON_ALWAYS;
3958 return D3D11_COMPARISON_NEVER;
3967 D3D11_SAMPLER_DESC desc = {};
3968 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3969 if (m_compareOp != Never)
3970 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3971 desc.AddressU = toD3DAddressMode(m_addressU);
3972 desc.AddressV = toD3DAddressMode(m_addressV);
3973 desc.AddressW = toD3DAddressMode(m_addressW);
3974 desc.MaxAnisotropy = 1.0f;
3975 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3976 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3979 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3981 qWarning(
"Failed to create sampler state: %s",
3982 qPrintable(QSystemError::windowsComString(hr)));
3987 rhiD->registerResource(
this);
4006 rhiD->unregisterResource(
this);
4019 rhiD->registerResource(rpD,
false);
4056 return d.sampleCount;
4060 const QRhiTextureRenderTargetDescription &desc,
4078 if (!rtv[0] && !dsv)
4097 rhiD->unregisterResource(
this);
4104 rhiD->registerResource(rpD,
false);
4113 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4114 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4115 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4119 int colorAttCount = 0;
4121 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4123 const QRhiColorAttachment &colorAtt(*it);
4124 QRhiTexture *texture = colorAtt.texture();
4125 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4126 Q_ASSERT(texture || rb);
4129 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4130 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4131 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4132 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4133 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4134 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4135 rtvDesc.Texture2DArray.ArraySize = 1;
4136 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4137 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4138 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4139 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4140 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4141 rtvDesc.Texture1DArray.ArraySize = 1;
4143 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4144 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4146 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4147 if (texD->sampleDesc.Count > 1) {
4148 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4149 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4150 rtvDesc.Texture2DMSArray.ArraySize = 1;
4152 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4153 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4154 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4155 rtvDesc.Texture2DArray.ArraySize = 1;
4157 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4158 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4159 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4160 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4161 rtvDesc.Texture3D.WSize = 1;
4163 if (texD->sampleDesc.Count > 1) {
4164 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4166 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4167 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4170 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4172 qWarning(
"Failed to create rtv: %s",
4173 qPrintable(QSystemError::windowsComString(hr)));
4177 if (attIndex == 0) {
4178 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4179 d.sampleCount =
int(texD->sampleDesc.Count);
4184 rtv[attIndex] = rbD->rtv;
4185 if (attIndex == 0) {
4186 d.pixelSize = rbD->pixelSize();
4187 d.sampleCount =
int(rbD->sampleDesc.Count);
4193 if (hasDepthStencil) {
4194 if (m_desc.depthTexture()) {
4197 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4198 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4199 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4200 : D3D11_DSV_DIMENSION_TEXTURE2D;
4201 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4202 if (depthTexD->sampleDesc.Count > 1) {
4203 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4204 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4205 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4206 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4208 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4209 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4212 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4213 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4214 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4215 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4217 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4218 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4222 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4224 qWarning(
"Failed to create dsv: %s",
4225 qPrintable(QSystemError::windowsComString(hr)));
4228 if (colorAttCount == 0) {
4229 d.pixelSize = depthTexD->pixelSize();
4230 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4235 dsv = depthRbD->dsv;
4236 if (colorAttCount == 0) {
4237 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4238 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4245 d.views.setFrom(colorAttCount, rtv, dsv);
4247 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4249 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4251 rhiD->registerResource(
this);
4257 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4270 return d.sampleCount;
4285 sortedBindings.clear();
4286 boundResourceData.clear();
4290 rhiD->unregisterResource(
this);
4295 if (!sortedBindings.isEmpty())
4299 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4302 rhiD->updateLayoutDesc(
this);
4304 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4305 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4307 boundResourceData.resize(sortedBindings.count());
4309 for (BoundResourceData &bd : boundResourceData)
4310 memset(&bd, 0,
sizeof(BoundResourceData));
4313 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4314 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4315 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4316 hasDynamicOffset =
true;
4322 rhiD->registerResource(
this,
false);
4328 sortedBindings.clear();
4329 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4330 if (!flags.testFlag(BindingsAreSorted))
4331 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4333 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4334 for (BoundResourceData &bd : boundResourceData)
4335 memset(&bd, 0,
sizeof(BoundResourceData));
4354 s.shader->Release();
4357 s.nativeResourceBindingMap.clear();
4369 blendState->Release();
4370 blendState =
nullptr;
4374 inputLayout->Release();
4375 inputLayout =
nullptr;
4379 rastState->Release();
4380 rastState =
nullptr;
4383 releasePipelineShader(vs);
4384 releasePipelineShader(hs);
4385 releasePipelineShader(ds);
4386 releasePipelineShader(gs);
4387 releasePipelineShader(fs);
4391 rhiD->unregisterResource(
this);
4397 case QRhiGraphicsPipeline::None:
4398 return D3D11_CULL_NONE;
4399 case QRhiGraphicsPipeline::Front:
4400 return D3D11_CULL_FRONT;
4401 case QRhiGraphicsPipeline::Back:
4402 return D3D11_CULL_BACK;
4405 return D3D11_CULL_NONE;
4412 case QRhiGraphicsPipeline::Fill:
4413 return D3D11_FILL_SOLID;
4414 case QRhiGraphicsPipeline::Line:
4415 return D3D11_FILL_WIREFRAME;
4418 return D3D11_FILL_SOLID;
4425 case QRhiGraphicsPipeline::Never:
4426 return D3D11_COMPARISON_NEVER;
4427 case QRhiGraphicsPipeline::Less:
4428 return D3D11_COMPARISON_LESS;
4429 case QRhiGraphicsPipeline::Equal:
4430 return D3D11_COMPARISON_EQUAL;
4431 case QRhiGraphicsPipeline::LessOrEqual:
4432 return D3D11_COMPARISON_LESS_EQUAL;
4433 case QRhiGraphicsPipeline::Greater:
4434 return D3D11_COMPARISON_GREATER;
4435 case QRhiGraphicsPipeline::NotEqual:
4436 return D3D11_COMPARISON_NOT_EQUAL;
4437 case QRhiGraphicsPipeline::GreaterOrEqual:
4438 return D3D11_COMPARISON_GREATER_EQUAL;
4439 case QRhiGraphicsPipeline::Always:
4440 return D3D11_COMPARISON_ALWAYS;
4443 return D3D11_COMPARISON_ALWAYS;
4450 case QRhiGraphicsPipeline::StencilZero:
4451 return D3D11_STENCIL_OP_ZERO;
4452 case QRhiGraphicsPipeline::Keep:
4453 return D3D11_STENCIL_OP_KEEP;
4454 case QRhiGraphicsPipeline::Replace:
4455 return D3D11_STENCIL_OP_REPLACE;
4456 case QRhiGraphicsPipeline::IncrementAndClamp:
4457 return D3D11_STENCIL_OP_INCR_SAT;
4458 case QRhiGraphicsPipeline::DecrementAndClamp:
4459 return D3D11_STENCIL_OP_DECR_SAT;
4460 case QRhiGraphicsPipeline::Invert:
4461 return D3D11_STENCIL_OP_INVERT;
4462 case QRhiGraphicsPipeline::IncrementAndWrap:
4463 return D3D11_STENCIL_OP_INCR;
4464 case QRhiGraphicsPipeline::DecrementAndWrap:
4465 return D3D11_STENCIL_OP_DECR;
4468 return D3D11_STENCIL_OP_KEEP;
4475 case QRhiVertexInputAttribute::Float4:
4476 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4477 case QRhiVertexInputAttribute::Float3:
4478 return DXGI_FORMAT_R32G32B32_FLOAT;
4479 case QRhiVertexInputAttribute::Float2:
4480 return DXGI_FORMAT_R32G32_FLOAT;
4481 case QRhiVertexInputAttribute::Float:
4482 return DXGI_FORMAT_R32_FLOAT;
4483 case QRhiVertexInputAttribute::UNormByte4:
4484 return DXGI_FORMAT_R8G8B8A8_UNORM;
4485 case QRhiVertexInputAttribute::UNormByte2:
4486 return DXGI_FORMAT_R8G8_UNORM;
4487 case QRhiVertexInputAttribute::UNormByte:
4488 return DXGI_FORMAT_R8_UNORM;
4489 case QRhiVertexInputAttribute::UInt4:
4490 return DXGI_FORMAT_R32G32B32A32_UINT;
4491 case QRhiVertexInputAttribute::UInt3:
4492 return DXGI_FORMAT_R32G32B32_UINT;
4493 case QRhiVertexInputAttribute::UInt2:
4494 return DXGI_FORMAT_R32G32_UINT;
4495 case QRhiVertexInputAttribute::UInt:
4496 return DXGI_FORMAT_R32_UINT;
4497 case QRhiVertexInputAttribute::SInt4:
4498 return DXGI_FORMAT_R32G32B32A32_SINT;
4499 case QRhiVertexInputAttribute::SInt3:
4500 return DXGI_FORMAT_R32G32B32_SINT;
4501 case QRhiVertexInputAttribute::SInt2:
4502 return DXGI_FORMAT_R32G32_SINT;
4503 case QRhiVertexInputAttribute::SInt:
4504 return DXGI_FORMAT_R32_SINT;
4505 case QRhiVertexInputAttribute::Half4:
4507 case QRhiVertexInputAttribute::Half3:
4508 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4509 case QRhiVertexInputAttribute::Half2:
4510 return DXGI_FORMAT_R16G16_FLOAT;
4511 case QRhiVertexInputAttribute::Half:
4512 return DXGI_FORMAT_R16_FLOAT;
4513 case QRhiVertexInputAttribute::UShort4:
4515 case QRhiVertexInputAttribute::UShort3:
4516 return DXGI_FORMAT_R16G16B16A16_UINT;
4517 case QRhiVertexInputAttribute::UShort2:
4518 return DXGI_FORMAT_R16G16_UINT;
4519 case QRhiVertexInputAttribute::UShort:
4520 return DXGI_FORMAT_R16_UINT;
4521 case QRhiVertexInputAttribute::SShort4:
4523 case QRhiVertexInputAttribute::SShort3:
4524 return DXGI_FORMAT_R16G16B16A16_SINT;
4525 case QRhiVertexInputAttribute::SShort2:
4526 return DXGI_FORMAT_R16G16_SINT;
4527 case QRhiVertexInputAttribute::SShort:
4528 return DXGI_FORMAT_R16_SINT;
4531 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4538 case QRhiGraphicsPipeline::Triangles:
4539 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4540 case QRhiGraphicsPipeline::TriangleStrip:
4541 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4542 case QRhiGraphicsPipeline::Lines:
4543 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4544 case QRhiGraphicsPipeline::LineStrip:
4545 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4546 case QRhiGraphicsPipeline::Points:
4547 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4548 case QRhiGraphicsPipeline::Patches:
4549 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4550 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4553 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4560 if (c.testFlag(QRhiGraphicsPipeline::R))
4561 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4562 if (c.testFlag(QRhiGraphicsPipeline::G))
4563 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4564 if (c.testFlag(QRhiGraphicsPipeline::B))
4565 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4566 if (c.testFlag(QRhiGraphicsPipeline::A))
4567 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4580 case QRhiGraphicsPipeline::Zero:
4581 return D3D11_BLEND_ZERO;
4582 case QRhiGraphicsPipeline::One:
4583 return D3D11_BLEND_ONE;
4584 case QRhiGraphicsPipeline::SrcColor:
4585 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4586 case QRhiGraphicsPipeline::OneMinusSrcColor:
4587 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4588 case QRhiGraphicsPipeline::DstColor:
4589 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4590 case QRhiGraphicsPipeline::OneMinusDstColor:
4591 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4592 case QRhiGraphicsPipeline::SrcAlpha:
4593 return D3D11_BLEND_SRC_ALPHA;
4594 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4595 return D3D11_BLEND_INV_SRC_ALPHA;
4596 case QRhiGraphicsPipeline::DstAlpha:
4597 return D3D11_BLEND_DEST_ALPHA;
4598 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4599 return D3D11_BLEND_INV_DEST_ALPHA;
4600 case QRhiGraphicsPipeline::ConstantColor:
4601 case QRhiGraphicsPipeline::ConstantAlpha:
4602 return D3D11_BLEND_BLEND_FACTOR;
4603 case QRhiGraphicsPipeline::OneMinusConstantColor:
4604 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4605 return D3D11_BLEND_INV_BLEND_FACTOR;
4606 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4607 return D3D11_BLEND_SRC_ALPHA_SAT;
4608 case QRhiGraphicsPipeline::Src1Color:
4609 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4610 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4611 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4612 case QRhiGraphicsPipeline::Src1Alpha:
4613 return D3D11_BLEND_SRC1_ALPHA;
4614 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4615 return D3D11_BLEND_INV_SRC1_ALPHA;
4618 return D3D11_BLEND_ZERO;
4625 case QRhiGraphicsPipeline::Add:
4626 return D3D11_BLEND_OP_ADD;
4627 case QRhiGraphicsPipeline::Subtract:
4628 return D3D11_BLEND_OP_SUBTRACT;
4629 case QRhiGraphicsPipeline::ReverseSubtract:
4630 return D3D11_BLEND_OP_REV_SUBTRACT;
4631 case QRhiGraphicsPipeline::Min:
4632 return D3D11_BLEND_OP_MIN;
4633 case QRhiGraphicsPipeline::Max:
4634 return D3D11_BLEND_OP_MAX;
4637 return D3D11_BLEND_OP_ADD;
4644 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4645 keyBuilder.addData(source);
4646 return keyBuilder.result().toHex();
4649QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4650 QString *error, QShaderKey *usedShaderKey)
4652 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4653 QShaderCode dxbc = shader.shader(key);
4654 if (!dxbc.shader().isEmpty()) {
4656 *usedShaderKey = key;
4657 return dxbc.shader();
4660 key = { QShader::HlslShader, 50, shaderVariant };
4661 QShaderCode hlslSource = shader.shader(key);
4662 if (hlslSource.shader().isEmpty()) {
4663 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4664 return QByteArray();
4668 *usedShaderKey = key;
4671 switch (shader.stage()) {
4672 case QShader::VertexStage:
4675 case QShader::TessellationControlStage:
4678 case QShader::TessellationEvaluationStage:
4681 case QShader::GeometryStage:
4684 case QShader::FragmentStage:
4687 case QShader::ComputeStage:
4692 return QByteArray();
4696 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4697 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4698 cacheKey.target = target;
4699 cacheKey.entryPoint = hlslSource.entryPoint();
4700 cacheKey.compileFlags = flags;
4701 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4702 if (cacheIt != m_bytecodeCache.constEnd())
4703 return cacheIt.value();
4706 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4707 if (d3dCompile ==
nullptr) {
4708 qWarning(
"Unable to resolve function D3DCompile()");
4709 return QByteArray();
4712 ID3DBlob *bytecode =
nullptr;
4713 ID3DBlob *errors =
nullptr;
4714 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4715 nullptr,
nullptr,
nullptr,
4716 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4717 if (FAILED(hr) || !bytecode) {
4718 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4720 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4721 int(errors->GetBufferSize()));
4724 return QByteArray();
4728 result.resize(
int(bytecode->GetBufferSize()));
4729 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4730 bytecode->Release();
4732 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4733 m_bytecodeCache.insert(cacheKey, result);
4744 rhiD->pipelineCreationStart();
4745 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4748 D3D11_RASTERIZER_DESC rastDesc = {};
4749 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4750 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4751 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4752 rastDesc.DepthBias = m_depthBias;
4753 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4754 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4755 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4756 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4757 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4759 qWarning(
"Failed to create rasterizer state: %s",
4760 qPrintable(QSystemError::windowsComString(hr)));
4764 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4765 dsDesc.DepthEnable = m_depthTest;
4766 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4767 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4768 dsDesc.StencilEnable = m_stencilTest;
4769 if (m_stencilTest) {
4770 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4771 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4772 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4773 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4774 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4775 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4776 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4777 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4778 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4779 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4781 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4783 qWarning(
"Failed to create depth-stencil state: %s",
4784 qPrintable(QSystemError::windowsComString(hr)));
4788 D3D11_BLEND_DESC blendDesc = {};
4789 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4790 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4791 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4792 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4793 blend.BlendEnable = b.enable;
4794 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4795 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4796 blend.BlendOp = toD3DBlendOp(b.opColor);
4797 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4798 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4799 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4800 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4801 blendDesc.RenderTarget[i] = blend;
4803 if (m_targetBlends.isEmpty()) {
4804 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4805 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4806 blendDesc.RenderTarget[0] = blend;
4808 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4810 qWarning(
"Failed to create blend state: %s",
4811 qPrintable(QSystemError::windowsComString(hr)));
4815 QByteArray vsByteCode;
4816 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4817 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4818 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4819 switch (shaderStage.type()) {
4820 case QRhiShaderStage::Vertex:
4821 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4822 vs.shader->AddRef();
4823 vsByteCode = cacheIt->bytecode;
4824 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4826 case QRhiShaderStage::TessellationControl:
4827 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4828 hs.shader->AddRef();
4829 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4831 case QRhiShaderStage::TessellationEvaluation:
4832 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4833 ds.shader->AddRef();
4834 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4836 case QRhiShaderStage::Geometry:
4837 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4838 gs.shader->AddRef();
4839 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4841 case QRhiShaderStage::Fragment:
4842 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4843 fs.shader->AddRef();
4844 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4851 QShaderKey shaderKey;
4852 UINT compileFlags = 0;
4853 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4854 compileFlags |= D3DCOMPILE_DEBUG;
4856 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4857 &error, &shaderKey);
4858 if (bytecode.isEmpty()) {
4859 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4863 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4865 rhiD->clearShaderCache();
4868 switch (shaderStage.type()) {
4869 case QRhiShaderStage::Vertex:
4870 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4872 qWarning(
"Failed to create vertex shader: %s",
4873 qPrintable(QSystemError::windowsComString(hr)));
4876 vsByteCode = bytecode;
4877 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4878 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4879 vs.shader->AddRef();
4881 case QRhiShaderStage::TessellationControl:
4882 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4884 qWarning(
"Failed to create hull shader: %s",
4885 qPrintable(QSystemError::windowsComString(hr)));
4888 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4889 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4890 hs.shader->AddRef();
4892 case QRhiShaderStage::TessellationEvaluation:
4893 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4895 qWarning(
"Failed to create domain shader: %s",
4896 qPrintable(QSystemError::windowsComString(hr)));
4899 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4900 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4901 ds.shader->AddRef();
4903 case QRhiShaderStage::Geometry:
4904 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4906 qWarning(
"Failed to create geometry shader: %s",
4907 qPrintable(QSystemError::windowsComString(hr)));
4910 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4911 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4912 gs.shader->AddRef();
4914 case QRhiShaderStage::Fragment:
4915 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4917 qWarning(
"Failed to create pixel shader: %s",
4918 qPrintable(QSystemError::windowsComString(hr)));
4921 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4922 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4923 fs.shader->AddRef();
4931 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4933 if (!vsByteCode.isEmpty()) {
4934 QByteArrayList matrixSliceSemantics;
4935 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4936 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4939 D3D11_INPUT_ELEMENT_DESC desc = {};
4944 const int matrixSlice = it->matrixSlice();
4945 if (matrixSlice < 0) {
4946 desc.SemanticName =
"TEXCOORD";
4947 desc.SemanticIndex = UINT(it->location());
4951 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4952 matrixSliceSemantics.append(sem);
4953 desc.SemanticName = matrixSliceSemantics.last().constData();
4954 desc.SemanticIndex = UINT(matrixSlice);
4956 desc.Format = toD3DAttributeFormat(it->format());
4957 desc.InputSlot = UINT(it->binding());
4958 desc.AlignedByteOffset = it->offset();
4959 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4960 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4961 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4962 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4964 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4966 inputDescs.append(desc);
4968 if (!inputDescs.isEmpty()) {
4969 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4970 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4972 qWarning(
"Failed to create input layout: %s",
4973 qPrintable(QSystemError::windowsComString(hr)));
4979 rhiD->pipelineCreationEnd();
4981 rhiD->registerResource(
this);
5000 cs.shader->Release();
5001 cs.shader =
nullptr;
5002 cs.nativeResourceBindingMap.clear();
5006 rhiD->unregisterResource(
this);
5015 rhiD->pipelineCreationStart();
5017 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5018 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5019 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5020 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5023 QShaderKey shaderKey;
5024 UINT compileFlags = 0;
5025 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5026 compileFlags |= D3DCOMPILE_DEBUG;
5028 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5029 &error, &shaderKey);
5030 if (bytecode.isEmpty()) {
5031 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5035 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5037 qWarning(
"Failed to create compute shader: %s",
5038 qPrintable(QSystemError::windowsComString(hr)));
5042 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5044 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5047 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5050 cs.shader->AddRef();
5052 rhiD->pipelineCreationEnd();
5054 rhiD->registerResource(
this);
5079 D3D11_QUERY_DESC queryDesc = {};
5081 if (!disjointQuery[i]) {
5082 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5083 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5085 qWarning(
"Failed to create timestamp disjoint query: %s",
5086 qPrintable(QSystemError::windowsComString(hr)));
5090 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5091 for (
int j = 0; j < 2; ++j) {
5092 const int idx = 2 * i + j;
5094 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5096 qWarning(
"Failed to create timestamp query: %s",
5097 qPrintable(QSystemError::windowsComString(hr)));
5110 if (disjointQuery[i]) {
5111 disjointQuery[i]->Release();
5112 disjointQuery[i] =
nullptr;
5114 for (
int j = 0; j < 2; ++j) {
5117 query[idx]->Release();
5118 query[idx] =
nullptr;
5126 bool result =
false;
5130 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5131 ID3D11Query *tsStart = query[pairIndex * 2];
5132 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5133 quint64 timestamps[2];
5134 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5137 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5138 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5139 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5142 if (!dj.Disjoint && dj.Frequency) {
5143 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5144 *elapsedSec = elapsedMs / 1000.0;
5147 active[pairIndex] =
false;
5156 backBufferTex =
nullptr;
5157 backBufferRtv =
nullptr;
5159 msaaTex[i] =
nullptr;
5160 msaaRtv[i] =
nullptr;
5171 if (backBufferRtv) {
5172 backBufferRtv->Release();
5173 backBufferRtv =
nullptr;
5175 if (backBufferRtvRight) {
5176 backBufferRtvRight->Release();
5177 backBufferRtvRight =
nullptr;
5179 if (backBufferTex) {
5180 backBufferTex->Release();
5181 backBufferTex =
nullptr;
5185 msaaRtv[i]->Release();
5186 msaaRtv[i] =
nullptr;
5189 msaaTex[i]->Release();
5190 msaaTex[i] =
nullptr;
5202 timestamps.destroy();
5204 swapChain->Release();
5205 swapChain =
nullptr;
5208 dcompVisual->Release();
5209 dcompVisual =
nullptr;
5213 dcompTarget->Release();
5214 dcompTarget =
nullptr;
5217 if (frameLatencyWaitableObject) {
5218 CloseHandle(frameLatencyWaitableObject);
5219 frameLatencyWaitableObject =
nullptr;
5222 QDxgiVSyncService::instance()->unregisterWindow(window);
5226 rhiD->unregisterResource(
this);
5229 rhiD->context->Flush();
5245 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5251 return m_window->size() * m_window->devicePixelRatio();
5260 qWarning(
"Attempted to call isFormatSupported() without a window set");
5265 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5266 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5277 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5286 rhiD->registerResource(rpD,
false);
5291 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5293 D3D11_TEXTURE2D_DESC desc = {};
5294 desc.Width = UINT(size.width());
5295 desc.Height = UINT(size.height());
5298 desc.Format = format;
5299 desc.SampleDesc = sampleDesc;
5300 desc.Usage = D3D11_USAGE_DEFAULT;
5301 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5304 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5306 qWarning(
"Failed to create color buffer texture: %s",
5307 qPrintable(QSystemError::windowsComString(hr)));
5311 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5312 rtvDesc.Format = format;
5313 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5314 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5316 qWarning(
"Failed to create color buffer rtv: %s",
5317 qPrintable(QSystemError::windowsComString(hr)));
5331 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5332 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5333 return dcompDevice ?
true :
false;
5345 const bool needsRegistration = !window || window != m_window;
5346 const bool stereo = m_window->format().stereo();
5349 if (window && window != m_window)
5353 m_currentPixelSize = surfacePixelSize();
5354 pixelSize = m_currentPixelSize;
5356 if (pixelSize.isEmpty())
5359 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5364 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5367 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5369 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5370 qPrintable(QSystemError::windowsComString(hr)));
5373 if (dcompTarget && !dcompVisual) {
5374 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5376 qWarning(
"Failed to create DirectComposition visual: %s",
5377 qPrintable(QSystemError::windowsComString(hr)));
5382 if (
window->requestedFormat().alphaBufferSize() <= 0)
5383 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5384 "This may lead to problems.");
5387 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5394 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5395 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5399 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5400 && swapInterval != 0
5401 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5403 if (useFrameLatencyWaitableObject) {
5405 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5409 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5410 colorFormat = DEFAULT_FORMAT;
5411 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5413 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5414 if (m_format != SDR) {
5415 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5418 case HDRExtendedSrgbLinear:
5419 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5420 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5421 srgbAdjustedColorFormat = colorFormat;
5424 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5425 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5426 srgbAdjustedColorFormat = colorFormat;
5435 qWarning(
"The output associated with the window is not HDR capable "
5436 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5446 DXGI_SWAP_CHAIN_DESC1 desc = {};
5447 desc.Width = UINT(pixelSize.width());
5448 desc.Height = UINT(pixelSize.height());
5449 desc.Format = colorFormat;
5450 desc.SampleDesc.Count = 1;
5451 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5453 desc.Flags = swapChainFlags;
5454 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5455 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5456 desc.Stereo = stereo;
5462 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5467 desc.Scaling = DXGI_SCALING_STRETCH;
5470 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5471 IDXGISwapChain1 *sc1;
5474 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5476 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5481 if (FAILED(hr) && m_format != SDR) {
5482 colorFormat = DEFAULT_FORMAT;
5483 desc.Format = DEFAULT_FORMAT;
5485 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5487 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5490 if (SUCCEEDED(hr)) {
5492 IDXGISwapChain3 *sc3 =
nullptr;
5493 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5494 if (m_format != SDR) {
5495 hr = sc3->SetColorSpace1(hdrColorSpace);
5497 qWarning(
"Failed to set color space on swapchain: %s",
5498 qPrintable(QSystemError::windowsComString(hr)));
5500 if (useFrameLatencyWaitableObject) {
5501 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5502 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5506 if (m_format != SDR)
5507 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5508 if (useFrameLatencyWaitableObject) {
5509 IDXGISwapChain2 *sc2 =
nullptr;
5510 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5511 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5512 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5515 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5520 hr = dcompVisual->SetContent(sc1);
5521 if (SUCCEEDED(hr)) {
5522 hr = dcompTarget->SetRoot(dcompVisual);
5524 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5525 qPrintable(QSystemError::windowsComString(hr)));
5528 qWarning(
"Failed to set content for Direct Composition visual: %s",
5529 qPrintable(QSystemError::windowsComString(hr)));
5533 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5536 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5537 qWarning(
"Device loss detected during swapchain creation");
5540 }
else if (FAILED(hr)) {
5541 qWarning(
"Failed to create D3D11 swapchain: %s"
5542 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5543 qPrintable(QSystemError::windowsComString(hr)),
5544 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5545 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5551 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5552 colorFormat, swapChainFlags);
5553 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5554 qWarning(
"Device loss detected in ResizeBuffers()");
5557 }
else if (FAILED(hr)) {
5558 qWarning(
"Failed to resize D3D11 swapchain: %s",
5559 qPrintable(QSystemError::windowsComString(hr)));
5578 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5580 qWarning(
"Failed to query swapchain backbuffer: %s",
5581 qPrintable(QSystemError::windowsComString(hr)));
5584 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5585 rtvDesc.Format = srgbAdjustedColorFormat;
5586 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5587 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5589 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5590 qPrintable(QSystemError::windowsComString(hr)));
5596 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5597 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5598 rtvDesc.Texture2DArray.ArraySize = 1;
5599 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5601 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5602 qPrintable(QSystemError::windowsComString(hr)));
5609 if (sampleDesc.Count > 1) {
5610 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5615 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5616 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5617 m_depthStencil->sampleCount(), m_sampleCount);
5619 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5620 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5621 m_depthStencil->setPixelSize(pixelSize);
5622 if (!m_depthStencil->create())
5623 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5624 pixelSize.width(), pixelSize.height());
5626 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5627 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5628 pixelSize.width(), pixelSize.height());
5635 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5637 rt.setRenderPassDescriptor(m_renderPassDesc);
5639 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5640 rtD->d.pixelSize = pixelSize;
5641 rtD->d.dpr =
float(
window->devicePixelRatio());
5642 rtD->d.sampleCount =
int(sampleDesc.Count);
5643 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5646 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5647 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5648 rtD->d.pixelSize = pixelSize;
5649 rtD->d.dpr =
float(
window->devicePixelRatio());
5650 rtD->d.sampleCount =
int(sampleDesc.Count);
5651 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
5654 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5655 timestamps.prepare(rhiD);
5659 QDxgiVSyncService::instance()->registerWindow(window);
5661 if (needsRegistration)
5662 rhiD->registerResource(
this);
5670 if (rtViews.dsv != currentRtViews.dsv) {
5671 rtViews.dsv = currentRtViews.dsv;
5675 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
5676 rtViews.rtv[i] = currentRtViews.rtv[i];
5679 ret |= rtViews.rtv[i] !=
nullptr;
5680 rtViews.rtv[i] =
nullptr;
5682 for (
int i = 0; i < count; i++) {
5683 ret |= uav[i] != uavs[i];
5687 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