11#include <QtCore/qcryptographichash.h>
12#include <QtCore/private/qsystemerror_p.h>
19using namespace Qt::StringLiterals;
22
23
24
25
26
27
28
29
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
79
80
81
82
83
87
88
89
90
91
92
93
94
95
96
97
98
101
102
103
104
105
106
107
108
111
112
113
114
115
116
117
120
121
122
123
124
125
126
127
130
131
132
133
134
135
138
139
140
141
142
143
146#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
147#define DXGI_ADAPTER_FLAG_SOFTWARE 2
150#ifndef D3D11_1_UAV_SLOT_COUNT
151#define D3D11_1_UAV_SLOT_COUNT 64
154#ifndef D3D11_VS_INPUT_REGISTER_COUNT
155#define D3D11_VS_INPUT_REGISTER_COUNT 32
164 if (importParams->dev && importParams->context) {
165 dev =
reinterpret_cast<ID3D11Device *>(importParams->dev);
166 ID3D11DeviceContext *ctx =
reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
167 if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)))) {
172 qWarning(
"ID3D11DeviceContext1 not supported by context, cannot import");
175 featureLevel = D3D_FEATURE_LEVEL(importParams->featureLevel);
176 adapterLuid.LowPart = importParams->adapterLuidLow;
177 adapterLuid.HighPart = importParams->adapterLuidHigh;
184 return (v + byteAlign - 1) & ~(byteAlign - 1);
189 IDXGIFactory1 *result =
nullptr;
190 const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&result));
192 qWarning(
"CreateDXGIFactory2() failed to create DXGI factory: %s",
193 qPrintable(QSystemError::windowsComString(hr)));
205 devFlags |= D3D11_CREATE_DEVICE_DEBUG;
207 dxgiFactory = createDXGIFactory2();
215 IDXGIFactory5 *factory5 =
nullptr;
216 if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5),
reinterpret_cast<
void **>(&factory5)))) {
217 BOOL allowTearing =
false;
218 if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing,
sizeof(allowTearing))))
223 if (qEnvironmentVariableIntValue(
"QT_D3D_FLIP_DISCARD"))
224 qWarning(
"The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
232 if (qEnvironmentVariableIsSet(
"QT_D3D_MAX_FRAME_LATENCY"))
233 maxFrameLatency = UINT(qMax(0, qEnvironmentVariableIntValue(
"QT_D3D_MAX_FRAME_LATENCY")));
238 qCDebug(QRHI_LOG_INFO,
"FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s, max frame latency = %u",
242 if (maxFrameLatency == 0)
243 qCDebug(QRHI_LOG_INFO,
"Disabling FRAME_LATENCY_WAITABLE_OBJECT usage");
245 activeAdapter =
nullptr;
248 IDXGIAdapter1 *adapter;
249 int requestedAdapterIndex = -1;
250 if (qEnvironmentVariableIsSet(
"QT_D3D_ADAPTER_INDEX"))
251 requestedAdapterIndex = qEnvironmentVariableIntValue(
"QT_D3D_ADAPTER_INDEX");
253 if (requestedRhiAdapter)
254 adapterLuid =
static_cast<QD3D11Adapter *>(requestedRhiAdapter)->luid;
257 if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
258 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
259 DXGI_ADAPTER_DESC1 desc;
260 adapter->GetDesc1(&desc);
262 if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
263 && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
265 requestedAdapterIndex = adapterIndex;
271 if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
272 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
273 DXGI_ADAPTER_DESC1 desc;
274 adapter->GetDesc1(&desc);
277 requestedAdapterIndex = adapterIndex;
283 for (
int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
284 DXGI_ADAPTER_DESC1 desc;
285 adapter->GetDesc1(&desc);
286 const QString name = QString::fromUtf16(
reinterpret_cast<
char16_t *>(desc.Description));
287 qCDebug(QRHI_LOG_INFO,
"Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
293 if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
294 activeAdapter = adapter;
295 adapterLuid = desc.AdapterLuid;
297 qCDebug(QRHI_LOG_INFO,
" using this adapter");
302 if (!activeAdapter) {
303 qWarning(
"No adapter");
309 QVarLengthArray<D3D_FEATURE_LEVEL, 4> requestedFeatureLevels;
310 bool requestFeatureLevels =
false;
312 requestFeatureLevels =
true;
313 requestedFeatureLevels.append(featureLevel);
316 ID3D11DeviceContext *ctx =
nullptr;
317 HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
318 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
319 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
321 &dev, &featureLevel, &ctx);
323 if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING && debugLayer) {
324 qCDebug(QRHI_LOG_INFO,
"Debug layer was requested but is not available. "
325 "Attempting to create D3D11 device without it.");
326 devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
327 hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, devFlags,
328 requestFeatureLevels ? requestedFeatureLevels.constData() :
nullptr,
329 requestFeatureLevels ? requestedFeatureLevels.count() : 0,
331 &dev, &featureLevel, &ctx);
334 qWarning(
"Failed to create D3D11 device and context: %s",
335 qPrintable(QSystemError::windowsComString(hr)));
339 const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<
void **>(&context)));
342 qWarning(
"ID3D11DeviceContext1 not supported");
348 ID3D11VertexShader *testShader =
nullptr;
349 if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader,
sizeof(g_testVertexShader),
nullptr, &testShader))) {
350 testShader->Release();
352 static const char *msg =
"D3D11 smoke test: Failed to create vertex shader";
353 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
354 qCDebug(QRHI_LOG_INFO,
"%s", msg);
360 D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
361 if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features,
sizeof(features)))) {
365 if (!features.ConstantBufferOffsetting) {
366 static const char *msg =
"D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
367 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
368 qCDebug(QRHI_LOG_INFO,
"%s", msg);
374 static const char *msg =
"D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
375 if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
376 qCDebug(QRHI_LOG_INFO,
"%s", msg);
382 Q_ASSERT(dev && context);
383 featureLevel = dev->GetFeatureLevel();
384 IDXGIDevice *dxgiDev =
nullptr;
385 if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<
void **>(&dxgiDev)))) {
386 IDXGIAdapter *adapter =
nullptr;
387 if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
388 IDXGIAdapter1 *adapter1 =
nullptr;
389 if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1),
reinterpret_cast<
void **>(&adapter1)))) {
390 DXGI_ADAPTER_DESC1 desc;
391 adapter1->GetDesc1(&desc);
392 adapterLuid = desc.AdapterLuid;
394 activeAdapter = adapter1;
400 if (!activeAdapter) {
401 qWarning(
"Failed to query adapter from imported device");
404 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
407 QDxgiVSyncService::instance()->refAdapter(adapterLuid);
409 if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation),
reinterpret_cast<
void **>(&annotations))))
410 annotations =
nullptr;
414 nativeHandlesStruct.dev = dev;
415 nativeHandlesStruct.context = context;
416 nativeHandlesStruct.featureLevel = featureLevel;
417 nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
418 nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
425 for (
const Shader &s : std::as_const(m_shaderCache))
428 m_shaderCache.clear();
437 if (pushConstantBuffer) {
438 pushConstantBuffer->Release();
439 pushConstantBuffer =
nullptr;
442 if (ofr.tsDisjointQuery) {
443 ofr.tsDisjointQuery->Release();
444 ofr.tsDisjointQuery =
nullptr;
446 for (
int i = 0; i < 2; ++i) {
447 if (ofr.tsQueries[i]) {
448 ofr.tsQueries[i]->Release();
449 ofr.tsQueries[i] =
nullptr;
454 annotations->Release();
455 annotations =
nullptr;
470 dcompDevice->Release();
471 dcompDevice =
nullptr;
475 activeAdapter->Release();
476 activeAdapter =
nullptr;
480 dxgiFactory->Release();
481 dxgiFactory =
nullptr;
484 QDxgiVSyncService::instance()->derefAdapter(adapterLuid);
494 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug),
reinterpret_cast<
void **>(&debug)))) {
495 debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
500QRhi::AdapterList
QRhiD3D11::enumerateAdaptersBeforeCreate(QRhiNativeHandles *nativeHandles)
const
502 LUID requestedLuid = {};
504 QRhiD3D11NativeHandles *h =
static_cast<QRhiD3D11NativeHandles *>(nativeHandles);
505 const LUID adapterLuid = { h->adapterLuidLow, h->adapterLuidHigh };
506 if (adapterLuid.LowPart || adapterLuid.HighPart)
507 requestedLuid = adapterLuid;
510 IDXGIFactory1 *dxgi = createDXGIFactory2();
514 QRhi::AdapterList list;
515 IDXGIAdapter1 *adapter;
516 for (
int adapterIndex = 0; dxgi->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
517 DXGI_ADAPTER_DESC1 desc;
518 adapter->GetDesc1(&desc);
520 if (requestedLuid.LowPart || requestedLuid.HighPart) {
521 if (desc.AdapterLuid.LowPart != requestedLuid.LowPart
522 || desc.AdapterLuid.HighPart != requestedLuid.HighPart)
527 QD3D11Adapter *a =
new QD3D11Adapter;
528 a->luid = desc.AdapterLuid;
529 QRhiD3D::fillDriverInfo(&a->adapterInfo, desc);
544 return { 1, 2, 4, 8 };
549 Q_UNUSED(sampleCount);
550 return { QSize(1, 1) };
555 DXGI_SAMPLE_DESC desc;
559 const int s = effectiveSampleCount(sampleCount);
561 desc.Count = UINT(s);
563 desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
572 return new QD3D11SwapChain(
this);
575QRhiBuffer *
QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
577 return new QD3D11Buffer(
this, type, usage, size);
605 static constexpr QMatrix4x4 m(1.0f, 0.0f, 0.0f, 0.0f,
606 0.0f, 1.0f, 0.0f, 0.0f,
607 0.0f, 0.0f, 0.5f, 0.5f,
608 0.0f, 0.0f, 0.0f, 1.0f);
616 if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
625 case QRhi::MultisampleTexture:
627 case QRhi::MultisampleRenderBuffer:
629 case QRhi::DebugMarkers:
630 return annotations !=
nullptr;
631 case QRhi::Timestamps:
633 case QRhi::Instancing:
635 case QRhi::CustomInstanceStepRate:
637 case QRhi::PrimitiveRestart:
639 case QRhi::NonDynamicUniformBuffers:
641 case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
643 case QRhi::NPOTTextureRepeat:
645 case QRhi::RedOrAlpha8IsRed:
647 case QRhi::ElementIndexUint:
652 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
653 case QRhi::WideLines:
655 case QRhi::VertexShaderPointSize:
657 case QRhi::BaseVertex:
659 case QRhi::BaseInstance:
661 case QRhi::TriangleFanTopology:
663 case QRhi::ReadBackNonUniformBuffer:
665 case QRhi::ReadBackNonBaseMipLevel:
667 case QRhi::TexelFetch:
669 case QRhi::RenderToNonBaseMipLevel:
671 case QRhi::IntAttributes:
673 case QRhi::ScreenSpaceDerivatives:
675 case QRhi::ReadBackAnyTextureFormat:
677 case QRhi::PipelineCacheDataLoadSave:
679 case QRhi::ImageDataStride:
681 case QRhi::RenderBufferImport:
683 case QRhi::ThreeDimensionalTextures:
685 case QRhi::RenderTo3DTextureSlice:
687 case QRhi::TextureArrays:
689 case QRhi::Tessellation:
691 case QRhi::GeometryShader:
693 case QRhi::TextureArrayRange:
695 case QRhi::NonFillPolygonMode:
697 case QRhi::OneDimensionalTextures:
699 case QRhi::OneDimensionalTextureMipmaps:
701 case QRhi::HalfAttributes:
703 case QRhi::RenderToOneDimensionalTexture:
705 case QRhi::ThreeDimensionalTextureMipmaps:
707 case QRhi::MultiView:
709 case QRhi::TextureViewFormat:
711 case QRhi::ResolveDepthStencil:
713 case QRhi::VariableRateShading:
715 case QRhi::VariableRateShadingMap:
716 case QRhi::VariableRateShadingMapWithTexture:
718 case QRhi::PerRenderTargetBlending:
719 case QRhi::SampleVariables:
721 case QRhi::InstanceIndexIncludesBaseInstance:
723 case QRhi::DepthClamp:
725 case QRhi::DrawIndirect:
726 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
727 case QRhi::DrawIndirectMulti:
728 case QRhi::ShaderDrawParameters:
730 case QRhi::PushConstants:
732 case QRhi::DrawIndirectCount:
734 case QRhi::DispatchIndirect:
735 return featureLevel >= D3D_FEATURE_LEVEL_11_0;
736 case QRhi::BufferToBufferCopy:
738 case QRhi::StaticBuffersOnGpuTimeline:
749 case QRhi::TextureSizeMin:
751 case QRhi::TextureSizeMax:
752 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
753 case QRhi::MaxColorAttachments:
755 case QRhi::FramesInFlight:
761 case QRhi::MaxAsyncReadbackFrames:
763 case QRhi::MaxThreadGroupsPerDimension:
764 return D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
765 case QRhi::MaxThreadsPerThreadGroup:
766 return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
767 case QRhi::MaxThreadGroupX:
768 return D3D11_CS_THREAD_GROUP_MAX_X;
769 case QRhi::MaxThreadGroupY:
770 return D3D11_CS_THREAD_GROUP_MAX_Y;
771 case QRhi::MaxThreadGroupZ:
772 return D3D11_CS_THREAD_GROUP_MAX_Z;
773 case QRhi::TextureArraySizeMax:
774 return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
775 case QRhi::MaxUniformBufferRange:
777 case QRhi::MaxVertexInputs:
779 case QRhi::MaxVertexOutputs:
780 return D3D11_VS_OUTPUT_REGISTER_COUNT;
781 case QRhi::MaxVertexStorageBuffers:
783 case QRhi::MaxPushConstantsSize:
785 return int(MAX_PUSH_CONSTANTS_SIZE);
786 case QRhi::MaxFragmentStorageBuffers:
787 return featureLevel >= D3D_FEATURE_LEVEL_11_1
789 case QRhi::ShadingRateImageTileSize:
799 return &nativeHandlesStruct;
804 return driverInfoStruct;
810 result.totalPipelineCreationTime = totalPipelineCreationTime();
820void QRhiD3D11::setQueueSubmitParams(QRhiNativeHandles *)
828 m_bytecodeCache.clear();
848 if (m_bytecodeCache.data.isEmpty())
852 memset(&header, 0,
sizeof(header));
853 header.rhiId = pipelineCacheRhiId();
854 header.arch = quint32(
sizeof(
void*));
855 header.count = m_bytecodeCache.data.count();
857 const size_t dataOffset =
sizeof(header);
859 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
861 QByteArray bytecode = it.value();
863 sizeof(quint32) + key.sourceHash.size()
864 +
sizeof(quint32) + key.target.size()
865 +
sizeof(quint32) + key.entryPoint.size()
867 +
sizeof(quint32) + bytecode.size();
870 QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
871 char *p = buf.data() + dataOffset;
872 for (
auto it = m_bytecodeCache.data.cbegin(), end = m_bytecodeCache.data.cend(); it != end; ++it) {
874 QByteArray bytecode = it.value();
876 quint32 i = key.sourceHash.size();
879 memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
880 p += key.sourceHash.size();
882 i = key.target.size();
885 memcpy(p, key.target.constData(), key.target.size());
886 p += key.target.size();
888 i = key.entryPoint.size();
891 memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
892 p += key.entryPoint.size();
901 memcpy(p, bytecode.constData(), bytecode.size());
902 p += bytecode.size();
904 Q_ASSERT(p == buf.data() + dataOffset + dataSize);
906 header.dataSize = quint32(dataSize);
907 memcpy(buf.data(), &header,
sizeof(header));
918 if (data.size() < qsizetype(headerSize)) {
919 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
922 const size_t dataOffset = headerSize;
924 memcpy(&header, data.constData(), headerSize);
926 const quint32 rhiId = pipelineCacheRhiId();
927 if (header.rhiId != rhiId) {
928 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
929 rhiId, header.rhiId);
932 const quint32 arch = quint32(
sizeof(
void*));
933 if (header.arch != arch) {
934 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
938 if (header.count == 0)
941 if (quint64(data.size()) < quint64(dataOffset) + header.dataSize) {
942 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
946 m_bytecodeCache.clear();
949 for (quint32 i = 0; i < header.count; ++i) {
953 if (!reader.readByteArray(&cacheKey.sourceHash)
954 || !reader.readByteArray(&cacheKey.target)
955 || !reader.readByteArray(&cacheKey.entryPoint)
956 || !reader.readUInt32(&flags)
957 || !reader.readByteArray(&bytecode))
959 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob (truncated or corrupt bytecode data)");
960 m_bytecodeCache.clear();
965 m_bytecodeCache.insertWithCapacityLimit(cacheKey, bytecode);
968 qCDebug(QRHI_LOG_INFO,
"Seeded bytecode cache with %d shaders",
int(m_bytecodeCache.data.count()));
971QRhiRenderBuffer *
QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
972 int sampleCount, QRhiRenderBuffer::Flags flags,
973 QRhiTexture::Format backingFormatHint)
975 return new QD3D11RenderBuffer(
this, type, pixelSize, sampleCount, flags, backingFormatHint);
979 const QSize &pixelSize,
int depth,
int arraySize,
980 int sampleCount, QRhiTexture::Flags flags)
982 return new QD3D11Texture(
this, format, pixelSize, depth, arraySize, sampleCount, flags);
986 QRhiSampler::Filter mipmapMode,
987 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
989 return new QD3D11Sampler(
this, magFilter, minFilter, mipmapMode, u, v, w);
993 QRhiTextureRenderTarget::Flags flags)
1005 return new QD3D11GraphicsPipeline(
this);
1010 return new QD3D11ComputePipeline(
this);
1015 return new QD3D11ShaderResourceBindings(
this);
1025 if (pipelineChanged) {
1026 cbD->currentGraphicsPipeline = ps;
1027 cbD->currentComputePipeline =
nullptr;
1032 cmd.args.bindGraphicsPipeline.topology = psD->d3dTopology;
1033 cmd.args.bindGraphicsPipeline.inputLayout = psD->inputLayout;
1034 cmd.args.bindGraphicsPipeline.dsState = psD->dsState;
1035 cmd.args.bindGraphicsPipeline.blendState = psD->blendState;
1036 cmd.args.bindGraphicsPipeline.rastState = psD->rastState;
1037 cmd.args.bindGraphicsPipeline.vs = psD->vs.shader;
1038 cmd.args.bindGraphicsPipeline.hs = psD->hs.shader;
1039 cmd.args.bindGraphicsPipeline.ds = psD->ds.shader;
1040 cmd.args.bindGraphicsPipeline.gs = psD->gs.shader;
1041 cmd.args.bindGraphicsPipeline.fs = psD->fs.shader;
1056 case QRhiShaderStage::Vertex:
1058 case QRhiShaderStage::TessellationControl:
1060 case QRhiShaderStage::TessellationEvaluation:
1062 case QRhiShaderStage::Geometry:
1063 return RBM_GEOMETRY;
1064 case QRhiShaderStage::Fragment:
1065 return RBM_FRAGMENT;
1066 case QRhiShaderStage::Compute:
1077 const QList<QShaderDescription::PushConstantBlock> blocks = shader.description().pushConstantBlocks();
1078 if (blocks.isEmpty())
1080 *reg = shader.nativeShaderInfo(key).extraBufferBindings.value(QShaderPrivate::HlslPushConstantBufferBinding, -1);
1081 *size = quint32((blocks.first().size + 3) & ~3);
1085 int dynamicOffsetCount,
1086 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
1095 srb = gfxPsD->m_shaderResourceBindings;
1097 srb = compPsD->m_shaderResourceBindings;
1102 bool pipelineChanged =
false;
1111 bool srbUpdate =
false;
1112 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
1113 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
1116 case QRhiShaderResourceBinding::UniformBuffer:
1120 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic && bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
1121 sanityCheckResourceOwnership(bufD);
1125 if (bufD
->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
1127 bd.ubuf.id = bufD->m_id;
1132 case QRhiShaderResourceBinding::SampledTexture:
1133 case QRhiShaderResourceBinding::Texture:
1134 case QRhiShaderResourceBinding::Sampler:
1136 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex;
1137 if (bd.stex.d.size() != data->count()) {
1138 bd.stex.d.resize(data->count());
1141 for (
int elem = 0; elem < data->count(); ++elem) {
1147 Q_ASSERT(texD || samplerD);
1148 sanityCheckResourceOwnership(texD);
1149 sanityCheckResourceOwnership(samplerD);
1150 const quint64 texId = texD ? texD->m_id : 0;
1152 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
1153 const uint samplerGen = samplerD ? samplerD
->generation : 0;
1154 if (texGen != bd.stex.d[elem].texGeneration
1155 || texId != bd.stex.d[elem].texId
1156 || samplerGen != bd.stex.d[elem].samplerGeneration
1157 || samplerId != bd.stex.d[elem].samplerId)
1160 bd.stex.d[elem].texId = texId;
1161 bd.stex.d[elem].texGeneration = texGen;
1162 bd.stex.d[elem].samplerId = samplerId;
1163 bd.stex.d[elem].samplerGeneration = samplerGen;
1168 case QRhiShaderResourceBinding::ImageLoad:
1169 case QRhiShaderResourceBinding::ImageStore:
1170 case QRhiShaderResourceBinding::ImageLoadStore:
1173 sanityCheckResourceOwnership(texD);
1174 if (texD
->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
1176 bd.simage.id = texD->m_id;
1181 case QRhiShaderResourceBinding::BufferLoad:
1182 case QRhiShaderResourceBinding::BufferStore:
1183 case QRhiShaderResourceBinding::BufferLoadStore:
1186 sanityCheckResourceOwnership(bufD);
1187 if (bufD
->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
1189 bd.sbuf.id = bufD->m_id;
1200 if (srbUpdate || pipelineChanged) {
1202 memset(resBindMaps, 0,
sizeof(resBindMaps));
1203 uint pushConstantStages = 0;
1205 resBindMaps[
RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
1206 resBindMaps[
RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
1207 resBindMaps[
RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
1208 resBindMaps[
RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
1209 resBindMaps[
RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
1210 pushConstantStages = gfxPsD->pushConstants.stages;
1212 resBindMaps[
RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
1213 if (compPsD->pushConstants.reg >= 0 && compPsD->pushConstants.size)
1216 updateShaderResourceBindings(srbD, resBindMaps, pushConstantStages);
1219 const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
1222 if (pipelineChanged || srbChanged || srbRebuilt || srbUpdate || srbD
->hasDynamicOffset) {
1224 cbD->currentGraphicsSrb = srb;
1225 cbD->currentComputeSrb =
nullptr;
1227 cbD->currentGraphicsSrb =
nullptr;
1228 cbD->currentComputeSrb = srb;
1237 cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD
->hasDynamicOffset;
1238 cmd.args.bindShaderResources.dynamicOffsetCount = 0;
1241 cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
1242 uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
1243 for (
int i = 0; i < dynamicOffsetCount; ++i) {
1244 const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
1245 const uint binding = uint(dynOfs.first);
1246 Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
1247 const quint32 offsetInConstants = dynOfs.second / 16;
1249 *p++ = offsetInConstants;
1252 qWarning(
"Too many dynamic offsets (%d, max is %d)",
1260 int startBinding,
int bindingCount,
const QRhiCommandBuffer::VertexInput *bindings,
1261 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
1266 bool needsBindVBuf =
false;
1267 for (
int i = 0; i < bindingCount; ++i) {
1268 const int inputSlot = startBinding + i;
1270 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
1271 if (bufD->m_type == QRhiBuffer::Dynamic)
1274 if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
1275 || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
1277 needsBindVBuf =
true;
1278 cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
1279 cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
1283 if (needsBindVBuf) {
1286 cmd.args.bindVertexBuffers.startSlot = startBinding;
1288 qWarning(
"Too many vertex buffer bindings (%d, max is %d)",
1292 cmd.args.bindVertexBuffers.slotCount = bindingCount;
1294 const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
1295 const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
1296 for (
int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
1298 cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
1299 cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
1300 cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride();
1306 Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
1307 if (ibufD->m_type == QRhiBuffer::Dynamic)
1310 const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
1311 : DXGI_FORMAT_R32_UINT;
1312 if (cbD->currentIndexBuffer != ibufD->buffer
1313 || cbD->currentIndexOffset != indexOffset
1314 || cbD->currentIndexFormat != dxgiFormat)
1316 cbD->currentIndexBuffer = ibufD->buffer;
1317 cbD->currentIndexOffset = indexOffset;
1318 cbD->currentIndexFormat = dxgiFormat;
1322 cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
1323 cmd.args.bindIndexBuffer.offset = indexOffset;
1324 cmd.args.bindIndexBuffer.format = dxgiFormat;
1333 Q_ASSERT(cbD->currentTarget);
1334 const QSize outputSize = cbD->currentTarget->pixelSize();
1338 if (!qrhi_toTopLeftRenderTargetRect<
UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
1343 cmd.args.viewport.x = x;
1344 cmd.args.viewport.y = y;
1345 cmd.args.viewport.w = w;
1346 cmd.args.viewport.h = h;
1347 cmd.args.viewport.d0 = viewport.minDepth();
1348 cmd.args.viewport.d1 = viewport.maxDepth();
1355 Q_ASSERT(cbD->currentTarget);
1356 const QSize outputSize = cbD->currentTarget->pixelSize();
1360 if (!qrhi_toTopLeftRenderTargetRect<
Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
1365 cmd.args.scissor.x = x;
1366 cmd.args.scissor.y = y;
1367 cmd.args.scissor.w = w;
1368 cmd.args.scissor.h = h;
1379 cmd.args.blendConstants.c[0] =
float(c.redF());
1380 cmd.args.blendConstants.c[1] =
float(c.greenF());
1381 cmd.args.blendConstants.c[2] =
float(c.blueF());
1382 cmd.args.blendConstants.c[3] =
float(c.alphaF());
1393 cmd.args.stencilRef.ref = refValue;
1402 quint32 blockSize = 0;
1408 reg = psD->pushConstants.reg;
1409 blockSize = psD->pushConstants.size;
1415 reg = psD->pushConstants.reg;
1416 blockSize = psD->pushConstants.size;
1417 stages = psD->pushConstants.stages;
1419 if (reg < 0 || !blockSize || !stages) {
1420 qWarning(
"No pipeline with a push constant block is active; setPushConstants ignored");
1424 if (offset + size > MAX_PUSH_CONSTANTS_SIZE) {
1425 qWarning(
"Push constant data of %u bytes at offset %u exceeds the %u byte maximum; "
1426 "setPushConstants ignored", size, offset, MAX_PUSH_CONSTANTS_SIZE);
1435 const quint32 total = qMin(qMax(blockSize, offset + size), MAX_PUSH_CONSTANTS_SIZE);
1436 if (quint32(cbD->pushConstantData.size()) < total)
1437 cbD->pushConstantData.resize(
int(total), 0);
1438 memcpy(cbD->pushConstantData.data() + offset, data, size);
1440 const quint32 dataOffset = quint32(cbD->pushConstantPool.size());
1441 cbD->pushConstantPool.append(cbD->pushConstantData.constData(), total);
1445 cmd.args.setPushConstants.buffer = pushConstantBuffer;
1446 cmd.args.setPushConstants.dataOffset = dataOffset;
1447 cmd.args.setPushConstants.size = total;
1448 cmd.args.setPushConstants.startSlot = uint(reg);
1449 cmd.args.setPushConstants.stages = stages;
1454 if (pushConstantBuffer)
1457 D3D11_BUFFER_DESC desc = {};
1458 desc.ByteWidth = aligned(MAX_PUSH_CONSTANTS_SIZE, 256u);
1459 desc.Usage = D3D11_USAGE_DYNAMIC;
1460 desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1461 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1462 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &pushConstantBuffer);
1464 qWarning(
"Failed to create push constant buffer: %s",
1465 qPrintable(QSystemError::windowsComString(hr)));
1466 pushConstantBuffer =
nullptr;
1475 Q_UNUSED(coarsePixelSize);
1479 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
1486 cmd.args.draw.vertexCount = vertexCount;
1487 cmd.args.draw.instanceCount = instanceCount;
1488 cmd.args.draw.firstVertex = firstVertex;
1489 cmd.args.draw.firstInstance = firstInstance;
1493 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
1500 cmd.args.drawIndexed.indexCount = indexCount;
1501 cmd.args.drawIndexed.instanceCount = instanceCount;
1502 cmd.args.drawIndexed.firstIndex = firstIndex;
1503 cmd.args.drawIndexed.vertexOffset = vertexOffset;
1504 cmd.args.drawIndexed.firstInstance = firstInstance;
1508 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1515 cmd.args.drawIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1516 cmd.args.drawIndirect.indirectBufferOffset = indirectBufferOffset;
1517 cmd.args.drawIndirect.drawCount = drawCount;
1518 cmd.args.drawIndirect.stride = stride;
1523 switch (rt->resourceType()) {
1524 case QRhiResource::SwapChainRenderTarget:
1525 return &
QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
1526 case QRhiResource::TextureRenderTarget:
1527 return &
QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
1535 quint32 indirectBufferOffset, quint32 drawCount, quint32 stride)
1542 cmd.args.drawIndexedIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
1543 cmd.args.drawIndexedIndirect.indirectBufferOffset = indirectBufferOffset;
1544 cmd.args.drawIndexedIndirect.drawCount = drawCount;
1545 cmd.args.drawIndexedIndirect.stride = stride;
1550 if (!debugMarkers || !annotations)
1556 qstrncpy(cmd.args.debugMark.s, name.constData(),
sizeof(cmd.args.debugMark.s));
1561 if (!debugMarkers || !annotations)
1571 if (!debugMarkers || !annotations)
1577 qstrncpy(cmd.args.debugMark.s, msg.constData(),
sizeof(cmd.args.debugMark.s));
1596 Q_ASSERT(cbD->commands.isEmpty());
1598 if (cbD->currentTarget) {
1602 fbCmd.args.setRenderTarget.rtViews = rtD->views;
1617 return QRhi::FrameOpDeviceLost;
1624 if (swapChainD->frameLatencyWaitableObject) {
1627 WaitForSingleObjectEx(swapChainD->frameLatencyWaitableObject, 1000,
true);
1632 swapChainD->cb.resetState();
1634 swapChainD->rt.d.views.setFrom(1,
1635 swapChainD->sampleDesc.Count > 1 ? &swapChainD->msaaRtv[currentFrameSlot] : &swapChainD->backBufferRtv,
1636 swapChainD
->ds ? swapChainD
->ds->dsv :
nullptr);
1641 double elapsedSec = 0;
1643 swapChainD->cb.lastGpuTime = elapsedSec;
1652 cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart :
nullptr;
1653 cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint :
nullptr;
1654 cmd.args.beginFrame.swapchainRtv = swapChainD->rt.d.views.rtv[0];
1655 cmd.args.beginFrame.swapchainDsv = swapChainD->rt.d.views.dsv;
1657 QDxgiVSyncService::instance()->beginFrame(adapterLuid);
1659 return QRhi::FrameOpSuccess;
1670 cmd.args.endFrame.tsQuery =
nullptr;
1671 cmd.args.endFrame.tsDisjointQuery =
nullptr;
1676 if (swapChainD->sampleDesc.Count > 1) {
1677 context->ResolveSubresource(swapChainD->backBufferTex, 0,
1678 swapChainD->msaaTex[currentFrameSlot], 0,
1679 swapChainD->colorFormat);
1686 if (recordTimestamps) {
1687 context->End(tsEnd);
1688 context->End(tsDisjoint);
1693 if (!flags.testFlag(QRhi::SkipPresent)) {
1694 UINT presentFlags = 0;
1695 if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
1696 presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
1697 if (!swapChainD->swapChain) {
1698 qWarning(
"Failed to present: IDXGISwapChain is unavailable");
1699 return QRhi::FrameOpError;
1701 HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
1702 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
1703 qWarning(
"Device loss detected in Present()");
1705 return QRhi::FrameOpDeviceLost;
1706 }
else if (FAILED(hr)) {
1707 qWarning(
"Failed to present: %s",
1708 qPrintable(QSystemError::windowsComString(hr)));
1709 return QRhi::FrameOpError;
1712 if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
1713 dcompDevice->Commit();
1724 return QRhi::FrameOpSuccess;
1732 ofr.cbWrapper.resetState();
1733 *cb = &ofr.cbWrapper;
1735 if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
1736 D3D11_QUERY_DESC queryDesc = {};
1737 if (!ofr.tsDisjointQuery) {
1738 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
1739 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
1741 qWarning(
"Failed to create timestamp disjoint query: %s",
1742 qPrintable(QSystemError::windowsComString(hr)));
1743 return QRhi::FrameOpError;
1746 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
1747 for (
int i = 0; i < 2; ++i) {
1748 if (!ofr.tsQueries[i]) {
1749 HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
1751 qWarning(
"Failed to create timestamp query: %s",
1752 qPrintable(QSystemError::windowsComString(hr)));
1753 return QRhi::FrameOpError;
1761 cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] :
nullptr;
1762 cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1763 cmd.args.beginFrame.swapchainRtv =
nullptr;
1764 cmd.args.beginFrame.swapchainDsv =
nullptr;
1766 return QRhi::FrameOpSuccess;
1776 cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] :
nullptr;
1777 cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery :
nullptr;
1784 if (ofr.tsQueries[0]) {
1785 quint64 timestamps[2];
1786 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
1790 hr = context->GetData(ofr.tsDisjointQuery, &dj,
sizeof(dj), 0);
1791 }
while (hr == S_FALSE);
1794 hr = context->GetData(ofr.tsQueries[1], ×tamps[1],
sizeof(quint64), 0);
1795 }
while (hr == S_FALSE);
1798 hr = context->GetData(ofr.tsQueries[0], ×tamps[0],
sizeof(quint64), 0);
1799 }
while (hr == S_FALSE);
1802 if (!dj.Disjoint && dj.Frequency) {
1803 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
1804 ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
1809 return QRhi::FrameOpSuccess;
1814 const bool srgb = flags.testFlag(QRhiTexture::sRGB);
1816 case QRhiTexture::RGBA8:
1817 return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
1818 case QRhiTexture::BGRA8:
1819 return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
1820 case QRhiTexture::R8:
1821 return DXGI_FORMAT_R8_UNORM;
1822 case QRhiTexture::R8SI:
1823 return DXGI_FORMAT_R8_SINT;
1824 case QRhiTexture::R8UI:
1825 return DXGI_FORMAT_R8_UINT;
1826 case QRhiTexture::RG8:
1827 return DXGI_FORMAT_R8G8_UNORM;
1828 case QRhiTexture::R16:
1829 return DXGI_FORMAT_R16_UNORM;
1830 case QRhiTexture::RG16:
1831 return DXGI_FORMAT_R16G16_UNORM;
1832 case QRhiTexture::RED_OR_ALPHA8:
1833 return DXGI_FORMAT_R8_UNORM;
1835 case QRhiTexture::RGBA16F:
1836 return DXGI_FORMAT_R16G16B16A16_FLOAT;
1837 case QRhiTexture::RGBA32F:
1838 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1839 case QRhiTexture::R16F:
1840 return DXGI_FORMAT_R16_FLOAT;
1841 case QRhiTexture::R32F:
1842 return DXGI_FORMAT_R32_FLOAT;
1844 case QRhiTexture::RGB10A2:
1845 return DXGI_FORMAT_R10G10B10A2_UNORM;
1847 case QRhiTexture::R32SI:
1848 return DXGI_FORMAT_R32_SINT;
1849 case QRhiTexture::R32UI:
1850 return DXGI_FORMAT_R32_UINT;
1851 case QRhiTexture::RG32SI:
1852 return DXGI_FORMAT_R32G32_SINT;
1853 case QRhiTexture::RG32UI:
1854 return DXGI_FORMAT_R32G32_UINT;
1855 case QRhiTexture::RGBA32SI:
1856 return DXGI_FORMAT_R32G32B32A32_SINT;
1857 case QRhiTexture::RGBA32UI:
1858 return DXGI_FORMAT_R32G32B32A32_UINT;
1860 case QRhiTexture::D16:
1861 return DXGI_FORMAT_R16_TYPELESS;
1862 case QRhiTexture::D24:
1863 return DXGI_FORMAT_R24G8_TYPELESS;
1864 case QRhiTexture::D24S8:
1865 return DXGI_FORMAT_R24G8_TYPELESS;
1866 case QRhiTexture::D32F:
1867 return DXGI_FORMAT_R32_TYPELESS;
1868 case QRhiTexture::D32FS8:
1869 return DXGI_FORMAT_R32G8X24_TYPELESS;
1871 case QRhiTexture::BC1:
1872 return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
1873 case QRhiTexture::BC2:
1874 return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
1875 case QRhiTexture::BC3:
1876 return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
1877 case QRhiTexture::BC4:
1878 return DXGI_FORMAT_BC4_UNORM;
1879 case QRhiTexture::BC5:
1880 return DXGI_FORMAT_BC5_UNORM;
1881 case QRhiTexture::BC6H:
1882 return DXGI_FORMAT_BC6H_UF16;
1883 case QRhiTexture::BC7:
1884 return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
1886 case QRhiTexture::ETC2_RGB8:
1887 case QRhiTexture::ETC2_RGB8A1:
1888 case QRhiTexture::ETC2_RGBA8:
1889 qWarning(
"QRhiD3D11 does not support ETC2 textures");
1890 return DXGI_FORMAT_R8G8B8A8_UNORM;
1892 case QRhiTexture::ASTC_4x4:
1893 case QRhiTexture::ASTC_5x4:
1894 case QRhiTexture::ASTC_5x5:
1895 case QRhiTexture::ASTC_6x5:
1896 case QRhiTexture::ASTC_6x6:
1897 case QRhiTexture::ASTC_8x5:
1898 case QRhiTexture::ASTC_8x6:
1899 case QRhiTexture::ASTC_8x8:
1900 case QRhiTexture::ASTC_10x5:
1901 case QRhiTexture::ASTC_10x6:
1902 case QRhiTexture::ASTC_10x8:
1903 case QRhiTexture::ASTC_10x10:
1904 case QRhiTexture::ASTC_12x10:
1905 case QRhiTexture::ASTC_12x12:
1906 qWarning(
"QRhiD3D11 does not support ASTC textures");
1907 return DXGI_FORMAT_R8G8B8A8_UNORM;
1911 return DXGI_FORMAT_R8G8B8A8_UNORM;
1918 case DXGI_FORMAT_R8G8B8A8_UNORM:
1919 return QRhiTexture::RGBA8;
1920 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1922 (*flags) |= QRhiTexture::sRGB;
1923 return QRhiTexture::RGBA8;
1924 case DXGI_FORMAT_B8G8R8A8_UNORM:
1925 return QRhiTexture::BGRA8;
1926 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1928 (*flags) |= QRhiTexture::sRGB;
1929 return QRhiTexture::BGRA8;
1930 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1931 return QRhiTexture::RGBA16F;
1932 case DXGI_FORMAT_R32G32B32A32_FLOAT:
1933 return QRhiTexture::RGBA32F;
1934 case DXGI_FORMAT_R10G10B10A2_UNORM:
1935 return QRhiTexture::RGB10A2;
1937 qWarning(
"DXGI_FORMAT %d cannot be read back", format);
1940 return QRhiTexture::UnknownFormat;
1946 case QRhiTexture::Format::D16:
1947 case QRhiTexture::Format::D24:
1948 case QRhiTexture::Format::D24S8:
1949 case QRhiTexture::Format::D32F:
1950 case QRhiTexture::Format::D32FS8:
1963 Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
1965 ofr.cbWrapper.resetCommands();
1976 return QRhi::FrameOpSuccess;
1980 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
1982 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
1983 UINT subres = D3D11CalcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD
->mipLevelCount);
1985 box.front = is3D ? UINT(layer) : 0u;
1987 box.back = box.front + 1;
1990 cmd.args.updateSubRes.dst = texD->textureResource();
1991 cmd.args.updateSubRes.dstSubRes = subres;
1993 const QPoint dp = subresDesc.destinationTopLeft();
1994 if (!subresDesc.image().isNull()) {
1995 QImage img = subresDesc.image();
1996 QSize size = img.size();
1997 int bpl = img.bytesPerLine();
1998 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
1999 const QPoint sp = subresDesc.sourceTopLeft();
2000 if (!subresDesc.sourceSize().isEmpty())
2001 size = subresDesc.sourceSize();
2002 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2003 if (img.depth() == 32) {
2004 const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
2005 cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
2007 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2008 bpl = img.bytesPerLine();
2009 cmd.args.updateSubRes.src = cbD->retainImage(img);
2012 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2013 cmd.args.updateSubRes.src = cbD->retainImage(img);
2015 box.left = UINT(dp.x());
2016 box.top = UINT(dp.y());
2017 box.right = UINT(dp.x() + size.width());
2018 box.bottom = UINT(dp.y() + size.height());
2019 cmd.args.updateSubRes.hasDstBox =
true;
2020 cmd.args.updateSubRes.dstBox = box;
2021 cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
2022 }
else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
2023 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2024 : subresDesc.sourceSize();
2027 compressedFormatInfo(texD->m_format, size, &bpl,
nullptr, &blockDim);
2031 box.left = UINT(aligned(dp.x(), blockDim.width()));
2032 box.top = UINT(aligned(dp.y(), blockDim.height()));
2033 box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
2034 box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
2035 cmd.args.updateSubRes.hasDstBox =
true;
2036 cmd.args.updateSubRes.dstBox = box;
2037 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2038 cmd.args.updateSubRes.srcRowPitch = bpl;
2039 }
else if (!subresDesc.data().isEmpty()) {
2040 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2041 : subresDesc.sourceSize();
2042 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2043 quint32 bytesPerPixel = 0;
2044 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
2045 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
2046 bytesPerPixel, subresDesc.data().size());
2047 if (size.isEmpty()) {
2048 cbD->commands.unget();
2052 if (subresDesc.dataStride())
2053 bpl = subresDesc.dataStride();
2055 textureFormatInfo(texD->m_format, size, &bpl,
nullptr,
nullptr);
2056 box.left = UINT(dp.x());
2057 box.top = UINT(dp.y());
2058 box.right = UINT(dp.x() + size.width());
2059 box.bottom = UINT(dp.y() + size.height());
2060 cmd.args.updateSubRes.hasDstBox =
true;
2061 cmd.args.updateSubRes.dstBox = box;
2062 cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
2063 cmd.args.updateSubRes.srcRowPitch = bpl;
2065 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
2066 cbD->commands.unget();
2079 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2084 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2085 Q_ASSERT(u.offset + u
.data.size() <= bufD->m_size);
2088 cmd.args.updateSubRes.dst = bufD->buffer;
2089 cmd.args.updateSubRes.dstSubRes = 0;
2090 cmd.args.updateSubRes.src = cbD->retainBufferData(u
.data);
2091 cmd.args.updateSubRes.srcRowPitch = 0;
2096 box.left = u.offset;
2097 box.top = box.front = 0;
2098 box.back = box.bottom = 1;
2099 box.right = u.offset + u
.data.size();
2100 cmd.args.updateSubRes.hasDstBox =
true;
2101 cmd.args.updateSubRes.dstBox = box;
2104 if (bufD->m_type == QRhiBuffer::Dynamic) {
2105 u.result->data.resize(u.readSize);
2106 memcpy(u.result->data.data(), bufD
->dynBuf + u.offset, size_t(u.readSize));
2107 if (u.result->completed)
2108 u.result->completed();
2111 readback.result = u.result;
2112 readback.byteSize = u.readSize;
2114 D3D11_BUFFER_DESC desc = {};
2115 desc.ByteWidth = readback.byteSize;
2116 desc.Usage = D3D11_USAGE_STAGING;
2117 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2118 HRESULT hr = dev->CreateBuffer(&desc,
nullptr, &readback.stagingBuf);
2120 qWarning(
"Failed to create buffer: %s",
2121 qPrintable(QSystemError::windowsComString(hr)));
2127 cmd.args.copySubRes.dst = readback.stagingBuf;
2128 cmd.args.copySubRes.dstSubRes = 0;
2129 cmd.args.copySubRes.dstX = 0;
2130 cmd.args.copySubRes.dstY = 0;
2131 cmd.args.copySubRes.dstZ = 0;
2132 cmd.args.copySubRes.src = bufD->buffer;
2133 cmd.args.copySubRes.srcSubRes = 0;
2134 cmd.args.copySubRes.hasSrcBox =
true;
2136 box.left = u.offset;
2137 box.top = box.front = 0;
2138 box.back = box.bottom = 1;
2139 box.right = u.offset + u.readSize;
2140 cmd.args.copySubRes.srcBox = box;
2142 activeBufferReadbacks.append(readback);
2147 Q_ASSERT(dstD->m_type != QRhiBuffer::Dynamic && srcD->m_type != QRhiBuffer::Dynamic);
2151 cmd.args.copySubRes.dst = dstD->buffer;
2152 cmd.args.copySubRes.dstSubRes = 0;
2153 cmd.args.copySubRes.dstX = u.offset;
2154 cmd.args.copySubRes.dstY = 0;
2155 cmd.args.copySubRes.dstZ = 0;
2156 cmd.args.copySubRes.src = srcD->buffer;
2157 cmd.args.copySubRes.srcSubRes = 0;
2158 cmd.args.copySubRes.hasSrcBox =
true;
2160 box.left = u.srcOffset;
2161 box.top = box.front = 0;
2162 box.back = box.bottom = 1;
2163 box.right = u.srcOffset + u.readSize;
2164 cmd.args.copySubRes.srcBox = box;
2167 Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
2169 ID3D11UnorderedAccessView *uav = bufD->createClearUnorderedAccessView(u.offset, u.readSize);
2172 cbD->ownedUavs.append(uav);
2176 cmd.args.clearUav.uav = uav;
2177 for (UINT &v : cmd.args.clearUav.values)
2178 v = u.fillValue32();
2185 for (
const auto &subres : u.subresDesc)
2186 enqueueSubresUpload(texD, cbD, subres.layer, subres.level, subres.desc);
2191 const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2192 const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2193 UINT srcSubRes = D3D11CalcSubresource(UINT(u.desc.sourceLevel()), srcIs3D ? 0u : UINT(u.desc.sourceLayer()), srcD
->mipLevelCount);
2194 UINT dstSubRes = D3D11CalcSubresource(UINT(u.desc.destinationLevel()), dstIs3D ? 0u : UINT(u.desc.destinationLayer()), dstD
->mipLevelCount);
2195 const QPoint dp = u.desc.destinationTopLeft();
2196 const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
2197 const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
2198 const QPoint sp = u.desc.sourceTopLeft();
2200 srcBox.left = UINT(sp.x());
2201 srcBox.top = UINT(sp.y());
2202 srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
2204 srcBox.right = srcBox.left + UINT(copySize.width());
2205 srcBox.bottom = srcBox.top + UINT(copySize.height());
2206 srcBox.back = srcBox.front + 1;
2209 cmd.args.copySubRes.dst = dstD->textureResource();
2210 cmd.args.copySubRes.dstSubRes = dstSubRes;
2211 cmd.args.copySubRes.dstX = UINT(dp.x());
2212 cmd.args.copySubRes.dstY = UINT(dp.y());
2213 cmd.args.copySubRes.dstZ = dstIs3D ? UINT(u.desc.destinationLayer()) : 0u;
2214 cmd.args.copySubRes.src = srcD->textureResource();
2215 cmd.args.copySubRes.srcSubRes = srcSubRes;
2216 cmd.args.copySubRes.hasSrcBox =
true;
2217 cmd.args.copySubRes.srcBox = srcBox;
2220 readback.desc = u.rb;
2221 readback.result = u.result;
2223 ID3D11Resource *src;
2224 DXGI_FORMAT dxgiFormat;
2226 QRhiTexture::Format format;
2233 if (texD->sampleDesc.Count > 1) {
2234 qWarning(
"Multisample texture cannot be read back");
2237 src = texD->textureResource();
2238 dxgiFormat = texD->dxgiFormat;
2239 if (u.rb.rect().isValid())
2242 rect = QRect({0, 0}, q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize));
2243 format = texD->m_format;
2244 is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2245 subres = D3D11CalcSubresource(UINT(u.rb.level()), UINT(is3D ? 0 : u.rb.layer()), texD
->mipLevelCount);
2249 if (swapChainD->sampleDesc.Count > 1) {
2254 rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex;
2255 rcmd.args.resolveSubRes.dstSubRes = 0;
2257 rcmd.args.resolveSubRes.srcSubRes = 0;
2258 rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
2260 src = swapChainD->backBufferTex;
2261 dxgiFormat = swapChainD->colorFormat;
2262 if (u.rb.rect().isValid())
2265 rect = QRect({0, 0}, swapChainD->pixelSize);
2266 format = swapchainReadbackTextureFormat(dxgiFormat,
nullptr);
2267 if (format == QRhiTexture::UnknownFormat)
2270 quint32 byteSize = 0;
2272 textureFormatInfo(format, rect.size(), &bpl, &byteSize,
nullptr);
2274 D3D11_TEXTURE2D_DESC desc = {};
2275 desc.Width = UINT(rect.width());
2276 desc.Height = UINT(rect.height());
2279 desc.Format = dxgiFormat;
2280 desc.SampleDesc.Count = 1;
2281 desc.Usage = D3D11_USAGE_STAGING;
2282 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
2283 ID3D11Texture2D *stagingTex;
2284 HRESULT hr = dev->CreateTexture2D(&desc,
nullptr, &stagingTex);
2286 qWarning(
"Failed to create readback staging texture: %s",
2287 qPrintable(QSystemError::windowsComString(hr)));
2293 cmd.args.copySubRes.dst = stagingTex;
2294 cmd.args.copySubRes.dstSubRes = 0;
2295 cmd.args.copySubRes.dstX = 0;
2296 cmd.args.copySubRes.dstY = 0;
2297 cmd.args.copySubRes.dstZ = 0;
2298 cmd.args.copySubRes.src = src;
2299 cmd.args.copySubRes.srcSubRes = subres;
2301 D3D11_BOX srcBox = {};
2302 srcBox.left = UINT(rect.left());
2303 srcBox.top = UINT(rect.top());
2304 srcBox.front = is3D ? UINT(u.rb.layer()) : 0u;
2306 srcBox.right = srcBox.left + desc.Width;
2307 srcBox.bottom = srcBox.top + desc.Height;
2308 srcBox.back = srcBox.front + 1;
2309 cmd.args.copySubRes.hasSrcBox =
true;
2310 cmd.args.copySubRes.srcBox = srcBox;
2312 readback.stagingTex = stagingTex;
2313 readback.byteSize = byteSize;
2315 readback.pixelSize = rect.size();
2316 readback.format = format;
2318 activeTextureReadbacks.append(readback);
2320 Q_ASSERT(u
.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
2323 cmd.args.genMip.srv =
QRHI_RES(QD3D11Texture, u.dst)->srv;
2332 QVarLengthArray<std::function<
void()>, 4> completedCallbacks;
2334 for (
int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
2336 readback.result->format = readback.format;
2337 readback.result->pixelSize = readback.pixelSize;
2339 D3D11_MAPPED_SUBRESOURCE mp;
2340 HRESULT hr = context->Map(readback.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
2341 if (SUCCEEDED(hr)) {
2342 readback.result->data.resize(
int(readback.byteSize));
2345 char *dst = readback.result->data.data();
2346 char *src =
static_cast<
char *>(mp.pData);
2347 for (
int y = 0, h = readback.pixelSize.height(); y != h; ++y) {
2348 memcpy(dst, src, readback.bpl);
2349 dst += readback.bpl;
2352 context->Unmap(readback.stagingTex, 0);
2354 qWarning(
"Failed to map readback staging texture: %s",
2355 qPrintable(QSystemError::windowsComString(hr)));
2358 readback.stagingTex->Release();
2360 if (readback.result->completed)
2361 completedCallbacks.append(readback.result->completed);
2363 activeTextureReadbacks.removeLast();
2366 for (
int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
2369 D3D11_MAPPED_SUBRESOURCE mp;
2370 HRESULT hr = context->Map(readback.stagingBuf, 0, D3D11_MAP_READ, 0, &mp);
2371 if (SUCCEEDED(hr)) {
2372 readback.result->data.resize(
int(readback.byteSize));
2373 memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
2374 context->Unmap(readback.stagingBuf, 0);
2376 qWarning(
"Failed to map readback staging texture: %s",
2377 qPrintable(QSystemError::windowsComString(hr)));
2380 readback.stagingBuf->Release();
2382 if (readback.result->completed)
2383 completedCallbacks.append(readback.result->completed);
2385 activeBufferReadbacks.removeLast();
2388 for (
auto f : completedCallbacks)
2394 Q_ASSERT(
QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
2400 QRhiRenderTarget *rt,
2401 const QColor &colorClearValue,
2402 const QRhiDepthStencilClearValue &depthStencilClearValue,
2403 QRhiResourceUpdateBatch *resourceUpdates,
2409 if (resourceUpdates)
2412 bool wantsColorClear =
true;
2413 bool wantsDsClear =
true;
2415 if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
2417 wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
2418 wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
2419 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
2427 fbCmd.args.setRenderTarget.rtViews = rtD->views;
2431 clearCmd.args.clear.rtViews = rtD->views;
2432 clearCmd.args.clear.mask = 0;
2433 if (rtD->views.colorAttCount && wantsColorClear)
2435 if (rtD->views.dsv && wantsDsClear)
2438 clearCmd.args.clear.c[0] = colorClearValue.redF();
2439 clearCmd.args.clear.c[1] = colorClearValue.greenF();
2440 clearCmd.args.clear.c[2] = colorClearValue.blueF();
2441 clearCmd.args.clear.c[3] = colorClearValue.alphaF();
2442 clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
2443 clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
2446 cbD->currentTarget = rt;
2456 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
2458 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
2461 const QRhiColorAttachment &colorAtt(*it);
2462 if (!colorAtt.resolveTexture())
2468 Q_ASSERT(srcTexD || srcRbD);
2471 cmd.args.resolveSubRes.dst = dstTexD->textureResource();
2472 cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
2473 UINT(colorAtt.resolveLayer()),
2476 cmd.args.resolveSubRes.src = srcTexD->textureResource();
2477 if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
2478 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2479 int(srcTexD->dxgiFormat),
int(dstTexD->dxgiFormat));
2480 cbD->commands.unget();
2483 if (srcTexD->sampleDesc.Count <= 1) {
2484 qWarning(
"Cannot resolve a non-multisample texture");
2485 cbD->commands.unget();
2488 if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
2489 qWarning(
"Resolve source and destination sizes do not match");
2490 cbD->commands.unget();
2494 cmd.args.resolveSubRes.src = srcRbD->tex;
2495 if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
2496 qWarning(
"Resolve source (%d) and destination (%d) formats do not match",
2497 int(srcRbD->dxgiFormat),
int(dstTexD->dxgiFormat));
2498 cbD->commands.unget();
2501 if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
2502 qWarning(
"Resolve source and destination sizes do not match");
2503 cbD->commands.unget();
2507 cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
2508 cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
2510 if (rtTex->m_desc.depthResolveTexture())
2511 qWarning(
"Resolving multisample depth-stencil buffers is not supported with D3D");
2515 cbD->currentTarget =
nullptr;
2517 if (resourceUpdates)
2522 QRhiResourceUpdateBatch *resourceUpdates,
2528 if (resourceUpdates)
2536 fbCmd.args.setRenderTarget.rtViews.reset();
2553 if (resourceUpdates)
2564 if (pipelineChanged) {
2565 cbD->currentGraphicsPipeline =
nullptr;
2566 cbD->currentComputePipeline = psD;
2571 cmd.args.bindComputePipeline.cs = psD->cs.shader;
2582 cmd.args.dispatch.x = UINT(x);
2583 cmd.args.dispatch.y = UINT(y);
2584 cmd.args.dispatch.z = UINT(z);
2588 quint32 indirectBufferOffset)
2595 cmd.args.dispatchIndirect.indirectBuffer =
QRHI_RES(QD3D11Buffer, indirectBuffer)->buffer;
2596 cmd.args.dispatchIndirect.indirectBufferOffset = indirectBufferOffset;
2600 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2601 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2602 quint32 maxDrawCount, quint32 stride)
2605 Q_UNUSED(indirectBuffer);
2606 Q_UNUSED(indirectBufferOffset);
2607 Q_UNUSED(countBuffer);
2608 Q_UNUSED(countBufferOffset);
2609 Q_UNUSED(maxDrawCount);
2611 qWarning(
"drawIndirectCount is not supported by the D3D11 backend");
2615 QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset,
2616 QRhiBuffer *countBuffer, quint32 countBufferOffset,
2617 quint32 maxDrawCount, quint32 stride)
2620 Q_UNUSED(indirectBuffer);
2621 Q_UNUSED(indirectBufferOffset);
2622 Q_UNUSED(countBuffer);
2623 Q_UNUSED(countBufferOffset);
2624 Q_UNUSED(maxDrawCount);
2626 qWarning(
"drawIndexedIndirectCount is not supported by the D3D11 backend");
2631 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2632 uint pushConstantStages)
2634 const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
2635 if (!map || map->isEmpty()) {
2643 if (pushConstantStages & (1u << uint(stageIndex)))
2645 return { binding, binding };
2648 auto it = map->constFind(binding);
2649 if (it != map->cend())
2659 const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[],
2660 uint pushConstantStages)
2662 srbD->resourceBatches.clear();
2668 ID3D11Buffer *buffer;
2669 uint offsetInConstants;
2670 uint sizeInConstants;
2674 ID3D11ShaderResourceView *srv;
2678 ID3D11SamplerState *sampler;
2682 ID3D11UnorderedAccessView *uav;
2684 QVarLengthArray<Buffer, 8> buffers;
2685 QVarLengthArray<Texture, 8> textures;
2686 QVarLengthArray<Sampler, 8> samplers;
2687 QVarLengthArray<Uav, 8> uavs;
2690 for (
const Buffer &buf : buffers) {
2691 batches.ubufs.feed(buf.breg, buf.buffer);
2692 batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
2693 batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
2694 batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
2700 for (
const Texture &t : textures)
2701 batches.shaderresources.feed(t.treg, t.srv);
2702 for (
const Sampler &s : samplers)
2703 batches.samplers.feed(s.sreg, s.sampler);
2708 for (
const Stage::Uav &u : uavs)
2709 batches.uavs.feed(u.ureg, u.uav);
2714 for (
int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
2715 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
2718 case QRhiShaderResourceBinding::UniformBuffer:
2721 Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
2722 bd.ubuf.id = bufD->m_id;
2730 const quint32 offsetInConstants = b->u.ubuf.offset / 16;
2734 const quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
2735 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2736 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2737 if (nativeBinding.first >= 0)
2738 res[
RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2740 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2741 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2742 if (nativeBinding.first >= 0)
2743 res[
RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2745 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2746 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2747 if (nativeBinding.first >= 0)
2748 res[
RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2750 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2751 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2752 if (nativeBinding.first >= 0)
2753 res[
RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2755 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2756 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2757 if (nativeBinding.first >= 0)
2758 res[
RBM_FRAGMENT].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2760 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2761 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2762 if (nativeBinding.first >= 0)
2763 res[
RBM_COMPUTE].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
2767 case QRhiShaderResourceBinding::SampledTexture:
2768 case QRhiShaderResourceBinding::Texture:
2769 case QRhiShaderResourceBinding::Sampler:
2771 const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->stex;
2772 bd.stex.d.resize(data->count());
2773 const std::pair<
int,
int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps, pushConstantStages);
2774 const std::pair<
int,
int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps, pushConstantStages);
2775 const std::pair<
int,
int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps, pushConstantStages);
2776 const std::pair<
int,
int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps, pushConstantStages);
2777 const std::pair<
int,
int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2778 const std::pair<
int,
int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2782 for (
int elem = 0; elem < data->count(); ++elem) {
2785 bd.stex.d[elem].texId = texD ? texD->m_id : 0;
2786 bd.stex.d[elem].texGeneration = texD ? texD
->generation : 0;
2787 bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
2788 bd.stex.d[elem].samplerGeneration = samplerD ? samplerD
->generation : 0;
2793 if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
2794 const int samplerBinding = texD && samplerD ? nativeBindingVert.second
2795 : (samplerD ? nativeBindingVert.first : -1);
2796 if (nativeBindingVert.first >= 0 && texD)
2797 res[
RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
2798 if (samplerBinding >= 0)
2799 res[
RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2801 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
2802 const int samplerBinding = texD && samplerD ? nativeBindingHull.second
2803 : (samplerD ? nativeBindingHull.first : -1);
2804 if (nativeBindingHull.first >= 0 && texD)
2805 res[
RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
2806 if (samplerBinding >= 0)
2807 res[
RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2809 if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
2810 const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
2811 : (samplerD ? nativeBindingDomain.first : -1);
2812 if (nativeBindingDomain.first >= 0 && texD)
2813 res[
RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
2814 if (samplerBinding >= 0)
2815 res[
RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2817 if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
2818 const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
2819 : (samplerD ? nativeBindingGeom.first : -1);
2820 if (nativeBindingGeom.first >= 0 && texD)
2821 res[
RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
2822 if (samplerBinding >= 0)
2823 res[
RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2825 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2826 const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
2827 : (samplerD ? nativeBindingFrag.first : -1);
2828 if (nativeBindingFrag.first >= 0 && texD)
2829 res[
RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
2830 if (samplerBinding >= 0)
2831 res[
RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2833 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2834 const int samplerBinding = texD && samplerD ? nativeBindingComp.second
2835 : (samplerD ? nativeBindingComp.first : -1);
2836 if (nativeBindingComp.first >= 0 && texD)
2837 res[
RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
2838 if (samplerBinding >= 0)
2839 res[
RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
2844 case QRhiShaderResourceBinding::ImageLoad:
2845 case QRhiShaderResourceBinding::ImageStore:
2846 case QRhiShaderResourceBinding::ImageLoadStore:
2849 bd.simage.id = texD->m_id;
2851 bool validStage =
false;
2852 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2853 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2854 if (nativeBinding.first >= 0) {
2855 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2857 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2861 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2862 QPair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2863 if (nativeBinding.first >= 0) {
2864 ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
2866 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2871 qWarning(
"Unordered access only supported at fragment/compute stage");
2874 case QRhiShaderResourceBinding::BufferLoad:
2875 case QRhiShaderResourceBinding::BufferStore:
2876 case QRhiShaderResourceBinding::BufferLoadStore:
2879 bd.sbuf.id = bufD->m_id;
2881 bool validStage =
false;
2882 if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
2883 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps, pushConstantStages);
2884 if (nativeBinding.first >= 0) {
2885 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2887 res[
RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
2891 if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
2892 std::pair<
int,
int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps, pushConstantStages);
2893 if (nativeBinding.first >= 0) {
2894 ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
2896 res[
RBM_FRAGMENT].uavs.append({ nativeBinding.first, uav });
2901 qWarning(
"Unordered access only supported at fragment/compute stage");
2915 std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](
const Stage::Buffer &a,
const Stage::Buffer &b) {
2916 return a.breg < b.breg;
2918 std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](
const Stage::Texture &a,
const Stage::Texture &b) {
2919 return a.treg < b.treg;
2921 std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](
const Stage::Sampler &a,
const Stage::Sampler &b) {
2922 return a.sreg < b.sreg;
2924 std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](
const Stage::Uav &a,
const Stage::Uav &b) {
2925 return a.ureg < b.ureg;
2929 res[
RBM_VERTEX].buildBufferBatches(srbD->resourceBatches.vsUniformBufferBatches);
2930 res[
RBM_HULL].buildBufferBatches(srbD->resourceBatches.hsUniformBufferBatches);
2931 res[
RBM_DOMAIN].buildBufferBatches(srbD->resourceBatches.dsUniformBufferBatches);
2932 res[
RBM_GEOMETRY].buildBufferBatches(srbD->resourceBatches.gsUniformBufferBatches);
2933 res[
RBM_FRAGMENT].buildBufferBatches(srbD->resourceBatches.fsUniformBufferBatches);
2934 res[
RBM_COMPUTE].buildBufferBatches(srbD->resourceBatches.csUniformBufferBatches);
2936 res[
RBM_VERTEX].buildSamplerBatches(srbD->resourceBatches.vsSamplerBatches);
2937 res[
RBM_HULL].buildSamplerBatches(srbD->resourceBatches.hsSamplerBatches);
2938 res[
RBM_DOMAIN].buildSamplerBatches(srbD->resourceBatches.dsSamplerBatches);
2939 res[
RBM_GEOMETRY].buildSamplerBatches(srbD->resourceBatches.gsSamplerBatches);
2940 res[
RBM_FRAGMENT].buildSamplerBatches(srbD->resourceBatches.fsSamplerBatches);
2941 res[
RBM_COMPUTE].buildSamplerBatches(srbD->resourceBatches.csSamplerBatches);
2943 res[
RBM_FRAGMENT].buildUavBatches(srbD->resourceBatches.fsUavBatches);
2944 res[
RBM_COMPUTE].buildUavBatches(srbD->resourceBatches.csUavBatches);
2952 Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
2954 D3D11_MAPPED_SUBRESOURCE mp;
2955 HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
2956 if (SUCCEEDED(hr)) {
2957 memcpy(mp.pData, bufD
->dynBuf, bufD->m_size);
2958 context->Unmap(bufD->buffer, 0);
2960 qWarning(
"Failed to map buffer: %s",
2961 qPrintable(QSystemError::windowsComString(hr)));
2967 const QRhiBatchedBindings<UINT> *originalBindings,
2968 const QRhiBatchedBindings<UINT> *staticOffsets,
2969 const uint *dynOfsPairs,
int dynOfsPairCount)
2971 const int count = staticOffsets->batches[batchIndex].resources.count();
2974 for (
int b = 0; b < count; ++b) {
2975 offsets[b] = staticOffsets->batches[batchIndex].resources[b];
2976 for (
int di = 0; di < dynOfsPairCount; ++di) {
2977 const uint binding = dynOfsPairs[2 * di];
2980 if (binding == originalBindings->batches[batchIndex].resources[b]) {
2981 const uint offsetInConstants = dynOfsPairs[2 * di + 1];
2982 offsets[b] = offsetInConstants;
2991 if (startSlot + countSlots > maxSlots) {
2992 qWarning(
"Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
2993 resType, countSlots, startSlot, maxSlots);
2994 countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
2999#define SETUBUFBATCH(stagePrefixL, stagePrefixU)
3000 if (allResourceBatches.stagePrefixL##UniformBufferBatches.present) {
3001 const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(allResourceBatches.stagePrefixL##UniformBufferBatches);
3002 for (int i = 0
, ie = batches.ubufs.batches.count(); i != ie; ++i) {
3003 const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding,
3004 batches.ubufs.batches[i].resources.count(),
3005 D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
3006 #stagePrefixU " cbuf");
3008 if (!dynOfsPairCount) {
3009 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3011 batches.ubufs.batches[i].resources.constData(),
3012 batches.ubufoffsets.batches[i].resources.constData(),
3013 batches.ubufsizes.batches[i].resources.constData());
3015 applyDynamicOffsets(offsets, i,
3016 &batches.ubuforigbindings, &batches.ubufoffsets,
3017 dynOfsPairs, dynOfsPairCount);
3018 context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding,
3020 batches.ubufs.batches[i].resources.constData(),
3022 batches.ubufsizes.batches[i].resources.constData());
3028#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
3029 if (allResourceBatches.stagePrefixL##SamplerBatches.present) {
3030 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.samplers.batches) {
3031 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3032 D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler");
3034 context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData());
3036 for (const auto &batch : allResourceBatches.stagePrefixL##SamplerBatches.shaderresources.batches) {
3037 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3038 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV");
3040 context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData());
3041 contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding,
3042 int(batch.startBinding + count) - 1
);
3047#define SETUAVBATCH(stagePrefixL, stagePrefixU)
3048 if (allResourceBatches.stagePrefixL##UavBatches.present) {
3049 for (const auto &batch : allResourceBatches.stagePrefixL##UavBatches.uavs.batches) {
3050 const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
3053 context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding,
3055 batch.resources.constData(),
3057 contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding,
3058 int(batch.startBinding + count) - 1
);
3065 const uint *dynOfsPairs,
int dynOfsPairCount,
3066 bool offsetOnlyChange,
3078 if (!offsetOnlyChange) {
3088 if (allResourceBatches.fsUavBatches.present) {
3089 for (
const auto &batch : allResourceBatches.fsUavBatches.uavs.batches) {
3090 const uint count = qMin(clampedResourceCount(batch.startBinding, batch.resources.count(),
3092 uint(QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS));
3094 if (rtUavState->update(cbD->currentRenderTargetViews, batch.resources.constData(), count)) {
3095 context->OMSetRenderTargetsAndUnorderedAccessViews(
3096 UINT(rtUavState->rtViews.colorAttCount),
3097 rtUavState->rtViews.colorAttCount ? rtUavState->rtViews.rtv :
nullptr,
3098 rtUavState->rtViews.dsv,
3099 UINT(batch.startBinding),
3101 batch.resources.constData(),
3104 contextState.fsHighestActiveUavBinding = qMax(contextState.fsHighestActiveUavBinding,
3105 int(batch.startBinding + count) - 1);
3118 context->IASetIndexBuffer(
nullptr, DXGI_FORMAT_R16_UINT, 0);
3124 QVarLengthArray<ID3D11Buffer *, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullbufs(count);
3125 for (
int i = 0; i < count; ++i)
3126 nullbufs[i] =
nullptr;
3127 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nullstrides(count);
3128 for (
int i = 0; i < count; ++i)
3130 QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
3131 for (
int i = 0; i < count; ++i)
3133 context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
3143 if (nullsrvCount > 0) {
3144 QVarLengthArray<ID3D11ShaderResourceView *,
3145 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
3146 for (
int i = 0; i < nullsrvs.count(); ++i)
3147 nullsrvs[i] =
nullptr;
3149 context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
3153 context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
3157 context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
3161 context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
3165 context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
3169 context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
3175 rtUavState->update(cbD->currentRenderTargetViews);
3176 context->OMSetRenderTargetsAndUnorderedAccessViews(
3177 UINT(cbD->currentRenderTargetViews.colorAttCount),
3178 cbD->currentRenderTargetViews.colorAttCount ? cbD->currentRenderTargetViews.rtv :
nullptr,
3179 cbD->currentRenderTargetViews.dsv,
3180 0, 0,
nullptr,
nullptr);
3185 QVarLengthArray<ID3D11UnorderedAccessView *,
3186 D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
3187 for (
int i = 0; i < nulluavCount; ++i)
3188 nulluavs[i] =
nullptr;
3189 context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(),
nullptr);
3194#define SETSHADER(StageL, StageU)
3195 if (cmd.args.bindGraphicsPipeline.StageL) {
3196 context->StageU##SetShader(cmd.args.bindGraphicsPipeline.StageL, nullptr, 0
);
3197 currentShaderMask |= StageU##MaskBit;
3198 } else if (currentShaderMask & StageU##MaskBit) {
3199 context->StageU##SetShader(nullptr, nullptr, 0
);
3200 currentShaderMask &= ~StageU##MaskBit;
3205 quint32 stencilRef = 0;
3206 float blendConstants[] = { 1, 1, 1, 1 };
3207 enum ActiveShaderMask {
3214 int currentShaderMask = 0xFF;
3220 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3223 case QD3D11CommandBuffer::Command::BeginFrame:
3224 if (cmd.args.beginFrame.tsDisjointQuery)
3225 context->Begin(cmd.args.beginFrame.tsDisjointQuery);
3226 if (cmd.args.beginFrame.tsQuery) {
3227 if (cmd.args.beginFrame.swapchainRtv) {
3232 cbD->currentRenderTargetViews.setFrom(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3233 rtUavState.update(cbD->currentRenderTargetViews);
3234 context->OMSetRenderTargets(1, &cmd.args.beginFrame.swapchainRtv, cmd.args.beginFrame.swapchainDsv);
3236 context->End(cmd.args.beginFrame.tsQuery);
3239 case QD3D11CommandBuffer::Command::EndFrame:
3240 if (cmd.args.endFrame.tsQuery)
3241 context->End(cmd.args.endFrame.tsQuery);
3242 if (cmd.args.endFrame.tsDisjointQuery)
3243 context->End(cmd.args.endFrame.tsDisjointQuery);
3250 cbD->currentRenderTargetViews = cmd.args.setRenderTarget.rtViews;
3251 if (rtUavState.update(cbD->currentRenderTargetViews)) {
3252 const UINT colorAttCount = UINT(cmd.args.setRenderTarget.rtViews.colorAttCount);
3253 context->OMSetRenderTargets(colorAttCount,
3254 colorAttCount ? cmd.args.setRenderTarget.rtViews.rtv :
nullptr,
3255 cmd.args.setRenderTarget.rtViews.dsv);
3262 for (
int i = 0; i < cmd.args.clear.rtViews.colorAttCount; ++i)
3263 context->ClearRenderTargetView(cmd.args.clear.rtViews.rtv[i], cmd.args.clear.c);
3266 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
3267 ds |= D3D11_CLEAR_DEPTH;
3268 if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
3269 ds |= D3D11_CLEAR_STENCIL;
3270 if (ds && cmd.args.clear.rtViews.dsv)
3271 context->ClearDepthStencilView(cmd.args.clear.rtViews.dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
3277 v.TopLeftX = cmd.args.viewport.x;
3278 v.TopLeftY = cmd.args.viewport.y;
3279 v.Width = cmd.args.viewport.w;
3280 v.Height = cmd.args.viewport.h;
3281 v.MinDepth = cmd.args.viewport.d0;
3282 v.MaxDepth = cmd.args.viewport.d1;
3283 context->RSSetViewports(1, &v);
3289 r.left = cmd.args.scissor.x;
3290 r.top = cmd.args.scissor.y;
3292 r.right = cmd.args.scissor.x + cmd.args.scissor.w;
3293 r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
3294 context->RSSetScissorRects(1, &r);
3300 cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
3301 context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
3302 UINT(cmd.args.bindVertexBuffers.slotCount),
3303 cmd.args.bindVertexBuffers.buffers,
3304 cmd.args.bindVertexBuffers.strides,
3305 cmd.args.bindVertexBuffers.offsets);
3309 context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
3310 cmd.args.bindIndexBuffer.format,
3311 cmd.args.bindIndexBuffer.offset);
3320 context->IASetPrimitiveTopology(cmd.args.bindGraphicsPipeline.topology);
3321 context->IASetInputLayout(cmd.args.bindGraphicsPipeline.inputLayout);
3322 context->OMSetDepthStencilState(cmd.args.bindGraphicsPipeline.dsState, stencilRef);
3323 context->OMSetBlendState(cmd.args.bindGraphicsPipeline.blendState, blendConstants, 0xffffffff);
3324 context->RSSetState(cmd.args.bindGraphicsPipeline.rastState);
3329 cbD->resourceBatchRetainPool[cmd.args.bindShaderResources.resourceBatchesIndex]
,
3330 cmd.args.bindShaderResources.dynamicOffsetPairs
,
3331 cmd.args.bindShaderResources.dynamicOffsetCount
,
3332 cmd.args.bindShaderResources.offsetOnlyChange
,
3340 ID3D11Buffer *buf = cmd.args.setPushConstants.buffer;
3341 D3D11_MAPPED_SUBRESOURCE mp;
3342 HRESULT hr = context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3343 if (SUCCEEDED(hr)) {
3344 memcpy(mp.pData, cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
3345 cmd.args.setPushConstants.size);
3346 context->Unmap(buf, 0);
3348 qWarning(
"Failed to map push constant buffer: %s",
3349 qPrintable(QSystemError::windowsComString(hr)));
3352 const UINT startSlot = cmd.args.setPushConstants.startSlot;
3353 const uint stages = cmd.args.setPushConstants.stages;
3357 if (stages & (1u << uint(RBM_VERTEX)))
3358 context->VSSetConstantBuffers(startSlot, 1, &buf);
3359 if (stages & (1u << uint(RBM_HULL)))
3360 context->HSSetConstantBuffers(startSlot, 1, &buf);
3361 if (stages & (1u << uint(RBM_DOMAIN)))
3362 context->DSSetConstantBuffers(startSlot, 1, &buf);
3363 if (stages & (1u << uint(RBM_GEOMETRY)))
3364 context->GSSetConstantBuffers(startSlot, 1, &buf);
3365 if (stages & (1u << uint(RBM_FRAGMENT)))
3366 context->PSSetConstantBuffers(startSlot, 1, &buf);
3367 if (stages & (1u << uint(RBM_COMPUTE)))
3368 context->CSSetConstantBuffers(startSlot, 1, &buf);
3372 stencilRef = cmd.args.stencilRef.ref;
3373 context->OMSetDepthStencilState(cmd.args.stencilRef.dsState, stencilRef);
3376 memcpy(blendConstants, cmd.args.blendConstants.c, 4 *
sizeof(
float));
3377 context->OMSetBlendState(cmd.args.blendConstants.blendState, blendConstants, 0xffffffff);
3379 case QD3D11CommandBuffer::Command::Draw:
3380 if (cmd.args.draw.instanceCount == 1 && cmd.args.draw.firstInstance == 0)
3381 context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
3383 context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
3384 cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
3386 case QD3D11CommandBuffer::Command::DrawIndexed:
3387 if (cmd.args.drawIndexed.instanceCount == 1 && cmd.args.drawIndexed.firstInstance == 0)
3388 context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
3389 cmd.args.drawIndexed.vertexOffset);
3391 context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
3392 cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
3393 cmd.args.drawIndexed.firstInstance);
3397 UINT alignedByteOffsetForArgs = cmd.args.drawIndirect.indirectBufferOffset;
3398 const UINT stride = cmd.args.drawIndirect.stride;
3399 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3400 context->DrawInstancedIndirect(cmd.args.drawIndirect.indirectBuffer, alignedByteOffsetForArgs);
3401 alignedByteOffsetForArgs += stride;
3407 UINT alignedByteOffsetForArgs = cmd.args.drawIndexedIndirect.indirectBufferOffset;
3408 const UINT stride = cmd.args.drawIndexedIndirect.stride;
3409 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3410 context->DrawIndexedInstancedIndirect(cmd.args.drawIndexedIndirect.indirectBuffer, alignedByteOffsetForArgs);
3411 alignedByteOffsetForArgs += stride;
3417 if (cmd.args.updateSubRes.dst) {
3418 context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
3419 cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox :
nullptr,
3420 cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
3423 case QD3D11CommandBuffer::Command::CopySubRes:
3424 context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
3425 cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, cmd.args.copySubRes.dstZ,
3426 cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
3427 cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox :
nullptr);
3429 case QD3D11CommandBuffer::Command::ClearUav:
3430 context->ClearUnorderedAccessViewUint(cmd.args.clearUav.uav, cmd.args.clearUav.values);
3432 case QD3D11CommandBuffer::Command::ResolveSubRes:
3433 context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
3434 cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
3435 cmd.args.resolveSubRes.format);
3437 case QD3D11CommandBuffer::Command::GenMip:
3438 context->GenerateMips(cmd.args.genMip.srv);
3440 case QD3D11CommandBuffer::Command::DebugMarkBegin:
3441 annotations->BeginEvent(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3443 case QD3D11CommandBuffer::Command::DebugMarkEnd:
3444 annotations->EndEvent();
3446 case QD3D11CommandBuffer::Command::DebugMarkMsg:
3447 annotations->SetMarker(
reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
3449 case QD3D11CommandBuffer::Command::BindComputePipeline:
3450 context->CSSetShader(cmd.args.bindComputePipeline.cs,
nullptr, 0);
3452 case QD3D11CommandBuffer::Command::Dispatch:
3453 context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3455 case QD3D11CommandBuffer::Command::DispatchIndirect:
3456 context->DispatchIndirect(cmd.args.dispatchIndirect.indirectBuffer,
3457 cmd.args.dispatchIndirect.indirectBufferOffset);
3486 for (
auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
3487 it.value()->Release();
3492 rhiD->unregisterResource(
this);
3498 if (usage.testFlag(QRhiBuffer::VertexBuffer))
3499 u |= D3D11_BIND_VERTEX_BUFFER;
3500 if (usage.testFlag(QRhiBuffer::IndexBuffer))
3501 u |= D3D11_BIND_INDEX_BUFFER;
3502 if (usage.testFlag(QRhiBuffer::UniformBuffer))
3503 u |= D3D11_BIND_CONSTANT_BUFFER;
3504 if (usage.testFlag(QRhiBuffer::StorageBuffer))
3505 u |= D3D11_BIND_UNORDERED_ACCESS;
3514 if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
3515 qWarning(
"UniformBuffer must always be combined with Dynamic on D3D11");
3519 if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
3520 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3524 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer) && m_type == Dynamic) {
3525 qWarning(
"IndirectBuffer cannot be combined with Dynamic on D3D11");
3529 const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
3534 const quint32 minSize = m_usage.testFlag(QRhiBuffer::IndirectBuffer) ? 12u : 1u;
3535 const quint32 roundedSize = aligned(qMax(nonZeroSize, minSize),
3536 m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
3538 D3D11_BUFFER_DESC desc = {};
3539 desc.ByteWidth = roundedSize;
3540 desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
3541 desc.BindFlags = toD3DBufferUsage(m_usage);
3542 desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
3543 desc.MiscFlags = m_usage.testFlag(QRhiBuffer::StorageBuffer) ? D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS : 0;
3544 if (m_usage.testFlag(QRhiBuffer::IndirectBuffer))
3545 desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
3548 HRESULT hr = rhiD->dev->CreateBuffer(&desc,
nullptr, &buffer);
3550 qWarning(
"Failed to create buffer: %s",
3551 qPrintable(QSystemError::windowsComString(hr)));
3555 if (m_type == Dynamic) {
3556 dynBuf =
new char[nonZeroSize];
3560 if (!m_objectName.isEmpty())
3561 buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3564 rhiD->registerResource(
this);
3570 if (m_type == Dynamic) {
3574 return { { &buffer }, 1 };
3585 Q_ASSERT(m_type == Dynamic);
3586 D3D11_MAPPED_SUBRESOURCE mp;
3588 HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
3590 qWarning(
"Failed to map buffer: %s",
3591 qPrintable(QSystemError::windowsComString(hr)));
3594 return static_cast<
char *>(mp.pData);
3600 rhiD->context->Unmap(buffer, 0);
3605 auto it = uavs.find(offset);
3606 if (it != uavs.end())
3610 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3611 desc.Format = DXGI_FORMAT_R32_TYPELESS;
3612 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3613 desc.Buffer.FirstElement = offset / 4u;
3614 desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
3615 desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
3618 ID3D11UnorderedAccessView *uav =
nullptr;
3619 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3621 qWarning(
"Failed to create UAV: %s",
3622 qPrintable(QSystemError::windowsComString(hr)));
3635 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
3636 desc.Format = DXGI_FORMAT_R32_UINT;
3637 desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
3638 desc.Buffer.FirstElement = offset / 4u;
3639 desc.Buffer.NumElements = size / 4u;
3642 ID3D11UnorderedAccessView *uav =
nullptr;
3643 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
3645 qWarning(
"Failed to create UAV: %s",
3646 qPrintable(QSystemError::windowsComString(hr)));
3654 int sampleCount, QRhiRenderBuffer::Flags flags,
3655 QRhiTexture::Format backingFormatHint)
3685 rhiD->unregisterResource(
this);
3693 if (m_pixelSize.isEmpty())
3697 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3699 D3D11_TEXTURE2D_DESC desc = {};
3700 desc.Width = UINT(m_pixelSize.width());
3701 desc.Height = UINT(m_pixelSize.height());
3704 desc.SampleDesc = sampleDesc;
3705 desc.Usage = D3D11_USAGE_DEFAULT;
3707 if (m_type == Color) {
3708 dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
3709 : toD3DTextureFormat(m_backingFormatHint, {});
3710 desc.Format = dxgiFormat;
3711 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
3712 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3714 qWarning(
"Failed to create color renderbuffer: %s",
3715 qPrintable(QSystemError::windowsComString(hr)));
3718 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3719 rtvDesc.Format = dxgiFormat;
3720 rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
3721 : D3D11_RTV_DIMENSION_TEXTURE2D;
3722 hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
3724 qWarning(
"Failed to create rtv: %s",
3725 qPrintable(QSystemError::windowsComString(hr)));
3728 }
else if (m_type == DepthStencil) {
3729 dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
3730 desc.Format = dxgiFormat;
3731 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
3732 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
3734 qWarning(
"Failed to create depth-stencil buffer: %s",
3735 qPrintable(QSystemError::windowsComString(hr)));
3738 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
3739 dsvDesc.Format = dxgiFormat;
3740 dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
3741 : D3D11_DSV_DIMENSION_TEXTURE2D;
3742 hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
3744 qWarning(
"Failed to create dsv: %s",
3745 qPrintable(QSystemError::windowsComString(hr)));
3752 if (!m_objectName.isEmpty())
3753 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
3756 rhiD->registerResource(
this);
3762 if (m_backingFormatHint != QRhiTexture::UnknownFormat)
3763 return m_backingFormatHint;
3765 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
3769 int arraySize,
int sampleCount, Flags flags)
3772 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
3773 perLevelViews[i] =
nullptr;
3783 if (!tex && !tex3D && !tex1D)
3791 for (
int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i) {
3792 if (perLevelViews[i]) {
3793 perLevelViews[i]->Release();
3794 perLevelViews[i] =
nullptr;
3813 rhiD->unregisterResource(
this);
3819 case QRhiTexture::Format::D16:
3820 return DXGI_FORMAT_R16_FLOAT;
3821 case QRhiTexture::Format::D24:
3822 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3823 case QRhiTexture::Format::D24S8:
3824 return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
3825 case QRhiTexture::Format::D32F:
3826 return DXGI_FORMAT_R32_FLOAT;
3827 case QRhiTexture::Format::D32FS8:
3828 return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
3831 return DXGI_FORMAT_R32_FLOAT;
3838 case QRhiTexture::Format::D16:
3839 return DXGI_FORMAT_D16_UNORM;
3840 case QRhiTexture::Format::D24:
3841 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3842 case QRhiTexture::Format::D24S8:
3843 return DXGI_FORMAT_D24_UNORM_S8_UINT;
3844 case QRhiTexture::Format::D32F:
3845 return DXGI_FORMAT_D32_FLOAT;
3846 case QRhiTexture::Format::D32FS8:
3847 return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
3850 return DXGI_FORMAT_D32_FLOAT;
3856 if (tex || tex3D || tex1D)
3860 if (!rhiD->isTextureFormatSupported(m_format, m_flags))
3863 const bool isDepth = isDepthTextureFormat(m_format);
3864 const bool isCube = m_flags.testFlag(CubeMap);
3865 const bool is3D = m_flags.testFlag(ThreeDimensional);
3866 const bool isArray = m_flags.testFlag(TextureArray);
3867 const bool hasMipMaps = m_flags.testFlag(MipMapped);
3868 const bool is1D = m_flags.testFlag(OneDimensional);
3870 const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
3871 : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
3873 dxgiFormat = toD3DTextureFormat(m_format, m_flags);
3874 mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
3875 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
3876 if (sampleDesc.Count > 1) {
3878 qWarning(
"Cubemap texture cannot be multisample");
3882 qWarning(
"3D texture cannot be multisample");
3886 qWarning(
"Multisample texture cannot have mipmaps");
3890 if (isDepth && hasMipMaps) {
3891 qWarning(
"Depth texture cannot have mipmaps");
3894 if (isCube && is3D) {
3895 qWarning(
"Texture cannot be both cube and 3D");
3898 if (isArray && is3D) {
3899 qWarning(
"Texture cannot be both array and 3D");
3902 if (isCube && is1D) {
3903 qWarning(
"Texture cannot be both cube and 1D");
3907 qWarning(
"Texture cannot be both 1D and 3D");
3910 if (m_depth > 1 && !is3D) {
3911 qWarning(
"Texture cannot have a depth of %d when it is not 3D", m_depth);
3914 if (m_arraySize > 0 && !isArray) {
3915 qWarning(
"Texture cannot have an array size of %d when it is not an array", m_arraySize);
3918 if (m_arraySize < 1 && isArray) {
3919 qWarning(
"Texture is an array but array size is %d", m_arraySize);
3923 if (!rhiD->textureFormatInfo(m_format, size,
nullptr,
nullptr,
nullptr))
3927 *adjustedSize = size;
3935 const bool isDepth = isDepthTextureFormat(m_format);
3936 const bool isCube = m_flags.testFlag(CubeMap);
3937 const bool is3D = m_flags.testFlag(ThreeDimensional);
3938 const bool isArray = m_flags.testFlag(TextureArray);
3939 const bool is1D = m_flags.testFlag(OneDimensional);
3941 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3942 srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
3944 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
3949 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
3951 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3952 srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3953 srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
3955 srvDesc.Texture1DArray.FirstArraySlice = 0;
3956 srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
3959 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
3962 }
else if (isArray) {
3963 if (sampleDesc.Count > 1) {
3964 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
3965 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3966 srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
3967 srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
3969 srvDesc.Texture2DMSArray.FirstArraySlice = 0;
3970 srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
3973 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
3975 if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
3976 srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
3977 srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
3979 srvDesc.Texture2DArray.FirstArraySlice = 0;
3980 srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
3984 if (sampleDesc.Count > 1) {
3985 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
3987 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
3990 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3996 HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
3998 qWarning(
"Failed to create srv: %s",
3999 qPrintable(QSystemError::windowsComString(hr)));
4010 if (!prepareCreate(&size))
4013 const bool isDepth = isDepthTextureFormat(m_format);
4014 const bool isCube = m_flags.testFlag(CubeMap);
4015 const bool is3D = m_flags.testFlag(ThreeDimensional);
4016 const bool isArray = m_flags.testFlag(TextureArray);
4017 const bool is1D = m_flags.testFlag(OneDimensional);
4019 uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
4020 uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
4021 if (m_flags.testFlag(RenderTarget)) {
4023 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
4025 bindFlags |= D3D11_BIND_RENDER_TARGET;
4027 if (m_flags.testFlag(UsedWithGenerateMips)) {
4029 qWarning(
"Depth texture cannot have mipmaps generated");
4032 bindFlags |= D3D11_BIND_RENDER_TARGET;
4033 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
4035 if (m_flags.testFlag(UsedWithLoadStore))
4036 bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
4040 D3D11_TEXTURE1D_DESC desc = {};
4041 desc.Width = UINT(size.width());
4043 desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
4044 desc.Format = dxgiFormat;
4045 desc.Usage = D3D11_USAGE_DEFAULT;
4046 desc.BindFlags = bindFlags;
4047 desc.MiscFlags = miscFlags;
4049 HRESULT hr = rhiD->dev->CreateTexture1D(&desc,
nullptr, &tex1D);
4051 qWarning(
"Failed to create 1D texture: %s",
4052 qPrintable(QSystemError::windowsComString(hr)));
4055 if (!m_objectName.isEmpty())
4056 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
4057 m_objectName.constData());
4059 D3D11_TEXTURE2D_DESC desc = {};
4060 desc.Width = UINT(size.width());
4061 desc.Height = UINT(size.height());
4063 desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
4064 desc.Format = dxgiFormat;
4065 desc.SampleDesc = sampleDesc;
4066 desc.Usage = D3D11_USAGE_DEFAULT;
4067 desc.BindFlags = bindFlags;
4068 desc.MiscFlags = miscFlags;
4070 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, &tex);
4072 qWarning(
"Failed to create 2D texture: %s",
4073 qPrintable(QSystemError::windowsComString(hr)));
4074 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4078 if (!m_objectName.isEmpty())
4079 tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4081 D3D11_TEXTURE3D_DESC desc = {};
4082 desc.Width = UINT(size.width());
4083 desc.Height = UINT(size.height());
4084 desc.Depth = UINT(qMax(1, m_depth));
4086 desc.Format = dxgiFormat;
4087 desc.Usage = D3D11_USAGE_DEFAULT;
4088 desc.BindFlags = bindFlags;
4089 desc.MiscFlags = miscFlags;
4091 HRESULT hr = rhiD->dev->CreateTexture3D(&desc,
nullptr, &tex3D);
4093 qWarning(
"Failed to create 3D texture: %s",
4094 qPrintable(QSystemError::windowsComString(hr)));
4095 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
4099 if (!m_objectName.isEmpty())
4100 tex3D->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
4107 rhiD->registerResource(
this);
4116 if (!prepareCreate())
4119 if (m_flags.testFlag(ThreeDimensional))
4120 tex3D =
reinterpret_cast<ID3D11Texture3D *>(src.object);
4121 else if (m_flags.testFlags(OneDimensional))
4122 tex1D =
reinterpret_cast<ID3D11Texture1D *>(src.object);
4124 tex =
reinterpret_cast<ID3D11Texture2D *>(src.object);
4131 rhiD->registerResource(
this);
4137 return { quint64(textureResource()), 0 };
4142 if (perLevelViews[level])
4143 return perLevelViews[level];
4145 const bool isCube = m_flags.testFlag(CubeMap);
4146 const bool isArray = m_flags.testFlag(TextureArray);
4147 const bool is3D = m_flags.testFlag(ThreeDimensional);
4148 D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
4149 desc.Format = dxgiFormat;
4151 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4152 desc.Texture2DArray.MipSlice = UINT(level);
4153 desc.Texture2DArray.FirstArraySlice = 0;
4154 desc.Texture2DArray.ArraySize = 6;
4155 }
else if (isArray) {
4156 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
4157 desc.Texture2DArray.MipSlice = UINT(level);
4158 desc.Texture2DArray.FirstArraySlice = 0;
4159 desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
4161 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
4162 desc.Texture3D.MipSlice = UINT(level);
4163 desc.Texture3D.WSize = UINT(m_depth);
4165 desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
4166 desc.Texture2D.MipSlice = UINT(level);
4170 ID3D11UnorderedAccessView *uav =
nullptr;
4171 HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
4173 qWarning(
"Failed to create UAV: %s",
4174 qPrintable(QSystemError::windowsComString(hr)));
4178 perLevelViews[level] = uav;
4183 AddressMode u, AddressMode v, AddressMode w)
4198 samplerState->Release();
4199 samplerState =
nullptr;
4203 rhiD->unregisterResource(
this);
4206static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
4208 if (minFilter == QRhiSampler::Nearest) {
4209 if (magFilter == QRhiSampler::Nearest) {
4210 if (mipFilter == QRhiSampler::Linear)
4211 return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
4213 return D3D11_FILTER_MIN_MAG_MIP_POINT;
4215 if (mipFilter == QRhiSampler::Linear)
4216 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
4218 return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
4221 if (magFilter == QRhiSampler::Nearest) {
4222 if (mipFilter == QRhiSampler::Linear)
4223 return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
4225 return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
4227 if (mipFilter == QRhiSampler::Linear)
4228 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4230 return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
4235 return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
4241 case QRhiSampler::Repeat:
4242 return D3D11_TEXTURE_ADDRESS_WRAP;
4243 case QRhiSampler::ClampToEdge:
4244 return D3D11_TEXTURE_ADDRESS_CLAMP;
4245 case QRhiSampler::Mirror:
4246 return D3D11_TEXTURE_ADDRESS_MIRROR;
4249 return D3D11_TEXTURE_ADDRESS_CLAMP;
4256 case QRhiSampler::Never:
4257 return D3D11_COMPARISON_NEVER;
4258 case QRhiSampler::Less:
4259 return D3D11_COMPARISON_LESS;
4260 case QRhiSampler::Equal:
4261 return D3D11_COMPARISON_EQUAL;
4262 case QRhiSampler::LessOrEqual:
4263 return D3D11_COMPARISON_LESS_EQUAL;
4264 case QRhiSampler::Greater:
4265 return D3D11_COMPARISON_GREATER;
4266 case QRhiSampler::NotEqual:
4267 return D3D11_COMPARISON_NOT_EQUAL;
4268 case QRhiSampler::GreaterOrEqual:
4269 return D3D11_COMPARISON_GREATER_EQUAL;
4270 case QRhiSampler::Always:
4271 return D3D11_COMPARISON_ALWAYS;
4274 return D3D11_COMPARISON_NEVER;
4283 D3D11_SAMPLER_DESC desc = {};
4284 desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
4285 if (m_compareOp != Never)
4286 desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
4287 desc.AddressU = toD3DAddressMode(m_addressU);
4288 desc.AddressV = toD3DAddressMode(m_addressV);
4289 desc.AddressW = toD3DAddressMode(m_addressW);
4290 desc.MaxAnisotropy = 1.0f;
4291 desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
4292 desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
4295 HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
4297 qWarning(
"Failed to create sampler state: %s",
4298 qPrintable(QSystemError::windowsComString(hr)));
4303 rhiD->registerResource(
this);
4322 rhiD->unregisterResource(
this);
4335 rhiD->registerResource(rpD,
false);
4372 return d.sampleCount;
4376 const QRhiTextureRenderTargetDescription &desc,
4394 if (!rtv[0] && !dsv)
4413 rhiD->unregisterResource(
this);
4420 rhiD->registerResource(rpD,
false);
4429 Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
4430 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
4431 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
4435 int colorAttCount = 0;
4437 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
4439 const QRhiColorAttachment &colorAtt(*it);
4440 QRhiTexture *texture = colorAtt.texture();
4441 QRhiRenderBuffer *rb = colorAtt.renderBuffer();
4442 Q_ASSERT(texture || rb);
4445 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
4446 rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
4447 if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
4448 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4449 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4450 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4451 rtvDesc.Texture2DArray.ArraySize = 1;
4452 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
4453 if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4454 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
4455 rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
4456 rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
4457 rtvDesc.Texture1DArray.ArraySize = 1;
4459 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
4460 rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
4462 }
else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
4463 if (texD->sampleDesc.Count > 1) {
4464 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
4465 rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
4466 rtvDesc.Texture2DMSArray.ArraySize = 1;
4468 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
4469 rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
4470 rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
4471 rtvDesc.Texture2DArray.ArraySize = 1;
4473 }
else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
4474 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
4475 rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
4476 rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
4477 rtvDesc.Texture3D.WSize = 1;
4479 if (texD->sampleDesc.Count > 1) {
4480 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
4482 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
4483 rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
4486 HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
4488 qWarning(
"Failed to create rtv: %s",
4489 qPrintable(QSystemError::windowsComString(hr)));
4493 if (attIndex == 0) {
4494 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
4495 d.sampleCount =
int(texD->sampleDesc.Count);
4500 rtv[attIndex] = rbD->rtv;
4501 if (attIndex == 0) {
4502 d.pixelSize = rbD->pixelSize();
4503 d.sampleCount =
int(rbD->sampleDesc.Count);
4509 if (hasDepthStencil) {
4510 if (m_desc.depthTexture()) {
4513 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
4514 dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
4515 const bool isMultisample = depthTexD->sampleDesc.Count > 1;
4516 if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
4517 if (isMultisample) {
4518 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
4519 if (m_desc.depthLayer() >= 0) {
4520 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_desc.depthLayer());
4521 dsvDesc.Texture2DMSArray.ArraySize = 1;
4522 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4523 dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4524 dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4526 dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
4527 dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4530 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
4531 if (m_desc.depthLayer() >= 0) {
4532 dsvDesc.Texture2DArray.FirstArraySlice = UINT(m_desc.depthLayer());
4533 dsvDesc.Texture2DArray.ArraySize = 1;
4534 }
else if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
4535 dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
4536 dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
4538 dsvDesc.Texture2DArray.FirstArraySlice = 0;
4539 dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
4544 dsvDesc.ViewDimension = isMultisample ? D3D11_DSV_DIMENSION_TEXTURE2DMS
4545 : D3D11_DSV_DIMENSION_TEXTURE2D;
4547 HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
4549 qWarning(
"Failed to create dsv: %s",
4550 qPrintable(QSystemError::windowsComString(hr)));
4553 if (colorAttCount == 0) {
4554 d.pixelSize = depthTexD->pixelSize();
4555 d.sampleCount =
int(depthTexD->sampleDesc.Count);
4560 dsv = depthRbD->dsv;
4561 if (colorAttCount == 0) {
4562 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
4563 d.sampleCount =
int(depthRbD->sampleDesc.Count);
4570 d.views.setFrom(colorAttCount, rtv, dsv);
4572 d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
4574 QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
4576 rhiD->registerResource(
this);
4582 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
4595 return d.sampleCount;
4610 sortedBindings.clear();
4611 boundResourceData.clear();
4615 rhiD->unregisterResource(
this);
4620 if (!sortedBindings.isEmpty())
4624 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4627 rhiD->updateLayoutDesc(
this);
4629 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4630 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4632 boundResourceData.resize(sortedBindings.count());
4634 for (BoundResourceData &bd : boundResourceData)
4638 for (
const QRhiShaderResourceBinding &b : sortedBindings) {
4639 const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
4640 if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
4641 hasDynamicOffset =
true;
4647 rhiD->registerResource(
this,
false);
4653 sortedBindings.clear();
4654 std::copy(m_bindings.cbegin(), m_bindings.cend(),
std::back_inserter(sortedBindings));
4655 if (!flags.testFlag(BindingsAreSorted))
4656 std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
4658 Q_ASSERT(boundResourceData.count() == sortedBindings.count());
4659 for (BoundResourceData &bd : boundResourceData)
4679 s.shader->Release();
4682 s.nativeResourceBindingMap.clear();
4694 blendState->Release();
4695 blendState =
nullptr;
4699 inputLayout->Release();
4700 inputLayout =
nullptr;
4704 rastState->Release();
4705 rastState =
nullptr;
4708 releasePipelineShader(vs);
4709 releasePipelineShader(hs);
4710 releasePipelineShader(ds);
4711 releasePipelineShader(gs);
4712 releasePipelineShader(fs);
4718 rhiD->unregisterResource(
this);
4724 case QRhiGraphicsPipeline::None:
4725 return D3D11_CULL_NONE;
4726 case QRhiGraphicsPipeline::Front:
4727 return D3D11_CULL_FRONT;
4728 case QRhiGraphicsPipeline::Back:
4729 return D3D11_CULL_BACK;
4732 return D3D11_CULL_NONE;
4739 case QRhiGraphicsPipeline::Fill:
4740 return D3D11_FILL_SOLID;
4741 case QRhiGraphicsPipeline::Line:
4742 return D3D11_FILL_WIREFRAME;
4745 return D3D11_FILL_SOLID;
4752 case QRhiGraphicsPipeline::Never:
4753 return D3D11_COMPARISON_NEVER;
4754 case QRhiGraphicsPipeline::Less:
4755 return D3D11_COMPARISON_LESS;
4756 case QRhiGraphicsPipeline::Equal:
4757 return D3D11_COMPARISON_EQUAL;
4758 case QRhiGraphicsPipeline::LessOrEqual:
4759 return D3D11_COMPARISON_LESS_EQUAL;
4760 case QRhiGraphicsPipeline::Greater:
4761 return D3D11_COMPARISON_GREATER;
4762 case QRhiGraphicsPipeline::NotEqual:
4763 return D3D11_COMPARISON_NOT_EQUAL;
4764 case QRhiGraphicsPipeline::GreaterOrEqual:
4765 return D3D11_COMPARISON_GREATER_EQUAL;
4766 case QRhiGraphicsPipeline::Always:
4767 return D3D11_COMPARISON_ALWAYS;
4770 return D3D11_COMPARISON_ALWAYS;
4777 case QRhiGraphicsPipeline::StencilZero:
4778 return D3D11_STENCIL_OP_ZERO;
4779 case QRhiGraphicsPipeline::Keep:
4780 return D3D11_STENCIL_OP_KEEP;
4781 case QRhiGraphicsPipeline::Replace:
4782 return D3D11_STENCIL_OP_REPLACE;
4783 case QRhiGraphicsPipeline::IncrementAndClamp:
4784 return D3D11_STENCIL_OP_INCR_SAT;
4785 case QRhiGraphicsPipeline::DecrementAndClamp:
4786 return D3D11_STENCIL_OP_DECR_SAT;
4787 case QRhiGraphicsPipeline::Invert:
4788 return D3D11_STENCIL_OP_INVERT;
4789 case QRhiGraphicsPipeline::IncrementAndWrap:
4790 return D3D11_STENCIL_OP_INCR;
4791 case QRhiGraphicsPipeline::DecrementAndWrap:
4792 return D3D11_STENCIL_OP_DECR;
4795 return D3D11_STENCIL_OP_KEEP;
4802 case QRhiVertexInputAttribute::Float4:
4803 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4804 case QRhiVertexInputAttribute::Float3:
4805 return DXGI_FORMAT_R32G32B32_FLOAT;
4806 case QRhiVertexInputAttribute::Float2:
4807 return DXGI_FORMAT_R32G32_FLOAT;
4808 case QRhiVertexInputAttribute::Float:
4809 return DXGI_FORMAT_R32_FLOAT;
4810 case QRhiVertexInputAttribute::UNormByte4:
4811 return DXGI_FORMAT_R8G8B8A8_UNORM;
4812 case QRhiVertexInputAttribute::UNormByte2:
4813 return DXGI_FORMAT_R8G8_UNORM;
4814 case QRhiVertexInputAttribute::UNormByte:
4815 return DXGI_FORMAT_R8_UNORM;
4816 case QRhiVertexInputAttribute::UInt4:
4817 return DXGI_FORMAT_R32G32B32A32_UINT;
4818 case QRhiVertexInputAttribute::UInt3:
4819 return DXGI_FORMAT_R32G32B32_UINT;
4820 case QRhiVertexInputAttribute::UInt2:
4821 return DXGI_FORMAT_R32G32_UINT;
4822 case QRhiVertexInputAttribute::UInt:
4823 return DXGI_FORMAT_R32_UINT;
4824 case QRhiVertexInputAttribute::SInt4:
4825 return DXGI_FORMAT_R32G32B32A32_SINT;
4826 case QRhiVertexInputAttribute::SInt3:
4827 return DXGI_FORMAT_R32G32B32_SINT;
4828 case QRhiVertexInputAttribute::SInt2:
4829 return DXGI_FORMAT_R32G32_SINT;
4830 case QRhiVertexInputAttribute::SInt:
4831 return DXGI_FORMAT_R32_SINT;
4832 case QRhiVertexInputAttribute::Half4:
4834 case QRhiVertexInputAttribute::Half3:
4835 return DXGI_FORMAT_R16G16B16A16_FLOAT;
4836 case QRhiVertexInputAttribute::Half2:
4837 return DXGI_FORMAT_R16G16_FLOAT;
4838 case QRhiVertexInputAttribute::Half:
4839 return DXGI_FORMAT_R16_FLOAT;
4840 case QRhiVertexInputAttribute::UShort4:
4842 case QRhiVertexInputAttribute::UShort3:
4843 return DXGI_FORMAT_R16G16B16A16_UINT;
4844 case QRhiVertexInputAttribute::UShort2:
4845 return DXGI_FORMAT_R16G16_UINT;
4846 case QRhiVertexInputAttribute::UShort:
4847 return DXGI_FORMAT_R16_UINT;
4848 case QRhiVertexInputAttribute::SShort4:
4850 case QRhiVertexInputAttribute::SShort3:
4851 return DXGI_FORMAT_R16G16B16A16_SINT;
4852 case QRhiVertexInputAttribute::SShort2:
4853 return DXGI_FORMAT_R16G16_SINT;
4854 case QRhiVertexInputAttribute::SShort:
4855 return DXGI_FORMAT_R16_SINT;
4858 return DXGI_FORMAT_R32G32B32A32_FLOAT;
4865 case QRhiGraphicsPipeline::Triangles:
4866 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4867 case QRhiGraphicsPipeline::TriangleStrip:
4868 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
4869 case QRhiGraphicsPipeline::Lines:
4870 return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
4871 case QRhiGraphicsPipeline::LineStrip:
4872 return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
4873 case QRhiGraphicsPipeline::Points:
4874 return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
4875 case QRhiGraphicsPipeline::Patches:
4876 Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
4877 return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
4880 return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
4887 if (c.testFlag(QRhiGraphicsPipeline::R))
4888 f |= D3D11_COLOR_WRITE_ENABLE_RED;
4889 if (c.testFlag(QRhiGraphicsPipeline::G))
4890 f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
4891 if (c.testFlag(QRhiGraphicsPipeline::B))
4892 f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
4893 if (c.testFlag(QRhiGraphicsPipeline::A))
4894 f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
4907 case QRhiGraphicsPipeline::Zero:
4908 return D3D11_BLEND_ZERO;
4909 case QRhiGraphicsPipeline::One:
4910 return D3D11_BLEND_ONE;
4911 case QRhiGraphicsPipeline::SrcColor:
4912 return rgb ? D3D11_BLEND_SRC_COLOR : D3D11_BLEND_SRC_ALPHA;
4913 case QRhiGraphicsPipeline::OneMinusSrcColor:
4914 return rgb ? D3D11_BLEND_INV_SRC_COLOR : D3D11_BLEND_INV_SRC_ALPHA;
4915 case QRhiGraphicsPipeline::DstColor:
4916 return rgb ? D3D11_BLEND_DEST_COLOR : D3D11_BLEND_DEST_ALPHA;
4917 case QRhiGraphicsPipeline::OneMinusDstColor:
4918 return rgb ? D3D11_BLEND_INV_DEST_COLOR : D3D11_BLEND_INV_DEST_ALPHA;
4919 case QRhiGraphicsPipeline::SrcAlpha:
4920 return D3D11_BLEND_SRC_ALPHA;
4921 case QRhiGraphicsPipeline::OneMinusSrcAlpha:
4922 return D3D11_BLEND_INV_SRC_ALPHA;
4923 case QRhiGraphicsPipeline::DstAlpha:
4924 return D3D11_BLEND_DEST_ALPHA;
4925 case QRhiGraphicsPipeline::OneMinusDstAlpha:
4926 return D3D11_BLEND_INV_DEST_ALPHA;
4927 case QRhiGraphicsPipeline::ConstantColor:
4928 case QRhiGraphicsPipeline::ConstantAlpha:
4929 return D3D11_BLEND_BLEND_FACTOR;
4930 case QRhiGraphicsPipeline::OneMinusConstantColor:
4931 case QRhiGraphicsPipeline::OneMinusConstantAlpha:
4932 return D3D11_BLEND_INV_BLEND_FACTOR;
4933 case QRhiGraphicsPipeline::SrcAlphaSaturate:
4934 return D3D11_BLEND_SRC_ALPHA_SAT;
4935 case QRhiGraphicsPipeline::Src1Color:
4936 return rgb ? D3D11_BLEND_SRC1_COLOR : D3D11_BLEND_SRC1_ALPHA;
4937 case QRhiGraphicsPipeline::OneMinusSrc1Color:
4938 return rgb ? D3D11_BLEND_INV_SRC1_COLOR : D3D11_BLEND_INV_SRC1_ALPHA;
4939 case QRhiGraphicsPipeline::Src1Alpha:
4940 return D3D11_BLEND_SRC1_ALPHA;
4941 case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
4942 return D3D11_BLEND_INV_SRC1_ALPHA;
4945 return D3D11_BLEND_ZERO;
4952 case QRhiGraphicsPipeline::Add:
4953 return D3D11_BLEND_OP_ADD;
4954 case QRhiGraphicsPipeline::Subtract:
4955 return D3D11_BLEND_OP_SUBTRACT;
4956 case QRhiGraphicsPipeline::ReverseSubtract:
4957 return D3D11_BLEND_OP_REV_SUBTRACT;
4958 case QRhiGraphicsPipeline::Min:
4959 return D3D11_BLEND_OP_MIN;
4960 case QRhiGraphicsPipeline::Max:
4961 return D3D11_BLEND_OP_MAX;
4964 return D3D11_BLEND_OP_ADD;
4971 QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
4972 keyBuilder.addData(source);
4973 return keyBuilder.result().toHex();
4977 QString *error, QShaderKey *usedShaderKey)
4979 QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
4980 QShaderCode dxbc = shader.shader(key);
4981 if (!dxbc.shader().isEmpty()) {
4983 *usedShaderKey = key;
4984 return dxbc.shader();
4987 key = { QShader::HlslShader, 50, shaderVariant };
4988 QShaderCode hlslSource = shader.shader(key);
4989 if (hlslSource.shader().isEmpty()) {
4990 qWarning() <<
"No HLSL (shader model 5.0) code found in baked shader" << shader;
4991 return QByteArray();
4995 *usedShaderKey = key;
4998 switch (shader.stage()) {
4999 case QShader::VertexStage:
5002 case QShader::TessellationControlStage:
5005 case QShader::TessellationEvaluationStage:
5008 case QShader::GeometryStage:
5011 case QShader::FragmentStage:
5014 case QShader::ComputeStage:
5018 qWarning(
"compileHlslShaderSource: Unknown SM 5.0 stage (%d)",
int(shader.stage()));
5019 return QByteArray();
5023 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
5024 cacheKey.sourceHash = sourceHash(hlslSource.shader());
5025 cacheKey.target = target;
5026 cacheKey.entryPoint = hlslSource.entryPoint();
5028 auto cacheIt = m_bytecodeCache.data.constFind(cacheKey);
5029 if (cacheIt != m_bytecodeCache.data.constEnd())
5030 return cacheIt.value();
5033 static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
5034 if (d3dCompile ==
nullptr) {
5035 qWarning(
"Unable to resolve function D3DCompile()");
5036 return QByteArray();
5039 ID3DBlob *bytecode =
nullptr;
5040 ID3DBlob *errors =
nullptr;
5041 HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
5042 nullptr,
nullptr,
nullptr,
5043 hlslSource.entryPoint().constData(), target, flags, 0, &bytecode, &errors);
5044 if (FAILED(hr) || !bytecode) {
5045 qWarning(
"HLSL shader compilation failed: 0x%x", uint(hr));
5047 *error = QString::fromUtf8(
static_cast<
const char *>(errors->GetBufferPointer()),
5048 int(errors->GetBufferSize()));
5051 return QByteArray();
5055 result.resize(
int(bytecode->GetBufferSize()));
5056 memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
5057 bytecode->Release();
5059 if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
5060 m_bytecodeCache.insertWithCapacityLimit(cacheKey, result);
5071 rhiD->pipelineCreationStart();
5072 if (!rhiD->sanityCheckGraphicsPipeline(
this))
5075 D3D11_RASTERIZER_DESC rastDesc = {};
5076 rastDesc.FillMode = toD3DFillMode(m_polygonMode);
5077 rastDesc.CullMode = toD3DCullMode(m_cullMode);
5078 rastDesc.FrontCounterClockwise = m_frontFace == CCW;
5079 rastDesc.DepthBias = m_depthBias;
5080 rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
5081 rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
5082 rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
5083 rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
5084 HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
5086 qWarning(
"Failed to create rasterizer state: %s",
5087 qPrintable(QSystemError::windowsComString(hr)));
5091 D3D11_DEPTH_STENCIL_DESC dsDesc = {};
5092 dsDesc.DepthEnable = m_depthTest;
5093 dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
5094 dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
5095 dsDesc.StencilEnable = m_stencilTest;
5096 if (m_stencilTest) {
5097 dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
5098 dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
5099 dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
5100 dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
5101 dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
5102 dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
5103 dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
5104 dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
5105 dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
5106 dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
5108 hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
5110 qWarning(
"Failed to create depth-stencil state: %s",
5111 qPrintable(QSystemError::windowsComString(hr)));
5115 D3D11_BLEND_DESC blendDesc = {};
5116 blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
5117 for (
int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
5118 const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
5119 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5120 blend.BlendEnable = b.enable;
5121 blend.SrcBlend = toD3DBlendFactor(b.srcColor,
true);
5122 blend.DestBlend = toD3DBlendFactor(b.dstColor,
true);
5123 blend.BlendOp = toD3DBlendOp(b.opColor);
5124 blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha,
false);
5125 blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha,
false);
5126 blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
5127 blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
5128 blendDesc.RenderTarget[i] = blend;
5130 if (m_targetBlends.isEmpty()) {
5131 D3D11_RENDER_TARGET_BLEND_DESC blend = {};
5132 blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
5133 blendDesc.RenderTarget[0] = blend;
5135 hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
5137 qWarning(
"Failed to create blend state: %s",
5138 qPrintable(QSystemError::windowsComString(hr)));
5142 QByteArray vsByteCode;
5143 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
5144 int stagePushConstantRegister = -1;
5145 quint32 stagePushConstantSize = 0;
5146 auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
5147 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5148 stagePushConstantRegister = cacheIt->pushConstantRegister;
5149 stagePushConstantSize = cacheIt->pushConstantSize;
5150 switch (shaderStage.type()) {
5151 case QRhiShaderStage::Vertex:
5152 vs.shader =
static_cast<ID3D11VertexShader *>(cacheIt->s);
5153 vs.shader->AddRef();
5154 vsByteCode = cacheIt->bytecode;
5155 vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5157 case QRhiShaderStage::TessellationControl:
5158 hs.shader =
static_cast<ID3D11HullShader *>(cacheIt->s);
5159 hs.shader->AddRef();
5160 hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5162 case QRhiShaderStage::TessellationEvaluation:
5163 ds.shader =
static_cast<ID3D11DomainShader *>(cacheIt->s);
5164 ds.shader->AddRef();
5165 ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5167 case QRhiShaderStage::Geometry:
5168 gs.shader =
static_cast<ID3D11GeometryShader *>(cacheIt->s);
5169 gs.shader->AddRef();
5170 gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5172 case QRhiShaderStage::Fragment:
5173 fs.shader =
static_cast<ID3D11PixelShader *>(cacheIt->s);
5174 fs.shader->AddRef();
5175 fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5182 QShaderKey shaderKey;
5183 UINT compileFlags = 0;
5184 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5185 compileFlags |= D3DCOMPILE_DEBUG;
5187 const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
5188 &error, &shaderKey);
5189 if (bytecode.isEmpty()) {
5190 qWarning(
"HLSL shader compilation failed: %s", qPrintable(error));
5194 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
5196 rhiD->clearShaderCache();
5199 getPushConstantInfo(shaderStage.shader(), shaderKey, &stagePushConstantRegister, &stagePushConstantSize);
5201 switch (shaderStage.type()) {
5202 case QRhiShaderStage::Vertex:
5203 hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &vs.shader);
5205 qWarning(
"Failed to create vertex shader: %s",
5206 qPrintable(QSystemError::windowsComString(hr)));
5209 vsByteCode = bytecode;
5210 vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5211 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap,
5212 stagePushConstantRegister, stagePushConstantSize));
5213 vs.shader->AddRef();
5215 case QRhiShaderStage::TessellationControl:
5216 hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &hs.shader);
5218 qWarning(
"Failed to create hull shader: %s",
5219 qPrintable(QSystemError::windowsComString(hr)));
5222 hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5223 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap,
5224 stagePushConstantRegister, stagePushConstantSize));
5225 hs.shader->AddRef();
5227 case QRhiShaderStage::TessellationEvaluation:
5228 hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &ds.shader);
5230 qWarning(
"Failed to create domain shader: %s",
5231 qPrintable(QSystemError::windowsComString(hr)));
5234 ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5235 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap,
5236 stagePushConstantRegister, stagePushConstantSize));
5237 ds.shader->AddRef();
5239 case QRhiShaderStage::Geometry:
5240 hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &gs.shader);
5242 qWarning(
"Failed to create geometry shader: %s",
5243 qPrintable(QSystemError::windowsComString(hr)));
5246 gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5247 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap,
5248 stagePushConstantRegister, stagePushConstantSize));
5249 gs.shader->AddRef();
5251 case QRhiShaderStage::Fragment:
5252 hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &fs.shader);
5254 qWarning(
"Failed to create pixel shader: %s",
5255 qPrintable(QSystemError::windowsComString(hr)));
5258 fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
5259 rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap,
5260 stagePushConstantRegister, stagePushConstantSize));
5261 fs.shader->AddRef();
5268 if (stagePushConstantRegister >= 0 && stagePushConstantSize) {
5269 const int stageIndex = rbmStageIndex(shaderStage.type());
5270 if (stageIndex >= 0) {
5271 pushConstants.reg = stagePushConstantRegister;
5272 pushConstants.size = qMax(pushConstants.size, stagePushConstantSize);
5273 pushConstants.stages |= 1u << uint(stageIndex);
5278 d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
5280 if (!vsByteCode.isEmpty()) {
5281 QByteArrayList matrixSliceSemantics;
5282 QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
5283 for (
auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
5286 D3D11_INPUT_ELEMENT_DESC desc = {};
5291 const int matrixSlice = it->matrixSlice();
5292 if (matrixSlice < 0) {
5293 desc.SemanticName =
"TEXCOORD";
5294 desc.SemanticIndex = UINT(it->location());
5298 std::snprintf(sem.data(), sem.size(),
"TEXCOORD%d_", it->location() - matrixSlice);
5299 matrixSliceSemantics.append(sem);
5300 desc.SemanticName = matrixSliceSemantics.last().constData();
5301 desc.SemanticIndex = UINT(matrixSlice);
5303 desc.Format = toD3DAttributeFormat(it->format());
5304 desc.InputSlot = UINT(it->binding());
5305 desc.AlignedByteOffset = it->offset();
5306 const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
5307 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
5308 desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
5309 desc.InstanceDataStepRate = inputBinding->instanceStepRate();
5311 desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
5313 inputDescs.append(desc);
5315 if (!inputDescs.isEmpty()) {
5316 hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
5317 vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
5319 qWarning(
"Failed to create input layout: %s",
5320 qPrintable(QSystemError::windowsComString(hr)));
5326 rhiD->pipelineCreationEnd();
5328 rhiD->registerResource(
this);
5347 cs.shader->Release();
5348 cs.shader =
nullptr;
5349 cs.nativeResourceBindingMap.clear();
5354 rhiD->unregisterResource(
this);
5363 rhiD->pipelineCreationStart();
5365 auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
5366 if (cacheIt != rhiD->m_shaderCache.constEnd()) {
5367 cs.shader =
static_cast<ID3D11ComputeShader *>(cacheIt->s);
5368 cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
5369 pushConstants.reg = cacheIt->pushConstantRegister;
5370 pushConstants.size = cacheIt->pushConstantSize;
5373 QShaderKey shaderKey;
5374 UINT compileFlags = 0;
5375 if (m_flags.testFlag(CompileShadersWithDebugInfo))
5376 compileFlags |= D3DCOMPILE_DEBUG;
5378 const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
5379 &error, &shaderKey);
5380 if (bytecode.isEmpty()) {
5381 qWarning(
"HLSL compute shader compilation failed: %s", qPrintable(error));
5385 HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()),
nullptr, &cs.shader);
5387 qWarning(
"Failed to create compute shader: %s",
5388 qPrintable(QSystemError::windowsComString(hr)));
5392 cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
5393 getPushConstantInfo(m_shaderStage.shader(), shaderKey, &pushConstants.reg, &pushConstants.size);
5395 if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
5398 rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap,
5399 pushConstants.reg, pushConstants.size));
5402 cs.shader->AddRef();
5404 rhiD->pipelineCreationEnd();
5406 rhiD->registerResource(
this);
5431 D3D11_QUERY_DESC queryDesc = {};
5433 if (!disjointQuery[i]) {
5434 queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
5435 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
5437 qWarning(
"Failed to create timestamp disjoint query: %s",
5438 qPrintable(QSystemError::windowsComString(hr)));
5442 queryDesc.Query = D3D11_QUERY_TIMESTAMP;
5443 for (
int j = 0; j < 2; ++j) {
5444 const int idx = 2 * i + j;
5446 HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
5448 qWarning(
"Failed to create timestamp query: %s",
5449 qPrintable(QSystemError::windowsComString(hr)));
5462 if (disjointQuery[i]) {
5463 disjointQuery[i]->Release();
5464 disjointQuery[i] =
nullptr;
5466 for (
int j = 0; j < 2; ++j) {
5469 query[idx]->Release();
5470 query[idx] =
nullptr;
5478 bool result =
false;
5482 ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
5483 ID3D11Query *tsStart = query[pairIndex * 2];
5484 ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
5485 quint64 timestamps[2];
5486 D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
5489 ok &= context->GetData(tsDisjoint, &dj,
sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5490 ok &= context->GetData(tsEnd, ×tamps[1],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5491 ok &= context->GetData(tsStart, ×tamps[0],
sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
5494 if (!dj.Disjoint && dj.Frequency) {
5495 const float elapsedMs = (timestamps[1] - timestamps[0]) /
float(dj.Frequency) * 1000.0f;
5496 *elapsedSec = elapsedMs / 1000.0;
5499 active[pairIndex] =
false;
5508 backBufferTex =
nullptr;
5509 backBufferRtv =
nullptr;
5511 msaaTex[i] =
nullptr;
5512 msaaRtv[i] =
nullptr;
5523 if (backBufferRtv) {
5524 backBufferRtv->Release();
5525 backBufferRtv =
nullptr;
5527 if (backBufferRtvRight) {
5528 backBufferRtvRight->Release();
5529 backBufferRtvRight =
nullptr;
5531 if (backBufferTex) {
5532 backBufferTex->Release();
5533 backBufferTex =
nullptr;
5537 msaaRtv[i]->Release();
5538 msaaRtv[i] =
nullptr;
5541 msaaTex[i]->Release();
5542 msaaTex[i] =
nullptr;
5554 timestamps.destroy();
5556 swapChain->Release();
5557 swapChain =
nullptr;
5560 dcompVisual->Release();
5561 dcompVisual =
nullptr;
5565 dcompTarget->Release();
5566 dcompTarget =
nullptr;
5569 if (frameLatencyWaitableObject) {
5570 CloseHandle(frameLatencyWaitableObject);
5571 frameLatencyWaitableObject =
nullptr;
5574 QDxgiVSyncService::instance()->unregisterWindow(window);
5578 rhiD->unregisterResource(
this);
5581 rhiD->context->Flush();
5597 return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
5603 return m_window->size() * m_window->devicePixelRatio();
5612 qWarning(
"Attempted to call isFormatSupported() without a window set");
5617 if (QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window))
5618 return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
5629 info = QDxgiHdrInfo(rhiD->activeAdapter).queryHdrInfo(m_window);
5638 rhiD->registerResource(rpD,
false);
5643 ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv)
const
5645 D3D11_TEXTURE2D_DESC desc = {};
5646 desc.Width = UINT(size.width());
5647 desc.Height = UINT(size.height());
5650 desc.Format = format;
5651 desc.SampleDesc = sampleDesc;
5652 desc.Usage = D3D11_USAGE_DEFAULT;
5653 desc.BindFlags = D3D11_BIND_RENDER_TARGET;
5656 HRESULT hr = rhiD->dev->CreateTexture2D(&desc,
nullptr, tex);
5658 qWarning(
"Failed to create color buffer texture: %s",
5659 qPrintable(QSystemError::windowsComString(hr)));
5663 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5664 rtvDesc.Format = format;
5665 rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
5666 hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
5668 qWarning(
"Failed to create color buffer rtv: %s",
5669 qPrintable(QSystemError::windowsComString(hr)));
5683 qCDebug(QRHI_LOG_INFO,
"Creating Direct Composition device (needed for semi-transparent windows)");
5684 dcompDevice = QRhiD3D::createDirectCompositionDevice();
5685 return dcompDevice ?
true :
false;
5697 const bool needsRegistration = !window || window != m_window;
5698 const bool stereo = m_window->format().stereo();
5701 if (window && window != m_window)
5705 m_currentPixelSize = surfacePixelSize();
5706 pixelSize = m_currentPixelSize;
5708 if (pixelSize.isEmpty())
5711 HWND hwnd =
reinterpret_cast<HWND>(
window->winId());
5716 if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
5719 hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd,
false, &dcompTarget);
5721 qWarning(
"Failed to create Direct Compsition target for the window: %s",
5722 qPrintable(QSystemError::windowsComString(hr)));
5725 if (dcompTarget && !dcompVisual) {
5726 hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
5728 qWarning(
"Failed to create DirectComposition visual: %s",
5729 qPrintable(QSystemError::windowsComString(hr)));
5734 if (
window->requestedFormat().alphaBufferSize() <= 0)
5735 qWarning(
"Swapchain says surface has alpha but the window has no alphaBufferSize set. "
5736 "This may lead to problems.");
5739 swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
5746 if (swapInterval == 0 && rhiD->supportsAllowTearing)
5747 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
5751 const bool useFrameLatencyWaitableObject = rhiD->maxFrameLatency != 0
5752 && swapInterval != 0
5753 && rhiD->driverInfoStruct.deviceType != QRhiDriverInfo::CpuDevice;
5755 if (useFrameLatencyWaitableObject) {
5757 swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
5761 sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
5762 colorFormat = DEFAULT_FORMAT;
5763 srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
5765 DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
5766 if (m_format != SDR) {
5767 if (
QDxgiHdrInfo(rhiD->activeAdapter).isHdrCapable(m_window)) {
5770 case HDRExtendedSrgbLinear:
5771 colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
5772 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
5773 srgbAdjustedColorFormat = colorFormat;
5776 colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
5777 hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
5778 srgbAdjustedColorFormat = colorFormat;
5787 qWarning(
"The output associated with the window is not HDR capable "
5788 "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
5798 DXGI_SWAP_CHAIN_DESC1 desc = {};
5799 desc.Width = UINT(pixelSize.width());
5800 desc.Height = UINT(pixelSize.height());
5801 desc.Format = colorFormat;
5802 desc.SampleDesc.Count = 1;
5803 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
5805 desc.Flags = swapChainFlags;
5806 desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
5807 desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
5808 desc.Stereo = stereo;
5814 desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
5819 desc.Scaling = DXGI_SCALING_STRETCH;
5822 IDXGIFactory2 *fac =
static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
5823 IDXGISwapChain1 *sc1;
5826 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5828 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5833 if (FAILED(hr) && m_format != SDR) {
5834 colorFormat = DEFAULT_FORMAT;
5835 desc.Format = DEFAULT_FORMAT;
5837 hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc,
nullptr, &sc1);
5839 hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
nullptr,
nullptr, &sc1);
5842 if (SUCCEEDED(hr)) {
5844 IDXGISwapChain3 *sc3 =
nullptr;
5845 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3),
reinterpret_cast<
void **>(&sc3)))) {
5846 if (m_format != SDR) {
5847 hr = sc3->SetColorSpace1(hdrColorSpace);
5849 qWarning(
"Failed to set color space on swapchain: %s",
5850 qPrintable(QSystemError::windowsComString(hr)));
5852 if (useFrameLatencyWaitableObject) {
5853 sc3->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5854 frameLatencyWaitableObject = sc3->GetFrameLatencyWaitableObject();
5858 if (m_format != SDR)
5859 qWarning(
"IDXGISwapChain3 not available, HDR swapchain will not work as expected");
5860 if (useFrameLatencyWaitableObject) {
5861 IDXGISwapChain2 *sc2 =
nullptr;
5862 if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain2),
reinterpret_cast<
void **>(&sc2)))) {
5863 sc2->SetMaximumFrameLatency(rhiD->maxFrameLatency);
5864 frameLatencyWaitableObject = sc2->GetFrameLatencyWaitableObject();
5867 qWarning(
"IDXGISwapChain2 not available, FrameLatencyWaitableObject cannot be used");
5872 hr = dcompVisual->SetContent(sc1);
5873 if (SUCCEEDED(hr)) {
5874 hr = dcompTarget->SetRoot(dcompVisual);
5876 qWarning(
"Failed to associate Direct Composition visual with the target: %s",
5877 qPrintable(QSystemError::windowsComString(hr)));
5880 qWarning(
"Failed to set content for Direct Composition visual: %s",
5881 qPrintable(QSystemError::windowsComString(hr)));
5885 rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
5888 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5889 qWarning(
"Device loss detected during swapchain creation");
5892 }
else if (FAILED(hr)) {
5893 qWarning(
"Failed to create D3D11 swapchain: %s"
5894 " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
5895 qPrintable(QSystemError::windowsComString(hr)),
5896 desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
5897 desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
5903 hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
5904 colorFormat, swapChainFlags);
5905 if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
5906 qWarning(
"Device loss detected in ResizeBuffers()");
5909 }
else if (FAILED(hr)) {
5910 qWarning(
"Failed to resize D3D11 swapchain: %s",
5911 qPrintable(QSystemError::windowsComString(hr)));
5930 hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
reinterpret_cast<
void **>(&backBufferTex));
5932 qWarning(
"Failed to query swapchain backbuffer: %s",
5933 qPrintable(QSystemError::windowsComString(hr)));
5936 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
5937 rtvDesc.Format = srgbAdjustedColorFormat;
5938 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
5939 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
5941 qWarning(
"Failed to create rtv for swapchain backbuffer: %s",
5942 qPrintable(QSystemError::windowsComString(hr)));
5948 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
5949 rtvDesc.Texture2DArray.FirstArraySlice = 1;
5950 rtvDesc.Texture2DArray.ArraySize = 1;
5951 hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
5953 qWarning(
"Failed to create rtv for swapchain backbuffer (right eye): %s",
5954 qPrintable(QSystemError::windowsComString(hr)));
5961 if (sampleDesc.Count > 1) {
5962 if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
5967 if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
5968 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
5969 m_depthStencil->sampleCount(), m_sampleCount);
5971 if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
5972 if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
5973 m_depthStencil->setPixelSize(pixelSize);
5974 if (!m_depthStencil->create())
5975 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
5976 pixelSize.width(), pixelSize.height());
5978 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
5979 m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
5980 pixelSize.width(), pixelSize.height());
5987 ds = m_depthStencil ?
QRHI_RES(QD3D11RenderBuffer, m_depthStencil) :
nullptr;
5989 rt.setRenderPassDescriptor(m_renderPassDesc);
5991 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
5992 rtD->d.pixelSize = pixelSize;
5993 rtD->d.dpr =
float(
window->devicePixelRatio());
5994 rtD->d.sampleCount =
int(sampleDesc.Count);
5995 rtD->d.views.setFrom(1, &backBufferRtv,
ds ?
ds->dsv :
nullptr);
5998 rtD =
QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
5999 rtD->d.rp =
QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
6000 rtD->d.pixelSize = pixelSize;
6001 rtD->d.dpr =
float(
window->devicePixelRatio());
6002 rtD->d.sampleCount =
int(sampleDesc.Count);
6003 rtD->d.views.setFrom(1, &backBufferRtvRight,
ds ?
ds->dsv :
nullptr);
6006 if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
6007 timestamps.prepare(rhiD);
6011 QDxgiVSyncService::instance()->registerWindow(window);
6013 if (needsRegistration)
6014 rhiD->registerResource(
this);
6022 if (rtViews.dsv != currentRtViews.dsv) {
6023 rtViews.dsv = currentRtViews.dsv;
6027 ret |= rtViews.rtv[i] != currentRtViews.rtv[i];
6028 rtViews.rtv[i] = currentRtViews.rtv[i];
6030 rtViews.colorAttCount = currentRtViews.colorAttCount;
6032 ret |= rtViews.rtv[i] !=
nullptr;
6033 rtViews.rtv[i] =
nullptr;
6035 for (
int i = 0; i < count; i++) {
6036 ret |= uav[i] != uavs[i];
6040 ret |= uav[i] !=
nullptr;
QRhiDriverInfo info() const override
const char * constData() const
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[], uint pushConstantStages)
int gsHighestActiveSrvBinding
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int dsHighestActiveSrvBinding
bool isYUpInNDC() const override
void drawIndexedIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
QRhiSwapChain * createSwapChain() override
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
bool isFeatureSupported(QRhi::Feature feature) const override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
bool isDeviceLost() const override
bool vsHasIndexBufferBound
void executeBufferHostWrites(QD3D11Buffer *bufD)
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
int csHighestActiveSrvBinding
bool isClipDepthZeroToOne() const override
void resetShaderResources(QD3D11CommandBuffer *cbD, QD3D11RenderTargetUavUpdateState *rtUavState)
bool ensureDirectCompositionDevice()
const QRhiNativeHandles * nativeHandles(QRhiCommandBuffer *cb) override
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
QD3D11SwapChain * currentSwapChain
void reportLiveObjects(ID3D11Device *device)
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QMatrix4x4 clipSpaceCorrMatrix() const override
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
int csHighestActiveUavBinding
void finishActiveReadbacks()
int fsHighestActiveSrvBinding
void setShadingRate(QRhiCommandBuffer *cb, const QSize &coarsePixelSize) override
QByteArray pipelineCacheData() override
const QRhiNativeHandles * nativeHandles() override
QRhiDriverInfo driverInfo() const override
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
int ubufAlignment() const override
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void 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
int vsHighestActiveSrvBinding
int hsHighestActiveSrvBinding
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice=nullptr)
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const
int fsHighestActiveUavBinding
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
int vsHighestActiveVertexBufferBinding
void drawIndirect(QRhiCommandBuffer *cb, QRhiBuffer *indirectBuffer, quint32 indirectBufferOffset, quint32 drawCount, quint32 stride) override
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
static const DXGI_FORMAT DEFAULT_SRGB_FORMAT
static void applyDynamicOffsets(UINT *offsets, int batchIndex, const QRhiBatchedBindings< UINT > *originalBindings, const QRhiBatchedBindings< UINT > *staticOffsets, const uint *dynOfsPairs, int dynOfsPairCount)
static D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
#define SETUAVBATCH(stagePrefixL, stagePrefixU)
static QByteArray sourceHash(const QByteArray &source)
#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU)
static const int RBM_HULL
static uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
static 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 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