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 (Shader &s : 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.ps = psD;
1041 int dynamicOffsetCount,
1042 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1051 srb = gfxPsD->m_shaderResourceBindings;
1053 srb = compPsD->m_shaderResourceBindings;
1058 bool pipelineChanged =
false;
1067 bool srbUpdate =
false;
1068 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1069 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1072 case QRhiShaderResourceBinding::UniformBuffer:
1076 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1077 sanityCheckResourceOwnership(bufD);
1081 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1083 bd.ubuf.id = bufD->m_id;
1084 bd.ubuf.generation = bufD->generation;
1088 case QRhiShaderResourceBinding::SampledTexture:
1089 case QRhiShaderResourceBinding::Texture:
1090 case QRhiShaderResourceBinding::Sampler:
1092 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1093 if (bd.stex.count != data->count) {
1094 bd.stex.count = data->count;
1097 for (
int elem = 0; elem < data->count; ++elem) {
1103 Q_ASSERT(texD || samplerD);
1104 sanityCheckResourceOwnership(texD);
1105 sanityCheckResourceOwnership(samplerD);
1106 const quint64 texId = texD ? texD->m_id : 0;
1107 const uint texGen = texD ? texD->generation : 0;
1108 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1109 const uint samplerGen = samplerD ? samplerD->generation : 0;
1110 if (texGen != bd.stex.d[elem].texGeneration
1111 || texId != bd.stex.d[elem].texId
1112 || samplerGen != bd.stex.d[elem].samplerGeneration
1113 || samplerId != bd.stex.d[elem].samplerId)
1116 bd.stex.d[elem].texId = texId;
1117 bd.stex.d[elem].texGeneration = texGen;
1118 bd.stex.d[elem].samplerId = samplerId;
1119 bd.stex.d[elem].samplerGeneration = samplerGen;
1124 case QRhiShaderResourceBinding::ImageLoad:
1125 case QRhiShaderResourceBinding::ImageStore:
1126 case QRhiShaderResourceBinding::ImageLoadStore:
1129 sanityCheckResourceOwnership(texD);
1130 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1132 bd.simage.id = texD->m_id;
1133 bd.simage.generation = texD->generation;
1137 case QRhiShaderResourceBinding::BufferLoad:
1138 case QRhiShaderResourceBinding::BufferStore:
1139 case QRhiShaderResourceBinding::BufferLoadStore:
1142 sanityCheckResourceOwnership(bufD);
1143 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1145 bd.sbuf.id = bufD->m_id;
1146 bd.sbuf.generation = bufD->generation;
1156 if (srbUpdate || pipelineChanged) {
1158 memset(resBindMaps, 0,
sizeof(resBindMaps));
1160 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1161 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1162 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1163 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1164 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1166 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1168 updateShaderResourceBindings(srbD, resBindMaps);
1171 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1172 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1174 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1176 cbD->currentGraphicsSrb = srb;
1177 cbD->currentComputeSrb =
nullptr;
1179 cbD->currentGraphicsSrb =
nullptr;
1180 cbD->currentComputeSrb = srb;
1182 cbD->currentSrbGeneration = srbD->generation;
1189 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1190 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1193 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1194 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1195 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1196 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1197 const uint binding = uint(dynOfs.first);
1198 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1199 const quint32 offsetInConstants = dynOfs.second / 16;
1201 *p++ = offsetInConstants;
1204 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1212 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1213 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1218 bool needsBindVBuf =
false;
1219 for (
int i = 0; i < bindingCount; ++i) {
1220 const int inputSlot = startBinding + i;
1222 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1223 if (bufD->m_type == QRhiBuffer::Dynamic)
1226 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1227 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1229 needsBindVBuf =
true;
1230 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1231 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1235 if (needsBindVBuf) {
1238 cmd.args.bindVertexBuffers.startSlot = startBinding;
1240 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1244 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1246 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1247 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1248 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1250 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1251 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1252 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1258 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1259 if (ibufD->m_type == QRhiBuffer::Dynamic)
1262 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1263 : DXGI_FORMAT_R32_UINT;
1264 if (cbD->currentIndexBuffer != ibufD->buffer
1265 || cbD->currentIndexOffset != indexOffset
1266 || cbD->currentIndexFormat != dxgiFormat)
1268 cbD->currentIndexBuffer = ibufD->buffer;
1269 cbD->currentIndexOffset = indexOffset;
1270 cbD->currentIndexFormat = dxgiFormat;
1274 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1275 cmd.args.bindIndexBuffer.offset = indexOffset;
1276 cmd.args.bindIndexBuffer.format = dxgiFormat;
1285 Q_ASSERT(cbD->currentTarget);
1286 const QSize outputSize = cbD->currentTarget->pixelSize();
1290 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1295 cmd.args.viewport.x = x;
1296 cmd.args.viewport.y = y;
1297 cmd.args.viewport.w = w;
1298 cmd.args.viewport.h = h;
1299 cmd.args.viewport.d0 = viewport.minDepth();
1300 cmd.args.viewport.d1 = viewport.maxDepth();
1307 Q_ASSERT(cbD->currentTarget);
1308 const QSize outputSize = cbD->currentTarget->pixelSize();
1312 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1317 cmd.args.scissor.x = x;
1318 cmd.args.scissor.y = y;
1319 cmd.args.scissor.w = w;
1320 cmd.args.scissor.h = h;
1331 cmd.args.blendConstants.c[0] =
float(c.redF());
1332 cmd.args.blendConstants.c[1] =
float(c.greenF());
1333 cmd.args.blendConstants.c[2] =
float(c.blueF());
1334 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1345 cmd.args.stencilRef.ref = refValue;
1351 Q_UNUSED(coarsePixelSize);
1355 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1363 cmd.args.draw.vertexCount = vertexCount;
1364 cmd.args.draw.instanceCount = instanceCount;
1365 cmd.args.draw.firstVertex = firstVertex;
1366 cmd.args.draw.firstInstance = firstInstance;
1370 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1378 cmd.args.drawIndexed.indexCount = indexCount;
1379 cmd.args.drawIndexed.instanceCount = instanceCount;
1380 cmd.args.drawIndexed.firstIndex = firstIndex;
1381 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1382 cmd.args.drawIndexed.firstInstance = firstInstance;
1386 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1394 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer);
1395 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1396 cmd.args.drawIndirect.drawCount = drawCount;
1397 cmd.args.drawIndirect.stride = stride;
1401 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1409 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer);
1410 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1411 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1412 cmd.args.drawIndexedIndirect.stride = stride;
1417 if (!debugMarkers || !annotations)
1423 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1428 if (!debugMarkers || !annotations)
1438 if (!debugMarkers || !annotations)
1444 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1463 Q_ASSERT(cbD->commands.isEmpty());
1465 if (cbD->currentTarget) {
1468 fbCmd.args.setRenderTarget.rt = cbD->currentTarget;
1480 switch (rt->resourceType()) {
1481 case QRhiResource::SwapChainRenderTarget:
1482 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1483 case QRhiResource::TextureRenderTarget:
1484 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1500 if (swapChainD->frameLatencyWaitableObject) {
1503 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1508 swapChainD->cb.resetState();
1510 swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
1511 swapChainD->msaaRtv[currentFrameSlot] : swapChainD->backBufferRtv;
1512 swapChainD->rt.d.dsv = swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr;
1517 double elapsedSec = 0;
1519 swapChainD->cb.lastGpuTime = elapsedSec;
1528 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1529 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1530 cmd.args.beginFrame.swapchainData =
rtData(&swapChainD->rt
);
1532 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1534 return QRhi::FrameOpSuccess;
1545 cmd.args.endFrame.tsQuery =
nullptr;
1546 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1551 if (swapChainD->sampleDesc.Count > 1) {
1552 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1553 swapChainD->msaaTex[currentFrameSlot], 0,
1554 swapChainD->colorFormat);
1561 if (recordTimestamps) {
1562 context->End(tsEnd);
1563 context->End(tsDisjoint);
1568 if (!flags.testFlag(QRhi::SkipPresent)) {
1569 UINT presentFlags = 0;
1570 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1571 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1572 if (!swapChainD->swapChain) {
1573 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1574 return QRhi::FrameOpError;
1576 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1577 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1578 qWarning(
"Device loss detected in Present()");
1580 return QRhi::FrameOpDeviceLost;
1581 }
else if (FAILED(hr)) {
1582 qWarning(
"Failed to present: %s",
1583 qPrintable(QSystemError::windowsComString(hr)));
1584 return QRhi::FrameOpError;
1587 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1588 dcompDevice->Commit();
1599 return QRhi::FrameOpSuccess;
1607 ofr.cbWrapper.resetState();
1608 *cb = &ofr.cbWrapper;
1610 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1611 D3D11_QUERY_DESC queryDesc = {};
1612 if (!ofr.tsDisjointQuery) {
1613 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1614 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1616 qWarning(
"Failed to create timestamp disjoint query: %s",
1617 qPrintable(QSystemError::windowsComString(hr)));
1618 return QRhi::FrameOpError;
1621 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1622 for (
int i = 0; i < 2; ++i) {
1623 if (!ofr.tsQueries[i]) {
1624 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1626 qWarning(
"Failed to create timestamp query: %s",
1627 qPrintable(QSystemError::windowsComString(hr)));
1628 return QRhi::FrameOpError;
1636 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1637 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1638 cmd.args.beginFrame.swapchainData =
nullptr;
1640 return QRhi::FrameOpSuccess;
1650 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1651 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1658 if (ofr.tsQueries[0]) {
1659 quint64 timestamps[2];
1660 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1664 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1665 }
while (hr == S_FALSE);
1668 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1669 }
while (hr == S_FALSE);
1672 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1673 }
while (hr == S_FALSE);
1676 if (!dj.Disjoint && dj.Frequency) {
1677 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1678 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1683 return QRhi::FrameOpSuccess;
1688 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1690 case QRhiTexture::RGBA8:
1691 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1692 case QRhiTexture::BGRA8:
1693 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1694 case QRhiTexture::R8:
1695 return DXGI_FORMAT_R8_UNORM;
1696 case QRhiTexture::R8SI:
1697 return DXGI_FORMAT_R8_SINT;
1698 case QRhiTexture::R8UI:
1699 return DXGI_FORMAT_R8_UINT;
1700 case QRhiTexture::RG8:
1701 return DXGI_FORMAT_R8G8_UNORM;
1702 case QRhiTexture::R16:
1703 return DXGI_FORMAT_R16_UNORM;
1704 case QRhiTexture::RG16:
1705 return DXGI_FORMAT_R16G16_UNORM;
1706 case QRhiTexture::RED_OR_ALPHA8:
1707 return DXGI_FORMAT_R8_UNORM;
1709 case QRhiTexture::RGBA16F:
1710 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1711 case QRhiTexture::RGBA32F:
1712 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1713 case QRhiTexture::R16F:
1714 return DXGI_FORMAT_R16_FLOAT;
1715 case QRhiTexture::R32F:
1716 return DXGI_FORMAT_R32_FLOAT;
1718 case QRhiTexture::RGB10A2:
1719 return DXGI_FORMAT_R10G10B10A2_UNORM;
1721 case QRhiTexture::R32SI:
1722 return DXGI_FORMAT_R32_SINT;
1723 case QRhiTexture::R32UI:
1724 return DXGI_FORMAT_R32_UINT;
1725 case QRhiTexture::RG32SI:
1726 return DXGI_FORMAT_R32G32_SINT;
1727 case QRhiTexture::RG32UI:
1728 return DXGI_FORMAT_R32G32_UINT;
1729 case QRhiTexture::RGBA32SI:
1730 return DXGI_FORMAT_R32G32B32A32_SINT;
1731 case QRhiTexture::RGBA32UI:
1732 return DXGI_FORMAT_R32G32B32A32_UINT;
1734 case QRhiTexture::D16:
1735 return DXGI_FORMAT_R16_TYPELESS;
1736 case QRhiTexture::D24:
1737 return DXGI_FORMAT_R24G8_TYPELESS;
1738 case QRhiTexture::D24S8:
1739 return DXGI_FORMAT_R24G8_TYPELESS;
1740 case QRhiTexture::D32F:
1741 return DXGI_FORMAT_R32_TYPELESS;
1742 case QRhiTexture::D32FS8:
1743 return DXGI_FORMAT_R32G8X24_TYPELESS;
1745 case QRhiTexture::BC1:
1746 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1747 case QRhiTexture::BC2:
1748 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1749 case QRhiTexture::BC3:
1750 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1751 case QRhiTexture::BC4:
1752 return DXGI_FORMAT_BC4_UNORM;
1753 case QRhiTexture::BC5:
1754 return DXGI_FORMAT_BC5_UNORM;
1755 case QRhiTexture::BC6H:
1756 return DXGI_FORMAT_BC6H_UF16;
1757 case QRhiTexture::BC7:
1758 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1760 case QRhiTexture::ETC2_RGB8:
1761 case QRhiTexture::ETC2_RGB8A1:
1762 case QRhiTexture::ETC2_RGBA8:
1763 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1764 return DXGI_FORMAT_R8G8B8A8_UNORM;
1766 case QRhiTexture::ASTC_4x4:
1767 case QRhiTexture::ASTC_5x4:
1768 case QRhiTexture::ASTC_5x5:
1769 case QRhiTexture::ASTC_6x5:
1770 case QRhiTexture::ASTC_6x6:
1771 case QRhiTexture::ASTC_8x5:
1772 case QRhiTexture::ASTC_8x6:
1773 case QRhiTexture::ASTC_8x8:
1774 case QRhiTexture::ASTC_10x5:
1775 case QRhiTexture::ASTC_10x6:
1776 case QRhiTexture::ASTC_10x8:
1777 case QRhiTexture::ASTC_10x10:
1778 case QRhiTexture::ASTC_12x10:
1779 case QRhiTexture::ASTC_12x12:
1780 qWarning(
"QRhiD3D11 does not support ASTC textures");
1781 return DXGI_FORMAT_R8G8B8A8_UNORM;
1785 return DXGI_FORMAT_R8G8B8A8_UNORM;
1792 case DXGI_FORMAT_R8G8B8A8_UNORM:
1793 return QRhiTexture::RGBA8;
1794 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1796 (*flags) |= QRhiTexture::sRGB;
1797 return QRhiTexture::RGBA8;
1798 case DXGI_FORMAT_B8G8R8A8_UNORM:
1799 return QRhiTexture::BGRA8;
1800 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1802 (*flags) |= QRhiTexture::sRGB;
1803 return QRhiTexture::BGRA8;
1804 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1805 return QRhiTexture::RGBA16F;
1806 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1807 return QRhiTexture::RGBA32F;
1808 case DXGI_FORMAT_R10G10B10A2_UNORM:
1809 return QRhiTexture::RGB10A2;
1811 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1814 return QRhiTexture::UnknownFormat;
1820 case QRhiTexture::Format::D16:
1821 case QRhiTexture::Format::D24:
1822 case QRhiTexture::Format::D24S8:
1823 case QRhiTexture::Format::D32F:
1824 case QRhiTexture::Format::D32FS8:
1837 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1839 ofr.cbWrapper.resetCommands();
1850 return QRhi::FrameOpSuccess;
1854 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1856 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1857 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1859 box.front = is3D ? UINT(layer) : 0u;
1861 box.back = box.front + 1;
1864 cmd.args.updateSubRes.dst = texD->textureResource();
1865 cmd.args.updateSubRes.dstSubRes = subres;
1867 const QPoint dp = subresDesc.destinationTopLeft();
1868 if (!subresDesc.image().isNull()) {
1869 QImage img = subresDesc.image();
1870 QSize size = img.size();
1871 int bpl = img.bytesPerLine();
1872 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1873 const QPoint sp = subresDesc.sourceTopLeft();
1874 if (!subresDesc.sourceSize().isEmpty())
1875 size = subresDesc.sourceSize();
1876 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1877 if (img.depth() == 32) {
1878 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1879 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1881 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1882 bpl = img.bytesPerLine();
1883 cmd.args.updateSubRes.src = cbD->retainImage(img);
1886 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1887 cmd.args.updateSubRes.src = cbD->retainImage(img);
1889 box.left = UINT(dp.x());
1890 box.top = UINT(dp.y());
1891 box.right = UINT(dp.x() + size.width());
1892 box.bottom = UINT(dp.y() + size.height());
1893 cmd.args.updateSubRes.hasDstBox =
true;
1894 cmd.args.updateSubRes.dstBox = box;
1895 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1896 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1897 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1898 : subresDesc.sourceSize();
1901 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1905 box.left = UINT(aligned(dp.x(), blockDim.width()));
1906 box.top = UINT(aligned(dp.y(), blockDim.height()));
1907 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1908 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1909 cmd.args.updateSubRes.hasDstBox =
true;
1910 cmd.args.updateSubRes.dstBox = box;
1911 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1912 cmd.args.updateSubRes.srcRowPitch = bpl;
1913 }
else if (!subresDesc.data().isEmpty()) {
1914 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1915 : subresDesc.sourceSize();
1917 if (subresDesc.dataStride())
1918 bpl = subresDesc.dataStride();
1920 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1921 box.left = UINT(dp.x());
1922 box.top = UINT(dp.y());
1923 box.right = UINT(dp.x() + size.width());
1924 box.bottom = UINT(dp.y() + size.height());
1925 cmd.args.updateSubRes.hasDstBox =
true;
1926 cmd.args.updateSubRes.dstBox = box;
1927 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1928 cmd.args.updateSubRes.srcRowPitch = bpl;
1930 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1931 cbD->commands.unget();
1944 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1949 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1950 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1953 cmd.args.updateSubRes.dst = bufD->buffer;
1954 cmd.args.updateSubRes.dstSubRes = 0;
1955 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1956 cmd.args.updateSubRes.srcRowPitch = 0;
1961 box.left = u.offset;
1962 box.top = box.front = 0;
1963 box.back = box.bottom = 1;
1964 box.right = u.offset + u
.data.size();
1965 cmd.args.updateSubRes.hasDstBox =
true;
1966 cmd.args.updateSubRes.dstBox = box;
1969 if (bufD->m_type == QRhiBuffer::Dynamic) {
1970 u.result->data.resize(u.readSize);
1971 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1972 if (u.result->completed)
1973 u.result->completed();
1976 readback.result = u.result;
1977 readback.byteSize = u.readSize;
1979 D3D11_BUFFER_DESC desc = {};
1980 desc.ByteWidth = readback.byteSize;
1981 desc.Usage = D3D11_USAGE_STAGING;
1982 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1983 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1985 qWarning(
"Failed to create buffer: %s",
1986 qPrintable(QSystemError::windowsComString(hr)));
1992 cmd.args.copySubRes.dst = readback.stagingBuf;
1993 cmd.args.copySubRes.dstSubRes = 0;
1994 cmd.args.copySubRes.dstX = 0;
1995 cmd.args.copySubRes.dstY = 0;
1996 cmd.args.copySubRes.dstZ = 0;
1997 cmd.args.copySubRes.src = bufD->buffer;
1998 cmd.args.copySubRes.srcSubRes = 0;
1999 cmd.args.copySubRes.hasSrcBox =
true;
2001 box.left = u.offset;
2002 box.top = box.front = 0;
2003 box.back = box.bottom = 1;
2004 box.right = u.offset + u.readSize;
2005 cmd.args.copySubRes.srcBox = box;
2007 activeBufferReadbacks.append(readback);
2015 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2016 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2017 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2018 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2025 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2026 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2027 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2028 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2029 const QPoint dp = u.desc.destinationTopLeft();
2030 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2031 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2032 const QPoint sp = u.desc.sourceTopLeft();
2034 srcBox.left = UINT(sp.x());
2035 srcBox.top = UINT(sp.y());
2036 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2038 srcBox.right = srcBox.left + UINT(copySize.width());
2039 srcBox.bottom = srcBox.top + UINT(copySize.height());
2040 srcBox.back = srcBox.front + 1;
2043 cmd.args.copySubRes.dst = dstD->textureResource();
2044 cmd.args.copySubRes.dstSubRes = dstSubRes;
2045 cmd.args.copySubRes.dstX = UINT(dp.x());
2046 cmd.args.copySubRes.dstY = UINT(dp.y());
2047 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2048 cmd.args.copySubRes.src = srcD->textureResource();
2049 cmd.args.copySubRes.srcSubRes = srcSubRes;
2050 cmd.args.copySubRes.hasSrcBox =
true;
2051 cmd.args.copySubRes.srcBox = srcBox;
2054 readback.desc = u.rb;
2055 readback.result = u.result;
2057 ID3D11Resource *src;
2058 DXGI_FORMAT dxgiFormat;
2060 QRhiTexture::Format format;
2067 if (texD->sampleDesc.Count > 1) {
2068 qWarning(
"Multisample texture cannot be read back");
2071 src = texD->textureResource();
2072 dxgiFormat = texD->dxgiFormat;
2073 if (u.rb.rect().isValid())
2076 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2077 format = texD->m_format;
2078 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2079 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2083 if (swapChainD->sampleDesc.Count > 1) {
2088 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2089 rcmd.args.resolveSubRes.dstSubRes = 0;
2091 rcmd.args.resolveSubRes.srcSubRes = 0;
2092 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2094 src = swapChainD->backBufferTex;
2095 dxgiFormat = swapChainD->colorFormat;
2096 if (u.rb.rect().isValid())
2099 rect = QRect({0, 0}, swapChainD->pixelSize);
2100 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2101 if (format == QRhiTexture::UnknownFormat)
2104 quint32 byteSize = 0;
2106 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2108 D3D11_TEXTURE2D_DESC desc = {};
2109 desc.Width = UINT(rect.width());
2110 desc.Height = UINT(rect.height());
2113 desc.Format = dxgiFormat;
2114 desc.SampleDesc.Count = 1;
2115 desc.Usage = D3D11_USAGE_STAGING;
2116 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2117 ID3D11Texture2D *stagingTex;
2118 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2120 qWarning(
"Failed to create readback staging texture: %s",
2121 qPrintable(QSystemError::windowsComString(hr)));
2127 cmd.args.copySubRes.dst = stagingTex;
2128 cmd.args.copySubRes.dstSubRes = 0;
2129 cmd.args.copySubRes.dstX = 0;
2130 cmd.args.copySubRes.dstY = 0;
2131 cmd.args.copySubRes.dstZ = 0;
2132 cmd.args.copySubRes.src = src;
2133 cmd.args.copySubRes.srcSubRes = subres;
2135 D3D11_BOX srcBox = {};
2136 srcBox.left = UINT(rect.left());
2137 srcBox.top = UINT(rect.top());
2138 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2140 srcBox.right = srcBox.left + desc.Width;
2141 srcBox.bottom = srcBox.top + desc.Height;
2142 srcBox.back = srcBox.front + 1;
2143 cmd.args.copySubRes.hasSrcBox =
true;
2144 cmd.args.copySubRes.srcBox = srcBox;
2146 readback.stagingTex = stagingTex;
2147 readback.byteSize = byteSize;
2149 readback.pixelSize = rect.size();
2150 readback.format = format;
2152 activeTextureReadbacks.append(readback);
2154 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2157 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2166 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2168 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2170 readback.result->format = readback.format;
2171 readback.result->pixelSize = readback.pixelSize;
2173 D3D11_MAPPED_SUBRESOURCE mp;
2174 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2175 if (SUCCEEDED(hr)) {
2176 readback.result->data.resize(
int(readback.byteSize));
2179 char *dst = readback.result->data.data();
2180 char *src =
static_cast<
char *>(mp.pData);
2181 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2182 memcpy(dst, src, readback.bpl);
2183 dst += readback.bpl;
2186 context->Unmap(readback.stagingTex, 0);
2188 qWarning(
"Failed to map readback staging texture: %s",
2189 qPrintable(QSystemError::windowsComString(hr)));
2192 readback.stagingTex->Release();
2194 if (readback.result->completed)
2195 completedCallbacks.append(readback.result->completed);
2197 activeTextureReadbacks.removeLast();
2200 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2203 D3D11_MAPPED_SUBRESOURCE mp;
2204 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2205 if (SUCCEEDED(hr)) {
2206 readback.result->data.resize(
int(readback.byteSize));
2207 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2208 context->Unmap(readback.stagingBuf, 0);
2210 qWarning(
"Failed to map readback staging texture: %s",
2211 qPrintable(QSystemError::windowsComString(hr)));
2214 readback.stagingBuf->Release();
2216 if (readback.result->completed)
2217 completedCallbacks.append(readback.result->completed);
2219 activeBufferReadbacks.removeLast();
2222 for (
auto f : completedCallbacks)
2228 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2234 QRhiRenderTarget *rt,
2235 const QColor &colorClearValue,
2236 const QRhiDepthStencilClearValue &depthStencilClearValue,
2237 QRhiResourceUpdateBatch *resourceUpdates,
2243 if (resourceUpdates)
2246 bool wantsColorClear =
true;
2247 bool wantsDsClear =
true;
2249 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2251 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2252 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2253 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2261 fbCmd.args.setRenderTarget.rt = rt;
2265 clearCmd.args.clear.rt = rt;
2266 clearCmd.args.clear.mask = 0;
2272 clearCmd.args.clear.c[0] = colorClearValue.redF();
2273 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2274 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2275 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2276 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2277 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2280 cbD->currentTarget = rt;
2290 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2292 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2295 const QRhiColorAttachment &colorAtt(*it);
2296 if (!colorAtt.resolveTexture())
2302 Q_ASSERT(srcTexD || srcRbD);
2305 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2306 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2307 UINT(colorAtt.resolveLayer()),
2308 dstTexD->mipLevelCount);
2310 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2311 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2312 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2313 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2314 cbD->commands.unget();
2317 if (srcTexD->sampleDesc.Count <= 1) {
2318 qWarning(
"Cannot resolve a non-multisample texture");
2319 cbD->commands.unget();
2322 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2323 qWarning(
"Resolve source and destination sizes do not match");
2324 cbD->commands.unget();
2328 cmd.args.resolveSubRes.src = srcRbD->tex;
2329 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2330 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2331 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2332 cbD->commands.unget();
2335 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2336 qWarning(
"Resolve source and destination sizes do not match");
2337 cbD->commands.unget();
2341 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2342 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2344 if (rtTex->m_desc.depthResolveTexture())
2345 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2349 cbD->currentTarget =
nullptr;
2351 if (resourceUpdates)
2356 QRhiResourceUpdateBatch *resourceUpdates,
2362 if (resourceUpdates)
2380 if (resourceUpdates)
2389 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2391 if (pipelineChanged) {
2392 cbD->currentGraphicsPipeline =
nullptr;
2393 cbD->currentComputePipeline = psD;
2394 cbD->currentPipelineGeneration = psD->generation;
2398 cmd.args.bindComputePipeline.ps = psD;
2409 cmd.args.dispatch.x = UINT(x);
2410 cmd.args.dispatch.y = UINT(y);
2411 cmd.args.dispatch.z = UINT(z);
2416 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2418 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2419 if (!map || map->isEmpty())
2420 return { binding, binding };
2422 auto it = map->constFind(binding);
2423 if (it != map->cend())
2433 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2435 srbD->resourceBatches.clear();
2441 ID3D11Buffer *buffer;
2442 uint offsetInConstants;
2443 uint sizeInConstants;
2447 ID3D11ShaderResourceView *srv;
2451 ID3D11SamplerState *sampler;
2455 ID3D11UnorderedAccessView *uav;
2457 QVarLengthArray<Buffer, 8> buffers;
2458 QVarLengthArray<Texture, 8> textures;
2459 QVarLengthArray<Sampler, 8> samplers;
2460 QVarLengthArray<Uav, 8> uavs;
2463 for (
const Buffer &buf : buffers) {
2464 batches.ubufs.feed(buf.breg, buf.buffer);
2465 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2466 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2467 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2473 for (
const Texture &t : textures)
2474 batches.shaderresources.feed(t.treg, t.srv);
2475 for (
const Sampler &s : samplers)
2476 batches.samplers.feed(s.sreg, s.sampler);
2481 for (
const Stage::Uav &u : uavs)
2482 batches.uavs.feed(u.ureg, u.uav);
2487 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2488 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2491 case QRhiShaderResourceBinding::UniformBuffer:
2494 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2495 bd.ubuf.id = bufD->m_id;
2496 bd.ubuf.generation = bufD->generation;
2503 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2507 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2508 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2509 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2510 if (nativeBinding.first >= 0)
2511 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2513 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2514 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2515 if (nativeBinding.first >= 0)
2516 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2518 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2519 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2520 if (nativeBinding.first >= 0)
2521 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2523 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2524 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2525 if (nativeBinding.first >= 0)
2526 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2528 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2529 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2530 if (nativeBinding.first >= 0)
2531 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2533 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2534 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2535 if (nativeBinding.first >= 0)
2536 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2540 case QRhiShaderResourceBinding::SampledTexture:
2541 case QRhiShaderResourceBinding::Texture:
2542 case QRhiShaderResourceBinding::Sampler:
2544 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2545 bd.stex.count = data->count;
2546 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2547 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2548 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2549 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2550 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2551 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2555 for (
int elem = 0; elem < data->count; ++elem) {
2558 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2559 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2560 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2561 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2566 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2567 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2568 : (samplerD ? nativeBindingVert.first : -1);
2569 if (nativeBindingVert.first >= 0 && texD)
2570 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2571 if (samplerBinding >= 0)
2572 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2574 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2575 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2576 : (samplerD ? nativeBindingHull.first : -1);
2577 if (nativeBindingHull.first >= 0 && texD)
2578 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2579 if (samplerBinding >= 0)
2580 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2582 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2583 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2584 : (samplerD ? nativeBindingDomain.first : -1);
2585 if (nativeBindingDomain.first >= 0 && texD)
2586 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2587 if (samplerBinding >= 0)
2588 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2590 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2591 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2592 : (samplerD ? nativeBindingGeom.first : -1);
2593 if (nativeBindingGeom.first >= 0 && texD)
2594 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2595 if (samplerBinding >= 0)
2596 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2598 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2599 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2600 : (samplerD ? nativeBindingFrag.first : -1);
2601 if (nativeBindingFrag.first >= 0 && texD)
2602 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2603 if (samplerBinding >= 0)
2604 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2606 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2607 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2608 : (samplerD ? nativeBindingComp.first : -1);
2609 if (nativeBindingComp.first >= 0 && texD)
2610 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2611 if (samplerBinding >= 0)
2612 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2617 case QRhiShaderResourceBinding::ImageLoad:
2618 case QRhiShaderResourceBinding::ImageStore:
2619 case QRhiShaderResourceBinding::ImageLoadStore:
2622 bd.simage.id = texD->m_id;
2623 bd.simage.generation = texD->generation;
2624 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2625 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2626 if (nativeBinding.first >= 0) {
2627 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2629 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2631 }
else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2632 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2633 if (nativeBinding.first >= 0) {
2634 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2636 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2639 qWarning(
"Unordered access only supported at fragment/compute stage");
2643 case QRhiShaderResourceBinding::BufferLoad:
2644 case QRhiShaderResourceBinding::BufferStore:
2645 case QRhiShaderResourceBinding::BufferLoadStore:
2648 bd.sbuf.id = bufD->m_id;
2649 bd.sbuf.generation = bufD->generation;
2650 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2651 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2652 if (nativeBinding.first >= 0) {
2653 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2655 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2658 qWarning(
"Unordered access only supported at compute stage");
2673 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2674 return a.breg < b.breg;
2676 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2677 return a.treg < b.treg;
2679 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2680 return a.sreg < b.sreg;
2682 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2683 return a.ureg < b.ureg;
2687 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2688 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2689 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2690 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2691 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2692 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2694 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2695 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2696 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2697 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2698 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2699 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2701 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2702 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2710 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2712 D3D11_MAPPED_SUBRESOURCE mp;
2713 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2714 if (SUCCEEDED(hr)) {
2715 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2716 context->Unmap(bufD->buffer, 0);
2718 qWarning(
"Failed to map buffer: %s",
2719 qPrintable(QSystemError::windowsComString(hr)));
2725 const QRhiBatchedBindings<UINT> *originalBindings,
2726 const QRhiBatchedBindings<UINT> *staticOffsets,
2727 const uint *dynOfsPairs,
int dynOfsPairCount)
2729 const int count = staticOffsets->batches[batchIndex].resources.count();
2732 for (
int b = 0; b < count; ++b) {
2733 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2734 for (
int di = 0; di < dynOfsPairCount; ++di) {
2735 const uint binding = dynOfsPairs[2 * di];
2738 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2739 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2740 offsets[b] = offsetInConstants;
2749 if (startSlot + countSlots > maxSlots) {
2750 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2751 resType, countSlots, startSlot, maxSlots);
2752 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2757#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2758 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2759 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2760 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2761 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2762 batches.ubufs.batches[i].resources.count(),
2763 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2764 #stagePrefixU " cbuf");
2766 if (!dynOfsPairCount) {
2767 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2769 batches.ubufs.batches[i].resources.constData(),
2770 batches.ubufoffsets.batches[i].resources.constData(),
2771 batches.ubufsizes.batches[i].resources.constData());
2773 applyDynamicOffsets(offsets, i,
2774 &batches.ubuforigbindings, &batches.ubufoffsets,
2775 dynOfsPairs, dynOfsPairCount);
2776 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2778 batches.ubufs.batches[i].resources.constData(),
2780 batches.ubufsizes.batches[i].resources.constData());
2786#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2787 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2788 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2789 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2790 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2792 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2794 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2795 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2796 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2798 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2799 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2800 int(batch.startBinding + count) - 1
);
2805#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2806 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2807 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2808 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2811 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2813 batch.resources.constData(),
2815 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2816 int(batch.startBinding + count) - 1
);
2822 const uint *dynOfsPairs,
int dynOfsPairCount,
2823 bool offsetOnlyChange,
2836 if (!offsetOnlyChange) {
2846 if (allResourceBatches.fsUavBatches.present) {
2847 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2848 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2850 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2852 if (rtUavState.update(rtD, batch.resources.constData(), count)) {
2853 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv,
2854 UINT(rtD->colorAttCount), count, batch.resources.constData(),
nullptr);
2856 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2857 int(batch.startBinding + count) - 1);
2870 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2876 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2877 for (
int i = 0; i < count; ++i)
2878 nullbufs[i] =
nullptr;
2879 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2880 for (
int i = 0; i < count; ++i)
2882 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2883 for (
int i = 0; i < count; ++i)
2885 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2895 if (nullsrvCount > 0) {
2896 QVarLengthArray<ID3D11ShaderResourceView *,
2897 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2898 for (
int i = 0; i < nullsrvs.count(); ++i)
2899 nullsrvs[i] =
nullptr;
2901 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2905 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2909 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2913 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2917 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2921 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2927 rtUavState.update(rtD);
2928 context->OMSetRenderTargetsAndUnorderedAccessViews(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv, 0, 0,
nullptr,
nullptr);
2933 QVarLengthArray<ID3D11UnorderedAccessView *,
2934 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2935 for (
int i = 0; i < nulluavCount; ++i)
2936 nulluavs[i] =
nullptr;
2937 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2942#define SETSHADER(StageL, StageU)
2943 if (psD->StageL.shader) {
2944 context->StageU##SetShader(psD->StageL.shader, nullptr, 0
);
2945 currentShaderMask |= StageU##MaskBit;
2946 } else if (currentShaderMask & StageU##MaskBit) {
2947 context->StageU##SetShader(nullptr, nullptr, 0
);
2948 currentShaderMask &= ~StageU##MaskBit;
2953 quint32 stencilRef = 0;
2954 float blendConstants[] = { 1, 1, 1, 1 };
2955 enum ActiveShaderMask {
2962 int currentShaderMask = 0xFF;
2968 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
2971 case QD3D11CommandBuffer::Command::BeginFrame:
2972 if (cmd.args.beginFrame.tsDisjointQuery)
2973 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
2974 if (cmd.args.beginFrame.tsQuery) {
2975 if (cmd.args.beginFrame.swapchainData) {
2981 rtUavState.update(rtD);
2982 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
2985 context->End(cmd.args.beginFrame.tsQuery);
2988 case QD3D11CommandBuffer::Command::EndFrame:
2989 if (cmd.args.endFrame.tsQuery)
2990 context->End(cmd.args.endFrame.tsQuery);
2991 if (cmd.args.endFrame.tsDisjointQuery)
2992 context->End(cmd.args.endFrame.tsDisjointQuery);
3000 if (rtUavState.update(rtD))
3001 context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv :
nullptr, rtD->dsv);
3009 for (
int i = 0; i < rtD->colorAttCount; ++i)
3010 context->ClearRenderTargetView(rtD->rtv[i], cmd.args.clear.c);
3013 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3014 ds |= D3D11_CLEAR_DEPTH;
3015 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3016 ds |= D3D11_CLEAR_STENCIL;
3018 context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3024 v.TopLeftX = cmd.args.viewport.x;
3025 v.TopLeftY = cmd.args.viewport.y;
3026 v.Width = cmd.args.viewport.w;
3027 v.Height = cmd.args.viewport.h;
3028 v.MinDepth = cmd.args.viewport.d0;
3029 v.MaxDepth = cmd.args.viewport.d1;
3030 context->RSSetViewports(1, &v);
3036 r.left = cmd.args.scissor.x;
3037 r.top = cmd.args.scissor.y;
3039 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3040 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3041 context->RSSetScissorRects(1, &r);
3047 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3048 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3049 UINT(cmd.args.bindVertexBuffers.slotCount),
3050 cmd.args.bindVertexBuffers.buffers,
3051 cmd.args.bindVertexBuffers.strides,
3052 cmd.args.bindVertexBuffers.offsets);
3056 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3057 cmd.args.bindIndexBuffer.format,
3058 cmd.args.bindIndexBuffer.offset);
3068 context->IASetPrimitiveTopology(psD->d3dTopology);
3069 context->IASetInputLayout(psD->inputLayout);
3070 context->OMSetDepthStencilState(psD->dsState, stencilRef);
3071 context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
3072 context->RSSetState(psD->rastState);
3075 case QD3D11CommandBuffer::Command::BindShaderResources:
3076 bindShaderResources(cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3077 cmd.args.bindShaderResources.dynamicOffsetPairs,
3078 cmd.args.bindShaderResources.dynamicOffsetCount,
3079 cmd.args.bindShaderResources.offsetOnlyChange,
3084 stencilRef = cmd.args.stencilRef.ref;
3085 context->OMSetDepthStencilState(cmd.args.stencilRef.ps->dsState, stencilRef);
3088 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3089 context->OMSetBlendState(cmd.args.blendConstants.ps->blendState, blendConstants, 0xffffffff);
3092 if (cmd.args.draw.ps) {
3093 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3094 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3096 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3097 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3099 qWarning(
"No graphics pipeline active for draw; ignored");
3103 if (cmd.args.drawIndexed.ps) {
3104 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3105 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3106 cmd.args.drawIndexed.vertexOffset);
3108 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3109 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3110 cmd.args.drawIndexed.firstInstance);
3112 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3116 if (cmd.args.drawIndirect.ps) {
3117 ID3D11Buffer *pBufferForArgs = cmd.args.drawIndirect.indirectBuffer->buffer;
3118 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3119 const UINT stride = cmd.args.drawIndirect.stride;
3120 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3121 context->DrawInstancedIndirect(pBufferForArgs, alignedByteOffsetForArgs);
3122 alignedByteOffsetForArgs += stride;
3125 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
3129 if (cmd.args.drawIndexedIndirect.ps) {
3130 ID3D11Buffer *pBufferForArgs = cmd.args.drawIndexedIndirect.indirectBuffer->buffer;
3131 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3132 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3133 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3134 context->DrawIndexedInstancedIndirect(pBufferForArgs, alignedByteOffsetForArgs);
3135 alignedByteOffsetForArgs += stride;
3138 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
3141 case QD3D11CommandBuffer::Command::UpdateSubRes:
3142 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3143 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3144 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3146 case QD3D11CommandBuffer::Command::CopySubRes:
3147 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3148 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3149 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3150 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3152 case QD3D11CommandBuffer::Command::ResolveSubRes:
3153 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3154 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3155 cmd.args.resolveSubRes.format);
3157 case QD3D11CommandBuffer::Command::GenMip:
3158 context->GenerateMips(cmd.args.genMip.srv);
3160 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3161 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3163 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3164 annotations->EndEvent();
3166 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3167 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3169 case QD3D11CommandBuffer::Command::BindComputePipeline:
3170 context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader,
nullptr, 0);
3172 case QD3D11CommandBuffer::Command::Dispatch:
3173 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3202 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3203 it.value()->Release();
3208 rhiD->unregisterResource(
this);
3214 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3215 u |= D3D11_BIND_VERTEX_BUFFER;
3216 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3217 u |= D3D11_BIND_INDEX_BUFFER;
3218 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3219 u |= D3D11_BIND_CONSTANT_BUFFER;
3220 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3221 u |= D3D11_BIND_UNORDERED_ACCESS;
3230 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3231 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3235 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3236 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3240 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3241 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3245 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3246 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3248 D3D11_BUFFER_DESC desc = {};
3249 desc.ByteWidth = roundedSize;
3250 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3251 desc.BindFlags = toD3DBufferUsage(m_usage);
3252 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3253 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3254 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3255 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3258 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3260 qWarning(
"Failed to create buffer: %s",
3261 qPrintable(QSystemError::windowsComString(hr)));
3265 if (m_type == Dynamic) {
3266 dynBuf =
new char[nonZeroSize];
3270 if (!m_objectName.isEmpty())
3271 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3274 rhiD->registerResource(
this);
3280 if (m_type == Dynamic) {
3284 return { { &buffer }, 1 };
3295 Q_ASSERT(m_type == Dynamic);
3296 D3D11_MAPPED_SUBRESOURCE mp;
3298 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3300 qWarning(
"Failed to map buffer: %s",
3301 qPrintable(QSystemError::windowsComString(hr)));
3304 return static_cast<
char *>(mp.pData);
3310 rhiD->context->Unmap(buffer, 0);
3315 auto it = uavs.find(offset);
3316 if (it != uavs.end())
3320 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3321 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3322 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3323 desc.Buffer.FirstElement = offset / 4u;
3324 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3325 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3328 ID3D11UnorderedAccessView *uav =
nullptr;
3329 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3331 qWarning(
"Failed to create UAV: %s",
3332 qPrintable(QSystemError::windowsComString(hr)));
3341 int sampleCount, QRhiRenderBuffer::Flags flags,
3342 QRhiTexture::Format backingFormatHint)
3372 rhiD->unregisterResource(
this);
3380 if (m_pixelSize.isEmpty())
3384 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3386 D3D11_TEXTURE2D_DESC desc = {};
3387 desc.Width = UINT(m_pixelSize.width());
3388 desc.Height = UINT(m_pixelSize.height());
3391 desc.SampleDesc = sampleDesc;
3392 desc.Usage = D3D11_USAGE_DEFAULT;
3394 if (m_type == Color) {
3395 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3396 : toD3DTextureFormat(m_backingFormatHint, {});
3397 desc.Format = dxgiFormat;
3398 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3399 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3401 qWarning(
"Failed to create color renderbuffer: %s",
3402 qPrintable(QSystemError::windowsComString(hr)));
3405 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3406 rtvDesc.Format = dxgiFormat;
3407 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3408 : D3D11_RTV_DIMENSION_TEXTURE2D;
3409 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3411 qWarning(
"Failed to create rtv: %s",
3412 qPrintable(QSystemError::windowsComString(hr)));
3415 }
else if (m_type == DepthStencil) {
3416 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3417 desc.Format = dxgiFormat;
3418 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3419 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3421 qWarning(
"Failed to create depth-stencil buffer: %s",
3422 qPrintable(QSystemError::windowsComString(hr)));
3425 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3426 dsvDesc.Format = dxgiFormat;
3427 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3428 : D3D11_DSV_DIMENSION_TEXTURE2D;
3429 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3431 qWarning(
"Failed to create dsv: %s",
3432 qPrintable(QSystemError::windowsComString(hr)));
3439 if (!m_objectName.isEmpty())
3440 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3443 rhiD->registerResource(
this);
3449 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3450 return m_backingFormatHint;
3452 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3456 int arraySize,
int sampleCount, Flags flags)
3459 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3460 perLevelViews[i] =
nullptr;
3470 if (!tex && !tex3D && !tex1D)
3478 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3479 if (perLevelViews[i]) {
3480 perLevelViews[i]->Release();
3481 perLevelViews[i] =
nullptr;
3500 rhiD->unregisterResource(
this);
3506 case QRhiTexture::Format::D16:
3507 return DXGI_FORMAT_R16_FLOAT;
3508 case QRhiTexture::Format::D24:
3509 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3510 case QRhiTexture::Format::D24S8:
3511 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3512 case QRhiTexture::Format::D32F:
3513 return DXGI_FORMAT_R32_FLOAT;
3514 case QRhiTexture::Format::D32FS8:
3515 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3518 return DXGI_FORMAT_R32_FLOAT;
3525 case QRhiTexture::Format::D16:
3526 return DXGI_FORMAT_D16_UNORM;
3527 case QRhiTexture::Format::D24:
3528 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3529 case QRhiTexture::Format::D24S8:
3530 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3531 case QRhiTexture::Format::D32F:
3532 return DXGI_FORMAT_D32_FLOAT;
3533 case QRhiTexture::Format::D32FS8:
3534 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3537 return DXGI_FORMAT_D32_FLOAT;
3543 if (tex || tex3D || tex1D)
3547 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3550 const bool isDepth = isDepthTextureFormat(m_format);
3551 const bool isCube = m_flags.testFlag(CubeMap);
3552 const bool is3D = m_flags.testFlag(ThreeDimensional);
3553 const bool isArray = m_flags.testFlag(TextureArray);
3554 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3555 const bool is1D = m_flags.testFlag(OneDimensional);
3557 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3558 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3560 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3561 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3562 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3563 if (sampleDesc.Count > 1) {
3565 qWarning(
"Cubemap texture cannot be multisample");
3569 qWarning(
"3D texture cannot be multisample");
3573 qWarning(
"Multisample texture cannot have mipmaps");
3577 if (isDepth && hasMipMaps) {
3578 qWarning(
"Depth texture cannot have mipmaps");
3581 if (isCube && is3D) {
3582 qWarning(
"Texture cannot be both cube and 3D");
3585 if (isArray && is3D) {
3586 qWarning(
"Texture cannot be both array and 3D");
3589 if (isCube && is1D) {
3590 qWarning(
"Texture cannot be both cube and 1D");
3594 qWarning(
"Texture cannot be both 1D and 3D");
3597 if (m_depth > 1 && !is3D) {
3598 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3601 if (m_arraySize > 0 && !isArray) {
3602 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3605 if (m_arraySize < 1 && isArray) {
3606 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3611 *adjustedSize = size;
3619 const bool isDepth = isDepthTextureFormat(m_format);
3620 const bool isCube = m_flags.testFlag(CubeMap);
3621 const bool is3D = m_flags.testFlag(ThreeDimensional);
3622 const bool isArray = m_flags.testFlag(TextureArray);
3623 const bool is1D = m_flags.testFlag(OneDimensional);
3625 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3626 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3628 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3629 srvDesc.TextureCube.MipLevels = mipLevelCount;
3633 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3634 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3635 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3636 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3637 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3639 srvDesc.Texture1DArray.FirstArraySlice = 0;
3640 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3643 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3644 srvDesc.Texture1D.MipLevels = mipLevelCount;
3646 }
else if (isArray) {
3647 if (sampleDesc.Count > 1) {
3648 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3649 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3650 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3651 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3653 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3654 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3657 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3658 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3659 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3660 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3661 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3663 srvDesc.Texture2DArray.FirstArraySlice = 0;
3664 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3668 if (sampleDesc.Count > 1) {
3669 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3671 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3672 srvDesc.Texture3D.MipLevels = mipLevelCount;
3674 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3675 srvDesc.Texture2D.MipLevels = mipLevelCount;
3680 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3682 qWarning(
"Failed to create srv: %s",
3683 qPrintable(QSystemError::windowsComString(hr)));
3694 if (!prepareCreate(&size))
3697 const bool isDepth = isDepthTextureFormat(m_format);
3698 const bool isCube = m_flags.testFlag(CubeMap);
3699 const bool is3D = m_flags.testFlag(ThreeDimensional);
3700 const bool isArray = m_flags.testFlag(TextureArray);
3701 const bool is1D = m_flags.testFlag(OneDimensional);
3703 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3704 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3705 if (m_flags.testFlag(RenderTarget)) {
3707 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3709 bindFlags |= D3D11_BIND_RENDER_TARGET;
3711 if (m_flags.testFlag(UsedWithGenerateMips)) {
3713 qWarning(
"Depth texture cannot have mipmaps generated");
3716 bindFlags |= D3D11_BIND_RENDER_TARGET;
3717 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3719 if (m_flags.testFlag(UsedWithLoadStore))
3720 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3724 D3D11_TEXTURE1D_DESC desc = {};
3725 desc.Width = UINT(size.width());
3726 desc.MipLevels = mipLevelCount;
3727 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3728 desc.Format = dxgiFormat;
3729 desc.Usage = D3D11_USAGE_DEFAULT;
3730 desc.BindFlags = bindFlags;
3731 desc.MiscFlags = miscFlags;
3733 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3735 qWarning(
"Failed to create 1D texture: %s",
3736 qPrintable(QSystemError::windowsComString(hr)));
3739 if (!m_objectName.isEmpty())
3740 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3741 m_objectName.constData());
3743 D3D11_TEXTURE2D_DESC desc = {};
3744 desc.Width = UINT(size.width());
3745 desc.Height = UINT(size.height());
3746 desc.MipLevels = mipLevelCount;
3747 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3748 desc.Format = dxgiFormat;
3749 desc.SampleDesc = sampleDesc;
3750 desc.Usage = D3D11_USAGE_DEFAULT;
3751 desc.BindFlags = bindFlags;
3752 desc.MiscFlags = miscFlags;
3754 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3756 qWarning(
"Failed to create 2D texture: %s",
3757 qPrintable(QSystemError::windowsComString(hr)));
3760 if (!m_objectName.isEmpty())
3761 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3763 D3D11_TEXTURE3D_DESC desc = {};
3764 desc.Width = UINT(size.width());
3765 desc.Height = UINT(size.height());
3766 desc.Depth = UINT(qMax(1, m_depth));
3767 desc.MipLevels = mipLevelCount;
3768 desc.Format = dxgiFormat;
3769 desc.Usage = D3D11_USAGE_DEFAULT;
3770 desc.BindFlags = bindFlags;
3771 desc.MiscFlags = miscFlags;
3773 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3775 qWarning(
"Failed to create 3D texture: %s",
3776 qPrintable(QSystemError::windowsComString(hr)));
3779 if (!m_objectName.isEmpty())
3780 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3787 rhiD->registerResource(
this);
3796 if (!prepareCreate())
3799 if (m_flags.testFlag(ThreeDimensional))
3800 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3801 else if (m_flags.testFlags(OneDimensional))
3802 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3804 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3811 rhiD->registerResource(
this);
3817 return { quint64(textureResource()), 0 };
3822 if (perLevelViews[level])
3823 return perLevelViews[level];
3825 const bool isCube = m_flags.testFlag(CubeMap);
3826 const bool isArray = m_flags.testFlag(TextureArray);
3827 const bool is3D = m_flags.testFlag(ThreeDimensional);
3828 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3829 desc.Format = dxgiFormat;
3831 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3832 desc.Texture2DArray.MipSlice = UINT(level);
3833 desc.Texture2DArray.FirstArraySlice = 0;
3834 desc.Texture2DArray.ArraySize = 6;
3835 }
else if (isArray) {
3836 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3837 desc.Texture2DArray.MipSlice = UINT(level);
3838 desc.Texture2DArray.FirstArraySlice = 0;
3839 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3841 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3842 desc.Texture3D.MipSlice = UINT(level);
3843 desc.Texture3D.WSize = UINT(m_depth);
3845 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3846 desc.Texture2D.MipSlice = UINT(level);
3850 ID3D11UnorderedAccessView *uav =
nullptr;
3851 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3853 qWarning(
"Failed to create UAV: %s",
3854 qPrintable(QSystemError::windowsComString(hr)));
3858 perLevelViews[level] = uav;
3863 AddressMode u, AddressMode v, AddressMode w)
3878 samplerState->Release();
3879 samplerState =
nullptr;
3883 rhiD->unregisterResource(
this);
3886static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3888 if (minFilter == QRhiSampler::Nearest) {
3889 if (magFilter == QRhiSampler::Nearest) {
3890 if (mipFilter == QRhiSampler::Linear)
3891 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3893 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3895 if (mipFilter == QRhiSampler::Linear)
3896 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3898 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3901 if (magFilter == QRhiSampler::Nearest) {
3902 if (mipFilter == QRhiSampler::Linear)
3903 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3905 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3907 if (mipFilter == QRhiSampler::Linear)
3908 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3910 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3915 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3921 case QRhiSampler::Repeat:
3922 return D3D11_TEXTURE_ADDRESS_WRAP;
3923 case QRhiSampler::ClampToEdge:
3924 return D3D11_TEXTURE_ADDRESS_CLAMP;
3925 case QRhiSampler::Mirror:
3926 return D3D11_TEXTURE_ADDRESS_MIRROR;
3929 return D3D11_TEXTURE_ADDRESS_CLAMP;
3936 case QRhiSampler::Never:
3937 return D3D11_COMPARISON_NEVER;
3938 case QRhiSampler::Less:
3939 return D3D11_COMPARISON_LESS;
3940 case QRhiSampler::Equal:
3941 return D3D11_COMPARISON_EQUAL;
3942 case QRhiSampler::LessOrEqual:
3943 return D3D11_COMPARISON_LESS_EQUAL;
3944 case QRhiSampler::Greater:
3945 return D3D11_COMPARISON_GREATER;
3946 case QRhiSampler::NotEqual:
3947 return D3D11_COMPARISON_NOT_EQUAL;
3948 case QRhiSampler::GreaterOrEqual:
3949 return D3D11_COMPARISON_GREATER_EQUAL;
3950 case QRhiSampler::Always:
3951 return D3D11_COMPARISON_ALWAYS;
3954 return D3D11_COMPARISON_NEVER;
3963 D3D11_SAMPLER_DESC desc = {};
3964 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3965 if (m_compareOp != Never)
3966 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3967 desc.AddressU = toD3DAddressMode(m_addressU);
3968 desc.AddressV = toD3DAddressMode(m_addressV);
3969 desc.AddressW = toD3DAddressMode(m_addressW);
3970 desc.MaxAnisotropy = 1.0f;
3971 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3972 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
3975 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
3977 qWarning(
"Failed to create sampler state: %s",
3978 qPrintable(QSystemError::windowsComString(hr)));
3983 rhiD->registerResource(
this);
4002 rhiD->unregisterResource(
this);
4015 rhiD->registerResource(rpD,
false);
4052 return d.sampleCount;
4056 const QRhiTextureRenderTargetDescription &desc,
4074 if (!rtv[0] && !dsv)
4093 rhiD->unregisterResource(
this);
4100 rhiD->registerResource(rpD,
false);
4109 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4110 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4111 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4115 d.colorAttCount = 0;
4117 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4118 d.colorAttCount += 1;
4119 const QRhiColorAttachment &colorAtt(*it);
4120 QRhiTexture *texture = colorAtt.texture();
4121 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4122 Q_ASSERT(texture || rb);
4125 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4126 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4127 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4128 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4129 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4130 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4131 rtvDesc.Texture2DArray.ArraySize = 1;
4132 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4133 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4134 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4135 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4136 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4137 rtvDesc.Texture1DArray.ArraySize = 1;
4139 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4140 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4142 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4143 if (texD->sampleDesc.Count > 1) {
4144 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4145 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4146 rtvDesc.Texture2DMSArray.ArraySize = 1;
4148 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4149 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4150 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4151 rtvDesc.Texture2DArray.ArraySize = 1;
4153 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4154 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4155 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4156 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4157 rtvDesc.Texture3D.WSize = 1;
4159 if (texD->sampleDesc.Count > 1) {
4160 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4162 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4163 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4166 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4168 qWarning(
"Failed to create rtv: %s",
4169 qPrintable(QSystemError::windowsComString(hr)));
4173 if (attIndex == 0) {
4174 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4175 d.sampleCount =
int(texD->sampleDesc.Count);
4180 rtv[attIndex] = rbD->rtv;
4181 if (attIndex == 0) {
4182 d.pixelSize = rbD->pixelSize();
4183 d.sampleCount =
int(rbD->sampleDesc.Count);
4189 if (hasDepthStencil) {
4190 if (m_desc.depthTexture()) {
4193 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4194 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4195 dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4196 : D3D11_DSV_DIMENSION_TEXTURE2D;
4197 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4198 if (depthTexD->sampleDesc.Count > 1) {
4199 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4200 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4201 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4202 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4204 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4205 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4208 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4209 if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4210 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4211 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4213 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4214 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4218 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4220 qWarning(
"Failed to create dsv: %s",
4221 qPrintable(QSystemError::windowsComString(hr)));
4224 if (d.colorAttCount == 0) {
4225 d.pixelSize = depthTexD->pixelSize();
4226 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4231 dsv = depthRbD->dsv;
4232 if (d.colorAttCount == 0) {
4233 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4234 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4242 for (
int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
4243 d.rtv[i] = i < d.colorAttCount ? rtv[i] :
nullptr;
4246 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4248 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4250 rhiD->registerResource(
this);
4256 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4269 return d.sampleCount;
4284 sortedBindings.clear();
4285 boundResourceData.clear();
4289 rhiD->unregisterResource(
this);
4294 if (!sortedBindings.isEmpty())
4298 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4301 rhiD->updateLayoutDesc(
this);
4303 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4304 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4306 boundResourceData.resize(sortedBindings.count());
4308 for (BoundResourceData &bd : boundResourceData)
4309 memset(&bd, 0,
sizeof(BoundResourceData));
4312 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4313 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4314 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4315 hasDynamicOffset =
true;
4321 rhiD->registerResource(
this,
false);
4327 sortedBindings.clear();
4328 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4329 if (!flags.testFlag(BindingsAreSorted))
4330 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4332 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4333 for (BoundResourceData &bd : boundResourceData)
4334 memset(&bd, 0,
sizeof(BoundResourceData));
4353 s.shader->Release();
4356 s.nativeResourceBindingMap.clear();
4368 blendState->Release();
4369 blendState =
nullptr;
4373 inputLayout->Release();
4374 inputLayout =
nullptr;
4378 rastState->Release();
4379 rastState =
nullptr;
4382 releasePipelineShader(vs);
4383 releasePipelineShader(hs);
4384 releasePipelineShader(ds);
4385 releasePipelineShader(gs);
4386 releasePipelineShader(fs);
4390 rhiD->unregisterResource(
this);
4396 case QRhiGraphicsPipeline::None:
4397 return D3D11_CULL_NONE;
4398 case QRhiGraphicsPipeline::Front:
4399 return D3D11_CULL_FRONT;
4400 case QRhiGraphicsPipeline::Back:
4401 return D3D11_CULL_BACK;
4404 return D3D11_CULL_NONE;
4411 case QRhiGraphicsPipeline::Fill:
4412 return D3D11_FILL_SOLID;
4413 case QRhiGraphicsPipeline::Line:
4414 return D3D11_FILL_WIREFRAME;
4417 return D3D11_FILL_SOLID;
4424 case QRhiGraphicsPipeline::Never:
4425 return D3D11_COMPARISON_NEVER;
4426 case QRhiGraphicsPipeline::Less:
4427 return D3D11_COMPARISON_LESS;
4428 case QRhiGraphicsPipeline::Equal:
4429 return D3D11_COMPARISON_EQUAL;
4430 case QRhiGraphicsPipeline::LessOrEqual:
4431 return D3D11_COMPARISON_LESS_EQUAL;
4432 case QRhiGraphicsPipeline::Greater:
4433 return D3D11_COMPARISON_GREATER;
4434 case QRhiGraphicsPipeline::NotEqual:
4435 return D3D11_COMPARISON_NOT_EQUAL;
4436 case QRhiGraphicsPipeline::GreaterOrEqual:
4437 return D3D11_COMPARISON_GREATER_EQUAL;
4438 case QRhiGraphicsPipeline::Always:
4439 return D3D11_COMPARISON_ALWAYS;
4442 return D3D11_COMPARISON_ALWAYS;
4449 case QRhiGraphicsPipeline::StencilZero:
4450 return D3D11_STENCIL_OP_ZERO;
4451 case QRhiGraphicsPipeline::Keep:
4452 return D3D11_STENCIL_OP_KEEP;
4453 case QRhiGraphicsPipeline::Replace:
4454 return D3D11_STENCIL_OP_REPLACE;
4455 case QRhiGraphicsPipeline::IncrementAndClamp:
4456 return D3D11_STENCIL_OP_INCR_SAT;
4457 case QRhiGraphicsPipeline::DecrementAndClamp:
4458 return D3D11_STENCIL_OP_DECR_SAT;
4459 case QRhiGraphicsPipeline::Invert:
4460 return D3D11_STENCIL_OP_INVERT;
4461 case QRhiGraphicsPipeline::IncrementAndWrap:
4462 return D3D11_STENCIL_OP_INCR;
4463 case QRhiGraphicsPipeline::DecrementAndWrap:
4464 return D3D11_STENCIL_OP_DECR;
4467 return D3D11_STENCIL_OP_KEEP;
4474 case QRhiVertexInputAttribute::Float4:
4475 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4476 case QRhiVertexInputAttribute::Float3:
4477 return DXGI_FORMAT_R32G32B32_FLOAT;
4478 case QRhiVertexInputAttribute::Float2:
4479 return DXGI_FORMAT_R32G32_FLOAT;
4480 case QRhiVertexInputAttribute::Float:
4481 return DXGI_FORMAT_R32_FLOAT;
4482 case QRhiVertexInputAttribute::UNormByte4:
4483 return DXGI_FORMAT_R8G8B8A8_UNORM;
4484 case QRhiVertexInputAttribute::UNormByte2:
4485 return DXGI_FORMAT_R8G8_UNORM;
4486 case QRhiVertexInputAttribute::UNormByte:
4487 return DXGI_FORMAT_R8_UNORM;
4488 case QRhiVertexInputAttribute::UInt4:
4489 return DXGI_FORMAT_R32G32B32A32_UINT;
4490 case QRhiVertexInputAttribute::UInt3:
4491 return DXGI_FORMAT_R32G32B32_UINT;
4492 case QRhiVertexInputAttribute::UInt2:
4493 return DXGI_FORMAT_R32G32_UINT;
4494 case QRhiVertexInputAttribute::UInt:
4495 return DXGI_FORMAT_R32_UINT;
4496 case QRhiVertexInputAttribute::SInt4:
4497 return DXGI_FORMAT_R32G32B32A32_SINT;
4498 case QRhiVertexInputAttribute::SInt3:
4499 return DXGI_FORMAT_R32G32B32_SINT;
4500 case QRhiVertexInputAttribute::SInt2:
4501 return DXGI_FORMAT_R32G32_SINT;
4502 case QRhiVertexInputAttribute::SInt:
4503 return DXGI_FORMAT_R32_SINT;
4504 case QRhiVertexInputAttribute::Half4:
4506 case QRhiVertexInputAttribute::Half3:
4507 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4508 case QRhiVertexInputAttribute::Half2:
4509 return DXGI_FORMAT_R16G16_FLOAT;
4510 case QRhiVertexInputAttribute::Half:
4511 return DXGI_FORMAT_R16_FLOAT;
4512 case QRhiVertexInputAttribute::UShort4:
4514 case QRhiVertexInputAttribute::UShort3:
4515 return DXGI_FORMAT_R16G16B16A16_UINT;
4516 case QRhiVertexInputAttribute::UShort2:
4517 return DXGI_FORMAT_R16G16_UINT;
4518 case QRhiVertexInputAttribute::UShort:
4519 return DXGI_FORMAT_R16_UINT;
4520 case QRhiVertexInputAttribute::SShort4:
4522 case QRhiVertexInputAttribute::SShort3:
4523 return DXGI_FORMAT_R16G16B16A16_SINT;
4524 case QRhiVertexInputAttribute::SShort2:
4525 return DXGI_FORMAT_R16G16_SINT;
4526 case QRhiVertexInputAttribute::SShort:
4527 return DXGI_FORMAT_R16_SINT;
4530 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4537 case QRhiGraphicsPipeline::Triangles:
4538 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4539 case QRhiGraphicsPipeline::TriangleStrip:
4540 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4541 case QRhiGraphicsPipeline::Lines:
4542 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4543 case QRhiGraphicsPipeline::LineStrip:
4544 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4545 case QRhiGraphicsPipeline::Points:
4546 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4547 case QRhiGraphicsPipeline::Patches:
4548 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4549 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4552 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4559 if (c.testFlag(QRhiGraphicsPipeline::R))
4560 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4561 if (c.testFlag(QRhiGraphicsPipeline::G))
4562 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4563 if (c.testFlag(QRhiGraphicsPipeline::B))
4564 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4565 if (c.testFlag(QRhiGraphicsPipeline::A))
4566 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4579 case QRhiGraphicsPipeline::Zero:
4580 return D3D11_BLEND_ZERO;
4581 case QRhiGraphicsPipeline::One:
4582 return D3D11_BLEND_ONE;
4583 case QRhiGraphicsPipeline::SrcColor:
4584 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4585 case QRhiGraphicsPipeline::OneMinusSrcColor:
4586 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4587 case QRhiGraphicsPipeline::DstColor:
4588 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4589 case QRhiGraphicsPipeline::OneMinusDstColor:
4590 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4591 case QRhiGraphicsPipeline::SrcAlpha:
4592 return D3D11_BLEND_SRC_ALPHA;
4593 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4594 return D3D11_BLEND_INV_SRC_ALPHA;
4595 case QRhiGraphicsPipeline::DstAlpha:
4596 return D3D11_BLEND_DEST_ALPHA;
4597 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4598 return D3D11_BLEND_INV_DEST_ALPHA;
4599 case QRhiGraphicsPipeline::ConstantColor:
4600 case QRhiGraphicsPipeline::ConstantAlpha:
4601 return D3D11_BLEND_BLEND_FACTOR;
4602 case QRhiGraphicsPipeline::OneMinusConstantColor:
4603 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4604 return D3D11_BLEND_INV_BLEND_FACTOR;
4605 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4606 return D3D11_BLEND_SRC_ALPHA_SAT;
4607 case QRhiGraphicsPipeline::Src1Color:
4608 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4609 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4610 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4611 case QRhiGraphicsPipeline::Src1Alpha:
4612 return D3D11_BLEND_SRC1_ALPHA;
4613 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4614 return D3D11_BLEND_INV_SRC1_ALPHA;
4617 return D3D11_BLEND_ZERO;
4624 case QRhiGraphicsPipeline::Add:
4625 return D3D11_BLEND_OP_ADD;
4626 case QRhiGraphicsPipeline::Subtract:
4627 return D3D11_BLEND_OP_SUBTRACT;
4628 case QRhiGraphicsPipeline::ReverseSubtract:
4629 return D3D11_BLEND_OP_REV_SUBTRACT;
4630 case QRhiGraphicsPipeline::Min:
4631 return D3D11_BLEND_OP_MIN;
4632 case QRhiGraphicsPipeline::Max:
4633 return D3D11_BLEND_OP_MAX;
4636 return D3D11_BLEND_OP_ADD;
4643 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4644 keyBuilder.addData(source);
4645 return keyBuilder.result().toHex();
4648QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4649 QString *error, QShaderKey *usedShaderKey)
4651 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4652 QShaderCode dxbc = shader.shader(key);
4653 if (!dxbc.shader().isEmpty()) {
4655 *usedShaderKey = key;
4656 return dxbc.shader();
4659 key = { QShader::HlslShader, 50, shaderVariant };
4660 QShaderCode hlslSource = shader.shader(key);
4661 if (hlslSource.shader().isEmpty()) {
4662 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4663 return QByteArray();
4667 *usedShaderKey = key;
4670 switch (shader.stage()) {
4671 case QShader::VertexStage:
4674 case QShader::TessellationControlStage:
4677 case QShader::TessellationEvaluationStage:
4680 case QShader::GeometryStage:
4683 case QShader::FragmentStage:
4686 case QShader::ComputeStage:
4691 return QByteArray();
4695 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4696 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4697 cacheKey.target = target;
4698 cacheKey.entryPoint = hlslSource.entryPoint();
4699 cacheKey.compileFlags = flags;
4700 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4701 if (cacheIt != m_bytecodeCache.constEnd())
4702 return cacheIt.value();
4705 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4706 if (d3dCompile ==
nullptr) {
4707 qWarning(
"Unable to resolve function D3DCompile()");
4708 return QByteArray();
4711 ID3DBlob *bytecode =
nullptr;
4712 ID3DBlob *errors =
nullptr;
4713 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4714 nullptr,
nullptr,
nullptr,
4715 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4716 if (FAILED(hr) || !bytecode) {
4717 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4719 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4720 int(errors->GetBufferSize()));
4723 return QByteArray();
4727 result.resize(
int(bytecode->GetBufferSize()));
4728 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4729 bytecode->Release();
4731 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4732 m_bytecodeCache.insert(cacheKey, result);
4743 rhiD->pipelineCreationStart();
4744 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4747 D3D11_RASTERIZER_DESC rastDesc = {};
4748 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4749 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4750 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4751 rastDesc.DepthBias = m_depthBias;
4752 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4753 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4754 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4755 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4756 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4758 qWarning(
"Failed to create rasterizer state: %s",
4759 qPrintable(QSystemError::windowsComString(hr)));
4763 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4764 dsDesc.DepthEnable = m_depthTest;
4765 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4766 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4767 dsDesc.StencilEnable = m_stencilTest;
4768 if (m_stencilTest) {
4769 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4770 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4771 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4772 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4773 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4774 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4775 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4776 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4777 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4778 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4780 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4782 qWarning(
"Failed to create depth-stencil state: %s",
4783 qPrintable(QSystemError::windowsComString(hr)));
4787 D3D11_BLEND_DESC blendDesc = {};
4788 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4789 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4790 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4791 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4792 blend.BlendEnable = b.enable;
4793 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4794 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4795 blend.BlendOp = toD3DBlendOp(b.opColor);
4796 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4797 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4798 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4799 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4800 blendDesc.RenderTarget[i] = blend;
4802 if (m_targetBlends.isEmpty()) {
4803 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4804 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4805 blendDesc.RenderTarget[0] = blend;
4807 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4809 qWarning(
"Failed to create blend state: %s",
4810 qPrintable(QSystemError::windowsComString(hr)));
4814 QByteArray vsByteCode;
4815 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4816 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4817 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4818 switch (shaderStage.type()) {
4819 case QRhiShaderStage::Vertex:
4820 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4821 vs.shader->AddRef();
4822 vsByteCode = cacheIt->bytecode;
4823 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4825 case QRhiShaderStage::TessellationControl:
4826 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4827 hs.shader->AddRef();
4828 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4830 case QRhiShaderStage::TessellationEvaluation:
4831 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4832 ds.shader->AddRef();
4833 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4835 case QRhiShaderStage::Geometry:
4836 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4837 gs.shader->AddRef();
4838 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4840 case QRhiShaderStage::Fragment:
4841 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4842 fs.shader->AddRef();
4843 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4850 QShaderKey shaderKey;
4851 UINT compileFlags = 0;
4852 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4853 compileFlags |= D3DCOMPILE_DEBUG;
4855 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4856 &error, &shaderKey);
4857 if (bytecode.isEmpty()) {
4858 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4862 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4864 rhiD->clearShaderCache();
4867 switch (shaderStage.type()) {
4868 case QRhiShaderStage::Vertex:
4869 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4871 qWarning(
"Failed to create vertex shader: %s",
4872 qPrintable(QSystemError::windowsComString(hr)));
4875 vsByteCode = bytecode;
4876 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4877 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4878 vs.shader->AddRef();
4880 case QRhiShaderStage::TessellationControl:
4881 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4883 qWarning(
"Failed to create hull shader: %s",
4884 qPrintable(QSystemError::windowsComString(hr)));
4887 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4888 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4889 hs.shader->AddRef();
4891 case QRhiShaderStage::TessellationEvaluation:
4892 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4894 qWarning(
"Failed to create domain shader: %s",
4895 qPrintable(QSystemError::windowsComString(hr)));
4898 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4899 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4900 ds.shader->AddRef();
4902 case QRhiShaderStage::Geometry:
4903 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4905 qWarning(
"Failed to create geometry shader: %s",
4906 qPrintable(QSystemError::windowsComString(hr)));
4909 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4910 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4911 gs.shader->AddRef();
4913 case QRhiShaderStage::Fragment:
4914 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4916 qWarning(
"Failed to create pixel shader: %s",
4917 qPrintable(QSystemError::windowsComString(hr)));
4920 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4921 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4922 fs.shader->AddRef();
4930 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4932 if (!vsByteCode.isEmpty()) {
4933 QByteArrayList matrixSliceSemantics;
4934 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4935 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4938 D3D11_INPUT_ELEMENT_DESC desc = {};
4943 const int matrixSlice = it->matrixSlice();
4944 if (matrixSlice < 0) {
4945 desc.SemanticName =
"TEXCOORD";
4946 desc.SemanticIndex = UINT(it->location());
4950 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4951 matrixSliceSemantics.append(sem);
4952 desc.SemanticName = matrixSliceSemantics.last().constData();
4953 desc.SemanticIndex = UINT(matrixSlice);
4955 desc.Format = toD3DAttributeFormat(it->format());
4956 desc.InputSlot = UINT(it->binding());
4957 desc.AlignedByteOffset = it->offset();
4958 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4959 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4960 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4961 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4963 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4965 inputDescs.append(desc);
4967 if (!inputDescs.isEmpty()) {
4968 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
4969 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
4971 qWarning(
"Failed to create input layout: %s",
4972 qPrintable(QSystemError::windowsComString(hr)));
4978 rhiD->pipelineCreationEnd();
4980 rhiD->registerResource(
this);
4999 cs.shader->Release();
5000 cs.shader =
nullptr;
5001 cs.nativeResourceBindingMap.clear();
5005 rhiD->unregisterResource(
this);
5014 rhiD->pipelineCreationStart();
5016 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5017 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5018 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5019 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5022 QShaderKey shaderKey;
5023 UINT compileFlags = 0;
5024 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5025 compileFlags |= D3DCOMPILE_DEBUG;
5027 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5028 &error, &shaderKey);
5029 if (bytecode.isEmpty()) {
5030 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5034 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5036 qWarning(
"Failed to create compute shader: %s",
5037 qPrintable(QSystemError::windowsComString(hr)));
5041 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5043 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5046 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5049 cs.shader->AddRef();
5051 rhiD->pipelineCreationEnd();
5053 rhiD->registerResource(
this);
5078 D3D11_QUERY_DESC queryDesc = {};
5080 if (!disjointQuery[i]) {
5081 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5082 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5084 qWarning(
"Failed to create timestamp disjoint query: %s",
5085 qPrintable(QSystemError::windowsComString(hr)));
5089 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5090 for (
int j = 0; j < 2; ++j) {
5091 const int idx = 2 * i + j;
5093 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5095 qWarning(
"Failed to create timestamp query: %s",
5096 qPrintable(QSystemError::windowsComString(hr)));
5109 if (disjointQuery[i]) {
5110 disjointQuery[i]->Release();
5111 disjointQuery[i] =
nullptr;
5113 for (
int j = 0; j < 2; ++j) {
5116 query[idx]->Release();
5117 query[idx] =
nullptr;
5125 bool result =
false;
5129 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5130 ID3D11Query *tsStart = query[pairIndex * 2];
5131 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5132 quint64 timestamps[2];
5133 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5136 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5137 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5138 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5141 if (!dj.Disjoint && dj.Frequency) {
5142 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5143 *elapsedSec = elapsedMs / 1000.0;
5146 active[pairIndex] =
false;
5155 backBufferTex =
nullptr;
5156 backBufferRtv =
nullptr;
5158 msaaTex[i] =
nullptr;
5159 msaaRtv[i] =
nullptr;
5170 if (backBufferRtv) {
5171 backBufferRtv->Release();
5172 backBufferRtv =
nullptr;
5174 if (backBufferRtvRight) {
5175 backBufferRtvRight->Release();
5176 backBufferRtvRight =
nullptr;
5178 if (backBufferTex) {
5179 backBufferTex->Release();
5180 backBufferTex =
nullptr;
5184 msaaRtv[i]->Release();
5185 msaaRtv[i] =
nullptr;
5188 msaaTex[i]->Release();
5189 msaaTex[i] =
nullptr;
5201 timestamps.destroy();
5203 swapChain->Release();
5204 swapChain =
nullptr;
5207 dcompVisual->Release();
5208 dcompVisual =
nullptr;
5212 dcompTarget->Release();
5213 dcompTarget =
nullptr;
5216 if (frameLatencyWaitableObject) {
5217 CloseHandle(frameLatencyWaitableObject);
5218 frameLatencyWaitableObject =
nullptr;
5221 QDxgiVSyncService::instance()->unregisterWindow(window);
5225 rhiD->unregisterResource(
this);
5228 rhiD->context->Flush();
5244 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5250 return m_window->size() * m_window->devicePixelRatio();
5259 qWarning(
"Attempted to call isFormatSupported() without a window set");
5264 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5265 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5276 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5285 rhiD->registerResource(rpD,
false);
5290 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5292 D3D11_TEXTURE2D_DESC desc = {};
5293 desc.Width = UINT(size.width());
5294 desc.Height = UINT(size.height());
5297 desc.Format = format;
5298 desc.SampleDesc = sampleDesc;
5299 desc.Usage = D3D11_USAGE_DEFAULT;
5300 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5303 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5305 qWarning(
"Failed to create color buffer texture: %s",
5306 qPrintable(QSystemError::windowsComString(hr)));
5310 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5311 rtvDesc.Format = format;
5312 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5313 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5315 qWarning(
"Failed to create color buffer rtv: %s",
5316 qPrintable(QSystemError::windowsComString(hr)));
5330 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5331 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5332 return dcompDevice ?
true :
false;
5344 const bool needsRegistration = !window || window != m_window;
5345 const bool stereo = m_window->format().stereo();
5348 if (window && window != m_window)
5352 m_currentPixelSize = surfacePixelSize();
5353 pixelSize = m_currentPixelSize;
5355 if (pixelSize.isEmpty())
5358 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5363 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5366 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5368 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5369 qPrintable(QSystemError::windowsComString(hr)));
5372 if (dcompTarget && !dcompVisual) {
5373 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5375 qWarning(
"Failed to create DirectComposition visual: %s",
5376 qPrintable(QSystemError::windowsComString(hr)));
5381 if (
window->requestedFormat().alphaBufferSize() <= 0)
5382 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5383 "This may lead to problems.");
5386 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5393 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5394 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5398 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5399 && swapInterval != 0
5400 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5402 if (useFrameLatencyWaitableObject) {
5404 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5408 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5409 colorFormat = DEFAULT_FORMAT;
5410 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5412 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5413 if (m_format != SDR) {
5414 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5417 case HDRExtendedSrgbLinear:
5418 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5419 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5420 srgbAdjustedColorFormat = colorFormat;
5423 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5424 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5425 srgbAdjustedColorFormat = colorFormat;
5434 qWarning(
"The output associated with the window is not HDR capable "
5435 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5445 DXGI_SWAP_CHAIN_DESC1 desc = {};
5446 desc.Width = UINT(pixelSize.width());
5447 desc.Height = UINT(pixelSize.height());
5448 desc.Format = colorFormat;
5449 desc.SampleDesc.Count = 1;
5450 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5452 desc.Flags = swapChainFlags;
5453 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5454 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5455 desc.Stereo = stereo;
5461 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5466 desc.Scaling = DXGI_SCALING_STRETCH;
5469 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5470 IDXGISwapChain1 *sc1;
5473 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5475 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5480 if (FAILED(hr) && m_format != SDR) {
5481 colorFormat = DEFAULT_FORMAT;
5482 desc.Format = DEFAULT_FORMAT;
5484 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5486 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5489 if (SUCCEEDED(hr)) {
5491 IDXGISwapChain3 *sc3 =
nullptr;
5492 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5493 if (m_format != SDR) {
5494 hr = sc3->SetColorSpace1(hdrColorSpace);
5496 qWarning(
"Failed to set color space on swapchain: %s",
5497 qPrintable(QSystemError::windowsComString(hr)));
5499 if (useFrameLatencyWaitableObject) {
5500 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5501 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5505 if (m_format != SDR)
5506 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5507 if (useFrameLatencyWaitableObject) {
5508 IDXGISwapChain2 *sc2 =
nullptr;
5509 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5510 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5511 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5514 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5519 hr = dcompVisual->SetContent(sc1);
5520 if (SUCCEEDED(hr)) {
5521 hr = dcompTarget->SetRoot(dcompVisual);
5523 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5524 qPrintable(QSystemError::windowsComString(hr)));
5527 qWarning(
"Failed to set content for Direct Composition visual: %s",
5528 qPrintable(QSystemError::windowsComString(hr)));
5532 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5535 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5536 qWarning(
"Device loss detected during swapchain creation");
5539 }
else if (FAILED(hr)) {
5540 qWarning(
"Failed to create D3D11 swapchain: %s"
5541 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5542 qPrintable(QSystemError::windowsComString(hr)),
5543 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5544 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5550 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5551 colorFormat, swapChainFlags);
5552 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5553 qWarning(
"Device loss detected in ResizeBuffers()");
5556 }
else if (FAILED(hr)) {
5557 qWarning(
"Failed to resize D3D11 swapchain: %s",
5558 qPrintable(QSystemError::windowsComString(hr)));
5577 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5579 qWarning(
"Failed to query swapchain backbuffer: %s",
5580 qPrintable(QSystemError::windowsComString(hr)));
5583 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5584 rtvDesc.Format = srgbAdjustedColorFormat;
5585 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5586 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5588 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5589 qPrintable(QSystemError::windowsComString(hr)));
5595 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5596 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5597 rtvDesc.Texture2DArray.ArraySize = 1;
5598 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5600 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5601 qPrintable(QSystemError::windowsComString(hr)));
5608 if (sampleDesc.Count > 1) {
5609 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5614 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5615 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5616 m_depthStencil->sampleCount(), m_sampleCount);
5618 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5619 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5620 m_depthStencil->setPixelSize(pixelSize);
5621 if (!m_depthStencil->create())
5622 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5623 pixelSize.width(), pixelSize.height());
5625 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5626 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5627 pixelSize.width(), pixelSize.height());
5634 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5636 rt.setRenderPassDescriptor(m_renderPassDesc);
5638 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5639 rtD->d.pixelSize = pixelSize;
5640 rtD->d.dpr =
float(
window->devicePixelRatio());
5641 rtD->d.sampleCount =
int(sampleDesc.Count);
5642 rtD->d.colorAttCount = 1;
5643 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
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.colorAttCount = 1;
5652 rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
5653 rtD->d.rtv[0] = backBufferRtvRight;
5654 rtD->d.dsv =
ds ?
ds->dsv :
nullptr;
5657 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5658 timestamps.prepare(rhiD);
5662 QDxgiVSyncService::instance()->registerWindow(window);
5664 if (needsRegistration)
5665 rhiD->registerResource(
this);
5673 if (dsv != data->dsv) {
5678 ret |= rtv[i] != data->rtv[i];
5679 rtv[i] = data->rtv[i];
5682 ret |= rtv[i] !=
nullptr;
5685 for (
int i = 0; i < count; i++) {
5686 ret |= uav[i] != uavs[i];
5690 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
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
bool isYUpInFramebuffer() const override
int resourceLimit(QRhi::ResourceLimit limit) const override
void beginExternal(QRhiCommandBuffer *cb) override
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void setPipelineCacheData(const QByteArray &data) override
void executeCommandBuffer(QD3D11CommandBuffer *cbD)
void debugMarkEnd(QRhiCommandBuffer *cb) override
void releaseCachedResources() override
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
bool importedDeviceAndContext
void resetShaderResources(QD3D11RenderTargetData *rtD, RenderTargetUavUpdateState &rtUavState)
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
bool supportsAllowTearing
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
void endExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
QRhiShadingRateMap * createShadingRateMap() override
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
bool useLegacySwapchainModel
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
bool makeThreadLocalNativeContextCurrent() override
bool create(QRhi::Flags flags) override
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
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)
QD3D11RenderTargetData * prevRtD
static const int MAX_DYNAMIC_OFFSET_COUNT
static const int MAX_VERTEX_BUFFER_BINDING_COUNT
int retainResourceBatches(const QD3D11ShaderResourceBindings::ResourceBatches &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ComputePipeline(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11GraphicsPipeline(QRhiImplementation *rhi)
~QD3D11GraphicsPipeline()
bool create() override
Creates the corresponding native graphics resources.
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags, QRhiTexture::Format backingFormatHint)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool create() override
Creates the corresponding native graphics resources.
QRhiTexture::Format backingFormat() const override
QD3D11RenderPassDescriptor(QRhiImplementation *rhi)
~QD3D11RenderPassDescriptor()
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool isCompatible(const QRhiRenderPassDescriptor *other) const override
QVector< quint32 > serializedFormat() const override
static const int MAX_COLOR_ATTACHMENTS
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
QD3D11GraphicsPipeline * lastUsedGraphicsPipeline
bool create() override
Creates the corresponding resource binding set.
~QD3D11ShaderResourceBindings()
void updateResources(UpdateFlags flags) override
QD3D11ComputePipeline * lastUsedComputePipeline
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
int sampleCount() const override
~QD3D11SwapChainRenderTarget()
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
float devicePixelRatio() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QSize pixelSize() const override
bool prepare(QRhiD3D11 *rhiD)
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
bool active[TIMESTAMP_PAIRS]
static const int TIMESTAMP_PAIRS
QRhiSwapChainHdrInfo hdrInfo() override
\variable QRhiSwapChainHdrInfo::limitsType
int lastFrameLatencyWaitSlot
QRhiRenderTarget * currentFrameRenderTarget() override
QD3D11SwapChain(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
QSize surfacePixelSize() override
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
static const int BUFFER_COUNT
bool isFormatSupported(Format f) override
QRhiCommandBuffer * currentFrameCommandBuffer() override
int currentTimestampPairIndex
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
QSize pixelSize() const override
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
float devicePixelRatio() const override
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
~QD3D11TextureRenderTarget()
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
ID3D11UnorderedAccessView * unorderedAccessViewForLevel(int level)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool update(QD3D11RenderTargetData *data, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)