10#include <QtCore/qcryptographichash.h>
11#include <QtCore/private/qsystemerror_p.h>
18using namespace Qt::StringLiterals;
21
22
23
24
25
26
27
28
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
78
79
80
81
82
86
87
88
89
90
91
92
93
94
95
96
97
100
101
102
103
104
105
106
107
110
111
112
113
114
115
116
119
120
121
122
123
124
125
126
129
130
131
132
133
134
137
138
139
140
141
142
145#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
146#define DXGI_ADAPTER_FLAG_SOFTWARE 2
149#ifndef D3D11_1_UAV_SLOT_COUNT
150#define D3D11_1_UAV_SLOT_COUNT 64
153#ifndef D3D11_VS_INPUT_REGISTER_COUNT
154#define D3D11_VS_INPUT_REGISTER_COUNT 32
163 if (importParams->dev && importParams->context) {
164 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
165 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
166 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
171 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
174 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
175 adapterLuid.LowPart = importParams->adapterLuidLow;
176 adapterLuid.HighPart = importParams->adapterLuidHigh;
183 return (v + byteAlign - 1) & ~(byteAlign - 1);
188 IDXGIFactory1 *result =
nullptr;
189 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
191 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
192 qPrintable(QSystemError::windowsComString(hr)));
204 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
206 dxgiFactory = createDXGIFactory2();
214 IDXGIFactory5 *factory5 =
nullptr;
215 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
216 BOOL allowTearing =
false;
217 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
222 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
223 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
231 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
232 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
237 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
241 if (maxFrameLatency == 0)
242 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
244 activeAdapter =
nullptr;
247 IDXGIAdapter1 *adapter;
248 int requestedAdapterIndex = -1;
249 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
250 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
252 if (requestedRhiAdapter)
253 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
256 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
257 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
258 DXGI_ADAPTER_DESC1 desc;
259 adapter->GetDesc1(&desc);
261 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
262 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
264 requestedAdapterIndex = adapterIndex;
270 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
271 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
272 DXGI_ADAPTER_DESC1 desc;
273 adapter->GetDesc1(&desc);
276 requestedAdapterIndex = adapterIndex;
282 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
283 DXGI_ADAPTER_DESC1 desc;
284 adapter->GetDesc1(&desc);
285 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
286 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
292 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
293 activeAdapter = adapter;
294 adapterLuid = desc.AdapterLuid;
296 qCDebug(QRHI_LOG_INFO,
" using this adapter");
301 if (!activeAdapter) {
302 qWarning(
"No adapter");
308 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
309 bool requestFeatureLevels =
false;
311 requestFeatureLevels =
true;
312 requestedFeatureLevels.append(featureLevel);
315 ID3D11DeviceContext *ctx =
nullptr;
316 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
317 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
318 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
320 &dev, &featureLevel, &ctx);
322 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
323 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
324 "Attempting to create D3D11 device without it.");
325 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
326 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
327 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
328 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
330 &dev, &featureLevel, &ctx);
333 qWarning(
"Failed to create D3D11 device and context: %s",
334 qPrintable(QSystemError::windowsComString(hr)));
338 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
341 qWarning(
"ID3D11DeviceContext1 not supported");
347 ID3D11VertexShader *testShader =
nullptr;
348 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
349 testShader->Release();
351 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
352 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
353 qCDebug(QRHI_LOG_INFO,
"%s", msg);
359 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
360 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
364 if (!features.ConstantBufferOffsetting) {
365 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
366 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
367 qCDebug(QRHI_LOG_INFO,
"%s", msg);
373 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
374 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
375 qCDebug(QRHI_LOG_INFO,
"%s", msg);
381 Q_ASSERT(dev && context);
382 featureLevel = dev->GetFeatureLevel();
383 IDXGIDevice *dxgiDev =
nullptr;
384 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
385 IDXGIAdapter *adapter =
nullptr;
386 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
387 IDXGIAdapter1 *adapter1 =
nullptr;
388 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
389 DXGI_ADAPTER_DESC1 desc;
390 adapter1->GetDesc1(&desc);
391 adapterLuid = desc.AdapterLuid;
393 activeAdapter = adapter1;
399 if (!activeAdapter) {
400 qWarning(
"Failed to query adapter from imported device");
403 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
406 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
408 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
409 annotations =
nullptr;
413 nativeHandlesStruct.dev = dev;
414 nativeHandlesStruct.context = context;
415 nativeHandlesStruct.featureLevel = featureLevel;
416 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
417 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
424 for (
const Shader &s : std::as_const(m_shaderCache))
427 m_shaderCache.clear();
436 if (ofr.tsDisjointQuery) {
437 ofr.tsDisjointQuery->Release();
438 ofr.tsDisjointQuery =
nullptr;
440 for (
int i = 0; i < 2; ++i) {
441 if (ofr.tsQueries[i]) {
442 ofr.tsQueries[i]->Release();
443 ofr.tsQueries[i] =
nullptr;
448 annotations->Release();
449 annotations =
nullptr;
464 dcompDevice->Release();
465 dcompDevice =
nullptr;
469 activeAdapter->Release();
470 activeAdapter =
nullptr;
474 dxgiFactory->Release();
475 dxgiFactory =
nullptr;
478 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
488 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
489 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
494QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
496 LUID requestedLuid = {};
498 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
499 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
500 if (adapterLuid.LowPart || adapterLuid.HighPart)
501 requestedLuid = adapterLuid;
504 IDXGIFactory1 *dxgi = createDXGIFactory2();
508 QRhi::AdapterList list;
509 IDXGIAdapter1 *adapter;
510 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
511 DXGI_ADAPTER_DESC1 desc;
512 adapter->GetDesc1(&desc);
514 if (requestedLuid.LowPart || requestedLuid.HighPart) {
515 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
516 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
521 QD3D11Adapter *a =
new QD3D11Adapter;
522 a->luid = desc.AdapterLuid;
523 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
538 return { 1, 2, 4, 8 };
543 Q_UNUSED(sampleCount);
544 return { QSize(1, 1) };
549 DXGI_SAMPLE_DESC desc;
553 const int s = effectiveSampleCount(sampleCount);
555 desc.Count = UINT(s);
557 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
566 return new QD3D11SwapChain(
this);
569QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
571 return new QD3D11Buffer(
this, type, usage, size);
599 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
600 0.0f, 1.0f, 0.0f, 0.0f,
601 0.0f, 0.0f, 0.5f, 0.5f,
602 0.0f, 0.0f, 0.0f, 1.0f);
610 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
619 case QRhi::MultisampleTexture:
621 case QRhi::MultisampleRenderBuffer:
623 case QRhi::DebugMarkers:
624 return annotations !=
nullptr;
625 case QRhi::Timestamps:
627 case QRhi::Instancing:
629 case QRhi::CustomInstanceStepRate:
631 case QRhi::PrimitiveRestart:
633 case QRhi::NonDynamicUniformBuffers:
635 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
637 case QRhi::NPOTTextureRepeat:
639 case QRhi::RedOrAlpha8IsRed:
641 case QRhi::ElementIndexUint:
645 case QRhi::WideLines:
647 case QRhi::VertexShaderPointSize:
649 case QRhi::BaseVertex:
651 case QRhi::BaseInstance:
653 case QRhi::TriangleFanTopology:
655 case QRhi::ReadBackNonUniformBuffer:
657 case QRhi::ReadBackNonBaseMipLevel:
659 case QRhi::TexelFetch:
661 case QRhi::RenderToNonBaseMipLevel:
663 case QRhi::IntAttributes:
665 case QRhi::ScreenSpaceDerivatives:
667 case QRhi::ReadBackAnyTextureFormat:
669 case QRhi::PipelineCacheDataLoadSave:
671 case QRhi::ImageDataStride:
673 case QRhi::RenderBufferImport:
675 case QRhi::ThreeDimensionalTextures:
677 case QRhi::RenderTo3DTextureSlice:
679 case QRhi::TextureArrays:
681 case QRhi::Tessellation:
683 case QRhi::GeometryShader:
685 case QRhi::TextureArrayRange:
687 case QRhi::NonFillPolygonMode:
689 case QRhi::OneDimensionalTextures:
691 case QRhi::OneDimensionalTextureMipmaps:
693 case QRhi::HalfAttributes:
695 case QRhi::RenderToOneDimensionalTexture:
697 case QRhi::ThreeDimensionalTextureMipmaps:
699 case QRhi::MultiView:
701 case QRhi::TextureViewFormat:
703 case QRhi::ResolveDepthStencil:
705 case QRhi::VariableRateShading:
707 case QRhi::VariableRateShadingMap:
708 case QRhi::VariableRateShadingMapWithTexture:
710 case QRhi::PerRenderTargetBlending:
711 case QRhi::SampleVariables:
713 case QRhi::InstanceIndexIncludesBaseInstance:
715 case QRhi::DepthClamp:
717 case QRhi::DrawIndirect:
718 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
719 case QRhi::DrawIndirectMulti:
720 case QRhi::ShaderDrawParameters:
731 case QRhi::TextureSizeMin:
733 case QRhi::TextureSizeMax:
734 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
735 case QRhi::MaxColorAttachments:
737 case QRhi::FramesInFlight:
743 case QRhi::MaxAsyncReadbackFrames:
745 case QRhi::MaxThreadGroupsPerDimension:
746 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
747 case QRhi::MaxThreadsPerThreadGroup:
748 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
749 case QRhi::MaxThreadGroupX:
750 return D3D11_CS_THREAD_GROUP_MAX_X;
751 case QRhi::MaxThreadGroupY:
752 return D3D11_CS_THREAD_GROUP_MAX_Y;
753 case QRhi::MaxThreadGroupZ:
754 return D3D11_CS_THREAD_GROUP_MAX_Z;
755 case QRhi::TextureArraySizeMax:
756 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
757 case QRhi::MaxUniformBufferRange:
759 case QRhi::MaxVertexInputs:
761 case QRhi::MaxVertexOutputs:
762 return D3D11_VS_OUTPUT_REGISTER_COUNT;
763 case QRhi::ShadingRateImageTileSize:
773 return &nativeHandlesStruct;
778 return driverInfoStruct;
784 result.totalPipelineCreationTime = totalPipelineCreationTime();
794void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
802 m_bytecodeCache.clear();
822 if (m_bytecodeCache.isEmpty())
826 memset(&header, 0,
sizeof(header));
827 header.rhiId = pipelineCacheRhiId();
828 header.arch = quint32(
sizeof(
void*));
829 header.count = m_bytecodeCache.count();
831 const size_t dataOffset =
sizeof(header);
833 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
835 QByteArray bytecode = it.value();
837 sizeof(quint32) + key.sourceHash.size()
838 +
sizeof(quint32) + key.target.size()
839 +
sizeof(quint32) + key.entryPoint.size()
841 +
sizeof(quint32) + bytecode.size();
844 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
845 char *p = buf.data() + dataOffset;
846 for (
auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
848 QByteArray bytecode = it.value();
850 quint32 i = key.sourceHash.size();
853 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
854 p += key.sourceHash.size();
856 i = key.target.size();
859 memcpy(p, key.target.constData(), key.target.size());
860 p += key.target.size();
862 i = key.entryPoint.size();
865 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
866 p += key.entryPoint.size();
868 quint32 f = key.compileFlags;
875 memcpy(p, bytecode.constData(), bytecode.size());
876 p += bytecode.size();
878 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
880 header.dataSize = quint32(dataSize);
881 memcpy(buf.data(), &header,
sizeof(header));
892 if (data.size() < qsizetype(headerSize)) {
893 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
896 const size_t dataOffset = headerSize;
898 memcpy(&header, data.constData(), headerSize);
900 const quint32 rhiId = pipelineCacheRhiId();
901 if (header.rhiId != rhiId) {
902 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
903 rhiId, header.rhiId);
906 const quint32 arch = quint32(
sizeof(
void*));
907 if (header.arch != arch) {
908 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
912 if (header.count == 0)
915 if (quint64(data.size()) < quint64(dataOffset) + header.dataSize) {
916 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
920 m_bytecodeCache.clear();
923 for (quint32 i = 0; i < header.count; ++i) {
927 if (!reader.readByteArray(&cacheKey.sourceHash)
928 || !reader.readByteArray(&cacheKey.target)
929 || !reader.readByteArray(&cacheKey.entryPoint)
930 || !reader.readUInt32(&flags)
931 || !reader.readByteArray(&bytecode))
933 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob (truncated or corrupt bytecode data)");
934 m_bytecodeCache.clear();
937 cacheKey.compileFlags = flags;
939 m_bytecodeCache.insert(cacheKey, bytecode);
942 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.count()));
945QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
946 int sampleCount, QRhiRenderBuffer::Flags flags,
947 QRhiTexture::Format backingFormatHint)
949 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
953 const QSize &pixelSize,
int depth,
int arraySize,
954 int sampleCount, QRhiTexture::Flags flags)
956 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
960 QRhiSampler::Filter mipmapMode,
961 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
963 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
967 QRhiTextureRenderTarget::Flags flags)
979 return new QD3D11GraphicsPipeline(
this);
984 return new QD3D11ComputePipeline(
this);
989 return new QD3D11ShaderResourceBindings(
this);
997 const bool pipelineChanged = cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
999 if (pipelineChanged) {
1000 cbD->currentGraphicsPipeline = ps;
1001 cbD->currentComputePipeline =
nullptr;
1002 cbD->currentPipelineGeneration = psD->generation;
1006 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1007 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1008 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1009 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1010 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1011 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1012 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1013 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1014 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1015 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1028 int dynamicOffsetCount,
1029 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1038 srb = gfxPsD->m_shaderResourceBindings;
1040 srb = compPsD->m_shaderResourceBindings;
1045 bool pipelineChanged =
false;
1054 bool srbUpdate =
false;
1055 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1056 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1059 case QRhiShaderResourceBinding::UniformBuffer:
1063 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1064 sanityCheckResourceOwnership(bufD);
1068 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1070 bd.ubuf.id = bufD->m_id;
1071 bd.ubuf.generation = bufD->generation;
1075 case QRhiShaderResourceBinding::SampledTexture:
1076 case QRhiShaderResourceBinding::Texture:
1077 case QRhiShaderResourceBinding::Sampler:
1079 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
1080 if (bd.stex.count != data->count) {
1081 bd.stex.count = data->count;
1084 for (
int elem = 0; elem < data->count; ++elem) {
1090 Q_ASSERT(texD || samplerD);
1091 sanityCheckResourceOwnership(texD);
1092 sanityCheckResourceOwnership(samplerD);
1093 const quint64 texId = texD ? texD->m_id : 0;
1094 const uint texGen = texD ? texD->generation : 0;
1095 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1096 const uint samplerGen = samplerD ? samplerD->generation : 0;
1097 if (texGen != bd.stex.d[elem].texGeneration
1098 || texId != bd.stex.d[elem].texId
1099 || samplerGen != bd.stex.d[elem].samplerGeneration
1100 || samplerId != bd.stex.d[elem].samplerId)
1103 bd.stex.d[elem].texId = texId;
1104 bd.stex.d[elem].texGeneration = texGen;
1105 bd.stex.d[elem].samplerId = samplerId;
1106 bd.stex.d[elem].samplerGeneration = samplerGen;
1111 case QRhiShaderResourceBinding::ImageLoad:
1112 case QRhiShaderResourceBinding::ImageStore:
1113 case QRhiShaderResourceBinding::ImageLoadStore:
1116 sanityCheckResourceOwnership(texD);
1117 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1119 bd.simage.id = texD->m_id;
1120 bd.simage.generation = texD->generation;
1124 case QRhiShaderResourceBinding::BufferLoad:
1125 case QRhiShaderResourceBinding::BufferStore:
1126 case QRhiShaderResourceBinding::BufferLoadStore:
1129 sanityCheckResourceOwnership(bufD);
1130 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1132 bd.sbuf.id = bufD->m_id;
1133 bd.sbuf.generation = bufD->generation;
1143 if (srbUpdate || pipelineChanged) {
1145 memset(resBindMaps, 0,
sizeof(resBindMaps));
1147 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1148 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1149 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1150 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1151 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1153 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1155 updateShaderResourceBindings(srbD, resBindMaps);
1158 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1159 const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
1161 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1163 cbD->currentGraphicsSrb = srb;
1164 cbD->currentComputeSrb =
nullptr;
1166 cbD->currentGraphicsSrb =
nullptr;
1167 cbD->currentComputeSrb = srb;
1169 cbD->currentSrbGeneration = srbD->generation;
1176 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1177 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1180 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1181 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1182 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1183 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1184 const uint binding = uint(dynOfs.first);
1185 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1186 const quint32 offsetInConstants = dynOfs.second / 16;
1188 *p++ = offsetInConstants;
1191 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1199 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1200 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1205 bool needsBindVBuf =
false;
1206 for (
int i = 0; i < bindingCount; ++i) {
1207 const int inputSlot = startBinding + i;
1209 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1210 if (bufD->m_type == QRhiBuffer::Dynamic)
1213 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1214 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1216 needsBindVBuf =
true;
1217 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1218 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1222 if (needsBindVBuf) {
1225 cmd.args.bindVertexBuffers.startSlot = startBinding;
1227 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1231 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1233 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1234 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1235 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1237 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1238 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1239 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1245 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1246 if (ibufD->m_type == QRhiBuffer::Dynamic)
1249 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1250 : DXGI_FORMAT_R32_UINT;
1251 if (cbD->currentIndexBuffer != ibufD->buffer
1252 || cbD->currentIndexOffset != indexOffset
1253 || cbD->currentIndexFormat != dxgiFormat)
1255 cbD->currentIndexBuffer = ibufD->buffer;
1256 cbD->currentIndexOffset = indexOffset;
1257 cbD->currentIndexFormat = dxgiFormat;
1261 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1262 cmd.args.bindIndexBuffer.offset = indexOffset;
1263 cmd.args.bindIndexBuffer.format = dxgiFormat;
1272 Q_ASSERT(cbD->currentTarget);
1273 const QSize outputSize = cbD->currentTarget->pixelSize();
1277 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1282 cmd.args.viewport.x = x;
1283 cmd.args.viewport.y = y;
1284 cmd.args.viewport.w = w;
1285 cmd.args.viewport.h = h;
1286 cmd.args.viewport.d0 = viewport.minDepth();
1287 cmd.args.viewport.d1 = viewport.maxDepth();
1294 Q_ASSERT(cbD->currentTarget);
1295 const QSize outputSize = cbD->currentTarget->pixelSize();
1299 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1304 cmd.args.scissor.x = x;
1305 cmd.args.scissor.y = y;
1306 cmd.args.scissor.w = w;
1307 cmd.args.scissor.h = h;
1318 cmd.args.blendConstants.c[0] =
float(c.redF());
1319 cmd.args.blendConstants.c[1] =
float(c.greenF());
1320 cmd.args.blendConstants.c[2] =
float(c.blueF());
1321 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1332 cmd.args.stencilRef.ref = refValue;
1338 Q_UNUSED(coarsePixelSize);
1342 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1349 cmd.args.draw.vertexCount = vertexCount;
1350 cmd.args.draw.instanceCount = instanceCount;
1351 cmd.args.draw.firstVertex = firstVertex;
1352 cmd.args.draw.firstInstance = firstInstance;
1356 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1363 cmd.args.drawIndexed.indexCount = indexCount;
1364 cmd.args.drawIndexed.instanceCount = instanceCount;
1365 cmd.args.drawIndexed.firstIndex = firstIndex;
1366 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1367 cmd.args.drawIndexed.firstInstance = firstInstance;
1371 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1378 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1379 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1380 cmd.args.drawIndirect.drawCount = drawCount;
1381 cmd.args.drawIndirect.stride = stride;
1386 switch (rt->resourceType()) {
1387 case QRhiResource::SwapChainRenderTarget:
1388 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1389 case QRhiResource::TextureRenderTarget:
1390 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1398 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1405 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1406 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1407 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1408 cmd.args.drawIndexedIndirect.stride = stride;
1413 if (!debugMarkers || !annotations)
1419 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1424 if (!debugMarkers || !annotations)
1434 if (!debugMarkers || !annotations)
1440 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1459 Q_ASSERT(cbD->commands.isEmpty());
1461 if (cbD->currentTarget) {
1465 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1480 return QRhi::FrameOpDeviceLost;
1487 if (swapChainD->frameLatencyWaitableObject) {
1490 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1495 swapChainD->cb.resetState();
1497 swapChainD->rt.d.views.setFrom(1,
1498 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1499 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1504 double elapsedSec = 0;
1506 swapChainD->cb.lastGpuTime = elapsedSec;
1515 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1516 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1517 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1518 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1520 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1522 return QRhi::FrameOpSuccess;
1533 cmd.args.endFrame.tsQuery =
nullptr;
1534 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1539 if (swapChainD->sampleDesc.Count > 1) {
1540 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1541 swapChainD->msaaTex[currentFrameSlot], 0,
1542 swapChainD->colorFormat);
1549 if (recordTimestamps) {
1550 context->End(tsEnd);
1551 context->End(tsDisjoint);
1556 if (!flags.testFlag(QRhi::SkipPresent)) {
1557 UINT presentFlags = 0;
1558 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1559 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1560 if (!swapChainD->swapChain) {
1561 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1562 return QRhi::FrameOpError;
1564 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1565 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1566 qWarning(
"Device loss detected in Present()");
1568 return QRhi::FrameOpDeviceLost;
1569 }
else if (FAILED(hr)) {
1570 qWarning(
"Failed to present: %s",
1571 qPrintable(QSystemError::windowsComString(hr)));
1572 return QRhi::FrameOpError;
1575 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1576 dcompDevice->Commit();
1587 return QRhi::FrameOpSuccess;
1595 ofr.cbWrapper.resetState();
1596 *cb = &ofr.cbWrapper;
1598 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1599 D3D11_QUERY_DESC queryDesc = {};
1600 if (!ofr.tsDisjointQuery) {
1601 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1602 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1604 qWarning(
"Failed to create timestamp disjoint query: %s",
1605 qPrintable(QSystemError::windowsComString(hr)));
1606 return QRhi::FrameOpError;
1609 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1610 for (
int i = 0; i < 2; ++i) {
1611 if (!ofr.tsQueries[i]) {
1612 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1614 qWarning(
"Failed to create timestamp query: %s",
1615 qPrintable(QSystemError::windowsComString(hr)));
1616 return QRhi::FrameOpError;
1624 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1625 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1626 cmd.args.beginFrame.swapchainRtv =
nullptr;
1627 cmd.args.beginFrame.swapchainDsv =
nullptr;
1629 return QRhi::FrameOpSuccess;
1639 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1640 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1647 if (ofr.tsQueries[0]) {
1648 quint64 timestamps[2];
1649 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1653 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1654 }
while (hr == S_FALSE);
1657 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1658 }
while (hr == S_FALSE);
1661 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1662 }
while (hr == S_FALSE);
1665 if (!dj.Disjoint && dj.Frequency) {
1666 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1667 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1672 return QRhi::FrameOpSuccess;
1677 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1679 case QRhiTexture::RGBA8:
1680 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1681 case QRhiTexture::BGRA8:
1682 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1683 case QRhiTexture::R8:
1684 return DXGI_FORMAT_R8_UNORM;
1685 case QRhiTexture::R8SI:
1686 return DXGI_FORMAT_R8_SINT;
1687 case QRhiTexture::R8UI:
1688 return DXGI_FORMAT_R8_UINT;
1689 case QRhiTexture::RG8:
1690 return DXGI_FORMAT_R8G8_UNORM;
1691 case QRhiTexture::R16:
1692 return DXGI_FORMAT_R16_UNORM;
1693 case QRhiTexture::RG16:
1694 return DXGI_FORMAT_R16G16_UNORM;
1695 case QRhiTexture::RED_OR_ALPHA8:
1696 return DXGI_FORMAT_R8_UNORM;
1698 case QRhiTexture::RGBA16F:
1699 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1700 case QRhiTexture::RGBA32F:
1701 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1702 case QRhiTexture::R16F:
1703 return DXGI_FORMAT_R16_FLOAT;
1704 case QRhiTexture::R32F:
1705 return DXGI_FORMAT_R32_FLOAT;
1707 case QRhiTexture::RGB10A2:
1708 return DXGI_FORMAT_R10G10B10A2_UNORM;
1710 case QRhiTexture::R32SI:
1711 return DXGI_FORMAT_R32_SINT;
1712 case QRhiTexture::R32UI:
1713 return DXGI_FORMAT_R32_UINT;
1714 case QRhiTexture::RG32SI:
1715 return DXGI_FORMAT_R32G32_SINT;
1716 case QRhiTexture::RG32UI:
1717 return DXGI_FORMAT_R32G32_UINT;
1718 case QRhiTexture::RGBA32SI:
1719 return DXGI_FORMAT_R32G32B32A32_SINT;
1720 case QRhiTexture::RGBA32UI:
1721 return DXGI_FORMAT_R32G32B32A32_UINT;
1723 case QRhiTexture::D16:
1724 return DXGI_FORMAT_R16_TYPELESS;
1725 case QRhiTexture::D24:
1726 return DXGI_FORMAT_R24G8_TYPELESS;
1727 case QRhiTexture::D24S8:
1728 return DXGI_FORMAT_R24G8_TYPELESS;
1729 case QRhiTexture::D32F:
1730 return DXGI_FORMAT_R32_TYPELESS;
1731 case QRhiTexture::D32FS8:
1732 return DXGI_FORMAT_R32G8X24_TYPELESS;
1734 case QRhiTexture::BC1:
1735 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1736 case QRhiTexture::BC2:
1737 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1738 case QRhiTexture::BC3:
1739 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1740 case QRhiTexture::BC4:
1741 return DXGI_FORMAT_BC4_UNORM;
1742 case QRhiTexture::BC5:
1743 return DXGI_FORMAT_BC5_UNORM;
1744 case QRhiTexture::BC6H:
1745 return DXGI_FORMAT_BC6H_UF16;
1746 case QRhiTexture::BC7:
1747 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1749 case QRhiTexture::ETC2_RGB8:
1750 case QRhiTexture::ETC2_RGB8A1:
1751 case QRhiTexture::ETC2_RGBA8:
1752 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1753 return DXGI_FORMAT_R8G8B8A8_UNORM;
1755 case QRhiTexture::ASTC_4x4:
1756 case QRhiTexture::ASTC_5x4:
1757 case QRhiTexture::ASTC_5x5:
1758 case QRhiTexture::ASTC_6x5:
1759 case QRhiTexture::ASTC_6x6:
1760 case QRhiTexture::ASTC_8x5:
1761 case QRhiTexture::ASTC_8x6:
1762 case QRhiTexture::ASTC_8x8:
1763 case QRhiTexture::ASTC_10x5:
1764 case QRhiTexture::ASTC_10x6:
1765 case QRhiTexture::ASTC_10x8:
1766 case QRhiTexture::ASTC_10x10:
1767 case QRhiTexture::ASTC_12x10:
1768 case QRhiTexture::ASTC_12x12:
1769 qWarning(
"QRhiD3D11 does not support ASTC textures");
1770 return DXGI_FORMAT_R8G8B8A8_UNORM;
1774 return DXGI_FORMAT_R8G8B8A8_UNORM;
1781 case DXGI_FORMAT_R8G8B8A8_UNORM:
1782 return QRhiTexture::RGBA8;
1783 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1785 (*flags) |= QRhiTexture::sRGB;
1786 return QRhiTexture::RGBA8;
1787 case DXGI_FORMAT_B8G8R8A8_UNORM:
1788 return QRhiTexture::BGRA8;
1789 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1791 (*flags) |= QRhiTexture::sRGB;
1792 return QRhiTexture::BGRA8;
1793 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1794 return QRhiTexture::RGBA16F;
1795 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1796 return QRhiTexture::RGBA32F;
1797 case DXGI_FORMAT_R10G10B10A2_UNORM:
1798 return QRhiTexture::RGB10A2;
1800 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1803 return QRhiTexture::UnknownFormat;
1809 case QRhiTexture::Format::D16:
1810 case QRhiTexture::Format::D24:
1811 case QRhiTexture::Format::D24S8:
1812 case QRhiTexture::Format::D32F:
1813 case QRhiTexture::Format::D32FS8:
1826 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1828 ofr.cbWrapper.resetCommands();
1839 return QRhi::FrameOpSuccess;
1843 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1845 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1846 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
1848 box.front = is3D ? UINT(layer) : 0u;
1850 box.back = box.front + 1;
1853 cmd.args.updateSubRes.dst = texD->textureResource();
1854 cmd.args.updateSubRes.dstSubRes = subres;
1856 const QPoint dp = subresDesc.destinationTopLeft();
1857 if (!subresDesc.image().isNull()) {
1858 QImage img = subresDesc.image();
1859 QSize size = img.size();
1860 int bpl = img.bytesPerLine();
1861 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1862 const QPoint sp = subresDesc.sourceTopLeft();
1863 if (!subresDesc.sourceSize().isEmpty())
1864 size = subresDesc.sourceSize();
1865 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1866 if (img.depth() == 32) {
1867 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
1868 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
1870 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
1871 bpl = img.bytesPerLine();
1872 cmd.args.updateSubRes.src = cbD->retainImage(img);
1875 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1876 cmd.args.updateSubRes.src = cbD->retainImage(img);
1878 box.left = UINT(dp.x());
1879 box.top = UINT(dp.y());
1880 box.right = UINT(dp.x() + size.width());
1881 box.bottom = UINT(dp.y() + size.height());
1882 cmd.args.updateSubRes.hasDstBox =
true;
1883 cmd.args.updateSubRes.dstBox = box;
1884 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
1885 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
1886 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1887 : subresDesc.sourceSize();
1890 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
1894 box.left = UINT(aligned(dp.x(), blockDim.width()));
1895 box.top = UINT(aligned(dp.y(), blockDim.height()));
1896 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
1897 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
1898 cmd.args.updateSubRes.hasDstBox =
true;
1899 cmd.args.updateSubRes.dstBox = box;
1900 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1901 cmd.args.updateSubRes.srcRowPitch = bpl;
1902 }
else if (!subresDesc.data().isEmpty()) {
1903 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
1904 : subresDesc.sourceSize();
1905 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
1906 quint32 bytesPerPixel = 0;
1907 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
1908 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
1909 bytesPerPixel, subresDesc.data().size());
1910 if (size.isEmpty()) {
1911 cbD->commands.unget();
1915 if (subresDesc.dataStride())
1916 bpl = subresDesc.dataStride();
1918 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
1919 box.left = UINT(dp.x());
1920 box.top = UINT(dp.y());
1921 box.right = UINT(dp.x() + size.width());
1922 box.bottom = UINT(dp.y() + size.height());
1923 cmd.args.updateSubRes.hasDstBox =
true;
1924 cmd.args.updateSubRes.dstBox = box;
1925 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
1926 cmd.args.updateSubRes.srcRowPitch = bpl;
1928 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
1929 cbD->commands.unget();
1942 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
1947 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
1948 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
1951 cmd.args.updateSubRes.dst = bufD->buffer;
1952 cmd.args.updateSubRes.dstSubRes = 0;
1953 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
1954 cmd.args.updateSubRes.srcRowPitch = 0;
1959 box.left = u.offset;
1960 box.top = box.front = 0;
1961 box.back = box.bottom = 1;
1962 box.right = u.offset + u
.data.size();
1963 cmd.args.updateSubRes.hasDstBox =
true;
1964 cmd.args.updateSubRes.dstBox = box;
1967 if (bufD->m_type == QRhiBuffer::Dynamic) {
1968 u.result->data.resize(u.readSize);
1969 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
1970 if (u.result->completed)
1971 u.result->completed();
1974 readback.result = u.result;
1975 readback.byteSize = u.readSize;
1977 D3D11_BUFFER_DESC desc = {};
1978 desc.ByteWidth = readback.byteSize;
1979 desc.Usage = D3D11_USAGE_STAGING;
1980 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
1981 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
1983 qWarning(
"Failed to create buffer: %s",
1984 qPrintable(QSystemError::windowsComString(hr)));
1990 cmd.args.copySubRes.dst = readback.stagingBuf;
1991 cmd.args.copySubRes.dstSubRes = 0;
1992 cmd.args.copySubRes.dstX = 0;
1993 cmd.args.copySubRes.dstY = 0;
1994 cmd.args.copySubRes.dstZ = 0;
1995 cmd.args.copySubRes.src = bufD->buffer;
1996 cmd.args.copySubRes.srcSubRes = 0;
1997 cmd.args.copySubRes.hasSrcBox =
true;
1999 box.left = u.offset;
2000 box.top = box.front = 0;
2001 box.back = box.bottom = 1;
2002 box.right = u.offset + u.readSize;
2003 cmd.args.copySubRes.srcBox = box;
2005 activeBufferReadbacks.append(readback);
2013 for (
int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
2014 for (
int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
2015 for (
const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
2016 enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
2023 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2024 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2025 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD->mipLevelCount);
2026 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD->mipLevelCount);
2027 const QPoint dp = u.desc.destinationTopLeft();
2028 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2029 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2030 const QPoint sp = u.desc.sourceTopLeft();
2032 srcBox.left = UINT(sp.x());
2033 srcBox.top = UINT(sp.y());
2034 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2036 srcBox.right = srcBox.left + UINT(copySize.width());
2037 srcBox.bottom = srcBox.top + UINT(copySize.height());
2038 srcBox.back = srcBox.front + 1;
2041 cmd.args.copySubRes.dst = dstD->textureResource();
2042 cmd.args.copySubRes.dstSubRes = dstSubRes;
2043 cmd.args.copySubRes.dstX = UINT(dp.x());
2044 cmd.args.copySubRes.dstY = UINT(dp.y());
2045 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2046 cmd.args.copySubRes.src = srcD->textureResource();
2047 cmd.args.copySubRes.srcSubRes = srcSubRes;
2048 cmd.args.copySubRes.hasSrcBox =
true;
2049 cmd.args.copySubRes.srcBox = srcBox;
2052 readback.desc = u.rb;
2053 readback.result = u.result;
2055 ID3D11Resource *src;
2056 DXGI_FORMAT dxgiFormat;
2058 QRhiTexture::Format format;
2065 if (texD->sampleDesc.Count > 1) {
2066 qWarning(
"Multisample texture cannot be read back");
2069 src = texD->textureResource();
2070 dxgiFormat = texD->dxgiFormat;
2071 if (u.rb.rect().isValid())
2074 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2075 format = texD->m_format;
2076 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2077 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD->mipLevelCount);
2081 if (swapChainD->sampleDesc.Count > 1) {
2086 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2087 rcmd.args.resolveSubRes.dstSubRes = 0;
2089 rcmd.args.resolveSubRes.srcSubRes = 0;
2090 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2092 src = swapChainD->backBufferTex;
2093 dxgiFormat = swapChainD->colorFormat;
2094 if (u.rb.rect().isValid())
2097 rect = QRect({0, 0}, swapChainD->pixelSize);
2098 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2099 if (format == QRhiTexture::UnknownFormat)
2102 quint32 byteSize = 0;
2104 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2106 D3D11_TEXTURE2D_DESC desc = {};
2107 desc.Width = UINT(rect.width());
2108 desc.Height = UINT(rect.height());
2111 desc.Format = dxgiFormat;
2112 desc.SampleDesc.Count = 1;
2113 desc.Usage = D3D11_USAGE_STAGING;
2114 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2115 ID3D11Texture2D *stagingTex;
2116 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2118 qWarning(
"Failed to create readback staging texture: %s",
2119 qPrintable(QSystemError::windowsComString(hr)));
2125 cmd.args.copySubRes.dst = stagingTex;
2126 cmd.args.copySubRes.dstSubRes = 0;
2127 cmd.args.copySubRes.dstX = 0;
2128 cmd.args.copySubRes.dstY = 0;
2129 cmd.args.copySubRes.dstZ = 0;
2130 cmd.args.copySubRes.src = src;
2131 cmd.args.copySubRes.srcSubRes = subres;
2133 D3D11_BOX srcBox = {};
2134 srcBox.left = UINT(rect.left());
2135 srcBox.top = UINT(rect.top());
2136 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2138 srcBox.right = srcBox.left + desc.Width;
2139 srcBox.bottom = srcBox.top + desc.Height;
2140 srcBox.back = srcBox.front + 1;
2141 cmd.args.copySubRes.hasSrcBox =
true;
2142 cmd.args.copySubRes.srcBox = srcBox;
2144 readback.stagingTex = stagingTex;
2145 readback.byteSize = byteSize;
2147 readback.pixelSize = rect.size();
2148 readback.format = format;
2150 activeTextureReadbacks.append(readback);
2152 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2155 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2164 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2166 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2168 readback.result->format = readback.format;
2169 readback.result->pixelSize = readback.pixelSize;
2171 D3D11_MAPPED_SUBRESOURCE mp;
2172 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2173 if (SUCCEEDED(hr)) {
2174 readback.result->data.resize(
int(readback.byteSize));
2177 char *dst = readback.result->data.data();
2178 char *src =
static_cast<
char *>(mp.pData);
2179 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2180 memcpy(dst, src, readback.bpl);
2181 dst += readback.bpl;
2184 context->Unmap(readback.stagingTex, 0);
2186 qWarning(
"Failed to map readback staging texture: %s",
2187 qPrintable(QSystemError::windowsComString(hr)));
2190 readback.stagingTex->Release();
2192 if (readback.result->completed)
2193 completedCallbacks.append(readback.result->completed);
2195 activeTextureReadbacks.removeLast();
2198 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2201 D3D11_MAPPED_SUBRESOURCE mp;
2202 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2203 if (SUCCEEDED(hr)) {
2204 readback.result->data.resize(
int(readback.byteSize));
2205 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2206 context->Unmap(readback.stagingBuf, 0);
2208 qWarning(
"Failed to map readback staging texture: %s",
2209 qPrintable(QSystemError::windowsComString(hr)));
2212 readback.stagingBuf->Release();
2214 if (readback.result->completed)
2215 completedCallbacks.append(readback.result->completed);
2217 activeBufferReadbacks.removeLast();
2220 for (
auto f : completedCallbacks)
2226 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2232 QRhiRenderTarget *rt,
2233 const QColor &colorClearValue,
2234 const QRhiDepthStencilClearValue &depthStencilClearValue,
2235 QRhiResourceUpdateBatch *resourceUpdates,
2241 if (resourceUpdates)
2244 bool wantsColorClear =
true;
2245 bool wantsDsClear =
true;
2247 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2249 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2250 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2251 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2259 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2263 clearCmd.args.clear.rtViews = rtD->views;
2264 clearCmd.args.clear.mask = 0;
2265 if (rtD->views.colorAttCount && wantsColorClear)
2267 if (rtD->views.dsv && wantsDsClear)
2270 clearCmd.args.clear.c[0] = colorClearValue.redF();
2271 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2272 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2273 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2274 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2275 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2278 cbD->currentTarget = rt;
2288 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2290 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2293 const QRhiColorAttachment &colorAtt(*it);
2294 if (!colorAtt.resolveTexture())
2300 Q_ASSERT(srcTexD || srcRbD);
2303 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2304 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2305 UINT(colorAtt.resolveLayer()),
2306 dstTexD->mipLevelCount);
2308 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2309 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2310 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2311 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2312 cbD->commands.unget();
2315 if (srcTexD->sampleDesc.Count <= 1) {
2316 qWarning(
"Cannot resolve a non-multisample texture");
2317 cbD->commands.unget();
2320 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2321 qWarning(
"Resolve source and destination sizes do not match");
2322 cbD->commands.unget();
2326 cmd.args.resolveSubRes.src = srcRbD->tex;
2327 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2328 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2329 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2330 cbD->commands.unget();
2333 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2334 qWarning(
"Resolve source and destination sizes do not match");
2335 cbD->commands.unget();
2339 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2340 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2342 if (rtTex->m_desc.depthResolveTexture())
2343 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2347 cbD->currentTarget =
nullptr;
2349 if (resourceUpdates)
2354 QRhiResourceUpdateBatch *resourceUpdates,
2360 if (resourceUpdates)
2368 fbCmd.args.setRenderTarget.rtViews.reset();
2385 if (resourceUpdates)
2394 const bool pipelineChanged = cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation;
2396 if (pipelineChanged) {
2397 cbD->currentGraphicsPipeline =
nullptr;
2398 cbD->currentComputePipeline = psD;
2399 cbD->currentPipelineGeneration = psD->generation;
2403 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2414 cmd.args.dispatch.x = UINT(x);
2415 cmd.args.dispatch.y = UINT(y);
2416 cmd.args.dispatch.z = UINT(z);
2421 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2423 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2424 if (!map || map->isEmpty())
2425 return { binding, binding };
2427 auto it = map->constFind(binding);
2428 if (it != map->cend())
2438 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
2440 srbD->resourceBatches.clear();
2446 ID3D11Buffer *buffer;
2447 uint offsetInConstants;
2448 uint sizeInConstants;
2452 ID3D11ShaderResourceView *srv;
2456 ID3D11SamplerState *sampler;
2460 ID3D11UnorderedAccessView *uav;
2462 QVarLengthArray<Buffer, 8> buffers;
2463 QVarLengthArray<Texture, 8> textures;
2464 QVarLengthArray<Sampler, 8> samplers;
2465 QVarLengthArray<Uav, 8> uavs;
2468 for (
const Buffer &buf : buffers) {
2469 batches.ubufs.feed(buf.breg, buf.buffer);
2470 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2471 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2472 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2478 for (
const Texture &t : textures)
2479 batches.shaderresources.feed(t.treg, t.srv);
2480 for (
const Sampler &s : samplers)
2481 batches.samplers.feed(s.sreg, s.sampler);
2486 for (
const Stage::Uav &u : uavs)
2487 batches.uavs.feed(u.ureg, u.uav);
2492 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2493 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2496 case QRhiShaderResourceBinding::UniformBuffer:
2499 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2500 bd.ubuf.id = bufD->m_id;
2501 bd.ubuf.generation = bufD->generation;
2508 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2512 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2513 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2514 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2515 if (nativeBinding.first >= 0)
2516 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2518 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2519 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2520 if (nativeBinding.first >= 0)
2521 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2523 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2524 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2525 if (nativeBinding.first >= 0)
2526 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2528 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2529 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2530 if (nativeBinding.first >= 0)
2531 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2533 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2534 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2535 if (nativeBinding.first >= 0)
2536 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2538 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2539 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2540 if (nativeBinding.first >= 0)
2541 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2545 case QRhiShaderResourceBinding::SampledTexture:
2546 case QRhiShaderResourceBinding::Texture:
2547 case QRhiShaderResourceBinding::Sampler:
2549 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
2550 bd.stex.count = data->count;
2551 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
2552 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
2553 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
2554 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
2555 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2556 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2560 for (
int elem = 0; elem < data->count; ++elem) {
2563 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2564 bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
2565 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2566 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
2571 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2572 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2573 : (samplerD ? nativeBindingVert.first : -1);
2574 if (nativeBindingVert.first >= 0 && texD)
2575 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2576 if (samplerBinding >= 0)
2577 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2579 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2580 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2581 : (samplerD ? nativeBindingHull.first : -1);
2582 if (nativeBindingHull.first >= 0 && texD)
2583 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2584 if (samplerBinding >= 0)
2585 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2587 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2588 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2589 : (samplerD ? nativeBindingDomain.first : -1);
2590 if (nativeBindingDomain.first >= 0 && texD)
2591 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2592 if (samplerBinding >= 0)
2593 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2595 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2596 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2597 : (samplerD ? nativeBindingGeom.first : -1);
2598 if (nativeBindingGeom.first >= 0 && texD)
2599 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2600 if (samplerBinding >= 0)
2601 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2603 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2604 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2605 : (samplerD ? nativeBindingFrag.first : -1);
2606 if (nativeBindingFrag.first >= 0 && texD)
2607 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2608 if (samplerBinding >= 0)
2609 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2611 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2612 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2613 : (samplerD ? nativeBindingComp.first : -1);
2614 if (nativeBindingComp.first >= 0 && texD)
2615 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2616 if (samplerBinding >= 0)
2617 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2622 case QRhiShaderResourceBinding::ImageLoad:
2623 case QRhiShaderResourceBinding::ImageStore:
2624 case QRhiShaderResourceBinding::ImageLoadStore:
2627 bd.simage.id = texD->m_id;
2628 bd.simage.generation = texD->generation;
2629 bool validStage =
false;
2630 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2631 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2632 if (nativeBinding.first >= 0) {
2633 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2635 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2639 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2640 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2641 if (nativeBinding.first >= 0) {
2642 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2644 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2649 qWarning(
"Unordered access only supported at fragment/compute stage");
2652 case QRhiShaderResourceBinding::BufferLoad:
2653 case QRhiShaderResourceBinding::BufferStore:
2654 case QRhiShaderResourceBinding::BufferLoadStore:
2657 bd.sbuf.id = bufD->m_id;
2658 bd.sbuf.generation = bufD->generation;
2659 bool validStage =
false;
2660 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2661 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
2662 if (nativeBinding.first >= 0) {
2663 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2665 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2669 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2670 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
2671 if (nativeBinding.first >= 0) {
2672 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2674 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2679 qWarning(
"Unordered access only supported at fragment/compute stage");
2693 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2694 return a.breg < b.breg;
2696 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2697 return a.treg < b.treg;
2699 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2700 return a.sreg < b.sreg;
2702 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2703 return a.ureg < b.ureg;
2707 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2708 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2709 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2710 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2711 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2712 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2714 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2715 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2716 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2717 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2718 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2719 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2721 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2722 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2730 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2732 D3D11_MAPPED_SUBRESOURCE mp;
2733 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2734 if (SUCCEEDED(hr)) {
2735 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2736 context->Unmap(bufD->buffer, 0);
2738 qWarning(
"Failed to map buffer: %s",
2739 qPrintable(QSystemError::windowsComString(hr)));
2745 const QRhiBatchedBindings<UINT> *originalBindings,
2746 const QRhiBatchedBindings<UINT> *staticOffsets,
2747 const uint *dynOfsPairs,
int dynOfsPairCount)
2749 const int count = staticOffsets->batches[batchIndex].resources.count();
2752 for (
int b = 0; b < count; ++b) {
2753 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2754 for (
int di = 0; di < dynOfsPairCount; ++di) {
2755 const uint binding = dynOfsPairs[2 * di];
2758 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2759 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2760 offsets[b] = offsetInConstants;
2769 if (startSlot + countSlots > maxSlots) {
2770 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2771 resType, countSlots, startSlot, maxSlots);
2772 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2777#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
2778 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
2779 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
2780 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
2781 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
2782 batches.ubufs.batches[i].resources.count(),
2783 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
2784 #stagePrefixU " cbuf");
2786 if (!dynOfsPairCount) {
2787 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2789 batches.ubufs.batches[i].resources.constData(),
2790 batches.ubufoffsets.batches[i].resources.constData(),
2791 batches.ubufsizes.batches[i].resources.constData());
2793 applyDynamicOffsets(offsets, i,
2794 &batches.ubuforigbindings, &batches.ubufoffsets,
2795 dynOfsPairs, dynOfsPairCount);
2796 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
2798 batches.ubufs.batches[i].resources.constData(),
2800 batches.ubufsizes.batches[i].resources.constData());
2806#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
2807 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
2808 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
2809 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2810 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
2812 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
2814 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
2815 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2816 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
2818 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
2819 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
2820 int(batch.startBinding + count) - 1
);
2825#define SETUAVBATCH(stagePrefixL, stagePrefixU)
2826 if (allResourceBatches.stagePrefixL##UavBatches.present) {
2827 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
2828 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
2831 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
2833 batch.resources.constData(),
2835 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
2836 int(batch.startBinding + count) - 1
);
2843 const uint *dynOfsPairs,
int dynOfsPairCount,
2844 bool offsetOnlyChange,
2856 if (!offsetOnlyChange) {
2866 if (allResourceBatches.fsUavBatches.present) {
2867 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
2868 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
2870 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
2872 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
2873 context->OMSetRenderTargetsAndUnorderedAccessViews(
2874 UINT(rtUavState->rtViews.colorAttCount),
2875 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
2876 rtUavState->rtViews.dsv,
2877 UINT(batch.startBinding),
2879 batch.resources.constData(),
2882 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
2883 int(batch.startBinding + count) - 1);
2896 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
2902 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
2903 for (
int i = 0; i < count; ++i)
2904 nullbufs[i] =
nullptr;
2905 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
2906 for (
int i = 0; i < count; ++i)
2908 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
2909 for (
int i = 0; i < count; ++i)
2911 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
2921 if (nullsrvCount > 0) {
2922 QVarLengthArray<ID3D11ShaderResourceView *,
2923 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
2924 for (
int i = 0; i < nullsrvs.count(); ++i)
2925 nullsrvs[i] =
nullptr;
2927 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
2931 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
2935 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
2939 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
2943 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
2947 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
2953 rtUavState->update(cbD->currentRenderTargetViews);
2954 context->OMSetRenderTargetsAndUnorderedAccessViews(
2955 UINT(cbD->currentRenderTargetViews.colorAttCount),
2956 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
2957 cbD->currentRenderTargetViews.dsv,
2958 0, 0,
nullptr,
nullptr);
2963 QVarLengthArray<ID3D11UnorderedAccessView *,
2964 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
2965 for (
int i = 0; i < nulluavCount; ++i)
2966 nulluavs[i] =
nullptr;
2967 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
2972#define SETSHADER(StageL, StageU)
2973 if (cmd.args.bindGraphicsPipeline.StageL) {
2974 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
2975 currentShaderMask |= StageU##MaskBit;
2976 } else if (currentShaderMask & StageU##MaskBit) {
2977 context->StageU##SetShader(nullptr, nullptr, 0
);
2978 currentShaderMask &= ~StageU##MaskBit;
2983 quint32 stencilRef = 0;
2984 float blendConstants[] = { 1, 1, 1, 1 };
2985 enum ActiveShaderMask {
2992 int currentShaderMask = 0xFF;
2998 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3001 case QD3D11CommandBuffer::Command::BeginFrame:
3002 if (cmd.args.beginFrame.tsDisjointQuery)
3003 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3004 if (cmd.args.beginFrame.tsQuery) {
3005 if (cmd.args.beginFrame.swapchainRtv) {
3010 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3011 rtUavState.update(cbD->currentRenderTargetViews);
3012 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3014 context->End(cmd.args.beginFrame.tsQuery);
3017 case QD3D11CommandBuffer::Command::EndFrame:
3018 if (cmd.args.endFrame.tsQuery)
3019 context->End(cmd.args.endFrame.tsQuery);
3020 if (cmd.args.endFrame.tsDisjointQuery)
3021 context->End(cmd.args.endFrame.tsDisjointQuery);
3028 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3029 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3030 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3031 context->OMSetRenderTargets(colorAttCount,
3032 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3033 cmd.args.setRenderTarget.rtViews.dsv);
3040 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3041 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3044 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3045 ds |= D3D11_CLEAR_DEPTH;
3046 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3047 ds |= D3D11_CLEAR_STENCIL;
3048 if (ds && cmd.args.clear.rtViews.dsv)
3049 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3055 v.TopLeftX = cmd.args.viewport.x;
3056 v.TopLeftY = cmd.args.viewport.y;
3057 v.Width = cmd.args.viewport.w;
3058 v.Height = cmd.args.viewport.h;
3059 v.MinDepth = cmd.args.viewport.d0;
3060 v.MaxDepth = cmd.args.viewport.d1;
3061 context->RSSetViewports(1, &v);
3067 r.left = cmd.args.scissor.x;
3068 r.top = cmd.args.scissor.y;
3070 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3071 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3072 context->RSSetScissorRects(1, &r);
3078 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3079 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3080 UINT(cmd.args.bindVertexBuffers.slotCount),
3081 cmd.args.bindVertexBuffers.buffers,
3082 cmd.args.bindVertexBuffers.strides,
3083 cmd.args.bindVertexBuffers.offsets);
3087 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3088 cmd.args.bindIndexBuffer.format,
3089 cmd.args.bindIndexBuffer.offset);
3098 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3099 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3100 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3101 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3102 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3105 case QD3D11CommandBuffer::Command::BindShaderResources:
3106 bindShaderResources(cbD,
3107 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex],
3108 cmd.args.bindShaderResources.dynamicOffsetPairs,
3109 cmd.args.bindShaderResources.dynamicOffsetCount,
3110 cmd.args.bindShaderResources.offsetOnlyChange,
3114 stencilRef = cmd.args.stencilRef.ref;
3115 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3118 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3119 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3121 case QD3D11CommandBuffer::Command::Draw:
3122 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3123 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3125 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3126 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3128 case QD3D11CommandBuffer::Command::DrawIndexed:
3129 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3130 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3131 cmd.args.drawIndexed.vertexOffset);
3133 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3134 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3135 cmd.args.drawIndexed.firstInstance);
3139 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3140 const UINT stride = cmd.args.drawIndirect.stride;
3141 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3142 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3143 alignedByteOffsetForArgs += stride;
3149 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3150 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3151 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3152 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3153 alignedByteOffsetForArgs += stride;
3159 if (cmd.args.updateSubRes.dst) {
3160 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3161 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3162 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3165 case QD3D11CommandBuffer::Command::CopySubRes:
3166 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3167 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3168 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3169 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3171 case QD3D11CommandBuffer::Command::ResolveSubRes:
3172 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3173 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3174 cmd.args.resolveSubRes.format);
3176 case QD3D11CommandBuffer::Command::GenMip:
3177 context->GenerateMips(cmd.args.genMip.srv);
3179 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3180 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3182 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3183 annotations->EndEvent();
3185 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3186 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3188 case QD3D11CommandBuffer::Command::BindComputePipeline:
3189 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3191 case QD3D11CommandBuffer::Command::Dispatch:
3192 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3221 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3222 it.value()->Release();
3227 rhiD->unregisterResource(
this);
3233 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3234 u |= D3D11_BIND_VERTEX_BUFFER;
3235 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3236 u |= D3D11_BIND_INDEX_BUFFER;
3237 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3238 u |= D3D11_BIND_CONSTANT_BUFFER;
3239 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3240 u |= D3D11_BIND_UNORDERED_ACCESS;
3249 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3250 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3254 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3255 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3259 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3260 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3264 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3265 const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3267 D3D11_BUFFER_DESC desc = {};
3268 desc.ByteWidth = roundedSize;
3269 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3270 desc.BindFlags = toD3DBufferUsage(m_usage);
3271 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3272 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3273 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3274 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3277 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3279 qWarning(
"Failed to create buffer: %s",
3280 qPrintable(QSystemError::windowsComString(hr)));
3284 if (m_type == Dynamic) {
3285 dynBuf =
new char[nonZeroSize];
3289 if (!m_objectName.isEmpty())
3290 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3293 rhiD->registerResource(
this);
3299 if (m_type == Dynamic) {
3303 return { { &buffer }, 1 };
3314 Q_ASSERT(m_type == Dynamic);
3315 D3D11_MAPPED_SUBRESOURCE mp;
3317 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3319 qWarning(
"Failed to map buffer: %s",
3320 qPrintable(QSystemError::windowsComString(hr)));
3323 return static_cast<
char *>(mp.pData);
3329 rhiD->context->Unmap(buffer, 0);
3334 auto it = uavs.find(offset);
3335 if (it != uavs.end())
3339 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3340 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3341 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3342 desc.Buffer.FirstElement = offset / 4u;
3343 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3344 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3347 ID3D11UnorderedAccessView *uav =
nullptr;
3348 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3350 qWarning(
"Failed to create UAV: %s",
3351 qPrintable(QSystemError::windowsComString(hr)));
3360 int sampleCount, QRhiRenderBuffer::Flags flags,
3361 QRhiTexture::Format backingFormatHint)
3391 rhiD->unregisterResource(
this);
3399 if (m_pixelSize.isEmpty())
3403 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3405 D3D11_TEXTURE2D_DESC desc = {};
3406 desc.Width = UINT(m_pixelSize.width());
3407 desc.Height = UINT(m_pixelSize.height());
3410 desc.SampleDesc = sampleDesc;
3411 desc.Usage = D3D11_USAGE_DEFAULT;
3413 if (m_type == Color) {
3414 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3415 : toD3DTextureFormat(m_backingFormatHint, {});
3416 desc.Format = dxgiFormat;
3417 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3418 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3420 qWarning(
"Failed to create color renderbuffer: %s",
3421 qPrintable(QSystemError::windowsComString(hr)));
3424 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3425 rtvDesc.Format = dxgiFormat;
3426 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3427 : D3D11_RTV_DIMENSION_TEXTURE2D;
3428 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3430 qWarning(
"Failed to create rtv: %s",
3431 qPrintable(QSystemError::windowsComString(hr)));
3434 }
else if (m_type == DepthStencil) {
3435 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3436 desc.Format = dxgiFormat;
3437 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3438 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3440 qWarning(
"Failed to create depth-stencil buffer: %s",
3441 qPrintable(QSystemError::windowsComString(hr)));
3444 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3445 dsvDesc.Format = dxgiFormat;
3446 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3447 : D3D11_DSV_DIMENSION_TEXTURE2D;
3448 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3450 qWarning(
"Failed to create dsv: %s",
3451 qPrintable(QSystemError::windowsComString(hr)));
3458 if (!m_objectName.isEmpty())
3459 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3462 rhiD->registerResource(
this);
3468 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3469 return m_backingFormatHint;
3471 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3475 int arraySize,
int sampleCount, Flags flags)
3478 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3479 perLevelViews[i] =
nullptr;
3489 if (!tex && !tex3D && !tex1D)
3497 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3498 if (perLevelViews[i]) {
3499 perLevelViews[i]->Release();
3500 perLevelViews[i] =
nullptr;
3519 rhiD->unregisterResource(
this);
3525 case QRhiTexture::Format::D16:
3526 return DXGI_FORMAT_R16_FLOAT;
3527 case QRhiTexture::Format::D24:
3528 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3529 case QRhiTexture::Format::D24S8:
3530 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3531 case QRhiTexture::Format::D32F:
3532 return DXGI_FORMAT_R32_FLOAT;
3533 case QRhiTexture::Format::D32FS8:
3534 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3537 return DXGI_FORMAT_R32_FLOAT;
3544 case QRhiTexture::Format::D16:
3545 return DXGI_FORMAT_D16_UNORM;
3546 case QRhiTexture::Format::D24:
3547 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3548 case QRhiTexture::Format::D24S8:
3549 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3550 case QRhiTexture::Format::D32F:
3551 return DXGI_FORMAT_D32_FLOAT;
3552 case QRhiTexture::Format::D32FS8:
3553 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3556 return DXGI_FORMAT_D32_FLOAT;
3562 if (tex || tex3D || tex1D)
3566 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3569 const bool isDepth = isDepthTextureFormat(m_format);
3570 const bool isCube = m_flags.testFlag(CubeMap);
3571 const bool is3D = m_flags.testFlag(ThreeDimensional);
3572 const bool isArray = m_flags.testFlag(TextureArray);
3573 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3574 const bool is1D = m_flags.testFlag(OneDimensional);
3576 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3577 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3579 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3580 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3581 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3582 if (sampleDesc.Count > 1) {
3584 qWarning(
"Cubemap texture cannot be multisample");
3588 qWarning(
"3D texture cannot be multisample");
3592 qWarning(
"Multisample texture cannot have mipmaps");
3596 if (isDepth && hasMipMaps) {
3597 qWarning(
"Depth texture cannot have mipmaps");
3600 if (isCube && is3D) {
3601 qWarning(
"Texture cannot be both cube and 3D");
3604 if (isArray && is3D) {
3605 qWarning(
"Texture cannot be both array and 3D");
3608 if (isCube && is1D) {
3609 qWarning(
"Texture cannot be both cube and 1D");
3613 qWarning(
"Texture cannot be both 1D and 3D");
3616 if (m_depth > 1 && !is3D) {
3617 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3620 if (m_arraySize > 0 && !isArray) {
3621 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3624 if (m_arraySize < 1 && isArray) {
3625 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3629 if (!rhiD->textureFormatInfo(m_format, size,
nullptr,
nullptr,
nullptr))
3633 *adjustedSize = size;
3641 const bool isDepth = isDepthTextureFormat(m_format);
3642 const bool isCube = m_flags.testFlag(CubeMap);
3643 const bool is3D = m_flags.testFlag(ThreeDimensional);
3644 const bool isArray = m_flags.testFlag(TextureArray);
3645 const bool is1D = m_flags.testFlag(OneDimensional);
3647 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3648 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3650 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3651 srvDesc.TextureCube.MipLevels = mipLevelCount;
3655 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3656 srvDesc.Texture1DArray.MipLevels = mipLevelCount;
3657 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3658 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3659 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3661 srvDesc.Texture1DArray.FirstArraySlice = 0;
3662 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3665 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3666 srvDesc.Texture1D.MipLevels = mipLevelCount;
3668 }
else if (isArray) {
3669 if (sampleDesc.Count > 1) {
3670 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3671 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3672 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3673 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3675 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3676 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3679 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3680 srvDesc.Texture2DArray.MipLevels = mipLevelCount;
3681 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3682 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3683 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3685 srvDesc.Texture2DArray.FirstArraySlice = 0;
3686 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3690 if (sampleDesc.Count > 1) {
3691 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3693 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3694 srvDesc.Texture3D.MipLevels = mipLevelCount;
3696 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3697 srvDesc.Texture2D.MipLevels = mipLevelCount;
3702 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3704 qWarning(
"Failed to create srv: %s",
3705 qPrintable(QSystemError::windowsComString(hr)));
3716 if (!prepareCreate(&size))
3719 const bool isDepth = isDepthTextureFormat(m_format);
3720 const bool isCube = m_flags.testFlag(CubeMap);
3721 const bool is3D = m_flags.testFlag(ThreeDimensional);
3722 const bool isArray = m_flags.testFlag(TextureArray);
3723 const bool is1D = m_flags.testFlag(OneDimensional);
3725 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
3726 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
3727 if (m_flags.testFlag(RenderTarget)) {
3729 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
3731 bindFlags |= D3D11_BIND_RENDER_TARGET;
3733 if (m_flags.testFlag(UsedWithGenerateMips)) {
3735 qWarning(
"Depth texture cannot have mipmaps generated");
3738 bindFlags |= D3D11_BIND_RENDER_TARGET;
3739 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
3741 if (m_flags.testFlag(UsedWithLoadStore))
3742 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
3746 D3D11_TEXTURE1D_DESC desc = {};
3747 desc.Width = UINT(size.width());
3748 desc.MipLevels = mipLevelCount;
3749 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
3750 desc.Format = dxgiFormat;
3751 desc.Usage = D3D11_USAGE_DEFAULT;
3752 desc.BindFlags = bindFlags;
3753 desc.MiscFlags = miscFlags;
3755 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
3757 qWarning(
"Failed to create 1D texture: %s",
3758 qPrintable(QSystemError::windowsComString(hr)));
3761 if (!m_objectName.isEmpty())
3762 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
3763 m_objectName.constData());
3765 D3D11_TEXTURE2D_DESC desc = {};
3766 desc.Width = UINT(size.width());
3767 desc.Height = UINT(size.height());
3768 desc.MipLevels = mipLevelCount;
3769 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
3770 desc.Format = dxgiFormat;
3771 desc.SampleDesc = sampleDesc;
3772 desc.Usage = D3D11_USAGE_DEFAULT;
3773 desc.BindFlags = bindFlags;
3774 desc.MiscFlags = miscFlags;
3776 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3778 qWarning(
"Failed to create 2D texture: %s",
3779 qPrintable(QSystemError::windowsComString(hr)));
3780 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
3784 if (!m_objectName.isEmpty())
3785 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3787 D3D11_TEXTURE3D_DESC desc = {};
3788 desc.Width = UINT(size.width());
3789 desc.Height = UINT(size.height());
3790 desc.Depth = UINT(qMax(1, m_depth));
3791 desc.MipLevels = mipLevelCount;
3792 desc.Format = dxgiFormat;
3793 desc.Usage = D3D11_USAGE_DEFAULT;
3794 desc.BindFlags = bindFlags;
3795 desc.MiscFlags = miscFlags;
3797 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
3799 qWarning(
"Failed to create 3D texture: %s",
3800 qPrintable(QSystemError::windowsComString(hr)));
3801 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
3805 if (!m_objectName.isEmpty())
3806 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3813 rhiD->registerResource(
this);
3822 if (!prepareCreate())
3825 if (m_flags.testFlag(ThreeDimensional))
3826 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
3827 else if (m_flags.testFlags(OneDimensional))
3828 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
3830 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
3837 rhiD->registerResource(
this);
3843 return { quint64(textureResource()), 0 };
3848 if (perLevelViews[level])
3849 return perLevelViews[level];
3851 const bool isCube = m_flags.testFlag(CubeMap);
3852 const bool isArray = m_flags.testFlag(TextureArray);
3853 const bool is3D = m_flags.testFlag(ThreeDimensional);
3854 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3855 desc.Format = dxgiFormat;
3857 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3858 desc.Texture2DArray.MipSlice = UINT(level);
3859 desc.Texture2DArray.FirstArraySlice = 0;
3860 desc.Texture2DArray.ArraySize = 6;
3861 }
else if (isArray) {
3862 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
3863 desc.Texture2DArray.MipSlice = UINT(level);
3864 desc.Texture2DArray.FirstArraySlice = 0;
3865 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3867 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
3868 desc.Texture3D.MipSlice = UINT(level);
3869 desc.Texture3D.WSize = UINT(m_depth);
3871 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
3872 desc.Texture2D.MipSlice = UINT(level);
3876 ID3D11UnorderedAccessView *uav =
nullptr;
3877 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
3879 qWarning(
"Failed to create UAV: %s",
3880 qPrintable(QSystemError::windowsComString(hr)));
3884 perLevelViews[level] = uav;
3889 AddressMode u, AddressMode v, AddressMode w)
3904 samplerState->Release();
3905 samplerState =
nullptr;
3909 rhiD->unregisterResource(
this);
3912static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
3914 if (minFilter == QRhiSampler::Nearest) {
3915 if (magFilter == QRhiSampler::Nearest) {
3916 if (mipFilter == QRhiSampler::Linear)
3917 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
3919 return D3D11_FILTER_MIN_MAG_MIP_POINT;
3921 if (mipFilter == QRhiSampler::Linear)
3922 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
3924 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
3927 if (magFilter == QRhiSampler::Nearest) {
3928 if (mipFilter == QRhiSampler::Linear)
3929 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
3931 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
3933 if (mipFilter == QRhiSampler::Linear)
3934 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3936 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
3941 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
3947 case QRhiSampler::Repeat:
3948 return D3D11_TEXTURE_ADDRESS_WRAP;
3949 case QRhiSampler::ClampToEdge:
3950 return D3D11_TEXTURE_ADDRESS_CLAMP;
3951 case QRhiSampler::Mirror:
3952 return D3D11_TEXTURE_ADDRESS_MIRROR;
3955 return D3D11_TEXTURE_ADDRESS_CLAMP;
3962 case QRhiSampler::Never:
3963 return D3D11_COMPARISON_NEVER;
3964 case QRhiSampler::Less:
3965 return D3D11_COMPARISON_LESS;
3966 case QRhiSampler::Equal:
3967 return D3D11_COMPARISON_EQUAL;
3968 case QRhiSampler::LessOrEqual:
3969 return D3D11_COMPARISON_LESS_EQUAL;
3970 case QRhiSampler::Greater:
3971 return D3D11_COMPARISON_GREATER;
3972 case QRhiSampler::NotEqual:
3973 return D3D11_COMPARISON_NOT_EQUAL;
3974 case QRhiSampler::GreaterOrEqual:
3975 return D3D11_COMPARISON_GREATER_EQUAL;
3976 case QRhiSampler::Always:
3977 return D3D11_COMPARISON_ALWAYS;
3980 return D3D11_COMPARISON_NEVER;
3989 D3D11_SAMPLER_DESC desc = {};
3990 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
3991 if (m_compareOp != Never)
3992 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
3993 desc.AddressU = toD3DAddressMode(m_addressU);
3994 desc.AddressV = toD3DAddressMode(m_addressV);
3995 desc.AddressW = toD3DAddressMode(m_addressW);
3996 desc.MaxAnisotropy = 1.0f;
3997 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
3998 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
4001 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
4003 qWarning(
"Failed to create sampler state: %s",
4004 qPrintable(QSystemError::windowsComString(hr)));
4009 rhiD->registerResource(
this);
4028 rhiD->unregisterResource(
this);
4041 rhiD->registerResource(rpD,
false);
4078 return d.sampleCount;
4082 const QRhiTextureRenderTargetDescription &desc,
4100 if (!rtv[0] && !dsv)
4119 rhiD->unregisterResource(
this);
4126 rhiD->registerResource(rpD,
false);
4135 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4136 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4137 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4141 int colorAttCount = 0;
4143 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4145 const QRhiColorAttachment &colorAtt(*it);
4146 QRhiTexture *texture = colorAtt.texture();
4147 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4148 Q_ASSERT(texture || rb);
4151 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4152 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4153 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4154 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4155 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4156 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4157 rtvDesc.Texture2DArray.ArraySize = 1;
4158 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4159 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4160 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4161 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4162 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4163 rtvDesc.Texture1DArray.ArraySize = 1;
4165 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4166 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4168 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4169 if (texD->sampleDesc.Count > 1) {
4170 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4171 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4172 rtvDesc.Texture2DMSArray.ArraySize = 1;
4174 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4175 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4176 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4177 rtvDesc.Texture2DArray.ArraySize = 1;
4179 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4180 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4181 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4182 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4183 rtvDesc.Texture3D.WSize = 1;
4185 if (texD->sampleDesc.Count > 1) {
4186 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4188 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4189 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4192 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4194 qWarning(
"Failed to create rtv: %s",
4195 qPrintable(QSystemError::windowsComString(hr)));
4199 if (attIndex == 0) {
4200 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4201 d.sampleCount =
int(texD->sampleDesc.Count);
4206 rtv[attIndex] = rbD->rtv;
4207 if (attIndex == 0) {
4208 d.pixelSize = rbD->pixelSize();
4209 d.sampleCount =
int(rbD->sampleDesc.Count);
4215 if (hasDepthStencil) {
4216 if (m_desc.depthTexture()) {
4219 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4220 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4221 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4222 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4223 if (isMultisample) {
4224 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4225 if (m_desc.depthLayer() >= 0) {
4226 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4227 dsvDesc.Texture2DMSArray.ArraySize = 1;
4228 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4229 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4230 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4232 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4233 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4236 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4237 if (m_desc.depthLayer() >= 0) {
4238 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4239 dsvDesc.Texture2DArray.ArraySize = 1;
4240 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4241 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4242 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4244 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4245 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4250 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4251 : D3D11_DSV_DIMENSION_TEXTURE2D;
4253 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4255 qWarning(
"Failed to create dsv: %s",
4256 qPrintable(QSystemError::windowsComString(hr)));
4259 if (colorAttCount == 0) {
4260 d.pixelSize = depthTexD->pixelSize();
4261 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4266 dsv = depthRbD->dsv;
4267 if (colorAttCount == 0) {
4268 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4269 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4276 d.views.setFrom(colorAttCount, rtv, dsv);
4278 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4280 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4282 rhiD->registerResource(
this);
4288 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4301 return d.sampleCount;
4316 sortedBindings.clear();
4317 boundResourceData.clear();
4321 rhiD->unregisterResource(
this);
4326 if (!sortedBindings.isEmpty())
4330 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4333 rhiD->updateLayoutDesc(
this);
4335 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4336 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4338 boundResourceData.resize(sortedBindings.count());
4340 for (BoundResourceData &bd : boundResourceData)
4341 memset(&bd, 0,
sizeof(BoundResourceData));
4344 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4345 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4346 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4347 hasDynamicOffset =
true;
4353 rhiD->registerResource(
this,
false);
4359 sortedBindings.clear();
4360 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4361 if (!flags.testFlag(BindingsAreSorted))
4362 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4364 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4365 for (BoundResourceData &bd : boundResourceData)
4366 memset(&bd, 0,
sizeof(BoundResourceData));
4385 s.shader->Release();
4388 s.nativeResourceBindingMap.clear();
4400 blendState->Release();
4401 blendState =
nullptr;
4405 inputLayout->Release();
4406 inputLayout =
nullptr;
4410 rastState->Release();
4411 rastState =
nullptr;
4414 releasePipelineShader(vs);
4415 releasePipelineShader(hs);
4416 releasePipelineShader(ds);
4417 releasePipelineShader(gs);
4418 releasePipelineShader(fs);
4422 rhiD->unregisterResource(
this);
4428 case QRhiGraphicsPipeline::None:
4429 return D3D11_CULL_NONE;
4430 case QRhiGraphicsPipeline::Front:
4431 return D3D11_CULL_FRONT;
4432 case QRhiGraphicsPipeline::Back:
4433 return D3D11_CULL_BACK;
4436 return D3D11_CULL_NONE;
4443 case QRhiGraphicsPipeline::Fill:
4444 return D3D11_FILL_SOLID;
4445 case QRhiGraphicsPipeline::Line:
4446 return D3D11_FILL_WIREFRAME;
4449 return D3D11_FILL_SOLID;
4456 case QRhiGraphicsPipeline::Never:
4457 return D3D11_COMPARISON_NEVER;
4458 case QRhiGraphicsPipeline::Less:
4459 return D3D11_COMPARISON_LESS;
4460 case QRhiGraphicsPipeline::Equal:
4461 return D3D11_COMPARISON_EQUAL;
4462 case QRhiGraphicsPipeline::LessOrEqual:
4463 return D3D11_COMPARISON_LESS_EQUAL;
4464 case QRhiGraphicsPipeline::Greater:
4465 return D3D11_COMPARISON_GREATER;
4466 case QRhiGraphicsPipeline::NotEqual:
4467 return D3D11_COMPARISON_NOT_EQUAL;
4468 case QRhiGraphicsPipeline::GreaterOrEqual:
4469 return D3D11_COMPARISON_GREATER_EQUAL;
4470 case QRhiGraphicsPipeline::Always:
4471 return D3D11_COMPARISON_ALWAYS;
4474 return D3D11_COMPARISON_ALWAYS;
4481 case QRhiGraphicsPipeline::StencilZero:
4482 return D3D11_STENCIL_OP_ZERO;
4483 case QRhiGraphicsPipeline::Keep:
4484 return D3D11_STENCIL_OP_KEEP;
4485 case QRhiGraphicsPipeline::Replace:
4486 return D3D11_STENCIL_OP_REPLACE;
4487 case QRhiGraphicsPipeline::IncrementAndClamp:
4488 return D3D11_STENCIL_OP_INCR_SAT;
4489 case QRhiGraphicsPipeline::DecrementAndClamp:
4490 return D3D11_STENCIL_OP_DECR_SAT;
4491 case QRhiGraphicsPipeline::Invert:
4492 return D3D11_STENCIL_OP_INVERT;
4493 case QRhiGraphicsPipeline::IncrementAndWrap:
4494 return D3D11_STENCIL_OP_INCR;
4495 case QRhiGraphicsPipeline::DecrementAndWrap:
4496 return D3D11_STENCIL_OP_DECR;
4499 return D3D11_STENCIL_OP_KEEP;
4506 case QRhiVertexInputAttribute::Float4:
4507 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4508 case QRhiVertexInputAttribute::Float3:
4509 return DXGI_FORMAT_R32G32B32_FLOAT;
4510 case QRhiVertexInputAttribute::Float2:
4511 return DXGI_FORMAT_R32G32_FLOAT;
4512 case QRhiVertexInputAttribute::Float:
4513 return DXGI_FORMAT_R32_FLOAT;
4514 case QRhiVertexInputAttribute::UNormByte4:
4515 return DXGI_FORMAT_R8G8B8A8_UNORM;
4516 case QRhiVertexInputAttribute::UNormByte2:
4517 return DXGI_FORMAT_R8G8_UNORM;
4518 case QRhiVertexInputAttribute::UNormByte:
4519 return DXGI_FORMAT_R8_UNORM;
4520 case QRhiVertexInputAttribute::UInt4:
4521 return DXGI_FORMAT_R32G32B32A32_UINT;
4522 case QRhiVertexInputAttribute::UInt3:
4523 return DXGI_FORMAT_R32G32B32_UINT;
4524 case QRhiVertexInputAttribute::UInt2:
4525 return DXGI_FORMAT_R32G32_UINT;
4526 case QRhiVertexInputAttribute::UInt:
4527 return DXGI_FORMAT_R32_UINT;
4528 case QRhiVertexInputAttribute::SInt4:
4529 return DXGI_FORMAT_R32G32B32A32_SINT;
4530 case QRhiVertexInputAttribute::SInt3:
4531 return DXGI_FORMAT_R32G32B32_SINT;
4532 case QRhiVertexInputAttribute::SInt2:
4533 return DXGI_FORMAT_R32G32_SINT;
4534 case QRhiVertexInputAttribute::SInt:
4535 return DXGI_FORMAT_R32_SINT;
4536 case QRhiVertexInputAttribute::Half4:
4538 case QRhiVertexInputAttribute::Half3:
4539 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4540 case QRhiVertexInputAttribute::Half2:
4541 return DXGI_FORMAT_R16G16_FLOAT;
4542 case QRhiVertexInputAttribute::Half:
4543 return DXGI_FORMAT_R16_FLOAT;
4544 case QRhiVertexInputAttribute::UShort4:
4546 case QRhiVertexInputAttribute::UShort3:
4547 return DXGI_FORMAT_R16G16B16A16_UINT;
4548 case QRhiVertexInputAttribute::UShort2:
4549 return DXGI_FORMAT_R16G16_UINT;
4550 case QRhiVertexInputAttribute::UShort:
4551 return DXGI_FORMAT_R16_UINT;
4552 case QRhiVertexInputAttribute::SShort4:
4554 case QRhiVertexInputAttribute::SShort3:
4555 return DXGI_FORMAT_R16G16B16A16_SINT;
4556 case QRhiVertexInputAttribute::SShort2:
4557 return DXGI_FORMAT_R16G16_SINT;
4558 case QRhiVertexInputAttribute::SShort:
4559 return DXGI_FORMAT_R16_SINT;
4562 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4569 case QRhiGraphicsPipeline::Triangles:
4570 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4571 case QRhiGraphicsPipeline::TriangleStrip:
4572 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4573 case QRhiGraphicsPipeline::Lines:
4574 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4575 case QRhiGraphicsPipeline::LineStrip:
4576 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4577 case QRhiGraphicsPipeline::Points:
4578 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4579 case QRhiGraphicsPipeline::Patches:
4580 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4581 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4584 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4591 if (c.testFlag(QRhiGraphicsPipeline::R))
4592 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4593 if (c.testFlag(QRhiGraphicsPipeline::G))
4594 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4595 if (c.testFlag(QRhiGraphicsPipeline::B))
4596 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4597 if (c.testFlag(QRhiGraphicsPipeline::A))
4598 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4611 case QRhiGraphicsPipeline::Zero:
4612 return D3D11_BLEND_ZERO;
4613 case QRhiGraphicsPipeline::One:
4614 return D3D11_BLEND_ONE;
4615 case QRhiGraphicsPipeline::SrcColor:
4616 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4617 case QRhiGraphicsPipeline::OneMinusSrcColor:
4618 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4619 case QRhiGraphicsPipeline::DstColor:
4620 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4621 case QRhiGraphicsPipeline::OneMinusDstColor:
4622 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4623 case QRhiGraphicsPipeline::SrcAlpha:
4624 return D3D11_BLEND_SRC_ALPHA;
4625 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4626 return D3D11_BLEND_INV_SRC_ALPHA;
4627 case QRhiGraphicsPipeline::DstAlpha:
4628 return D3D11_BLEND_DEST_ALPHA;
4629 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4630 return D3D11_BLEND_INV_DEST_ALPHA;
4631 case QRhiGraphicsPipeline::ConstantColor:
4632 case QRhiGraphicsPipeline::ConstantAlpha:
4633 return D3D11_BLEND_BLEND_FACTOR;
4634 case QRhiGraphicsPipeline::OneMinusConstantColor:
4635 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4636 return D3D11_BLEND_INV_BLEND_FACTOR;
4637 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4638 return D3D11_BLEND_SRC_ALPHA_SAT;
4639 case QRhiGraphicsPipeline::Src1Color:
4640 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4641 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4642 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4643 case QRhiGraphicsPipeline::Src1Alpha:
4644 return D3D11_BLEND_SRC1_ALPHA;
4645 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4646 return D3D11_BLEND_INV_SRC1_ALPHA;
4649 return D3D11_BLEND_ZERO;
4656 case QRhiGraphicsPipeline::Add:
4657 return D3D11_BLEND_OP_ADD;
4658 case QRhiGraphicsPipeline::Subtract:
4659 return D3D11_BLEND_OP_SUBTRACT;
4660 case QRhiGraphicsPipeline::ReverseSubtract:
4661 return D3D11_BLEND_OP_REV_SUBTRACT;
4662 case QRhiGraphicsPipeline::Min:
4663 return D3D11_BLEND_OP_MIN;
4664 case QRhiGraphicsPipeline::Max:
4665 return D3D11_BLEND_OP_MAX;
4668 return D3D11_BLEND_OP_ADD;
4675 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4676 keyBuilder.addData(source);
4677 return keyBuilder.result().toHex();
4680QByteArray
QRhiD3D11::compileHlslShaderSource(
const QShader &shader, QShader::Variant shaderVariant, uint flags,
4681 QString *error, QShaderKey *usedShaderKey)
4683 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4684 QShaderCode dxbc = shader.shader(key);
4685 if (!dxbc.shader().isEmpty()) {
4687 *usedShaderKey = key;
4688 return dxbc.shader();
4691 key = { QShader::HlslShader, 50, shaderVariant };
4692 QShaderCode hlslSource = shader.shader(key);
4693 if (hlslSource.shader().isEmpty()) {
4694 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4695 return QByteArray();
4699 *usedShaderKey = key;
4702 switch (shader.stage()) {
4703 case QShader::VertexStage:
4706 case QShader::TessellationControlStage:
4709 case QShader::TessellationEvaluationStage:
4712 case QShader::GeometryStage:
4715 case QShader::FragmentStage:
4718 case QShader::ComputeStage:
4722 qWarning(
"compileHlslShaderSource: Unknown SM 5.0 stage (%d)",
int(shader.stage()));
4723 return QByteArray();
4727 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
4728 cacheKey.sourceHash = sourceHash(hlslSource.shader());
4729 cacheKey.target = target;
4730 cacheKey.entryPoint = hlslSource.entryPoint();
4731 cacheKey.compileFlags = flags;
4732 auto cacheIt = m_bytecodeCache.constFind(cacheKey);
4733 if (cacheIt != m_bytecodeCache.constEnd())
4734 return cacheIt.value();
4737 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
4738 if (d3dCompile ==
nullptr) {
4739 qWarning(
"Unable to resolve function D3DCompile()");
4740 return QByteArray();
4743 ID3DBlob *bytecode =
nullptr;
4744 ID3DBlob *errors =
nullptr;
4745 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
4746 nullptr,
nullptr,
nullptr,
4747 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
4748 if (FAILED(hr) || !bytecode) {
4749 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
4751 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
4752 int(errors->GetBufferSize()));
4755 return QByteArray();
4759 result.resize(
int(bytecode->GetBufferSize()));
4760 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
4761 bytecode->Release();
4763 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
4764 m_bytecodeCache.insert(cacheKey, result);
4775 rhiD->pipelineCreationStart();
4776 if (!rhiD->sanityCheckGraphicsPipeline(
this))
4779 D3D11_RASTERIZER_DESC rastDesc = {};
4780 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
4781 rastDesc.CullMode = toD3DCullMode(m_cullMode);
4782 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
4783 rastDesc.DepthBias = m_depthBias;
4784 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
4785 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
4786 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
4787 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
4788 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
4790 qWarning(
"Failed to create rasterizer state: %s",
4791 qPrintable(QSystemError::windowsComString(hr)));
4795 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
4796 dsDesc.DepthEnable = m_depthTest;
4797 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
4798 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
4799 dsDesc.StencilEnable = m_stencilTest;
4800 if (m_stencilTest) {
4801 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
4802 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
4803 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
4804 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
4805 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
4806 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
4807 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
4808 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
4809 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
4810 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
4812 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
4814 qWarning(
"Failed to create depth-stencil state: %s",
4815 qPrintable(QSystemError::windowsComString(hr)));
4819 D3D11_BLEND_DESC blendDesc = {};
4820 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
4821 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
4822 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
4823 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4824 blend.BlendEnable = b.enable;
4825 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
4826 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
4827 blend.BlendOp = toD3DBlendOp(b.opColor);
4828 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
4829 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
4830 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
4831 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
4832 blendDesc.RenderTarget[i] = blend;
4834 if (m_targetBlends.isEmpty()) {
4835 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
4836 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
4837 blendDesc.RenderTarget[0] = blend;
4839 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
4841 qWarning(
"Failed to create blend state: %s",
4842 qPrintable(QSystemError::windowsComString(hr)));
4846 QByteArray vsByteCode;
4847 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
4848 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
4849 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
4850 switch (shaderStage.type()) {
4851 case QRhiShaderStage::Vertex:
4852 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
4853 vs.shader->AddRef();
4854 vsByteCode = cacheIt->bytecode;
4855 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4857 case QRhiShaderStage::TessellationControl:
4858 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
4859 hs.shader->AddRef();
4860 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4862 case QRhiShaderStage::TessellationEvaluation:
4863 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
4864 ds.shader->AddRef();
4865 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4867 case QRhiShaderStage::Geometry:
4868 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
4869 gs.shader->AddRef();
4870 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4872 case QRhiShaderStage::Fragment:
4873 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
4874 fs.shader->AddRef();
4875 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
4882 QShaderKey shaderKey;
4883 UINT compileFlags = 0;
4884 if (m_flags.testFlag(CompileShadersWithDebugInfo))
4885 compileFlags |= D3DCOMPILE_DEBUG;
4887 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
4888 &error, &shaderKey);
4889 if (bytecode.isEmpty()) {
4890 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
4894 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
4896 rhiD->clearShaderCache();
4899 switch (shaderStage.type()) {
4900 case QRhiShaderStage::Vertex:
4901 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
4903 qWarning(
"Failed to create vertex shader: %s",
4904 qPrintable(QSystemError::windowsComString(hr)));
4907 vsByteCode = bytecode;
4908 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4909 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
4910 vs.shader->AddRef();
4912 case QRhiShaderStage::TessellationControl:
4913 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
4915 qWarning(
"Failed to create hull shader: %s",
4916 qPrintable(QSystemError::windowsComString(hr)));
4919 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4920 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
4921 hs.shader->AddRef();
4923 case QRhiShaderStage::TessellationEvaluation:
4924 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
4926 qWarning(
"Failed to create domain shader: %s",
4927 qPrintable(QSystemError::windowsComString(hr)));
4930 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4931 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
4932 ds.shader->AddRef();
4934 case QRhiShaderStage::Geometry:
4935 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
4937 qWarning(
"Failed to create geometry shader: %s",
4938 qPrintable(QSystemError::windowsComString(hr)));
4941 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4942 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
4943 gs.shader->AddRef();
4945 case QRhiShaderStage::Fragment:
4946 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
4948 qWarning(
"Failed to create pixel shader: %s",
4949 qPrintable(QSystemError::windowsComString(hr)));
4952 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
4953 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
4954 fs.shader->AddRef();
4962 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
4964 if (!vsByteCode.isEmpty()) {
4965 QByteArrayList matrixSliceSemantics;
4966 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
4967 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
4970 D3D11_INPUT_ELEMENT_DESC desc = {};
4975 const int matrixSlice = it->matrixSlice();
4976 if (matrixSlice < 0) {
4977 desc.SemanticName =
"TEXCOORD";
4978 desc.SemanticIndex = UINT(it->location());
4982 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
4983 matrixSliceSemantics.append(sem);
4984 desc.SemanticName = matrixSliceSemantics.last().constData();
4985 desc.SemanticIndex = UINT(matrixSlice);
4987 desc.Format = toD3DAttributeFormat(it->format());
4988 desc.InputSlot = UINT(it->binding());
4989 desc.AlignedByteOffset = it->offset();
4990 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
4991 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
4992 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
4993 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
4995 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
4997 inputDescs.append(desc);
4999 if (!inputDescs.isEmpty()) {
5000 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
5001 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
5003 qWarning(
"Failed to create input layout: %s",
5004 qPrintable(QSystemError::windowsComString(hr)));
5010 rhiD->pipelineCreationEnd();
5012 rhiD->registerResource(
this);
5031 cs.shader->Release();
5032 cs.shader =
nullptr;
5033 cs.nativeResourceBindingMap.clear();
5037 rhiD->unregisterResource(
this);
5046 rhiD->pipelineCreationStart();
5048 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5049 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5050 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5051 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5054 QShaderKey shaderKey;
5055 UINT compileFlags = 0;
5056 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5057 compileFlags |= D3DCOMPILE_DEBUG;
5059 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5060 &error, &shaderKey);
5061 if (bytecode.isEmpty()) {
5062 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5066 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5068 qWarning(
"Failed to create compute shader: %s",
5069 qPrintable(QSystemError::windowsComString(hr)));
5073 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5075 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5078 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
5081 cs.shader->AddRef();
5083 rhiD->pipelineCreationEnd();
5085 rhiD->registerResource(
this);
5110 D3D11_QUERY_DESC queryDesc = {};
5112 if (!disjointQuery[i]) {
5113 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5114 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5116 qWarning(
"Failed to create timestamp disjoint query: %s",
5117 qPrintable(QSystemError::windowsComString(hr)));
5121 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5122 for (
int j = 0; j < 2; ++j) {
5123 const int idx = 2 * i + j;
5125 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5127 qWarning(
"Failed to create timestamp query: %s",
5128 qPrintable(QSystemError::windowsComString(hr)));
5141 if (disjointQuery[i]) {
5142 disjointQuery[i]->Release();
5143 disjointQuery[i] =
nullptr;
5145 for (
int j = 0; j < 2; ++j) {
5148 query[idx]->Release();
5149 query[idx] =
nullptr;
5157 bool result =
false;
5161 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5162 ID3D11Query *tsStart = query[pairIndex * 2];
5163 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5164 quint64 timestamps[2];
5165 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5168 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5169 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5170 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5173 if (!dj.Disjoint && dj.Frequency) {
5174 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5175 *elapsedSec = elapsedMs / 1000.0;
5178 active[pairIndex] =
false;
5187 backBufferTex =
nullptr;
5188 backBufferRtv =
nullptr;
5190 msaaTex[i] =
nullptr;
5191 msaaRtv[i] =
nullptr;
5202 if (backBufferRtv) {
5203 backBufferRtv->Release();
5204 backBufferRtv =
nullptr;
5206 if (backBufferRtvRight) {
5207 backBufferRtvRight->Release();
5208 backBufferRtvRight =
nullptr;
5210 if (backBufferTex) {
5211 backBufferTex->Release();
5212 backBufferTex =
nullptr;
5216 msaaRtv[i]->Release();
5217 msaaRtv[i] =
nullptr;
5220 msaaTex[i]->Release();
5221 msaaTex[i] =
nullptr;
5233 timestamps.destroy();
5235 swapChain->Release();
5236 swapChain =
nullptr;
5239 dcompVisual->Release();
5240 dcompVisual =
nullptr;
5244 dcompTarget->Release();
5245 dcompTarget =
nullptr;
5248 if (frameLatencyWaitableObject) {
5249 CloseHandle(frameLatencyWaitableObject);
5250 frameLatencyWaitableObject =
nullptr;
5253 QDxgiVSyncService::instance()->unregisterWindow(window);
5257 rhiD->unregisterResource(
this);
5260 rhiD->context->Flush();
5276 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5282 return m_window->size() * m_window->devicePixelRatio();
5291 qWarning(
"Attempted to call isFormatSupported() without a window set");
5296 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5297 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5308 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5317 rhiD->registerResource(rpD,
false);
5322 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5324 D3D11_TEXTURE2D_DESC desc = {};
5325 desc.Width = UINT(size.width());
5326 desc.Height = UINT(size.height());
5329 desc.Format = format;
5330 desc.SampleDesc = sampleDesc;
5331 desc.Usage = D3D11_USAGE_DEFAULT;
5332 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5335 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5337 qWarning(
"Failed to create color buffer texture: %s",
5338 qPrintable(QSystemError::windowsComString(hr)));
5342 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5343 rtvDesc.Format = format;
5344 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5345 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5347 qWarning(
"Failed to create color buffer rtv: %s",
5348 qPrintable(QSystemError::windowsComString(hr)));
5362 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5363 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5364 return dcompDevice ?
true :
false;
5376 const bool needsRegistration = !window || window != m_window;
5377 const bool stereo = m_window->format().stereo();
5380 if (window && window != m_window)
5384 m_currentPixelSize = surfacePixelSize();
5385 pixelSize = m_currentPixelSize;
5387 if (pixelSize.isEmpty())
5390 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5395 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5398 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5400 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5401 qPrintable(QSystemError::windowsComString(hr)));
5404 if (dcompTarget && !dcompVisual) {
5405 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5407 qWarning(
"Failed to create DirectComposition visual: %s",
5408 qPrintable(QSystemError::windowsComString(hr)));
5413 if (
window->requestedFormat().alphaBufferSize() <= 0)
5414 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5415 "This may lead to problems.");
5418 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5425 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5426 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5430 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5431 && swapInterval != 0
5432 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5434 if (useFrameLatencyWaitableObject) {
5436 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5440 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5441 colorFormat = DEFAULT_FORMAT;
5442 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5444 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5445 if (m_format != SDR) {
5446 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5449 case HDRExtendedSrgbLinear:
5450 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5451 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5452 srgbAdjustedColorFormat = colorFormat;
5455 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5456 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5457 srgbAdjustedColorFormat = colorFormat;
5466 qWarning(
"The output associated with the window is not HDR capable "
5467 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5477 DXGI_SWAP_CHAIN_DESC1 desc = {};
5478 desc.Width = UINT(pixelSize.width());
5479 desc.Height = UINT(pixelSize.height());
5480 desc.Format = colorFormat;
5481 desc.SampleDesc.Count = 1;
5482 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5484 desc.Flags = swapChainFlags;
5485 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5486 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5487 desc.Stereo = stereo;
5493 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5498 desc.Scaling = DXGI_SCALING_STRETCH;
5501 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5502 IDXGISwapChain1 *sc1;
5505 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5507 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5512 if (FAILED(hr) && m_format != SDR) {
5513 colorFormat = DEFAULT_FORMAT;
5514 desc.Format = DEFAULT_FORMAT;
5516 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5518 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5521 if (SUCCEEDED(hr)) {
5523 IDXGISwapChain3 *sc3 =
nullptr;
5524 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5525 if (m_format != SDR) {
5526 hr = sc3->SetColorSpace1(hdrColorSpace);
5528 qWarning(
"Failed to set color space on swapchain: %s",
5529 qPrintable(QSystemError::windowsComString(hr)));
5531 if (useFrameLatencyWaitableObject) {
5532 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5533 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5537 if (m_format != SDR)
5538 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5539 if (useFrameLatencyWaitableObject) {
5540 IDXGISwapChain2 *sc2 =
nullptr;
5541 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5542 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5543 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5546 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5551 hr = dcompVisual->SetContent(sc1);
5552 if (SUCCEEDED(hr)) {
5553 hr = dcompTarget->SetRoot(dcompVisual);
5555 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5556 qPrintable(QSystemError::windowsComString(hr)));
5559 qWarning(
"Failed to set content for Direct Composition visual: %s",
5560 qPrintable(QSystemError::windowsComString(hr)));
5564 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5567 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5568 qWarning(
"Device loss detected during swapchain creation");
5571 }
else if (FAILED(hr)) {
5572 qWarning(
"Failed to create D3D11 swapchain: %s"
5573 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5574 qPrintable(QSystemError::windowsComString(hr)),
5575 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5576 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5582 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5583 colorFormat, swapChainFlags);
5584 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5585 qWarning(
"Device loss detected in ResizeBuffers()");
5588 }
else if (FAILED(hr)) {
5589 qWarning(
"Failed to resize D3D11 swapchain: %s",
5590 qPrintable(QSystemError::windowsComString(hr)));
5609 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5611 qWarning(
"Failed to query swapchain backbuffer: %s",
5612 qPrintable(QSystemError::windowsComString(hr)));
5615 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5616 rtvDesc.Format = srgbAdjustedColorFormat;
5617 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5618 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5620 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5621 qPrintable(QSystemError::windowsComString(hr)));
5627 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5628 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5629 rtvDesc.Texture2DArray.ArraySize = 1;
5630 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5632 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5633 qPrintable(QSystemError::windowsComString(hr)));
5640 if (sampleDesc.Count > 1) {
5641 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5646 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5647 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5648 m_depthStencil->sampleCount(), m_sampleCount);
5650 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5651 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5652 m_depthStencil->setPixelSize(pixelSize);
5653 if (!m_depthStencil->create())
5654 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5655 pixelSize.width(), pixelSize.height());
5657 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5658 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5659 pixelSize.width(), pixelSize.height());
5666 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5668 rt.setRenderPassDescriptor(m_renderPassDesc);
5670 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5671 rtD->d.pixelSize = pixelSize;
5672 rtD->d.dpr =
float(
window->devicePixelRatio());
5673 rtD->d.sampleCount =
int(sampleDesc.Count);
5674 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5677 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5678 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5679 rtD->d.pixelSize = pixelSize;
5680 rtD->d.dpr =
float(
window->devicePixelRatio());
5681 rtD->d.sampleCount =
int(sampleDesc.Count);
5682 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
5685 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
5686 timestamps.prepare(rhiD);
5690 QDxgiVSyncService::instance()->registerWindow(window);
5692 if (needsRegistration)
5693 rhiD->registerResource(
this);
5701 if (rtViews.dsv != currentRtViews.dsv) {
5702 rtViews.dsv = currentRtViews.dsv;
5706 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
5707 rtViews.rtv[i] = currentRtViews.rtv[i];
5709 rtViews.colorAttCount = currentRtViews.colorAttCount;
5711 ret |= rtViews.rtv[i] !=
nullptr;
5712 rtViews.rtv[i] =
nullptr;
5714 for (
int i = 0; i < count; i++) {
5715 ret |= uav[i] != uavs[i];
5719 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
const char * constData() const
int gsHighestActiveSrvBinding
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int dsHighestActiveSrvBinding
bool isYUpInNDC() const override
void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
QRhiSwapChain * createSwapChain() override
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
bool isFeatureSupported(QRhi::Feature feature) const override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
bool isDeviceLost() const override
bool vsHasIndexBufferBound
void executeBufferHostWrites(QD3D11Buffer *bufD)
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
QRhiStats statistics() override
QList< QSize > supportedShadingRates(int sampleCount) const override
QRhiComputePipeline * createComputePipeline() override
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override
QRhi::FrameOpResult finish() override
void setVertexInput(QRhiCommandBuffer *cb, int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat) override
QRhiGraphicsPipeline * createGraphicsPipeline() override
QRhiShaderResourceBindings * createShaderResourceBindings() override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QList< int > supportedSampleCounts() const override
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
void resetShaderResources(QD3D11CommandBuffer *cbD, QD3D11RenderTargetUavUpdateState *rtUavState)
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
bool isYUpInFramebuffer() const override
int resourceLimit(QRhi::ResourceLimit limit) const override
void beginExternal(QRhiCommandBuffer *cb) override
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void setPipelineCacheData(const QByteArray &data) override
void executeCommandBuffer(QD3D11CommandBuffer *cbD)
void debugMarkEnd(QRhiCommandBuffer *cb) override
void releaseCachedResources() override
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
bool importedDeviceAndContext
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
bool supportsAllowTearing
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
void endExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
QRhiShadingRateMap * createShadingRateMap() override
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
bool useLegacySwapchainModel
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
bool makeThreadLocalNativeContextCurrent() override
bool create(QRhi::Flags flags) override
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
static void applyDynamicOffsets(UINT *offsets, int batchIndex, const QRhiBatchedBindings< UINT > *originalBindings, const QRhiBatchedBindings< UINT > *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount)
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
#define SETUAVBATCH(stagePrefixL, stagePrefixU)
static QByteArray sourceHash(const QByteArray &source)
#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
static const int RBM_HULL
static uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
static std::pair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
static const int RBM_FRAGMENT
#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
Int aligned(Int v, Int byteAlign)
\variable QRhiVulkanQueueSubmitParams::waitSemaphoreCount
static DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
static D3D11_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f, bool rgb)
static const int RBM_VERTEX
static D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
#define D3D11_1_UAV_SLOT_COUNT
static const int RBM_DOMAIN
static D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
static QD3D11RenderTargetData * rtData(QRhiRenderTarget *rt)
static UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
static D3D11_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
void releasePipelineShader(T &s)
static D3D11_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
static DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
static const int RBM_GEOMETRY
static D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
static IDXGIFactory1 * createDXGIFactory2()
static D3D11_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
static bool isDepthTextureFormat(QRhiTexture::Format format)
static const int RBM_COMPUTE
static D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
#define SETSHADER(StageL, StageU)
static DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
static const DXGI_FORMAT DEFAULT_FORMAT
static uint clampedResourceCount(uint startSlot, int countSlots, uint maxSlots, const char *resType)
#define D3D11_VS_INPUT_REGISTER_COUNT
#define DXGI_ADAPTER_FLAG_SOFTWARE
\variable QRhiD3D11NativeHandles::dev
static QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
static D3D11_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
static DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
static const int RBM_SUPPORTED_STAGES
bool hasPendingDynamicUpdates
void endFullDynamicBufferUpdateForCurrentFrame() override
To be called when the entire contents of the buffer data has been updated in the memory block returne...
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
char * beginFullDynamicBufferUpdateForCurrentFrame() override
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiBuffer::NativeBuffer nativeBuffer() override
ID3D11UnorderedAccessView * unorderedAccessView(quint32 offset)
static const int MAX_DYNAMIC_OFFSET_COUNT
static const int MAX_VERTEX_BUFFER_BINDING_COUNT
int retainResourceBatches(const QD3D11ShaderResourceBindings::ResourceBatches &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ComputePipeline(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11GraphicsPipeline(QRhiImplementation *rhi)
~QD3D11GraphicsPipeline()
bool create() override
Creates the corresponding native graphics resources.
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags, QRhiTexture::Format backingFormatHint)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool create() override
Creates the corresponding native graphics resources.
QRhiTexture::Format backingFormat() const override
QD3D11RenderPassDescriptor(QRhiImplementation *rhi)
~QD3D11RenderPassDescriptor()
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool isCompatible(const QRhiRenderPassDescriptor *other) const override
QVector< quint32 > serializedFormat() const override
static const int MAX_COLOR_ATTACHMENTS
bool update(const QD3D11RenderTargetData::Views ¤tRtViews, ID3D11UnorderedAccessView *const *uavs=nullptr, int count=0)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
QD3D11GraphicsPipeline * lastUsedGraphicsPipeline
bool create() override
Creates the corresponding resource binding set.
~QD3D11ShaderResourceBindings()
void updateResources(UpdateFlags flags) override
QD3D11ComputePipeline * lastUsedComputePipeline
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
int sampleCount() const override
~QD3D11SwapChainRenderTarget()
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
float devicePixelRatio() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QSize pixelSize() const override
bool prepare(QRhiD3D11 *rhiD)
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
bool active[TIMESTAMP_PAIRS]
static const int TIMESTAMP_PAIRS
QRhiSwapChainHdrInfo hdrInfo() override
\variable QRhiSwapChainHdrInfo::limitsType
int lastFrameLatencyWaitSlot
QRhiRenderTarget * currentFrameRenderTarget() override
QD3D11SwapChain(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
QSize surfacePixelSize() override
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc, ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
static const int BUFFER_COUNT
bool isFormatSupported(Format f) override
QRhiCommandBuffer * currentFrameCommandBuffer() override
int currentTimestampPairIndex
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
QSize pixelSize() const override
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
float devicePixelRatio() const override
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
~QD3D11TextureRenderTarget()
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
ID3D11UnorderedAccessView * unorderedAccessViewForLevel(int level)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h