11#include <QtCore/qcryptographichash.h>
12#include <QtCore/qendian.h>
13#include <QtCore/private/qsystemerror_p.h>
20using namespace Qt::StringLiterals;
23
24
25
26
27
28
29
30
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
76
77
80
81
82
83
84
88
89
90
91
92
93
94
95
96
97
98
99
102
103
104
105
106
107
108
109
112
113
114
115
116
117
118
121
122
123
124
125
126
127
128
131
132
133
134
135
136
139
140
141
142
143
144
147#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
148#define DXGI_ADAPTER_FLAG_SOFTWARE 2
151#ifndef D3D11_1_UAV_SLOT_COUNT
152#define D3D11_1_UAV_SLOT_COUNT 64
155#ifndef D3D11_VS_INPUT_REGISTER_COUNT
156#define D3D11_VS_INPUT_REGISTER_COUNT 32
165 if (importParams->dev && importParams->context) {
166 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
167 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
168 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
173 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
176 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
177 adapterLuid.LowPart = importParams->adapterLuidLow;
178 adapterLuid.HighPart = importParams->adapterLuidHigh;
185 return (v + byteAlign - 1) & ~(byteAlign - 1);
190 IDXGIFactory1 *result =
nullptr;
191 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
193 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
194 qPrintable(QSystemError::windowsComString(hr)));
206 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
208 dxgiFactory = createDXGIFactory2();
216 IDXGIFactory5 *factory5 =
nullptr;
217 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
218 BOOL allowTearing =
false;
219 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
224 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
225 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
233 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
234 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
239 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
243 if (maxFrameLatency == 0)
244 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
246 activeAdapter =
nullptr;
249 IDXGIAdapter1 *adapter;
250 int requestedAdapterIndex = -1;
251 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
252 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
254 if (requestedRhiAdapter)
255 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
258 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
259 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
260 DXGI_ADAPTER_DESC1 desc;
261 adapter->GetDesc1(&desc);
263 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
264 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
266 requestedAdapterIndex = adapterIndex;
272 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
273 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
274 DXGI_ADAPTER_DESC1 desc;
275 adapter->GetDesc1(&desc);
278 requestedAdapterIndex = adapterIndex;
284 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
285 DXGI_ADAPTER_DESC1 desc;
286 adapter->GetDesc1(&desc);
287 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
288 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
294 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
295 activeAdapter = adapter;
296 adapterLuid = desc.AdapterLuid;
298 qCDebug(QRHI_LOG_INFO,
" using this adapter");
303 if (!activeAdapter) {
304 qWarning(
"No adapter");
310 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
311 bool requestFeatureLevels =
false;
313 requestFeatureLevels =
true;
314 requestedFeatureLevels.append(featureLevel);
317 ID3D11DeviceContext *ctx =
nullptr;
318 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
319 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
320 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
322 &dev, &featureLevel, &ctx);
324 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
325 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
326 "Attempting to create D3D11 device without it.");
327 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
328 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
329 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
330 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
332 &dev, &featureLevel, &ctx);
335 qWarning(
"Failed to create D3D11 device and context: %s",
336 qPrintable(QSystemError::windowsComString(hr)));
340 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
343 qWarning(
"ID3D11DeviceContext1 not supported");
349 ID3D11VertexShader *testShader =
nullptr;
350 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
351 testShader->Release();
353 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
354 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
355 qCDebug(QRHI_LOG_INFO,
"%s", msg);
361 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
362 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
366 if (!features.ConstantBufferOffsetting) {
367 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
368 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
369 qCDebug(QRHI_LOG_INFO,
"%s", msg);
375 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
376 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
377 qCDebug(QRHI_LOG_INFO,
"%s", msg);
383 Q_ASSERT(dev && context);
384 featureLevel = dev->GetFeatureLevel();
385 IDXGIDevice *dxgiDev =
nullptr;
386 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
387 IDXGIAdapter *adapter =
nullptr;
388 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
389 IDXGIAdapter1 *adapter1 =
nullptr;
390 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
391 DXGI_ADAPTER_DESC1 desc;
392 adapter1->GetDesc1(&desc);
393 adapterLuid = desc.AdapterLuid;
395 activeAdapter = adapter1;
401 if (!activeAdapter) {
402 qWarning(
"Failed to query adapter from imported device");
405 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
408 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
410 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
411 annotations =
nullptr;
415 nativeHandlesStruct.dev = dev;
416 nativeHandlesStruct.context = context;
417 nativeHandlesStruct.featureLevel = featureLevel;
418 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
419 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
426 for (
const Shader &s : std::as_const(m_shaderCache))
429 m_shaderCache.clear();
438 if (pushConstantBuffer) {
439 pushConstantBuffer->Release();
440 pushConstantBuffer =
nullptr;
443 if (ofr.tsDisjointQuery) {
444 ofr.tsDisjointQuery->Release();
445 ofr.tsDisjointQuery =
nullptr;
447 for (
int i = 0; i < 2; ++i) {
448 if (ofr.tsQueries[i]) {
449 ofr.tsQueries[i]->Release();
450 ofr.tsQueries[i] =
nullptr;
455 annotations->Release();
456 annotations =
nullptr;
471 dcompDevice->Release();
472 dcompDevice =
nullptr;
476 activeAdapter->Release();
477 activeAdapter =
nullptr;
481 dxgiFactory->Release();
482 dxgiFactory =
nullptr;
485 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
495 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
496 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
501QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
503 LUID requestedLuid = {};
505 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
506 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
507 if (adapterLuid.LowPart || adapterLuid.HighPart)
508 requestedLuid = adapterLuid;
511 IDXGIFactory1 *dxgi = createDXGIFactory2();
515 QRhi::AdapterList list;
516 IDXGIAdapter1 *adapter;
517 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
518 DXGI_ADAPTER_DESC1 desc;
519 adapter->GetDesc1(&desc);
521 if (requestedLuid.LowPart || requestedLuid.HighPart) {
522 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
523 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
528 QD3D11Adapter *a =
new QD3D11Adapter;
529 a->luid = desc.AdapterLuid;
530 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
545 return { 1, 2, 4, 8 };
550 Q_UNUSED(sampleCount);
551 return { QSize(1, 1) };
556 DXGI_SAMPLE_DESC desc;
560 const int s = effectiveSampleCount(sampleCount);
562 desc.Count = UINT(s);
564 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
573 return new QD3D11SwapChain(
this);
576QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
578 return new QD3D11Buffer(
this, type, usage, size);
606 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
607 0.0f, 1.0f, 0.0f, 0.0f,
608 0.0f, 0.0f, 0.5f, 0.5f,
609 0.0f, 0.0f, 0.0f, 1.0f);
617 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
626 case QRhi::MultisampleTexture:
628 case QRhi::MultisampleRenderBuffer:
630 case QRhi::DebugMarkers:
631 return annotations !=
nullptr;
632 case QRhi::Timestamps:
634 case QRhi::Instancing:
636 case QRhi::CustomInstanceStepRate:
638 case QRhi::PrimitiveRestart:
640 case QRhi::NonDynamicUniformBuffers:
642 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
644 case QRhi::NPOTTextureRepeat:
646 case QRhi::RedOrAlpha8IsRed:
648 case QRhi::ElementIndexUint:
653 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
654 case QRhi::FragmentStoresAndAtomics:
655 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
656 case QRhi::WideLines:
658 case QRhi::VertexShaderPointSize:
660 case QRhi::BaseVertex:
662 case QRhi::BaseInstance:
664 case QRhi::TriangleFanTopology:
666 case QRhi::ReadBackNonUniformBuffer:
668 case QRhi::ReadBackNonBaseMipLevel:
670 case QRhi::TexelFetch:
672 case QRhi::RenderToNonBaseMipLevel:
674 case QRhi::IntAttributes:
676 case QRhi::ScreenSpaceDerivatives:
678 case QRhi::ReadBackAnyTextureFormat:
680 case QRhi::PipelineCacheDataLoadSave:
682 case QRhi::ImageDataStride:
684 case QRhi::RenderBufferImport:
686 case QRhi::ThreeDimensionalTextures:
688 case QRhi::RenderTo3DTextureSlice:
690 case QRhi::TextureArrays:
692 case QRhi::Tessellation:
694 case QRhi::GeometryShader:
696 case QRhi::TextureArrayRange:
698 case QRhi::NonFillPolygonMode:
700 case QRhi::OneDimensionalTextures:
702 case QRhi::OneDimensionalTextureMipmaps:
704 case QRhi::HalfAttributes:
706 case QRhi::RenderToOneDimensionalTexture:
708 case QRhi::ThreeDimensionalTextureMipmaps:
710 case QRhi::MultiView:
712 case QRhi::TextureViewFormat:
714 case QRhi::ResolveDepthStencil:
716 case QRhi::VariableRateShading:
718 case QRhi::VariableRateShadingMap:
719 case QRhi::VariableRateShadingMapWithTexture:
721 case QRhi::PerRenderTargetBlending:
722 case QRhi::SampleVariables:
724 case QRhi::InstanceIndexIncludesBaseInstance:
726 case QRhi::DepthClamp:
728 case QRhi::DrawIndirect:
729 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
730 case QRhi::DrawIndirectMulti:
731 case QRhi::ShaderDrawParameters:
733 case QRhi::PushConstants:
735 case QRhi::DrawIndirectCount:
737 case QRhi::DispatchIndirect:
738 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
739 case QRhi::BufferToBufferCopy:
741 case QRhi::StaticBuffersOnGpuTimeline:
752 case QRhi::TextureSizeMin:
754 case QRhi::TextureSizeMax:
755 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
756 case QRhi::MaxColorAttachments:
758 case QRhi::FramesInFlight:
764 case QRhi::MaxAsyncReadbackFrames:
766 case QRhi::MaxThreadGroupsPerDimension:
767 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
768 case QRhi::MaxThreadsPerThreadGroup:
769 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
770 case QRhi::MaxThreadGroupX:
771 return D3D11_CS_THREAD_GROUP_MAX_X;
772 case QRhi::MaxThreadGroupY:
773 return D3D11_CS_THREAD_GROUP_MAX_Y;
774 case QRhi::MaxThreadGroupZ:
775 return D3D11_CS_THREAD_GROUP_MAX_Z;
776 case QRhi::TextureArraySizeMax:
777 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
778 case QRhi::MaxUniformBufferRange:
780 case QRhi::MaxVertexInputs:
782 case QRhi::MaxVertexOutputs:
783 return D3D11_VS_OUTPUT_REGISTER_COUNT;
784 case QRhi::MaxVertexStorageBuffers:
786 case QRhi::MaxPushConstantsSize:
788 return int(MAX_PUSH_CONSTANTS_SIZE);
789 case QRhi::MaxFragmentStorageBuffers:
790 return featureLevel >= D3D_FEATURE_LEVEL_11_1
792 case QRhi::ShadingRateImageTileSize:
802 return &nativeHandlesStruct;
807 return driverInfoStruct;
813 result.totalPipelineCreationTime = totalPipelineCreationTime();
823void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
831 m_bytecodeCache.clear();
851 if (m_bytecodeCache.data.isEmpty())
855 memset(&header, 0,
sizeof(header));
856 header.rhiId = pipelineCacheRhiId();
857 header.arch = quint32(
sizeof(
void*));
858 header.count = m_bytecodeCache.data.count();
860 const size_t dataOffset =
sizeof(header);
862 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
864 QByteArray bytecode = it.value();
866 sizeof(quint32) + key.sourceHash.size()
867 +
sizeof(quint32) + key.target.size()
868 +
sizeof(quint32) + key.entryPoint.size()
870 +
sizeof(quint32) + bytecode.size();
873 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
874 char *p = buf.data() + dataOffset;
875 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
877 QByteArray bytecode = it.value();
879 quint32 i = key.sourceHash.size();
882 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
883 p += key.sourceHash.size();
885 i = key.target.size();
888 memcpy(p, key.target.constData(), key.target.size());
889 p += key.target.size();
891 i = key.entryPoint.size();
894 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
895 p += key.entryPoint.size();
904 memcpy(p, bytecode.constData(), bytecode.size());
905 p += bytecode.size();
907 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
909 header.dataSize = quint32(dataSize);
910 memcpy(buf.data(), &header,
sizeof(header));
921 if (data.size() < qsizetype(headerSize)) {
922 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
925 const size_t dataOffset = headerSize;
927 memcpy(&header, data.constData(), headerSize);
929 const quint32 rhiId = pipelineCacheRhiId();
930 if (header.rhiId != rhiId) {
931 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
932 rhiId, header.rhiId);
935 const quint32 arch = quint32(
sizeof(
void*));
936 if (header.arch != arch) {
937 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
941 if (header.count == 0)
944 if (quint64(data.size()) < quint64(dataOffset) + header.dataSize) {
945 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
949 m_bytecodeCache.clear();
952 for (quint32 i = 0; i < header.count; ++i) {
956 if (!reader.readByteArray(&cacheKey.sourceHash)
957 || !reader.readByteArray(&cacheKey.target)
958 || !reader.readByteArray(&cacheKey.entryPoint)
959 || !reader.readUInt32(&flags)
960 || !reader.readByteArray(&bytecode))
962 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob (truncated or corrupt bytecode data)");
963 m_bytecodeCache.clear();
968 m_bytecodeCache.insertWithCapacityLimit(cacheKey, bytecode);
971 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.data.count()));
974QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
975 int sampleCount, QRhiRenderBuffer::Flags flags,
976 QRhiTexture::Format backingFormatHint)
978 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
982 const QSize &pixelSize,
int depth,
int arraySize,
983 int sampleCount, QRhiTexture::Flags flags)
985 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
989 QRhiSampler::Filter mipmapMode,
990 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
992 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
996 QRhiTextureRenderTarget::Flags flags)
1008 return new QD3D11GraphicsPipeline(
this);
1013 return new QD3D11ComputePipeline(
this);
1018 return new QD3D11ShaderResourceBindings(
this);
1028 if (pipelineChanged) {
1029 cbD->currentGraphicsPipeline = ps;
1030 cbD->currentComputePipeline =
nullptr;
1035 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1036 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1037 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1038 cmd.args.bindGraphicsPipeline.stencilRef = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesStencilRef)
1039 ? cbD->currentStencilRef : 0;
1040 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1041 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1042 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1043 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1044 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1045 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1046 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1061 case QRhiShaderStage::Vertex:
1063 case QRhiShaderStage::TessellationControl:
1065 case QRhiShaderStage::TessellationEvaluation:
1067 case QRhiShaderStage::Geometry:
1068 return RBM_GEOMETRY;
1069 case QRhiShaderStage::Fragment:
1070 return RBM_FRAGMENT;
1071 case QRhiShaderStage::Compute:
1082 const QList<QShaderDescription::PushConstantBlock> blocks = shader.description().pushConstantBlocks();
1083 if (blocks.isEmpty())
1085 *reg = shader.nativeShaderInfo(key).extraBufferBindings.value(QShaderPrivate::HlslPushConstantBufferBinding, -1);
1086 *size = quint32((blocks.first().size + 3) & ~3);
1090 int dynamicOffsetCount,
1091 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1100 srb = gfxPsD->m_shaderResourceBindings;
1102 srb = compPsD->m_shaderResourceBindings;
1107 bool pipelineChanged =
false;
1116 bool srbUpdate =
false;
1117 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1118 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1120 switch (b->type()) {
1121 case QRhiShaderResourceBinding::UniformBuffer:
1125 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1126 sanityCheckResourceOwnership(bufD);
1130 if (bufD
->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1132 bd.ubuf.id = bufD->m_id;
1137 case QRhiShaderResourceBinding::SampledTexture:
1138 case QRhiShaderResourceBinding::Texture:
1139 case QRhiShaderResourceBinding::Sampler:
1141 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex();
1142 if (bd.stex.d.size() != data->count()) {
1143 bd.stex.d.resize(data->count());
1146 for (
int elem = 0; elem < data->count(); ++elem) {
1152 Q_ASSERT(texD || samplerD);
1153 sanityCheckResourceOwnership(texD);
1154 sanityCheckResourceOwnership(samplerD);
1155 const quint64 texId = texD ? texD->m_id : 0;
1157 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1158 const uint samplerGen = samplerD ? samplerD
->generation : 0;
1159 if (texGen != bd.stex.d[elem].texGeneration
1160 || texId != bd.stex.d[elem].texId
1161 || samplerGen != bd.stex.d[elem].samplerGeneration
1162 || samplerId != bd.stex.d[elem].samplerId)
1165 bd.stex.d[elem].texId = texId;
1166 bd.stex.d[elem].texGeneration = texGen;
1167 bd.stex.d[elem].samplerId = samplerId;
1168 bd.stex.d[elem].samplerGeneration = samplerGen;
1173 case QRhiShaderResourceBinding::ImageLoad:
1174 case QRhiShaderResourceBinding::ImageStore:
1175 case QRhiShaderResourceBinding::ImageLoadStore:
1178 sanityCheckResourceOwnership(texD);
1179 if (texD
->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1181 bd.simage.id = texD->m_id;
1186 case QRhiShaderResourceBinding::BufferLoad:
1187 case QRhiShaderResourceBinding::BufferStore:
1188 case QRhiShaderResourceBinding::BufferLoadStore:
1191 sanityCheckResourceOwnership(bufD);
1192 if (bufD
->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1194 bd.sbuf.id = bufD->m_id;
1205 if (srbUpdate || pipelineChanged) {
1207 memset(resBindMaps, 0,
sizeof(resBindMaps));
1208 uint pushConstantStages = 0;
1210 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1211 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1212 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1213 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1214 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1215 pushConstantStages = gfxPsD->pushConstants.stages;
1217 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1218 if (compPsD->pushConstants.reg >= 0 && compPsD->pushConstants.size)
1221 updateShaderResourceBindings(srbD, resBindMaps, pushConstantStages);
1224 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1227 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1229 cbD->currentGraphicsSrb = srb;
1230 cbD->currentComputeSrb =
nullptr;
1232 cbD->currentGraphicsSrb =
nullptr;
1233 cbD->currentComputeSrb = srb;
1242 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1243 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1246 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1247 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1248 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1249 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1250 const uint binding = uint(dynOfs.first);
1251 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1252 const quint32 offsetInConstants = dynOfs.second / 16;
1254 *p++ = offsetInConstants;
1257 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1265 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1266 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1271 bool needsBindVBuf =
false;
1272 for (
int i = 0; i < bindingCount; ++i) {
1273 const int inputSlot = startBinding + i;
1275 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1276 if (bufD->m_type == QRhiBuffer::Dynamic)
1279 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1280 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1282 needsBindVBuf =
true;
1283 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1284 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1288 if (needsBindVBuf) {
1291 cmd.args.bindVertexBuffers.startSlot = startBinding;
1293 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1297 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1299 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1300 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1301 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1303 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1304 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1305 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1311 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1312 if (ibufD->m_type == QRhiBuffer::Dynamic)
1315 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1316 : DXGI_FORMAT_R32_UINT;
1317 if (cbD->currentIndexBuffer != ibufD->buffer
1318 || cbD->currentIndexOffset != indexOffset
1319 || cbD->currentIndexFormat != dxgiFormat)
1321 cbD->currentIndexBuffer = ibufD->buffer;
1322 cbD->currentIndexOffset = indexOffset;
1323 cbD->currentIndexFormat = dxgiFormat;
1327 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1328 cmd.args.bindIndexBuffer.offset = indexOffset;
1329 cmd.args.bindIndexBuffer.format = dxgiFormat;
1338 Q_ASSERT(cbD->currentTarget);
1339 const QSize outputSize = cbD->currentTarget->pixelSize();
1343 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1348 cmd.args.viewport.x = x;
1349 cmd.args.viewport.y = y;
1350 cmd.args.viewport.w = w;
1351 cmd.args.viewport.h = h;
1352 cmd.args.viewport.d0 = viewport.minDepth();
1353 cmd.args.viewport.d1 = viewport.maxDepth();
1360 Q_ASSERT(cbD->currentTarget);
1361 const QSize outputSize = cbD->currentTarget->pixelSize();
1365 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1370 cmd.args.scissor.x = x;
1371 cmd.args.scissor.y = y;
1372 cmd.args.scissor.w = w;
1373 cmd.args.scissor.h = h;
1384 cmd.args.blendConstants.c[0] =
float(c.redF());
1385 cmd.args.blendConstants.c[1] =
float(c.greenF());
1386 cmd.args.blendConstants.c[2] =
float(c.blueF());
1387 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1398 cmd.args.stencilRef.ref = refValue;
1399 cbD->currentStencilRef = refValue;
1408 quint32 blockSize = 0;
1414 reg = psD->pushConstants.reg;
1415 blockSize = psD->pushConstants.size;
1421 reg = psD->pushConstants.reg;
1422 blockSize = psD->pushConstants.size;
1423 stages = psD->pushConstants.stages;
1425 if (reg < 0 || !blockSize || !stages) {
1426 qWarning(
"No pipeline with a push constant block is active; setPushConstants ignored");
1430 if (offset + size > MAX_PUSH_CONSTANTS_SIZE) {
1431 qWarning(
"Push constant data of %u bytes at offset %u exceeds the %u byte maximum; "
1432 "setPushConstants ignored", size, offset, MAX_PUSH_CONSTANTS_SIZE);
1441 const quint32 total = qMin(qMax(blockSize, offset + size), MAX_PUSH_CONSTANTS_SIZE);
1442 if (quint32(cbD->pushConstantData.size()) < total)
1443 cbD->pushConstantData.resize(
int(total), 0);
1444 memcpy(cbD->pushConstantData.data() + offset, data, size);
1446 const quint32 dataOffset = quint32(cbD->pushConstantPool.size());
1447 cbD->pushConstantPool.append(cbD->pushConstantData.constData(), total);
1451 cmd.args.setPushConstants.buffer = pushConstantBuffer;
1452 cmd.args.setPushConstants.dataOffset = dataOffset;
1453 cmd.args.setPushConstants.size = total;
1454 cmd.args.setPushConstants.startSlot = uint(reg);
1455 cmd.args.setPushConstants.stages = stages;
1460 if (pushConstantBuffer)
1463 D3D11_BUFFER_DESC desc = {};
1464 desc.ByteWidth = aligned(MAX_PUSH_CONSTANTS_SIZE, 256u);
1465 desc.Usage = D3D11_USAGE_DYNAMIC;
1466 desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1467 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1468 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &pushConstantBuffer);
1470 qWarning(
"Failed to create push constant buffer: %s",
1471 qPrintable(QSystemError::windowsComString(hr)));
1472 pushConstantBuffer =
nullptr;
1481 Q_UNUSED(coarsePixelSize);
1485 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1492 cmd.args.draw.vertexCount = vertexCount;
1493 cmd.args.draw.instanceCount = instanceCount;
1494 cmd.args.draw.firstVertex = firstVertex;
1495 cmd.args.draw.firstInstance = firstInstance;
1499 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1506 cmd.args.drawIndexed.indexCount = indexCount;
1507 cmd.args.drawIndexed.instanceCount = instanceCount;
1508 cmd.args.drawIndexed.firstIndex = firstIndex;
1509 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1510 cmd.args.drawIndexed.firstInstance = firstInstance;
1514 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1521 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1522 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1523 cmd.args.drawIndirect.drawCount = drawCount;
1524 cmd.args.drawIndirect.stride = stride;
1529 switch (rt->resourceType()) {
1530 case QRhiResource::SwapChainRenderTarget:
1531 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1532 case QRhiResource::TextureRenderTarget:
1533 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1541 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1548 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1549 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1550 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1551 cmd.args.drawIndexedIndirect.stride = stride;
1556 if (!debugMarkers || !annotations)
1562 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1567 if (!debugMarkers || !annotations)
1577 if (!debugMarkers || !annotations)
1583 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1602 Q_ASSERT(cbD->commands.isEmpty());
1604 if (cbD->currentTarget) {
1608 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1623 return QRhi::FrameOpDeviceLost;
1626 contextState.currentSwapChain = swapChainD;
1630 if (swapChainD->frameLatencyWaitableObject) {
1633 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1638 swapChainD->cb.resetState();
1640 swapChainD->rt.d.views.setFrom(1,
1641 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1642 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1647 double elapsedSec = 0;
1649 swapChainD->cb.lastGpuTime = elapsedSec;
1658 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1659 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1660 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1661 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1663 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1665 return QRhi::FrameOpSuccess;
1671 Q_ASSERT(contextState.currentSwapChain = swapChainD);
1676 cmd.args.endFrame.tsQuery =
nullptr;
1677 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1682 if (swapChainD->sampleDesc.Count > 1) {
1683 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1684 swapChainD->msaaTex[currentFrameSlot], 0,
1685 swapChainD->colorFormat);
1692 if (recordTimestamps) {
1693 context->End(tsEnd);
1694 context->End(tsDisjoint);
1699 if (!flags.testFlag(QRhi::SkipPresent)) {
1700 UINT presentFlags = 0;
1701 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1702 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1703 if (!swapChainD->swapChain) {
1704 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1705 return QRhi::FrameOpError;
1707 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1708 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1709 qWarning(
"Device loss detected in Present()");
1711 return QRhi::FrameOpDeviceLost;
1712 }
else if (FAILED(hr)) {
1713 qWarning(
"Failed to present: %s",
1714 qPrintable(QSystemError::windowsComString(hr)));
1715 return QRhi::FrameOpError;
1718 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1719 dcompDevice->Commit();
1728 contextState.currentSwapChain =
nullptr;
1730 return QRhi::FrameOpSuccess;
1738 ofr.cbWrapper.resetState();
1739 *cb = &ofr.cbWrapper;
1741 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1742 D3D11_QUERY_DESC queryDesc = {};
1743 if (!ofr.tsDisjointQuery) {
1744 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1745 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1747 qWarning(
"Failed to create timestamp disjoint query: %s",
1748 qPrintable(QSystemError::windowsComString(hr)));
1749 return QRhi::FrameOpError;
1752 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1753 for (
int i = 0; i < 2; ++i) {
1754 if (!ofr.tsQueries[i]) {
1755 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1757 qWarning(
"Failed to create timestamp query: %s",
1758 qPrintable(QSystemError::windowsComString(hr)));
1759 return QRhi::FrameOpError;
1767 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1768 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1769 cmd.args.beginFrame.swapchainRtv =
nullptr;
1770 cmd.args.beginFrame.swapchainDsv =
nullptr;
1772 return QRhi::FrameOpSuccess;
1782 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1783 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1790 if (ofr.tsQueries[0]) {
1791 quint64 timestamps[2];
1792 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1796 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1797 }
while (hr == S_FALSE);
1800 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1801 }
while (hr == S_FALSE);
1804 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1805 }
while (hr == S_FALSE);
1808 if (!dj.Disjoint && dj.Frequency) {
1809 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1810 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1815 return QRhi::FrameOpSuccess;
1820 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1822 case QRhiTexture::RGBA8:
1823 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1824 case QRhiTexture::BGRA8:
1825 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1826 case QRhiTexture::R8:
1827 return DXGI_FORMAT_R8_UNORM;
1828 case QRhiTexture::R8SI:
1829 return DXGI_FORMAT_R8_SINT;
1830 case QRhiTexture::R8UI:
1831 return DXGI_FORMAT_R8_UINT;
1832 case QRhiTexture::RG8:
1833 return DXGI_FORMAT_R8G8_UNORM;
1834 case QRhiTexture::R16:
1835 return DXGI_FORMAT_R16_UNORM;
1836 case QRhiTexture::RG16:
1837 return DXGI_FORMAT_R16G16_UNORM;
1838 case QRhiTexture::RED_OR_ALPHA8:
1839 return DXGI_FORMAT_R8_UNORM;
1841 case QRhiTexture::RGBA16F:
1842 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1843 case QRhiTexture::RGBA32F:
1844 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1845 case QRhiTexture::R16F:
1846 return DXGI_FORMAT_R16_FLOAT;
1847 case QRhiTexture::R32F:
1848 return DXGI_FORMAT_R32_FLOAT;
1850 case QRhiTexture::RGB10A2:
1851 return DXGI_FORMAT_R10G10B10A2_UNORM;
1853 case QRhiTexture::R32SI:
1854 return DXGI_FORMAT_R32_SINT;
1855 case QRhiTexture::R32UI:
1856 return DXGI_FORMAT_R32_UINT;
1857 case QRhiTexture::RG32SI:
1858 return DXGI_FORMAT_R32G32_SINT;
1859 case QRhiTexture::RG32UI:
1860 return DXGI_FORMAT_R32G32_UINT;
1861 case QRhiTexture::RGBA32SI:
1862 return DXGI_FORMAT_R32G32B32A32_SINT;
1863 case QRhiTexture::RGBA32UI:
1864 return DXGI_FORMAT_R32G32B32A32_UINT;
1866 case QRhiTexture::D16:
1867 return DXGI_FORMAT_R16_TYPELESS;
1868 case QRhiTexture::D24:
1869 return DXGI_FORMAT_R24G8_TYPELESS;
1870 case QRhiTexture::D24S8:
1871 return DXGI_FORMAT_R24G8_TYPELESS;
1872 case QRhiTexture::D32F:
1873 return DXGI_FORMAT_R32_TYPELESS;
1874 case QRhiTexture::D32FS8:
1875 return DXGI_FORMAT_R32G8X24_TYPELESS;
1877 case QRhiTexture::BC1:
1878 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1879 case QRhiTexture::BC2:
1880 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1881 case QRhiTexture::BC3:
1882 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1883 case QRhiTexture::BC4:
1884 return DXGI_FORMAT_BC4_UNORM;
1885 case QRhiTexture::BC5:
1886 return DXGI_FORMAT_BC5_UNORM;
1887 case QRhiTexture::BC6H:
1888 return DXGI_FORMAT_BC6H_UF16;
1889 case QRhiTexture::BC7:
1890 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1892 case QRhiTexture::ETC2_RGB8:
1893 case QRhiTexture::ETC2_RGB8A1:
1894 case QRhiTexture::ETC2_RGBA8:
1895 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1896 return DXGI_FORMAT_R8G8B8A8_UNORM;
1898 case QRhiTexture::ASTC_4x4:
1899 case QRhiTexture::ASTC_5x4:
1900 case QRhiTexture::ASTC_5x5:
1901 case QRhiTexture::ASTC_6x5:
1902 case QRhiTexture::ASTC_6x6:
1903 case QRhiTexture::ASTC_8x5:
1904 case QRhiTexture::ASTC_8x6:
1905 case QRhiTexture::ASTC_8x8:
1906 case QRhiTexture::ASTC_10x5:
1907 case QRhiTexture::ASTC_10x6:
1908 case QRhiTexture::ASTC_10x8:
1909 case QRhiTexture::ASTC_10x10:
1910 case QRhiTexture::ASTC_12x10:
1911 case QRhiTexture::ASTC_12x12:
1912 qWarning(
"QRhiD3D11 does not support ASTC textures");
1913 return DXGI_FORMAT_R8G8B8A8_UNORM;
1917 return DXGI_FORMAT_R8G8B8A8_UNORM;
1924 case DXGI_FORMAT_R8G8B8A8_UNORM:
1925 return QRhiTexture::RGBA8;
1926 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1928 (*flags) |= QRhiTexture::sRGB;
1929 return QRhiTexture::RGBA8;
1930 case DXGI_FORMAT_B8G8R8A8_UNORM:
1931 return QRhiTexture::BGRA8;
1932 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1934 (*flags) |= QRhiTexture::sRGB;
1935 return QRhiTexture::BGRA8;
1936 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1937 return QRhiTexture::RGBA16F;
1938 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1939 return QRhiTexture::RGBA32F;
1940 case DXGI_FORMAT_R10G10B10A2_UNORM:
1941 return QRhiTexture::RGB10A2;
1943 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1946 return QRhiTexture::UnknownFormat;
1952 case QRhiTexture::Format::D16:
1953 case QRhiTexture::Format::D24:
1954 case QRhiTexture::Format::D24S8:
1955 case QRhiTexture::Format::D32F:
1956 case QRhiTexture::Format::D32FS8:
1968 Q_ASSERT(!contextState.currentSwapChain);
1969 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1971 ofr.cbWrapper.resetCommands();
1973 Q_ASSERT(contextState.currentSwapChain);
1976 contextState.currentSwapChain->cb.resetCommands();
1982 return QRhi::FrameOpSuccess;
1986 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1988 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1989 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD
->mipLevelCount);
1991 box.front = is3D ? UINT(layer) : 0u;
1993 box.back = box.front + 1;
1996 cmd.args.updateSubRes.dst = texD->textureResource();
1997 cmd.args.updateSubRes.dstSubRes = subres;
1999 const QPoint dp = subresDesc.destinationTopLeft();
2000 if (!subresDesc.image().isNull()) {
2001 QImage img = subresDesc.image();
2002 QSize size = img.size();
2003 int bpl = img.bytesPerLine();
2004 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2005 const QPoint sp = subresDesc.sourceTopLeft();
2006 if (!subresDesc.sourceSize().isEmpty())
2007 size = subresDesc.sourceSize();
2008 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2009 if (img.depth() == 32) {
2010 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
2011 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
2013 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2014 bpl = img.bytesPerLine();
2015 cmd.args.updateSubRes.src = cbD->retainImage(img);
2018 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2019 cmd.args.updateSubRes.src = cbD->retainImage(img);
2021 box.left = UINT(dp.x());
2022 box.top = UINT(dp.y());
2023 box.right = UINT(dp.x() + size.width());
2024 box.bottom = UINT(dp.y() + size.height());
2025 cmd.args.updateSubRes.hasDstBox =
true;
2026 cmd.args.updateSubRes.dstBox = box;
2027 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
2028 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
2029 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2030 : subresDesc.sourceSize();
2033 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
2037 box.left = UINT(aligned(dp.x(), blockDim.width()));
2038 box.top = UINT(aligned(dp.y(), blockDim.height()));
2039 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
2040 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
2041 cmd.args.updateSubRes.hasDstBox =
true;
2042 cmd.args.updateSubRes.dstBox = box;
2043 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2044 cmd.args.updateSubRes.srcRowPitch = bpl;
2045 }
else if (!subresDesc.data().isEmpty()) {
2046 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2047 : subresDesc.sourceSize();
2048 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2049 quint32 bytesPerPixel = 0;
2050 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
2051 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
2052 bytesPerPixel, subresDesc.data().size());
2053 if (size.isEmpty()) {
2054 cbD->commands.unget();
2058 if (subresDesc.dataStride())
2059 bpl = subresDesc.dataStride();
2061 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
2062 box.left = UINT(dp.x());
2063 box.top = UINT(dp.y());
2064 box.right = UINT(dp.x() + size.width());
2065 box.bottom = UINT(dp.y() + size.height());
2066 cmd.args.updateSubRes.hasDstBox =
true;
2067 cmd.args.updateSubRes.dstBox = box;
2068 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2069 cmd.args.updateSubRes.srcRowPitch = bpl;
2071 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
2072 cbD->commands.unget();
2085 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2086 memcpy(bufD
->dynBuf + u.offset, u.data.constData(), size_t(u.data.size()));
2090 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2091 Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
2094 cmd.args.updateSubRes.dst = bufD->buffer;
2095 cmd.args.updateSubRes.dstSubRes = 0;
2096 cmd.args.updateSubRes.src = cbD->retainBufferData(u.data);
2097 cmd.args.updateSubRes.srcRowPitch = 0;
2102 box.left = u.offset;
2103 box.top = box.front = 0;
2104 box.back = box.bottom = 1;
2105 box.right = u.offset + u.data.size();
2106 cmd.args.updateSubRes.hasDstBox =
true;
2107 cmd.args.updateSubRes.dstBox = box;
2110 if (bufD->m_type == QRhiBuffer::Dynamic) {
2111 u.result->data.resize(u.readSize);
2112 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
2113 if (u.result->completed)
2114 u.result->completed();
2117 readback.result = u.result;
2118 readback.byteSize = u.readSize;
2120 D3D11_BUFFER_DESC desc = {};
2121 desc.ByteWidth = readback.byteSize;
2122 desc.Usage = D3D11_USAGE_STAGING;
2123 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2124 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
2126 qWarning(
"Failed to create buffer: %s",
2127 qPrintable(QSystemError::windowsComString(hr)));
2133 cmd.args.copySubRes.dst = readback.stagingBuf;
2134 cmd.args.copySubRes.dstSubRes = 0;
2135 cmd.args.copySubRes.dstX = 0;
2136 cmd.args.copySubRes.dstY = 0;
2137 cmd.args.copySubRes.dstZ = 0;
2138 cmd.args.copySubRes.src = bufD->buffer;
2139 cmd.args.copySubRes.srcSubRes = 0;
2140 cmd.args.copySubRes.hasSrcBox =
true;
2142 box.left = u.offset;
2143 box.top = box.front = 0;
2144 box.back = box.bottom = 1;
2145 box.right = u.offset + u.readSize;
2146 cmd.args.copySubRes.srcBox = box;
2148 activeBufferReadbacks.append(readback);
2153 Q_ASSERT(dstD->m_type != QRhiBuffer::Dynamic && srcD->m_type != QRhiBuffer::Dynamic);
2157 cmd.args.copySubRes.dst = dstD->buffer;
2158 cmd.args.copySubRes.dstSubRes = 0;
2159 cmd.args.copySubRes.dstX = u.offset;
2160 cmd.args.copySubRes.dstY = 0;
2161 cmd.args.copySubRes.dstZ = 0;
2162 cmd.args.copySubRes.src = srcD->buffer;
2163 cmd.args.copySubRes.srcSubRes = 0;
2164 cmd.args.copySubRes.hasSrcBox =
true;
2166 box.left = u.srcOffset;
2167 box.top = box.front = 0;
2168 box.back = box.bottom = 1;
2169 box.right = u.srcOffset + u.readSize;
2170 cmd.args.copySubRes.srcBox = box;
2173 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2175 ID3D11UnorderedAccessView *uav = bufD->createClearUnorderedAccessView(u.offset, u.readSize);
2178 cbD->ownedUavs.append(uav);
2182 cmd.args.clearUav.uav = uav;
2183 for (UINT &v : cmd.args.clearUav.values)
2184 v = u.fillValue32();
2191 for (
const auto &subres : u.subresDesc)
2192 enqueueSubresUpload(texD, cbD, subres.layer, subres.level, subres.desc);
2197 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2198 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2199 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD
->mipLevelCount);
2200 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD
->mipLevelCount);
2201 const QPoint dp = u.desc.destinationTopLeft();
2202 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2203 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2204 const QPoint sp = u.desc.sourceTopLeft();
2206 srcBox.left = UINT(sp.x());
2207 srcBox.top = UINT(sp.y());
2208 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2210 srcBox.right = srcBox.left + UINT(copySize.width());
2211 srcBox.bottom = srcBox.top + UINT(copySize.height());
2212 srcBox.back = srcBox.front + 1;
2215 cmd.args.copySubRes.dst = dstD->textureResource();
2216 cmd.args.copySubRes.dstSubRes = dstSubRes;
2217 cmd.args.copySubRes.dstX = UINT(dp.x());
2218 cmd.args.copySubRes.dstY = UINT(dp.y());
2219 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2220 cmd.args.copySubRes.src = srcD->textureResource();
2221 cmd.args.copySubRes.srcSubRes = srcSubRes;
2222 cmd.args.copySubRes.hasSrcBox =
true;
2223 cmd.args.copySubRes.srcBox = srcBox;
2226 readback.desc = u.rb;
2227 readback.result = u.result;
2229 ID3D11Resource *src;
2230 DXGI_FORMAT dxgiFormat;
2234 QRhiTexture::Format format;
2241 if (texD->sampleDesc.Count > 1) {
2242 qWarning(
"Multisample texture cannot be read back");
2245 src = texD->textureResource();
2246 dxgiFormat = texD->dxgiFormat;
2247 format = texD->m_format;
2248 const QRect levelRect(QPoint(0, 0), q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2249 rect = u.rb.rect().isValid() ? u.rb.rect() : levelRect;
2251 if (isDepthTextureFormat(format)) {
2258 rect = rect.intersected(levelRect);
2259 copyRect = levelRect;
2260 cropOrigin = rect.topLeft();
2262 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2263 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD
->mipLevelCount);
2265 Q_ASSERT(contextState.currentSwapChain);
2267 if (swapChainD->sampleDesc.Count > 1) {
2272 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2273 rcmd.args.resolveSubRes.dstSubRes = 0;
2275 rcmd.args.resolveSubRes.srcSubRes = 0;
2276 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2278 src = swapChainD->backBufferTex;
2279 dxgiFormat = swapChainD->colorFormat;
2280 if (u.rb.rect().isValid())
2283 rect = QRect({0, 0}, swapChainD->pixelSize);
2285 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2286 if (format == QRhiTexture::UnknownFormat)
2289 quint32 byteSize = 0;
2291 quint32 bytesPerPixel = 0;
2292 textureFormatInfo(format, rect.size(), &bpl, &byteSize, &bytesPerPixel);
2294 D3D11_TEXTURE2D_DESC desc = {};
2295 desc.Width = UINT(copyRect.width());
2296 desc.Height = UINT(copyRect.height());
2299 desc.Format = dxgiFormat;
2300 desc.SampleDesc.Count = 1;
2301 desc.Usage = D3D11_USAGE_STAGING;
2302 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2303 ID3D11Texture2D *stagingTex;
2304 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2306 qWarning(
"Failed to create readback staging texture: %s",
2307 qPrintable(QSystemError::windowsComString(hr)));
2313 cmd.args.copySubRes.dst = stagingTex;
2314 cmd.args.copySubRes.dstSubRes = 0;
2315 cmd.args.copySubRes.dstX = 0;
2316 cmd.args.copySubRes.dstY = 0;
2317 cmd.args.copySubRes.dstZ = 0;
2318 cmd.args.copySubRes.src = src;
2319 cmd.args.copySubRes.srcSubRes = subres;
2321 D3D11_BOX srcBox = {};
2322 srcBox.left = UINT(copyRect.left());
2323 srcBox.top = UINT(copyRect.top());
2324 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2326 srcBox.right = srcBox.left + desc.Width;
2327 srcBox.bottom = srcBox.top + desc.Height;
2328 srcBox.back = srcBox.front + 1;
2330 cmd.args.copySubRes.hasSrcBox = !isDepthTextureFormat(format);
2331 cmd.args.copySubRes.srcBox = srcBox;
2333 readback.stagingTex = stagingTex;
2334 readback.byteSize = byteSize;
2336 readback.pixelSize = rect.size();
2337 readback.format = format;
2338 readback.cropOrigin = cropOrigin;
2339 readback.bytesPerPixel = bytesPerPixel;
2341 activeTextureReadbacks.append(readback);
2343 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2346 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2355 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2357 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2359 readback.result->format = readback.format;
2360 readback.result->pixelSize = readback.pixelSize;
2362 D3D11_MAPPED_SUBRESOURCE mp;
2363 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2364 if (SUCCEEDED(hr)) {
2365 readback.result->data.resize(
int(readback.byteSize));
2368 char *dst = readback.result->data.data();
2369 char *src =
static_cast<
char *>(mp.pData)
2370 + readback.cropOrigin.y() * mp.RowPitch
2371 + readback.cropOrigin.x() * readback.bytesPerPixel;
2372 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2373 memcpy(dst, src, readback.bpl);
2374 dst += readback.bpl;
2377 context->Unmap(readback.stagingTex, 0);
2386 char *p = readback.result->data.data();
2387 if (readback.format == QRhiTexture::D24 || readback.format == QRhiTexture::D24S8) {
2388 const bool hasStencil = readback.format == QRhiTexture::D24S8;
2389 for (qsizetype px = 0, count = readback.result->data.size() / 4; px < count; ++px) {
2390 const quint32 texel = qFromUnaligned<quint32>(p + px * 4);
2391 const quint32 stencil = hasStencil ? texel >> 24 : 0;
2392 qToUnaligned(((texel & 0x00FFFFFFu) << 8) | stencil, p + px * 4);
2394 }
else if (readback.format == QRhiTexture::D32FS8) {
2395 for (qsizetype px = 1, count = readback.result->data.size() / 4; px < count; px += 2)
2396 qToUnaligned(qFromUnaligned<quint32>(p + px * 4) & 0xFFu, p + px * 4);
2399 qWarning(
"Failed to map readback staging texture: %s",
2400 qPrintable(QSystemError::windowsComString(hr)));
2403 readback.stagingTex->Release();
2405 if (readback.result->completed)
2406 completedCallbacks.append(readback.result->completed);
2408 activeTextureReadbacks.removeLast();
2411 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2414 D3D11_MAPPED_SUBRESOURCE mp;
2415 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2416 if (SUCCEEDED(hr)) {
2417 readback.result->data.resize(
int(readback.byteSize));
2418 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2419 context->Unmap(readback.stagingBuf, 0);
2421 qWarning(
"Failed to map readback staging texture: %s",
2422 qPrintable(QSystemError::windowsComString(hr)));
2425 readback.stagingBuf->Release();
2427 if (readback.result->completed)
2428 completedCallbacks.append(readback.result->completed);
2430 activeBufferReadbacks.removeLast();
2433 for (
auto f : completedCallbacks)
2439 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2445 QRhiRenderTarget *rt,
2446 const QColor &colorClearValue,
2447 const QRhiDepthStencilClearValue &depthStencilClearValue,
2448 QRhiResourceUpdateBatch *resourceUpdates,
2454 if (resourceUpdates)
2457 bool wantsColorClear =
true;
2458 bool wantsDsClear =
true;
2460 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2462 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2463 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2464 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2472 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2476 clearCmd.args.clear.rtViews = rtD->views;
2477 clearCmd.args.clear.mask = 0;
2478 if (rtD->views.colorAttCount && wantsColorClear)
2480 if (rtD->views.dsv && wantsDsClear)
2483 clearCmd.args.clear.c[0] = colorClearValue.redF();
2484 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2485 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2486 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2487 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2488 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2491 cbD->currentTarget = rt;
2501 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2503 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2506 const QRhiColorAttachment &colorAtt(*it);
2507 if (!colorAtt.resolveTexture())
2513 Q_ASSERT(srcTexD || srcRbD);
2516 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2517 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2518 UINT(colorAtt.resolveLayer()),
2521 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2522 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2523 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2524 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2525 cbD->commands.unget();
2528 if (srcTexD->sampleDesc.Count <= 1) {
2529 qWarning(
"Cannot resolve a non-multisample texture");
2530 cbD->commands.unget();
2533 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2534 qWarning(
"Resolve source and destination sizes do not match");
2535 cbD->commands.unget();
2539 cmd.args.resolveSubRes.src = srcRbD->tex;
2540 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2541 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2542 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2543 cbD->commands.unget();
2546 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2547 qWarning(
"Resolve source and destination sizes do not match");
2548 cbD->commands.unget();
2552 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2553 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2555 if (rtTex->m_desc.depthResolveTexture())
2556 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2560 cbD->currentTarget =
nullptr;
2562 if (resourceUpdates)
2567 QRhiResourceUpdateBatch *resourceUpdates,
2573 if (resourceUpdates)
2581 fbCmd.args.setRenderTarget.rtViews.reset();
2598 if (resourceUpdates)
2609 if (pipelineChanged) {
2610 cbD->currentGraphicsPipeline =
nullptr;
2611 cbD->currentComputePipeline = psD;
2616 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2627 cmd.args.dispatch.x = UINT(x);
2628 cmd.args.dispatch.y = UINT(y);
2629 cmd.args.dispatch.z = UINT(z);
2633 quint32 indirectBufferOffset)
2640 cmd.args.dispatchIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
2641 cmd.args.dispatchIndirect.indirectBufferOffset = indirectBufferOffset;
2645 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2646 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2647 quint32 maxDrawCount, quint32 stride)
2650 Q_UNUSED(indirectBuffer);
2651 Q_UNUSED(indirectBufferOffset);
2652 Q_UNUSED(countBuffer);
2653 Q_UNUSED(countBufferOffset);
2654 Q_UNUSED(maxDrawCount);
2656 qWarning(
"drawIndirectCount is not supported by the D3D11 backend");
2660 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2661 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2662 quint32 maxDrawCount, quint32 stride)
2665 Q_UNUSED(indirectBuffer);
2666 Q_UNUSED(indirectBufferOffset);
2667 Q_UNUSED(countBuffer);
2668 Q_UNUSED(countBufferOffset);
2669 Q_UNUSED(maxDrawCount);
2671 qWarning(
"drawIndexedIndirectCount is not supported by the D3D11 backend");
2676 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2677 uint pushConstantStages)
2679 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2680 if (!map || map->isEmpty()) {
2688 if (pushConstantStages & (1u << uint(stageIndex)))
2690 return { binding, binding };
2693 auto it = map->constFind(binding);
2694 if (it != map->cend())
2704 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2705 uint pushConstantStages)
2712 if (!srbD->resourceBatches || srbD->resourceBatches.use_count() > 1)
2715 srbD->resourceBatches->clear();
2723 ID3D11Buffer *buffer;
2724 uint offsetInConstants;
2725 uint sizeInConstants;
2729 ID3D11ShaderResourceView *srv;
2733 ID3D11SamplerState *sampler;
2737 ID3D11UnorderedAccessView *uav;
2739 QVarLengthArray<Buffer, 8> buffers;
2740 QVarLengthArray<Texture, 8> textures;
2741 QVarLengthArray<Sampler, 8> samplers;
2742 QVarLengthArray<Uav, 8> uavs;
2745 for (
const Buffer &buf : buffers) {
2746 batches.ubufs.feed(buf.breg, buf.buffer);
2747 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2748 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2749 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2755 for (
const Texture &t : textures)
2756 batches.shaderresources.feed(t.treg, t.srv);
2757 for (
const Sampler &s : samplers)
2758 batches.samplers.feed(s.sreg, s.sampler);
2763 for (
const Stage::Uav &u : uavs)
2764 batches.uavs.feed(u.ureg, u.uav);
2769 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2770 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2772 switch (b->type()) {
2773 case QRhiShaderResourceBinding::UniformBuffer:
2776 Q_ASSERT(aligned(b->ubuf().offset, 256u) == b->ubuf().offset);
2777 bd.ubuf.id = bufD->m_id;
2785 const quint32 offsetInConstants = b->ubuf().offset / 16;
2789 const quint32 sizeInConstants = aligned(b->ubuf().maybeSize ? b->ubuf().maybeSize : bufD->m_size, 256u) / 16;
2790 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2791 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2792 if (nativeBinding.first >= 0)
2793 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2795 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2796 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2797 if (nativeBinding.first >= 0)
2798 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2800 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2801 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2802 if (nativeBinding.first >= 0)
2803 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2805 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2806 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2807 if (nativeBinding.first >= 0)
2808 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2810 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2811 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2812 if (nativeBinding.first >= 0)
2813 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2815 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2816 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2817 if (nativeBinding.first >= 0)
2818 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2822 case QRhiShaderResourceBinding::SampledTexture:
2823 case QRhiShaderResourceBinding::Texture:
2824 case QRhiShaderResourceBinding::Sampler:
2826 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex();
2827 bd.stex.d.resize(data->count());
2828 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2829 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2830 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2831 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2832 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2833 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2837 for (
int elem = 0; elem < data->count(); ++elem) {
2840 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2841 bd.stex.d[elem].texGeneration = texD ? texD
->generation : 0;
2842 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2843 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD
->generation : 0;
2848 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2849 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2850 : (samplerD ? nativeBindingVert.first : -1);
2851 if (nativeBindingVert.first >= 0 && texD)
2852 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2853 if (samplerBinding >= 0)
2854 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2856 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2857 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2858 : (samplerD ? nativeBindingHull.first : -1);
2859 if (nativeBindingHull.first >= 0 && texD)
2860 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2861 if (samplerBinding >= 0)
2862 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2864 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2865 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2866 : (samplerD ? nativeBindingDomain.first : -1);
2867 if (nativeBindingDomain.first >= 0 && texD)
2868 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2869 if (samplerBinding >= 0)
2870 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2872 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2873 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2874 : (samplerD ? nativeBindingGeom.first : -1);
2875 if (nativeBindingGeom.first >= 0 && texD)
2876 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2877 if (samplerBinding >= 0)
2878 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2880 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2881 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2882 : (samplerD ? nativeBindingFrag.first : -1);
2883 if (nativeBindingFrag.first >= 0 && texD)
2884 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2885 if (samplerBinding >= 0)
2886 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2888 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2889 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2890 : (samplerD ? nativeBindingComp.first : -1);
2891 if (nativeBindingComp.first >= 0 && texD)
2892 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2893 if (samplerBinding >= 0)
2894 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2899 case QRhiShaderResourceBinding::ImageLoad:
2900 case QRhiShaderResourceBinding::ImageStore:
2901 case QRhiShaderResourceBinding::ImageLoadStore:
2904 bd.simage.id = texD->m_id;
2906 bool validStage =
false;
2907 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2908 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2909 if (nativeBinding.first >= 0) {
2910 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->simage().level);
2912 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2916 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2917 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2918 if (nativeBinding.first >= 0) {
2919 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->simage().level);
2921 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2926 qWarning(
"Unordered access only supported at fragment/compute stage");
2929 case QRhiShaderResourceBinding::BufferLoad:
2930 case QRhiShaderResourceBinding::BufferStore:
2931 case QRhiShaderResourceBinding::BufferLoadStore:
2934 bd.sbuf.id = bufD->m_id;
2936 bool validStage =
false;
2937 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2938 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2939 if (nativeBinding.first >= 0) {
2940 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->sbuf().offset);
2942 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2946 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2947 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2948 if (nativeBinding.first >= 0) {
2949 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->sbuf().offset);
2951 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2956 qWarning(
"Unordered access only supported at fragment/compute stage");
2970 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2971 return a.breg < b.breg;
2973 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2974 return a.treg < b.treg;
2976 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2977 return a.sreg < b.sreg;
2979 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2980 return a.ureg < b.ureg;
2984 res[
RBM_VERTEX].buildBufferBatches(batches.vsUniformBufferBatches);
2985 res[
RBM_HULL].buildBufferBatches(batches.hsUniformBufferBatches);
2986 res[
RBM_DOMAIN].buildBufferBatches(batches.dsUniformBufferBatches);
2987 res[
RBM_GEOMETRY].buildBufferBatches(batches.gsUniformBufferBatches);
2988 res[
RBM_FRAGMENT].buildBufferBatches(batches.fsUniformBufferBatches);
2989 res[
RBM_COMPUTE].buildBufferBatches(batches.csUniformBufferBatches);
2991 res[
RBM_VERTEX].buildSamplerBatches(batches.vsSamplerBatches);
2992 res[
RBM_HULL].buildSamplerBatches(batches.hsSamplerBatches);
2993 res[
RBM_DOMAIN].buildSamplerBatches(batches.dsSamplerBatches);
2994 res[
RBM_GEOMETRY].buildSamplerBatches(batches.gsSamplerBatches);
2995 res[
RBM_FRAGMENT].buildSamplerBatches(batches.fsSamplerBatches);
2996 res[
RBM_COMPUTE].buildSamplerBatches(batches.csSamplerBatches);
2998 res[
RBM_FRAGMENT].buildUavBatches(batches.fsUavBatches);
2999 res[
RBM_COMPUTE].buildUavBatches(batches.csUavBatches);
3007 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
3009 D3D11_MAPPED_SUBRESOURCE mp;
3010 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3011 if (SUCCEEDED(hr)) {
3012 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
3013 context->Unmap(bufD->buffer, 0);
3015 qWarning(
"Failed to map buffer: %s",
3016 qPrintable(QSystemError::windowsComString(hr)));
3022 const QRhiBatchedBindings<UINT> *originalBindings,
3023 const QRhiBatchedBindings<UINT> *staticOffsets,
3024 const uint *dynOfsPairs,
int dynOfsPairCount)
3026 const int count = staticOffsets->batches[batchIndex].resources.count();
3029 for (
int b = 0; b < count; ++b) {
3030 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
3031 for (
int di = 0; di < dynOfsPairCount; ++di) {
3032 const uint binding = dynOfsPairs[2 * di];
3035 if (binding == originalBindings->batches[batchIndex].resources[b]) {
3036 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
3037 offsets[b] = offsetInConstants;
3046 if (startSlot + countSlots > maxSlots) {
3047 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
3048 resType, countSlots, startSlot, maxSlots);
3049 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
3054#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
3055 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
3056 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
3057 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
3058 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
3059 batches.ubufs.batches[i].resources.count(),
3060 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
3061 #stagePrefixU " cbuf");
3063 if (!dynOfsPairCount) {
3064 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3066 batches.ubufs.batches[i].resources.constData(),
3067 batches.ubufoffsets.batches[i].resources.constData(),
3068 batches.ubufsizes.batches[i].resources.constData());
3070 applyDynamicOffsets(offsets, i,
3071 &batches.ubuforigbindings, &batches.ubufoffsets,
3072 dynOfsPairs, dynOfsPairCount);
3073 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3075 batches.ubufs.batches[i].resources.constData(),
3077 batches.ubufsizes.batches[i].resources.constData());
3083#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
3084 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
3085 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
3086 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3087 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
3089 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
3091 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
3092 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3093 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
3095 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
3096 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
3097 int(batch.startBinding + count) - 1
);
3102#define SETUAVBATCH(stagePrefixL, stagePrefixU)
3103 if (allResourceBatches.stagePrefixL##UavBatches.present) {
3104 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
3105 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3108 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
3110 batch.resources.constData(),
3112 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
3113 int(batch.startBinding + count) - 1
);
3120 const uint *dynOfsPairs,
int dynOfsPairCount,
3121 bool offsetOnlyChange,
3133 if (!offsetOnlyChange) {
3143 if (allResourceBatches.fsUavBatches.present) {
3144 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
3145 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
3147 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
3149 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
3150 context->OMSetRenderTargetsAndUnorderedAccessViews(
3151 UINT(rtUavState->rtViews.colorAttCount),
3152 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
3153 rtUavState->rtViews.dsv,
3154 UINT(batch.startBinding),
3156 batch.resources.constData(),
3159 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
3160 int(batch.startBinding + count) - 1);
3172 if (contextState.vsHasIndexBufferBound) {
3173 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
3174 contextState.vsHasIndexBufferBound =
false;
3177 if (contextState.vsHighestActiveVertexBufferBinding >= 0) {
3178 const int count = contextState.vsHighestActiveVertexBufferBinding + 1;
3179 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
3180 for (
int i = 0; i < count; ++i)
3181 nullbufs[i] =
nullptr;
3182 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
3183 for (
int i = 0; i < count; ++i)
3185 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
3186 for (
int i = 0; i < count; ++i)
3188 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
3189 contextState.vsHighestActiveVertexBufferBinding = -1;
3192 int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding);
3193 nullsrvCount = qMax(nullsrvCount, contextState.hsHighestActiveSrvBinding);
3194 nullsrvCount = qMax(nullsrvCount, contextState.dsHighestActiveSrvBinding);
3195 nullsrvCount = qMax(nullsrvCount, contextState.gsHighestActiveSrvBinding);
3196 nullsrvCount = qMax(nullsrvCount, contextState.csHighestActiveSrvBinding);
3198 if (nullsrvCount > 0) {
3199 QVarLengthArray<ID3D11ShaderResourceView *,
3200 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
3201 for (
int i = 0; i < nullsrvs.count(); ++i)
3202 nullsrvs[i] =
nullptr;
3203 if (contextState.vsHighestActiveSrvBinding >= 0) {
3204 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
3205 contextState.vsHighestActiveSrvBinding = -1;
3207 if (contextState.hsHighestActiveSrvBinding >= 0) {
3208 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
3209 contextState.hsHighestActiveSrvBinding = -1;
3211 if (contextState.dsHighestActiveSrvBinding >= 0) {
3212 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
3213 contextState.dsHighestActiveSrvBinding = -1;
3215 if (contextState.gsHighestActiveSrvBinding >= 0) {
3216 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
3217 contextState.gsHighestActiveSrvBinding = -1;
3219 if (contextState.fsHighestActiveSrvBinding >= 0) {
3220 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
3221 contextState.fsHighestActiveSrvBinding = -1;
3223 if (contextState.csHighestActiveSrvBinding >= 0) {
3224 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
3225 contextState.csHighestActiveSrvBinding = -1;
3229 if (contextState.fsHighestActiveUavBinding >= 0) {
3230 rtUavState->update(cbD->currentRenderTargetViews);
3231 context->OMSetRenderTargetsAndUnorderedAccessViews(
3232 UINT(cbD->currentRenderTargetViews.colorAttCount),
3233 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
3234 cbD->currentRenderTargetViews.dsv,
3235 0, 0,
nullptr,
nullptr);
3236 contextState.fsHighestActiveUavBinding = -1;
3238 if (contextState.csHighestActiveUavBinding >= 0) {
3239 const int nulluavCount = contextState.csHighestActiveUavBinding + 1;
3240 QVarLengthArray<ID3D11UnorderedAccessView *,
3241 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
3242 for (
int i = 0; i < nulluavCount; ++i)
3243 nulluavs[i] =
nullptr;
3244 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
3245 contextState.csHighestActiveUavBinding = -1;
3249#define SETSHADER(StageL, StageU)
3250 if (cmd.args.bindGraphicsPipeline.StageL) {
3251 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
3252 currentShaderMask |= StageU##MaskBit;
3253 } else if (currentShaderMask & StageU##MaskBit) {
3254 context->StageU##SetShader(nullptr, nullptr, 0
);
3255 currentShaderMask &= ~StageU##MaskBit;
3260 float blendConstants[] = { 1, 1, 1, 1 };
3261 enum ActiveShaderMask {
3268 int currentShaderMask = 0xFF;
3274 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3277 case QD3D11CommandBuffer::Command::BeginFrame:
3278 if (cmd.args.beginFrame.tsDisjointQuery)
3279 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3280 if (cmd.args.beginFrame.tsQuery) {
3281 if (cmd.args.beginFrame.swapchainRtv) {
3286 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3287 rtUavState.update(cbD->currentRenderTargetViews);
3288 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3290 context->End(cmd.args.beginFrame.tsQuery);
3293 case QD3D11CommandBuffer::Command::EndFrame:
3294 if (cmd.args.endFrame.tsQuery)
3295 context->End(cmd.args.endFrame.tsQuery);
3296 if (cmd.args.endFrame.tsDisjointQuery)
3297 context->End(cmd.args.endFrame.tsDisjointQuery);
3304 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3305 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3306 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3307 context->OMSetRenderTargets(colorAttCount,
3308 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3309 cmd.args.setRenderTarget.rtViews.dsv);
3316 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3317 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3321 ds |= D3D11_CLEAR_DEPTH;
3323 ds |= D3D11_CLEAR_STENCIL;
3324 if (ds && cmd.args.clear.rtViews.dsv)
3325 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3331 v.TopLeftX = cmd.args.viewport.x;
3332 v.TopLeftY = cmd.args.viewport.y;
3333 v.Width = cmd.args.viewport.w;
3334 v.Height = cmd.args.viewport.h;
3335 v.MinDepth = cmd.args.viewport.d0;
3336 v.MaxDepth = cmd.args.viewport.d1;
3337 context->RSSetViewports(1, &v);
3343 r.left = cmd.args.scissor.x;
3344 r.top = cmd.args.scissor.y;
3346 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3347 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3348 context->RSSetScissorRects(1, &r);
3352 contextState.vsHighestActiveVertexBufferBinding = qMax<
int>(
3353 contextState.vsHighestActiveVertexBufferBinding,
3354 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3355 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3356 UINT(cmd.args.bindVertexBuffers.slotCount),
3357 cmd.args.bindVertexBuffers.buffers,
3358 cmd.args.bindVertexBuffers.strides,
3359 cmd.args.bindVertexBuffers.offsets);
3362 contextState.vsHasIndexBufferBound =
true;
3363 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3364 cmd.args.bindIndexBuffer.format,
3365 cmd.args.bindIndexBuffer.offset);
3374 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3375 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3376 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, cmd.args.bindGraphicsPipeline.stencilRef);
3377 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3378 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3383 *cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex]
,
3384 cmd.args.bindShaderResources.dynamicOffsetPairs
,
3385 cmd.args.bindShaderResources.dynamicOffsetCount
,
3386 cmd.args.bindShaderResources.offsetOnlyChange
,
3394 ID3D11Buffer *buf = cmd.args.setPushConstants.buffer;
3395 D3D11_MAPPED_SUBRESOURCE mp;
3396 HRESULT hr = context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3397 if (SUCCEEDED(hr)) {
3398 memcpy(mp.pData, cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
3399 cmd.args.setPushConstants.size);
3400 context->Unmap(buf, 0);
3402 qWarning(
"Failed to map push constant buffer: %s",
3403 qPrintable(QSystemError::windowsComString(hr)));
3406 const UINT startSlot = cmd.args.setPushConstants.startSlot;
3407 const uint stages = cmd.args.setPushConstants.stages;
3411 if (stages & (1u << uint(RBM_VERTEX)))
3412 context->VSSetConstantBuffers(startSlot, 1, &buf);
3413 if (stages & (1u << uint(RBM_HULL)))
3414 context->HSSetConstantBuffers(startSlot, 1, &buf);
3415 if (stages & (1u << uint(RBM_DOMAIN)))
3416 context->DSSetConstantBuffers(startSlot, 1, &buf);
3417 if (stages & (1u << uint(RBM_GEOMETRY)))
3418 context->GSSetConstantBuffers(startSlot, 1, &buf);
3419 if (stages & (1u << uint(RBM_FRAGMENT)))
3420 context->PSSetConstantBuffers(startSlot, 1, &buf);
3421 if (stages & (1u << uint(RBM_COMPUTE)))
3422 context->CSSetConstantBuffers(startSlot, 1, &buf);
3425 case QD3D11CommandBuffer::Command::StencilRef:
3426 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, cmd.args.stencilRef.ref);
3429 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3430 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3432 case QD3D11CommandBuffer::Command::Draw:
3433 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3434 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3436 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3437 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3439 case QD3D11CommandBuffer::Command::DrawIndexed:
3440 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3441 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3442 cmd.args.drawIndexed.vertexOffset);
3444 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3445 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3446 cmd.args.drawIndexed.firstInstance);
3450 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3451 const UINT stride = cmd.args.drawIndirect.stride;
3452 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3453 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3454 alignedByteOffsetForArgs += stride;
3460 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3461 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3462 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3463 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3464 alignedByteOffsetForArgs += stride;
3470 if (cmd.args.updateSubRes.dst) {
3471 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3472 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3473 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3476 case QD3D11CommandBuffer::Command::CopySubRes:
3477 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3478 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3479 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3480 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3482 case QD3D11CommandBuffer::Command::ClearUav:
3483 context->ClearUnorderedAccessViewUint(cmd.args.clearUav.uav, cmd.args.clearUav.values);
3485 case QD3D11CommandBuffer::Command::ResolveSubRes:
3486 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3487 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3488 cmd.args.resolveSubRes.format);
3490 case QD3D11CommandBuffer::Command::GenMip:
3491 context->GenerateMips(cmd.args.genMip.srv);
3493 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3494 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3496 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3497 annotations->EndEvent();
3499 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3500 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3502 case QD3D11CommandBuffer::Command::BindComputePipeline:
3503 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3505 case QD3D11CommandBuffer::Command::Dispatch:
3506 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3508 case QD3D11CommandBuffer::Command::DispatchIndirect:
3509 context->DispatchIndirect(cmd.args.dispatchIndirect.indirectBuffer,
3510 cmd.args.dispatchIndirect.indirectBufferOffset);
3539 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3540 it.value()->Release();
3545 rhiD->unregisterResource(
this);
3551 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3552 u |= D3D11_BIND_VERTEX_BUFFER;
3553 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3554 u |= D3D11_BIND_INDEX_BUFFER;
3555 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3556 u |= D3D11_BIND_CONSTANT_BUFFER;
3557 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3558 u |= D3D11_BIND_UNORDERED_ACCESS;
3567 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3568 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3572 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3573 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3577 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3578 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3582 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3587 const quint32 minSize = m_usage.testFlag(QRhiBuffer::IndirectBuffer) ? 12u : 1u;
3588 const quint32 roundedSize = aligned(qMax(nonZeroSize, minSize),
3589 m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3591 D3D11_BUFFER_DESC desc = {};
3592 desc.ByteWidth = roundedSize;
3593 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3594 desc.BindFlags = toD3DBufferUsage(m_usage);
3595 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3596 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3597 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3598 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3601 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3603 qWarning(
"Failed to create buffer: %s",
3604 qPrintable(QSystemError::windowsComString(hr)));
3608 if (m_type == Dynamic) {
3609 dynBuf =
new char[nonZeroSize];
3613 if (!m_objectName.isEmpty())
3614 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3617 rhiD->registerResource(
this);
3623 if (m_type == Dynamic) {
3627 return { { &buffer }, 1 };
3638 Q_ASSERT(m_type == Dynamic);
3639 D3D11_MAPPED_SUBRESOURCE mp;
3641 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3643 qWarning(
"Failed to map buffer: %s",
3644 qPrintable(QSystemError::windowsComString(hr)));
3647 return static_cast<
char *>(mp.pData);
3653 rhiD->context->Unmap(buffer, 0);
3658 auto it = uavs.find(offset);
3659 if (it != uavs.end())
3663 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3664 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3665 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3666 desc.Buffer.FirstElement = offset / 4u;
3667 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3668 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3671 ID3D11UnorderedAccessView *uav =
nullptr;
3672 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3674 qWarning(
"Failed to create UAV: %s",
3675 qPrintable(QSystemError::windowsComString(hr)));
3688 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3689 desc.Format = DXGI_FORMAT_R32_UINT;
3690 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3691 desc.Buffer.FirstElement = offset / 4u;
3692 desc.Buffer.NumElements = size / 4u;
3695 ID3D11UnorderedAccessView *uav =
nullptr;
3696 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3698 qWarning(
"Failed to create UAV: %s",
3699 qPrintable(QSystemError::windowsComString(hr)));
3707 int sampleCount, QRhiRenderBuffer::Flags flags,
3708 QRhiTexture::Format backingFormatHint)
3738 rhiD->unregisterResource(
this);
3746 if (m_pixelSize.isEmpty())
3750 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3752 D3D11_TEXTURE2D_DESC desc = {};
3753 desc.Width = UINT(m_pixelSize.width());
3754 desc.Height = UINT(m_pixelSize.height());
3757 desc.SampleDesc = sampleDesc;
3758 desc.Usage = D3D11_USAGE_DEFAULT;
3760 if (m_type == Color) {
3761 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3762 : toD3DTextureFormat(m_backingFormatHint, {});
3763 desc.Format = dxgiFormat;
3764 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3765 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3767 qWarning(
"Failed to create color renderbuffer: %s",
3768 qPrintable(QSystemError::windowsComString(hr)));
3771 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3772 rtvDesc.Format = dxgiFormat;
3773 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3774 : D3D11_RTV_DIMENSION_TEXTURE2D;
3775 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3777 qWarning(
"Failed to create rtv: %s",
3778 qPrintable(QSystemError::windowsComString(hr)));
3781 }
else if (m_type == DepthStencil) {
3782 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3783 desc.Format = dxgiFormat;
3784 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3785 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3787 qWarning(
"Failed to create depth-stencil buffer: %s",
3788 qPrintable(QSystemError::windowsComString(hr)));
3791 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3792 dsvDesc.Format = dxgiFormat;
3793 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3794 : D3D11_DSV_DIMENSION_TEXTURE2D;
3795 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3797 qWarning(
"Failed to create dsv: %s",
3798 qPrintable(QSystemError::windowsComString(hr)));
3805 if (!m_objectName.isEmpty())
3806 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3809 rhiD->registerResource(
this);
3815 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3816 return m_backingFormatHint;
3818 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3822 int arraySize,
int sampleCount, Flags flags)
3825 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3826 perLevelViews[i] =
nullptr;
3836 if (!tex && !tex3D && !tex1D)
3844 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3845 if (perLevelViews[i]) {
3846 perLevelViews[i]->Release();
3847 perLevelViews[i] =
nullptr;
3866 rhiD->unregisterResource(
this);
3872 case QRhiTexture::Format::D16:
3873 return DXGI_FORMAT_R16_FLOAT;
3874 case QRhiTexture::Format::D24:
3875 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3876 case QRhiTexture::Format::D24S8:
3877 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3878 case QRhiTexture::Format::D32F:
3879 return DXGI_FORMAT_R32_FLOAT;
3880 case QRhiTexture::Format::D32FS8:
3881 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3884 return DXGI_FORMAT_R32_FLOAT;
3891 case QRhiTexture::Format::D16:
3892 return DXGI_FORMAT_D16_UNORM;
3893 case QRhiTexture::Format::D24:
3894 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3895 case QRhiTexture::Format::D24S8:
3896 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3897 case QRhiTexture::Format::D32F:
3898 return DXGI_FORMAT_D32_FLOAT;
3899 case QRhiTexture::Format::D32FS8:
3900 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3903 return DXGI_FORMAT_D32_FLOAT;
3909 if (tex || tex3D || tex1D)
3913 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3916 const bool isDepth = isDepthTextureFormat(m_format);
3917 const bool isCube = m_flags.testFlag(CubeMap);
3918 const bool is3D = m_flags.testFlag(ThreeDimensional);
3919 const bool isArray = m_flags.testFlag(TextureArray);
3920 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3921 const bool is1D = m_flags.testFlag(OneDimensional);
3923 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3924 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3926 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3927 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3928 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3929 if (sampleDesc.Count > 1) {
3931 qWarning(
"Cubemap texture cannot be multisample");
3935 qWarning(
"3D texture cannot be multisample");
3939 qWarning(
"Multisample texture cannot have mipmaps");
3943 if (isDepth && hasMipMaps) {
3944 qWarning(
"Depth texture cannot have mipmaps");
3947 if (isCube && is3D) {
3948 qWarning(
"Texture cannot be both cube and 3D");
3951 if (isArray && is3D) {
3952 qWarning(
"Texture cannot be both array and 3D");
3955 if (isCube && is1D) {
3956 qWarning(
"Texture cannot be both cube and 1D");
3960 qWarning(
"Texture cannot be both 1D and 3D");
3963 if (m_depth > 1 && !is3D) {
3964 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3967 if (m_arraySize > 0 && !isArray) {
3968 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3971 if (m_arraySize < 1 && isArray) {
3972 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3976 if (!rhiD->textureFormatInfo(m_format, size,
nullptr,
nullptr,
nullptr))
3980 *adjustedSize = size;
3988 const bool isDepth = isDepthTextureFormat(m_format);
3989 const bool isCube = m_flags.testFlag(CubeMap);
3990 const bool is3D = m_flags.testFlag(ThreeDimensional);
3991 const bool isArray = m_flags.testFlag(TextureArray);
3992 const bool is1D = m_flags.testFlag(OneDimensional);
3994 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3995 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3997 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
4002 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
4004 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4005 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
4006 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
4008 srvDesc.Texture1DArray.FirstArraySlice = 0;
4009 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
4012 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
4015 }
else if (isArray) {
4016 if (sampleDesc.Count > 1) {
4017 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
4018 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4019 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
4020 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
4022 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
4023 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
4026 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
4028 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
4029 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
4030 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
4032 srvDesc.Texture2DArray.FirstArraySlice = 0;
4033 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
4037 if (sampleDesc.Count > 1) {
4038 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
4040 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
4043 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
4049 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
4051 qWarning(
"Failed to create srv: %s",
4052 qPrintable(QSystemError::windowsComString(hr)));
4063 if (!prepareCreate(&size))
4066 const bool isDepth = isDepthTextureFormat(m_format);
4067 const bool isCube = m_flags.testFlag(CubeMap);
4068 const bool is3D = m_flags.testFlag(ThreeDimensional);
4069 const bool isArray = m_flags.testFlag(TextureArray);
4070 const bool is1D = m_flags.testFlag(OneDimensional);
4072 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
4073 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
4074 if (m_flags.testFlag(RenderTarget)) {
4076 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
4078 bindFlags |= D3D11_BIND_RENDER_TARGET;
4080 if (m_flags.testFlag(UsedWithGenerateMips)) {
4082 qWarning(
"Depth texture cannot have mipmaps generated");
4085 bindFlags |= D3D11_BIND_RENDER_TARGET;
4086 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
4088 if (m_flags.testFlag(UsedWithLoadStore))
4089 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
4093 D3D11_TEXTURE1D_DESC desc = {};
4094 desc.Width = UINT(size.width());
4096 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
4097 desc.Format = dxgiFormat;
4098 desc.Usage = D3D11_USAGE_DEFAULT;
4099 desc.BindFlags = bindFlags;
4100 desc.MiscFlags = miscFlags;
4102 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
4104 qWarning(
"Failed to create 1D texture: %s",
4105 qPrintable(QSystemError::windowsComString(hr)));
4108 if (!m_objectName.isEmpty())
4109 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
4110 m_objectName.constData());
4112 D3D11_TEXTURE2D_DESC desc = {};
4113 desc.Width = UINT(size.width());
4114 desc.Height = UINT(size.height());
4116 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
4117 desc.Format = dxgiFormat;
4118 desc.SampleDesc = sampleDesc;
4119 desc.Usage = D3D11_USAGE_DEFAULT;
4120 desc.BindFlags = bindFlags;
4121 desc.MiscFlags = miscFlags;
4123 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
4125 qWarning(
"Failed to create 2D texture: %s",
4126 qPrintable(QSystemError::windowsComString(hr)));
4127 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4131 if (!m_objectName.isEmpty())
4132 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4134 D3D11_TEXTURE3D_DESC desc = {};
4135 desc.Width = UINT(size.width());
4136 desc.Height = UINT(size.height());
4137 desc.Depth = UINT(qMax(1, m_depth));
4139 desc.Format = dxgiFormat;
4140 desc.Usage = D3D11_USAGE_DEFAULT;
4141 desc.BindFlags = bindFlags;
4142 desc.MiscFlags = miscFlags;
4144 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
4146 qWarning(
"Failed to create 3D texture: %s",
4147 qPrintable(QSystemError::windowsComString(hr)));
4148 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4152 if (!m_objectName.isEmpty())
4153 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4160 rhiD->registerResource(
this);
4169 if (!prepareCreate())
4172 if (m_flags.testFlag(ThreeDimensional))
4173 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
4174 else if (m_flags.testFlags(OneDimensional))
4175 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
4177 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
4184 rhiD->registerResource(
this);
4190 return { quint64(textureResource()), 0 };
4195 if (perLevelViews[level])
4196 return perLevelViews[level];
4198 const bool isCube = m_flags.testFlag(CubeMap);
4199 const bool isArray = m_flags.testFlag(TextureArray);
4200 const bool is3D = m_flags.testFlag(ThreeDimensional);
4201 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
4202 desc.Format = dxgiFormat;
4204 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4205 desc.Texture2DArray.MipSlice = UINT(level);
4206 desc.Texture2DArray.FirstArraySlice = 0;
4207 desc.Texture2DArray.ArraySize = 6;
4208 }
else if (isArray) {
4209 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4210 desc.Texture2DArray.MipSlice = UINT(level);
4211 desc.Texture2DArray.FirstArraySlice = 0;
4212 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
4214 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
4215 desc.Texture3D.MipSlice = UINT(level);
4216 desc.Texture3D.WSize = UINT(m_depth);
4218 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
4219 desc.Texture2D.MipSlice = UINT(level);
4223 ID3D11UnorderedAccessView *uav =
nullptr;
4224 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
4226 qWarning(
"Failed to create UAV: %s",
4227 qPrintable(QSystemError::windowsComString(hr)));
4231 perLevelViews[level] = uav;
4236 AddressMode u, AddressMode v, AddressMode w)
4251 samplerState->Release();
4252 samplerState =
nullptr;
4256 rhiD->unregisterResource(
this);
4259static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
4261 if (minFilter == QRhiSampler::Nearest) {
4262 if (magFilter == QRhiSampler::Nearest) {
4263 if (mipFilter == QRhiSampler::Linear)
4264 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
4266 return D3D11_FILTER_MIN_MAG_MIP_POINT;
4268 if (mipFilter == QRhiSampler::Linear)
4269 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
4271 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
4274 if (magFilter == QRhiSampler::Nearest) {
4275 if (mipFilter == QRhiSampler::Linear)
4276 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
4278 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
4280 if (mipFilter == QRhiSampler::Linear)
4281 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4283 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
4288 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4294 case QRhiSampler::Repeat:
4295 return D3D11_TEXTURE_ADDRESS_WRAP;
4296 case QRhiSampler::ClampToEdge:
4297 return D3D11_TEXTURE_ADDRESS_CLAMP;
4298 case QRhiSampler::Mirror:
4299 return D3D11_TEXTURE_ADDRESS_MIRROR;
4302 return D3D11_TEXTURE_ADDRESS_CLAMP;
4309 case QRhiSampler::Never:
4310 return D3D11_COMPARISON_NEVER;
4311 case QRhiSampler::Less:
4312 return D3D11_COMPARISON_LESS;
4313 case QRhiSampler::Equal:
4314 return D3D11_COMPARISON_EQUAL;
4315 case QRhiSampler::LessOrEqual:
4316 return D3D11_COMPARISON_LESS_EQUAL;
4317 case QRhiSampler::Greater:
4318 return D3D11_COMPARISON_GREATER;
4319 case QRhiSampler::NotEqual:
4320 return D3D11_COMPARISON_NOT_EQUAL;
4321 case QRhiSampler::GreaterOrEqual:
4322 return D3D11_COMPARISON_GREATER_EQUAL;
4323 case QRhiSampler::Always:
4324 return D3D11_COMPARISON_ALWAYS;
4327 return D3D11_COMPARISON_NEVER;
4336 D3D11_SAMPLER_DESC desc = {};
4337 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
4338 if (m_compareOp != Never)
4339 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
4340 desc.AddressU = toD3DAddressMode(m_addressU);
4341 desc.AddressV = toD3DAddressMode(m_addressV);
4342 desc.AddressW = toD3DAddressMode(m_addressW);
4343 desc.MaxAnisotropy = 1.0f;
4344 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
4345 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
4348 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
4350 qWarning(
"Failed to create sampler state: %s",
4351 qPrintable(QSystemError::windowsComString(hr)));
4356 rhiD->registerResource(
this);
4375 rhiD->unregisterResource(
this);
4388 rhiD->registerResource(rpD,
false);
4425 return d.sampleCount;
4429 const QRhiTextureRenderTargetDescription &desc,
4447 if (!rtv[0] && !dsv)
4466 rhiD->unregisterResource(
this);
4473 rhiD->registerResource(rpD,
false);
4482 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4483 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4484 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4488 int colorAttCount = 0;
4490 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4492 const QRhiColorAttachment &colorAtt(*it);
4493 QRhiTexture *texture = colorAtt.texture();
4494 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4495 Q_ASSERT(texture || rb);
4498 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4499 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4500 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4501 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4502 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4503 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4504 rtvDesc.Texture2DArray.ArraySize = 1;
4505 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4506 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4507 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4508 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4509 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4510 rtvDesc.Texture1DArray.ArraySize = 1;
4512 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4513 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4515 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4516 if (texD->sampleDesc.Count > 1) {
4517 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4518 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4519 rtvDesc.Texture2DMSArray.ArraySize = 1;
4521 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4522 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4523 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4524 rtvDesc.Texture2DArray.ArraySize = 1;
4526 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4527 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4528 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4529 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4530 rtvDesc.Texture3D.WSize = 1;
4532 if (texD->sampleDesc.Count > 1) {
4533 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4535 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4536 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4539 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4541 qWarning(
"Failed to create rtv: %s",
4542 qPrintable(QSystemError::windowsComString(hr)));
4546 if (attIndex == 0) {
4547 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4548 d.sampleCount =
int(texD->sampleDesc.Count);
4553 rtv[attIndex] = rbD->rtv;
4554 if (attIndex == 0) {
4555 d.pixelSize = rbD->pixelSize();
4556 d.sampleCount =
int(rbD->sampleDesc.Count);
4562 if (hasDepthStencil) {
4563 if (m_desc.depthTexture()) {
4566 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4567 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4568 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4569 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4570 if (isMultisample) {
4571 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4572 if (m_desc.depthLayer() >= 0) {
4573 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4574 dsvDesc.Texture2DMSArray.ArraySize = 1;
4575 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4576 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4577 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4579 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4580 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4583 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4584 if (m_desc.depthLayer() >= 0) {
4585 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4586 dsvDesc.Texture2DArray.ArraySize = 1;
4587 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4588 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4589 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4591 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4592 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4597 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4598 : D3D11_DSV_DIMENSION_TEXTURE2D;
4600 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4602 qWarning(
"Failed to create dsv: %s",
4603 qPrintable(QSystemError::windowsComString(hr)));
4606 if (colorAttCount == 0) {
4607 d.pixelSize = depthTexD->pixelSize();
4608 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4613 dsv = depthRbD->dsv;
4614 if (colorAttCount == 0) {
4615 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4616 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4623 d.views.setFrom(colorAttCount, rtv, dsv);
4625 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4627 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4629 rhiD->registerResource(
this);
4635 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4648 return d.sampleCount;
4663 sortedBindings.clear();
4664 boundResourceData.clear();
4668 rhiD->unregisterResource(
this);
4673 if (!sortedBindings.isEmpty())
4677 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4680 rhiD->updateLayoutDesc(
this);
4682 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4683 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4685 boundResourceData.resize(sortedBindings.count());
4687 for (BoundResourceData &bd : boundResourceData)
4691 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4692 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4693 if (bd->type() == QRhiShaderResourceBinding::UniformBuffer && bd->ubuf().hasDynamicOffset) {
4694 hasDynamicOffset =
true;
4700 rhiD->registerResource(
this,
false);
4706 sortedBindings.clear();
4707 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4708 if (!flags.testFlag(BindingsAreSorted))
4709 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4711 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4712 for (BoundResourceData &bd : boundResourceData)
4732 s.shader->Release();
4735 s.nativeResourceBindingMap.clear();
4747 blendState->Release();
4748 blendState =
nullptr;
4752 inputLayout->Release();
4753 inputLayout =
nullptr;
4757 rastState->Release();
4758 rastState =
nullptr;
4761 releasePipelineShader(vs);
4762 releasePipelineShader(hs);
4763 releasePipelineShader(ds);
4764 releasePipelineShader(gs);
4765 releasePipelineShader(fs);
4771 rhiD->unregisterResource(
this);
4777 case QRhiGraphicsPipeline::None:
4778 return D3D11_CULL_NONE;
4779 case QRhiGraphicsPipeline::Front:
4780 return D3D11_CULL_FRONT;
4781 case QRhiGraphicsPipeline::Back:
4782 return D3D11_CULL_BACK;
4785 return D3D11_CULL_NONE;
4792 case QRhiGraphicsPipeline::Fill:
4793 return D3D11_FILL_SOLID;
4794 case QRhiGraphicsPipeline::Line:
4795 return D3D11_FILL_WIREFRAME;
4798 return D3D11_FILL_SOLID;
4805 case QRhiGraphicsPipeline::Never:
4806 return D3D11_COMPARISON_NEVER;
4807 case QRhiGraphicsPipeline::Less:
4808 return D3D11_COMPARISON_LESS;
4809 case QRhiGraphicsPipeline::Equal:
4810 return D3D11_COMPARISON_EQUAL;
4811 case QRhiGraphicsPipeline::LessOrEqual:
4812 return D3D11_COMPARISON_LESS_EQUAL;
4813 case QRhiGraphicsPipeline::Greater:
4814 return D3D11_COMPARISON_GREATER;
4815 case QRhiGraphicsPipeline::NotEqual:
4816 return D3D11_COMPARISON_NOT_EQUAL;
4817 case QRhiGraphicsPipeline::GreaterOrEqual:
4818 return D3D11_COMPARISON_GREATER_EQUAL;
4819 case QRhiGraphicsPipeline::Always:
4820 return D3D11_COMPARISON_ALWAYS;
4823 return D3D11_COMPARISON_ALWAYS;
4830 case QRhiGraphicsPipeline::StencilZero:
4831 return D3D11_STENCIL_OP_ZERO;
4832 case QRhiGraphicsPipeline::Keep:
4833 return D3D11_STENCIL_OP_KEEP;
4834 case QRhiGraphicsPipeline::Replace:
4835 return D3D11_STENCIL_OP_REPLACE;
4836 case QRhiGraphicsPipeline::IncrementAndClamp:
4837 return D3D11_STENCIL_OP_INCR_SAT;
4838 case QRhiGraphicsPipeline::DecrementAndClamp:
4839 return D3D11_STENCIL_OP_DECR_SAT;
4840 case QRhiGraphicsPipeline::Invert:
4841 return D3D11_STENCIL_OP_INVERT;
4842 case QRhiGraphicsPipeline::IncrementAndWrap:
4843 return D3D11_STENCIL_OP_INCR;
4844 case QRhiGraphicsPipeline::DecrementAndWrap:
4845 return D3D11_STENCIL_OP_DECR;
4848 return D3D11_STENCIL_OP_KEEP;
4855 case QRhiVertexInputAttribute::Float4:
4856 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4857 case QRhiVertexInputAttribute::Float3:
4858 return DXGI_FORMAT_R32G32B32_FLOAT;
4859 case QRhiVertexInputAttribute::Float2:
4860 return DXGI_FORMAT_R32G32_FLOAT;
4861 case QRhiVertexInputAttribute::Float:
4862 return DXGI_FORMAT_R32_FLOAT;
4863 case QRhiVertexInputAttribute::UNormByte4:
4864 return DXGI_FORMAT_R8G8B8A8_UNORM;
4865 case QRhiVertexInputAttribute::UNormByte2:
4866 return DXGI_FORMAT_R8G8_UNORM;
4867 case QRhiVertexInputAttribute::UNormByte:
4868 return DXGI_FORMAT_R8_UNORM;
4869 case QRhiVertexInputAttribute::UInt4:
4870 return DXGI_FORMAT_R32G32B32A32_UINT;
4871 case QRhiVertexInputAttribute::UInt3:
4872 return DXGI_FORMAT_R32G32B32_UINT;
4873 case QRhiVertexInputAttribute::UInt2:
4874 return DXGI_FORMAT_R32G32_UINT;
4875 case QRhiVertexInputAttribute::UInt:
4876 return DXGI_FORMAT_R32_UINT;
4877 case QRhiVertexInputAttribute::SInt4:
4878 return DXGI_FORMAT_R32G32B32A32_SINT;
4879 case QRhiVertexInputAttribute::SInt3:
4880 return DXGI_FORMAT_R32G32B32_SINT;
4881 case QRhiVertexInputAttribute::SInt2:
4882 return DXGI_FORMAT_R32G32_SINT;
4883 case QRhiVertexInputAttribute::SInt:
4884 return DXGI_FORMAT_R32_SINT;
4885 case QRhiVertexInputAttribute::Half4:
4887 case QRhiVertexInputAttribute::Half3:
4888 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4889 case QRhiVertexInputAttribute::Half2:
4890 return DXGI_FORMAT_R16G16_FLOAT;
4891 case QRhiVertexInputAttribute::Half:
4892 return DXGI_FORMAT_R16_FLOAT;
4893 case QRhiVertexInputAttribute::UShort4:
4895 case QRhiVertexInputAttribute::UShort3:
4896 return DXGI_FORMAT_R16G16B16A16_UINT;
4897 case QRhiVertexInputAttribute::UShort2:
4898 return DXGI_FORMAT_R16G16_UINT;
4899 case QRhiVertexInputAttribute::UShort:
4900 return DXGI_FORMAT_R16_UINT;
4901 case QRhiVertexInputAttribute::SShort4:
4903 case QRhiVertexInputAttribute::SShort3:
4904 return DXGI_FORMAT_R16G16B16A16_SINT;
4905 case QRhiVertexInputAttribute::SShort2:
4906 return DXGI_FORMAT_R16G16_SINT;
4907 case QRhiVertexInputAttribute::SShort:
4908 return DXGI_FORMAT_R16_SINT;
4911 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4918 case QRhiGraphicsPipeline::Triangles:
4919 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4920 case QRhiGraphicsPipeline::TriangleStrip:
4921 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4922 case QRhiGraphicsPipeline::Lines:
4923 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4924 case QRhiGraphicsPipeline::LineStrip:
4925 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4926 case QRhiGraphicsPipeline::Points:
4927 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4928 case QRhiGraphicsPipeline::Patches:
4929 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4930 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4933 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4940 if (c.testFlag(QRhiGraphicsPipeline::R))
4941 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4942 if (c.testFlag(QRhiGraphicsPipeline::G))
4943 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4944 if (c.testFlag(QRhiGraphicsPipeline::B))
4945 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4946 if (c.testFlag(QRhiGraphicsPipeline::A))
4947 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4960 case QRhiGraphicsPipeline::Zero:
4961 return D3D11_BLEND_ZERO;
4962 case QRhiGraphicsPipeline::One:
4963 return D3D11_BLEND_ONE;
4964 case QRhiGraphicsPipeline::SrcColor:
4965 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4966 case QRhiGraphicsPipeline::OneMinusSrcColor:
4967 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4968 case QRhiGraphicsPipeline::DstColor:
4969 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4970 case QRhiGraphicsPipeline::OneMinusDstColor:
4971 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4972 case QRhiGraphicsPipeline::SrcAlpha:
4973 return D3D11_BLEND_SRC_ALPHA;
4974 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4975 return D3D11_BLEND_INV_SRC_ALPHA;
4976 case QRhiGraphicsPipeline::DstAlpha:
4977 return D3D11_BLEND_DEST_ALPHA;
4978 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4979 return D3D11_BLEND_INV_DEST_ALPHA;
4980 case QRhiGraphicsPipeline::ConstantColor:
4981 case QRhiGraphicsPipeline::ConstantAlpha:
4982 return D3D11_BLEND_BLEND_FACTOR;
4983 case QRhiGraphicsPipeline::OneMinusConstantColor:
4984 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4985 return D3D11_BLEND_INV_BLEND_FACTOR;
4986 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4987 return D3D11_BLEND_SRC_ALPHA_SAT;
4988 case QRhiGraphicsPipeline::Src1Color:
4989 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4990 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4991 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4992 case QRhiGraphicsPipeline::Src1Alpha:
4993 return D3D11_BLEND_SRC1_ALPHA;
4994 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4995 return D3D11_BLEND_INV_SRC1_ALPHA;
4998 return D3D11_BLEND_ZERO;
5005 case QRhiGraphicsPipeline::Add:
5006 return D3D11_BLEND_OP_ADD;
5007 case QRhiGraphicsPipeline::Subtract:
5008 return D3D11_BLEND_OP_SUBTRACT;
5009 case QRhiGraphicsPipeline::ReverseSubtract:
5010 return D3D11_BLEND_OP_REV_SUBTRACT;
5011 case QRhiGraphicsPipeline::Min:
5012 return D3D11_BLEND_OP_MIN;
5013 case QRhiGraphicsPipeline::Max:
5014 return D3D11_BLEND_OP_MAX;
5017 return D3D11_BLEND_OP_ADD;
5024 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
5025 keyBuilder.addData(source);
5026 return keyBuilder.result().toHex();
5030 QString *error, QShaderKey *usedShaderKey)
5032 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
5033 QShaderCode dxbc = shader.shader(key);
5034 if (!dxbc.shader().isEmpty()) {
5036 *usedShaderKey = key;
5037 return dxbc.shader();
5040 key = { QShader::HlslShader, 50, shaderVariant };
5041 QShaderCode hlslSource = shader.shader(key);
5042 if (hlslSource.shader().isEmpty()) {
5043 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
5044 return QByteArray();
5048 *usedShaderKey = key;
5051 switch (shader.stage()) {
5052 case QShader::VertexStage:
5055 case QShader::TessellationControlStage:
5058 case QShader::TessellationEvaluationStage:
5061 case QShader::GeometryStage:
5064 case QShader::FragmentStage:
5067 case QShader::ComputeStage:
5071 qWarning(
"compileHlslShaderSource: Unknown SM 5.0 stage (%d)",
int(shader.stage()));
5072 return QByteArray();
5076 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
5077 cacheKey.sourceHash = sourceHash(hlslSource.shader());
5078 cacheKey.target = target;
5079 cacheKey.entryPoint = hlslSource.entryPoint();
5081 auto cacheIt = m_bytecodeCache.data.constFind(cacheKey);
5082 if (cacheIt != m_bytecodeCache.data.constEnd())
5083 return cacheIt.value();
5086 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
5087 if (d3dCompile ==
nullptr) {
5088 qWarning(
"Unable to resolve function D3DCompile()");
5089 return QByteArray();
5092 ID3DBlob *bytecode =
nullptr;
5093 ID3DBlob *errors =
nullptr;
5094 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
5095 nullptr,
nullptr,
nullptr,
5096 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
5097 if (FAILED(hr) || !bytecode) {
5098 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
5100 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
5101 int(errors->GetBufferSize()));
5104 return QByteArray();
5108 result.resize(
int(bytecode->GetBufferSize()));
5109 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
5110 bytecode->Release();
5112 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
5113 m_bytecodeCache.insertWithCapacityLimit(cacheKey, result);
5124 rhiD->pipelineCreationStart();
5125 if (!rhiD->sanityCheckGraphicsPipeline(
this))
5128 D3D11_RASTERIZER_DESC rastDesc = {};
5129 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
5130 rastDesc.CullMode = toD3DCullMode(m_cullMode);
5131 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
5132 rastDesc.DepthBias = m_depthBias;
5133 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
5134 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
5135 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
5136 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
5137 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
5139 qWarning(
"Failed to create rasterizer state: %s",
5140 qPrintable(QSystemError::windowsComString(hr)));
5144 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
5145 dsDesc.DepthEnable = m_depthTest;
5146 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
5147 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
5148 dsDesc.StencilEnable = m_stencilTest;
5149 if (m_stencilTest) {
5150 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
5151 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
5152 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
5153 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
5154 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
5155 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
5156 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
5157 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
5158 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
5159 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
5161 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
5163 qWarning(
"Failed to create depth-stencil state: %s",
5164 qPrintable(QSystemError::windowsComString(hr)));
5168 D3D11_BLEND_DESC blendDesc = {};
5169 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
5170 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
5171 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
5172 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5173 blend.BlendEnable = b.enable;
5174 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
5175 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
5176 blend.BlendOp = toD3DBlendOp(b.opColor);
5177 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
5178 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
5179 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
5180 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
5181 blendDesc.RenderTarget[i] = blend;
5183 if (m_targetBlends.isEmpty()) {
5184 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5185 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
5186 blendDesc.RenderTarget[0] = blend;
5188 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
5190 qWarning(
"Failed to create blend state: %s",
5191 qPrintable(QSystemError::windowsComString(hr)));
5195 QByteArray vsByteCode;
5196 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
5197 int stagePushConstantRegister = -1;
5198 quint32 stagePushConstantSize = 0;
5199 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
5200 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5201 stagePushConstantRegister = cacheIt->pushConstantRegister;
5202 stagePushConstantSize = cacheIt->pushConstantSize;
5203 switch (shaderStage.type()) {
5204 case QRhiShaderStage::Vertex:
5205 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
5206 vs.shader->AddRef();
5207 vsByteCode = cacheIt->bytecode;
5208 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5210 case QRhiShaderStage::TessellationControl:
5211 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
5212 hs.shader->AddRef();
5213 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5215 case QRhiShaderStage::TessellationEvaluation:
5216 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
5217 ds.shader->AddRef();
5218 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5220 case QRhiShaderStage::Geometry:
5221 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
5222 gs.shader->AddRef();
5223 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5225 case QRhiShaderStage::Fragment:
5226 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
5227 fs.shader->AddRef();
5228 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5235 QShaderKey shaderKey;
5236 UINT compileFlags = 0;
5237 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5238 compileFlags |= D3DCOMPILE_DEBUG;
5240 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
5241 &error, &shaderKey);
5242 if (bytecode.isEmpty()) {
5243 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
5247 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
5249 rhiD->clearShaderCache();
5252 getPushConstantInfo(shaderStage.shader(), shaderKey, &stagePushConstantRegister, &stagePushConstantSize);
5254 switch (shaderStage.type()) {
5255 case QRhiShaderStage::Vertex:
5256 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
5258 qWarning(
"Failed to create vertex shader: %s",
5259 qPrintable(QSystemError::windowsComString(hr)));
5262 vsByteCode = bytecode;
5263 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5264 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap,
5265 stagePushConstantRegister, stagePushConstantSize));
5266 vs.shader->AddRef();
5268 case QRhiShaderStage::TessellationControl:
5269 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
5271 qWarning(
"Failed to create hull shader: %s",
5272 qPrintable(QSystemError::windowsComString(hr)));
5275 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5276 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap,
5277 stagePushConstantRegister, stagePushConstantSize));
5278 hs.shader->AddRef();
5280 case QRhiShaderStage::TessellationEvaluation:
5281 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
5283 qWarning(
"Failed to create domain shader: %s",
5284 qPrintable(QSystemError::windowsComString(hr)));
5287 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5288 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap,
5289 stagePushConstantRegister, stagePushConstantSize));
5290 ds.shader->AddRef();
5292 case QRhiShaderStage::Geometry:
5293 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
5295 qWarning(
"Failed to create geometry shader: %s",
5296 qPrintable(QSystemError::windowsComString(hr)));
5299 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5300 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap,
5301 stagePushConstantRegister, stagePushConstantSize));
5302 gs.shader->AddRef();
5304 case QRhiShaderStage::Fragment:
5305 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
5307 qWarning(
"Failed to create pixel shader: %s",
5308 qPrintable(QSystemError::windowsComString(hr)));
5311 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5312 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap,
5313 stagePushConstantRegister, stagePushConstantSize));
5314 fs.shader->AddRef();
5321 if (stagePushConstantRegister >= 0 && stagePushConstantSize) {
5322 const int stageIndex = rbmStageIndex(shaderStage.type());
5323 if (stageIndex >= 0) {
5324 pushConstants.reg = stagePushConstantRegister;
5325 pushConstants.size = qMax(pushConstants.size, stagePushConstantSize);
5326 pushConstants.stages |= 1u << uint(stageIndex);
5331 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
5333 if (!vsByteCode.isEmpty()) {
5334 QByteArrayList matrixSliceSemantics;
5335 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
5336 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
5339 D3D11_INPUT_ELEMENT_DESC desc = {};
5344 const int matrixSlice = it->matrixSlice();
5345 if (matrixSlice < 0) {
5346 desc.SemanticName =
"TEXCOORD";
5347 desc.SemanticIndex = UINT(it->location());
5351 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
5352 matrixSliceSemantics.append(sem);
5353 desc.SemanticName = matrixSliceSemantics.last().constData();
5354 desc.SemanticIndex = UINT(matrixSlice);
5356 desc.Format = toD3DAttributeFormat(it->format());
5357 desc.InputSlot = UINT(it->binding());
5358 desc.AlignedByteOffset = it->offset();
5359 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
5360 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
5361 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
5362 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
5364 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
5366 inputDescs.append(desc);
5368 if (!inputDescs.isEmpty()) {
5369 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
5370 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
5372 qWarning(
"Failed to create input layout: %s",
5373 qPrintable(QSystemError::windowsComString(hr)));
5379 rhiD->pipelineCreationEnd();
5381 rhiD->registerResource(
this);
5400 cs.shader->Release();
5401 cs.shader =
nullptr;
5402 cs.nativeResourceBindingMap.clear();
5407 rhiD->unregisterResource(
this);
5416 rhiD->pipelineCreationStart();
5418 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5419 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5420 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5421 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5422 pushConstants.reg = cacheIt->pushConstantRegister;
5423 pushConstants.size = cacheIt->pushConstantSize;
5426 QShaderKey shaderKey;
5427 UINT compileFlags = 0;
5428 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5429 compileFlags |= D3DCOMPILE_DEBUG;
5431 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5432 &error, &shaderKey);
5433 if (bytecode.isEmpty()) {
5434 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5438 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5440 qWarning(
"Failed to create compute shader: %s",
5441 qPrintable(QSystemError::windowsComString(hr)));
5445 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5446 getPushConstantInfo(m_shaderStage.shader(), shaderKey, &pushConstants.reg, &pushConstants.size);
5448 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5451 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap,
5452 pushConstants.reg, pushConstants.size));
5455 cs.shader->AddRef();
5457 rhiD->pipelineCreationEnd();
5459 rhiD->registerResource(
this);
5484 D3D11_QUERY_DESC queryDesc = {};
5486 if (!disjointQuery[i]) {
5487 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5488 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5490 qWarning(
"Failed to create timestamp disjoint query: %s",
5491 qPrintable(QSystemError::windowsComString(hr)));
5495 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5496 for (
int j = 0; j < 2; ++j) {
5497 const int idx = 2 * i + j;
5499 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5501 qWarning(
"Failed to create timestamp query: %s",
5502 qPrintable(QSystemError::windowsComString(hr)));
5515 if (disjointQuery[i]) {
5516 disjointQuery[i]->Release();
5517 disjointQuery[i] =
nullptr;
5519 for (
int j = 0; j < 2; ++j) {
5522 query[idx]->Release();
5523 query[idx] =
nullptr;
5531 bool result =
false;
5535 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5536 ID3D11Query *tsStart = query[pairIndex * 2];
5537 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5538 quint64 timestamps[2];
5539 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5542 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5543 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5544 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5547 if (!dj.Disjoint && dj.Frequency) {
5548 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5549 *elapsedSec = elapsedMs / 1000.0;
5552 active[pairIndex] =
false;
5561 backBufferTex =
nullptr;
5562 backBufferRtv =
nullptr;
5564 msaaTex[i] =
nullptr;
5565 msaaRtv[i] =
nullptr;
5576 if (backBufferRtv) {
5577 backBufferRtv->Release();
5578 backBufferRtv =
nullptr;
5580 if (backBufferRtvRight) {
5581 backBufferRtvRight->Release();
5582 backBufferRtvRight =
nullptr;
5584 if (backBufferTex) {
5585 backBufferTex->Release();
5586 backBufferTex =
nullptr;
5590 msaaRtv[i]->Release();
5591 msaaRtv[i] =
nullptr;
5594 msaaTex[i]->Release();
5595 msaaTex[i] =
nullptr;
5603 dcompVisual->Release();
5604 dcompVisual =
nullptr;
5608 dcompTarget->Release();
5609 dcompTarget =
nullptr;
5617 timestamps.destroy();
5619 swapChain->Release();
5620 swapChain =
nullptr;
5622 if (frameLatencyWaitableObject) {
5623 CloseHandle(frameLatencyWaitableObject);
5624 frameLatencyWaitableObject =
nullptr;
5627 QDxgiVSyncService::instance()->unregisterWindow(window);
5631 rhiD->unregisterResource(
this);
5634 rhiD->context->Flush();
5650 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5656 return m_window->size() * m_window->devicePixelRatio();
5665 qWarning(
"Attempted to call isFormatSupported() without a window set");
5670 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5671 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5682 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5691 rhiD->registerResource(rpD,
false);
5696 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5698 D3D11_TEXTURE2D_DESC desc = {};
5699 desc.Width = UINT(size.width());
5700 desc.Height = UINT(size.height());
5703 desc.Format = format;
5704 desc.SampleDesc = sampleDesc;
5705 desc.Usage = D3D11_USAGE_DEFAULT;
5706 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5709 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5711 qWarning(
"Failed to create color buffer texture: %s",
5712 qPrintable(QSystemError::windowsComString(hr)));
5716 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5717 rtvDesc.Format = format;
5718 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5719 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5721 qWarning(
"Failed to create color buffer rtv: %s",
5722 qPrintable(QSystemError::windowsComString(hr)));
5736 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5737 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5738 return dcompDevice ?
true :
false;
5750 const bool needsRegistration = !
window ||
window != m_window;
5751 const bool stereo = m_window->format().stereo();
5754 if (window && window != m_window)
5758 m_currentPixelSize = surfacePixelSize();
5759 pixelSize = m_currentPixelSize;
5761 if (pixelSize.isEmpty())
5764 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5769 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5772 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5774 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5775 qPrintable(QSystemError::windowsComString(hr)));
5778 if (dcompTarget && !dcompVisual) {
5779 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5781 qWarning(
"Failed to create DirectComposition visual: %s",
5782 qPrintable(QSystemError::windowsComString(hr)));
5787 if (
window->requestedFormat().alphaBufferSize() <= 0)
5788 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5789 "This may lead to problems.");
5792 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5799 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5800 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5804 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5805 && swapInterval != 0
5806 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5808 if (useFrameLatencyWaitableObject) {
5810 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5814 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5815 colorFormat = DEFAULT_FORMAT;
5816 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5818 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5819 if (m_format != SDR) {
5820 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5823 case HDRExtendedSrgbLinear:
5824 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5825 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5826 srgbAdjustedColorFormat = colorFormat;
5829 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5830 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5831 srgbAdjustedColorFormat = colorFormat;
5840 qWarning(
"The output associated with the window is not HDR capable "
5841 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5851 DXGI_SWAP_CHAIN_DESC1 desc = {};
5852 desc.Width = UINT(pixelSize.width());
5853 desc.Height = UINT(pixelSize.height());
5854 desc.Format = colorFormat;
5855 desc.SampleDesc.Count = 1;
5856 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5858 desc.Flags = swapChainFlags;
5859 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5860 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5861 desc.Stereo = stereo;
5867 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5872 desc.Scaling = DXGI_SCALING_STRETCH;
5875 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5876 IDXGISwapChain1 *sc1;
5879 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5881 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5886 if (FAILED(hr) && m_format != SDR) {
5887 colorFormat = DEFAULT_FORMAT;
5888 desc.Format = DEFAULT_FORMAT;
5890 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5892 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5895 if (SUCCEEDED(hr)) {
5897 IDXGISwapChain3 *sc3 =
nullptr;
5898 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5899 if (m_format != SDR) {
5900 hr = sc3->SetColorSpace1(hdrColorSpace);
5902 qWarning(
"Failed to set color space on swapchain: %s",
5903 qPrintable(QSystemError::windowsComString(hr)));
5905 if (useFrameLatencyWaitableObject) {
5906 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5907 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5911 if (m_format != SDR)
5912 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5913 if (useFrameLatencyWaitableObject) {
5914 IDXGISwapChain2 *sc2 =
nullptr;
5915 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5916 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5917 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5920 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5925 hr = dcompVisual->SetContent(sc1);
5926 if (SUCCEEDED(hr)) {
5927 hr = dcompTarget->SetRoot(dcompVisual);
5929 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5930 qPrintable(QSystemError::windowsComString(hr)));
5933 qWarning(
"Failed to set content for Direct Composition visual: %s",
5934 qPrintable(QSystemError::windowsComString(hr)));
5938 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5941 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5942 qWarning(
"Device loss detected during swapchain creation");
5945 }
else if (FAILED(hr)) {
5946 qWarning(
"Failed to create D3D11 swapchain: %s"
5947 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5948 qPrintable(QSystemError::windowsComString(hr)),
5949 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5950 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5956 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5957 colorFormat, swapChainFlags);
5958 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5959 qWarning(
"Device loss detected in ResizeBuffers()");
5962 }
else if (FAILED(hr)) {
5963 qWarning(
"Failed to resize D3D11 swapchain: %s",
5964 qPrintable(QSystemError::windowsComString(hr)));
5983 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5985 qWarning(
"Failed to query swapchain backbuffer: %s",
5986 qPrintable(QSystemError::windowsComString(hr)));
5989 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5990 rtvDesc.Format = srgbAdjustedColorFormat;
5991 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5992 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5994 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5995 qPrintable(QSystemError::windowsComString(hr)));
6001 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
6002 rtvDesc.Texture2DArray.FirstArraySlice = 1;
6003 rtvDesc.Texture2DArray.ArraySize = 1;
6004 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
6006 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
6007 qPrintable(QSystemError::windowsComString(hr)));
6014 if (sampleDesc.Count > 1) {
6015 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
6020 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
6021 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
6022 m_depthStencil->sampleCount(), m_sampleCount);
6024 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
6025 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
6026 m_depthStencil->setPixelSize(pixelSize);
6027 if (!m_depthStencil->create())
6028 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
6029 pixelSize.width(), pixelSize.height());
6031 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
6032 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
6033 pixelSize.width(), pixelSize.height());
6040 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
6042 rt.setRenderPassDescriptor(m_renderPassDesc);
6044 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
6045 rtD->d.pixelSize = pixelSize;
6046 rtD->d.dpr =
float(
window->devicePixelRatio());
6047 rtD->d.sampleCount =
int(sampleDesc.Count);
6048 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
6051 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
6052 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
6053 rtD->d.pixelSize = pixelSize;
6054 rtD->d.dpr =
float(
window->devicePixelRatio());
6055 rtD->d.sampleCount =
int(sampleDesc.Count);
6056 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
6059 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
6060 timestamps.prepare(rhiD);
6064 QDxgiVSyncService::instance()->registerWindow(window);
6066 if (needsRegistration)
6067 rhiD->registerResource(
this);
6075 if (rtViews.dsv != currentRtViews.dsv) {
6076 rtViews.dsv = currentRtViews.dsv;
6080 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
6081 rtViews.rtv[i] = currentRtViews.rtv[i];
6083 rtViews.colorAttCount = currentRtViews.colorAttCount;
6085 ret |= rtViews.rtv[i] !=
nullptr;
6086 rtViews.rtv[i] =
nullptr;
6088 for (
int i = 0; i < count; i++) {
6089 ret |= uav[i] != uavs[i];
6093 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[], uint pushConstantStages)
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
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
void executeBufferHostWrites(QD3D11Buffer *bufD)
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
void dispatchIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset) override
QRhiGraphicsPipeline * createGraphicsPipeline() override
void drawIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) 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
QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags, QString *error, QShaderKey *usedShaderKey)
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
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)
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
void setPushConstants(QRhiCommandBuffer *cb, quint32 offset, quint32 size, const void *data) 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
bool ensurePushConstantBuffer()
void drawIndexedIndirectCount(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, QRhiBuffer *countBuffer, quint32 countBufferOffset, quint32 maxDrawCount, quint32 stride) 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
void finishActiveReadbacks()
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 bindShaderResources(QD3D11CommandBuffer *cbD, const QD3D11ShaderResourceBindings::ResourceBatches &allResourceBatches, const uint *dynOfsPairs, int dynOfsPairCount, bool offsetOnlyChange, QD3D11RenderTargetUavUpdateState *rtUavState)
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
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
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 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 std::pair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[], uint pushConstantStages)
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 int rbmStageIndex(QRhiShaderStage::Type type)
static DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
static void getPushConstantInfo(const QShader &shader, const QShaderKey &key, int *reg, quint32 *size)
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.
ID3D11UnorderedAccessView * createClearUnorderedAccessView(quint32 offset, quint32 size)
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 std::shared_ptr< QD3D11ShaderResourceBindings::ResourceBatches > &resourceBatches)
QD3D11CommandBuffer(QRhiImplementation *rhi)
uint currentPipelineGeneration
uint currentSrbGeneration
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