summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/d3d11
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/libs/dxvk-native-1.9.2a/src/d3d11
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/dxvk-native-1.9.2a/src/d3d11')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11.def5
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.cpp92
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.h42
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.cpp309
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.h93
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.cpp287
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.h162
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.cpp59
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.h38
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmd.h43
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.cpp85
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.h49
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.cpp4507
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.h1011
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.cpp383
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.h131
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.cpp198
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.h78
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.cpp623
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.h166
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_state.h187
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.cpp51
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.h83
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.cpp166
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.h68
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.cpp3447
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.h857
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device_child.h130
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.cpp14
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.h7
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.cpp208
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.h41
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_include.h46
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp290
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.h73
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.cpp84
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.h47
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interfaces.h176
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.cpp166
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.h67
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_main.cpp247
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.cpp44
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.h109
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.cpp352
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.h114
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.cpp195
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.h66
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.cpp228
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.h147
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp147
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.h58
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.cpp140
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.h158
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.cpp199
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.h79
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.cpp37
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.h44
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.cpp681
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.h164
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.cpp1269
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.h628
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.cpp141
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.h46
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.cpp1303
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.h612
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view.h81
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.cpp280
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.h98
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.cpp440
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.h89
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.cpp592
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.h94
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.cpp447
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.h94
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/meson.build88
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_frag.frag56
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_vert.vert12
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/version.rc32
78 files changed, 24180 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11.def b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11.def
new file mode 100644
index 00000000..8b65655a
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11.def
@@ -0,0 +1,5 @@
+LIBRARY D3D11.DLL
+EXPORTS
+ D3D11CoreCreateDevice @18
+ D3D11CreateDevice @22
+ D3D11CreateDeviceAndSwapChain @23
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.cpp
new file mode 100644
index 00000000..010acdd8
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.cpp
@@ -0,0 +1,92 @@
+#include "d3d11_annotation.h"
+#include "d3d11_context.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11UserDefinedAnnotation::D3D11UserDefinedAnnotation(D3D11DeviceContext* ctx)
+ : m_container(ctx),
+ m_eventDepth(0) { }
+
+
+ D3D11UserDefinedAnnotation::~D3D11UserDefinedAnnotation() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11UserDefinedAnnotation::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11UserDefinedAnnotation::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ INT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::BeginEvent(
+ LPCWSTR Name) {
+ if (!m_container->IsAnnotationEnabled())
+ return -1;
+
+ m_container->EmitCs([labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) {
+ VkDebugUtilsLabelEXT label;
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label.pNext = nullptr;
+ label.pLabelName = labelName.c_str();
+ label.color[0] = 1.0f;
+ label.color[1] = 1.0f;
+ label.color[2] = 1.0f;
+ label.color[3] = 1.0f;
+
+ ctx->beginDebugLabel(&label);
+ });
+
+ return m_eventDepth++;
+ }
+
+
+ INT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::EndEvent() {
+ if (!m_container->IsAnnotationEnabled())
+ return -1;
+
+ m_container->EmitCs([](DxvkContext *ctx) {
+ ctx->endDebugLabel();
+ });
+
+ return m_eventDepth--;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11UserDefinedAnnotation::SetMarker(
+ LPCWSTR Name) {
+ if (!m_container->IsAnnotationEnabled())
+ return;
+
+ m_container->EmitCs([labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) {
+ VkDebugUtilsLabelEXT label;
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label.pNext = nullptr;
+ label.pLabelName = labelName.c_str();
+ label.color[0] = 1.0f;
+ label.color[1] = 1.0f;
+ label.color[2] = 1.0f;
+ label.color[3] = 1.0f;
+
+ ctx->insertDebugLabel(&label);
+ });
+ }
+
+
+ BOOL STDMETHODCALLTYPE D3D11UserDefinedAnnotation::GetStatus() {
+ return m_container->IsAnnotationEnabled();
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.h
new file mode 100644
index 00000000..97ee39c4
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_annotation.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ class D3D11DeviceContext;
+
+ class D3D11UserDefinedAnnotation : ID3DUserDefinedAnnotation {
+
+ public:
+
+ D3D11UserDefinedAnnotation(D3D11DeviceContext* ctx);
+ ~D3D11UserDefinedAnnotation();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ INT STDMETHODCALLTYPE BeginEvent(
+ LPCWSTR Name);
+
+ INT STDMETHODCALLTYPE EndEvent();
+
+ void STDMETHODCALLTYPE SetMarker(
+ LPCWSTR Name);
+
+ BOOL STDMETHODCALLTYPE GetStatus();
+
+ private:
+
+ D3D11DeviceContext* m_container;
+
+ // Stack depth for non-finalized BeginEvent calls
+ int32_t m_eventDepth;
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.cpp
new file mode 100644
index 00000000..caacc869
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.cpp
@@ -0,0 +1,309 @@
+#include "d3d11_blend.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11BlendState::D3D11BlendState(
+ D3D11Device* device,
+ const D3D11_BLEND_DESC1& desc)
+ : D3D11StateObject<ID3D11BlendState1>(device),
+ m_desc(desc), m_d3d10(this) {
+ // If Independent Blend is disabled, we must ignore the
+ // blend modes for render target 1 to 7. In Vulkan, all
+ // blend modes need to be identical in that case.
+ for (uint32_t i = 0; i < m_blendModes.size(); i++) {
+ m_blendModes.at(i) = DecodeBlendMode(
+ desc.IndependentBlendEnable
+ ? desc.RenderTarget[i]
+ : desc.RenderTarget[0]);
+ }
+
+ // Multisample state is part of the blend state in D3D11
+ m_msState.sampleMask = 0; // Set during bind
+ m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable;
+
+ // Vulkan only supports a global logic op for the blend
+ // state, which might be problematic in some cases.
+ if (desc.IndependentBlendEnable && desc.RenderTarget[0].LogicOpEnable)
+ Logger::warn("D3D11: Per-target logic ops not supported");
+
+ m_loState.enableLogicOp = desc.RenderTarget[0].LogicOpEnable;
+ m_loState.logicOp = DecodeLogicOp(desc.RenderTarget[0].LogicOp);
+ }
+
+
+ D3D11BlendState::~D3D11BlendState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11BlendState::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11BlendState)
+ || riid == __uuidof(ID3D11BlendState1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10BlendState)
+ || riid == __uuidof(ID3D10BlendState1)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11BlendState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11BlendState::GetDesc(D3D11_BLEND_DESC* pDesc) {
+ pDesc->AlphaToCoverageEnable = m_desc.AlphaToCoverageEnable;
+ pDesc->IndependentBlendEnable = m_desc.IndependentBlendEnable;
+
+ for (uint32_t i = 0; i < 8; i++) {
+ pDesc->RenderTarget[i].BlendEnable = m_desc.RenderTarget[i].BlendEnable;
+ pDesc->RenderTarget[i].SrcBlend = m_desc.RenderTarget[i].SrcBlend;
+ pDesc->RenderTarget[i].DestBlend = m_desc.RenderTarget[i].DestBlend;
+ pDesc->RenderTarget[i].BlendOp = m_desc.RenderTarget[i].BlendOp;
+ pDesc->RenderTarget[i].SrcBlendAlpha = m_desc.RenderTarget[i].SrcBlendAlpha;
+ pDesc->RenderTarget[i].DestBlendAlpha = m_desc.RenderTarget[i].DestBlendAlpha;
+ pDesc->RenderTarget[i].BlendOpAlpha = m_desc.RenderTarget[i].BlendOpAlpha;
+ pDesc->RenderTarget[i].RenderTargetWriteMask = m_desc.RenderTarget[i].RenderTargetWriteMask;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11BlendState::GetDesc1(D3D11_BLEND_DESC1* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ void D3D11BlendState::BindToContext(
+ const Rc<DxvkContext>& ctx,
+ uint32_t sampleMask) const {
+ // We handled Independent Blend during object creation
+ // already, so if it is disabled, all elements in the
+ // blend mode array will be identical
+ for (uint32_t i = 0; i < m_blendModes.size(); i++)
+ ctx->setBlendMode(i, m_blendModes.at(i));
+
+ // The sample mask is dynamic state in D3D11
+ DxvkMultisampleState msState = m_msState;
+ msState.sampleMask = sampleMask;
+ ctx->setMultisampleState(msState);
+
+ // Set up logic op state as well
+ ctx->setLogicOpState(m_loState);
+ }
+
+
+ D3D11_BLEND_DESC1 D3D11BlendState::PromoteDesc(const D3D11_BLEND_DESC* pSrcDesc) {
+ D3D11_BLEND_DESC1 dstDesc;
+ dstDesc.AlphaToCoverageEnable = pSrcDesc->AlphaToCoverageEnable;
+ dstDesc.IndependentBlendEnable = pSrcDesc->IndependentBlendEnable;
+
+ for (uint32_t i = 0; i < 8; i++) {
+ dstDesc.RenderTarget[i].BlendEnable = pSrcDesc->RenderTarget[i].BlendEnable;
+ dstDesc.RenderTarget[i].LogicOpEnable = FALSE;
+ dstDesc.RenderTarget[i].SrcBlend = pSrcDesc->RenderTarget[i].SrcBlend;
+ dstDesc.RenderTarget[i].DestBlend = pSrcDesc->RenderTarget[i].DestBlend;
+ dstDesc.RenderTarget[i].BlendOp = pSrcDesc->RenderTarget[i].BlendOp;
+ dstDesc.RenderTarget[i].SrcBlendAlpha = pSrcDesc->RenderTarget[i].SrcBlendAlpha;
+ dstDesc.RenderTarget[i].DestBlendAlpha = pSrcDesc->RenderTarget[i].DestBlendAlpha;
+ dstDesc.RenderTarget[i].BlendOpAlpha = pSrcDesc->RenderTarget[i].BlendOpAlpha;
+ dstDesc.RenderTarget[i].LogicOp = D3D11_LOGIC_OP_NOOP;
+ dstDesc.RenderTarget[i].RenderTargetWriteMask = pSrcDesc->RenderTarget[i].RenderTargetWriteMask;
+ }
+
+ return dstDesc;
+ }
+
+
+ HRESULT D3D11BlendState::NormalizeDesc(D3D11_BLEND_DESC1* pDesc) {
+ if (pDesc->AlphaToCoverageEnable)
+ pDesc->AlphaToCoverageEnable = TRUE;
+
+ if (pDesc->IndependentBlendEnable)
+ pDesc->IndependentBlendEnable = TRUE;
+
+ const uint32_t numRenderTargets = pDesc->IndependentBlendEnable ? 8 : 1;
+
+ for (uint32_t i = 0; i < numRenderTargets; i++) {
+ D3D11_RENDER_TARGET_BLEND_DESC1* rt = &pDesc->RenderTarget[i];
+
+ if (rt->BlendEnable) {
+ rt->BlendEnable = TRUE;
+
+ if (rt->LogicOpEnable)
+ return E_INVALIDARG;
+
+ if (!ValidateBlendOperations(
+ rt->SrcBlend, rt->SrcBlendAlpha,
+ rt->DestBlend, rt->DestBlendAlpha,
+ rt->BlendOp, rt->BlendOpAlpha))
+ return E_INVALIDARG;
+ } else {
+ rt->SrcBlend = D3D11_BLEND_ONE;
+ rt->DestBlend = D3D11_BLEND_ZERO;
+ rt->BlendOp = D3D11_BLEND_OP_ADD;
+ rt->SrcBlendAlpha = D3D11_BLEND_ONE;
+ rt->DestBlendAlpha = D3D11_BLEND_ZERO;
+ rt->BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ }
+
+ if (rt->LogicOpEnable) {
+ rt->LogicOpEnable = TRUE;
+
+ // Blending must be disabled
+ // if the logic op is enabled
+ if (rt->BlendEnable
+ || pDesc->IndependentBlendEnable
+ || !ValidateLogicOp(rt->LogicOp))
+ return E_INVALIDARG;
+ } else {
+ rt->LogicOp = D3D11_LOGIC_OP_NOOP;
+ }
+
+ if (rt->RenderTargetWriteMask > D3D11_COLOR_WRITE_ENABLE_ALL)
+ return E_INVALIDARG;
+ }
+
+ for (uint32_t i = numRenderTargets; i < 8; i++) {
+ // Render targets blend operations are the same
+ // across all render targets when blend is enabled
+ // on rendertarget[0] with independent blend disabled
+ pDesc->RenderTarget[i] = pDesc->RenderTarget[0];
+ }
+
+ return S_OK;
+ }
+
+
+ DxvkBlendMode D3D11BlendState::DecodeBlendMode(
+ const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc) {
+ DxvkBlendMode mode;
+ mode.enableBlending = BlendDesc.BlendEnable;
+ mode.colorSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlend, false);
+ mode.colorDstFactor = DecodeBlendFactor(BlendDesc.DestBlend, false);
+ mode.colorBlendOp = DecodeBlendOp(BlendDesc.BlendOp);
+ mode.alphaSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true);
+ mode.alphaDstFactor = DecodeBlendFactor(BlendDesc.DestBlendAlpha, true);
+ mode.alphaBlendOp = DecodeBlendOp(BlendDesc.BlendOpAlpha);
+ mode.writeMask = BlendDesc.RenderTargetWriteMask;
+ return mode;
+ }
+
+
+ VkBlendFactor D3D11BlendState::DecodeBlendFactor(D3D11_BLEND BlendFactor, bool IsAlpha) {
+ switch (BlendFactor) {
+ case D3D11_BLEND_ZERO: return VK_BLEND_FACTOR_ZERO;
+ case D3D11_BLEND_ONE: return VK_BLEND_FACTOR_ONE;
+ case D3D11_BLEND_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
+ case D3D11_BLEND_INV_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ case D3D11_BLEND_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
+ case D3D11_BLEND_INV_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ case D3D11_BLEND_DEST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
+ case D3D11_BLEND_INV_DEST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
+ case D3D11_BLEND_DEST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
+ case D3D11_BLEND_INV_DEST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
+ case D3D11_BLEND_SRC_ALPHA_SAT: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
+ case D3D11_BLEND_BLEND_FACTOR: return IsAlpha ? VK_BLEND_FACTOR_CONSTANT_ALPHA : VK_BLEND_FACTOR_CONSTANT_COLOR;
+ case D3D11_BLEND_INV_BLEND_FACTOR: return IsAlpha ? VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA : VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
+ case D3D11_BLEND_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;
+ case D3D11_BLEND_INV_SRC1_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
+ case D3D11_BLEND_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
+ case D3D11_BLEND_INV_SRC1_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+ default: return VK_BLEND_FACTOR_ZERO;
+ }
+ }
+
+
+ VkBlendOp D3D11BlendState::DecodeBlendOp(D3D11_BLEND_OP BlendOp) {
+ switch (BlendOp) {
+ case D3D11_BLEND_OP_ADD: return VK_BLEND_OP_ADD;
+ case D3D11_BLEND_OP_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
+ case D3D11_BLEND_OP_REV_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
+ case D3D11_BLEND_OP_MIN: return VK_BLEND_OP_MIN;
+ case D3D11_BLEND_OP_MAX: return VK_BLEND_OP_MAX;
+ default: return VK_BLEND_OP_ADD;
+ }
+ }
+
+
+ VkLogicOp D3D11BlendState::DecodeLogicOp(D3D11_LOGIC_OP LogicOp) {
+ switch (LogicOp) {
+ case D3D11_LOGIC_OP_CLEAR: return VK_LOGIC_OP_CLEAR;
+ case D3D11_LOGIC_OP_SET: return VK_LOGIC_OP_SET;
+ case D3D11_LOGIC_OP_COPY: return VK_LOGIC_OP_COPY;
+ case D3D11_LOGIC_OP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
+ case D3D11_LOGIC_OP_NOOP: return VK_LOGIC_OP_NO_OP;
+ case D3D11_LOGIC_OP_INVERT: return VK_LOGIC_OP_INVERT;
+ case D3D11_LOGIC_OP_AND: return VK_LOGIC_OP_AND;
+ case D3D11_LOGIC_OP_NAND: return VK_LOGIC_OP_NAND;
+ case D3D11_LOGIC_OP_OR: return VK_LOGIC_OP_OR;
+ case D3D11_LOGIC_OP_NOR: return VK_LOGIC_OP_NOR;
+ case D3D11_LOGIC_OP_XOR: return VK_LOGIC_OP_XOR;
+ case D3D11_LOGIC_OP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
+ case D3D11_LOGIC_OP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
+ case D3D11_LOGIC_OP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
+ case D3D11_LOGIC_OP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
+ case D3D11_LOGIC_OP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
+ default: return VK_LOGIC_OP_NO_OP;
+ }
+ }
+
+
+ bool D3D11BlendState::ValidateBlendFactor(D3D11_BLEND Blend) {
+ return Blend >= D3D11_BLEND_ZERO
+ && Blend <= D3D11_BLEND_INV_SRC1_ALPHA;
+ }
+
+
+ bool D3D11BlendState::ValidateBlendFactorAlpha(D3D11_BLEND BlendAlpha) {
+ return BlendAlpha >= D3D11_BLEND_ZERO
+ && BlendAlpha <= D3D11_BLEND_INV_SRC1_ALPHA
+ && BlendAlpha != D3D11_BLEND_SRC_COLOR
+ && BlendAlpha != D3D11_BLEND_INV_SRC_COLOR
+ && BlendAlpha != D3D11_BLEND_DEST_COLOR
+ && BlendAlpha != D3D11_BLEND_INV_DEST_COLOR
+ && BlendAlpha != D3D11_BLEND_SRC1_COLOR
+ && BlendAlpha != D3D11_BLEND_INV_SRC1_COLOR;
+ }
+
+
+ bool D3D11BlendState::ValidateBlendOp(D3D11_BLEND_OP BlendOp) {
+ return BlendOp >= D3D11_BLEND_OP_ADD
+ && BlendOp <= D3D11_BLEND_OP_MAX;
+ }
+
+
+ bool D3D11BlendState::ValidateLogicOp(D3D11_LOGIC_OP LogicOp) {
+ return LogicOp >= D3D11_LOGIC_OP_CLEAR
+ && LogicOp <= D3D11_LOGIC_OP_OR_INVERTED;
+ }
+
+
+ bool D3D11BlendState::ValidateBlendOperations(
+ D3D11_BLEND SrcBlend,
+ D3D11_BLEND SrcBlendAlpha,
+ D3D11_BLEND DestBlend,
+ D3D11_BLEND DestBlendAlpha,
+ D3D11_BLEND_OP BlendOp,
+ D3D11_BLEND_OP BlendOpAlpha) {
+ return ValidateBlendOp(BlendOp)
+ && ValidateBlendOp(BlendOpAlpha)
+ && ValidateBlendFactor(SrcBlend)
+ && ValidateBlendFactor(DestBlend)
+ && ValidateBlendFactorAlpha(SrcBlendAlpha)
+ && ValidateBlendFactorAlpha(DestBlendAlpha);
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.h
new file mode 100644
index 00000000..5761d3ca
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_blend.h
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_blend.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_util.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11BlendState : public D3D11StateObject<ID3D11BlendState1> {
+
+ public:
+
+ using DescType = D3D11_BLEND_DESC1;
+
+ D3D11BlendState(
+ D3D11Device* device,
+ const D3D11_BLEND_DESC1& desc);
+ ~D3D11BlendState();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_BLEND_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(
+ D3D11_BLEND_DESC1* pDesc) final;
+
+ void BindToContext(
+ const Rc<DxvkContext>& ctx,
+ UINT sampleMask) const;
+
+ D3D10BlendState* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static D3D11_BLEND_DESC1 PromoteDesc(
+ const D3D11_BLEND_DESC* pSrcDesc);
+
+ static HRESULT NormalizeDesc(
+ D3D11_BLEND_DESC1* pDesc);
+
+ private:
+
+ D3D11_BLEND_DESC1 m_desc;
+
+ std::array<DxvkBlendMode, 8> m_blendModes;
+ DxvkMultisampleState m_msState;
+ DxvkLogicOpState m_loState;
+
+ D3D10BlendState m_d3d10;
+
+ static DxvkBlendMode DecodeBlendMode(
+ const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc);
+
+ static VkBlendFactor DecodeBlendFactor(
+ D3D11_BLEND BlendFactor,
+ bool IsAlpha);
+
+ static VkBlendOp DecodeBlendOp(
+ D3D11_BLEND_OP BlendOp);
+
+ static VkLogicOp DecodeLogicOp(
+ D3D11_LOGIC_OP LogicOp);
+
+ static bool ValidateBlendFactor(
+ D3D11_BLEND Blend);
+
+ static bool ValidateBlendFactorAlpha(
+ D3D11_BLEND BlendAlpha);
+
+ static bool ValidateBlendOp(
+ D3D11_BLEND_OP BlendOp);
+
+ static bool ValidateLogicOp(
+ D3D11_LOGIC_OP LogicOp);
+
+ static bool ValidateBlendOperations(
+ D3D11_BLEND SrcBlend,
+ D3D11_BLEND SrcBlendAlpha,
+ D3D11_BLEND SestBlend,
+ D3D11_BLEND DestBlendAlpha,
+ D3D11_BLEND_OP BlendOp,
+ D3D11_BLEND_OP BlendOpAlpha);
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.cpp
new file mode 100644
index 00000000..687be0a5
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.cpp
@@ -0,0 +1,287 @@
+#include "d3d11_buffer.h"
+#include "d3d11_context.h"
+#include "d3d11_device.h"
+
+#include "../dxvk/dxvk_data.h"
+
+namespace dxvk {
+
+ D3D11Buffer::D3D11Buffer(
+ D3D11Device* pDevice,
+ const D3D11_BUFFER_DESC* pDesc)
+ : D3D11DeviceChild<ID3D11Buffer>(pDevice),
+ m_desc (*pDesc),
+ m_resource (this),
+ m_d3d10 (this) {
+ DxvkBufferCreateInfo info;
+ info.size = pDesc->ByteWidth;
+ info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ info.access = VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_TRANSFER_WRITE_BIT;
+
+ if (pDesc->BindFlags & D3D11_BIND_VERTEX_BUFFER) {
+ info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+ }
+
+ if (pDesc->BindFlags & D3D11_BIND_INDEX_BUFFER) {
+ info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+ info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ info.access |= VK_ACCESS_INDEX_READ_BIT;
+ }
+
+ if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
+ info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ info.stages |= m_parent->GetEnabledShaderStages();
+ info.access |= VK_ACCESS_UNIFORM_READ_BIT;
+
+ if (m_parent->GetOptions()->constantBufferRangeCheck)
+ info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ }
+
+ if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) {
+ info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
+ | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ info.stages |= m_parent->GetEnabledShaderStages();
+ info.access |= VK_ACCESS_SHADER_READ_BIT;
+ }
+
+ if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) {
+ info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
+ info.stages |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
+ info.access |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
+ }
+
+ if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
+ info.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
+ | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ info.stages |= m_parent->GetEnabledShaderStages();
+ info.access |= VK_ACCESS_SHADER_READ_BIT
+ | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+
+ if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) {
+ info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
+ info.stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ info.access |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ }
+
+ // Create the buffer and set the entire buffer slice as mapped,
+ // so that we only have to update it when invalidating th buffer
+ m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, GetMemoryFlags());
+ m_mapped = m_buffer->getSliceHandle();
+
+ // For Stream Output buffers we need a counter
+ if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT)
+ m_soCounter = CreateSoCounterBuffer();
+ }
+
+
+ D3D11Buffer::~D3D11Buffer() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11Resource)
+ || riid == __uuidof(ID3D11Buffer)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10Resource)
+ || riid == __uuidof(ID3D10Buffer)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIObject)
+ || riid == __uuidof(IDXGIDeviceSubObject)
+ || riid == __uuidof(IDXGIResource)
+ || riid == __uuidof(IDXGIResource1)) {
+ *ppvObject = ref(&m_resource);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() {
+ return DXGI_RESOURCE_PRIORITY_NORMAL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11Buffer::SetEvictionPriority: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) {
+ *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ bool D3D11Buffer::CheckViewCompatibility(
+ UINT BindFlags,
+ DXGI_FORMAT Format) const {
+ // Check whether the given bind flags are supported
+ if ((m_desc.BindFlags & BindFlags) != BindFlags)
+ return false;
+
+ // Structured buffer views use no format
+ if (Format == DXGI_FORMAT_UNKNOWN)
+ return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0;
+
+ // Check whether the given combination of buffer view
+ // type and view format is supported by the device
+ DXGI_VK_FORMAT_INFO viewFormat = m_parent->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY);
+ VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags);
+
+ return CheckFormatFeatureSupport(viewFormat.Format, features);
+ }
+
+
+ HRESULT D3D11Buffer::NormalizeBufferProperties(D3D11_BUFFER_DESC* pDesc) {
+ // Zero-sized buffers are illegal
+ if (!pDesc->ByteWidth)
+ return E_INVALIDARG;
+
+ // We don't support tiled resources
+ if (pDesc->MiscFlags & (D3D11_RESOURCE_MISC_TILE_POOL | D3D11_RESOURCE_MISC_TILED))
+ return E_INVALIDARG;
+
+ // Constant buffer size must be a multiple of 16
+ if ((pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER)
+ && (pDesc->ByteWidth & 0xF))
+ return E_INVALIDARG;
+
+ // Basic validation for structured buffers
+ if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
+ && ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
+ || (pDesc->StructureByteStride == 0)
+ || (pDesc->StructureByteStride & 0x3)))
+ return E_INVALIDARG;
+
+ // Basic validation for raw buffers
+ if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
+ && (!(pDesc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS))))
+ return E_INVALIDARG;
+
+ // Mip generation obviously doesn't work for buffers
+ if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)
+ return E_INVALIDARG;
+
+ if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED))
+ pDesc->StructureByteStride = 0;
+
+ return S_OK;
+ }
+
+
+ BOOL D3D11Buffer::CheckFormatFeatureSupport(
+ VkFormat Format,
+ VkFormatFeatureFlags Features) const {
+ VkFormatProperties properties = m_parent->GetDXVKDevice()->adapter()->formatProperties(Format);
+ return (properties.bufferFeatures & Features) == Features;
+ }
+
+
+ VkMemoryPropertyFlags D3D11Buffer::GetMemoryFlags() const {
+ VkMemoryPropertyFlags memoryFlags = 0;
+
+ switch (m_desc.Usage) {
+ case D3D11_USAGE_IMMUTABLE:
+ memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+
+ case D3D11_USAGE_DEFAULT:
+ memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+ if ((m_desc.BindFlags & D3D11_BIND_CONSTANT_BUFFER) || m_desc.CPUAccessFlags) {
+ memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ }
+
+ if (m_desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) {
+ memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+
+ case D3D11_USAGE_DYNAMIC:
+ memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+ if (m_desc.BindFlags)
+ memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+
+ case D3D11_USAGE_STAGING:
+ memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ break;
+ }
+
+ if (memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT && m_parent->GetOptions()->apitraceMode) {
+ memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ }
+
+ return memoryFlags;
+ }
+
+
+ Rc<DxvkBuffer> D3D11Buffer::CreateSoCounterBuffer() {
+ Rc<DxvkDevice> device = m_parent->GetDXVKDevice();
+
+ DxvkBufferCreateInfo info;
+ info.size = sizeof(D3D11SOCounter);
+ info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
+ | VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
+ | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
+ | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
+ | VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
+ info.access = VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_TRANSFER_WRITE_BIT
+ | VK_ACCESS_INDIRECT_COMMAND_READ_BIT
+ | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
+ | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
+ return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ }
+
+
+ D3D11Buffer* GetCommonBuffer(ID3D11Resource* pResource) {
+ D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&dimension);
+
+ return dimension == D3D11_RESOURCE_DIMENSION_BUFFER
+ ? static_cast<D3D11Buffer*>(pResource)
+ : nullptr;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.h
new file mode 100644
index 00000000..3ddd61a0
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_buffer.h
@@ -0,0 +1,162 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_buffer.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_interfaces.h"
+#include "d3d11_resource.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+ class D3D11DeviceContext;
+
+
+ /**
+ * \brief Buffer map mode
+ */
+ enum D3D11_COMMON_BUFFER_MAP_MODE {
+ D3D11_COMMON_BUFFER_MAP_MODE_NONE,
+ D3D11_COMMON_BUFFER_MAP_MODE_DIRECT,
+ };
+
+
+ /**
+ * \brief Stream output buffer offset
+ *
+ * A byte offset into the buffer that
+ * stores the byte offset where new
+ * data will be written to.
+ */
+ struct D3D11SOCounter {
+ uint32_t byteOffset;
+ };
+
+
+ class D3D11Buffer : public D3D11DeviceChild<ID3D11Buffer> {
+ static constexpr VkDeviceSize BufferSliceAlignment = 64;
+ public:
+
+ D3D11Buffer(
+ D3D11Device* pDevice,
+ const D3D11_BUFFER_DESC* pDesc);
+ ~D3D11Buffer();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetType(
+ D3D11_RESOURCE_DIMENSION *pResourceDimension) final;
+
+ UINT STDMETHODCALLTYPE GetEvictionPriority() final;
+
+ void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_BUFFER_DESC *pDesc) final;
+
+ bool CheckViewCompatibility(
+ UINT BindFlags,
+ DXGI_FORMAT Format) const;
+
+ const D3D11_BUFFER_DESC* Desc() const {
+ return &m_desc;
+ }
+
+ D3D11_COMMON_BUFFER_MAP_MODE GetMapMode() const {
+ return (m_buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ ? D3D11_COMMON_BUFFER_MAP_MODE_DIRECT
+ : D3D11_COMMON_BUFFER_MAP_MODE_NONE;
+ }
+
+ Rc<DxvkBuffer> GetBuffer() const {
+ return m_buffer;
+ }
+
+ DxvkBufferSlice GetBufferSlice() const {
+ return DxvkBufferSlice(m_buffer, 0, m_desc.ByteWidth);
+ }
+
+ DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const {
+ VkDeviceSize size = m_desc.ByteWidth;
+
+ return likely(offset < size)
+ ? DxvkBufferSlice(m_buffer, offset, size - offset)
+ : DxvkBufferSlice();
+ }
+
+ DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
+ VkDeviceSize size = m_desc.ByteWidth;
+
+ return likely(offset < size)
+ ? DxvkBufferSlice(m_buffer, offset, std::min(length, size - offset))
+ : DxvkBufferSlice();
+ }
+
+ DxvkBufferSlice GetSOCounter() {
+ return m_soCounter != nullptr
+ ? DxvkBufferSlice(m_soCounter)
+ : DxvkBufferSlice();
+ }
+
+ DxvkBufferSliceHandle AllocSlice() {
+ return m_buffer->allocSlice();
+ }
+
+ DxvkBufferSliceHandle DiscardSlice() {
+ m_mapped = m_buffer->allocSlice();
+ return m_mapped;
+ }
+
+ DxvkBufferSliceHandle GetMappedSlice() const {
+ return m_mapped;
+ }
+
+ D3D10Buffer* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ /**
+ * \brief Normalizes buffer description
+ *
+ * \param [in] pDesc Buffer description
+ * \returns \c S_OK if the parameters are valid
+ */
+ static HRESULT NormalizeBufferProperties(
+ D3D11_BUFFER_DESC* pDesc);
+
+ private:
+
+ const D3D11_BUFFER_DESC m_desc;
+
+ Rc<DxvkBuffer> m_buffer;
+ Rc<DxvkBuffer> m_soCounter;
+ DxvkBufferSliceHandle m_mapped;
+
+ D3D11DXGIResource m_resource;
+ D3D10Buffer m_d3d10;
+
+ BOOL CheckFormatFeatureSupport(
+ VkFormat Format,
+ VkFormatFeatureFlags Features) const;
+
+ VkMemoryPropertyFlags GetMemoryFlags() const;
+
+ Rc<DxvkBuffer> CreateSoCounterBuffer();
+
+ };
+
+
+ /**
+ * \brief Retrieves buffer from resource pointer
+ *
+ * \param [in] pResource The resource to query
+ * \returns Pointer to buffer, or \c nullptr
+ */
+ D3D11Buffer* GetCommonBuffer(
+ ID3D11Resource* pResource);
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.cpp
new file mode 100644
index 00000000..8070b660
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.cpp
@@ -0,0 +1,59 @@
+#include "d3d11_class_linkage.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11ClassLinkage::D3D11ClassLinkage(
+ D3D11Device* pDevice)
+ : D3D11DeviceChild<ID3D11ClassLinkage>(pDevice) {
+
+ }
+
+
+ D3D11ClassLinkage::~D3D11ClassLinkage() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11ClassLinkage)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11ClassLinkage::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::CreateClassInstance(
+ LPCSTR pClassTypeName,
+ UINT ConstantBufferOffset,
+ UINT ConstantVectorOffset,
+ UINT TextureOffset,
+ UINT SamplerOffset,
+ ID3D11ClassInstance **ppInstance) {
+ InitReturnPtr(ppInstance);
+
+ Logger::err("D3D11ClassLinkage::CreateClassInstance: Not implemented yet");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::GetClassInstance(
+ LPCSTR pClassInstanceName,
+ UINT InstanceIndex,
+ ID3D11ClassInstance **ppInstance) {
+ Logger::err("D3D11ClassLinkage::GetClassInstance: Not implemented yet");
+ return E_NOTIMPL;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.h
new file mode 100644
index 00000000..7d1c324c
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_class_linkage.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "d3d11_device_child.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ // TODO implement properly
+ class D3D11ClassLinkage : public D3D11DeviceChild<ID3D11ClassLinkage> {
+
+ public:
+
+ D3D11ClassLinkage(
+ D3D11Device* pDevice);
+
+ ~D3D11ClassLinkage();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ HRESULT STDMETHODCALLTYPE CreateClassInstance(
+ LPCSTR pClassTypeName,
+ UINT ConstantBufferOffset,
+ UINT ConstantVectorOffset,
+ UINT TextureOffset,
+ UINT SamplerOffset,
+ ID3D11ClassInstance **ppInstance);
+
+ HRESULT STDMETHODCALLTYPE GetClassInstance(
+ LPCSTR pClassInstanceName,
+ UINT InstanceIndex,
+ ID3D11ClassInstance **ppInstance);
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmd.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmd.h
new file mode 100644
index 00000000..52f2f4db
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmd.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ /**
+ * \brief D3D11 command type
+ *
+ * Used to identify the type of command
+ * data most recently added to a CS chunk.
+ */
+ enum class D3D11CmdType {
+ DrawIndirect,
+ DrawIndirectIndexed,
+ };
+
+
+ /**
+ * \brief Command data header
+ *
+ * Stores the command type. All command
+ * data structs must inherit this struct.
+ */
+ struct D3D11CmdData {
+ D3D11CmdType type;
+ };
+
+
+ /**
+ * \brief Indirect draw command data
+ *
+ * Stores the offset into the draw buffer for
+ * the first draw, as well as the number of
+ * draws to execute.
+ */
+ struct D3D11CmdDrawIndirectData : public D3D11CmdData {
+ uint32_t offset;
+ uint32_t count;
+ uint32_t stride;
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.cpp
new file mode 100644
index 00000000..0ce56211
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.cpp
@@ -0,0 +1,85 @@
+#include "d3d11_cmdlist.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11CommandList::D3D11CommandList(
+ D3D11Device* pDevice,
+ UINT ContextFlags)
+ : D3D11DeviceChild<ID3D11CommandList>(pDevice),
+ m_contextFlags(ContextFlags) { }
+
+
+ D3D11CommandList::~D3D11CommandList() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11CommandList::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11CommandList)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11CommandList::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11CommandList::GetContextFlags() {
+ return m_contextFlags;
+ }
+
+
+ void D3D11CommandList::AddChunk(DxvkCsChunkRef&& Chunk) {
+ m_chunks.push_back(std::move(Chunk));
+ }
+
+
+ void D3D11CommandList::AddQuery(D3D11Query* pQuery) {
+ m_queries.emplace_back(pQuery);
+ }
+
+
+ void D3D11CommandList::EmitToCommandList(ID3D11CommandList* pCommandList) {
+ auto cmdList = static_cast<D3D11CommandList*>(pCommandList);
+
+ for (const auto& chunk : m_chunks)
+ cmdList->m_chunks.push_back(chunk);
+
+ for (const auto& query : m_queries)
+ cmdList->m_queries.push_back(query);
+
+ MarkSubmitted();
+ }
+
+
+ void D3D11CommandList::EmitToCsThread(DxvkCsThread* CsThread) {
+ for (const auto& query : m_queries)
+ query->DoDeferredEnd();
+
+ for (const auto& chunk : m_chunks)
+ CsThread->dispatchChunk(DxvkCsChunkRef(chunk));
+
+ MarkSubmitted();
+ }
+
+
+ void D3D11CommandList::MarkSubmitted() {
+ if (m_submitted.exchange(true) && !m_warned.exchange(true)
+ && m_parent->GetOptions()->dcSingleUseMode) {
+ Logger::warn(
+ "D3D11: Command list submitted multiple times,\n"
+ " but d3d11.dcSingleUseMode is enabled");
+ }
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.h
new file mode 100644
index 00000000..ce207aaf
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cmdlist.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "d3d11_context.h"
+
+namespace dxvk {
+
+ class D3D11CommandList : public D3D11DeviceChild<ID3D11CommandList> {
+
+ public:
+
+ D3D11CommandList(
+ D3D11Device* pDevice,
+ UINT ContextFlags);
+
+ ~D3D11CommandList();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ UINT STDMETHODCALLTYPE GetContextFlags() final;
+
+ void AddChunk(
+ DxvkCsChunkRef&& Chunk);
+
+ void AddQuery(
+ D3D11Query* pQuery);
+
+ void EmitToCommandList(
+ ID3D11CommandList* pCommandList);
+
+ void EmitToCsThread(
+ DxvkCsThread* CsThread);
+
+ private:
+
+ UINT const m_contextFlags;
+
+ std::vector<DxvkCsChunkRef> m_chunks;
+ std::vector<Com<D3D11Query, false>> m_queries;
+
+ std::atomic<bool> m_submitted = { false };
+ std::atomic<bool> m_warned = { false };
+
+ void MarkSubmitted();
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.cpp
new file mode 100644
index 00000000..45af2f7b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.cpp
@@ -0,0 +1,4507 @@
+#include <cstring>
+
+#include "d3d11_context.h"
+#include "d3d11_device.h"
+#include "d3d11_query.h"
+#include "d3d11_texture.h"
+#include "d3d11_video.h"
+
+#include "../dxbc/dxbc_util.h"
+
+namespace dxvk {
+
+ D3D11DeviceContext::D3D11DeviceContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device,
+ DxvkCsChunkFlags CsFlags)
+ : D3D11DeviceChild<ID3D11DeviceContext4>(pParent),
+ m_contextExt(this),
+ m_annotation(this),
+ m_multithread(this, false),
+ m_device (Device),
+ m_csFlags (CsFlags),
+ m_csChunk (AllocCsChunk()),
+ m_cmdData (nullptr) {
+
+ }
+
+
+ D3D11DeviceContext::~D3D11DeviceContext() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContext::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11DeviceContext)
+ || riid == __uuidof(ID3D11DeviceContext1)
+ || riid == __uuidof(ID3D11DeviceContext2)
+ || riid == __uuidof(ID3D11DeviceContext3)
+ || riid == __uuidof(ID3D11DeviceContext4)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D11VkExtContext)
+ || riid == __uuidof(ID3D11VkExtContext1)) {
+ *ppvObject = ref(&m_contextExt);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3DUserDefinedAnnotation)) {
+ *ppvObject = ref(&m_annotation);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10Multithread)) {
+ *ppvObject = ref(&m_multithread);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DiscardResource(ID3D11Resource* pResource) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (!pResource)
+ return;
+
+ // We don't support the Discard API for images
+ D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resType);
+
+ if (resType == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ DiscardBuffer(pResource);
+ } else {
+ auto texture = GetCommonTexture(pResource);
+
+ for (uint32_t i = 0; i < texture->CountSubresources(); i++)
+ DiscardTexture(pResource, i);
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView(ID3D11View* pResourceView) {
+ DiscardView1(pResourceView, nullptr, 0);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView1(
+ ID3D11View* pResourceView,
+ const D3D11_RECT* pRects,
+ UINT NumRects) {
+ D3D10DeviceLock lock = LockContext();
+
+ // We don't support discarding individual rectangles
+ if (!pResourceView || (NumRects && pRects))
+ return;
+
+ // ID3D11View has no methods to query the exact type of
+ // the view, so we'll have to check each possible class
+ auto dsv = dynamic_cast<D3D11DepthStencilView*>(pResourceView);
+ auto rtv = dynamic_cast<D3D11RenderTargetView*>(pResourceView);
+ auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pResourceView);
+
+ Rc<DxvkImageView> view;
+ if (dsv) view = dsv->GetImageView();
+ if (rtv) view = rtv->GetImageView();
+ if (uav) view = uav->GetImageView();
+
+ if (view == nullptr)
+ return;
+
+ // Get information about underlying resource
+ Com<ID3D11Resource> resource;
+ pResourceView->GetResource(&resource);
+
+ uint32_t mipCount = GetCommonTexture(resource.ptr())->Desc()->MipLevels;
+
+ // Discard mip levels one by one
+ VkImageSubresourceRange sr = view->subresources();
+
+ for (uint32_t layer = 0; layer < sr.layerCount; layer++) {
+ for (uint32_t mip = 0; mip < sr.levelCount; mip++) {
+ DiscardTexture(resource.ptr(), D3D11CalcSubresource(
+ sr.baseMipLevel + mip, sr.baseArrayLayer + layer, mipCount));
+ }
+ }
+
+ // Since we don't handle SRVs here, we can assume that the
+ // view covers all aspects of the underlying resource.
+ EmitCs([cView = view] (DxvkContext* ctx) {
+ ctx->discardImageView(cView, cView->formatInfo()->aspectMask);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearState() {
+ D3D10DeviceLock lock = LockContext();
+
+ // Default shaders
+ m_state.vs.shader = nullptr;
+ m_state.hs.shader = nullptr;
+ m_state.ds.shader = nullptr;
+ m_state.gs.shader = nullptr;
+ m_state.ps.shader = nullptr;
+ m_state.cs.shader = nullptr;
+
+ // Default constant buffers
+ for (uint32_t i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) {
+ m_state.vs.constantBuffers[i] = { nullptr, 0, 0 };
+ m_state.hs.constantBuffers[i] = { nullptr, 0, 0 };
+ m_state.ds.constantBuffers[i] = { nullptr, 0, 0 };
+ m_state.gs.constantBuffers[i] = { nullptr, 0, 0 };
+ m_state.ps.constantBuffers[i] = { nullptr, 0, 0 };
+ m_state.cs.constantBuffers[i] = { nullptr, 0, 0 };
+ }
+
+ // Default samplers
+ for (uint32_t i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) {
+ m_state.vs.samplers[i] = nullptr;
+ m_state.hs.samplers[i] = nullptr;
+ m_state.ds.samplers[i] = nullptr;
+ m_state.gs.samplers[i] = nullptr;
+ m_state.ps.samplers[i] = nullptr;
+ m_state.cs.samplers[i] = nullptr;
+ }
+
+ // Default shader resources
+ for (uint32_t i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) {
+ m_state.vs.shaderResources.views[i] = nullptr;
+ m_state.hs.shaderResources.views[i] = nullptr;
+ m_state.ds.shaderResources.views[i] = nullptr;
+ m_state.gs.shaderResources.views[i] = nullptr;
+ m_state.ps.shaderResources.views[i] = nullptr;
+ m_state.cs.shaderResources.views[i] = nullptr;
+ }
+
+ m_state.vs.shaderResources.hazardous.clear();
+ m_state.hs.shaderResources.hazardous.clear();
+ m_state.ds.shaderResources.hazardous.clear();
+ m_state.gs.shaderResources.hazardous.clear();
+ m_state.ps.shaderResources.hazardous.clear();
+ m_state.cs.shaderResources.hazardous.clear();
+
+ // Default UAVs
+ for (uint32_t i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++) {
+ m_state.ps.unorderedAccessViews[i] = nullptr;
+ m_state.cs.unorderedAccessViews[i] = nullptr;
+ }
+
+ m_state.cs.uavMask.clear();
+
+ // Default ID state
+ m_state.id.argBuffer = nullptr;
+
+ // Default IA state
+ m_state.ia.inputLayout = nullptr;
+ m_state.ia.primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
+
+ for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) {
+ m_state.ia.vertexBuffers[i].buffer = nullptr;
+ m_state.ia.vertexBuffers[i].offset = 0;
+ m_state.ia.vertexBuffers[i].stride = 0;
+ }
+
+ m_state.ia.indexBuffer.buffer = nullptr;
+ m_state.ia.indexBuffer.offset = 0;
+ m_state.ia.indexBuffer.format = DXGI_FORMAT_UNKNOWN;
+
+ // Default OM State
+ for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ m_state.om.renderTargetViews[i] = nullptr;
+ m_state.om.depthStencilView = nullptr;
+
+ m_state.om.cbState = nullptr;
+ m_state.om.dsState = nullptr;
+
+ for (uint32_t i = 0; i < 4; i++)
+ m_state.om.blendFactor[i] = 1.0f;
+
+ m_state.om.sampleMask = D3D11_DEFAULT_SAMPLE_MASK;
+ m_state.om.stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE;
+
+ m_state.om.maxRtv = 0;
+ m_state.om.maxUav = 0;
+
+ // Default RS state
+ m_state.rs.state = nullptr;
+ m_state.rs.numViewports = 0;
+ m_state.rs.numScissors = 0;
+
+ for (uint32_t i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++) {
+ m_state.rs.viewports[i] = D3D11_VIEWPORT { };
+ m_state.rs.scissors [i] = D3D11_RECT { };
+ }
+
+ // Default SO state
+ for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
+ m_state.so.targets[i].buffer = nullptr;
+ m_state.so.targets[i].offset = 0;
+ }
+
+ // Default predication
+ m_state.pr.predicateObject = nullptr;
+ m_state.pr.predicateValue = FALSE;
+
+ // Make sure to apply all state
+ ResetState();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SetPredication(
+ ID3D11Predicate* pPredicate,
+ BOOL PredicateValue) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto predicate = D3D11Query::FromPredicate(pPredicate);
+ m_state.pr.predicateObject = predicate;
+ m_state.pr.predicateValue = PredicateValue;
+
+ static bool s_errorShown = false;
+
+ if (pPredicate && !std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::SetPredication: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GetPredication(
+ ID3D11Predicate** ppPredicate,
+ BOOL* pPredicateValue) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppPredicate)
+ *ppPredicate = D3D11Query::AsPredicate(m_state.pr.predicateObject.ref());
+
+ if (pPredicateValue)
+ *pPredicateValue = m_state.pr.predicateValue;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ UINT DstX,
+ UINT DstY,
+ UINT DstZ,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox) {
+ CopySubresourceRegion1(
+ pDstResource, DstSubresource, DstX, DstY, DstZ,
+ pSrcResource, SrcSubresource, pSrcBox, 0);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ UINT DstX,
+ UINT DstY,
+ UINT DstZ,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox,
+ UINT CopyFlags) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (!pDstResource || !pSrcResource)
+ return;
+
+ if (pSrcBox
+ && (pSrcBox->left >= pSrcBox->right
+ || pSrcBox->top >= pSrcBox->bottom
+ || pSrcBox->front >= pSrcBox->back))
+ return;
+
+ D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+
+ pDstResource->GetType(&dstResourceDim);
+ pSrcResource->GetType(&srcResourceDim);
+
+ if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ auto dstBuffer = static_cast<D3D11Buffer*>(pDstResource);
+ auto srcBuffer = static_cast<D3D11Buffer*>(pSrcResource);
+
+ VkDeviceSize dstOffset = DstX;
+ VkDeviceSize srcOffset = 0;
+ VkDeviceSize byteCount = -1;
+
+ if (pSrcBox) {
+ srcOffset = pSrcBox->left;
+ byteCount = pSrcBox->right - pSrcBox->left;
+ }
+
+ CopyBuffer(dstBuffer, dstOffset, srcBuffer, srcOffset, byteCount);
+ } else if (dstResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) {
+ auto dstTexture = GetCommonTexture(pDstResource);
+ auto srcTexture = GetCommonTexture(pSrcResource);
+
+ if (DstSubresource >= dstTexture->CountSubresources()
+ || SrcSubresource >= srcTexture->CountSubresources())
+ return;
+
+ auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat());
+ auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat());
+
+ auto dstLayers = vk::makeSubresourceLayers(dstTexture->GetSubresourceFromIndex(dstFormatInfo->aspectMask, DstSubresource));
+ auto srcLayers = vk::makeSubresourceLayers(srcTexture->GetSubresourceFromIndex(srcFormatInfo->aspectMask, SrcSubresource));
+
+ VkOffset3D srcOffset = { 0, 0, 0 };
+ VkOffset3D dstOffset = { int32_t(DstX), int32_t(DstY), int32_t(DstZ) };
+
+ VkExtent3D srcExtent = srcTexture->MipLevelExtent(srcLayers.mipLevel);
+
+ if (pSrcBox != nullptr) {
+ srcOffset.x = pSrcBox->left;
+ srcOffset.y = pSrcBox->top;
+ srcOffset.z = pSrcBox->front;
+
+ srcExtent.width = pSrcBox->right - pSrcBox->left;
+ srcExtent.height = pSrcBox->bottom - pSrcBox->top;
+ srcExtent.depth = pSrcBox->back - pSrcBox->front;
+ }
+
+ CopyImage(
+ dstTexture, &dstLayers, dstOffset,
+ srcTexture, &srcLayers, srcOffset,
+ srcExtent);
+ } else {
+ Logger::err(str::format(
+ "D3D11: CopySubresourceRegion1: Incompatible resources",
+ "\n Dst resource type: ", dstResourceDim,
+ "\n Src resource type: ", srcResourceDim));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CopyResource(
+ ID3D11Resource* pDstResource,
+ ID3D11Resource* pSrcResource) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (!pDstResource || !pSrcResource || (pDstResource == pSrcResource))
+ return;
+
+ D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+
+ pDstResource->GetType(&dstResourceDim);
+ pSrcResource->GetType(&srcResourceDim);
+
+ if (dstResourceDim != srcResourceDim) {
+ Logger::err(str::format(
+ "D3D11: CopyResource: Incompatible resources",
+ "\n Dst resource type: ", dstResourceDim,
+ "\n Src resource type: ", srcResourceDim));
+ return;
+ }
+
+ if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ auto dstBuffer = static_cast<D3D11Buffer*>(pDstResource);
+ auto srcBuffer = static_cast<D3D11Buffer*>(pSrcResource);
+
+ if (dstBuffer->Desc()->ByteWidth != srcBuffer->Desc()->ByteWidth)
+ return;
+
+ CopyBuffer(dstBuffer, 0, srcBuffer, 0, -1);
+ } else {
+ auto dstTexture = GetCommonTexture(pDstResource);
+ auto srcTexture = GetCommonTexture(pSrcResource);
+
+ auto dstDesc = dstTexture->Desc();
+ auto srcDesc = srcTexture->Desc();
+
+ // The subresource count must match as well
+ if (dstDesc->ArraySize != srcDesc->ArraySize
+ || dstDesc->MipLevels != srcDesc->MipLevels) {
+ Logger::err("D3D11: CopyResource: Incompatible images");
+ return;
+ }
+
+ auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat());
+ auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat());
+
+ for (uint32_t i = 0; i < dstDesc->MipLevels; i++) {
+ VkImageSubresourceLayers dstLayers = { dstFormatInfo->aspectMask, i, 0, dstDesc->ArraySize };
+ VkImageSubresourceLayers srcLayers = { srcFormatInfo->aspectMask, i, 0, srcDesc->ArraySize };
+
+ CopyImage(
+ dstTexture, &dstLayers, VkOffset3D(),
+ srcTexture, &srcLayers, VkOffset3D(),
+ srcTexture->MipLevelExtent(i));
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CopyStructureCount(
+ ID3D11Buffer* pDstBuffer,
+ UINT DstAlignedByteOffset,
+ ID3D11UnorderedAccessView* pSrcView) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto buf = static_cast<D3D11Buffer*>(pDstBuffer);
+ auto uav = static_cast<D3D11UnorderedAccessView*>(pSrcView);
+
+ if (!buf || !uav)
+ return;
+
+ auto counterSlice = uav->GetCounterSlice();
+ if (!counterSlice.defined())
+ return;
+
+ EmitCs([
+ cDstSlice = buf->GetBufferSlice(DstAlignedByteOffset),
+ cSrcSlice = std::move(counterSlice)
+ ] (DxvkContext* ctx) {
+ ctx->copyBuffer(
+ cDstSlice.buffer(),
+ cDstSlice.offset(),
+ cSrcSlice.buffer(),
+ cSrcSlice.offset(),
+ sizeof(uint32_t));
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CopyTiles(
+ ID3D11Resource* pTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pTileRegionSize,
+ ID3D11Buffer* pBuffer,
+ UINT64 BufferStartOffsetInBytes,
+ UINT Flags) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::CopyTiles: Not implemented");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContext::CopyTileMappings(
+ ID3D11Resource* pDestTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pDestRegionStartCoordinate,
+ ID3D11Resource* pSourceTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pTileRegionSize,
+ UINT Flags) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::CopyTileMappings: Not implemented");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContext::ResizeTilePool(
+ ID3D11Buffer* pTilePool,
+ UINT64 NewSizeInBytes) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::ResizeTilePool: Not implemented");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::TiledResourceBarrier(
+ ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier,
+ ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier) {
+
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearRenderTargetView(
+ ID3D11RenderTargetView* pRenderTargetView,
+ const FLOAT ColorRGBA[4]) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
+
+ if (!rtv)
+ return;
+
+ auto view = rtv->GetImageView();
+ auto color = ConvertColorValue(ColorRGBA, view->formatInfo());
+
+ EmitCs([
+ cClearValue = color,
+ cImageView = std::move(view)
+ ] (DxvkContext* ctx) {
+ ctx->clearRenderTarget(
+ cImageView,
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ cClearValue);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewUint(
+ ID3D11UnorderedAccessView* pUnorderedAccessView,
+ const UINT Values[4]) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
+
+ if (!uav)
+ return;
+
+ // Gather UAV format info. We'll use this to determine
+ // whether we need to create a temporary view or not.
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uav->GetDesc(&uavDesc);
+
+ VkFormat uavFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_ANY).Format;
+ VkFormat rawFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_RAW).Format;
+
+ if (uavFormat != rawFormat && rawFormat == VK_FORMAT_UNDEFINED) {
+ Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat));
+ return;
+ }
+
+ // Set up clear color struct
+ VkClearValue clearValue;
+ clearValue.color.uint32[0] = Values[0];
+ clearValue.color.uint32[1] = Values[1];
+ clearValue.color.uint32[2] = Values[2];
+ clearValue.color.uint32[3] = Values[3];
+
+ // This is the only packed format that has UAV support
+ if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
+ clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
+ | ((Values[1] & 0x7FF) << 11)
+ | ((Values[2] & 0x3FF) << 22);
+ }
+
+ if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ // In case of raw and structured buffers as well as typed
+ // buffers that can be used for atomic operations, we can
+ // use the fast Vulkan buffer clear function.
+ Rc<DxvkBufferView> bufferView = uav->GetBufferView();
+
+ if (bufferView->info().format == VK_FORMAT_R32_UINT
+ || bufferView->info().format == VK_FORMAT_R32_SINT
+ || bufferView->info().format == VK_FORMAT_R32_SFLOAT) {
+ EmitCs([
+ cClearValue = Values[0],
+ cDstSlice = bufferView->slice()
+ ] (DxvkContext* ctx) {
+ ctx->clearBuffer(
+ cDstSlice.buffer(),
+ cDstSlice.offset(),
+ cDstSlice.length(),
+ cClearValue);
+ });
+ } else {
+ // Create a view with an integer format if necessary
+ if (uavFormat != rawFormat) {
+ DxvkBufferViewCreateInfo info = bufferView->info();
+ info.format = rawFormat;
+
+ bufferView = m_device->createBufferView(
+ bufferView->buffer(), info);
+ }
+
+ EmitCs([
+ cClearValue = clearValue,
+ cDstView = bufferView
+ ] (DxvkContext* ctx) {
+ ctx->clearBufferView(
+ cDstView, 0,
+ cDstView->elementCount(),
+ cClearValue.color);
+ });
+ }
+ } else {
+ // Create a view with an integer format if necessary
+ Rc<DxvkImageView> imageView = uav->GetImageView();
+
+ if (uavFormat != rawFormat) {
+ DxvkImageViewCreateInfo info = imageView->info();
+ info.format = rawFormat;
+
+ imageView = m_device->createImageView(
+ imageView->image(), info);
+ }
+
+ EmitCs([
+ cClearValue = clearValue,
+ cDstView = imageView
+ ] (DxvkContext* ctx) {
+ ctx->clearImageView(cDstView,
+ VkOffset3D { 0, 0, 0 },
+ cDstView->mipLevelExtent(0),
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ cClearValue);
+ });
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewFloat(
+ ID3D11UnorderedAccessView* pUnorderedAccessView,
+ const FLOAT Values[4]) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
+
+ if (!uav)
+ return;
+
+ auto imgView = uav->GetImageView();
+ auto bufView = uav->GetBufferView();
+
+ const DxvkFormatInfo* info = nullptr;
+ if (imgView != nullptr) info = imgView->formatInfo();
+ if (bufView != nullptr) info = bufView->formatInfo();
+
+ if (!info || info->flags.any(DxvkFormatFlag::SampledSInt, DxvkFormatFlag::SampledUInt))
+ return;
+
+ VkClearValue clearValue;
+ clearValue.color.float32[0] = Values[0];
+ clearValue.color.float32[1] = Values[1];
+ clearValue.color.float32[2] = Values[2];
+ clearValue.color.float32[3] = Values[3];
+
+ if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ EmitCs([
+ cClearValue = clearValue,
+ cDstView = std::move(bufView)
+ ] (DxvkContext* ctx) {
+ ctx->clearBufferView(
+ cDstView, 0,
+ cDstView->elementCount(),
+ cClearValue.color);
+ });
+ } else {
+ EmitCs([
+ cClearValue = clearValue,
+ cDstView = std::move(imgView)
+ ] (DxvkContext* ctx) {
+ ctx->clearImageView(cDstView,
+ VkOffset3D { 0, 0, 0 },
+ cDstView->mipLevelExtent(0),
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ cClearValue);
+ });
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearDepthStencilView(
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT ClearFlags,
+ FLOAT Depth,
+ UINT8 Stencil) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
+
+ if (!dsv)
+ return;
+
+ // Figure out which aspects to clear based on
+ // the image view properties and clear flags.
+ VkImageAspectFlags aspectMask = 0;
+
+ if (ClearFlags & D3D11_CLEAR_DEPTH)
+ aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ if (ClearFlags & D3D11_CLEAR_STENCIL)
+ aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ aspectMask &= dsv->GetWritableAspectMask();
+
+ if (!aspectMask)
+ return;
+
+ VkClearValue clearValue;
+ clearValue.depthStencil.depth = Depth;
+ clearValue.depthStencil.stencil = Stencil;
+
+ EmitCs([
+ cClearValue = clearValue,
+ cAspectMask = aspectMask,
+ cImageView = dsv->GetImageView()
+ ] (DxvkContext* ctx) {
+ ctx->clearRenderTarget(
+ cImageView,
+ cAspectMask,
+ cClearValue);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ClearView(
+ ID3D11View* pView,
+ const FLOAT Color[4],
+ const D3D11_RECT* pRect,
+ UINT NumRects) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (NumRects && !pRect)
+ return;
+
+ // ID3D11View has no methods to query the exact type of
+ // the view, so we'll have to check each possible class
+ auto dsv = dynamic_cast<D3D11DepthStencilView*>(pView);
+ auto rtv = dynamic_cast<D3D11RenderTargetView*>(pView);
+ auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pView);
+ auto vov = dynamic_cast<D3D11VideoProcessorOutputView*>(pView);
+
+ // Retrieve underlying resource view
+ Rc<DxvkBufferView> bufView;
+ Rc<DxvkImageView> imgView;
+
+ if (dsv != nullptr)
+ imgView = dsv->GetImageView();
+
+ if (rtv != nullptr)
+ imgView = rtv->GetImageView();
+
+ if (uav != nullptr) {
+ bufView = uav->GetBufferView();
+ imgView = uav->GetImageView();
+ }
+
+ if (vov != nullptr)
+ imgView = vov->GetView();
+
+ // 3D views are unsupported
+ if (imgView != nullptr
+ && imgView->info().type == VK_IMAGE_VIEW_TYPE_3D)
+ return;
+
+ // Query the view format. We'll have to convert
+ // the clear color based on the format's data type.
+ VkFormat format = VK_FORMAT_UNDEFINED;
+
+ if (bufView != nullptr)
+ format = bufView->info().format;
+
+ if (imgView != nullptr)
+ format = imgView->info().format;
+
+ if (format == VK_FORMAT_UNDEFINED)
+ return;
+
+ // We'll need the format info to determine the buffer
+ // element size, and we also need it for depth images.
+ const DxvkFormatInfo* formatInfo = imageFormatInfo(format);
+
+ // Convert the clear color format. ClearView takes
+ // the clear value for integer formats as a set of
+ // integral floats, so we'll have to convert.
+ VkClearValue clearValue = ConvertColorValue(Color, formatInfo);
+ VkImageAspectFlags clearAspect = formatInfo->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
+
+ // Clear all the rectangles that are specified
+ for (uint32_t i = 0; i < NumRects || i < 1; i++) {
+ if (pRect) {
+ if (pRect[i].left >= pRect[i].right
+ || pRect[i].top >= pRect[i].bottom)
+ continue;
+ }
+
+ if (bufView != nullptr) {
+ VkDeviceSize offset = 0;
+ VkDeviceSize length = bufView->info().rangeLength / formatInfo->elementSize;
+
+ if (pRect) {
+ offset = pRect[i].left;
+ length = pRect[i].right - pRect[i].left;
+ }
+
+ EmitCs([
+ cBufferView = bufView,
+ cRangeOffset = offset,
+ cRangeLength = length,
+ cClearValue = clearValue
+ ] (DxvkContext* ctx) {
+ ctx->clearBufferView(
+ cBufferView,
+ cRangeOffset,
+ cRangeLength,
+ cClearValue.color);
+ });
+ }
+
+ if (imgView != nullptr) {
+ VkOffset3D offset = { 0, 0, 0 };
+ VkExtent3D extent = imgView->mipLevelExtent(0);
+
+ if (pRect) {
+ offset = { pRect[i].left, pRect[i].top, 0 };
+ extent = {
+ uint32_t(pRect[i].right - pRect[i].left),
+ uint32_t(pRect[i].bottom - pRect[i].top), 1 };
+ }
+
+ EmitCs([
+ cImageView = imgView,
+ cAreaOffset = offset,
+ cAreaExtent = extent,
+ cClearAspect = clearAspect,
+ cClearValue = clearValue
+ ] (DxvkContext* ctx) {
+ const VkImageUsageFlags rtUsage =
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ bool isFullSize = cImageView->mipLevelExtent(0) == cAreaExtent;
+
+ if ((cImageView->info().usage & rtUsage) && isFullSize) {
+ ctx->clearRenderTarget(
+ cImageView,
+ cClearAspect,
+ cClearValue);
+ } else {
+ ctx->clearImageView(
+ cImageView,
+ cAreaOffset,
+ cAreaExtent,
+ cClearAspect,
+ cClearValue);
+ }
+ });
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto view = static_cast<D3D11ShaderResourceView*>(pShaderResourceView);
+
+ if (!view || view->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER)
+ return;
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc = view->GetResourceDesc();
+
+ if (!(resourceDesc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS))
+ return;
+
+ EmitCs([cDstImageView = view->GetImageView()]
+ (DxvkContext* ctx) {
+ ctx->generateMipmaps(cDstImageView, VK_FILTER_LINEAR);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::UpdateSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch) {
+ UpdateSubresource1(pDstResource,
+ DstSubresource, pDstBox, pSrcData,
+ SrcRowPitch, SrcDepthPitch, 0);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::UpdateSubresource1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (!pDstResource)
+ return;
+
+ // Filter out invalid copy flags
+ CopyFlags &= D3D11_COPY_NO_OVERWRITE | D3D11_COPY_DISCARD;
+
+ // We need a different code path for buffers
+ D3D11_RESOURCE_DIMENSION resourceType;
+ pDstResource->GetType(&resourceType);
+
+ if (resourceType == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ const auto bufferResource = static_cast<D3D11Buffer*>(pDstResource);
+ const auto bufferSlice = bufferResource->GetBufferSlice();
+
+ VkDeviceSize offset = bufferSlice.offset();
+ VkDeviceSize size = bufferSlice.length();
+
+ if (pDstBox != nullptr) {
+ offset = pDstBox->left;
+ size = pDstBox->right - pDstBox->left;
+ }
+
+ if (!size || offset + size > bufferSlice.length())
+ return;
+
+ bool useMap = (bufferSlice.buffer()->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ && (size == bufferSlice.length() || CopyFlags);
+
+ if (useMap) {
+ D3D11_MAP mapType = (CopyFlags & D3D11_COPY_NO_OVERWRITE)
+ ? D3D11_MAP_WRITE_NO_OVERWRITE
+ : D3D11_MAP_WRITE_DISCARD;
+
+ D3D11_MAPPED_SUBRESOURCE mappedSr;
+ if (likely(useMap = SUCCEEDED(Map(pDstResource, 0, mapType, 0, &mappedSr)))) {
+ std::memcpy(reinterpret_cast<char*>(mappedSr.pData) + offset, pSrcData, size);
+ Unmap(pDstResource, 0);
+ }
+ }
+
+ if (!useMap) {
+ DxvkDataSlice dataSlice = AllocUpdateBufferSlice(size);
+ std::memcpy(dataSlice.ptr(), pSrcData, size);
+
+ EmitCs([
+ cDataBuffer = std::move(dataSlice),
+ cBufferSlice = bufferSlice.subSlice(offset, size)
+ ] (DxvkContext* ctx) {
+ ctx->updateBuffer(
+ cBufferSlice.buffer(),
+ cBufferSlice.offset(),
+ cBufferSlice.length(),
+ cDataBuffer.ptr());
+ });
+ }
+ } else {
+ D3D11CommonTexture* dstTexture = GetCommonTexture(pDstResource);
+
+ if (DstSubresource >= dstTexture->CountSubresources())
+ return;
+
+ VkFormat packedFormat = dstTexture->GetPackedFormat();
+
+ auto formatInfo = imageFormatInfo(packedFormat);
+ auto subresource = dstTexture->GetSubresourceFromIndex(
+ formatInfo->aspectMask, DstSubresource);
+
+ VkExtent3D mipExtent = dstTexture->MipLevelExtent(subresource.mipLevel);
+
+ VkOffset3D offset = { 0, 0, 0 };
+ VkExtent3D extent = mipExtent;
+
+ if (pDstBox != nullptr) {
+ if (pDstBox->left >= pDstBox->right
+ || pDstBox->top >= pDstBox->bottom
+ || pDstBox->front >= pDstBox->back)
+ return; // no-op, but legal
+
+ offset.x = pDstBox->left;
+ offset.y = pDstBox->top;
+ offset.z = pDstBox->front;
+
+ extent.width = pDstBox->right - pDstBox->left;
+ extent.height = pDstBox->bottom - pDstBox->top;
+ extent.depth = pDstBox->back - pDstBox->front;
+ }
+
+ if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) {
+ Logger::err("D3D11: UpdateSubresource1: Unaligned region");
+ return;
+ }
+
+ auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent));
+
+ util::packImageData(stagingSlice.mapPtr(0),
+ pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0,
+ dstTexture->GetVkImageType(), extent, 1,
+ formatInfo, formatInfo->aspectMask);
+
+ UpdateImage(dstTexture, &subresource,
+ offset, extent, std::move(stagingSlice));
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContext::UpdateTileMappings(
+ ID3D11Resource* pTiledResource,
+ UINT NumTiledResourceRegions,
+ const D3D11_TILED_RESOURCE_COORDINATE* pTiledResourceRegionStartCoordinates,
+ const D3D11_TILE_REGION_SIZE* pTiledResourceRegionSizes,
+ ID3D11Buffer* pTilePool,
+ UINT NumRanges,
+ const UINT* pRangeFlags,
+ const UINT* pTilePoolStartOffsets,
+ const UINT* pRangeTileCounts,
+ UINT Flags) {
+ bool s_errorShown = false;
+
+ if (std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::UpdateTileMappings: Not implemented");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::UpdateTiles(
+ ID3D11Resource* pDestTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pDestTileRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
+ const void* pSourceTileData,
+ UINT Flags) {
+ bool s_errorShown = false;
+
+ if (std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::UpdateTiles: Not implemented");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SetResourceMinLOD(
+ ID3D11Resource* pResource,
+ FLOAT MinLOD) {
+ bool s_errorShown = false;
+
+ if (std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::SetResourceMinLOD: Not implemented");
+ }
+
+
+ FLOAT STDMETHODCALLTYPE D3D11DeviceContext::GetResourceMinLOD(ID3D11Resource* pResource) {
+ bool s_errorShown = false;
+
+ if (std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::GetResourceMinLOD: Not implemented");
+
+ return 0.0f;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::ResolveSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ DXGI_FORMAT Format) {
+ D3D10DeviceLock lock = LockContext();
+
+ bool isSameSubresource = pDstResource == pSrcResource
+ && DstSubresource == SrcSubresource;
+
+ if (!pDstResource || !pSrcResource || isSameSubresource)
+ return;
+
+ D3D11_RESOURCE_DIMENSION dstResourceType;
+ D3D11_RESOURCE_DIMENSION srcResourceType;
+
+ pDstResource->GetType(&dstResourceType);
+ pSrcResource->GetType(&srcResourceType);
+
+ if (dstResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D
+ || srcResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
+ Logger::err(str::format(
+ "D3D11: ResolveSubresource: Incompatible resources",
+ "\n Dst resource type: ", dstResourceType,
+ "\n Src resource type: ", srcResourceType));
+ return;
+ }
+
+ auto dstTexture = static_cast<D3D11Texture2D*>(pDstResource);
+ auto srcTexture = static_cast<D3D11Texture2D*>(pSrcResource);
+
+ D3D11_TEXTURE2D_DESC dstDesc;
+ D3D11_TEXTURE2D_DESC srcDesc;
+
+ dstTexture->GetDesc(&dstDesc);
+ srcTexture->GetDesc(&srcDesc);
+
+ if (dstDesc.SampleDesc.Count != 1) {
+ Logger::err(str::format(
+ "D3D11: ResolveSubresource: Invalid sample counts",
+ "\n Dst sample count: ", dstDesc.SampleDesc.Count,
+ "\n Src sample count: ", srcDesc.SampleDesc.Count));
+ return;
+ }
+
+ const D3D11CommonTexture* dstTextureInfo = GetCommonTexture(pDstResource);
+ const D3D11CommonTexture* srcTextureInfo = GetCommonTexture(pSrcResource);
+
+ const DXGI_VK_FORMAT_INFO dstFormatInfo = m_parent->LookupFormat(dstDesc.Format, DXGI_VK_FORMAT_MODE_ANY);
+ const DXGI_VK_FORMAT_INFO srcFormatInfo = m_parent->LookupFormat(srcDesc.Format, DXGI_VK_FORMAT_MODE_ANY);
+
+ auto dstVulkanFormatInfo = imageFormatInfo(dstFormatInfo.Format);
+ auto srcVulkanFormatInfo = imageFormatInfo(srcFormatInfo.Format);
+
+ if (DstSubresource >= dstTextureInfo->CountSubresources()
+ || SrcSubresource >= srcTextureInfo->CountSubresources())
+ return;
+
+ const VkImageSubresource dstSubresource =
+ dstTextureInfo->GetSubresourceFromIndex(
+ dstVulkanFormatInfo->aspectMask, DstSubresource);
+
+ const VkImageSubresource srcSubresource =
+ srcTextureInfo->GetSubresourceFromIndex(
+ srcVulkanFormatInfo->aspectMask, SrcSubresource);
+
+ const VkImageSubresourceLayers dstSubresourceLayers = {
+ dstSubresource.aspectMask,
+ dstSubresource.mipLevel,
+ dstSubresource.arrayLayer, 1 };
+
+ const VkImageSubresourceLayers srcSubresourceLayers = {
+ srcSubresource.aspectMask,
+ srcSubresource.mipLevel,
+ srcSubresource.arrayLayer, 1 };
+
+ if (srcDesc.SampleDesc.Count == 1 || m_parent->GetOptions()->disableMsaa) {
+ EmitCs([
+ cDstImage = dstTextureInfo->GetImage(),
+ cSrcImage = srcTextureInfo->GetImage(),
+ cDstLayers = dstSubresourceLayers,
+ cSrcLayers = srcSubresourceLayers
+ ] (DxvkContext* ctx) {
+ ctx->copyImage(
+ cDstImage, cDstLayers, VkOffset3D { 0, 0, 0 },
+ cSrcImage, cSrcLayers, VkOffset3D { 0, 0, 0 },
+ cDstImage->mipLevelExtent(cDstLayers.mipLevel));
+ });
+ } else {
+ const VkFormat format = m_parent->LookupFormat(
+ Format, DXGI_VK_FORMAT_MODE_ANY).Format;
+
+ EmitCs([
+ cDstImage = dstTextureInfo->GetImage(),
+ cSrcImage = srcTextureInfo->GetImage(),
+ cDstSubres = dstSubresourceLayers,
+ cSrcSubres = srcSubresourceLayers,
+ cFormat = format
+ ] (DxvkContext* ctx) {
+ VkImageResolve region;
+ region.srcSubresource = cSrcSubres;
+ region.srcOffset = VkOffset3D { 0, 0, 0 };
+ region.dstSubresource = cDstSubres;
+ region.dstOffset = VkOffset3D { 0, 0, 0 };
+ region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel);
+
+ ctx->resolveImage(cDstImage, cSrcImage, region, cFormat);
+ });
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawAuto() {
+ D3D10DeviceLock lock = LockContext();
+
+ D3D11Buffer* buffer = m_state.ia.vertexBuffers[0].buffer.ptr();
+
+ if (buffer == nullptr)
+ return;
+
+ DxvkBufferSlice vtxBuf = buffer->GetBufferSlice();
+ DxvkBufferSlice ctrBuf = buffer->GetSOCounter();
+
+ if (!ctrBuf.defined())
+ return;
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->drawIndirectXfb(ctrBuf,
+ vtxBuf.buffer()->getXfbVertexStride(),
+ vtxBuf.offset());
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::Draw(
+ UINT VertexCount,
+ UINT StartVertexLocation) {
+ D3D10DeviceLock lock = LockContext();
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->draw(
+ VertexCount, 1,
+ StartVertexLocation, 0);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexed(
+ UINT IndexCount,
+ UINT StartIndexLocation,
+ INT BaseVertexLocation) {
+ D3D10DeviceLock lock = LockContext();
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->drawIndexed(
+ IndexCount, 1,
+ StartIndexLocation,
+ BaseVertexLocation, 0);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstanced(
+ UINT VertexCountPerInstance,
+ UINT InstanceCount,
+ UINT StartVertexLocation,
+ UINT StartInstanceLocation) {
+ D3D10DeviceLock lock = LockContext();
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->draw(
+ VertexCountPerInstance,
+ InstanceCount,
+ StartVertexLocation,
+ StartInstanceLocation);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstanced(
+ UINT IndexCountPerInstance,
+ UINT InstanceCount,
+ UINT StartIndexLocation,
+ INT BaseVertexLocation,
+ UINT StartInstanceLocation) {
+ D3D10DeviceLock lock = LockContext();
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->drawIndexed(
+ IndexCountPerInstance,
+ InstanceCount,
+ StartIndexLocation,
+ BaseVertexLocation,
+ StartInstanceLocation);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstancedIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs) {
+ D3D10DeviceLock lock = LockContext();
+ SetDrawBuffers(pBufferForArgs, nullptr);
+
+ if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand)))
+ return;
+
+ // If possible, batch up multiple indirect draw calls of
+ // the same type into one single multiDrawIndirect call
+ auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
+ auto stride = 0u;
+
+ if (cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed)
+ stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand));
+
+ if (stride) {
+ cmdData->count += 1;
+ cmdData->stride = stride;
+ } else {
+ cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
+ [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
+ ctx->drawIndexedIndirect(data->offset, data->count, data->stride);
+ });
+
+ cmdData->type = D3D11CmdType::DrawIndirectIndexed;
+ cmdData->offset = AlignedByteOffsetForArgs;
+ cmdData->count = 1;
+ cmdData->stride = 0;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstancedIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs) {
+ D3D10DeviceLock lock = LockContext();
+ SetDrawBuffers(pBufferForArgs, nullptr);
+
+ if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand)))
+ return;
+
+ // If possible, batch up multiple indirect draw calls of
+ // the same type into one single multiDrawIndirect call
+ auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
+ auto stride = 0u;
+
+ if (cmdData && cmdData->type == D3D11CmdType::DrawIndirect)
+ stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand));
+
+ if (stride) {
+ cmdData->count += 1;
+ cmdData->stride = stride;
+ } else {
+ cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
+ [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
+ ctx->drawIndirect(data->offset, data->count, data->stride);
+ });
+
+ cmdData->type = D3D11CmdType::DrawIndirect;
+ cmdData->offset = AlignedByteOffsetForArgs;
+ cmdData->count = 1;
+ cmdData->stride = 0;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::Dispatch(
+ UINT ThreadGroupCountX,
+ UINT ThreadGroupCountY,
+ UINT ThreadGroupCountZ) {
+ D3D10DeviceLock lock = LockContext();
+
+ EmitCs([=] (DxvkContext* ctx) {
+ ctx->dispatch(
+ ThreadGroupCountX,
+ ThreadGroupCountY,
+ ThreadGroupCountZ);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DispatchIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs) {
+ D3D10DeviceLock lock = LockContext();
+ SetDrawBuffers(pBufferForArgs, nullptr);
+
+ if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDispatchIndirectCommand)))
+ return;
+
+ EmitCs([cOffset = AlignedByteOffsetForArgs]
+ (DxvkContext* ctx) {
+ ctx->dispatchIndirect(cOffset);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IASetInputLayout(ID3D11InputLayout* pInputLayout) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto inputLayout = static_cast<D3D11InputLayout*>(pInputLayout);
+
+ if (m_state.ia.inputLayout != inputLayout) {
+ bool equal = false;
+
+ // Some games (e.g. Grim Dawn) create lots and lots of
+ // identical input layouts, so we'll only apply the state
+ // if the input layouts has actually changed between calls.
+ if (m_state.ia.inputLayout != nullptr && inputLayout != nullptr)
+ equal = m_state.ia.inputLayout->Compare(inputLayout);
+
+ m_state.ia.inputLayout = inputLayout;
+
+ if (!equal)
+ ApplyInputLayout();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topology) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (m_state.ia.primitiveTopology != Topology) {
+ m_state.ia.primitiveTopology = Topology;
+ ApplyPrimitiveTopology();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IASetVertexBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppVertexBuffers,
+ const UINT* pStrides,
+ const UINT* pOffsets) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ auto newBuffer = static_cast<D3D11Buffer*>(ppVertexBuffers[i]);
+ bool needsUpdate = m_state.ia.vertexBuffers[StartSlot + i].buffer != newBuffer;
+
+ if (needsUpdate)
+ m_state.ia.vertexBuffers[StartSlot + i].buffer = newBuffer;
+
+ needsUpdate |= m_state.ia.vertexBuffers[StartSlot + i].offset != pOffsets[i]
+ || m_state.ia.vertexBuffers[StartSlot + i].stride != pStrides[i];
+
+ if (needsUpdate) {
+ m_state.ia.vertexBuffers[StartSlot + i].offset = pOffsets[i];
+ m_state.ia.vertexBuffers[StartSlot + i].stride = pStrides[i];
+
+ BindVertexBuffer(StartSlot + i, newBuffer, pOffsets[i], pStrides[i]);
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IASetIndexBuffer(
+ ID3D11Buffer* pIndexBuffer,
+ DXGI_FORMAT Format,
+ UINT Offset) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto newBuffer = static_cast<D3D11Buffer*>(pIndexBuffer);
+ bool needsUpdate = m_state.ia.indexBuffer.buffer != newBuffer;
+
+ if (needsUpdate)
+ m_state.ia.indexBuffer.buffer = newBuffer;
+
+ needsUpdate |= m_state.ia.indexBuffer.offset != Offset
+ || m_state.ia.indexBuffer.format != Format;
+
+ if (needsUpdate) {
+ m_state.ia.indexBuffer.offset = Offset;
+ m_state.ia.indexBuffer.format = Format;
+
+ BindIndexBuffer(newBuffer, Offset, Format);
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout** ppInputLayout) {
+ D3D10DeviceLock lock = LockContext();
+
+ *ppInputLayout = m_state.ia.inputLayout.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IAGetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY* pTopology) {
+ D3D10DeviceLock lock = LockContext();
+
+ *pTopology = m_state.ia.primitiveTopology;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IAGetVertexBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppVertexBuffers,
+ UINT* pStrides,
+ UINT* pOffsets) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ const bool inRange = StartSlot + i < m_state.ia.vertexBuffers.size();
+
+ if (ppVertexBuffers != nullptr) {
+ ppVertexBuffers[i] = inRange
+ ? m_state.ia.vertexBuffers[StartSlot + i].buffer.ref()
+ : nullptr;
+ }
+
+ if (pStrides != nullptr) {
+ pStrides[i] = inRange
+ ? m_state.ia.vertexBuffers[StartSlot + i].stride
+ : 0u;
+ }
+
+ if (pOffsets != nullptr) {
+ pOffsets[i] = inRange
+ ? m_state.ia.vertexBuffers[StartSlot + i].offset
+ : 0u;
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::IAGetIndexBuffer(
+ ID3D11Buffer** ppIndexBuffer,
+ DXGI_FORMAT* pFormat,
+ UINT* pOffset) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppIndexBuffer != nullptr)
+ *ppIndexBuffer = m_state.ia.indexBuffer.buffer.ref();
+
+ if (pFormat != nullptr)
+ *pFormat = m_state.ia.indexBuffer.format;
+
+ if (pOffset != nullptr)
+ *pOffset = m_state.ia.indexBuffer.offset;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShader(
+ ID3D11VertexShader* pVertexShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11VertexShader*>(pVertexShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.vs.shader != shader) {
+ m_state.vs.shader = shader;
+
+ BindShader<DxbcProgramType::VertexShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::VertexShader>(
+ m_state.vs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::VertexShader>(
+ m_state.vs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::VertexShader>(
+ m_state.vs.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::VertexShader>(
+ m_state.vs.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShader(
+ ID3D11VertexShader** ppVertexShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppVertexShader != nullptr)
+ *ppVertexShader = m_state.vs.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.vs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.vs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.vs.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::VSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.vs.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShader(
+ ID3D11HullShader* pHullShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11HullShader*>(pHullShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.hs.shader != shader) {
+ m_state.hs.shader = shader;
+
+ BindShader<DxbcProgramType::HullShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::HullShader>(
+ m_state.hs.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::HullShader>(
+ m_state.hs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::HullShader>(
+ m_state.hs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::HullShader>(
+ m_state.hs.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShader(
+ ID3D11HullShader** ppHullShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppHullShader != nullptr)
+ *ppHullShader = m_state.hs.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.hs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.hs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.hs.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::HSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.hs.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShader(
+ ID3D11DomainShader* pDomainShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11DomainShader*>(pDomainShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.ds.shader != shader) {
+ m_state.ds.shader = shader;
+
+ BindShader<DxbcProgramType::DomainShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::DomainShader>(
+ m_state.ds.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::DomainShader>(
+ m_state.ds.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::DomainShader>(
+ m_state.ds.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::DomainShader>(
+ m_state.ds.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShader(
+ ID3D11DomainShader** ppDomainShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppDomainShader != nullptr)
+ *ppDomainShader = m_state.ds.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.ds.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.ds.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.ds.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::DSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.ds.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShader(
+ ID3D11GeometryShader* pShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11GeometryShader*>(pShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.gs.shader != shader) {
+ m_state.gs.shader = shader;
+
+ BindShader<DxbcProgramType::GeometryShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::GeometryShader>(
+ m_state.gs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::GeometryShader>(
+ m_state.gs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::GeometryShader>(
+ m_state.gs.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::GeometryShader>(
+ m_state.gs.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShader(
+ ID3D11GeometryShader** ppGeometryShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppGeometryShader != nullptr)
+ *ppGeometryShader = m_state.gs.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.gs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.gs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.gs.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.gs.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShader(
+ ID3D11PixelShader* pPixelShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11PixelShader*>(pPixelShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.ps.shader != shader) {
+ m_state.ps.shader = shader;
+
+ BindShader<DxbcProgramType::PixelShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::PixelShader>(
+ m_state.ps.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::PixelShader>(
+ m_state.ps.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::PixelShader>(
+ m_state.ps.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::PixelShader>(
+ m_state.ps.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShader(
+ ID3D11PixelShader** ppPixelShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppPixelShader != nullptr)
+ *ppPixelShader = m_state.ps.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.ps.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.ps.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.ps.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::PSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.ps.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShader(
+ ID3D11ComputeShader* pComputeShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto shader = static_cast<D3D11ComputeShader*>(pComputeShader);
+
+ if (NumClassInstances != 0)
+ Logger::err("D3D11: Class instances not supported");
+
+ if (m_state.cs.shader != shader) {
+ m_state.cs.shader = shader;
+
+ BindShader<DxbcProgramType::ComputeShader>(GetCommonShader(shader));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers<DxbcProgramType::ComputeShader>(
+ m_state.cs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetConstantBuffers1<DxbcProgramType::ComputeShader>(
+ m_state.cs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetShaderResources<DxbcProgramType::ComputeShader>(
+ m_state.cs.shaderResources,
+ StartSlot, NumViews,
+ ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ SetSamplers<DxbcProgramType::ComputeShader>(
+ m_state.cs.samplers,
+ StartSlot, NumSamplers,
+ ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSSetUnorderedAccessViews(
+ UINT StartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (TestRtvUavHazards(0, nullptr, NumUAVs, ppUnorderedAccessViews))
+ return;
+
+ // Unbind previously bound conflicting UAVs
+ uint32_t uavSlotId = computeUavBinding (DxbcProgramType::ComputeShader, 0);
+ uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::ComputeShader, 0);
+
+ int32_t uavId = m_state.cs.uavMask.findNext(0);
+
+ while (uavId >= 0) {
+ if (uint32_t(uavId) < StartSlot || uint32_t(uavId) >= StartSlot + NumUAVs) {
+ for (uint32_t i = 0; i < NumUAVs; i++) {
+ auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
+
+ if (CheckViewOverlap(uav, m_state.cs.unorderedAccessViews[uavId].ptr())) {
+ m_state.cs.unorderedAccessViews[uavId] = nullptr;
+ m_state.cs.uavMask.clr(uavId);
+
+ BindUnorderedAccessView(
+ uavSlotId + uavId, nullptr,
+ ctrSlotId + uavId, ~0u);
+ }
+ }
+
+ uavId = m_state.cs.uavMask.findNext(uavId + 1);
+ } else {
+ uavId = m_state.cs.uavMask.findNext(StartSlot + NumUAVs);
+ }
+ }
+
+ // Actually bind the given UAVs
+ for (uint32_t i = 0; i < NumUAVs; i++) {
+ auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
+ auto ctr = pUAVInitialCounts ? pUAVInitialCounts[i] : ~0u;
+
+ if (m_state.cs.unorderedAccessViews[StartSlot + i] != uav || ctr != ~0u) {
+ m_state.cs.unorderedAccessViews[StartSlot + i] = uav;
+ m_state.cs.uavMask.set(StartSlot + i, uav != nullptr);
+
+ BindUnorderedAccessView(
+ uavSlotId + StartSlot + i, uav,
+ ctrSlotId + StartSlot + i, ctr);
+
+ ResolveCsSrvHazards(uav);
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShader(
+ ID3D11ComputeShader** ppComputeShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppComputeShader != nullptr)
+ *ppComputeShader = m_state.cs.shader.ref();
+
+ if (pNumClassInstances != nullptr)
+ *pNumClassInstances = 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.cs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetConstantBuffers(
+ m_state.cs.constantBuffers,
+ StartSlot, NumBuffers,
+ ppConstantBuffers,
+ pFirstConstant,
+ pNumConstants);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetShaderResources(m_state.cs.shaderResources,
+ StartSlot, NumViews, ppShaderResourceViews);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ D3D10DeviceLock lock = LockContext();
+
+ GetSamplers(m_state.cs.samplers,
+ StartSlot, NumSamplers, ppSamplers);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::CSGetUnorderedAccessViews(
+ UINT StartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView** ppUnorderedAccessViews) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumUAVs; i++) {
+ ppUnorderedAccessViews[i] = StartSlot + i < m_state.cs.unorderedAccessViews.size()
+ ? m_state.cs.unorderedAccessViews[StartSlot + i].ref()
+ : nullptr;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView) {
+ OMSetRenderTargetsAndUnorderedAccessViews(
+ NumViews, ppRenderTargetViews, pDepthStencilView,
+ NumViews, 0, nullptr, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (TestRtvUavHazards(NumRTVs, ppRenderTargetViews, NumUAVs, ppUnorderedAccessViews))
+ return;
+
+ bool needsUpdate = false;
+
+ if (likely(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)) {
+ // Native D3D11 does not change the render targets if
+ // the parameters passed to this method are invalid.
+ if (!ValidateRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView))
+ return;
+
+ for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) {
+ auto rtv = i < NumRTVs
+ ? static_cast<D3D11RenderTargetView*>(ppRenderTargetViews[i])
+ : nullptr;
+
+ if (m_state.om.renderTargetViews[i] != rtv) {
+ m_state.om.renderTargetViews[i] = rtv;
+ needsUpdate = true;
+ ResolveOmSrvHazards(rtv);
+
+ if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS)
+ ResolveOmUavHazards(rtv);
+ }
+ }
+
+ auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
+
+ if (m_state.om.depthStencilView != dsv) {
+ m_state.om.depthStencilView = dsv;
+ needsUpdate = true;
+ ResolveOmSrvHazards(dsv);
+ }
+
+ m_state.om.maxRtv = NumRTVs;
+ }
+
+ if (unlikely(NumUAVs || m_state.om.maxUav)) {
+ uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0);
+ uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0);
+
+ if (likely(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS)) {
+ uint32_t newMaxUav = NumUAVs ? UAVStartSlot + NumUAVs : 0;
+ uint32_t oldMaxUav = std::exchange(m_state.om.maxUav, newMaxUav);
+
+ for (uint32_t i = 0; i < std::max(oldMaxUav, newMaxUav); i++) {
+ D3D11UnorderedAccessView* uav = nullptr;
+ uint32_t ctr = ~0u;
+
+ if (i >= UAVStartSlot && i < UAVStartSlot + NumUAVs) {
+ uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i - UAVStartSlot]);
+ ctr = pUAVInitialCounts ? pUAVInitialCounts[i - UAVStartSlot] : ~0u;
+ }
+
+ if (m_state.ps.unorderedAccessViews[i] != uav || ctr != ~0u) {
+ m_state.ps.unorderedAccessViews[i] = uav;
+
+ BindUnorderedAccessView(
+ uavSlotId + i, uav,
+ ctrSlotId + i, ctr);
+
+ ResolveOmSrvHazards(uav);
+
+ if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
+ needsUpdate |= ResolveOmRtvHazards(uav);
+ }
+ }
+ }
+ }
+
+ if (needsUpdate)
+ BindFramebuffer();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMSetBlendState(
+ ID3D11BlendState* pBlendState,
+ const FLOAT BlendFactor[4],
+ UINT SampleMask) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto blendState = static_cast<D3D11BlendState*>(pBlendState);
+
+ if (m_state.om.cbState != blendState
+ || m_state.om.sampleMask != SampleMask) {
+ m_state.om.cbState = blendState;
+ m_state.om.sampleMask = SampleMask;
+
+ ApplyBlendState();
+ }
+
+ if (BlendFactor != nullptr) {
+ for (uint32_t i = 0; i < 4; i++)
+ m_state.om.blendFactor[i] = BlendFactor[i];
+
+ ApplyBlendFactor();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMSetDepthStencilState(
+ ID3D11DepthStencilState* pDepthStencilState,
+ UINT StencilRef) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto depthStencilState = static_cast<D3D11DepthStencilState*>(pDepthStencilState);
+
+ if (m_state.om.dsState != depthStencilState) {
+ m_state.om.dsState = depthStencilState;
+ ApplyDepthStencilState();
+ }
+
+ if (m_state.om.stencilRef != StencilRef) {
+ m_state.om.stencilRef = StencilRef;
+ ApplyStencilRef();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView** ppRenderTargetViews,
+ ID3D11DepthStencilView** ppDepthStencilView) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppRenderTargetViews != nullptr) {
+ for (UINT i = 0; i < NumViews; i++) {
+ ppRenderTargetViews[i] = i < m_state.om.renderTargetViews.size()
+ ? m_state.om.renderTargetViews[i].ref()
+ : nullptr;
+ }
+ }
+
+ if (ppDepthStencilView != nullptr)
+ *ppDepthStencilView = m_state.om.depthStencilView.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView** ppRenderTargetViews,
+ ID3D11DepthStencilView** ppDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView** ppUnorderedAccessViews) {
+ OMGetRenderTargets(NumRTVs, ppRenderTargetViews, ppDepthStencilView);
+
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppUnorderedAccessViews != nullptr) {
+ for (UINT i = 0; i < NumUAVs; i++) {
+ ppUnorderedAccessViews[i] = UAVStartSlot + i < m_state.ps.unorderedAccessViews.size()
+ ? m_state.ps.unorderedAccessViews[UAVStartSlot + i].ref()
+ : nullptr;
+ }
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMGetBlendState(
+ ID3D11BlendState** ppBlendState,
+ FLOAT BlendFactor[4],
+ UINT* pSampleMask) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppBlendState != nullptr)
+ *ppBlendState = ref(m_state.om.cbState);
+
+ if (BlendFactor != nullptr)
+ std::memcpy(BlendFactor, m_state.om.blendFactor, sizeof(FLOAT) * 4);
+
+ if (pSampleMask != nullptr)
+ *pSampleMask = m_state.om.sampleMask;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::OMGetDepthStencilState(
+ ID3D11DepthStencilState** ppDepthStencilState,
+ UINT* pStencilRef) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppDepthStencilState != nullptr)
+ *ppDepthStencilState = ref(m_state.om.dsState);
+
+ if (pStencilRef != nullptr)
+ *pStencilRef = m_state.om.stencilRef;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSSetState(ID3D11RasterizerState* pRasterizerState) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto rasterizerState = static_cast<D3D11RasterizerState*>(pRasterizerState);
+
+ bool currScissorEnable = m_state.rs.state != nullptr
+ ? m_state.rs.state->Desc()->ScissorEnable
+ : false;
+
+ bool nextScissorEnable = rasterizerState != nullptr
+ ? rasterizerState->Desc()->ScissorEnable
+ : false;
+
+ if (m_state.rs.state != rasterizerState) {
+ m_state.rs.state = rasterizerState;
+
+ // In D3D11, the rasterizer state defines whether the
+ // scissor test is enabled, so we have to update the
+ // scissor rectangles as well.
+ ApplyRasterizerState();
+
+ if (currScissorEnable != nextScissorEnable)
+ ApplyViewportState();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSSetViewports(
+ UINT NumViewports,
+ const D3D11_VIEWPORT* pViewports) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(NumViewports > m_state.rs.viewports.size()))
+ return;
+
+ bool dirty = m_state.rs.numViewports != NumViewports;
+ m_state.rs.numViewports = NumViewports;
+
+ for (uint32_t i = 0; i < NumViewports; i++) {
+ const D3D11_VIEWPORT& vp = m_state.rs.viewports[i];
+
+ dirty |= vp.TopLeftX != pViewports[i].TopLeftX
+ || vp.TopLeftY != pViewports[i].TopLeftY
+ || vp.Width != pViewports[i].Width
+ || vp.Height != pViewports[i].Height
+ || vp.MinDepth != pViewports[i].MinDepth
+ || vp.MaxDepth != pViewports[i].MaxDepth;
+
+ m_state.rs.viewports[i] = pViewports[i];
+ }
+
+ if (dirty)
+ ApplyViewportState();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSSetScissorRects(
+ UINT NumRects,
+ const D3D11_RECT* pRects) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(NumRects > m_state.rs.scissors.size()))
+ return;
+
+ bool dirty = m_state.rs.numScissors != NumRects;
+ m_state.rs.numScissors = NumRects;
+
+ for (uint32_t i = 0; i < NumRects; i++) {
+ if (pRects[i].bottom >= pRects[i].top
+ && pRects[i].right >= pRects[i].left) {
+ const D3D11_RECT& sr = m_state.rs.scissors[i];
+
+ dirty |= sr.top != pRects[i].top
+ || sr.left != pRects[i].left
+ || sr.bottom != pRects[i].bottom
+ || sr.right != pRects[i].right;
+
+ m_state.rs.scissors[i] = pRects[i];
+ }
+ }
+
+ if (m_state.rs.state != nullptr && dirty) {
+ D3D11_RASTERIZER_DESC rsDesc;
+ m_state.rs.state->GetDesc(&rsDesc);
+
+ if (rsDesc.ScissorEnable)
+ ApplyViewportState();
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSGetState(ID3D11RasterizerState** ppRasterizerState) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (ppRasterizerState != nullptr)
+ *ppRasterizerState = ref(m_state.rs.state);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSGetViewports(
+ UINT* pNumViewports,
+ D3D11_VIEWPORT* pViewports) {
+ D3D10DeviceLock lock = LockContext();
+ uint32_t numWritten = m_state.rs.numViewports;
+
+ if (pViewports) {
+ numWritten = std::min(numWritten, *pNumViewports);
+
+ for (uint32_t i = 0; i < *pNumViewports; i++) {
+ if (i < m_state.rs.numViewports) {
+ pViewports[i] = m_state.rs.viewports[i];
+ } else {
+ pViewports[i].TopLeftX = 0.0f;
+ pViewports[i].TopLeftY = 0.0f;
+ pViewports[i].Width = 0.0f;
+ pViewports[i].Height = 0.0f;
+ pViewports[i].MinDepth = 0.0f;
+ pViewports[i].MaxDepth = 0.0f;
+ }
+ }
+ }
+
+ *pNumViewports = numWritten;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::RSGetScissorRects(
+ UINT* pNumRects,
+ D3D11_RECT* pRects) {
+ D3D10DeviceLock lock = LockContext();
+ uint32_t numWritten = m_state.rs.numScissors;
+
+ if (pRects) {
+ numWritten = std::min(numWritten, *pNumRects);
+
+ for (uint32_t i = 0; i < *pNumRects; i++) {
+ if (i < m_state.rs.numScissors) {
+ pRects[i] = m_state.rs.scissors[i];
+ } else {
+ pRects[i].left = 0;
+ pRects[i].top = 0;
+ pRects[i].right = 0;
+ pRects[i].bottom = 0;
+ }
+ }
+ }
+
+ *pNumRects = m_state.rs.numScissors;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SOSetTargets(
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppSOTargets,
+ const UINT* pOffsets) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ D3D11Buffer* buffer = static_cast<D3D11Buffer*>(ppSOTargets[i]);
+ UINT offset = pOffsets != nullptr ? pOffsets[i] : 0;
+
+ m_state.so.targets[i].buffer = buffer;
+ m_state.so.targets[i].offset = offset;
+ }
+
+ for (uint32_t i = NumBuffers; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
+ m_state.so.targets[i].buffer = nullptr;
+ m_state.so.targets[i].offset = 0;
+ }
+
+ for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
+ BindXfbBuffer(i,
+ m_state.so.targets[i].buffer.ptr(),
+ m_state.so.targets[i].offset);
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargets(
+ UINT NumBuffers,
+ ID3D11Buffer** ppSOTargets) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ ppSOTargets[i] = i < m_state.so.targets.size()
+ ? m_state.so.targets[i].buffer.ref()
+ : nullptr;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargetsWithOffsets(
+ UINT NumBuffers,
+ ID3D11Buffer** ppSOTargets,
+ UINT* pOffsets) {
+ D3D10DeviceLock lock = LockContext();
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ const bool inRange = i < m_state.so.targets.size();
+
+ if (ppSOTargets != nullptr) {
+ ppSOTargets[i] = inRange
+ ? m_state.so.targets[i].buffer.ref()
+ : nullptr;
+ }
+
+ if (pOffsets != nullptr) {
+ pOffsets[i] = inRange
+ ? m_state.so.targets[i].offset
+ : 0u;
+ }
+ }
+ }
+
+
+ BOOL STDMETHODCALLTYPE D3D11DeviceContext::IsAnnotationEnabled() {
+ return m_device->instance()->extensions().extDebugUtils;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SetMarkerInt(
+ LPCWSTR pLabel,
+ INT Data) {
+ // Not implemented in the backend, ignore
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::BeginEventInt(
+ LPCWSTR pLabel,
+ INT Data) {
+ // Not implemented in the backend, ignore
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::EndEvent() {
+ // Not implemented in the backend, ignore
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::GetHardwareProtectionState(
+ BOOL* pHwProtectionEnable) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::GetHardwareProtectionState: Not implemented");
+
+ if (pHwProtectionEnable)
+ *pHwProtectionEnable = FALSE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::SetHardwareProtectionState(
+ BOOL HwProtectionEnable) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DeviceContext::SetHardwareProtectionState: Not implemented");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout(
+ IDXGIVkInteropSurface* pSurface,
+ const VkImageSubresourceRange* pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout) {
+ D3D10DeviceLock lock = LockContext();
+
+ // Get the underlying D3D11 resource
+ Com<ID3D11Resource> resource;
+
+ pSurface->QueryInterface(__uuidof(ID3D11Resource),
+ reinterpret_cast<void**>(&resource));
+
+ // Get the texture from that resource
+ D3D11CommonTexture* texture = GetCommonTexture(resource.ptr());
+
+ EmitCs([
+ cImage = texture->GetImage(),
+ cSubresources = *pSubresources,
+ cOldLayout = OldLayout,
+ cNewLayout = NewLayout
+ ] (DxvkContext* ctx) {
+ ctx->transformImage(
+ cImage, cSubresources,
+ cOldLayout, cNewLayout);
+ });
+ }
+
+
+ void D3D11DeviceContext::ApplyInputLayout() {
+ auto inputLayout = m_state.ia.inputLayout.prvRef();
+
+ if (likely(inputLayout != nullptr)) {
+ EmitCs([
+ cInputLayout = std::move(inputLayout)
+ ] (DxvkContext* ctx) {
+ cInputLayout->BindToContext(ctx);
+ });
+ } else {
+ EmitCs([] (DxvkContext* ctx) {
+ ctx->setInputLayout(0, nullptr, 0, nullptr);
+ });
+ }
+ }
+
+
+ void D3D11DeviceContext::ApplyPrimitiveTopology() {
+ D3D11_PRIMITIVE_TOPOLOGY topology = m_state.ia.primitiveTopology;
+ DxvkInputAssemblyState iaState = { };
+
+ if (topology <= D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ) {
+ static const std::array<DxvkInputAssemblyState, 14> s_iaStates = {{
+ { VK_PRIMITIVE_TOPOLOGY_MAX_ENUM, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_TRUE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_TRUE, 0 },
+ { }, { }, { }, { }, // Random gap that exists for no reason
+ { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, VK_FALSE, 0 },
+ { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 },
+ }};
+
+ iaState = s_iaStates[uint32_t(topology)];
+ } else if (topology >= D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST
+ && topology <= D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST) {
+ // The number of control points per patch can be inferred from the enum value in D3D11
+ uint32_t vertexCount = uint32_t(topology - D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1);
+ iaState = { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE, vertexCount };
+ }
+
+ EmitCs([iaState] (DxvkContext* ctx) {
+ ctx->setInputAssemblyState(iaState);
+ });
+ }
+
+
+ void D3D11DeviceContext::ApplyBlendState() {
+ if (m_state.om.cbState != nullptr) {
+ EmitCs([
+ cBlendState = m_state.om.cbState,
+ cSampleMask = m_state.om.sampleMask
+ ] (DxvkContext* ctx) {
+ cBlendState->BindToContext(ctx, cSampleMask);
+ });
+ } else {
+ EmitCs([
+ cSampleMask = m_state.om.sampleMask
+ ] (DxvkContext* ctx) {
+ DxvkBlendMode cbState;
+ DxvkLogicOpState loState;
+ DxvkMultisampleState msState;
+ InitDefaultBlendState(&cbState, &loState, &msState, cSampleMask);
+
+ for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ ctx->setBlendMode(i, cbState);
+
+ ctx->setLogicOpState(loState);
+ ctx->setMultisampleState(msState);
+ });
+ }
+ }
+
+
+ void D3D11DeviceContext::ApplyBlendFactor() {
+ EmitCs([
+ cBlendConstants = DxvkBlendConstants {
+ m_state.om.blendFactor[0], m_state.om.blendFactor[1],
+ m_state.om.blendFactor[2], m_state.om.blendFactor[3] }
+ ] (DxvkContext* ctx) {
+ ctx->setBlendConstants(cBlendConstants);
+ });
+ }
+
+
+ void D3D11DeviceContext::ApplyDepthStencilState() {
+ if (m_state.om.dsState != nullptr) {
+ EmitCs([
+ cDepthStencilState = m_state.om.dsState
+ ] (DxvkContext* ctx) {
+ cDepthStencilState->BindToContext(ctx);
+ });
+ } else {
+ EmitCs([] (DxvkContext* ctx) {
+ DxvkDepthStencilState dsState;
+ InitDefaultDepthStencilState(&dsState);
+
+ ctx->setDepthStencilState(dsState);
+ });
+ }
+ }
+
+
+ void D3D11DeviceContext::ApplyStencilRef() {
+ EmitCs([
+ cStencilRef = m_state.om.stencilRef
+ ] (DxvkContext* ctx) {
+ ctx->setStencilReference(cStencilRef);
+ });
+ }
+
+
+ void D3D11DeviceContext::ApplyRasterizerState() {
+ if (m_state.rs.state != nullptr) {
+ EmitCs([
+ cRasterizerState = m_state.rs.state
+ ] (DxvkContext* ctx) {
+ cRasterizerState->BindToContext(ctx);
+ });
+ } else {
+ EmitCs([] (DxvkContext* ctx) {
+ DxvkRasterizerState rsState;
+ InitDefaultRasterizerState(&rsState);
+
+ ctx->setRasterizerState(rsState);
+ });
+ }
+ }
+
+
+ void D3D11DeviceContext::ApplyViewportState() {
+ std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
+ std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
+
+ // The backend can't handle a viewport count of zero,
+ // so we should at least specify one empty viewport
+ uint32_t viewportCount = m_state.rs.numViewports;
+
+ if (unlikely(!viewportCount)) {
+ viewportCount = 1;
+ viewports[0] = VkViewport();
+ scissors [0] = VkRect2D();
+ }
+
+ // D3D11's coordinate system has its origin in the bottom left,
+ // but the viewport coordinates are aligned to the top-left
+ // corner so we can get away with flipping the viewport.
+ for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
+ const D3D11_VIEWPORT& vp = m_state.rs.viewports[i];
+
+ viewports[i] = VkViewport {
+ vp.TopLeftX, vp.Height + vp.TopLeftY,
+ vp.Width, -vp.Height,
+ vp.MinDepth, vp.MaxDepth,
+ };
+ }
+
+ // Scissor rectangles. Vulkan does not provide an easy way
+ // to disable the scissor test, so we'll have to set scissor
+ // rects that are at least as large as the framebuffer.
+ bool enableScissorTest = false;
+
+ if (m_state.rs.state != nullptr) {
+ D3D11_RASTERIZER_DESC rsDesc;
+ m_state.rs.state->GetDesc(&rsDesc);
+ enableScissorTest = rsDesc.ScissorEnable;
+ }
+
+ for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
+ if (!enableScissorTest) {
+ scissors[i] = VkRect2D {
+ VkOffset2D { 0, 0 },
+ VkExtent2D {
+ D3D11_VIEWPORT_BOUNDS_MAX,
+ D3D11_VIEWPORT_BOUNDS_MAX } };
+ } else if (i >= m_state.rs.numScissors) {
+ scissors[i] = VkRect2D {
+ VkOffset2D { 0, 0 },
+ VkExtent2D { 0, 0 } };
+ } else {
+ D3D11_RECT sr = m_state.rs.scissors[i];
+
+ VkOffset2D srPosA;
+ srPosA.x = std::max<int32_t>(0, sr.left);
+ srPosA.y = std::max<int32_t>(0, sr.top);
+
+ VkOffset2D srPosB;
+ srPosB.x = std::max<int32_t>(srPosA.x, sr.right);
+ srPosB.y = std::max<int32_t>(srPosA.y, sr.bottom);
+
+ VkExtent2D srSize;
+ srSize.width = uint32_t(srPosB.x - srPosA.x);
+ srSize.height = uint32_t(srPosB.y - srPosA.y);
+
+ scissors[i] = VkRect2D { srPosA, srSize };
+ }
+ }
+
+ if (likely(viewportCount == 1)) {
+ EmitCs([
+ cViewport = viewports[0],
+ cScissor = scissors[0]
+ ] (DxvkContext* ctx) {
+ ctx->setViewports(1,
+ &cViewport,
+ &cScissor);
+ });
+ } else {
+ EmitCs([
+ cViewportCount = viewportCount,
+ cViewports = viewports,
+ cScissors = scissors
+ ] (DxvkContext* ctx) {
+ ctx->setViewports(
+ cViewportCount,
+ cViewports.data(),
+ cScissors.data());
+ });
+ }
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ void D3D11DeviceContext::BindShader(
+ const D3D11CommonShader* pShaderModule) {
+ // Bind the shader and the ICB at once
+ EmitCs([
+ cSlice = pShaderModule != nullptr
+ && pShaderModule->GetIcb() != nullptr
+ ? DxvkBufferSlice(pShaderModule->GetIcb())
+ : DxvkBufferSlice(),
+ cShader = pShaderModule != nullptr
+ ? pShaderModule->GetShader()
+ : nullptr
+ ] (DxvkContext* ctx) {
+ VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
+
+ uint32_t slotId = computeConstantBufferBinding(ShaderStage,
+ D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+
+ ctx->bindShader (stage, cShader);
+ ctx->bindResourceBuffer(slotId, cSlice);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindFramebuffer() {
+ DxvkRenderTargets attachments;
+
+ // D3D11 doesn't have the concept of a framebuffer object,
+ // so we'll just create a new one every time the render
+ // target bindings are updated. Set up the attachments.
+ for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
+ if (m_state.om.renderTargetViews[i] != nullptr) {
+ attachments.color[i] = {
+ m_state.om.renderTargetViews[i]->GetImageView(),
+ m_state.om.renderTargetViews[i]->GetRenderLayout() };
+ }
+ }
+
+ if (m_state.om.depthStencilView != nullptr) {
+ attachments.depth = {
+ m_state.om.depthStencilView->GetImageView(),
+ m_state.om.depthStencilView->GetRenderLayout() };
+ }
+
+ // Create and bind the framebuffer object to the context
+ EmitCs([
+ cAttachments = std::move(attachments)
+ ] (DxvkContext* ctx) {
+ ctx->bindRenderTargets(cAttachments);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindDrawBuffers(
+ D3D11Buffer* pBufferForArgs,
+ D3D11Buffer* pBufferForCount) {
+ EmitCs([
+ cArgBuffer = pBufferForArgs ? pBufferForArgs->GetBufferSlice() : DxvkBufferSlice(),
+ cCntBuffer = pBufferForCount ? pBufferForCount->GetBufferSlice() : DxvkBufferSlice()
+ ] (DxvkContext* ctx) {
+ ctx->bindDrawBuffers(cArgBuffer, cCntBuffer);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindVertexBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ UINT Stride) {
+ EmitCs([
+ cSlotId = Slot,
+ cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(),
+ cStride = Stride
+ ] (DxvkContext* ctx) {
+ ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindIndexBuffer(
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ DXGI_FORMAT Format) {
+ VkIndexType indexType = Format == DXGI_FORMAT_R16_UINT
+ ? VK_INDEX_TYPE_UINT16
+ : VK_INDEX_TYPE_UINT32;
+
+ EmitCs([
+ cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(),
+ cIndexType = indexType
+ ] (DxvkContext* ctx) {
+ ctx->bindIndexBuffer(cBufferSlice, cIndexType);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindXfbBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset) {
+ DxvkBufferSlice bufferSlice;
+ DxvkBufferSlice counterSlice;
+
+ if (pBuffer != nullptr) {
+ bufferSlice = pBuffer->GetBufferSlice();
+ counterSlice = pBuffer->GetSOCounter();
+ }
+
+ EmitCs([
+ cSlotId = Slot,
+ cOffset = Offset,
+ cBufferSlice = bufferSlice,
+ cCounterSlice = counterSlice
+ ] (DxvkContext* ctx) {
+ if (cCounterSlice.defined() && cOffset != ~0u) {
+ ctx->updateBuffer(
+ cCounterSlice.buffer(),
+ cCounterSlice.offset(),
+ sizeof(cOffset),
+ &cOffset);
+ }
+
+ ctx->bindXfbBuffer(cSlotId, cBufferSlice, cCounterSlice);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindConstantBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ UINT Length) {
+ EmitCs([
+ cSlotId = Slot,
+ cBufferSlice = Length ? pBuffer->GetBufferSlice(16 * Offset, 16 * Length) : DxvkBufferSlice()
+ ] (DxvkContext* ctx) {
+ ctx->bindResourceBuffer(cSlotId, cBufferSlice);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindSampler(
+ UINT Slot,
+ D3D11SamplerState* pSampler) {
+ EmitCs([
+ cSlotId = Slot,
+ cSampler = pSampler != nullptr ? pSampler->GetDXVKSampler() : nullptr
+ ] (DxvkContext* ctx) {
+ ctx->bindResourceSampler(cSlotId, cSampler);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindShaderResource(
+ UINT Slot,
+ D3D11ShaderResourceView* pResource) {
+ EmitCs([
+ cSlotId = Slot,
+ cImageView = pResource != nullptr ? pResource->GetImageView() : nullptr,
+ cBufferView = pResource != nullptr ? pResource->GetBufferView() : nullptr
+ ] (DxvkContext* ctx) {
+ ctx->bindResourceView(cSlotId, cImageView, cBufferView);
+ });
+ }
+
+
+ void D3D11DeviceContext::BindUnorderedAccessView(
+ UINT UavSlot,
+ D3D11UnorderedAccessView* pUav,
+ UINT CtrSlot,
+ UINT Counter) {
+ EmitCs([
+ cUavSlotId = UavSlot,
+ cCtrSlotId = CtrSlot,
+ cImageView = pUav != nullptr ? pUav->GetImageView() : nullptr,
+ cBufferView = pUav != nullptr ? pUav->GetBufferView() : nullptr,
+ cCounterSlice = pUav != nullptr ? pUav->GetCounterSlice() : DxvkBufferSlice(),
+ cCounterValue = Counter
+ ] (DxvkContext* ctx) {
+ if (cCounterSlice.defined() && cCounterValue != ~0u) {
+ ctx->updateBuffer(
+ cCounterSlice.buffer(),
+ cCounterSlice.offset(),
+ sizeof(uint32_t),
+ &cCounterValue);
+ }
+
+ ctx->bindResourceView (cUavSlotId, cImageView, cBufferView);
+ ctx->bindResourceBuffer (cCtrSlotId, cCounterSlice);
+ });
+ }
+
+
+ void D3D11DeviceContext::CopyBuffer(
+ D3D11Buffer* pDstBuffer,
+ VkDeviceSize DstOffset,
+ D3D11Buffer* pSrcBuffer,
+ VkDeviceSize SrcOffset,
+ VkDeviceSize ByteCount) {
+ // Clamp copy region to prevent out-of-bounds access
+ VkDeviceSize dstLength = pDstBuffer->Desc()->ByteWidth;
+ VkDeviceSize srcLength = pSrcBuffer->Desc()->ByteWidth;
+
+ if (SrcOffset >= srcLength || DstOffset >= dstLength || !ByteCount)
+ return;
+
+ ByteCount = std::min(dstLength - DstOffset, ByteCount);
+ ByteCount = std::min(srcLength - SrcOffset, ByteCount);
+
+ EmitCs([
+ cDstBuffer = pDstBuffer->GetBufferSlice(DstOffset, ByteCount),
+ cSrcBuffer = pSrcBuffer->GetBufferSlice(SrcOffset, ByteCount)
+ ] (DxvkContext* ctx) {
+ if (cDstBuffer.buffer() != cSrcBuffer.buffer()) {
+ ctx->copyBuffer(
+ cDstBuffer.buffer(),
+ cDstBuffer.offset(),
+ cSrcBuffer.buffer(),
+ cSrcBuffer.offset(),
+ cSrcBuffer.length());
+ } else {
+ ctx->copyBufferRegion(
+ cDstBuffer.buffer(),
+ cDstBuffer.offset(),
+ cSrcBuffer.offset(),
+ cSrcBuffer.length());
+ }
+ });
+ }
+
+
+ void D3D11DeviceContext::CopyImage(
+ D3D11CommonTexture* pDstTexture,
+ const VkImageSubresourceLayers* pDstLayers,
+ VkOffset3D DstOffset,
+ D3D11CommonTexture* pSrcTexture,
+ const VkImageSubresourceLayers* pSrcLayers,
+ VkOffset3D SrcOffset,
+ VkExtent3D SrcExtent) {
+ // Image formats must be size-compatible
+ auto dstFormatInfo = imageFormatInfo(pDstTexture->GetPackedFormat());
+ auto srcFormatInfo = imageFormatInfo(pSrcTexture->GetPackedFormat());
+
+ if (dstFormatInfo->elementSize != srcFormatInfo->elementSize) {
+ Logger::err("D3D11: CopyImage: Incompatible texel size");
+ return;
+ }
+
+ // Sample counts must match
+ if (pDstTexture->Desc()->SampleDesc.Count != pSrcTexture->Desc()->SampleDesc.Count) {
+ Logger::err("D3D11: CopyImage: Incompatible sample count");
+ return;
+ }
+
+ // Obviously, the copy region must not be empty
+ VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstLayers->mipLevel);
+ VkExtent3D srcMipExtent = pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel);
+
+ if (uint32_t(DstOffset.x) >= dstMipExtent.width
+ || uint32_t(DstOffset.y) >= dstMipExtent.height
+ || uint32_t(DstOffset.z) >= dstMipExtent.depth)
+ return;
+
+ if (uint32_t(SrcOffset.x) >= srcMipExtent.width
+ || uint32_t(SrcOffset.y) >= srcMipExtent.height
+ || uint32_t(SrcOffset.z) >= srcMipExtent.depth)
+ return;
+
+ // Don't perform the copy if the offsets aren't block-aligned
+ if (!util::isBlockAligned(SrcOffset, srcFormatInfo->blockSize)
+ || !util::isBlockAligned(DstOffset, dstFormatInfo->blockSize)) {
+ Logger::err(str::format("D3D11: CopyImage: Unaligned block offset"));
+ return;
+ }
+
+ // Clamp the image region in order to avoid out-of-bounds access
+ VkExtent3D blockCount = util::computeBlockCount(SrcExtent, srcFormatInfo->blockSize);
+ VkExtent3D dstBlockCount = util::computeMaxBlockCount(DstOffset, dstMipExtent, dstFormatInfo->blockSize);
+ VkExtent3D srcBlockCount = util::computeMaxBlockCount(SrcOffset, srcMipExtent, srcFormatInfo->blockSize);
+
+ blockCount = util::minExtent3D(blockCount, dstBlockCount);
+ blockCount = util::minExtent3D(blockCount, srcBlockCount);
+
+ SrcExtent = util::computeBlockExtent(blockCount, srcFormatInfo->blockSize);
+ SrcExtent = util::snapExtent3D(SrcOffset, SrcExtent, srcMipExtent);
+
+ if (!SrcExtent.width || !SrcExtent.height || !SrcExtent.depth)
+ return;
+
+ // While copying between 2D and 3D images is allowed in CopySubresourceRegion,
+ // copying more than one slice at a time is not suppoted. Layer counts are 1.
+ if ((pDstTexture->GetVkImageType() == VK_IMAGE_TYPE_3D)
+ != (pSrcTexture->GetVkImageType() == VK_IMAGE_TYPE_3D))
+ SrcExtent.depth = 1;
+
+ // Certain types of copies require us to pass the destination extent to
+ // the backend. This may be different when copying between compressed
+ // and uncompressed image formats.
+ VkExtent3D dstExtent = util::computeBlockExtent(blockCount, dstFormatInfo->blockSize);
+ dstExtent = util::snapExtent3D(DstOffset, dstExtent, dstMipExtent);
+
+ // It is possible for any of the given images to be a staging image with
+ // no actual image, so we need to account for all possibilities here.
+ bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
+ bool srcIsImage = pSrcTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
+
+ if (dstIsImage && srcIsImage) {
+ EmitCs([
+ cDstImage = pDstTexture->GetImage(),
+ cSrcImage = pSrcTexture->GetImage(),
+ cDstLayers = *pDstLayers,
+ cSrcLayers = *pSrcLayers,
+ cDstOffset = DstOffset,
+ cSrcOffset = SrcOffset,
+ cExtent = SrcExtent
+ ] (DxvkContext* ctx) {
+ // CopyResource can only copy between different images, and
+ // CopySubresourceRegion can only copy data from one single
+ // subresource at a time, so this check is safe.
+ if (cDstImage != cSrcImage || cDstLayers != cSrcLayers) {
+ ctx->copyImage(
+ cDstImage, cDstLayers, cDstOffset,
+ cSrcImage, cSrcLayers, cSrcOffset,
+ cExtent);
+ } else {
+ ctx->copyImageRegion(
+ cDstImage, cDstLayers, cDstOffset,
+ cSrcOffset, cExtent);
+ }
+ });
+ } else {
+ // Since each subresource uses a dedicated buffer, we are going
+ // to need one call per subresource for staging resource copies
+ for (uint32_t i = 0; i < pDstLayers->layerCount; i++) {
+ uint32_t dstSubresource = D3D11CalcSubresource(pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, pDstTexture->Desc()->MipLevels);
+ uint32_t srcSubresource = D3D11CalcSubresource(pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, pSrcTexture->Desc()->MipLevels);
+
+ // For multi-plane image data stored in a buffer, the backend
+ // assumes that the second plane immediately follows the first
+ // plane in memory, which is only true if we copy the full image.
+ uint32_t planeCount = 1;
+
+ if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
+ bool needsSeparateCopies = !dstIsImage && !srcIsImage;
+
+ if (!dstIsImage)
+ needsSeparateCopies |= pDstTexture->MipLevelExtent(pDstLayers->mipLevel) != SrcExtent;
+ if (!srcIsImage)
+ needsSeparateCopies |= pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel) != SrcExtent;
+
+ if (needsSeparateCopies)
+ planeCount = vk::getPlaneCount(srcFormatInfo->aspectMask);
+ }
+
+ for (uint32_t j = 0; j < planeCount; j++) {
+ VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
+ VkImageAspectFlags srcAspectMask = srcFormatInfo->aspectMask;
+
+ if (planeCount > 1) {
+ dstAspectMask = vk::getPlaneAspect(j);
+ srcAspectMask = dstAspectMask;
+ }
+
+ if (dstIsImage) {
+ VkImageSubresourceLayers dstLayer = { dstAspectMask,
+ pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, 1 };
+
+ EmitCs([
+ cDstImage = pDstTexture->GetImage(),
+ cDstLayers = dstLayer,
+ cDstOffset = DstOffset,
+ cDstExtent = dstExtent,
+ cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
+ cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource),
+ cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset),
+ cSrcCoord = SrcOffset,
+ cSrcExtent = srcMipExtent,
+ cSrcFormat = pSrcTexture->GetPackedFormat()
+ ] (DxvkContext* ctx) {
+ if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
+ cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch);
+ } else {
+ ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
+ VkOffset2D { cDstOffset.x, cDstOffset.y },
+ VkExtent2D { cDstExtent.width, cDstExtent.height },
+ cSrcBuffer, cSrcLayout.Offset,
+ VkOffset2D { cSrcCoord.x, cSrcCoord.y },
+ VkExtent2D { cSrcExtent.width, cSrcExtent.height },
+ cSrcFormat);
+ }
+ });
+ } else if (srcIsImage) {
+ VkImageSubresourceLayers srcLayer = { srcAspectMask,
+ pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, 1 };
+
+ EmitCs([
+ cSrcImage = pSrcTexture->GetImage(),
+ cSrcLayers = srcLayer,
+ cSrcOffset = SrcOffset,
+ cSrcExtent = SrcExtent,
+ cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
+ cDstLayout = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource),
+ cDstOffset = pDstTexture->ComputeMappedOffset(dstSubresource, j, DstOffset),
+ cDstCoord = DstOffset,
+ cDstExtent = dstMipExtent,
+ cDstFormat = pDstTexture->GetPackedFormat()
+ ] (DxvkContext* ctx) {
+ if (cSrcLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ ctx->copyImageToBuffer(cDstBuffer, cDstOffset, cDstLayout.RowPitch,
+ cDstLayout.DepthPitch, cSrcImage, cSrcLayers, cSrcOffset, cSrcExtent);
+ } else {
+ ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, cDstLayout.Offset,
+ VkOffset2D { cDstCoord.x, cDstCoord.y },
+ VkExtent2D { cDstExtent.width, cDstExtent.height },
+ cSrcImage, cSrcLayers,
+ VkOffset2D { cSrcOffset.x, cSrcOffset.y },
+ VkExtent2D { cSrcExtent.width, cSrcExtent.height },
+ cDstFormat);
+ }
+ });
+ } else {
+ // The backend is not aware of image metadata in this case,
+ // so we need to handle image planes and block sizes here
+ VkDeviceSize elementSize = dstFormatInfo->elementSize;
+ VkExtent3D dstBlockSize = dstFormatInfo->blockSize;
+ VkExtent3D srcBlockSize = srcFormatInfo->blockSize;
+ VkExtent3D planeBlockSize = { 1u, 1u, 1u };
+
+ if (planeCount > 1) {
+ auto plane = &dstFormatInfo->planes[j];
+ dstBlockSize.width *= plane->blockSize.width;
+ dstBlockSize.height *= plane->blockSize.height;
+ srcBlockSize.width *= plane->blockSize.width;
+ srcBlockSize.height *= plane->blockSize.height;
+
+ planeBlockSize.width = plane->blockSize.width;
+ planeBlockSize.height = plane->blockSize.height;
+ elementSize = plane->elementSize;
+ }
+
+ EmitCs([
+ cPixelSize = elementSize,
+ cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
+ cSrcStart = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource).Offset,
+ cSrcOffset = util::computeBlockOffset(SrcOffset, srcBlockSize),
+ cSrcSize = util::computeBlockCount(srcMipExtent, srcBlockSize),
+ cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
+ cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
+ cDstOffset = util::computeBlockOffset(DstOffset, dstBlockSize),
+ cDstSize = util::computeBlockCount(dstMipExtent, dstBlockSize),
+ cExtent = util::computeBlockCount(blockCount, planeBlockSize)
+ ] (DxvkContext* ctx) {
+ ctx->copyPackedBufferImage(
+ cDstBuffer, cDstStart, cDstOffset, cDstSize,
+ cSrcBuffer, cSrcStart, cSrcOffset, cSrcSize,
+ cExtent, cPixelSize);
+ });
+ }
+ }
+ }
+ }
+ }
+
+
+ void D3D11DeviceContext::DiscardBuffer(
+ ID3D11Resource* pResource) {
+ auto buffer = static_cast<D3D11Buffer*>(pResource);
+
+ if (buffer->GetMapMode() != D3D11_COMMON_BUFFER_MAP_MODE_NONE) {
+ D3D11_MAPPED_SUBRESOURCE sr;
+
+ Map(pResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
+ Unmap(pResource, 0);
+ }
+ }
+
+
+ void D3D11DeviceContext::DiscardTexture(
+ ID3D11Resource* pResource,
+ UINT Subresource) {
+ auto texture = GetCommonTexture(pResource);
+
+ if (texture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ D3D11_MAPPED_SUBRESOURCE sr;
+
+ Map(pResource, Subresource, D3D11_MAP_WRITE_DISCARD, 0, &sr);
+ Unmap(pResource, Subresource);
+ }
+ }
+
+
+ void D3D11DeviceContext::UpdateImage(
+ D3D11CommonTexture* pDstTexture,
+ const VkImageSubresource* pDstSubresource,
+ VkOffset3D DstOffset,
+ VkExtent3D DstExtent,
+ DxvkBufferSlice StagingBuffer) {
+ bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
+
+ if (dstIsImage) {
+ EmitCs([
+ cDstImage = pDstTexture->GetImage(),
+ cDstLayers = vk::makeSubresourceLayers(*pDstSubresource),
+ cDstOffset = DstOffset,
+ cDstExtent = DstExtent,
+ cStagingSlice = std::move(StagingBuffer),
+ cPackedFormat = pDstTexture->GetPackedFormat()
+ ] (DxvkContext* ctx) {
+ if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ ctx->copyBufferToImage(cDstImage,
+ cDstLayers, cDstOffset, cDstExtent,
+ cStagingSlice.buffer(),
+ cStagingSlice.offset(), 0, 0);
+ } else {
+ ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
+ VkOffset2D { cDstOffset.x, cDstOffset.y },
+ VkExtent2D { cDstExtent.width, cDstExtent.height },
+ cStagingSlice.buffer(),
+ cStagingSlice.offset(),
+ VkOffset2D { 0, 0 },
+ VkExtent2D { cDstExtent.width, cDstExtent.height },
+ cPackedFormat);
+ }
+ });
+ } else {
+ // If the destination image is backed only by a buffer, we need to use
+ // the packed buffer copy function which does not know about planes and
+ // format metadata, so deal with it manually here.
+ VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel);
+
+ uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel,
+ pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels);
+
+ auto dstFormat = pDstTexture->GetPackedFormat();
+ auto dstFormatInfo = imageFormatInfo(dstFormat);
+
+ uint32_t planeCount = 1;
+
+ if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane))
+ planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask);
+
+ // The source data isn't stored in an image so we'll also need to
+ // track the offset for that while iterating over the planes.
+ VkDeviceSize srcPlaneOffset = 0;
+
+ for (uint32_t i = 0; i < planeCount; i++) {
+ VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
+ VkDeviceSize elementSize = dstFormatInfo->elementSize;
+ VkExtent3D blockSize = dstFormatInfo->blockSize;
+
+ if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
+ dstAspectMask = vk::getPlaneAspect(i);
+
+ auto plane = &dstFormatInfo->planes[i];
+ blockSize.width *= plane->blockSize.width;
+ blockSize.height *= plane->blockSize.height;
+ elementSize = plane->elementSize;
+ }
+
+ VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize);
+
+ EmitCs([
+ cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
+ cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
+ cDstOffset = util::computeBlockOffset(DstOffset, blockSize),
+ cDstSize = util::computeBlockCount(dstMipExtent, blockSize),
+ cDstExtent = blockCount,
+ cSrcBuffer = StagingBuffer.buffer(),
+ cSrcStart = StagingBuffer.offset() + srcPlaneOffset,
+ cPixelSize = elementSize
+ ] (DxvkContext* ctx) {
+ ctx->copyPackedBufferImage(
+ cDstBuffer, cDstStart, cDstOffset, cDstSize,
+ cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent,
+ cDstExtent, cPixelSize);
+ });
+
+ srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize;
+ }
+ }
+ }
+
+
+ void D3D11DeviceContext::SetDrawBuffers(
+ ID3D11Buffer* pBufferForArgs,
+ ID3D11Buffer* pBufferForCount) {
+ auto argBuffer = static_cast<D3D11Buffer*>(pBufferForArgs);
+ auto cntBuffer = static_cast<D3D11Buffer*>(pBufferForCount);
+
+ if (m_state.id.argBuffer != argBuffer
+ || m_state.id.cntBuffer != cntBuffer) {
+ m_state.id.argBuffer = argBuffer;
+ m_state.id.cntBuffer = cntBuffer;
+
+ BindDrawBuffers(argBuffer, cntBuffer);
+ }
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ void D3D11DeviceContext::SetConstantBuffers(
+ D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers) {
+ uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot);
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ auto newBuffer = static_cast<D3D11Buffer*>(ppConstantBuffers[i]);
+
+ UINT constantCount = 0;
+
+ if (likely(newBuffer != nullptr))
+ constantCount = std::min(newBuffer->Desc()->ByteWidth / 16, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT));
+
+ if (Bindings[StartSlot + i].buffer != newBuffer
+ || Bindings[StartSlot + i].constantCount != constantCount) {
+ Bindings[StartSlot + i].buffer = newBuffer;
+ Bindings[StartSlot + i].constantOffset = 0;
+ Bindings[StartSlot + i].constantCount = constantCount;
+ Bindings[StartSlot + i].constantBound = constantCount;
+
+ BindConstantBuffer(slotId + i, newBuffer, 0, constantCount);
+ }
+ }
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ void D3D11DeviceContext::SetConstantBuffers1(
+ D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants) {
+ uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot);
+
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ auto newBuffer = static_cast<D3D11Buffer*>(ppConstantBuffers[i]);
+
+ UINT constantOffset;
+ UINT constantCount;
+ UINT constantBound;
+
+ if (likely(newBuffer != nullptr)) {
+ UINT bufferConstantsCount = newBuffer->Desc()->ByteWidth / 16;
+ constantBound = std::min(bufferConstantsCount, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT));
+
+ if (likely(pFirstConstant && pNumConstants)) {
+ constantOffset = pFirstConstant[i];
+ constantCount = pNumConstants [i];
+
+ if (unlikely(constantCount > D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT))
+ continue;
+
+ constantBound = (constantOffset + constantCount > bufferConstantsCount)
+ ? bufferConstantsCount - std::min(constantOffset, bufferConstantsCount)
+ : constantCount;
+ } else {
+ constantOffset = 0;
+ constantCount = constantBound;
+ }
+ } else {
+ constantOffset = 0;
+ constantCount = 0;
+ constantBound = 0;
+ }
+
+ bool needsUpdate = Bindings[StartSlot + i].buffer != newBuffer;
+
+ if (needsUpdate)
+ Bindings[StartSlot + i].buffer = newBuffer;
+
+ needsUpdate |= Bindings[StartSlot + i].constantOffset != constantOffset
+ || Bindings[StartSlot + i].constantCount != constantCount;
+
+ if (needsUpdate) {
+ Bindings[StartSlot + i].constantOffset = constantOffset;
+ Bindings[StartSlot + i].constantCount = constantCount;
+ Bindings[StartSlot + i].constantBound = constantBound;
+
+ BindConstantBuffer(slotId + i, newBuffer, constantOffset, constantBound);
+ }
+ }
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ void D3D11DeviceContext::SetSamplers(
+ D3D11SamplerBindings& Bindings,
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers) {
+ uint32_t slotId = computeSamplerBinding(ShaderStage, StartSlot);
+
+ for (uint32_t i = 0; i < NumSamplers; i++) {
+ auto sampler = static_cast<D3D11SamplerState*>(ppSamplers[i]);
+
+ if (Bindings[StartSlot + i] != sampler) {
+ Bindings[StartSlot + i] = sampler;
+ BindSampler(slotId + i, sampler);
+ }
+ }
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ void D3D11DeviceContext::SetShaderResources(
+ D3D11ShaderResourceBindings& Bindings,
+ UINT StartSlot,
+ UINT NumResources,
+ ID3D11ShaderResourceView* const* ppResources) {
+ uint32_t slotId = computeSrvBinding(ShaderStage, StartSlot);
+
+ for (uint32_t i = 0; i < NumResources; i++) {
+ auto resView = static_cast<D3D11ShaderResourceView*>(ppResources[i]);
+
+ if (Bindings.views[StartSlot + i] != resView) {
+ if (unlikely(resView && resView->TestHazards())) {
+ if (TestSrvHazards<ShaderStage>(resView))
+ resView = nullptr;
+
+ // Only set if necessary, but don't reset it on every
+ // bind as this would be more expensive than a few
+ // redundant checks in OMSetRenderTargets and friends.
+ Bindings.hazardous.set(StartSlot + i, resView);
+ }
+
+ Bindings.views[StartSlot + i] = resView;
+ BindShaderResource(slotId + i, resView);
+ }
+ }
+ }
+
+
+ void D3D11DeviceContext::GetConstantBuffers(
+ const D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants) {
+ for (uint32_t i = 0; i < NumBuffers; i++) {
+ const bool inRange = StartSlot + i < Bindings.size();
+
+ if (ppConstantBuffers != nullptr) {
+ ppConstantBuffers[i] = inRange
+ ? Bindings[StartSlot + i].buffer.ref()
+ : nullptr;
+ }
+
+ if (pFirstConstant != nullptr) {
+ pFirstConstant[i] = inRange
+ ? Bindings[StartSlot + i].constantOffset
+ : 0u;
+ }
+
+ if (pNumConstants != nullptr) {
+ pNumConstants[i] = inRange
+ ? Bindings[StartSlot + i].constantCount
+ : 0u;
+ }
+ }
+ }
+
+
+ void D3D11DeviceContext::GetShaderResources(
+ const D3D11ShaderResourceBindings& Bindings,
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews) {
+ for (uint32_t i = 0; i < NumViews; i++) {
+ ppShaderResourceViews[i] = StartSlot + i < Bindings.views.size()
+ ? Bindings.views[StartSlot + i].ref()
+ : nullptr;
+ }
+ }
+
+
+ void D3D11DeviceContext::GetSamplers(
+ const D3D11SamplerBindings& Bindings,
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers) {
+ for (uint32_t i = 0; i < NumSamplers; i++) {
+ ppSamplers[i] = StartSlot + i < Bindings.size()
+ ? ref(Bindings[StartSlot + i])
+ : nullptr;
+ }
+ }
+
+
+ void D3D11DeviceContext::ResetState() {
+ EmitCs([] (DxvkContext* ctx) {
+ // Reset render targets
+ ctx->bindRenderTargets(DxvkRenderTargets());
+
+ // Reset vertex input state
+ ctx->setInputLayout(0, nullptr, 0, nullptr);
+
+ // Reset render states
+ DxvkInputAssemblyState iaState;
+ InitDefaultPrimitiveTopology(&iaState);
+
+ DxvkDepthStencilState dsState;
+ InitDefaultDepthStencilState(&dsState);
+
+ DxvkRasterizerState rsState;
+ InitDefaultRasterizerState(&rsState);
+
+ DxvkBlendMode cbState;
+ DxvkLogicOpState loState;
+ DxvkMultisampleState msState;
+ InitDefaultBlendState(&cbState, &loState, &msState, D3D11_DEFAULT_SAMPLE_MASK);
+
+ ctx->setInputAssemblyState(iaState);
+ ctx->setDepthStencilState(dsState);
+ ctx->setRasterizerState(rsState);
+ ctx->setLogicOpState(loState);
+ ctx->setMultisampleState(msState);
+
+ for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ ctx->setBlendMode(i, cbState);
+
+ // Reset dynamic states
+ ctx->setBlendConstants(DxvkBlendConstants { 1.0f, 1.0f, 1.0f, 1.0f });
+ ctx->setStencilReference(D3D11_DEFAULT_STENCIL_REFERENCE);
+
+ // Reset viewports
+ auto viewport = VkViewport();
+ auto scissor = VkRect2D();
+
+ ctx->setViewports(1, &viewport, &scissor);
+
+ // Unbind indirect draw buffer
+ ctx->bindDrawBuffers(DxvkBufferSlice(), DxvkBufferSlice());
+
+ // Unbind index and vertex buffers
+ ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32);
+
+ for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
+ ctx->bindVertexBuffer(i, DxvkBufferSlice(), 0);
+
+ // Unbind transform feedback buffers
+ for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
+ ctx->bindXfbBuffer(i, DxvkBufferSlice(), DxvkBufferSlice());
+
+ // Unbind per-shader stage resources
+ for (uint32_t i = 0; i < 6; i++) {
+ auto programType = DxbcProgramType(i);
+ ctx->bindShader(GetShaderStage(programType), nullptr);
+
+ // Unbind constant buffers, including the shader's ICB
+ auto cbSlotId = computeConstantBufferBinding(programType, 0);
+
+ for (uint32_t j = 0; j <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; j++)
+ ctx->bindResourceBuffer(cbSlotId + j, DxvkBufferSlice());
+
+ // Unbind shader resource views
+ auto srvSlotId = computeSrvBinding(programType, 0);
+
+ for (uint32_t j = 0; j < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; j++)
+ ctx->bindResourceView(srvSlotId + j, nullptr, nullptr);
+
+ // Unbind texture samplers
+ auto samplerSlotId = computeSamplerBinding(programType, 0);
+
+ for (uint32_t j = 0; j < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; j++)
+ ctx->bindResourceSampler(samplerSlotId + j, nullptr);
+
+ // Unbind UAVs for supported stages
+ if (programType == DxbcProgramType::PixelShader
+ || programType == DxbcProgramType::ComputeShader) {
+ auto uavSlotId = computeUavBinding(programType, 0);
+ auto ctrSlotId = computeUavCounterBinding(programType, 0);
+
+ for (uint32_t j = 0; j < D3D11_1_UAV_SLOT_COUNT; j++) {
+ ctx->bindResourceView (uavSlotId, nullptr, nullptr);
+ ctx->bindResourceBuffer (ctrSlotId, DxvkBufferSlice());
+ }
+ }
+ }
+ });
+ }
+
+
+ void D3D11DeviceContext::RestoreState() {
+ BindFramebuffer();
+
+ BindShader<DxbcProgramType::VertexShader> (GetCommonShader(m_state.vs.shader.ptr()));
+ BindShader<DxbcProgramType::HullShader> (GetCommonShader(m_state.hs.shader.ptr()));
+ BindShader<DxbcProgramType::DomainShader> (GetCommonShader(m_state.ds.shader.ptr()));
+ BindShader<DxbcProgramType::GeometryShader> (GetCommonShader(m_state.gs.shader.ptr()));
+ BindShader<DxbcProgramType::PixelShader> (GetCommonShader(m_state.ps.shader.ptr()));
+ BindShader<DxbcProgramType::ComputeShader> (GetCommonShader(m_state.cs.shader.ptr()));
+
+ ApplyInputLayout();
+ ApplyPrimitiveTopology();
+ ApplyBlendState();
+ ApplyBlendFactor();
+ ApplyDepthStencilState();
+ ApplyStencilRef();
+ ApplyRasterizerState();
+ ApplyViewportState();
+
+ BindDrawBuffers(
+ m_state.id.argBuffer.ptr(),
+ m_state.id.cntBuffer.ptr());
+
+ BindIndexBuffer(
+ m_state.ia.indexBuffer.buffer.ptr(),
+ m_state.ia.indexBuffer.offset,
+ m_state.ia.indexBuffer.format);
+
+ for (uint32_t i = 0; i < m_state.ia.vertexBuffers.size(); i++) {
+ BindVertexBuffer(i,
+ m_state.ia.vertexBuffers[i].buffer.ptr(),
+ m_state.ia.vertexBuffers[i].offset,
+ m_state.ia.vertexBuffers[i].stride);
+ }
+
+ for (uint32_t i = 0; i < m_state.so.targets.size(); i++)
+ BindXfbBuffer(i, m_state.so.targets[i].buffer.ptr(), ~0u);
+
+ RestoreConstantBuffers<DxbcProgramType::VertexShader> (m_state.vs.constantBuffers);
+ RestoreConstantBuffers<DxbcProgramType::HullShader> (m_state.hs.constantBuffers);
+ RestoreConstantBuffers<DxbcProgramType::DomainShader> (m_state.ds.constantBuffers);
+ RestoreConstantBuffers<DxbcProgramType::GeometryShader> (m_state.gs.constantBuffers);
+ RestoreConstantBuffers<DxbcProgramType::PixelShader> (m_state.ps.constantBuffers);
+ RestoreConstantBuffers<DxbcProgramType::ComputeShader> (m_state.cs.constantBuffers);
+
+ RestoreSamplers<DxbcProgramType::VertexShader> (m_state.vs.samplers);
+ RestoreSamplers<DxbcProgramType::HullShader> (m_state.hs.samplers);
+ RestoreSamplers<DxbcProgramType::DomainShader> (m_state.ds.samplers);
+ RestoreSamplers<DxbcProgramType::GeometryShader>(m_state.gs.samplers);
+ RestoreSamplers<DxbcProgramType::PixelShader> (m_state.ps.samplers);
+ RestoreSamplers<DxbcProgramType::ComputeShader> (m_state.cs.samplers);
+
+ RestoreShaderResources<DxbcProgramType::VertexShader> (m_state.vs.shaderResources);
+ RestoreShaderResources<DxbcProgramType::HullShader> (m_state.hs.shaderResources);
+ RestoreShaderResources<DxbcProgramType::DomainShader> (m_state.ds.shaderResources);
+ RestoreShaderResources<DxbcProgramType::GeometryShader> (m_state.gs.shaderResources);
+ RestoreShaderResources<DxbcProgramType::PixelShader> (m_state.ps.shaderResources);
+ RestoreShaderResources<DxbcProgramType::ComputeShader> (m_state.cs.shaderResources);
+
+ RestoreUnorderedAccessViews<DxbcProgramType::PixelShader> (m_state.ps.unorderedAccessViews);
+ RestoreUnorderedAccessViews<DxbcProgramType::ComputeShader> (m_state.cs.unorderedAccessViews);
+ }
+
+
+ template<DxbcProgramType Stage>
+ void D3D11DeviceContext::RestoreConstantBuffers(
+ D3D11ConstantBufferBindings& Bindings) {
+ uint32_t slotId = computeConstantBufferBinding(Stage, 0);
+
+ for (uint32_t i = 0; i < Bindings.size(); i++) {
+ BindConstantBuffer(slotId + i, Bindings[i].buffer.ptr(),
+ Bindings[i].constantOffset, Bindings[i].constantBound);
+ }
+ }
+
+
+ template<DxbcProgramType Stage>
+ void D3D11DeviceContext::RestoreSamplers(
+ D3D11SamplerBindings& Bindings) {
+ uint32_t slotId = computeSamplerBinding(Stage, 0);
+
+ for (uint32_t i = 0; i < Bindings.size(); i++)
+ BindSampler(slotId + i, Bindings[i]);
+ }
+
+
+ template<DxbcProgramType Stage>
+ void D3D11DeviceContext::RestoreShaderResources(
+ D3D11ShaderResourceBindings& Bindings) {
+ uint32_t slotId = computeSrvBinding(Stage, 0);
+
+ for (uint32_t i = 0; i < Bindings.views.size(); i++)
+ BindShaderResource(slotId + i, Bindings.views[i].ptr());
+ }
+
+
+ template<DxbcProgramType Stage>
+ void D3D11DeviceContext::RestoreUnorderedAccessViews(
+ D3D11UnorderedAccessBindings& Bindings) {
+ uint32_t uavSlotId = computeUavBinding (Stage, 0);
+ uint32_t ctrSlotId = computeUavCounterBinding(Stage, 0);
+
+ for (uint32_t i = 0; i < Bindings.size(); i++) {
+ BindUnorderedAccessView(
+ uavSlotId + i,
+ Bindings[i].ptr(),
+ ctrSlotId + i, ~0u);
+ }
+ }
+
+
+ bool D3D11DeviceContext::TestRtvUavHazards(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRTVs,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUAVs) {
+ if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) NumRTVs = 0;
+ if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) NumUAVs = 0;
+
+ for (uint32_t i = 0; i < NumRTVs; i++) {
+ auto rtv = static_cast<D3D11RenderTargetView*>(ppRTVs[i]);
+
+ if (!rtv)
+ continue;
+
+ for (uint32_t j = 0; j < i; j++) {
+ if (CheckViewOverlap(rtv, static_cast<D3D11RenderTargetView*>(ppRTVs[j])))
+ return true;
+ }
+
+ if (rtv->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS)) {
+ for (uint32_t j = 0; j < NumUAVs; j++) {
+ if (CheckViewOverlap(rtv, static_cast<D3D11UnorderedAccessView*>(ppUAVs[j])))
+ return true;
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < NumUAVs; i++) {
+ auto uav = static_cast<D3D11UnorderedAccessView*>(ppUAVs[i]);
+
+ if (!uav)
+ continue;
+
+ for (uint32_t j = 0; j < i; j++) {
+ if (CheckViewOverlap(uav, static_cast<D3D11UnorderedAccessView*>(ppUAVs[j])))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ template<DxbcProgramType ShaderStage>
+ bool D3D11DeviceContext::TestSrvHazards(
+ D3D11ShaderResourceView* pView) {
+ bool hazard = false;
+
+ if (ShaderStage == DxbcProgramType::ComputeShader) {
+ int32_t uav = m_state.cs.uavMask.findNext(0);
+
+ while (uav >= 0 && !hazard) {
+ hazard = CheckViewOverlap(pView, m_state.cs.unorderedAccessViews[uav].ptr());
+ uav = m_state.cs.uavMask.findNext(uav + 1);
+ }
+ } else {
+ hazard = CheckViewOverlap(pView, m_state.om.depthStencilView.ptr());
+
+ for (uint32_t i = 0; !hazard && i < m_state.om.maxRtv; i++)
+ hazard = CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr());
+
+ for (uint32_t i = 0; !hazard && i < m_state.om.maxUav; i++)
+ hazard = CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr());
+ }
+
+ return hazard;
+ }
+
+
+ template<DxbcProgramType ShaderStage, typename T>
+ void D3D11DeviceContext::ResolveSrvHazards(
+ T* pView,
+ D3D11ShaderResourceBindings& Bindings) {
+ uint32_t slotId = computeSrvBinding(ShaderStage, 0);
+ int32_t srvId = Bindings.hazardous.findNext(0);
+
+ while (srvId >= 0) {
+ auto srv = Bindings.views[srvId].ptr();
+
+ if (likely(srv && srv->TestHazards())) {
+ bool hazard = CheckViewOverlap(pView, srv);
+
+ if (unlikely(hazard)) {
+ Bindings.views[srvId] = nullptr;
+ Bindings.hazardous.clr(srvId);
+
+ BindShaderResource(slotId + srvId, nullptr);
+ }
+ } else {
+ // Avoid further redundant iterations
+ Bindings.hazardous.clr(srvId);
+ }
+
+ srvId = Bindings.hazardous.findNext(srvId + 1);
+ }
+ }
+
+
+ template<typename T>
+ void D3D11DeviceContext::ResolveCsSrvHazards(
+ T* pView) {
+ if (!pView) return;
+ ResolveSrvHazards<DxbcProgramType::ComputeShader> (pView, m_state.cs.shaderResources);
+ }
+
+
+ template<typename T>
+ void D3D11DeviceContext::ResolveOmSrvHazards(
+ T* pView) {
+ if (!pView) return;
+ ResolveSrvHazards<DxbcProgramType::VertexShader> (pView, m_state.vs.shaderResources);
+ ResolveSrvHazards<DxbcProgramType::HullShader> (pView, m_state.hs.shaderResources);
+ ResolveSrvHazards<DxbcProgramType::DomainShader> (pView, m_state.ds.shaderResources);
+ ResolveSrvHazards<DxbcProgramType::GeometryShader> (pView, m_state.gs.shaderResources);
+ ResolveSrvHazards<DxbcProgramType::PixelShader> (pView, m_state.ps.shaderResources);
+ }
+
+
+ bool D3D11DeviceContext::ResolveOmRtvHazards(
+ D3D11UnorderedAccessView* pView) {
+ if (!pView || !pView->HasBindFlag(D3D11_BIND_RENDER_TARGET))
+ return false;
+
+ bool hazard = false;
+
+ if (CheckViewOverlap(pView, m_state.om.depthStencilView.ptr())) {
+ m_state.om.depthStencilView = nullptr;
+ hazard = true;
+ }
+
+ for (uint32_t i = 0; i < m_state.om.maxRtv; i++) {
+ if (CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr())) {
+ m_state.om.renderTargetViews[i] = nullptr;
+ hazard = true;
+ }
+ }
+
+ return hazard;
+ }
+
+
+ void D3D11DeviceContext::ResolveOmUavHazards(
+ D3D11RenderTargetView* pView) {
+ if (!pView || !pView->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS))
+ return;
+
+ uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0);
+ uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0);
+
+ for (uint32_t i = 0; i < m_state.om.maxUav; i++) {
+ if (CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr())) {
+ m_state.ps.unorderedAccessViews[i] = nullptr;
+
+ BindUnorderedAccessView(
+ uavSlotId + i, nullptr,
+ ctrSlotId + i, ~0u);
+ }
+ }
+ }
+
+
+ bool D3D11DeviceContext::ValidateRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView) {
+ Rc<DxvkImageView> refView;
+
+ if (pDepthStencilView != nullptr) {
+ refView = static_cast<D3D11DepthStencilView*>(
+ pDepthStencilView)->GetImageView();
+ }
+
+ for (uint32_t i = 0; i < NumViews; i++) {
+ if (ppRenderTargetViews[i] != nullptr) {
+ auto curView = static_cast<D3D11RenderTargetView*>(
+ ppRenderTargetViews[i])->GetImageView();
+
+ if (refView != nullptr) {
+ // Render target views must all have the same
+ // size, sample count, layer count, and type
+ if (curView->info().type != refView->info().type
+ || curView->info().numLayers != refView->info().numLayers)
+ return false;
+
+ if (curView->imageInfo().sampleCount
+ != refView->imageInfo().sampleCount)
+ return false;
+ } else {
+ // Set reference view. All remaining views
+ // must be compatible to the reference view.
+ refView = curView;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+ VkClearValue D3D11DeviceContext::ConvertColorValue(
+ const FLOAT Color[4],
+ const DxvkFormatInfo* pFormatInfo) {
+ VkClearValue result;
+
+ if (pFormatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
+ for (uint32_t i = 0; i < 4; i++) {
+ if (pFormatInfo->flags.test(DxvkFormatFlag::SampledUInt))
+ result.color.uint32[i] = uint32_t(std::max(0.0f, Color[i]));
+ else if (pFormatInfo->flags.test(DxvkFormatFlag::SampledSInt))
+ result.color.int32[i] = int32_t(Color[i]);
+ else
+ result.color.float32[i] = Color[i];
+ }
+ } else {
+ result.depthStencil.depth = Color[0];
+ result.depthStencil.stencil = 0;
+ }
+
+ return result;
+ }
+
+
+ DxvkDataSlice D3D11DeviceContext::AllocUpdateBufferSlice(size_t Size) {
+ constexpr size_t UpdateBufferSize = 16 * 1024 * 1024;
+
+ if (Size >= UpdateBufferSize) {
+ Rc<DxvkDataBuffer> buffer = new DxvkDataBuffer(Size);
+ return buffer->alloc(Size);
+ } else {
+ if (m_updateBuffer == nullptr)
+ m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize);
+
+ DxvkDataSlice slice = m_updateBuffer->alloc(Size);
+
+ if (slice.ptr() == nullptr) {
+ m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize);
+ slice = m_updateBuffer->alloc(Size);
+ }
+
+ return slice;
+ }
+ }
+
+
+ DxvkBufferSlice D3D11DeviceContext::AllocStagingBuffer(
+ VkDeviceSize Size) {
+ DxvkBufferCreateInfo info;
+ info.size = Size;
+ info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
+ | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
+ | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
+ | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ info.access = VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_SHADER_READ_BIT;
+
+ return DxvkBufferSlice(m_device->createBuffer(info,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
+ }
+
+
+ DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() {
+ return m_parent->AllocCsChunk(m_csFlags);
+ }
+
+
+ void D3D11DeviceContext::InitDefaultPrimitiveTopology(
+ DxvkInputAssemblyState* pIaState) {
+ pIaState->primitiveTopology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
+ pIaState->primitiveRestart = VK_FALSE;
+ pIaState->patchVertexCount = 0;
+ }
+
+
+ void D3D11DeviceContext::InitDefaultRasterizerState(
+ DxvkRasterizerState* pRsState) {
+ pRsState->polygonMode = VK_POLYGON_MODE_FILL;
+ pRsState->cullMode = VK_CULL_MODE_BACK_BIT;
+ pRsState->frontFace = VK_FRONT_FACE_CLOCKWISE;
+ pRsState->depthClipEnable = VK_TRUE;
+ pRsState->depthBiasEnable = VK_FALSE;
+ pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
+ pRsState->sampleCount = 0;
+ }
+
+
+ void D3D11DeviceContext::InitDefaultDepthStencilState(
+ DxvkDepthStencilState* pDsState) {
+ VkStencilOpState stencilOp;
+ stencilOp.failOp = VK_STENCIL_OP_KEEP;
+ stencilOp.passOp = VK_STENCIL_OP_KEEP;
+ stencilOp.depthFailOp = VK_STENCIL_OP_KEEP;
+ stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
+ stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+ stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+ stencilOp.reference = 0;
+
+ pDsState->enableDepthTest = VK_TRUE;
+ pDsState->enableDepthWrite = VK_TRUE;
+ pDsState->enableStencilTest = VK_FALSE;
+ pDsState->depthCompareOp = VK_COMPARE_OP_LESS;
+ pDsState->stencilOpFront = stencilOp;
+ pDsState->stencilOpBack = stencilOp;
+ }
+
+
+ void D3D11DeviceContext::InitDefaultBlendState(
+ DxvkBlendMode* pCbState,
+ DxvkLogicOpState* pLoState,
+ DxvkMultisampleState* pMsState,
+ UINT SampleMask) {
+ pCbState->enableBlending = VK_FALSE;
+ pCbState->colorSrcFactor = VK_BLEND_FACTOR_ONE;
+ pCbState->colorDstFactor = VK_BLEND_FACTOR_ZERO;
+ pCbState->colorBlendOp = VK_BLEND_OP_ADD;
+ pCbState->alphaSrcFactor = VK_BLEND_FACTOR_ONE;
+ pCbState->alphaDstFactor = VK_BLEND_FACTOR_ZERO;
+ pCbState->alphaBlendOp = VK_BLEND_OP_ADD;
+ pCbState->writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
+ | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+ pLoState->enableLogicOp = VK_FALSE;
+ pLoState->logicOp = VK_LOGIC_OP_NO_OP;
+
+ pMsState->sampleMask = SampleMask;
+ pMsState->enableAlphaToCoverage = VK_FALSE;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.h
new file mode 100644
index 00000000..483b0415
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context.h
@@ -0,0 +1,1011 @@
+#pragma once
+
+#include "../dxvk/dxvk_adapter.h"
+#include "../dxvk/dxvk_cs.h"
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_multithread.h"
+
+#include "d3d11_annotation.h"
+#include "d3d11_cmd.h"
+#include "d3d11_context_ext.h"
+#include "d3d11_context_state.h"
+#include "d3d11_device_child.h"
+#include "d3d11_texture.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11DeviceContext : public D3D11DeviceChild<ID3D11DeviceContext4> {
+ friend class D3D11DeviceContextExt;
+ // Needed in order to call EmitCs for pushing markers
+ friend class D3D11UserDefinedAnnotation;
+ public:
+
+ D3D11DeviceContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device,
+ DxvkCsChunkFlags CsFlags);
+ ~D3D11DeviceContext();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE DiscardResource(ID3D11Resource *pResource);
+
+ void STDMETHODCALLTYPE DiscardView(ID3D11View* pResourceView);
+
+ void STDMETHODCALLTYPE DiscardView1(
+ ID3D11View* pResourceView,
+ const D3D11_RECT* pRects,
+ UINT NumRects);
+
+ void STDMETHODCALLTYPE ClearState();
+
+ void STDMETHODCALLTYPE SetPredication(
+ ID3D11Predicate* pPredicate,
+ BOOL PredicateValue);
+
+ void STDMETHODCALLTYPE GetPredication(
+ ID3D11Predicate** ppPredicate,
+ BOOL* pPredicateValue);
+
+ void STDMETHODCALLTYPE CopySubresourceRegion(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ UINT DstX,
+ UINT DstY,
+ UINT DstZ,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox);
+
+ void STDMETHODCALLTYPE CopySubresourceRegion1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ UINT DstX,
+ UINT DstY,
+ UINT DstZ,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox,
+ UINT CopyFlags);
+
+ void STDMETHODCALLTYPE CopyResource(
+ ID3D11Resource* pDstResource,
+ ID3D11Resource* pSrcResource);
+
+ void STDMETHODCALLTYPE CopyStructureCount(
+ ID3D11Buffer* pDstBuffer,
+ UINT DstAlignedByteOffset,
+ ID3D11UnorderedAccessView* pSrcView);
+
+ void STDMETHODCALLTYPE CopyTiles(
+ ID3D11Resource* pTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pTileRegionSize,
+ ID3D11Buffer* pBuffer,
+ UINT64 BufferStartOffsetInBytes,
+ UINT Flags);
+
+ HRESULT STDMETHODCALLTYPE CopyTileMappings(
+ ID3D11Resource* pDestTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pDestRegionStartCoordinate,
+ ID3D11Resource* pSourceTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pTileRegionSize,
+ UINT Flags);
+
+ HRESULT STDMETHODCALLTYPE ResizeTilePool(
+ ID3D11Buffer* pTilePool,
+ UINT64 NewSizeInBytes);
+
+ void STDMETHODCALLTYPE TiledResourceBarrier(
+ ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier,
+ ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier);
+
+ void STDMETHODCALLTYPE ClearRenderTargetView(
+ ID3D11RenderTargetView* pRenderTargetView,
+ const FLOAT ColorRGBA[4]);
+
+ void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
+ ID3D11UnorderedAccessView* pUnorderedAccessView,
+ const UINT Values[4]);
+
+ void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
+ ID3D11UnorderedAccessView* pUnorderedAccessView,
+ const FLOAT Values[4]);
+
+ void STDMETHODCALLTYPE ClearDepthStencilView(
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT ClearFlags,
+ FLOAT Depth,
+ UINT8 Stencil);
+
+ void STDMETHODCALLTYPE ClearView(
+ ID3D11View *pView,
+ const FLOAT Color[4],
+ const D3D11_RECT *pRect,
+ UINT NumRects);
+
+ void STDMETHODCALLTYPE GenerateMips(
+ ID3D11ShaderResourceView* pShaderResourceView);
+
+ void STDMETHODCALLTYPE UpdateSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch);
+
+ void STDMETHODCALLTYPE UpdateSubresource1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags);
+
+ HRESULT STDMETHODCALLTYPE UpdateTileMappings(
+ ID3D11Resource* pTiledResource,
+ UINT NumTiledResourceRegions,
+ const D3D11_TILED_RESOURCE_COORDINATE* pTiledResourceRegionStartCoordinates,
+ const D3D11_TILE_REGION_SIZE* pTiledResourceRegionSizes,
+ ID3D11Buffer* pTilePool,
+ UINT NumRanges,
+ const UINT* pRangeFlags,
+ const UINT* pTilePoolStartOffsets,
+ const UINT* pRangeTileCounts,
+ UINT Flags);
+
+ void STDMETHODCALLTYPE UpdateTiles(
+ ID3D11Resource* pDestTiledResource,
+ const D3D11_TILED_RESOURCE_COORDINATE* pDestTileRegionStartCoordinate,
+ const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
+ const void* pSourceTileData,
+ UINT Flags);
+
+ void STDMETHODCALLTYPE SetResourceMinLOD(
+ ID3D11Resource* pResource,
+ FLOAT MinLOD);
+
+ FLOAT STDMETHODCALLTYPE GetResourceMinLOD(
+ ID3D11Resource* pResource);
+
+ void STDMETHODCALLTYPE ResolveSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ DXGI_FORMAT Format);
+
+ void STDMETHODCALLTYPE DrawAuto();
+
+ void STDMETHODCALLTYPE Draw(
+ UINT VertexCount,
+ UINT StartVertexLocation);
+
+ void STDMETHODCALLTYPE DrawIndexed(
+ UINT IndexCount,
+ UINT StartIndexLocation,
+ INT BaseVertexLocation);
+
+ void STDMETHODCALLTYPE DrawInstanced(
+ UINT VertexCountPerInstance,
+ UINT InstanceCount,
+ UINT StartVertexLocation,
+ UINT StartInstanceLocation);
+
+ void STDMETHODCALLTYPE DrawIndexedInstanced(
+ UINT IndexCountPerInstance,
+ UINT InstanceCount,
+ UINT StartIndexLocation,
+ INT BaseVertexLocation,
+ UINT StartInstanceLocation);
+
+ void STDMETHODCALLTYPE DrawIndexedInstancedIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs);
+
+ void STDMETHODCALLTYPE DrawInstancedIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs);
+
+ void STDMETHODCALLTYPE Dispatch(
+ UINT ThreadGroupCountX,
+ UINT ThreadGroupCountY,
+ UINT ThreadGroupCountZ);
+
+ void STDMETHODCALLTYPE DispatchIndirect(
+ ID3D11Buffer* pBufferForArgs,
+ UINT AlignedByteOffsetForArgs);
+
+ void STDMETHODCALLTYPE IASetInputLayout(
+ ID3D11InputLayout* pInputLayout);
+
+ void STDMETHODCALLTYPE IASetPrimitiveTopology(
+ D3D11_PRIMITIVE_TOPOLOGY Topology);
+
+ void STDMETHODCALLTYPE IASetVertexBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppVertexBuffers,
+ const UINT* pStrides,
+ const UINT* pOffsets);
+
+ void STDMETHODCALLTYPE IASetIndexBuffer(
+ ID3D11Buffer* pIndexBuffer,
+ DXGI_FORMAT Format,
+ UINT Offset);
+
+ void STDMETHODCALLTYPE IAGetInputLayout(
+ ID3D11InputLayout** ppInputLayout);
+
+ void STDMETHODCALLTYPE IAGetPrimitiveTopology(
+ D3D11_PRIMITIVE_TOPOLOGY* pTopology);
+
+ void STDMETHODCALLTYPE IAGetVertexBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppVertexBuffers,
+ UINT* pStrides,
+ UINT* pOffsets);
+
+ void STDMETHODCALLTYPE IAGetIndexBuffer(
+ ID3D11Buffer** ppIndexBuffer,
+ DXGI_FORMAT* pFormat,
+ UINT* pOffset);
+
+ void STDMETHODCALLTYPE VSSetShader(
+ ID3D11VertexShader* pVertexShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE VSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE VSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE VSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE VSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE VSGetShader(
+ ID3D11VertexShader** ppVertexShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE VSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE VSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE VSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE VSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE HSSetShader(
+ ID3D11HullShader* pHullShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE HSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE HSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE HSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE HSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE HSGetShader(
+ ID3D11HullShader** ppHullShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE HSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE HSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE HSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE HSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE DSSetShader(
+ ID3D11DomainShader* pDomainShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE DSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE DSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE DSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE DSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE DSGetShader(
+ ID3D11DomainShader** ppDomainShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE DSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE DSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE DSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE DSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE GSSetShader(
+ ID3D11GeometryShader* pShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE GSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE GSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE GSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE GSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE GSGetShader(
+ ID3D11GeometryShader** ppGeometryShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE GSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE GSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE GSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE GSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE PSSetShader(
+ ID3D11PixelShader* pPixelShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE PSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE PSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE PSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE PSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE PSGetShader(
+ ID3D11PixelShader** ppPixelShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE PSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE PSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE PSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE PSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE CSSetShader(
+ ID3D11ComputeShader* pComputeShader,
+ ID3D11ClassInstance* const* ppClassInstances,
+ UINT NumClassInstances);
+
+ void STDMETHODCALLTYPE CSSetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ void STDMETHODCALLTYPE CSSetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE CSSetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView* const* ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE CSSetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ void STDMETHODCALLTYPE CSSetUnorderedAccessViews(
+ UINT StartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts);
+
+ void STDMETHODCALLTYPE CSGetShader(
+ ID3D11ComputeShader** ppComputeShader,
+ ID3D11ClassInstance** ppClassInstances,
+ UINT* pNumClassInstances);
+
+ void STDMETHODCALLTYPE CSGetConstantBuffers(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers);
+
+ void STDMETHODCALLTYPE CSGetConstantBuffers1(
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void STDMETHODCALLTYPE CSGetShaderResources(
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void STDMETHODCALLTYPE CSGetSamplers(
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void STDMETHODCALLTYPE CSGetUnorderedAccessViews(
+ UINT StartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView** ppUnorderedAccessViews);
+
+ void STDMETHODCALLTYPE OMSetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView);
+
+ void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts);
+
+ void STDMETHODCALLTYPE OMSetBlendState(
+ ID3D11BlendState* pBlendState,
+ const FLOAT BlendFactor[4],
+ UINT SampleMask);
+
+ void STDMETHODCALLTYPE OMSetDepthStencilState(
+ ID3D11DepthStencilState* pDepthStencilState,
+ UINT StencilRef);
+
+ void STDMETHODCALLTYPE OMGetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView** ppRenderTargetViews,
+ ID3D11DepthStencilView** ppDepthStencilView);
+
+ void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView** ppRenderTargetViews,
+ ID3D11DepthStencilView** ppDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView** ppUnorderedAccessViews);
+
+ void STDMETHODCALLTYPE OMGetBlendState(
+ ID3D11BlendState** ppBlendState,
+ FLOAT BlendFactor[4],
+ UINT* pSampleMask);
+
+ void STDMETHODCALLTYPE OMGetDepthStencilState(
+ ID3D11DepthStencilState** ppDepthStencilState,
+ UINT* pStencilRef);
+
+ void STDMETHODCALLTYPE RSSetState(
+ ID3D11RasterizerState* pRasterizerState);
+
+ void STDMETHODCALLTYPE RSSetViewports(
+ UINT NumViewports,
+ const D3D11_VIEWPORT* pViewports);
+
+ void STDMETHODCALLTYPE RSSetScissorRects(
+ UINT NumRects,
+ const D3D11_RECT* pRects);
+
+ void STDMETHODCALLTYPE RSGetState(
+ ID3D11RasterizerState** ppRasterizerState);
+
+ void STDMETHODCALLTYPE RSGetViewports(
+ UINT* pNumViewports,
+ D3D11_VIEWPORT* pViewports);
+
+ void STDMETHODCALLTYPE RSGetScissorRects(
+ UINT* pNumRects,
+ D3D11_RECT* pRects);
+
+ void STDMETHODCALLTYPE SOSetTargets(
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppSOTargets,
+ const UINT* pOffsets);
+
+ void STDMETHODCALLTYPE SOGetTargets(
+ UINT NumBuffers,
+ ID3D11Buffer** ppSOTargets);
+
+ void STDMETHODCALLTYPE SOGetTargetsWithOffsets(
+ UINT NumBuffers,
+ ID3D11Buffer** ppSOTargets,
+ UINT* pOffsets);
+
+ BOOL STDMETHODCALLTYPE IsAnnotationEnabled();
+
+ void STDMETHODCALLTYPE SetMarkerInt(
+ LPCWSTR pLabel,
+ INT Data);
+
+ void STDMETHODCALLTYPE BeginEventInt(
+ LPCWSTR pLabel,
+ INT Data);
+
+ void STDMETHODCALLTYPE EndEvent();
+
+ void STDMETHODCALLTYPE GetHardwareProtectionState(
+ BOOL* pHwProtectionEnable);
+
+ void STDMETHODCALLTYPE SetHardwareProtectionState(
+ BOOL HwProtectionEnable);
+
+ void STDMETHODCALLTYPE TransitionSurfaceLayout(
+ IDXGIVkInteropSurface* pSurface,
+ const VkImageSubresourceRange* pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout);
+
+ D3D10DeviceLock LockContext() {
+ return m_multithread.AcquireLock();
+ }
+
+ protected:
+
+ D3D11DeviceContextExt m_contextExt;
+ D3D11UserDefinedAnnotation m_annotation;
+ D3D10Multithread m_multithread;
+
+ Rc<DxvkDevice> m_device;
+ Rc<DxvkDataBuffer> m_updateBuffer;
+
+ DxvkCsChunkFlags m_csFlags;
+ DxvkCsChunkRef m_csChunk;
+
+ D3D11ContextState m_state;
+ D3D11CmdData* m_cmdData;
+
+ void ApplyInputLayout();
+
+ void ApplyPrimitiveTopology();
+
+ void ApplyBlendState();
+
+ void ApplyBlendFactor();
+
+ void ApplyDepthStencilState();
+
+ void ApplyStencilRef();
+
+ void ApplyRasterizerState();
+
+ void ApplyViewportState();
+
+ template<DxbcProgramType ShaderStage>
+ void BindShader(
+ const D3D11CommonShader* pShaderModule);
+
+ void BindFramebuffer();
+
+ void BindDrawBuffers(
+ D3D11Buffer* pBufferForArgs,
+ D3D11Buffer* pBufferForCount);
+
+ void BindVertexBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ UINT Stride);
+
+ void BindIndexBuffer(
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ DXGI_FORMAT Format);
+
+ void BindXfbBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset);
+
+ void BindConstantBuffer(
+ UINT Slot,
+ D3D11Buffer* pBuffer,
+ UINT Offset,
+ UINT Length);
+
+ void BindSampler(
+ UINT Slot,
+ D3D11SamplerState* pSampler);
+
+ void BindShaderResource(
+ UINT Slot,
+ D3D11ShaderResourceView* pResource);
+
+ void BindUnorderedAccessView(
+ UINT UavSlot,
+ D3D11UnorderedAccessView* pUav,
+ UINT CtrSlot,
+ UINT Counter);
+
+ void CopyBuffer(
+ D3D11Buffer* pDstBuffer,
+ VkDeviceSize DstOffset,
+ D3D11Buffer* pSrcBuffer,
+ VkDeviceSize SrcOffset,
+ VkDeviceSize ByteCount);
+
+ void CopyImage(
+ D3D11CommonTexture* pDstTexture,
+ const VkImageSubresourceLayers* pDstLayers,
+ VkOffset3D DstOffset,
+ D3D11CommonTexture* pSrcTexture,
+ const VkImageSubresourceLayers* pSrcLayers,
+ VkOffset3D SrcOffset,
+ VkExtent3D SrcExtent);
+
+ void DiscardBuffer(
+ ID3D11Resource* pResource);
+
+ void DiscardTexture(
+ ID3D11Resource* pResource,
+ UINT Subresource);
+
+ void UpdateImage(
+ D3D11CommonTexture* pDstTexture,
+ const VkImageSubresource* pDstSubresource,
+ VkOffset3D DstOffset,
+ VkExtent3D DstExtent,
+ DxvkBufferSlice StagingBuffer);
+
+ void SetDrawBuffers(
+ ID3D11Buffer* pBufferForArgs,
+ ID3D11Buffer* pBufferForCount);
+
+ template<DxbcProgramType ShaderStage>
+ void SetConstantBuffers(
+ D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers);
+
+ template<DxbcProgramType ShaderStage>
+ void SetConstantBuffers1(
+ D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer* const* ppConstantBuffers,
+ const UINT* pFirstConstant,
+ const UINT* pNumConstants);
+
+ template<DxbcProgramType ShaderStage>
+ void SetSamplers(
+ D3D11SamplerBindings& Bindings,
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState* const* ppSamplers);
+
+ template<DxbcProgramType ShaderStage>
+ void SetShaderResources(
+ D3D11ShaderResourceBindings& Bindings,
+ UINT StartSlot,
+ UINT NumResources,
+ ID3D11ShaderResourceView* const* ppResources);
+
+ void GetConstantBuffers(
+ const D3D11ConstantBufferBindings& Bindings,
+ UINT StartSlot,
+ UINT NumBuffers,
+ ID3D11Buffer** ppConstantBuffers,
+ UINT* pFirstConstant,
+ UINT* pNumConstants);
+
+ void GetShaderResources(
+ const D3D11ShaderResourceBindings& Bindings,
+ UINT StartSlot,
+ UINT NumViews,
+ ID3D11ShaderResourceView** ppShaderResourceViews);
+
+ void GetSamplers(
+ const D3D11SamplerBindings& Bindings,
+ UINT StartSlot,
+ UINT NumSamplers,
+ ID3D11SamplerState** ppSamplers);
+
+ void ResetState();
+
+ void RestoreState();
+
+ template<DxbcProgramType Stage>
+ void RestoreConstantBuffers(
+ D3D11ConstantBufferBindings& Bindings);
+
+ template<DxbcProgramType Stage>
+ void RestoreSamplers(
+ D3D11SamplerBindings& Bindings);
+
+ template<DxbcProgramType Stage>
+ void RestoreShaderResources(
+ D3D11ShaderResourceBindings& Bindings);
+
+ template<DxbcProgramType Stage>
+ void RestoreUnorderedAccessViews(
+ D3D11UnorderedAccessBindings& Bindings);
+
+ bool TestRtvUavHazards(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRTVs,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUAVs);
+
+ template<DxbcProgramType ShaderStage>
+ bool TestSrvHazards(
+ D3D11ShaderResourceView* pView);
+
+ template<DxbcProgramType ShaderStage, typename T>
+ void ResolveSrvHazards(
+ T* pView,
+ D3D11ShaderResourceBindings& Bindings);
+
+ template<typename T>
+ void ResolveCsSrvHazards(
+ T* pView);
+
+ template<typename T>
+ void ResolveOmSrvHazards(
+ T* pView);
+
+ bool ResolveOmRtvHazards(
+ D3D11UnorderedAccessView* pView);
+
+ void ResolveOmUavHazards(
+ D3D11RenderTargetView* pView);
+
+ bool ValidateRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView);
+
+ VkClearValue ConvertColorValue(
+ const FLOAT Color[4],
+ const DxvkFormatInfo* pFormatInfo);
+
+ DxvkDataSlice AllocUpdateBufferSlice(size_t Size);
+
+ DxvkBufferSlice AllocStagingBuffer(
+ VkDeviceSize Size);
+
+ DxvkCsChunkRef AllocCsChunk();
+
+ static void InitDefaultPrimitiveTopology(
+ DxvkInputAssemblyState* pIaState);
+
+ static void InitDefaultRasterizerState(
+ DxvkRasterizerState* pRsState);
+
+ static void InitDefaultDepthStencilState(
+ DxvkDepthStencilState* pDsState);
+
+ static void InitDefaultBlendState(
+ DxvkBlendMode* pCbState,
+ DxvkLogicOpState* pLoState,
+ DxvkMultisampleState* pMsState,
+ UINT SampleMask);
+
+ template<typename T>
+ const D3D11CommonShader* GetCommonShader(T* pShader) const {
+ return pShader != nullptr ? pShader->GetCommonShader() : nullptr;
+ }
+
+ static uint32_t GetIndirectCommandStride(const D3D11CmdDrawIndirectData* cmdData, uint32_t offset, uint32_t minStride) {
+ if (likely(cmdData->stride))
+ return cmdData->offset + cmdData->count * cmdData->stride == offset ? cmdData->stride : 0;
+
+ uint32_t stride = offset - cmdData->offset;
+ return stride >= minStride && stride <= 32 ? stride : 0;
+ }
+
+ static bool ValidateDrawBufferSize(ID3D11Buffer* pBuffer, UINT Offset, UINT Size) {
+ UINT bufferSize = 0;
+
+ if (likely(pBuffer != nullptr))
+ bufferSize = static_cast<D3D11Buffer*>(pBuffer)->Desc()->ByteWidth;
+
+ return bufferSize >= Offset + Size;
+ }
+
+ template<typename Cmd>
+ void EmitCs(Cmd&& command) {
+ m_cmdData = nullptr;
+
+ if (unlikely(!m_csChunk->push(command))) {
+ EmitCsChunk(std::move(m_csChunk));
+
+ m_csChunk = AllocCsChunk();
+ m_csChunk->push(command);
+ }
+ }
+
+ template<typename M, typename Cmd, typename... Args>
+ M* EmitCsCmd(Cmd&& command, Args&&... args) {
+ M* data = m_csChunk->pushCmd<M, Cmd, Args...>(
+ command, std::forward<Args>(args)...);
+
+ if (unlikely(!data)) {
+ EmitCsChunk(std::move(m_csChunk));
+
+ m_csChunk = AllocCsChunk();
+ data = m_csChunk->pushCmd<M, Cmd, Args...>(
+ command, std::forward<Args>(args)...);
+ }
+
+ m_cmdData = data;
+ return data;
+ }
+
+ void FlushCsChunk() {
+ if (likely(!m_csChunk->empty())) {
+ EmitCsChunk(std::move(m_csChunk));
+ m_csChunk = AllocCsChunk();
+ m_cmdData = nullptr;
+ }
+ }
+
+ virtual void EmitCsChunk(DxvkCsChunkRef&& chunk) = 0;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.cpp
new file mode 100644
index 00000000..1ac44b06
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.cpp
@@ -0,0 +1,383 @@
+#include "d3d11_context_def.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11DeferredContext::D3D11DeferredContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device,
+ UINT ContextFlags)
+ : D3D11DeviceContext(pParent, Device, GetCsChunkFlags(pParent)),
+ m_contextFlags(ContextFlags),
+ m_commandList (CreateCommandList()) {
+ ClearState();
+ }
+
+
+ D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11DeferredContext::GetType() {
+ return D3D11_DEVICE_CONTEXT_DEFERRED;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11DeferredContext::GetContextFlags() {
+ return m_contextFlags;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeferredContext::GetData(
+ ID3D11Asynchronous* pAsync,
+ void* pData,
+ UINT DataSize,
+ UINT GetDataFlags) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: GetData called on a deferred context");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::Begin(
+ ID3D11Asynchronous* pAsync) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pAsync))
+ return;
+
+ Com<D3D11Query, false> query(static_cast<D3D11Query*>(pAsync));
+
+ if (unlikely(!query->IsScoped()))
+ return;
+
+ auto entry = std::find(
+ m_queriesBegun.begin(),
+ m_queriesBegun.end(), query);
+
+ if (unlikely(entry != m_queriesBegun.end()))
+ return;
+
+ EmitCs([cQuery = query]
+ (DxvkContext* ctx) {
+ cQuery->Begin(ctx);
+ });
+
+ m_queriesBegun.push_back(std::move(query));
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::End(
+ ID3D11Asynchronous* pAsync) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pAsync))
+ return;
+
+ Com<D3D11Query, false> query(static_cast<D3D11Query*>(pAsync));
+
+ if (query->IsScoped()) {
+ auto entry = std::find(
+ m_queriesBegun.begin(),
+ m_queriesBegun.end(), query);
+
+ if (likely(entry != m_queriesBegun.end())) {
+ m_queriesBegun.erase(entry);
+ } else {
+ EmitCs([cQuery = query]
+ (DxvkContext* ctx) {
+ cQuery->Begin(ctx);
+ });
+ }
+ }
+
+ m_commandList->AddQuery(query.ptr());
+
+ EmitCs([cQuery = std::move(query)]
+ (DxvkContext* ctx) {
+ cQuery->End(ctx);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::Flush() {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: Flush called on a deferred context");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::Flush1(
+ D3D11_CONTEXT_TYPE ContextType,
+ HANDLE hEvent) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: Flush1 called on a deferred context");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Signal(
+ ID3D11Fence* pFence,
+ UINT64 Value) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: Signal called on a deferred context");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Wait(
+ ID3D11Fence* pFence,
+ UINT64 Value) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: Wait called on a deferred context");
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::ExecuteCommandList(
+ ID3D11CommandList* pCommandList,
+ BOOL RestoreContextState) {
+ D3D10DeviceLock lock = LockContext();
+
+ FlushCsChunk();
+
+ static_cast<D3D11CommandList*>(pCommandList)->EmitToCommandList(m_commandList.ptr());
+
+ if (RestoreContextState)
+ RestoreState();
+ else
+ ClearState();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeferredContext::FinishCommandList(
+ BOOL RestoreDeferredContextState,
+ ID3D11CommandList **ppCommandList) {
+ D3D10DeviceLock lock = LockContext();
+
+ FinalizeQueries();
+ FlushCsChunk();
+
+ if (ppCommandList != nullptr)
+ *ppCommandList = m_commandList.ref();
+ m_commandList = CreateCommandList();
+
+ if (RestoreDeferredContextState)
+ RestoreState();
+ else
+ ClearState();
+
+ m_mappedResources.clear();
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Map(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pResource || !pMappedResource))
+ return E_INVALIDARG;
+
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ if (MapType == D3D11_MAP_WRITE_DISCARD) {
+ D3D11DeferredContextMapEntry entry;
+
+ HRESULT status = resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER
+ ? MapBuffer(pResource, MapType, MapFlags, &entry)
+ : MapImage (pResource, Subresource, MapType, MapFlags, &entry);
+
+ if (unlikely(FAILED(status))) {
+ *pMappedResource = D3D11_MAPPED_SUBRESOURCE();
+ return status;
+ }
+
+ // Adding a new map entry actually overrides the
+ // old one in practice because the lookup function
+ // scans the array in reverse order
+ m_mappedResources.push_back(std::move(entry));
+
+ // Fill mapped resource structure
+ pMappedResource->pData = entry.MapPointer;
+ pMappedResource->RowPitch = entry.RowPitch;
+ pMappedResource->DepthPitch = entry.DepthPitch;
+ return S_OK;
+ } else if (MapType == D3D11_MAP_WRITE_NO_OVERWRITE) {
+ // The resource must be mapped with D3D11_MAP_WRITE_DISCARD
+ // before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE.
+ auto entry = FindMapEntry(pResource, Subresource);
+
+ if (unlikely(entry == m_mappedResources.rend())) {
+ *pMappedResource = D3D11_MAPPED_SUBRESOURCE();
+ return E_INVALIDARG;
+ }
+
+ // Return same memory region as earlier
+ entry->MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
+
+ pMappedResource->pData = entry->MapPointer;
+ pMappedResource->RowPitch = entry->RowPitch;
+ pMappedResource->DepthPitch = entry->DepthPitch;
+ return S_OK;
+ } else {
+ // Not allowed on deferred contexts
+ *pMappedResource = D3D11_MAPPED_SUBRESOURCE();
+ return E_INVALIDARG;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::Unmap(
+ ID3D11Resource* pResource,
+ UINT Subresource) {
+ // No-op, updates are committed in Map
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeferredContext::SwapDeviceContextState(
+ ID3DDeviceContextState* pState,
+ ID3DDeviceContextState** ppPreviousState) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11: SwapDeviceContextState called on a deferred context");
+ }
+
+
+ HRESULT D3D11DeferredContext::MapBuffer(
+ ID3D11Resource* pResource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11DeferredContextMapEntry* pMapEntry) {
+ D3D11Buffer* pBuffer = static_cast<D3D11Buffer*>(pResource);
+
+ if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
+ Logger::err("D3D11: Cannot map a device-local buffer");
+ return E_INVALIDARG;
+ }
+
+ pMapEntry->pResource = pResource;
+ pMapEntry->Subresource = 0;
+ pMapEntry->MapType = D3D11_MAP_WRITE_DISCARD;
+ pMapEntry->RowPitch = pBuffer->Desc()->ByteWidth;
+ pMapEntry->DepthPitch = pBuffer->Desc()->ByteWidth;
+
+ if (likely(m_csFlags.test(DxvkCsChunkFlag::SingleUse))) {
+ // For resources that cannot be written by the GPU,
+ // we may write to the buffer resource directly and
+ // just swap in the buffer slice as needed.
+ auto bufferSlice = pBuffer->AllocSlice();
+ pMapEntry->MapPointer = bufferSlice.mapPtr;
+
+ EmitCs([
+ cDstBuffer = pBuffer->GetBuffer(),
+ cPhysSlice = bufferSlice
+ ] (DxvkContext* ctx) {
+ ctx->invalidateBuffer(cDstBuffer, cPhysSlice);
+ });
+ } else {
+ // For GPU-writable resources, we need a data slice
+ // to perform the update operation at execution time.
+ auto dataSlice = AllocUpdateBufferSlice(pBuffer->Desc()->ByteWidth);
+ pMapEntry->MapPointer = dataSlice.ptr();
+
+ EmitCs([
+ cDstBuffer = pBuffer->GetBuffer(),
+ cDataSlice = dataSlice
+ ] (DxvkContext* ctx) {
+ DxvkBufferSliceHandle slice = cDstBuffer->allocSlice();
+ std::memcpy(slice.mapPtr, cDataSlice.ptr(), cDataSlice.length());
+ ctx->invalidateBuffer(cDstBuffer, slice);
+ });
+ }
+
+ return S_OK;
+ }
+
+
+ HRESULT D3D11DeferredContext::MapImage(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11DeferredContextMapEntry* pMapEntry) {
+ D3D11CommonTexture* pTexture = GetCommonTexture(pResource);
+
+ if (unlikely(pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) {
+ Logger::err("D3D11: Cannot map a device-local image");
+ return E_INVALIDARG;
+ }
+
+ if (unlikely(Subresource >= pTexture->CountSubresources()))
+ return E_INVALIDARG;
+
+ VkFormat packedFormat = pTexture->GetPackedFormat();
+
+ auto formatInfo = imageFormatInfo(packedFormat);
+ auto subresource = pTexture->GetSubresourceFromIndex(
+ formatInfo->aspectMask, Subresource);
+
+ VkExtent3D levelExtent = pTexture->MipLevelExtent(subresource.mipLevel);
+
+ auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
+ auto dataSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, levelExtent));
+
+ pMapEntry->pResource = pResource;
+ pMapEntry->Subresource = Subresource;
+ pMapEntry->MapType = D3D11_MAP_WRITE_DISCARD;
+ pMapEntry->RowPitch = layout.RowPitch;
+ pMapEntry->DepthPitch = layout.DepthPitch;
+ pMapEntry->MapPointer = dataSlice.mapPtr(0);
+
+ UpdateImage(pTexture, &subresource,
+ VkOffset3D { 0, 0, 0 }, levelExtent,
+ std::move(dataSlice));
+ return S_OK;
+ }
+
+
+ void D3D11DeferredContext::FinalizeQueries() {
+ for (auto& query : m_queriesBegun) {
+ m_commandList->AddQuery(query.ptr());
+
+ EmitCs([cQuery = std::move(query)]
+ (DxvkContext* ctx) {
+ cQuery->End(ctx);
+ });
+ }
+
+ m_queriesBegun.clear();
+ }
+
+
+ Com<D3D11CommandList> D3D11DeferredContext::CreateCommandList() {
+ return new D3D11CommandList(m_parent, m_contextFlags);
+ }
+
+
+ void D3D11DeferredContext::EmitCsChunk(DxvkCsChunkRef&& chunk) {
+ m_commandList->AddChunk(std::move(chunk));
+ }
+
+
+ DxvkCsChunkFlags D3D11DeferredContext::GetCsChunkFlags(
+ D3D11Device* pDevice) {
+ return pDevice->GetOptions()->dcSingleUseMode
+ ? DxvkCsChunkFlags(DxvkCsChunkFlag::SingleUse)
+ : DxvkCsChunkFlags();
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.h
new file mode 100644
index 00000000..bdfcf441
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_def.h
@@ -0,0 +1,131 @@
+#pragma once
+
+#include "d3d11_buffer.h"
+#include "d3d11_cmdlist.h"
+#include "d3d11_context.h"
+#include "d3d11_texture.h"
+
+#include <algorithm>
+#include <vector>
+
+namespace dxvk {
+
+ struct D3D11DeferredContextMapEntry {
+ Com<ID3D11Resource> pResource;
+ UINT Subresource;
+ D3D11_MAP MapType;
+ UINT RowPitch;
+ UINT DepthPitch;
+ void* MapPointer;
+ };
+
+ class D3D11DeferredContext : public D3D11DeviceContext {
+
+ public:
+
+ D3D11DeferredContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device,
+ UINT ContextFlags);
+
+ D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType();
+
+ UINT STDMETHODCALLTYPE GetContextFlags();
+
+ HRESULT STDMETHODCALLTYPE GetData(
+ ID3D11Asynchronous* pAsync,
+ void* pData,
+ UINT DataSize,
+ UINT GetDataFlags);
+
+ void STDMETHODCALLTYPE Begin(
+ ID3D11Asynchronous* pAsync);
+
+ void STDMETHODCALLTYPE End(
+ ID3D11Asynchronous* pAsync);
+
+ void STDMETHODCALLTYPE Flush();
+
+ void STDMETHODCALLTYPE Flush1(
+ D3D11_CONTEXT_TYPE ContextType,
+ HANDLE hEvent);
+
+ HRESULT STDMETHODCALLTYPE Signal(
+ ID3D11Fence* pFence,
+ UINT64 Value);
+
+ HRESULT STDMETHODCALLTYPE Wait(
+ ID3D11Fence* pFence,
+ UINT64 Value);
+
+ void STDMETHODCALLTYPE ExecuteCommandList(
+ ID3D11CommandList* pCommandList,
+ BOOL RestoreContextState);
+
+ HRESULT STDMETHODCALLTYPE FinishCommandList(
+ BOOL RestoreDeferredContextState,
+ ID3D11CommandList** ppCommandList);
+
+ HRESULT STDMETHODCALLTYPE Map(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource);
+
+ void STDMETHODCALLTYPE Unmap(
+ ID3D11Resource* pResource,
+ UINT Subresource);
+
+ void STDMETHODCALLTYPE SwapDeviceContextState(
+ ID3DDeviceContextState* pState,
+ ID3DDeviceContextState** ppPreviousState);
+
+ private:
+
+ const UINT m_contextFlags;
+
+ // Command list that we're recording
+ Com<D3D11CommandList> m_commandList;
+
+ // Info about currently mapped (sub)resources. Using a vector
+ // here is reasonable since there will usually only be a small
+ // number of mapped resources per command list.
+ std::vector<D3D11DeferredContextMapEntry> m_mappedResources;
+
+ // Begun and ended queries, will also be stored in command list
+ std::vector<Com<D3D11Query, false>> m_queriesBegun;
+
+ HRESULT MapBuffer(
+ ID3D11Resource* pResource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11DeferredContextMapEntry* pMapEntry);
+
+ HRESULT MapImage(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11DeferredContextMapEntry* pMapEntry);
+
+ void FinalizeQueries();
+
+ Com<D3D11CommandList> CreateCommandList();
+
+ void EmitCsChunk(DxvkCsChunkRef&& chunk);
+
+ static DxvkCsChunkFlags GetCsChunkFlags(
+ D3D11Device* pDevice);
+
+ auto FindMapEntry(ID3D11Resource* pResource, UINT Subresource) {
+ return std::find_if(m_mappedResources.rbegin(), m_mappedResources.rend(),
+ [pResource, Subresource] (const D3D11DeferredContextMapEntry& entry) {
+ return entry.pResource == pResource
+ && entry.Subresource == Subresource;
+ });
+ }
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.cpp
new file mode 100644
index 00000000..c892f7ef
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.cpp
@@ -0,0 +1,198 @@
+#include <vector>
+#include <utility>
+#include <cstring>
+
+#include "d3d11_device.h"
+#include "d3d11_context.h"
+#include "d3d11_cuda.h"
+
+#include "../util/log/log.h"
+
+namespace dxvk {
+
+ D3D11DeviceContextExt::D3D11DeviceContextExt(
+ D3D11DeviceContext* pContext)
+ : m_ctx(pContext) {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DeviceContextExt::AddRef() {
+ return m_ctx->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DeviceContextExt::Release() {
+ return m_ctx->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContextExt::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_ctx->QueryInterface(riid, ppvObject);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+ m_ctx->SetDrawBuffers(pBufferForArgs, nullptr);
+
+ m_ctx->EmitCs([
+ cCount = DrawCount,
+ cOffset = ByteOffsetForArgs,
+ cStride = ByteStrideForArgs
+ ] (DxvkContext* ctx) {
+ ctx->drawIndirect(cOffset, cCount, cStride);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndexedIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+ m_ctx->SetDrawBuffers(pBufferForArgs, nullptr);
+
+ m_ctx->EmitCs([
+ cCount = DrawCount,
+ cOffset = ByteOffsetForArgs,
+ cStride = ByteStrideForArgs
+ ] (DxvkContext* ctx) {
+ ctx->drawIndexedIndirect(cOffset, cCount, cStride);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+ m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount);
+
+ m_ctx->EmitCs([
+ cMaxCount = MaxDrawCount,
+ cArgOffset = ByteOffsetForArgs,
+ cCntOffset = ByteOffsetForCount,
+ cStride = ByteStrideForArgs
+ ] (DxvkContext* ctx) {
+ ctx->drawIndirectCount(cArgOffset, cCntOffset, cMaxCount, cStride);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndexedIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+ m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount);
+
+ m_ctx->EmitCs([
+ cMaxCount = MaxDrawCount,
+ cArgOffset = ByteOffsetForArgs,
+ cCntOffset = ByteOffsetForCount,
+ cStride = ByteStrideForArgs
+ ] (DxvkContext* ctx) {
+ ctx->drawIndexedIndirectCount(cArgOffset, cCntOffset, cMaxCount, cStride);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::SetDepthBoundsTest(
+ BOOL Enable,
+ FLOAT MinDepthBounds,
+ FLOAT MaxDepthBounds) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ DxvkDepthBounds db;
+ db.enableDepthBounds = Enable;
+ db.minDepthBounds = MinDepthBounds;
+ db.maxDepthBounds = MaxDepthBounds;
+
+ m_ctx->EmitCs([cDepthBounds = db] (DxvkContext* ctx) {
+ ctx->setDepthBounds(cDepthBounds);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DeviceContextExt::SetBarrierControl(
+ UINT ControlFlags) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+ DxvkBarrierControlFlags flags;
+
+ if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE)
+ flags.set(DxvkBarrierControl::IgnoreWriteAfterWrite);
+
+ if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV)
+ flags.set(DxvkBarrierControl::IgnoreGraphicsBarriers);
+
+ m_ctx->EmitCs([cFlags = flags] (DxvkContext* ctx) {
+ ctx->setBarrierControl(cFlags);
+ });
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceContextExt::LaunchCubinShaderNVX(IUnknown* hShader, uint32_t GridX, uint32_t GridY, uint32_t GridZ,
+ const void* pParams, uint32_t ParamSize, void* const* pReadResources, uint32_t NumReadResources, void* const* pWriteResources, uint32_t NumWriteResources) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ CubinShaderWrapper* cubinShader = static_cast<CubinShaderWrapper*>(hShader);
+ CubinShaderLaunchInfo launchInfo;
+
+ const uint32_t maxResources = NumReadResources + NumWriteResources;
+ launchInfo.buffers.reserve(maxResources);
+ launchInfo.images.reserve(maxResources);
+
+ for (uint32_t i = 0; i < NumReadResources; i++)
+ launchInfo.insertResource(static_cast<ID3D11Resource*>(pReadResources[i]), DxvkAccess::Read);
+
+ for (uint32_t i = 0; i < NumWriteResources; i++)
+ launchInfo.insertResource(static_cast<ID3D11Resource*>(pWriteResources[i]), DxvkAccess::Write);
+
+ launchInfo.paramSize = ParamSize;
+ launchInfo.params.resize(launchInfo.paramSize);
+ std::memcpy(launchInfo.params.data(), pParams, ParamSize);
+
+ launchInfo.cuLaunchConfig[0] = reinterpret_cast<void*>(0x01); // CU_LAUNCH_PARAM_BUFFER_POINTER
+ launchInfo.cuLaunchConfig[1] = launchInfo.params.data();
+ launchInfo.cuLaunchConfig[2] = reinterpret_cast<void*>(0x02); // CU_LAUNCH_PARAM_BUFFER_SIZE
+ launchInfo.cuLaunchConfig[3] = &launchInfo.paramSize; // yes, this actually requires a pointer to a size_t containing the parameter size
+ launchInfo.cuLaunchConfig[4] = reinterpret_cast<void*>(0x00); // CU_LAUNCH_PARAM_END
+
+ launchInfo.nvxLaunchInfo.function = cubinShader->cuFunction();
+ launchInfo.nvxLaunchInfo.gridDimX = GridX;
+ launchInfo.nvxLaunchInfo.gridDimY = GridY;
+ launchInfo.nvxLaunchInfo.gridDimZ = GridZ;
+ launchInfo.nvxLaunchInfo.blockDimX = cubinShader->blockDim().width;
+ launchInfo.nvxLaunchInfo.blockDimY = cubinShader->blockDim().height;
+ launchInfo.nvxLaunchInfo.blockDimZ = cubinShader->blockDim().depth;
+ launchInfo.nvxLaunchInfo.sharedMemBytes = 0;
+ launchInfo.nvxLaunchInfo.paramCount = 0;
+ launchInfo.nvxLaunchInfo.pParams = nullptr;
+ launchInfo.nvxLaunchInfo.extraCount = 1;
+ launchInfo.nvxLaunchInfo.pExtras = launchInfo.cuLaunchConfig.data();
+
+ launchInfo.shader = cubinShader;
+
+ /* Need to capture by value in case this gets called from a deferred context */
+ m_ctx->EmitCs([cLaunchInfo = std::move(launchInfo)] (DxvkContext* ctx) {
+ ctx->launchCuKernelNVX(cLaunchInfo.nvxLaunchInfo, cLaunchInfo.buffers, cLaunchInfo.images);
+ });
+
+ return true;
+ }
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.h
new file mode 100644
index 00000000..2109a0de
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_ext.h
@@ -0,0 +1,78 @@
+#pragma once
+
+#include "d3d11_interfaces.h"
+
+namespace dxvk {
+
+ class D3D11DeviceContext;
+
+ class D3D11DeviceContextExt : public ID3D11VkExtContext1 {
+
+ public:
+
+ D3D11DeviceContextExt(
+ D3D11DeviceContext* pContext);
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE MultiDrawIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs);
+
+ void STDMETHODCALLTYPE MultiDrawIndexedIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs);
+
+ void STDMETHODCALLTYPE MultiDrawIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs);
+
+ void STDMETHODCALLTYPE MultiDrawIndexedIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs);
+
+ void STDMETHODCALLTYPE SetDepthBoundsTest(
+ BOOL Enable,
+ FLOAT MinDepthBounds,
+ FLOAT MaxDepthBounds);
+
+ void STDMETHODCALLTYPE SetBarrierControl(
+ UINT ControlFlags);
+
+ bool STDMETHODCALLTYPE LaunchCubinShaderNVX(
+ IUnknown* hShader,
+ uint32_t GridX,
+ uint32_t GridY,
+ uint32_t GridZ,
+ const void* pParams,
+ uint32_t paramSize,
+ void* const* pReadResources,
+ uint32_t NumReadResources,
+ void* const* pWriteResources,
+ uint32_t NumWriteResources);
+
+ private:
+
+ D3D11DeviceContext* m_ctx;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.cpp
new file mode 100644
index 00000000..3bac02e7
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.cpp
@@ -0,0 +1,623 @@
+#include "d3d11_cmdlist.h"
+#include "d3d11_context_imm.h"
+#include "d3d11_device.h"
+#include "d3d11_texture.h"
+
+constexpr static uint32_t MinFlushIntervalUs = 750;
+constexpr static uint32_t IncFlushIntervalUs = 250;
+constexpr static uint32_t MaxPendingSubmits = 6;
+
+namespace dxvk {
+
+ D3D11ImmediateContext::D3D11ImmediateContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device)
+ : D3D11DeviceContext(pParent, Device, DxvkCsChunkFlag::SingleUse),
+ m_csThread(Device->createContext()),
+ m_videoContext(this, Device) {
+ EmitCs([
+ cDevice = m_device,
+ cRelaxedBarriers = pParent->GetOptions()->relaxedBarriers,
+ cIgnoreGraphicsBarriers = pParent->GetOptions()->ignoreGraphicsBarriers
+ ] (DxvkContext* ctx) {
+ ctx->beginRecording(cDevice->createCommandList());
+
+ DxvkBarrierControlFlags barrierControl;
+
+ if (cRelaxedBarriers)
+ barrierControl.set(DxvkBarrierControl::IgnoreWriteAfterWrite);
+
+ if (cIgnoreGraphicsBarriers)
+ barrierControl.set(DxvkBarrierControl::IgnoreGraphicsBarriers);
+
+ ctx->setBarrierControl(barrierControl);
+ });
+
+ ClearState();
+ }
+
+
+ D3D11ImmediateContext::~D3D11ImmediateContext() {
+ Flush();
+ SynchronizeCsThread();
+ SynchronizeDevice();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::QueryInterface(REFIID riid, void** ppvObject) {
+ if (riid == __uuidof(ID3D11VideoContext)) {
+ *ppvObject = ref(&m_videoContext);
+ return S_OK;
+ }
+
+ return D3D11DeviceContext::QueryInterface(riid, ppvObject);
+ }
+
+
+ D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11ImmediateContext::GetType() {
+ return D3D11_DEVICE_CONTEXT_IMMEDIATE;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11ImmediateContext::GetContextFlags() {
+ return 0;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::GetData(
+ ID3D11Asynchronous* pAsync,
+ void* pData,
+ UINT DataSize,
+ UINT GetDataFlags) {
+ if (!pAsync || (DataSize && !pData))
+ return E_INVALIDARG;
+
+ // Check whether the data size is actually correct
+ if (DataSize && DataSize != pAsync->GetDataSize())
+ return E_INVALIDARG;
+
+ // Passing a non-null pData is actually allowed if
+ // DataSize is 0, but we should ignore that pointer
+ pData = DataSize ? pData : nullptr;
+
+ // Get query status directly from the query object
+ auto query = static_cast<D3D11Query*>(pAsync);
+ HRESULT hr = query->GetData(pData, GetDataFlags);
+
+ // If we're likely going to spin on the asynchronous object,
+ // flush the context so that we're keeping the GPU busy.
+ if (hr == S_FALSE) {
+ // Don't mark the event query as stalling if the app does
+ // not intend to spin on it. This reduces flushes on End.
+ if (!(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH))
+ query->NotifyStall();
+
+ // Ignore the DONOTFLUSH flag here as some games will spin
+ // on queries without ever flushing the context otherwise.
+ FlushImplicit(FALSE);
+ }
+
+ return hr;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::Begin(ID3D11Asynchronous* pAsync) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pAsync))
+ return;
+
+ auto query = static_cast<D3D11Query*>(pAsync);
+
+ if (unlikely(!query->DoBegin()))
+ return;
+
+ EmitCs([cQuery = Com<D3D11Query, false>(query)]
+ (DxvkContext* ctx) {
+ cQuery->Begin(ctx);
+ });
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::End(ID3D11Asynchronous* pAsync) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pAsync))
+ return;
+
+ auto query = static_cast<D3D11Query*>(pAsync);
+
+ if (unlikely(!query->DoEnd())) {
+ EmitCs([cQuery = Com<D3D11Query, false>(query)]
+ (DxvkContext* ctx) {
+ cQuery->Begin(ctx);
+ });
+ }
+
+ EmitCs([cQuery = Com<D3D11Query, false>(query)]
+ (DxvkContext* ctx) {
+ cQuery->End(ctx);
+ });
+
+ if (unlikely(query->IsEvent())) {
+ query->NotifyEnd();
+ query->IsStalling()
+ ? Flush()
+ : FlushImplicit(TRUE);
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
+ Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::Flush1(
+ D3D11_CONTEXT_TYPE ContextType,
+ HANDLE hEvent) {
+ m_parent->FlushInitContext();
+
+ if (hEvent)
+ SignalEvent(hEvent);
+
+ D3D10DeviceLock lock = LockContext();
+
+ if (m_csIsBusy || !m_csChunk->empty()) {
+ // Add commands to flush the threaded
+ // context, then flush the command list
+ EmitCs([] (DxvkContext* ctx) {
+ ctx->flushCommandList();
+ });
+
+ FlushCsChunk();
+
+ // Reset flush timer used for implicit flushes
+ m_lastFlush = dxvk::high_resolution_clock::now();
+ m_csIsBusy = false;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Signal(
+ ID3D11Fence* pFence,
+ UINT64 Value) {
+ Logger::err("D3D11ImmediateContext::Signal: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Wait(
+ ID3D11Fence* pFence,
+ UINT64 Value) {
+ Logger::err("D3D11ImmediateContext::Wait: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList(
+ ID3D11CommandList* pCommandList,
+ BOOL RestoreContextState) {
+ D3D10DeviceLock lock = LockContext();
+
+ auto commandList = static_cast<D3D11CommandList*>(pCommandList);
+
+ // Flush any outstanding commands so that
+ // we don't mess up the execution order
+ FlushCsChunk();
+
+ // As an optimization, flush everything if the
+ // number of pending draw calls is high enough.
+ FlushImplicit(FALSE);
+
+ // Dispatch command list to the CS thread and
+ // restore the immediate context's state
+ commandList->EmitToCsThread(&m_csThread);
+
+ if (RestoreContextState)
+ RestoreState();
+ else
+ ClearState();
+
+ // Mark CS thread as busy so that subsequent
+ // flush operations get executed correctly.
+ m_csIsBusy = true;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::FinishCommandList(
+ BOOL RestoreDeferredContextState,
+ ID3D11CommandList **ppCommandList) {
+ InitReturnPtr(ppCommandList);
+
+ Logger::err("D3D11: FinishCommandList called on immediate context");
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Map(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
+ D3D10DeviceLock lock = LockContext();
+
+ if (unlikely(!pResource))
+ return E_INVALIDARG;
+
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ HRESULT hr;
+
+ if (likely(resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER)) {
+ hr = MapBuffer(
+ static_cast<D3D11Buffer*>(pResource),
+ MapType, MapFlags, pMappedResource);
+ } else {
+ hr = MapImage(
+ GetCommonTexture(pResource),
+ Subresource, MapType, MapFlags,
+ pMappedResource);
+ }
+
+ if (unlikely(FAILED(hr)))
+ *pMappedResource = D3D11_MAPPED_SUBRESOURCE();
+
+ return hr;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::Unmap(
+ ID3D11Resource* pResource,
+ UINT Subresource) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ if (unlikely(resourceDim != D3D11_RESOURCE_DIMENSION_BUFFER)) {
+ D3D10DeviceLock lock = LockContext();
+ UnmapImage(GetCommonTexture(pResource), Subresource);
+ }
+ }
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::UpdateSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch) {
+ FlushImplicit(FALSE);
+
+ D3D11DeviceContext::UpdateSubresource(
+ pDstResource, DstSubresource, pDstBox,
+ pSrcData, SrcRowPitch, SrcDepthPitch);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::UpdateSubresource1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags) {
+ FlushImplicit(FALSE);
+
+ D3D11DeviceContext::UpdateSubresource1(
+ pDstResource, DstSubresource, pDstBox,
+ pSrcData, SrcRowPitch, SrcDepthPitch,
+ CopyFlags);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::OMSetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView) {
+ FlushImplicit(TRUE);
+
+ D3D11DeviceContext::OMSetRenderTargets(
+ NumViews, ppRenderTargetViews, pDepthStencilView);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::OMSetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts) {
+ FlushImplicit(TRUE);
+
+ D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(
+ NumRTVs, ppRenderTargetViews, pDepthStencilView,
+ UAVStartSlot, NumUAVs, ppUnorderedAccessViews,
+ pUAVInitialCounts);
+ }
+
+
+ HRESULT D3D11ImmediateContext::MapBuffer(
+ D3D11Buffer* pResource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
+ if (unlikely(!pMappedResource))
+ return E_INVALIDARG;
+
+ if (unlikely(pResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) {
+ Logger::err("D3D11: Cannot map a device-local buffer");
+ return E_INVALIDARG;
+ }
+
+ if (MapType == D3D11_MAP_WRITE_DISCARD) {
+ // Allocate a new backing slice for the buffer and set
+ // it as the 'new' mapped slice. This assumes that the
+ // only way to invalidate a buffer is by mapping it.
+ auto physSlice = pResource->DiscardSlice();
+ pMappedResource->pData = physSlice.mapPtr;
+ pMappedResource->RowPitch = pResource->Desc()->ByteWidth;
+ pMappedResource->DepthPitch = pResource->Desc()->ByteWidth;
+
+ EmitCs([
+ cBuffer = pResource->GetBuffer(),
+ cBufferSlice = physSlice
+ ] (DxvkContext* ctx) {
+ ctx->invalidateBuffer(cBuffer, cBufferSlice);
+ });
+
+ return S_OK;
+ } else {
+ // Wait until the resource is no longer in use
+ if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
+ if (!WaitForResource(pResource->GetBuffer(), MapType, MapFlags))
+ return DXGI_ERROR_WAS_STILL_DRAWING;
+ }
+
+ // Use map pointer from previous map operation. This
+ // way we don't have to synchronize with the CS thread
+ // if the map mode is D3D11_MAP_WRITE_NO_OVERWRITE.
+ DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice();
+
+ pMappedResource->pData = physSlice.mapPtr;
+ pMappedResource->RowPitch = pResource->Desc()->ByteWidth;
+ pMappedResource->DepthPitch = pResource->Desc()->ByteWidth;
+ return S_OK;
+ }
+ }
+
+
+ HRESULT D3D11ImmediateContext::MapImage(
+ D3D11CommonTexture* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
+ const Rc<DxvkImage> mappedImage = pResource->GetImage();
+ const Rc<DxvkBuffer> mappedBuffer = pResource->GetMappedBuffer(Subresource);
+
+ auto mapMode = pResource->GetMapMode();
+
+ if (unlikely(mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) {
+ Logger::err("D3D11: Cannot map a device-local image");
+ return E_INVALIDARG;
+ }
+
+ if (unlikely(Subresource >= pResource->CountSubresources()))
+ return E_INVALIDARG;
+
+ if (likely(pMappedResource != nullptr)) {
+ // Resources with an unknown memory layout cannot return a pointer
+ if (pResource->Desc()->Usage == D3D11_USAGE_DEFAULT
+ && pResource->Desc()->TextureLayout == D3D11_TEXTURE_LAYOUT_UNDEFINED)
+ return E_INVALIDARG;
+ } else {
+ if (pResource->Desc()->Usage != D3D11_USAGE_DEFAULT)
+ return E_INVALIDARG;
+ }
+
+ VkFormat packedFormat = m_parent->LookupPackedFormat(
+ pResource->Desc()->Format, pResource->GetFormatMode()).Format;
+
+ auto formatInfo = imageFormatInfo(packedFormat);
+ void* mapPtr;
+
+ if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
+ // Wait for the resource to become available
+ if (!WaitForResource(mappedImage, MapType, MapFlags))
+ return DXGI_ERROR_WAS_STILL_DRAWING;
+
+ // Query the subresource's memory layout and hope that
+ // the application respects the returned pitch values.
+ mapPtr = mappedImage->mapPtr(0);
+ } else {
+ if (MapType == D3D11_MAP_WRITE_DISCARD) {
+ // We do not have to preserve the contents of the
+ // buffer if the entire image gets discarded.
+ DxvkBufferSliceHandle physSlice = pResource->DiscardSlice(Subresource);
+
+ EmitCs([
+ cImageBuffer = mappedBuffer,
+ cBufferSlice = physSlice
+ ] (DxvkContext* ctx) {
+ ctx->invalidateBuffer(cImageBuffer, cBufferSlice);
+ });
+
+ mapPtr = physSlice.mapPtr;
+ } else {
+ bool wait = MapType != D3D11_MAP_WRITE_NO_OVERWRITE
+ || mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
+
+ // Wait for mapped buffer to become available
+ if (wait && !WaitForResource(mappedBuffer, MapType, MapFlags))
+ return DXGI_ERROR_WAS_STILL_DRAWING;
+
+ mapPtr = pResource->GetMappedSlice(Subresource).mapPtr;
+ }
+ }
+
+ // Mark the given subresource as mapped
+ pResource->SetMapType(Subresource, MapType);
+
+ if (pMappedResource) {
+ auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource);
+ pMappedResource->pData = reinterpret_cast<char*>(mapPtr) + layout.Offset;
+ pMappedResource->RowPitch = layout.RowPitch;
+ pMappedResource->DepthPitch = layout.DepthPitch;
+ }
+
+ return S_OK;
+ }
+
+
+ void D3D11ImmediateContext::UnmapImage(
+ D3D11CommonTexture* pResource,
+ UINT Subresource) {
+ D3D11_MAP mapType = pResource->GetMapType(Subresource);
+ pResource->SetMapType(Subresource, D3D11_MAP(~0u));
+
+ if (mapType == D3D11_MAP(~0u)
+ || mapType == D3D11_MAP_READ)
+ return;
+
+ if (pResource->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) {
+ // Now that data has been written into the buffer,
+ // we need to copy its contents into the image
+ VkImageAspectFlags aspectMask = imageFormatInfo(pResource->GetPackedFormat())->aspectMask;
+ VkImageSubresource subresource = pResource->GetSubresourceFromIndex(aspectMask, Subresource);
+
+ UpdateImage(pResource, &subresource, VkOffset3D { 0, 0, 0 },
+ pResource->MipLevelExtent(subresource.mipLevel),
+ DxvkBufferSlice(pResource->GetMappedBuffer(Subresource)));
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ImmediateContext::SwapDeviceContextState(
+ ID3DDeviceContextState* pState,
+ ID3DDeviceContextState** ppPreviousState) {
+ InitReturnPtr(ppPreviousState);
+
+ if (!pState)
+ return;
+
+ Com<D3D11DeviceContextState> oldState = std::move(m_stateObject);
+ Com<D3D11DeviceContextState> newState = static_cast<D3D11DeviceContextState*>(pState);
+
+ if (oldState == nullptr)
+ oldState = new D3D11DeviceContextState(m_parent);
+
+ if (ppPreviousState)
+ *ppPreviousState = oldState.ref();
+
+ m_stateObject = newState;
+
+ oldState->SetState(m_state);
+ newState->GetState(m_state);
+
+ RestoreState();
+ }
+
+
+ void D3D11ImmediateContext::SynchronizeCsThread() {
+ D3D10DeviceLock lock = LockContext();
+
+ // Dispatch current chunk so that all commands
+ // recorded prior to this function will be run
+ FlushCsChunk();
+
+ if (m_csThread.isBusy())
+ m_csThread.synchronize();
+ }
+
+
+ void D3D11ImmediateContext::SynchronizeDevice() {
+ m_device->waitForIdle();
+ }
+
+
+ bool D3D11ImmediateContext::WaitForResource(
+ const Rc<DxvkResource>& Resource,
+ D3D11_MAP MapType,
+ UINT MapFlags) {
+ // Determine access type to wait for based on map mode
+ DxvkAccess access = MapType == D3D11_MAP_READ
+ ? DxvkAccess::Write
+ : DxvkAccess::Read;
+
+ // Wait for the any pending D3D11 command to be executed
+ // on the CS thread so that we can determine whether the
+ // resource is currently in use or not.
+ if (!Resource->isInUse(access))
+ SynchronizeCsThread();
+
+ if (Resource->isInUse(access)) {
+ if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) {
+ // We don't have to wait, but misbehaving games may
+ // still try to spin on `Map` until the resource is
+ // idle, so we should flush pending commands
+ FlushImplicit(FALSE);
+ return false;
+ } else {
+ // Make sure pending commands using the resource get
+ // executed on the the GPU if we have to wait for it
+ Flush();
+ SynchronizeCsThread();
+
+ Resource->waitIdle(access);
+ }
+ }
+
+ return true;
+ }
+
+
+ void D3D11ImmediateContext::EmitCsChunk(DxvkCsChunkRef&& chunk) {
+ m_csThread.dispatchChunk(std::move(chunk));
+ m_csIsBusy = true;
+ }
+
+
+ void D3D11ImmediateContext::FlushImplicit(BOOL StrongHint) {
+ // Flush only if the GPU is about to go idle, in
+ // order to keep the number of submissions low.
+ uint32_t pending = m_device->pendingSubmissions();
+
+ if (StrongHint || pending <= MaxPendingSubmits) {
+ auto now = dxvk::high_resolution_clock::now();
+
+ uint32_t delay = MinFlushIntervalUs
+ + IncFlushIntervalUs * pending;
+
+ // Prevent flushing too often in short intervals.
+ if (now - m_lastFlush >= std::chrono::microseconds(delay))
+ Flush();
+ }
+ }
+
+
+ void D3D11ImmediateContext::SignalEvent(HANDLE hEvent) {
+#ifndef DXVK_NATIVE
+ uint64_t value = ++m_eventCount;
+
+ if (m_eventSignal == nullptr)
+ m_eventSignal = new sync::CallbackFence();
+
+ m_eventSignal->setCallback(value, [hEvent] {
+ SetEvent(hEvent);
+ });
+
+ EmitCs([
+ cSignal = m_eventSignal,
+ cValue = value
+ ] (DxvkContext* ctx) {
+ ctx->signal(cSignal, cValue);
+ });
+#endif
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.h
new file mode 100644
index 00000000..8a638da1
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_imm.h
@@ -0,0 +1,166 @@
+#pragma once
+
+#include "../util/util_time.h"
+
+#ifndef DXVK_NATIVE
+#include "../util/sync/sync_signal.h"
+#endif
+
+#include "d3d11_context.h"
+#include "d3d11_state_object.h"
+#include "d3d11_video.h"
+
+namespace dxvk {
+
+ class D3D11Buffer;
+ class D3D11CommonTexture;
+
+ class D3D11ImmediateContext : public D3D11DeviceContext {
+ friend class D3D11SwapChain;
+ friend class D3D11VideoContext;
+ public:
+
+ D3D11ImmediateContext(
+ D3D11Device* pParent,
+ const Rc<DxvkDevice>& Device);
+ ~D3D11ImmediateContext();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType();
+
+ UINT STDMETHODCALLTYPE GetContextFlags();
+
+ HRESULT STDMETHODCALLTYPE GetData(
+ ID3D11Asynchronous* pAsync,
+ void* pData,
+ UINT DataSize,
+ UINT GetDataFlags);
+
+ void STDMETHODCALLTYPE Begin(
+ ID3D11Asynchronous* pAsync);
+
+ void STDMETHODCALLTYPE End(
+ ID3D11Asynchronous* pAsync);
+
+ void STDMETHODCALLTYPE Flush();
+
+ void STDMETHODCALLTYPE Flush1(
+ D3D11_CONTEXT_TYPE ContextType,
+ HANDLE hEvent);
+
+ HRESULT STDMETHODCALLTYPE Signal(
+ ID3D11Fence* pFence,
+ UINT64 Value);
+
+ HRESULT STDMETHODCALLTYPE Wait(
+ ID3D11Fence* pFence,
+ UINT64 Value);
+
+ void STDMETHODCALLTYPE ExecuteCommandList(
+ ID3D11CommandList* pCommandList,
+ BOOL RestoreContextState);
+
+ HRESULT STDMETHODCALLTYPE FinishCommandList(
+ BOOL RestoreDeferredContextState,
+ ID3D11CommandList **ppCommandList);
+
+ HRESULT STDMETHODCALLTYPE Map(
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource);
+
+ void STDMETHODCALLTYPE Unmap(
+ ID3D11Resource* pResource,
+ UINT Subresource);
+
+ void STDMETHODCALLTYPE UpdateSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch);
+
+ void STDMETHODCALLTYPE UpdateSubresource1(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags);
+
+ void STDMETHODCALLTYPE OMSetRenderTargets(
+ UINT NumViews,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView);
+
+ void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews(
+ UINT NumRTVs,
+ ID3D11RenderTargetView* const* ppRenderTargetViews,
+ ID3D11DepthStencilView* pDepthStencilView,
+ UINT UAVStartSlot,
+ UINT NumUAVs,
+ ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
+ const UINT* pUAVInitialCounts);
+
+ void STDMETHODCALLTYPE SwapDeviceContextState(
+ ID3DDeviceContextState* pState,
+ ID3DDeviceContextState** ppPreviousState);
+
+ void SynchronizeCsThread();
+
+ private:
+
+ DxvkCsThread m_csThread;
+ bool m_csIsBusy = false;
+
+#ifndef DXVK_NATIVE
+ Rc<sync::CallbackFence> m_eventSignal;
+#endif
+ uint64_t m_eventCount = 0;
+
+ dxvk::high_resolution_clock::time_point m_lastFlush
+ = dxvk::high_resolution_clock::now();
+
+ D3D11VideoContext m_videoContext;
+ Com<D3D11DeviceContextState> m_stateObject;
+
+ HRESULT MapBuffer(
+ D3D11Buffer* pResource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource);
+
+ HRESULT MapImage(
+ D3D11CommonTexture* pResource,
+ UINT Subresource,
+ D3D11_MAP MapType,
+ UINT MapFlags,
+ D3D11_MAPPED_SUBRESOURCE* pMappedResource);
+
+ void UnmapImage(
+ D3D11CommonTexture* pResource,
+ UINT Subresource);
+
+ void SynchronizeDevice();
+
+ bool WaitForResource(
+ const Rc<DxvkResource>& Resource,
+ D3D11_MAP MapType,
+ UINT MapFlags);
+
+ void EmitCsChunk(DxvkCsChunkRef&& chunk);
+
+ void FlushImplicit(BOOL StrongHint);
+
+ void SignalEvent(HANDLE hEvent);
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_state.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_state.h
new file mode 100644
index 00000000..eca2a3c9
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_context_state.h
@@ -0,0 +1,187 @@
+#pragma once
+
+#include <array>
+
+#include "d3d11_buffer.h"
+#include "d3d11_input_layout.h"
+#include "d3d11_query.h"
+#include "d3d11_sampler.h"
+#include "d3d11_shader.h"
+#include "d3d11_state.h"
+#include "d3d11_view_dsv.h"
+#include "d3d11_view_rtv.h"
+#include "d3d11_view_srv.h"
+#include "d3d11_view_uav.h"
+
+namespace dxvk {
+
+ struct D3D11ConstantBufferBinding {
+ Com<D3D11Buffer> buffer = nullptr;
+ UINT constantOffset = 0;
+ UINT constantCount = 0;
+ UINT constantBound = 0;
+ };
+
+ using D3D11ConstantBufferBindings = std::array<
+ D3D11ConstantBufferBinding, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>;
+
+
+ using D3D11SamplerBindings = std::array<
+ D3D11SamplerState*, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT>;
+
+
+ struct D3D11ShaderResourceBindings {
+ std::array<Com<D3D11ShaderResourceView>, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> views = { };
+ DxvkBindingSet<D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> hazardous = { };
+ };
+
+
+ using D3D11UnorderedAccessBindings = std::array<
+ Com<D3D11UnorderedAccessView>, D3D11_1_UAV_SLOT_COUNT>;
+
+
+ struct D3D11ContextStateVS {
+ Com<D3D11VertexShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ };
+
+
+ struct D3D11ContextStateHS {
+ Com<D3D11HullShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ };
+
+
+ struct D3D11ContextStateDS {
+ Com<D3D11DomainShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ };
+
+
+ struct D3D11ContextStateGS {
+ Com<D3D11GeometryShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ };
+
+
+ struct D3D11ContextStatePS {
+ Com<D3D11PixelShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ D3D11UnorderedAccessBindings unorderedAccessViews = { };
+ };
+
+
+ struct D3D11ContextStateCS {
+ Com<D3D11ComputeShader> shader = nullptr;
+ D3D11ConstantBufferBindings constantBuffers = { };
+ D3D11SamplerBindings samplers = { };
+ D3D11ShaderResourceBindings shaderResources = { };
+ D3D11UnorderedAccessBindings unorderedAccessViews = { };
+
+ DxvkBindingSet<D3D11_1_UAV_SLOT_COUNT> uavMask = { };
+ };
+
+
+ struct D3D11VertexBufferBinding {
+ Com<D3D11Buffer> buffer = nullptr;
+ UINT offset = 0;
+ UINT stride = 0;
+ };
+
+
+ struct D3D11IndexBufferBinding {
+ Com<D3D11Buffer> buffer = nullptr;
+ UINT offset = 0;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ };
+
+
+ struct D3D11ContextStateID {
+ Com<D3D11Buffer> argBuffer = nullptr;
+ Com<D3D11Buffer> cntBuffer = nullptr;
+ };
+
+
+ struct D3D11ContextStateIA {
+ Com<D3D11InputLayout> inputLayout = nullptr;
+ D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
+
+ std::array<D3D11VertexBufferBinding, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> vertexBuffers = { };
+ D3D11IndexBufferBinding indexBuffer = { };
+ };
+
+
+ struct D3D11ContextStateOM {
+ std::array<Com<D3D11RenderTargetView, false>, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews = { };
+ Com<D3D11DepthStencilView, false> depthStencilView = { };
+
+ D3D11BlendState* cbState = nullptr;
+ D3D11DepthStencilState* dsState = nullptr;
+
+ FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ UINT sampleMask = 0xFFFFFFFFu;
+ UINT stencilRef = 0u;
+
+ UINT maxRtv = 0u;
+ UINT maxUav = 0u;
+ };
+
+
+ struct D3D11ContextStateRS {
+ uint32_t numViewports = 0;
+ uint32_t numScissors = 0;
+
+ std::array<D3D11_VIEWPORT, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports = { };
+ std::array<D3D11_RECT, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors = { };
+
+ D3D11RasterizerState* state = nullptr;
+ };
+
+
+ struct D3D11ContextSoTarget {
+ Com<D3D11Buffer> buffer = nullptr;
+ UINT offset = 0;
+ };
+
+
+ struct D3D11ContextStateSO {
+ std::array<D3D11ContextSoTarget, D3D11_SO_BUFFER_SLOT_COUNT> targets = { };
+ };
+
+
+ struct D3D11ContextStatePR {
+ Com<D3D11Query> predicateObject = nullptr;
+ BOOL predicateValue = FALSE;
+ };
+
+
+ /**
+ * \brief Context state
+ */
+ struct D3D11ContextState {
+ D3D11ContextStateCS cs;
+ D3D11ContextStateDS ds;
+ D3D11ContextStateGS gs;
+ D3D11ContextStateHS hs;
+ D3D11ContextStatePS ps;
+ D3D11ContextStateVS vs;
+
+ D3D11ContextStateID id;
+ D3D11ContextStateIA ia;
+ D3D11ContextStateOM om;
+ D3D11ContextStateRS rs;
+ D3D11ContextStateSO so;
+ D3D11ContextStatePR pr;
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.cpp
new file mode 100644
index 00000000..4a31d347
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.cpp
@@ -0,0 +1,51 @@
+#include "d3d11_cuda.h"
+
+namespace dxvk {
+
+ CubinShaderWrapper::CubinShaderWrapper(const Rc<dxvk::DxvkDevice>& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim)
+ : m_dxvkDevice(dxvkDevice), m_module(cuModule), m_function(cuFunction), m_blockDim(blockDim) { };
+
+
+ CubinShaderWrapper::~CubinShaderWrapper() {
+ VkDevice vkDevice = m_dxvkDevice->handle();
+ m_dxvkDevice->vkd()->vkDestroyCuFunctionNVX(vkDevice, m_function, nullptr);
+ m_dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, m_module, nullptr);
+ };
+
+
+ HRESULT STDMETHODCALLTYPE CubinShaderWrapper::QueryInterface(REFIID riid, void **ppvObject) {
+ if (riid == __uuidof(IUnknown)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("CubinShaderWrapper::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void CubinShaderLaunchInfo::insertResource(ID3D11Resource* pResource, DxvkAccessFlags access) {
+ auto img = GetCommonTexture(pResource);
+ auto buf = GetCommonBuffer(pResource);
+
+ if (img)
+ insertUniqueResource(images, img->GetImage(), access);
+ if (buf)
+ insertUniqueResource(buffers, buf->GetBuffer(), access);
+ }
+
+
+ template<typename T>
+ void CubinShaderLaunchInfo::insertUniqueResource(std::vector<std::pair<T, DxvkAccessFlags>>& list, const T& resource, DxvkAccessFlags access) {
+ for (auto& entry : list) {
+ if (entry.first == resource) {
+ entry.second.set(access);
+ return;
+ }
+ }
+
+ list.push_back({ resource, access });
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.h
new file mode 100644
index 00000000..a9fcdf4b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_cuda.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <utility>
+#include <vector>
+
+#include "../dxvk/dxvk_resource.h"
+
+#include "../util/com/com_guid.h"
+#include "../util/com/com_object.h"
+
+#include "d3d11_buffer.h"
+#include "d3d11_texture.h"
+
+namespace dxvk {
+
+ class CubinShaderWrapper : public ComObject<IUnknown> {
+
+ public:
+
+ CubinShaderWrapper(const Rc<dxvk::DxvkDevice>& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim);
+ ~CubinShaderWrapper();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+
+ VkCuModuleNVX cuModule() const {
+ return m_module;
+ }
+
+ VkCuFunctionNVX cuFunction() const {
+ return m_function;
+ }
+
+ VkExtent3D blockDim() const {
+ return m_blockDim;
+ }
+
+ private:
+
+ Rc<DxvkDevice> m_dxvkDevice;
+ VkCuModuleNVX m_module;
+ VkCuFunctionNVX m_function;
+ VkExtent3D m_blockDim;
+
+ };
+
+
+ struct CubinShaderLaunchInfo {
+
+ CubinShaderLaunchInfo() = default;
+
+ CubinShaderLaunchInfo(CubinShaderLaunchInfo&& other) {
+ shader = std::move(other.shader);
+ params = std::move(other.params);
+ paramSize = std::move(other.paramSize);
+ nvxLaunchInfo = std::move(other.nvxLaunchInfo);
+ cuLaunchConfig = other.cuLaunchConfig;
+ buffers = std::move(other.buffers);
+ images = std::move(other.images);
+ other.cuLaunchConfig[1] = nullptr;
+ other.cuLaunchConfig[3] = nullptr;
+ other.nvxLaunchInfo.pExtras = nullptr;
+ // fix-up internally-pointing pointers
+ cuLaunchConfig[1] = params.data();
+ cuLaunchConfig[3] = &paramSize;
+ nvxLaunchInfo.pExtras = cuLaunchConfig.data();
+ }
+
+ Com<CubinShaderWrapper> shader;
+ std::vector<uint8_t> params;
+ size_t paramSize;
+ VkCuLaunchInfoNVX nvxLaunchInfo = { VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX };
+ std::array<void*, 5> cuLaunchConfig;
+
+ std::vector<std::pair<Rc<DxvkBuffer>, DxvkAccessFlags>> buffers;
+ std::vector<std::pair<Rc<DxvkImage>, DxvkAccessFlags>> images;
+
+ void insertResource(ID3D11Resource* pResource, DxvkAccessFlags access);
+
+ template<typename T>
+ static void insertUniqueResource(std::vector<std::pair<T, DxvkAccessFlags>>& list, const T& resource, DxvkAccessFlags access);
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.cpp
new file mode 100644
index 00000000..b095e5ea
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.cpp
@@ -0,0 +1,166 @@
+#include "d3d11_depth_stencil.h"
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ D3D11DepthStencilState::D3D11DepthStencilState(
+ D3D11Device* device,
+ const D3D11_DEPTH_STENCIL_DESC& desc)
+ : D3D11StateObject<ID3D11DepthStencilState>(device),
+ m_desc(desc), m_d3d10(this) {
+ m_state.enableDepthTest = desc.DepthEnable;
+ m_state.enableDepthWrite = desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL;
+ m_state.enableStencilTest = desc.StencilEnable;
+ m_state.depthCompareOp = DecodeCompareOp(desc.DepthFunc);
+ m_state.stencilOpFront = DecodeStencilOpState(desc.FrontFace, desc);
+ m_state.stencilOpBack = DecodeStencilOpState(desc.BackFace, desc);
+ }
+
+
+ D3D11DepthStencilState::~D3D11DepthStencilState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DepthStencilState::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11DepthStencilState)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10DepthStencilState)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11DepthStencilState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DepthStencilState::GetDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ void D3D11DepthStencilState::BindToContext(const Rc<DxvkContext>& ctx) {
+ ctx->setDepthStencilState(m_state);
+ }
+
+
+ HRESULT D3D11DepthStencilState::NormalizeDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) {
+ if (pDesc->DepthEnable) {
+ pDesc->DepthEnable = TRUE;
+
+ if (!ValidateDepthFunc(pDesc->DepthFunc))
+ return E_INVALIDARG;
+ } else {
+ pDesc->DepthFunc = D3D11_COMPARISON_LESS;
+ pDesc->DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ }
+
+ if (!ValidateDepthWriteMask(pDesc->DepthWriteMask))
+ return E_INVALIDARG;
+
+ if (pDesc->StencilEnable) {
+ pDesc->StencilEnable = TRUE;
+
+ if (!ValidateStencilFunc(pDesc->FrontFace.StencilFunc)
+ || !ValidateStencilOp(pDesc->FrontFace.StencilFailOp)
+ || !ValidateStencilOp(pDesc->FrontFace.StencilDepthFailOp)
+ || !ValidateStencilOp(pDesc->FrontFace.StencilPassOp))
+ return E_INVALIDARG;
+
+ if (!ValidateStencilFunc(pDesc->BackFace.StencilFunc)
+ || !ValidateStencilOp(pDesc->BackFace.StencilFailOp)
+ || !ValidateStencilOp(pDesc->BackFace.StencilDepthFailOp)
+ || !ValidateStencilOp(pDesc->BackFace.StencilPassOp))
+ return E_INVALIDARG;
+ } else {
+ D3D11_DEPTH_STENCILOP_DESC stencilOp;
+ stencilOp.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ stencilOp.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ stencilOp.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ stencilOp.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ pDesc->FrontFace = stencilOp;
+ pDesc->BackFace = stencilOp;
+ pDesc->StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+ pDesc->StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+ }
+
+ return S_OK;
+ }
+
+
+ VkStencilOpState D3D11DepthStencilState::DecodeStencilOpState(
+ const D3D11_DEPTH_STENCILOP_DESC& StencilDesc,
+ const D3D11_DEPTH_STENCIL_DESC& Desc) const {
+ VkStencilOpState result;
+ result.failOp = VK_STENCIL_OP_KEEP;
+ result.passOp = VK_STENCIL_OP_KEEP;
+ result.depthFailOp = VK_STENCIL_OP_KEEP;
+ result.compareOp = VK_COMPARE_OP_ALWAYS;
+ result.compareMask = Desc.StencilReadMask;
+ result.writeMask = Desc.StencilWriteMask;
+ result.reference = 0;
+
+ if (Desc.StencilEnable) {
+ result.failOp = DecodeStencilOp(StencilDesc.StencilFailOp);
+ result.passOp = DecodeStencilOp(StencilDesc.StencilPassOp);
+ result.depthFailOp = DecodeStencilOp(StencilDesc.StencilDepthFailOp);
+ result.compareOp = DecodeCompareOp(StencilDesc.StencilFunc);
+ }
+
+ return result;
+ }
+
+
+ VkStencilOp D3D11DepthStencilState::DecodeStencilOp(D3D11_STENCIL_OP Op) const {
+ switch (Op) {
+ case D3D11_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;
+ case D3D11_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;
+ case D3D11_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;
+ case D3D11_STENCIL_OP_INCR_SAT: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
+ case D3D11_STENCIL_OP_DECR_SAT: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
+ case D3D11_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
+ case D3D11_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
+ case D3D11_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ default: return VK_STENCIL_OP_KEEP;
+ }
+ }
+
+
+ bool D3D11DepthStencilState::ValidateDepthFunc(D3D11_COMPARISON_FUNC Comparison) {
+ return Comparison >= D3D11_COMPARISON_NEVER
+ && Comparison <= D3D11_COMPARISON_ALWAYS;
+ }
+
+
+ bool D3D11DepthStencilState::ValidateStencilFunc(D3D11_COMPARISON_FUNC Comparison) {
+ return Comparison >= D3D11_COMPARISON_NEVER
+ && Comparison <= D3D11_COMPARISON_ALWAYS;
+ }
+
+
+ bool D3D11DepthStencilState::ValidateStencilOp(D3D11_STENCIL_OP StencilOp) {
+ return StencilOp >= D3D11_STENCIL_OP_KEEP
+ && StencilOp <= D3D11_STENCIL_OP_DECR;
+ }
+
+
+ bool D3D11DepthStencilState::ValidateDepthWriteMask(D3D11_DEPTH_WRITE_MASK Mask) {
+ return Mask == D3D11_DEPTH_WRITE_MASK_ZERO
+ || Mask == D3D11_DEPTH_WRITE_MASK_ALL;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.h
new file mode 100644
index 00000000..6311259f
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_depth_stencil.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_depth_stencil.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_util.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11DepthStencilState : public D3D11StateObject<ID3D11DepthStencilState> {
+
+ public:
+
+ using DescType = D3D11_DEPTH_STENCIL_DESC;
+
+ D3D11DepthStencilState(
+ D3D11Device* device,
+ const D3D11_DEPTH_STENCIL_DESC& desc);
+ ~D3D11DepthStencilState();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_DEPTH_STENCIL_DESC* pDesc) final;
+
+ void BindToContext(
+ const Rc<DxvkContext>& ctx);
+
+ D3D10DepthStencilState* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT NormalizeDesc(
+ D3D11_DEPTH_STENCIL_DESC* pDesc);
+
+ private:
+
+ D3D11_DEPTH_STENCIL_DESC m_desc;
+ DxvkDepthStencilState m_state;
+ D3D10DepthStencilState m_d3d10;
+
+ VkStencilOpState DecodeStencilOpState(
+ const D3D11_DEPTH_STENCILOP_DESC& StencilDesc,
+ const D3D11_DEPTH_STENCIL_DESC& Desc) const;
+
+ VkStencilOp DecodeStencilOp(
+ D3D11_STENCIL_OP Op) const;
+
+ static bool ValidateDepthFunc(
+ D3D11_COMPARISON_FUNC Comparison);
+
+ static bool ValidateStencilFunc(
+ D3D11_COMPARISON_FUNC Comparison);
+
+ static bool ValidateStencilOp(
+ D3D11_STENCIL_OP StencilOp);
+
+ static bool ValidateDepthWriteMask(
+ D3D11_DEPTH_WRITE_MASK Mask);
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.cpp
new file mode 100644
index 00000000..d55c36ba
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.cpp
@@ -0,0 +1,3447 @@
+#include <algorithm>
+#include <cstring>
+
+#include "../dxgi/dxgi_monitor.h"
+#include "../dxgi/dxgi_swapchain.h"
+
+#include "../dxvk/dxvk_adapter.h"
+#include "../dxvk/dxvk_instance.h"
+
+#include "d3d11_buffer.h"
+#include "d3d11_class_linkage.h"
+#include "d3d11_context_def.h"
+#include "d3d11_context_imm.h"
+#include "d3d11_device.h"
+#include "d3d11_input_layout.h"
+#include "d3d11_interop.h"
+#include "d3d11_query.h"
+#include "d3d11_resource.h"
+#include "d3d11_sampler.h"
+#include "d3d11_shader.h"
+#include "d3d11_state_object.h"
+#include "d3d11_swapchain.h"
+#include "d3d11_texture.h"
+#include "d3d11_video.h"
+
+namespace dxvk {
+
+ constexpr uint32_t D3D11DXGIDevice::DefaultFrameLatency;
+
+
+
+ D3D11Device::D3D11Device(
+ D3D11DXGIDevice* pContainer,
+ D3D_FEATURE_LEVEL FeatureLevel,
+ UINT FeatureFlags)
+ : m_container (pContainer),
+ m_featureLevel (FeatureLevel),
+ m_featureFlags (FeatureFlags),
+ m_dxvkDevice (pContainer->GetDXVKDevice()),
+ m_dxvkAdapter (m_dxvkDevice->adapter()),
+ m_d3d11Formats (m_dxvkAdapter),
+ m_d3d11Options (m_dxvkDevice->instance()->config(), m_dxvkDevice),
+ m_dxbcOptions (m_dxvkDevice, m_d3d11Options) {
+ m_initializer = new D3D11Initializer(this);
+ m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
+ m_d3d10Device = new D3D10Device(this, m_context.ptr());
+ }
+
+
+ D3D11Device::~D3D11Device() {
+ delete m_d3d10Device;
+ m_context = nullptr;
+ delete m_initializer;
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11Device::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11Device::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::QueryInterface(REFIID riid, void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateBuffer(
+ const D3D11_BUFFER_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Buffer** ppBuffer) {
+ InitReturnPtr(ppBuffer);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_BUFFER_DESC desc = *pDesc;
+ HRESULT hr = D3D11Buffer::NormalizeBufferProperties(&desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppBuffer)
+ return S_FALSE;
+
+ try {
+ const Com<D3D11Buffer> buffer = new D3D11Buffer(this, &desc);
+ m_initializer->InitBuffer(buffer.ptr(), pInitialData);
+ *ppBuffer = buffer.ref();
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture1D(
+ const D3D11_TEXTURE1D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture1D** ppTexture1D) {
+ InitReturnPtr(ppTexture1D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_TEXTURE_DESC desc;
+ desc.Width = pDesc->Width;
+ desc.Height = 1;
+ desc.Depth = 1;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.ArraySize = pDesc->ArraySize;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 };
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
+
+ HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppTexture1D)
+ return S_FALSE;
+
+ try {
+ const Com<D3D11Texture1D> texture = new D3D11Texture1D(this, &desc);
+ m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
+ *ppTexture1D = texture.ref();
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D(
+ const D3D11_TEXTURE2D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture2D** ppTexture2D) {
+ InitReturnPtr(ppTexture2D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_TEXTURE2D_DESC1 desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.ArraySize = pDesc->ArraySize;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = pDesc->SampleDesc;
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
+
+ ID3D11Texture2D1* texture2D = nullptr;
+ HRESULT hr = CreateTexture2D1(&desc, pInitialData, ppTexture2D ? &texture2D : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppTexture2D = texture2D;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D1(
+ const D3D11_TEXTURE2D_DESC1* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture2D1** ppTexture2D) {
+ InitReturnPtr(ppTexture2D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_TEXTURE_DESC desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.Depth = 1;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.ArraySize = pDesc->ArraySize;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = pDesc->SampleDesc;
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = pDesc->TextureLayout;
+
+ HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppTexture2D)
+ return S_FALSE;
+
+ try {
+ Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &desc);
+ m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
+ *ppTexture2D = texture.ref();
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D(
+ const D3D11_TEXTURE3D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture3D** ppTexture3D) {
+ InitReturnPtr(ppTexture3D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_TEXTURE3D_DESC1 desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.Depth = pDesc->Depth;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.Format = pDesc->Format;
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
+
+ ID3D11Texture3D1* texture3D = nullptr;
+ HRESULT hr = CreateTexture3D1(&desc, pInitialData, ppTexture3D ? &texture3D : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppTexture3D = texture3D;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D1(
+ const D3D11_TEXTURE3D_DESC1* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture3D1** ppTexture3D) {
+ InitReturnPtr(ppTexture3D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_TEXTURE_DESC desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.Depth = pDesc->Depth;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.ArraySize = 1;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 };
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = pDesc->TextureLayout;
+
+ HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppTexture3D)
+ return S_FALSE;
+
+ try {
+ Com<D3D11Texture3D> texture = new D3D11Texture3D(this, &desc);
+ m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
+ *ppTexture3D = texture.ref();
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ ID3D11ShaderResourceView** ppSRView) {
+ InitReturnPtr(ppSRView);
+
+ uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC1 desc = pDesc
+ ? D3D11ShaderResourceView::PromoteDesc(pDesc, plane)
+ : D3D11_SHADER_RESOURCE_VIEW_DESC1();
+
+ ID3D11ShaderResourceView1* view = nullptr;
+
+ HRESULT hr = CreateShaderResourceView1(pResource,
+ pDesc ? &desc : nullptr,
+ ppSRView ? &view : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppSRView = view;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView1(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
+ ID3D11ShaderResourceView1** ppSRView) {
+ InitReturnPtr(ppSRView);
+
+ if (!pResource)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ // The description is optional. If omitted, we'll create
+ // a view that covers all subresources of the image.
+ D3D11_SHADER_RESOURCE_VIEW_DESC1 desc;
+
+ if (!pDesc) {
+ if (FAILED(D3D11ShaderResourceView::GetDescFromResource(pResource, &desc)))
+ return E_INVALIDARG;
+ } else {
+ desc = *pDesc;
+
+ if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc)))
+ return E_INVALIDARG;
+ }
+
+ uint32_t plane = D3D11ShaderResourceView::GetPlaneSlice(&desc);
+
+ if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format, plane)) {
+ Logger::err(str::format("D3D11: Cannot create shader resource view:",
+ "\n Resource type: ", resourceDesc.Dim,
+ "\n Resource usage: ", resourceDesc.BindFlags,
+ "\n Resource format: ", resourceDesc.Format,
+ "\n View format: ", desc.Format,
+ "\n View plane: ", plane));
+ return E_INVALIDARG;
+ }
+
+ if (!ppSRView)
+ return S_FALSE;
+
+ try {
+ *ppSRView = ref(new D3D11ShaderResourceView(this, pResource, &desc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ ID3D11UnorderedAccessView** ppUAView) {
+ InitReturnPtr(ppUAView);
+
+ uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc = pDesc
+ ? D3D11UnorderedAccessView::PromoteDesc(pDesc, plane)
+ : D3D11_UNORDERED_ACCESS_VIEW_DESC1();
+
+ ID3D11UnorderedAccessView1* view = nullptr;
+
+ HRESULT hr = CreateUnorderedAccessView1(pResource,
+ pDesc ? &desc : nullptr,
+ ppUAView ? &view : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppUAView = view;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView1(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
+ ID3D11UnorderedAccessView1** ppUAView) {
+ InitReturnPtr(ppUAView);
+
+ if (!pResource)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ // The description is optional. If omitted, we'll create
+ // a view that covers all subresources of the image.
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc;
+
+ if (!pDesc) {
+ if (FAILED(D3D11UnorderedAccessView::GetDescFromResource(pResource, &desc)))
+ return E_INVALIDARG;
+ } else {
+ desc = *pDesc;
+
+ if (FAILED(D3D11UnorderedAccessView::NormalizeDesc(pResource, &desc)))
+ return E_INVALIDARG;
+ }
+
+ uint32_t plane = D3D11UnorderedAccessView::GetPlaneSlice(&desc);
+
+ if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format, plane)) {
+ Logger::err(str::format("D3D11: Cannot create unordered access view:",
+ "\n Resource type: ", resourceDesc.Dim,
+ "\n Resource usage: ", resourceDesc.BindFlags,
+ "\n Resource format: ", resourceDesc.Format,
+ "\n View format: ", desc.Format,
+ "\n View plane: ", plane));
+ return E_INVALIDARG;
+ }
+
+ if (!ppUAView)
+ return S_FALSE;
+
+ try {
+ auto uav = new D3D11UnorderedAccessView(this, pResource, &desc);
+ m_initializer->InitUavCounter(uav);
+ *ppUAView = ref(uav);
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView(
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
+ ID3D11RenderTargetView** ppRTView) {
+ InitReturnPtr(ppRTView);
+
+ uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN);
+
+ D3D11_RENDER_TARGET_VIEW_DESC1 desc = pDesc
+ ? D3D11RenderTargetView::PromoteDesc(pDesc, plane)
+ : D3D11_RENDER_TARGET_VIEW_DESC1();
+
+ ID3D11RenderTargetView1* view = nullptr;
+
+ HRESULT hr = CreateRenderTargetView1(pResource,
+ pDesc ? &desc : nullptr,
+ ppRTView ? &view : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppRTView = view;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView1(
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc,
+ ID3D11RenderTargetView1** ppRTView) {
+ InitReturnPtr(ppRTView);
+
+ if (!pResource)
+ return E_INVALIDARG;
+
+ // DXVK only supports render target views for image resources
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ Logger::warn("D3D11: Cannot create render target view for a buffer");
+ return S_OK; // It is required to run Battlefield 3 and Battlefield 4.
+ }
+
+ // The view description is optional. If not defined, it
+ // will use the resource's format and all array layers.
+ D3D11_RENDER_TARGET_VIEW_DESC1 desc;
+
+ if (!pDesc) {
+ if (FAILED(D3D11RenderTargetView::GetDescFromResource(pResource, &desc)))
+ return E_INVALIDARG;
+ } else {
+ desc = *pDesc;
+
+ if (FAILED(D3D11RenderTargetView::NormalizeDesc(pResource, &desc)))
+ return E_INVALIDARG;
+ }
+
+ uint32_t plane = D3D11RenderTargetView::GetPlaneSlice(&desc);
+
+ if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format, plane)) {
+ Logger::err(str::format("D3D11: Cannot create render target view:",
+ "\n Resource type: ", resourceDesc.Dim,
+ "\n Resource usage: ", resourceDesc.BindFlags,
+ "\n Resource format: ", resourceDesc.Format,
+ "\n View format: ", desc.Format,
+ "\n View plane: ", plane));
+ return E_INVALIDARG;
+ }
+
+ if (!ppRTView)
+ return S_FALSE;
+
+ try {
+ *ppRTView = ref(new D3D11RenderTargetView(this, pResource, &desc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilView(
+ ID3D11Resource* pResource,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
+ ID3D11DepthStencilView** ppDepthStencilView) {
+ InitReturnPtr(ppDepthStencilView);
+
+ if (pResource == nullptr)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ // The view description is optional. If not defined, it
+ // will use the resource's format and all array layers.
+ D3D11_DEPTH_STENCIL_VIEW_DESC desc;
+
+ if (pDesc == nullptr) {
+ if (FAILED(D3D11DepthStencilView::GetDescFromResource(pResource, &desc)))
+ return E_INVALIDARG;
+ } else {
+ desc = *pDesc;
+
+ if (FAILED(D3D11DepthStencilView::NormalizeDesc(pResource, &desc)))
+ return E_INVALIDARG;
+ }
+
+ if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format, 0)) {
+ Logger::err(str::format("D3D11: Cannot create depth-stencil view:",
+ "\n Resource type: ", resourceDesc.Dim,
+ "\n Resource usage: ", resourceDesc.BindFlags,
+ "\n Resource format: ", resourceDesc.Format,
+ "\n View format: ", desc.Format));
+ return E_INVALIDARG;
+ }
+
+ if (ppDepthStencilView == nullptr)
+ return S_FALSE;
+
+ try {
+ *ppDepthStencilView = ref(new D3D11DepthStencilView(this, pResource, &desc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateInputLayout(
+ const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
+ UINT NumElements,
+ const void* pShaderBytecodeWithInputSignature,
+ SIZE_T BytecodeLength,
+ ID3D11InputLayout** ppInputLayout) {
+ InitReturnPtr(ppInputLayout);
+
+ if (pInputElementDescs == nullptr)
+ return E_INVALIDARG;
+
+ try {
+ DxbcReader dxbcReader(reinterpret_cast<const char*>(
+ pShaderBytecodeWithInputSignature), BytecodeLength);
+ DxbcModule dxbcModule(dxbcReader);
+
+ const Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
+
+ uint32_t attrMask = 0;
+ uint32_t bindMask = 0;
+
+ std::array<DxvkVertexAttribute, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> attrList;
+ std::array<DxvkVertexBinding, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> bindList;
+
+ for (uint32_t i = 0; i < NumElements; i++) {
+ const DxbcSgnEntry* entry = inputSignature->find(
+ pInputElementDescs[i].SemanticName,
+ pInputElementDescs[i].SemanticIndex, 0);
+
+ if (entry == nullptr) {
+ Logger::debug(str::format(
+ "D3D11Device: No such vertex shader semantic: ",
+ pInputElementDescs[i].SemanticName,
+ pInputElementDescs[i].SemanticIndex));
+ }
+
+ // Create vertex input attribute description
+ DxvkVertexAttribute attrib;
+ attrib.location = entry != nullptr ? entry->registerId : 0;
+ attrib.binding = pInputElementDescs[i].InputSlot;
+ attrib.format = LookupFormat(pInputElementDescs[i].Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
+ attrib.offset = pInputElementDescs[i].AlignedByteOffset;
+
+ // The application may choose to let the implementation
+ // generate the exact vertex layout. In that case we'll
+ // pack attributes on the same binding in the order they
+ // are declared, aligning each attribute to four bytes.
+ const DxvkFormatInfo* formatInfo = imageFormatInfo(attrib.format);
+ VkDeviceSize alignment = std::min<VkDeviceSize>(formatInfo->elementSize, 4);
+
+ if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) {
+ attrib.offset = 0;
+
+ for (uint32_t j = 1; j <= i; j++) {
+ const DxvkVertexAttribute& prev = attrList.at(i - j);
+
+ if (prev.binding == attrib.binding) {
+ attrib.offset = align(prev.offset + imageFormatInfo(prev.format)->elementSize, alignment);
+ break;
+ }
+ }
+ } else if (attrib.offset & (alignment - 1))
+ return E_INVALIDARG;
+
+ attrList.at(i) = attrib;
+
+ // Create vertex input binding description. The
+ // stride is dynamic state in D3D11 and will be
+ // set by D3D11DeviceContext::IASetVertexBuffers.
+ DxvkVertexBinding binding;
+ binding.binding = pInputElementDescs[i].InputSlot;
+ binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
+ binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
+ ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
+
+ // Check if the binding was already defined. If so, the
+ // parameters must be identical (namely, the input rate).
+ bool bindingDefined = false;
+
+ for (uint32_t j = 0; j < i; j++) {
+ uint32_t bindingId = attrList.at(j).binding;
+
+ if (binding.binding == bindingId) {
+ bindingDefined = true;
+
+ if (binding.inputRate != bindList.at(bindingId).inputRate) {
+ Logger::err(str::format(
+ "D3D11Device: Conflicting input rate for binding ",
+ binding.binding));
+ return E_INVALIDARG;
+ }
+ }
+ }
+
+ if (!bindingDefined)
+ bindList.at(binding.binding) = binding;
+
+ if (entry != nullptr) {
+ attrMask |= 1u << i;
+ bindMask |= 1u << binding.binding;
+ }
+ }
+
+ // Compact the attribute and binding lists to filter
+ // out attributes and bindings not used by the shader
+ uint32_t attrCount = CompactSparseList(attrList.data(), attrMask);
+ uint32_t bindCount = CompactSparseList(bindList.data(), bindMask);
+
+ // Check if there are any semantics defined in the
+ // shader that are not included in the current input
+ // layout.
+ for (auto i = inputSignature->begin(); i != inputSignature->end(); i++) {
+ bool found = i->systemValue != DxbcSystemValue::None;
+
+ for (uint32_t j = 0; j < attrCount && !found; j++)
+ found = attrList.at(j).location == i->registerId;
+
+ if (!found) {
+ Logger::warn(str::format(
+ "D3D11Device: Vertex input '",
+ i->semanticName, i->semanticIndex,
+ "' not defined by input layout"));
+ }
+ }
+
+ // Create the actual input layout object
+ // if the application requests it.
+ if (ppInputLayout != nullptr) {
+ *ppInputLayout = ref(
+ new D3D11InputLayout(this,
+ attrCount, attrList.data(),
+ bindCount, bindList.data()));
+ }
+
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateVertexShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11VertexShader** ppVertexShader) {
+ InitReturnPtr(ppVertexShader);
+ D3D11CommonShader module;
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_VERTEX_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage,
+ &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppVertexShader)
+ return S_FALSE;
+
+ *ppVertexShader = ref(new D3D11VertexShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11GeometryShader** ppGeometryShader) {
+ InitReturnPtr(ppGeometryShader);
+ D3D11CommonShader module;
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage,
+ &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppGeometryShader)
+ return S_FALSE;
+
+ *ppGeometryShader = ref(new D3D11GeometryShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShaderWithStreamOutput(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
+ UINT NumEntries,
+ const UINT* pBufferStrides,
+ UINT NumStrides,
+ UINT RasterizedStream,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11GeometryShader** ppGeometryShader) {
+ InitReturnPtr(ppGeometryShader);
+ D3D11CommonShader module;
+
+ if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback)
+ return DXGI_ERROR_INVALID_CALL;
+
+ // Zero-init some counterss so that we can increment
+ // them while walking over the stream output entries
+ DxbcXfbInfo xfb = { };
+
+ for (uint32_t i = 0; i < NumEntries; i++) {
+ const D3D11_SO_DECLARATION_ENTRY* so = &pSODeclaration[i];
+
+ if (so->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT)
+ return E_INVALIDARG;
+
+ if (so->SemanticName != nullptr) {
+ if (so->Stream >= D3D11_SO_BUFFER_SLOT_COUNT
+ || so->StartComponent >= 4
+ || so->ComponentCount < 1
+ || so->ComponentCount > 4)
+ return E_INVALIDARG;
+
+ DxbcXfbEntry* entry = &xfb.entries[xfb.entryCount++];
+ entry->semanticName = so->SemanticName;
+ entry->semanticIndex = so->SemanticIndex;
+ entry->componentIndex = so->StartComponent;
+ entry->componentCount = so->ComponentCount;
+ entry->streamId = so->Stream;
+ entry->bufferId = so->OutputSlot;
+ entry->offset = xfb.strides[so->OutputSlot];
+ }
+
+ xfb.strides[so->OutputSlot] += so->ComponentCount * sizeof(uint32_t);
+ }
+
+ // If necessary, override the buffer strides
+ for (uint32_t i = 0; i < NumStrides; i++)
+ xfb.strides[i] = pBufferStrides[i];
+
+ // Set stream to rasterize, if any
+ xfb.rasterizedStream = -1;
+
+ if (RasterizedStream != D3D11_SO_NO_RASTERIZED_STREAM)
+ Logger::err("D3D11: CreateGeometryShaderWithStreamOutput: Rasterized stream not supported");
+
+ // Compute hash from both the xfb info and the source
+ // code, because both influence the generated code
+ DxbcXfbInfo hashXfb = xfb;
+
+ std::vector<Sha1Data> chunks = {{
+ { pShaderBytecode, BytecodeLength },
+ { &hashXfb, sizeof(hashXfb) },
+ }};
+
+ for (uint32_t i = 0; i < hashXfb.entryCount; i++) {
+ const char* semantic = hashXfb.entries[i].semanticName;
+
+ if (semantic) {
+ chunks.push_back({ semantic, std::strlen(semantic) });
+ hashXfb.entries[i].semanticName = nullptr;
+ }
+ }
+
+ Sha1Hash hash = Sha1Hash::compute(chunks.size(), chunks.data());
+
+ // Create the actual shader module
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = &xfb;
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage,
+ &moduleInfo);
+
+ if (FAILED(hr))
+ return E_INVALIDARG;
+
+ if (!ppGeometryShader)
+ return S_FALSE;
+
+ *ppGeometryShader = ref(new D3D11GeometryShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreatePixelShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11PixelShader** ppPixelShader) {
+ InitReturnPtr(ppPixelShader);
+ D3D11CommonShader module;
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_FRAGMENT_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage,
+ &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppPixelShader)
+ return S_FALSE;
+
+ *ppPixelShader = ref(new D3D11PixelShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateHullShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11HullShader** ppHullShader) {
+ InitReturnPtr(ppHullShader);
+ D3D11CommonShader module;
+
+ DxbcTessInfo tessInfo;
+ tessInfo.maxTessFactor = float(m_d3d11Options.maxTessFactor);
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ if (tessInfo.maxTessFactor >= 8.0f)
+ moduleInfo.tess = &tessInfo;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppHullShader)
+ return S_FALSE;
+
+ *ppHullShader = ref(new D3D11HullShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDomainShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11DomainShader** ppDomainShader) {
+ InitReturnPtr(ppDomainShader);
+ D3D11CommonShader module;
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (ppDomainShader == nullptr)
+ return S_FALSE;
+
+ *ppDomainShader = ref(new D3D11DomainShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateComputeShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11ComputeShader** ppComputeShader) {
+ InitReturnPtr(ppComputeShader);
+ D3D11CommonShader module;
+
+ DxbcModuleInfo moduleInfo;
+ moduleInfo.options = m_dxbcOptions;
+ moduleInfo.tess = nullptr;
+ moduleInfo.xfb = nullptr;
+
+ Sha1Hash hash = Sha1Hash::compute(
+ pShaderBytecode, BytecodeLength);
+
+ HRESULT hr = CreateShaderModule(&module,
+ DxvkShaderKey(VK_SHADER_STAGE_COMPUTE_BIT, hash),
+ pShaderBytecode, BytecodeLength, pClassLinkage,
+ &moduleInfo);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppComputeShader)
+ return S_FALSE;
+
+ *ppComputeShader = ref(new D3D11ComputeShader(this, module));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) {
+ *ppLinkage = ref(new D3D11ClassLinkage(this));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState(
+ const D3D11_BLEND_DESC* pBlendStateDesc,
+ ID3D11BlendState** ppBlendState) {
+ InitReturnPtr(ppBlendState);
+
+ if (!pBlendStateDesc)
+ return E_INVALIDARG;
+
+ D3D11_BLEND_DESC1 desc = D3D11BlendState::PromoteDesc(pBlendStateDesc);
+
+ if (FAILED(D3D11BlendState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (ppBlendState != nullptr) {
+ *ppBlendState = m_bsStateObjects.Create(this, desc);
+ return S_OK;
+ } return S_FALSE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState1(
+ const D3D11_BLEND_DESC1* pBlendStateDesc,
+ ID3D11BlendState1** ppBlendState) {
+ InitReturnPtr(ppBlendState);
+
+ if (!pBlendStateDesc)
+ return E_INVALIDARG;
+
+ D3D11_BLEND_DESC1 desc = *pBlendStateDesc;
+
+ if (FAILED(D3D11BlendState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (ppBlendState != nullptr) {
+ *ppBlendState = m_bsStateObjects.Create(this, desc);
+ return S_OK;
+ } return S_FALSE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilState(
+ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
+ ID3D11DepthStencilState** ppDepthStencilState) {
+ InitReturnPtr(ppDepthStencilState);
+
+ if (!pDepthStencilDesc)
+ return E_INVALIDARG;
+
+ D3D11_DEPTH_STENCIL_DESC desc = *pDepthStencilDesc;
+
+ if (FAILED(D3D11DepthStencilState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (ppDepthStencilState != nullptr) {
+ *ppDepthStencilState = m_dsStateObjects.Create(this, desc);
+ return S_OK;
+ } return S_FALSE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateRasterizerState(
+ const D3D11_RASTERIZER_DESC* pRasterizerDesc,
+ ID3D11RasterizerState** ppRasterizerState) {
+ InitReturnPtr(ppRasterizerState);
+
+ if (!pRasterizerDesc)
+ return E_INVALIDARG;
+
+ D3D11_RASTERIZER_DESC2 desc = D3D11RasterizerState::PromoteDesc(pRasterizerDesc);
+
+ if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (!ppRasterizerState)
+ return S_FALSE;
+
+ *ppRasterizerState = m_rsStateObjects.Create(this, desc);
+ return S_OK;
+ }
+
+
+ HRESULT D3D11Device::CreateRasterizerState1(
+ const D3D11_RASTERIZER_DESC1* pRasterizerDesc,
+ ID3D11RasterizerState1** ppRasterizerState) {
+ InitReturnPtr(ppRasterizerState);
+
+ if (!pRasterizerDesc)
+ return E_INVALIDARG;
+
+ D3D11_RASTERIZER_DESC2 desc = D3D11RasterizerState::PromoteDesc(pRasterizerDesc);
+
+ if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (!ppRasterizerState)
+ return S_FALSE;
+
+ *ppRasterizerState = m_rsStateObjects.Create(this, desc);
+ return S_OK;
+ }
+
+
+ HRESULT D3D11Device::CreateRasterizerState2(
+ const D3D11_RASTERIZER_DESC2* pRasterizerDesc,
+ ID3D11RasterizerState2** ppRasterizerState) {
+ InitReturnPtr(ppRasterizerState);
+
+ if (!pRasterizerDesc)
+ return E_INVALIDARG;
+
+ D3D11_RASTERIZER_DESC2 desc = *pRasterizerDesc;
+
+ if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (desc.ConservativeRaster != D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF
+ && !m_dxvkDevice->extensions().extConservativeRasterization)
+ return E_INVALIDARG;
+
+ if (!ppRasterizerState)
+ return S_FALSE;
+
+ *ppRasterizerState = m_rsStateObjects.Create(this, desc);
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateSamplerState(
+ const D3D11_SAMPLER_DESC* pSamplerDesc,
+ ID3D11SamplerState** ppSamplerState) {
+ InitReturnPtr(ppSamplerState);
+
+ if (pSamplerDesc == nullptr)
+ return E_INVALIDARG;
+
+ D3D11_SAMPLER_DESC desc = *pSamplerDesc;
+
+ if (FAILED(D3D11SamplerState::NormalizeDesc(&desc)))
+ return E_INVALIDARG;
+
+ if (ppSamplerState == nullptr)
+ return S_FALSE;
+
+ try {
+ *ppSamplerState = m_samplerObjects.Create(this, desc);
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
+ const D3D11_QUERY_DESC* pQueryDesc,
+ ID3D11Query** ppQuery) {
+ InitReturnPtr(ppQuery);
+
+ if (!pQueryDesc)
+ return E_INVALIDARG;
+
+ D3D11_QUERY_DESC1 desc;
+ desc.Query = pQueryDesc->Query;
+ desc.MiscFlags = pQueryDesc->MiscFlags;
+ desc.ContextType = D3D11_CONTEXT_TYPE_ALL;
+
+ ID3D11Query1* query = nullptr;
+ HRESULT hr = CreateQuery1(&desc, ppQuery ? &query : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ *ppQuery = query;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery1(
+ const D3D11_QUERY_DESC1* pQueryDesc,
+ ID3D11Query1** ppQuery) {
+ InitReturnPtr(ppQuery);
+
+ if (!pQueryDesc)
+ return E_INVALIDARG;
+
+ HRESULT hr = D3D11Query::ValidateDesc(pQueryDesc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppQuery)
+ return S_FALSE;
+
+ try {
+ *ppQuery = ref(new D3D11Query(this, *pQueryDesc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
+ const D3D11_QUERY_DESC* pPredicateDesc,
+ ID3D11Predicate** ppPredicate) {
+ InitReturnPtr(ppPredicate);
+
+ if (!pPredicateDesc)
+ return E_INVALIDARG;
+
+ D3D11_QUERY_DESC1 desc;
+ desc.Query = pPredicateDesc->Query;
+ desc.MiscFlags = pPredicateDesc->MiscFlags;
+ desc.ContextType = D3D11_CONTEXT_TYPE_ALL;
+
+ if (desc.Query != D3D11_QUERY_OCCLUSION_PREDICATE) {
+ Logger::warn(str::format("D3D11: Unhandled predicate type: ", pPredicateDesc->Query));
+ return E_INVALIDARG;
+ }
+
+ if (!ppPredicate)
+ return S_FALSE;
+
+ try {
+ *ppPredicate = D3D11Query::AsPredicate(
+ ref(new D3D11Query(this, desc)));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateCounter(
+ const D3D11_COUNTER_DESC* pCounterDesc,
+ ID3D11Counter** ppCounter) {
+ InitReturnPtr(ppCounter);
+
+ Logger::err(str::format("D3D11: Unsupported counter: ", pCounterDesc->Counter));
+ return E_INVALIDARG;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext(
+ UINT ContextFlags,
+ ID3D11DeviceContext** ppDeferredContext) {
+ *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext1(
+ UINT ContextFlags,
+ ID3D11DeviceContext1** ppDeferredContext) {
+ *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext2(
+ UINT ContextFlags,
+ ID3D11DeviceContext2** ppDeferredContext) {
+ *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext3(
+ UINT ContextFlags,
+ ID3D11DeviceContext3** ppDeferredContext) {
+ *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeviceContextState(
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ REFIID EmulatedInterface,
+ D3D_FEATURE_LEVEL* pChosenFeatureLevel,
+ ID3DDeviceContextState** ppContextState) {
+ InitReturnPtr(ppContextState);
+
+ if (!pFeatureLevels || FeatureLevels == 0)
+ return E_INVALIDARG;
+
+ if (EmulatedInterface != __uuidof(ID3D10Device)
+ && EmulatedInterface != __uuidof(ID3D10Device1)
+ && EmulatedInterface != __uuidof(ID3D11Device)
+ && EmulatedInterface != __uuidof(ID3D11Device1))
+ return E_INVALIDARG;
+
+ UINT flId;
+ for (flId = 0; flId < FeatureLevels; flId++) {
+ if (CheckFeatureLevelSupport(m_dxvkDevice->instance(), m_dxvkAdapter, pFeatureLevels[flId]))
+ break;
+ }
+
+ if (flId == FeatureLevels)
+ return E_INVALIDARG;
+
+ if (pFeatureLevels[flId] > m_featureLevel)
+ m_featureLevel = pFeatureLevels[flId];
+
+ if (pChosenFeatureLevel)
+ *pChosenFeatureLevel = pFeatureLevels[flId];
+
+ if (!ppContextState)
+ return S_FALSE;
+
+ *ppContextState = ref(new D3D11DeviceContextState(this));
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CreateFence(
+ UINT64 InitialValue,
+ D3D11_FENCE_FLAG Flags,
+ REFIID ReturnedInterface,
+ void** ppFence) {
+ InitReturnPtr(ppFence);
+
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11Device::CreateFence: Not implemented");
+
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::ReadFromSubresource(
+ void* pDstData,
+ UINT DstRowPitch,
+ UINT DstDepthPitch,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox) {
+ CopySubresourceData(
+ pDstData, DstRowPitch, DstDepthPitch,
+ pSrcResource, SrcSubresource, pSrcBox);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::WriteToSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch) {
+ CopySubresourceData(
+ pSrcData, SrcRowPitch, SrcRowPitch,
+ pDstResource, DstSubresource, pDstBox);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource(
+ HANDLE hResource,
+ REFIID ReturnedInterface,
+ void** ppResource) {
+ InitReturnPtr(ppResource);
+
+ Logger::err("D3D11Device::OpenSharedResource: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource1(
+ HANDLE hResource,
+ REFIID ReturnedInterface,
+ void** ppResource) {
+ InitReturnPtr(ppResource);
+
+ Logger::err("D3D11Device::OpenSharedResource1: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResourceByName(
+ LPCWSTR lpName,
+ DWORD dwDesiredAccess,
+ REFIID returnedInterface,
+ void** ppResource) {
+ InitReturnPtr(ppResource);
+
+ Logger::err("D3D11Device::OpenSharedResourceByName: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedFence(
+ HANDLE hFence,
+ REFIID ReturnedInterface,
+ void** ppFence) {
+ InitReturnPtr(ppFence);
+
+ Logger::err("D3D11Device::OpenSharedFence: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CheckFormatSupport(
+ DXGI_FORMAT Format,
+ UINT* pFormatSupport) {
+ return GetFormatSupportFlags(Format, pFormatSupport, nullptr);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels(
+ DXGI_FORMAT Format,
+ UINT SampleCount,
+ UINT* pNumQualityLevels) {
+ return CheckMultisampleQualityLevels1(Format, SampleCount, 0, pNumQualityLevels);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels1(
+ DXGI_FORMAT Format,
+ UINT SampleCount,
+ UINT Flags,
+ UINT* pNumQualityLevels) {
+ // There are many error conditions, so we'll just assume
+ // that we will fail and return a non-zero value in case
+ // the device does actually support the format.
+ if (!pNumQualityLevels)
+ return E_INVALIDARG;
+
+ // We don't support tiled resources, but it's unclear what
+ // we are supposed to return in this case. Be conservative.
+ if (Flags) {
+ *pNumQualityLevels = 0;
+ return E_FAIL;
+ }
+
+ // For some reason, we can query DXGI_FORMAT_UNKNOWN
+ if (Format == DXGI_FORMAT_UNKNOWN) {
+ *pNumQualityLevels = SampleCount == 1 ? 1 : 0;
+ return SampleCount ? S_OK : E_FAIL;
+ }
+
+ // All other unknown formats should result in an error return.
+ VkFormat format = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY).Format;
+
+ if (format == VK_FORMAT_UNDEFINED)
+ return E_INVALIDARG;
+
+ // Zero-init now, leave value undefined otherwise.
+ // This does actually match native D3D11 behaviour.
+ *pNumQualityLevels = 0;
+
+ // Non-power of two sample counts are not supported, but querying
+ // support for them is legal, so we return zero quality levels.
+ VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
+
+ if (FAILED(DecodeSampleCount(SampleCount, &sampleCountFlag)))
+ return SampleCount && SampleCount <= 32 ? S_OK : E_FAIL;
+
+ // Check if the device supports the given combination of format
+ // and sample count. D3D exposes the opaque concept of quality
+ // levels to the application, we'll just define one such level.
+ VkImageFormatProperties formatProps;
+
+ VkResult status = m_dxvkAdapter->imageFormatProperties(
+ format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, formatProps);
+
+ if ((status == VK_SUCCESS) && (formatProps.sampleCounts & sampleCountFlag))
+ *pNumQualityLevels = 1;
+ return S_OK;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) {
+ // We basically don't support counters
+ pCounterInfo->LastDeviceDependentCounter = D3D11_COUNTER(0);
+ pCounterInfo->NumSimultaneousCounters = 0;
+ pCounterInfo->NumDetectableParallelUnits = 0;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CheckCounter(
+ const D3D11_COUNTER_DESC* pDesc,
+ D3D11_COUNTER_TYPE* pType,
+ UINT* pActiveCounters,
+ LPSTR szName,
+ UINT* pNameLength,
+ LPSTR szUnits,
+ UINT* pUnitsLength,
+ LPSTR szDescription,
+ UINT* pDescriptionLength) {
+ Logger::err("D3D11: Counters not supported");
+ return E_INVALIDARG;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::CheckFeatureSupport(
+ D3D11_FEATURE Feature,
+ void* pFeatureSupportData,
+ UINT FeatureSupportDataSize) {
+ switch (Feature) {
+ case D3D11_FEATURE_THREADING: {
+ auto info = static_cast<D3D11_FEATURE_DATA_THREADING*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ // We report native support for command lists here so that we do not actually
+ // have to re-implement the UpdateSubresource bug from the D3D11 runtime, see
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
+ info->DriverConcurrentCreates = TRUE;
+ info->DriverCommandLists = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_DOUBLES: {
+ auto info = static_cast<D3D11_FEATURE_DATA_DOUBLES*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->DoublePrecisionFloatShaderOps = m_dxvkDevice->features().core.features.shaderFloat64
+ && m_dxvkDevice->features().core.features.shaderInt64;
+ } return S_OK;
+
+ case D3D11_FEATURE_FORMAT_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_FORMAT_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ return GetFormatSupportFlags(info->InFormat, &info->OutFormatSupport, nullptr);
+ } return S_OK;
+
+ case D3D11_FEATURE_FORMAT_SUPPORT2: {
+ auto info = static_cast<D3D11_FEATURE_DATA_FORMAT_SUPPORT2*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ return GetFormatSupportFlags(info->InFormat, nullptr, &info->OutFormatSupport2);
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D11_OPTIONS: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404457(v=vs.85).aspx
+ const auto& features = m_dxvkDevice->features();
+
+ info->OutputMergerLogicOp = features.core.features.logicOp;
+ info->UAVOnlyRenderingForcedSampleCount = features.core.features.variableMultisampleRate;
+ info->DiscardAPIsSeenByDriver = TRUE;
+ info->FlagsForUpdateAndCopySeenByDriver = TRUE;
+ info->ClearView = TRUE;
+ info->CopyWithOverlap = TRUE;
+ info->ConstantBufferPartialUpdate = TRUE;
+ info->ConstantBufferOffsetting = TRUE;
+ info->MapNoOverwriteOnDynamicConstantBuffer = TRUE;
+ info->MapNoOverwriteOnDynamicBufferSRV = TRUE;
+ info->MultisampleRTVWithForcedSampleCountOne = TRUE; /* not really */
+ info->SAD4ShaderInstructions = TRUE;
+ info->ExtendedDoublesShaderInstructions = TRUE;
+ info->ExtendedResourceSharing = TRUE; /* not really */
+ } return S_OK;
+
+ case D3D11_FEATURE_ARCHITECTURE_INFO: {
+ auto info = static_cast<D3D11_FEATURE_DATA_ARCHITECTURE_INFO*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->TileBasedDeferredRenderer = FALSE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D9_OPTIONS: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D9_OPTIONS*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->FullNonPow2TextureSupport = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ // Report that we only support full 32-bit operations
+ info->PixelShaderMinPrecision = 0;
+ info->AllOtherShaderStagesMinPrecision = 0;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D9_SHADOW_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->SupportsDepthAsTextureWithLessEqualComparisonFilter = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D11_OPTIONS1: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS1*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ // Min/Max filtering requires Tiled Resources Tier 2 for some reason,
+ // so we cannot support it even though Vulkan exposes this feature
+ info->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED;
+ info->MinMaxFiltering = FALSE;
+ info->ClearViewAlsoSupportsDepthOnlyFormats = TRUE;
+ info->MapOnDefaultBuffers = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->SimpleInstancingSupported = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_MARKER_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_MARKER_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->Profile = FALSE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D9_OPTIONS1: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D9_OPTIONS1*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->FullNonPow2TextureSupported = TRUE;
+ info->DepthAsTextureWithLessEqualComparisonFilterSupported = TRUE;
+ info->SimpleInstancingSupported = TRUE;
+ info->TextureCubeFaceRenderTargetWithNonCubeDepthStencilSupported = TRUE;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D11_OPTIONS2: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS2*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ const auto& extensions = m_dxvkDevice->extensions();
+ const auto& features = m_dxvkDevice->features();
+
+ info->PSSpecifiedStencilRefSupported = extensions.extShaderStencilExport;
+ info->TypedUAVLoadAdditionalFormats = features.core.features.shaderStorageImageReadWithoutFormat;
+ info->ROVsSupported = FALSE;
+ info->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED;
+ info->MapOnDefaultTextures = TRUE;
+ info->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED;
+ info->StandardSwizzle = FALSE;
+ info->UnifiedMemoryArchitecture = m_dxvkDevice->isUnifiedMemoryArchitecture();
+
+ if (m_dxvkDevice->extensions().extConservativeRasterization) {
+ // We don't have a way to query uncertainty regions, so just check degenerate triangle behaviour
+ info->ConservativeRasterizationTier = m_dxvkDevice->properties().extConservativeRasterization.degenerateTrianglesRasterized
+ ? D3D11_CONSERVATIVE_RASTERIZATION_TIER_2 : D3D11_CONSERVATIVE_RASTERIZATION_TIER_1;
+ }
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D11_OPTIONS3: {
+ if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3))
+ return E_INVALIDARG;
+
+ const auto& extensions = m_dxvkDevice->extensions();
+
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS3*>(pFeatureSupportData);
+ info->VPAndRTArrayIndexFromAnyShaderFeedingRasterizer = extensions.extShaderViewportIndexLayer;
+ } return S_OK;
+
+ case D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT: {
+ auto info = static_cast<D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ // These numbers are not accurate, but it should not have any effect on D3D11 apps
+ info->MaxGPUVirtualAddressBitsPerResource = 32;
+ info->MaxGPUVirtualAddressBitsPerProcess = 40;
+ } return S_OK;
+
+ case D3D11_FEATURE_D3D11_OPTIONS4: {
+ auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS4*>(pFeatureSupportData);
+
+ if (FeatureSupportDataSize != sizeof(*info))
+ return E_INVALIDARG;
+
+ info->ExtendedNV12SharedTextureSupported = FALSE;
+ } return S_OK;
+
+ default:
+ Logger::err(str::format("D3D11Device: CheckFeatureSupport: Unknown feature: ", Feature));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::GetPrivateData(
+ REFGUID guid, UINT* pDataSize, void* pData) {
+ return m_container->GetPrivateData(guid, pDataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateData(
+ REFGUID guid, UINT DataSize, const void* pData) {
+ return m_container->SetPrivateData(guid, DataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateDataInterface(
+ REFGUID guid, const IUnknown* pData) {
+ return m_container->SetPrivateDataInterface(guid, pData);
+ }
+
+
+ D3D_FEATURE_LEVEL STDMETHODCALLTYPE D3D11Device::GetFeatureLevel() {
+ return m_featureLevel;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Device::GetCreationFlags() {
+ return m_featureFlags;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::GetDeviceRemovedReason() {
+ VkResult status = m_dxvkDevice->getDeviceStatus();
+
+ switch (status) {
+ case VK_SUCCESS: return S_OK;
+ default: return DXGI_ERROR_DEVICE_RESET;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) {
+ *ppImmediateContext = m_context.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::GetImmediateContext1(ID3D11DeviceContext1** ppImmediateContext) {
+ *ppImmediateContext = m_context.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::GetImmediateContext2(ID3D11DeviceContext2** ppImmediateContext) {
+ *ppImmediateContext = m_context.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::GetImmediateContext3(ID3D11DeviceContext3** ppImmediateContext) {
+ *ppImmediateContext = m_context.ref();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::SetExceptionMode(UINT RaiseFlags) {
+ Logger::err("D3D11Device::SetExceptionMode: Not implemented");
+ return E_NOTIMPL;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Device::GetExceptionMode() {
+ Logger::err("D3D11Device::GetExceptionMode: Not implemented");
+ return 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::GetResourceTiling(
+ ID3D11Resource* pTiledResource,
+ UINT* pNumTilesForEntireResource,
+ D3D11_PACKED_MIP_DESC* pPackedMipDesc,
+ D3D11_TILE_SHAPE* pStandardTileShapeForNonPackedMips,
+ UINT* pNumSubresourceTilings,
+ UINT FirstSubresourceTilingToGet,
+ D3D11_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11Device::GetResourceTiling: Tiled resources not supported");
+
+ if (pNumTilesForEntireResource)
+ *pNumTilesForEntireResource = 0;
+
+ if (pPackedMipDesc)
+ *pPackedMipDesc = D3D11_PACKED_MIP_DESC();
+
+ if (pStandardTileShapeForNonPackedMips)
+ *pStandardTileShapeForNonPackedMips = D3D11_TILE_SHAPE();
+
+ if (pNumSubresourceTilings) {
+ if (pSubresourceTilingsForNonPackedMips) {
+ for (uint32_t i = 0; i < *pNumSubresourceTilings; i++)
+ pSubresourceTilingsForNonPackedMips[i] = D3D11_SUBRESOURCE_TILING();
+ }
+
+ *pNumSubresourceTilings = 0;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Device::RegisterDeviceRemovedEvent(
+ HANDLE hEvent,
+ DWORD* pdwCookie) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11Device::RegisterDeviceRemovedEvent: Not implemented");
+
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Device::UnregisterDeviceRemoved(
+ DWORD dwCookie) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11Device::UnregisterDeviceRemovedEvent: Not implemented");
+ }
+
+
+ DXGI_VK_FORMAT_INFO D3D11Device::LookupFormat(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const {
+ return m_d3d11Formats.GetFormatInfo(Format, Mode);
+ }
+
+
+ DXGI_VK_FORMAT_INFO D3D11Device::LookupPackedFormat(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const {
+ return m_d3d11Formats.GetPackedFormatInfo(Format, Mode);
+ }
+
+
+ DXGI_VK_FORMAT_FAMILY D3D11Device::LookupFamily(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const {
+ return m_d3d11Formats.GetFormatFamily(Format, Mode);
+ }
+
+
+ void D3D11Device::FlushInitContext() {
+ m_initializer->Flush();
+ }
+
+
+ bool D3D11Device::CheckFeatureLevelSupport(
+ const Rc<DxvkInstance>& instance,
+ const Rc<DxvkAdapter>& adapter,
+ D3D_FEATURE_LEVEL featureLevel) {
+ if (featureLevel > GetMaxFeatureLevel(instance))
+ return false;
+
+ // Check whether all features are supported
+ const DxvkDeviceFeatures features
+ = GetDeviceFeatures(adapter, featureLevel);
+
+ if (!adapter->checkFeatureSupport(features))
+ return false;
+
+ // TODO also check for required limits
+ return true;
+ }
+
+
+ DxvkDeviceFeatures D3D11Device::GetDeviceFeatures(
+ const Rc<DxvkAdapter>& adapter,
+ D3D_FEATURE_LEVEL featureLevel) {
+ DxvkDeviceFeatures supported = adapter->features();
+ DxvkDeviceFeatures enabled = {};
+
+#ifndef VBOX
+ enabled.core.features.geometryShader = VK_TRUE;
+#else
+ enabled.core.features.geometryShader = supported.core.features.geometryShader;
+#endif
+ enabled.core.features.robustBufferAccess = VK_TRUE;
+ enabled.core.features.shaderStorageImageWriteWithoutFormat = VK_TRUE;
+ enabled.core.features.depthBounds = supported.core.features.depthBounds;
+
+ enabled.shaderDrawParameters.shaderDrawParameters = VK_TRUE;
+
+ enabled.extMemoryPriority.memoryPriority = supported.extMemoryPriority.memoryPriority;
+
+ enabled.extRobustness2.robustBufferAccess2 = supported.extRobustness2.robustBufferAccess2;
+ enabled.extRobustness2.robustImageAccess2 = supported.extRobustness2.robustImageAccess2;
+ enabled.extRobustness2.nullDescriptor = supported.extRobustness2.nullDescriptor;
+
+ enabled.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation = supported.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation;
+
+ enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor;
+ enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor;
+
+ if (supported.extCustomBorderColor.customBorderColorWithoutFormat) {
+ enabled.extCustomBorderColor.customBorderColors = VK_TRUE;
+ enabled.extCustomBorderColor.customBorderColorWithoutFormat = VK_TRUE;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
+ enabled.core.features.depthClamp = VK_TRUE;
+ enabled.core.features.depthBiasClamp = VK_TRUE;
+ enabled.core.features.fillModeNonSolid = VK_TRUE;
+ enabled.core.features.pipelineStatisticsQuery = supported.core.features.pipelineStatisticsQuery;
+ enabled.core.features.sampleRateShading = VK_TRUE;
+ enabled.core.features.samplerAnisotropy = supported.core.features.samplerAnisotropy;
+ enabled.core.features.shaderClipDistance = VK_TRUE;
+#ifndef VBOX
+ enabled.core.features.shaderCullDistance = VK_TRUE;
+#else
+ enabled.core.features.shaderCullDistance = supported.core.features.shaderCullDistance;
+#endif
+ enabled.core.features.textureCompressionBC = VK_TRUE;
+ enabled.extDepthClipEnable.depthClipEnable = supported.extDepthClipEnable.depthClipEnable;
+ enabled.extHostQueryReset.hostQueryReset = supported.extHostQueryReset.hostQueryReset;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
+ enabled.core.features.occlusionQueryPrecise = VK_TRUE;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
+ enabled.core.features.independentBlend = VK_TRUE;
+ enabled.core.features.multiViewport = VK_TRUE;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
+ enabled.core.features.fullDrawIndexUint32 = VK_TRUE;
+ enabled.core.features.logicOp = supported.core.features.logicOp;
+ enabled.core.features.shaderImageGatherExtended = VK_TRUE;
+ enabled.core.features.variableMultisampleRate = supported.core.features.variableMultisampleRate;
+#ifndef VBOX
+ enabled.extTransformFeedback.transformFeedback = VK_TRUE;
+#else
+ enabled.extTransformFeedback.transformFeedback = supported.extTransformFeedback.transformFeedback;
+#endif
+ enabled.extTransformFeedback.geometryStreams = VK_TRUE;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
+ enabled.core.features.dualSrcBlend = VK_TRUE;
+ enabled.core.features.imageCubeArray = VK_TRUE;
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
+ enabled.core.features.drawIndirectFirstInstance = VK_TRUE;
+ enabled.core.features.fragmentStoresAndAtomics = VK_TRUE;
+ enabled.core.features.multiDrawIndirect = VK_TRUE;
+ enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64;
+ enabled.core.features.shaderInt64 = supported.core.features.shaderInt64;
+ enabled.core.features.shaderStorageImageReadWithoutFormat = supported.core.features.shaderStorageImageReadWithoutFormat;
+#ifndef VBOX
+ enabled.core.features.tessellationShader = VK_TRUE;
+#else
+ enabled.core.features.tessellationShader = supported.core.features.tessellationShader;
+#endif
+ }
+
+ if (featureLevel >= D3D_FEATURE_LEVEL_11_1) {
+ enabled.core.features.logicOp = VK_TRUE;
+ enabled.core.features.variableMultisampleRate = VK_TRUE;
+ enabled.core.features.vertexPipelineStoresAndAtomics = VK_TRUE;
+ }
+
+ return enabled;
+ }
+
+
+ HRESULT D3D11Device::CreateShaderModule(
+ D3D11CommonShader* pShaderModule,
+ DxvkShaderKey ShaderKey,
+ const void* pShaderBytecode,
+ size_t BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ const DxbcModuleInfo* pModuleInfo) {
+ if (pClassLinkage != nullptr)
+ Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
+
+ D3D11CommonShader commonShader;
+
+ HRESULT hr = m_shaderModules.GetShaderModule(this,
+ &ShaderKey, pModuleInfo, pShaderBytecode, BytecodeLength,
+ &commonShader);
+
+ if (FAILED(hr))
+ return hr;
+
+ auto shader = commonShader.GetShader();
+
+ if (shader->flags().test(DxvkShaderFlag::ExportsStencilRef)
+ && !m_dxvkDevice->extensions().extShaderStencilExport)
+ return E_INVALIDARG;
+
+ if (shader->flags().test(DxvkShaderFlag::ExportsViewportIndexLayerFromVertexStage)
+ && !m_dxvkDevice->extensions().extShaderViewportIndexLayer)
+ return E_INVALIDARG;
+
+ *pShaderModule = std::move(commonShader);
+ return S_OK;
+ }
+
+
+ HRESULT D3D11Device::GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags1, UINT* pFlags2) const {
+ const DXGI_VK_FORMAT_INFO fmtMapping = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY);
+
+ // Reset output flags preemptively
+ if (pFlags1 != nullptr) *pFlags1 = 0;
+ if (pFlags2 != nullptr) *pFlags2 = 0;
+
+ // Unsupported or invalid format
+ if (Format != DXGI_FORMAT_UNKNOWN && fmtMapping.Format == VK_FORMAT_UNDEFINED)
+ return E_FAIL;
+
+ // Query Vulkan format properties and supported features for it
+ const DxvkFormatInfo* fmtProperties = imageFormatInfo(fmtMapping.Format);
+
+ VkFormatProperties fmtSupport = fmtMapping.Format != VK_FORMAT_UNDEFINED
+ ? m_dxvkAdapter->formatProperties(fmtMapping.Format)
+ : VkFormatProperties();
+
+ VkFormatFeatureFlags bufFeatures = fmtSupport.bufferFeatures;
+ VkFormatFeatureFlags imgFeatures = fmtSupport.optimalTilingFeatures | fmtSupport.linearTilingFeatures;
+
+ // For multi-plane images, we want to check available view formats as well
+ if (fmtProperties->flags.test(DxvkFormatFlag::MultiPlane)) {
+ const VkFormatFeatureFlags featureMask
+ = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+ | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
+ | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
+ | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
+ | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+
+ DXGI_VK_FORMAT_FAMILY formatFamily = LookupFamily(Format, DXGI_VK_FORMAT_MODE_ANY);
+
+ for (uint32_t i = 0; i < formatFamily.FormatCount; i++) {
+ VkFormatProperties viewFmtSupport = m_dxvkAdapter->formatProperties(formatFamily.Formats[i]);
+ imgFeatures |= (viewFmtSupport.optimalTilingFeatures | viewFmtSupport.linearTilingFeatures) & featureMask;
+ }
+ }
+
+ UINT flags1 = 0;
+ UINT flags2 = 0;
+
+ // Format can be used for shader resource views with buffers
+ if (bufFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
+ || Format == DXGI_FORMAT_UNKNOWN)
+ flags1 |= D3D11_FORMAT_SUPPORT_BUFFER;
+
+ // Format can be used for vertex data
+ if (bufFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
+ flags1 |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER;
+
+ // Format can be used for index data. Only
+ // these two formats are supported by D3D11.
+ if (Format == DXGI_FORMAT_R16_UINT
+ || Format == DXGI_FORMAT_R32_UINT)
+ flags1 |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
+
+ // These formats are technically irrelevant since
+ // SO buffers are passed in as raw buffers and not
+ // as views, but the feature flag exists regardless
+ if (Format == DXGI_FORMAT_R32_FLOAT
+ || Format == DXGI_FORMAT_R32_UINT
+ || Format == DXGI_FORMAT_R32_SINT
+ || Format == DXGI_FORMAT_R32G32_FLOAT
+ || Format == DXGI_FORMAT_R32G32_UINT
+ || Format == DXGI_FORMAT_R32G32_SINT
+ || Format == DXGI_FORMAT_R32G32B32_FLOAT
+ || Format == DXGI_FORMAT_R32G32B32_UINT
+ || Format == DXGI_FORMAT_R32G32B32_SINT
+ || Format == DXGI_FORMAT_R32G32B32A32_FLOAT
+ || Format == DXGI_FORMAT_R32G32B32A32_UINT
+ || Format == DXGI_FORMAT_R32G32B32A32_SINT)
+ flags1 |= D3D11_FORMAT_SUPPORT_SO_BUFFER;
+
+ if (imgFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+ || imgFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
+ const VkFormat depthFormat = LookupFormat(Format, DXGI_VK_FORMAT_MODE_DEPTH).Format;
+
+ if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_1D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE1D;
+ if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_2D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE2D;
+ if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_3D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+
+ flags1 |= D3D11_FORMAT_SUPPORT_MIP
+ | D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT;
+
+ // Format can be read
+ if (imgFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
+ flags1 |= D3D11_FORMAT_SUPPORT_TEXTURECUBE
+ | D3D11_FORMAT_SUPPORT_SHADER_LOAD
+ | D3D11_FORMAT_SUPPORT_SHADER_GATHER
+ | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
+ | D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT;
+
+ if (depthFormat != VK_FORMAT_UNDEFINED) {
+ flags1 |= D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON
+ | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
+ }
+ }
+
+ // Format is a color format that can be used for rendering
+ if (imgFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
+ flags1 |= D3D11_FORMAT_SUPPORT_RENDER_TARGET
+ | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
+ | D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT;
+
+ if (m_dxvkDevice->features().core.features.logicOp)
+ flags2 |= D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP;
+ }
+
+ // Format supports blending when used for rendering
+ if (imgFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
+ flags1 |= D3D11_FORMAT_SUPPORT_BLENDABLE;
+
+ // Format is a depth-stencil format that can be used for rendering
+ if (imgFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ flags1 |= D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
+
+ // FIXME implement properly. This would require a VkSurface.
+ if (Format == DXGI_FORMAT_R8G8B8A8_UNORM
+ || Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
+ || Format == DXGI_FORMAT_B8G8R8A8_UNORM
+ || Format == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
+ || Format == DXGI_FORMAT_R16G16B16A16_FLOAT
+ || Format == DXGI_FORMAT_R10G10B10A2_UNORM
+ || Format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM)
+ flags1 |= D3D11_FORMAT_SUPPORT_DISPLAY;
+
+ // Query multisample support for this format
+ VkImageFormatProperties imgFmtProperties;
+
+ VkResult status = m_dxvkAdapter->imageFormatProperties(fmtMapping.Format,
+ VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ (fmtProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
+ ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+ : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ 0, imgFmtProperties);
+
+ if (status == VK_SUCCESS && imgFmtProperties.sampleCounts > VK_SAMPLE_COUNT_1_BIT) {
+ flags1 |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
+ | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE
+ | D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD;
+ }
+ }
+
+ // Format can be used for storage images or storage texel buffers
+ if ((bufFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)
+ && (imgFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
+ flags1 |= D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW;
+ flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE;
+
+ if (m_dxvkDevice->features().core.features.shaderStorageImageReadWithoutFormat
+ || Format == DXGI_FORMAT_R32_UINT
+ || Format == DXGI_FORMAT_R32_SINT
+ || Format == DXGI_FORMAT_R32_FLOAT)
+ flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD;
+
+ if (Format == DXGI_FORMAT_R32_UINT
+ || Format == DXGI_FORMAT_R32_SINT) {
+ flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD
+ | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS
+ | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE
+ | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE;
+ }
+
+ if (Format == DXGI_FORMAT_R32_SINT)
+ flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX;
+
+ if (Format == DXGI_FORMAT_R32_UINT)
+ flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX;
+ }
+
+ // Mark everyting as CPU lockable
+ if (flags1 | flags2)
+ flags1 |= D3D11_FORMAT_SUPPORT_CPU_LOCKABLE;
+
+ // Write back format support flags
+ if (pFlags1 != nullptr) *pFlags1 = flags1;
+ if (pFlags2 != nullptr) *pFlags2 = flags2;
+ return (pFlags1 && flags1) || (pFlags2 && flags2) ? S_OK : E_FAIL;
+ }
+
+
+ BOOL D3D11Device::GetImageTypeSupport(VkFormat Format, VkImageType Type) const {
+ VkImageFormatProperties props;
+
+ VkResult status = m_dxvkAdapter->imageFormatProperties(
+ Format, Type, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, props);
+
+ if (status != VK_SUCCESS) {
+ status = m_dxvkAdapter->imageFormatProperties(
+ Format, Type, VK_IMAGE_TILING_LINEAR,
+ VK_IMAGE_USAGE_SAMPLED_BIT, 0, props);
+ }
+
+ return status == VK_SUCCESS;
+ }
+
+
+ uint32_t D3D11Device::GetViewPlaneIndex(
+ ID3D11Resource* pResource,
+ DXGI_FORMAT ViewFormat) {
+ auto texture = GetCommonTexture(pResource);
+
+ if (!texture)
+ return 0;
+
+ uint32_t planeCount = texture->GetPlaneCount();
+
+ if (planeCount == 1)
+ return 0;
+
+ auto formatMode = texture->GetFormatMode();
+ auto formatFamily = LookupFamily(texture->Desc()->Format, formatMode);
+ auto viewFormat = LookupFormat(ViewFormat, formatMode);
+
+ for (uint32_t i = 0; i < formatFamily.FormatCount; i++) {
+ if (formatFamily.Formats[i] == viewFormat.Format)
+ return i % planeCount;
+ }
+
+ return ~0u;
+ }
+
+
+ template<typename Void>
+ void D3D11Device::CopySubresourceData(
+ Void* pData,
+ UINT RowPitch,
+ UINT DepthPitch,
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ const D3D11_BOX* pBox) {
+ auto texture = GetCommonTexture(pResource);
+
+ if (!texture)
+ return;
+
+ // Validate texture state and skip invalid calls
+ if (texture->Desc()->Usage != D3D11_USAGE_DEFAULT
+ || texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE
+ || texture->CountSubresources() <= Subresource
+ || texture->GetMapType(Subresource) == D3D11_MAP(~0u))
+ return;
+
+ // Retrieve image format information
+ VkFormat packedFormat = LookupPackedFormat(
+ texture->Desc()->Format,
+ texture->GetFormatMode()).Format;
+
+ auto formatInfo = imageFormatInfo(packedFormat);
+
+ // Validate box against subresource dimensions
+ Rc<DxvkImage> image = texture->GetImage();
+
+ auto subresource = texture->GetSubresourceFromIndex(
+ formatInfo->aspectMask, Subresource);
+
+ VkOffset3D offset = { 0, 0, 0 };
+ VkExtent3D extent = image->mipLevelExtent(subresource.mipLevel);
+
+ if (pBox) {
+ if (pBox->left >= pBox->right
+ || pBox->top >= pBox->bottom
+ || pBox->front >= pBox->back)
+ return; // legal, but no-op
+
+ if (pBox->right > extent.width
+ || pBox->bottom > extent.height
+ || pBox->back > extent.depth)
+ return; // out of bounds
+
+ offset = VkOffset3D {
+ int32_t(pBox->left),
+ int32_t(pBox->top),
+ int32_t(pBox->front) };
+
+ extent = VkExtent3D {
+ pBox->right - pBox->left,
+ pBox->bottom - pBox->top,
+ pBox->back - pBox->front };
+ }
+
+ // We can only operate on full blocks of compressed images
+ offset = util::computeBlockOffset(offset, formatInfo->blockSize);
+ extent = util::computeBlockCount(extent, formatInfo->blockSize);
+
+ // Determine the memory layout of the image data
+ D3D11_MAPPED_SUBRESOURCE subresourceData = { };
+
+ if (texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
+ VkSubresourceLayout layout = image->querySubresourceLayout(subresource);
+ subresourceData.pData = image->mapPtr(layout.offset);
+ subresourceData.RowPitch = layout.rowPitch;
+ subresourceData.DepthPitch = layout.depthPitch;
+ } else {
+ subresourceData.pData = texture->GetMappedBuffer(Subresource)->mapPtr(0);
+ subresourceData.RowPitch = formatInfo->elementSize * extent.width;
+ subresourceData.DepthPitch = formatInfo->elementSize * extent.width * extent.height;
+ }
+
+ if constexpr (std::is_const<Void>::value) {
+ // WriteToSubresource
+ auto src = reinterpret_cast<const char*>(pData);
+ auto dst = reinterpret_cast< char*>(subresourceData.pData);
+
+ for (uint32_t z = 0; z < extent.depth; z++) {
+ for (uint32_t y = 0; y < extent.height; y++) {
+ std::memcpy(
+ dst + (offset.z + z) * subresourceData.DepthPitch
+ + (offset.y + y) * subresourceData.RowPitch
+ + (offset.x) * formatInfo->elementSize,
+ src + z * DepthPitch
+ + y * RowPitch,
+ formatInfo->elementSize * extent.width);
+ }
+ }
+ } else {
+ // ReadFromSubresource
+ auto src = reinterpret_cast<const char*>(subresourceData.pData);
+ auto dst = reinterpret_cast< char*>(pData);
+
+ for (uint32_t z = 0; z < extent.depth; z++) {
+ for (uint32_t y = 0; y < extent.height; y++) {
+ std::memcpy(
+ dst + z * DepthPitch
+ + y * RowPitch,
+ src + (offset.z + z) * subresourceData.DepthPitch
+ + (offset.y + y) * subresourceData.RowPitch
+ + (offset.x) * formatInfo->elementSize,
+ formatInfo->elementSize * extent.width);
+ }
+ }
+ }
+ }
+
+
+ D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel(const Rc<DxvkInstance>& pInstance) {
+ static const std::array<std::pair<std::string, D3D_FEATURE_LEVEL>, 9> s_featureLevels = {{
+ { "12_1", D3D_FEATURE_LEVEL_12_1 },
+ { "12_0", D3D_FEATURE_LEVEL_12_0 },
+ { "11_1", D3D_FEATURE_LEVEL_11_1 },
+ { "11_0", D3D_FEATURE_LEVEL_11_0 },
+ { "10_1", D3D_FEATURE_LEVEL_10_1 },
+ { "10_0", D3D_FEATURE_LEVEL_10_0 },
+ { "9_3", D3D_FEATURE_LEVEL_9_3 },
+ { "9_2", D3D_FEATURE_LEVEL_9_2 },
+ { "9_1", D3D_FEATURE_LEVEL_9_1 },
+ }};
+
+ const std::string maxLevel = pInstance->config()
+ .getOption<std::string>("d3d11.maxFeatureLevel");
+
+ auto entry = std::find_if(s_featureLevels.begin(), s_featureLevels.end(),
+ [&] (const std::pair<std::string, D3D_FEATURE_LEVEL>& pair) {
+ return pair.first == maxLevel;
+ });
+
+ return entry != s_featureLevels.end()
+ ? entry->second
+ : D3D_FEATURE_LEVEL_11_1;
+ }
+
+
+
+
+ D3D11DeviceExt::D3D11DeviceExt(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice)
+ : m_container(pContainer), m_device(pDevice) {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DeviceExt::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DeviceExt::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceExt::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ BOOL STDMETHODCALLTYPE D3D11DeviceExt::GetExtensionSupport(
+ D3D11_VK_EXTENSION Extension) {
+ const auto& deviceFeatures = m_device->GetDXVKDevice()->features();
+ const auto& deviceExtensions = m_device->GetDXVKDevice()->extensions();
+
+ switch (Extension) {
+ case D3D11_VK_EXT_BARRIER_CONTROL:
+ return true;
+
+ case D3D11_VK_EXT_MULTI_DRAW_INDIRECT:
+ return deviceFeatures.core.features.multiDrawIndirect;
+
+ case D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT:
+ return deviceFeatures.core.features.multiDrawIndirect
+ && deviceExtensions.khrDrawIndirectCount;
+
+ case D3D11_VK_EXT_DEPTH_BOUNDS:
+ return deviceFeatures.core.features.depthBounds;
+
+ case D3D11_VK_NVX_IMAGE_VIEW_HANDLE:
+ return deviceExtensions.nvxImageViewHandle;
+
+ case D3D11_VK_NVX_BINARY_IMPORT:
+ return deviceExtensions.nvxBinaryImport
+ && deviceExtensions.khrBufferDeviceAddress;
+
+ default:
+ return false;
+ }
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::GetCudaTextureObjectNVX(uint32_t srvDriverHandle, uint32_t samplerDriverHandle, uint32_t* pCudaTextureHandle) {
+ ID3D11ShaderResourceView* srv = HandleToSrvNVX(srvDriverHandle);
+
+ if (!srv) {
+ Logger::warn(str::format("GetCudaTextureObjectNVX() failure - srv handle wasn't found: ", srvDriverHandle));
+ return false;
+ }
+
+ ID3D11SamplerState* samplerState = HandleToSamplerNVX(samplerDriverHandle);
+
+ if (!samplerState) {
+ Logger::warn(str::format("GetCudaTextureObjectNVX() failure - sampler handle wasn't found: ", samplerDriverHandle));
+ return false;
+ }
+
+ D3D11SamplerState* pSS = static_cast<D3D11SamplerState*>(samplerState);
+ Rc<DxvkSampler> pDSS = pSS->GetDXVKSampler();
+ VkSampler vkSampler = pDSS->handle();
+
+ D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(srv);
+ Rc<DxvkImageView> pIV = pSRV->GetImageView();
+ VkImageView vkImageView = pIV->handle();
+
+ VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
+ imageViewHandleInfo.imageView = vkImageView;
+ imageViewHandleInfo.sampler = vkSampler;
+ imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+
+ // note: there's no implicit lifetime management here; it's up to the
+ // app to keep the sampler and SRV alive as long as it wants to use this
+ // derived handle.
+ VkDevice vkDevice = m_device->GetDXVKDevice()->handle();
+ *pCudaTextureHandle = m_device->GetDXVKDevice()->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
+
+ if (!*pCudaTextureHandle) {
+ Logger::warn("GetCudaTextureObjectNVX() handle==0 - failed");
+ return false;
+ }
+
+ return true;
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::CreateCubinComputeShaderWithNameNVX(const void* pCubin, uint32_t size,
+ uint32_t blockX, uint32_t blockY, uint32_t blockZ, const char* pShaderName, IUnknown** phShader) {
+ Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
+ VkDevice vkDevice = dxvkDevice->handle();
+
+ VkCuModuleCreateInfoNVX moduleCreateInfo = { VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX };
+ moduleCreateInfo.pData = pCubin;
+ moduleCreateInfo.dataSize = size;
+
+ VkCuModuleNVX cuModule;
+ VkCuFunctionNVX cuFunction;
+ VkResult result;
+
+ if ((result = dxvkDevice->vkd()->vkCreateCuModuleNVX(vkDevice, &moduleCreateInfo, nullptr, &cuModule))) {
+ Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create module - result=", result, " pcubindata=", pCubin, " cubinsize=", size));
+ return false; // failure
+ }
+
+ VkCuFunctionCreateInfoNVX functionCreateInfo = { VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX };
+ functionCreateInfo.module = cuModule;
+ functionCreateInfo.pName = pShaderName;
+
+ if ((result = dxvkDevice->vkd()->vkCreateCuFunctionNVX(vkDevice, &functionCreateInfo, nullptr, &cuFunction))) {
+ dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, cuModule, nullptr);
+ Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create function - result=", result));
+ return false;
+ }
+
+ *phShader = ref(new CubinShaderWrapper(dxvkDevice,
+ cuModule, cuFunction, { blockX, blockY, blockZ }));
+ return true;
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::GetResourceHandleGPUVirtualAddressAndSizeNVX(void* hObject, uint64_t* gpuVAStart, uint64_t* gpuVASize) {
+ // The hObject 'opaque driver handle' is really just a straight cast
+ // of the corresponding ID3D11Resource* in dxvk/dxvknvapi
+ ID3D11Resource* pResource = static_cast<ID3D11Resource*>(hObject);
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) {
+ Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - GetCommonResourceDesc() failed");
+ return false;
+ }
+
+ switch (resourceDesc.Dim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER:
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ // okay - we can deal with those two dimensions
+ break;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ case D3D11_RESOURCE_DIMENSION_UNKNOWN:
+ default:
+ Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - failure - unsupported dimension: ", resourceDesc.Dim));
+ return false;
+ }
+
+ Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
+ VkDevice vkDevice = dxvkDevice->handle();
+
+ if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
+ D3D11CommonTexture *texture = GetCommonTexture(pResource);
+ Rc<DxvkImage> dxvkImage = texture->GetImage();
+ if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
+ Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(res=", pResource,") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
+ return false;
+ }
+
+ // The d3d11 nvapi provides us a texture but vulkan only lets us get the GPU address from an imageview. So, make a private imageview and get the address from that...
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
+
+ const D3D11_COMMON_TEXTURE_DESC *texDesc = texture->Desc();
+ if (texDesc->ArraySize != 1) {
+ Logger::debug(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - unexpected array size: ", texDesc->ArraySize));
+ }
+ resourceViewDesc.Format = texDesc->Format;
+ resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ resourceViewDesc.Texture2D.MostDetailedMip = 0;
+ resourceViewDesc.Texture2D.MipLevels = texDesc->MipLevels;
+
+ Com<ID3D11ShaderResourceView> pNewSRV;
+ HRESULT hr = m_device->CreateShaderResourceView(pResource, &resourceViewDesc, &pNewSRV);
+ if (FAILED(hr)) {
+ Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - private CreateShaderResourceView() failed");
+ return false;
+ }
+
+ Rc<DxvkImageView> dxvkImageView = static_cast<D3D11ShaderResourceView*>(pNewSRV.ptr())->GetImageView();
+ VkImageView vkImageView = dxvkImageView->handle();
+
+ VkImageViewAddressPropertiesNVX imageViewAddressProperties = {VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX};
+
+ VkResult res = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice, vkImageView, &imageViewAddressProperties);
+ if (res != VK_SUCCESS) {
+ Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): vkGetImageViewAddressNVX() result is failure: ", res));
+ return false;
+ }
+
+ *gpuVAStart = imageViewAddressProperties.deviceAddress;
+ *gpuVASize = imageViewAddressProperties.size;
+ }
+ else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ D3D11Buffer *buffer = GetCommonBuffer(pResource);
+ const DxvkBufferSliceHandle bufSliceHandle = buffer->GetBuffer()->getSliceHandle();
+ VkBuffer vkBuffer = bufSliceHandle.handle;
+
+ VkBufferDeviceAddressInfoKHR bdaInfo = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR };
+ bdaInfo.buffer = vkBuffer;
+ VkDeviceAddress bufAddr = dxvkDevice->vkd()->vkGetBufferDeviceAddressKHR(vkDevice, &bdaInfo);
+ *gpuVAStart = uint64_t(bufAddr) + bufSliceHandle.offset;
+ *gpuVASize = bufSliceHandle.length;
+ }
+
+ if (!*gpuVAStart)
+ Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() addr==0 - unexpected"); // ... but not explicitly a failure; continue
+
+ return true;
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAV, uint32_t* pDriverHandle) {
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
+ Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
+ return false;
+ }
+ if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
+ Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
+ return false;
+ }
+
+ auto texture = GetCommonTexture(pResource);
+ Rc<DxvkImage> dxvkImage = texture->GetImage();
+ if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
+ Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
+ return false;
+ }
+
+ if (!SUCCEEDED(m_device->CreateUnorderedAccessView(pResource, pDesc, ppUAV))) {
+ return false;
+ }
+
+ D3D11UnorderedAccessView *pUAV = static_cast<D3D11UnorderedAccessView *>(*ppUAV);
+ Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
+ VkDevice vkDevice = dxvkDevice->handle();
+
+ VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
+ Rc<DxvkImageView> dxvkImageView = pUAV->GetImageView();
+ VkImageView vkImageView = dxvkImageView->handle();
+
+ imageViewHandleInfo.imageView = vkImageView;
+ imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+
+ *pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
+
+ if (!*pDriverHandle) {
+ Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() handle==0 - failure");
+ pUAV->Release();
+ return false;
+ }
+
+ return true;
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) {
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
+ Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
+ return false;
+ }
+ if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
+ Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
+ return false;
+ }
+
+ auto texture = GetCommonTexture(pResource);
+ Rc<DxvkImage> dxvkImage = texture->GetImage();
+ if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
+ Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
+ return false;
+ }
+
+ if (!SUCCEEDED(m_device->CreateShaderResourceView(pResource, pDesc, ppSRV))) {
+ return false;
+ }
+
+ D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(*ppSRV);
+ Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
+ VkDevice vkDevice = dxvkDevice->handle();
+
+ VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
+ Rc<DxvkImageView> dxvkImageView = pSRV->GetImageView();
+ VkImageView vkImageView = dxvkImageView->handle();
+
+ imageViewHandleInfo.imageView = vkImageView;
+ imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+
+ *pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
+
+ if (!*pDriverHandle) {
+ Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() handle==0 - failure");
+ pSRV->Release();
+ return false;
+ }
+
+ // will need to look-up resource from uint32 handle later
+ AddSrvAndHandleNVX(*ppSRV, *pDriverHandle);
+ return true;
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) {
+ if (!SUCCEEDED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState))) {
+ return false;
+ }
+
+ // for our purposes the actual value doesn't matter, only its uniqueness
+ static std::atomic<ULONG> s_seqNum = 0;
+ *pDriverHandle = ++s_seqNum;
+
+ // will need to look-up sampler from uint32 handle later
+ AddSamplerAndHandleNVX(*ppSamplerState, *pDriverHandle);
+ return true;
+ }
+
+
+ void D3D11DeviceExt::AddSamplerAndHandleNVX(ID3D11SamplerState* pSampler, uint32_t Handle) {
+ std::lock_guard lock(m_mapLock);
+ m_samplerHandleToPtr[Handle] = pSampler;
+ }
+
+
+ ID3D11SamplerState* D3D11DeviceExt::HandleToSamplerNVX(uint32_t Handle) {
+ std::lock_guard lock(m_mapLock);
+ auto got = m_samplerHandleToPtr.find(Handle);
+
+ if (got == m_samplerHandleToPtr.end())
+ return nullptr;
+
+ return static_cast<ID3D11SamplerState*>(got->second);
+ }
+
+
+ void D3D11DeviceExt::AddSrvAndHandleNVX(ID3D11ShaderResourceView* pSrv, uint32_t Handle) {
+ std::lock_guard lock(m_mapLock);
+ m_srvHandleToPtr[Handle] = pSrv;
+ }
+
+
+ ID3D11ShaderResourceView* D3D11DeviceExt::HandleToSrvNVX(uint32_t Handle) {
+ std::lock_guard lock(m_mapLock);
+ auto got = m_srvHandleToPtr.find(Handle);
+
+ if (got == m_srvHandleToPtr.end())
+ return nullptr;
+
+ return static_cast<ID3D11ShaderResourceView*>(got->second);
+ }
+
+
+
+
+
+ D3D11VideoDevice::D3D11VideoDevice(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice)
+ : m_container(pContainer), m_device(pDevice) {
+
+ }
+
+
+ D3D11VideoDevice::~D3D11VideoDevice() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VideoDevice::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VideoDevice::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoDecoder(
+ const D3D11_VIDEO_DECODER_DESC* pVideoDesc,
+ const D3D11_VIDEO_DECODER_CONFIG* pConfig,
+ ID3D11VideoDecoder** ppDecoder) {
+ Logger::err("D3D11VideoDevice::CreateVideoDecoder: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessor(
+ ID3D11VideoProcessorEnumerator* pEnum,
+ UINT RateConversionIndex,
+ ID3D11VideoProcessor** ppVideoProcessor) {
+ try {
+ auto enumerator = static_cast<D3D11VideoProcessorEnumerator*>(pEnum);
+ *ppVideoProcessor = ref(new D3D11VideoProcessor(m_device, enumerator, RateConversionIndex));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_FAIL;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateAuthenticatedChannel(
+ D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType,
+ ID3D11AuthenticatedChannel** ppAuthenticatedChannel) {
+ Logger::err("D3D11VideoDevice::CreateAuthenticatedChannel: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateCryptoSession(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ const GUID* pKeyExchangeType,
+ ID3D11CryptoSession** ppCryptoSession) {
+ Logger::err("D3D11VideoDevice::CreateCryptoSession: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoDecoderOutputView(
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc,
+ ID3D11VideoDecoderOutputView** ppVDOVView) {
+ Logger::err("D3D11VideoDevice::CreateVideoDecoderOutputView: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorInputView(
+ ID3D11Resource* pResource,
+ ID3D11VideoProcessorEnumerator* pEnum,
+ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc,
+ ID3D11VideoProcessorInputView** ppVPIView) {
+ try {
+ *ppVPIView = ref(new D3D11VideoProcessorInputView(m_device, pResource, *pDesc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_FAIL;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorOutputView(
+ ID3D11Resource* pResource,
+ ID3D11VideoProcessorEnumerator* pEnum,
+ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc,
+ ID3D11VideoProcessorOutputView** ppVPOView) {
+ try {
+ *ppVPOView = ref(new D3D11VideoProcessorOutputView(m_device, pResource, *pDesc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_FAIL;
+ }
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorEnumerator(
+ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc,
+ ID3D11VideoProcessorEnumerator** ppEnum) {
+ try {
+ *ppEnum = ref(new D3D11VideoProcessorEnumerator(m_device, *pDesc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_FAIL;
+ }
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderProfileCount() {
+ Logger::err("D3D11VideoDevice::GetVideoDecoderProfileCount: Stub");
+ return 0;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderProfile(
+ UINT Index,
+ GUID* pDecoderProfile) {
+ Logger::err("D3D11VideoDevice::GetVideoDecoderProfile: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CheckVideoDecoderFormat(
+ const GUID* pDecoderProfile,
+ DXGI_FORMAT Format,
+ BOOL* pSupported) {
+ Logger::err("D3D11VideoDevice::CheckVideoDecoderFormat: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderConfigCount(
+ const D3D11_VIDEO_DECODER_DESC* pDesc,
+ UINT* pCount) {
+ Logger::err("D3D11VideoDevice::GetVideoDecoderConfigCount: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderConfig(
+ const D3D11_VIDEO_DECODER_DESC* pDesc,
+ UINT Index,
+ D3D11_VIDEO_DECODER_CONFIG* pConfig) {
+ Logger::err("D3D11VideoDevice::GetVideoDecoderConfig: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetContentProtectionCaps(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps) {
+ Logger::err("D3D11VideoDevice::GetContentProtectionCaps: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CheckCryptoKeyExchange(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ UINT Index,
+ GUID* pKeyExchangeType) {
+ Logger::err("D3D11VideoDevice::CheckCryptoKeyExchange: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData) {
+ return m_container->SetPrivateData(Name, DataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoDevice::SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pData) {
+ return m_container->SetPrivateDataInterface(Name, pData);
+ }
+
+
+
+
+ WineDXGISwapChainFactory::WineDXGISwapChainFactory(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice)
+ : m_container(pContainer), m_device(pDevice) {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() {
+ return m_device->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() {
+ return m_device->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_device->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::CreateSwapChainForHwnd(
+ IDXGIFactory* pFactory,
+ HWND hWnd,
+ const DXGI_SWAP_CHAIN_DESC1* pDesc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
+ IDXGIOutput* pRestrictToOutput,
+ IDXGISwapChain1** ppSwapChain) {
+ InitReturnPtr(ppSwapChain);
+
+ if (!ppSwapChain || !pDesc || !hWnd)
+ return DXGI_ERROR_INVALID_CALL;
+
+ // Make sure the back buffer size is not zero
+ DXGI_SWAP_CHAIN_DESC1 desc = *pDesc;
+
+ wsi::getWindowSize(hWnd,
+ desc.Width ? nullptr : &desc.Width,
+ desc.Height ? nullptr : &desc.Height);
+
+ // If necessary, set up a default set of
+ // fullscreen parameters for the swap chain
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc;
+
+ if (pFullscreenDesc) {
+ fsDesc = *pFullscreenDesc;
+ } else {
+ fsDesc.RefreshRate = { 0, 0 };
+ fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ fsDesc.Windowed = TRUE;
+ }
+
+ try {
+ // Create presenter for the device
+ Com<D3D11SwapChain> presenter = new D3D11SwapChain(
+ m_container, m_device, hWnd, &desc);
+
+ // Create the actual swap chain
+ *ppSwapChain = ref(new DxgiSwapChain(
+ pFactory, presenter.ptr(), hWnd, &desc, &fsDesc));
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+
+
+
+ DXGIDXVKDevice::DXGIDXVKDevice(D3D11DXGIDevice* pContainer)
+ : m_container(pContainer), m_apiVersion(11) {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE DXGIDXVKDevice::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE DXGIDXVKDevice::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE DXGIDXVKDevice::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ void STDMETHODCALLTYPE DXGIDXVKDevice::SetAPIVersion(
+ UINT Version) {
+ m_apiVersion = Version;
+ }
+
+
+ UINT STDMETHODCALLTYPE DXGIDXVKDevice::GetAPIVersion() {
+ return m_apiVersion;
+ }
+
+
+
+
+ D3D11DXGIDevice::D3D11DXGIDevice(
+ IDXGIAdapter* pAdapter,
+ const Rc<DxvkInstance>& pDxvkInstance,
+ const Rc<DxvkAdapter>& pDxvkAdapter,
+ D3D_FEATURE_LEVEL FeatureLevel,
+ UINT FeatureFlags)
+ : m_dxgiAdapter (pAdapter),
+ m_dxvkInstance (pDxvkInstance),
+ m_dxvkAdapter (pDxvkAdapter),
+ m_dxvkDevice (CreateDevice(FeatureLevel)),
+ m_d3d11Device (this, FeatureLevel, FeatureFlags),
+ m_d3d11DeviceExt(this, &m_d3d11Device),
+ m_d3d11Interop (this, &m_d3d11Device),
+ m_d3d11Video (this, &m_d3d11Device),
+ m_metaDevice (this),
+ m_wineFactory (this, &m_d3d11Device) {
+
+ }
+
+
+ D3D11DXGIDevice::~D3D11DXGIDevice() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(IDXGIObject)
+ || riid == __uuidof(IDXGIDevice)
+ || riid == __uuidof(IDXGIDevice1)
+ || riid == __uuidof(IDXGIDevice2)
+ || riid == __uuidof(IDXGIDevice3)
+ || riid == __uuidof(IDXGIDevice4)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIVkInteropDevice)
+ || riid == __uuidof(IDXGIVkInteropDevice1)) {
+ *ppvObject = ref(&m_d3d11Interop);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10Device)
+ || riid == __uuidof(ID3D10Device1)) {
+ *ppvObject = ref(m_d3d11Device.GetD3D10Interface());
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D11Device)
+ || riid == __uuidof(ID3D11Device1)
+ || riid == __uuidof(ID3D11Device2)
+ || riid == __uuidof(ID3D11Device3)
+ || riid == __uuidof(ID3D11Device4)
+ || riid == __uuidof(ID3D11Device5)) {
+ *ppvObject = ref(&m_d3d11Device);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D11VkExtDevice)
+ || riid == __uuidof(ID3D11VkExtDevice1)) {
+ *ppvObject = ref(&m_d3d11DeviceExt);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIDXVKDevice)) {
+ *ppvObject = ref(&m_metaDevice);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IWineDXGISwapChainFactory)) {
+ *ppvObject = ref(&m_wineFactory);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D11VideoDevice)) {
+ *ppvObject = ref(&m_d3d11Video);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10Multithread)) {
+ Com<ID3D11DeviceContext> context;
+ m_d3d11Device.GetImmediateContext(&context);
+ return context->QueryInterface(riid, ppvObject);
+ }
+
+ if (riid == __uuidof(ID3D11Debug))
+ return E_NOINTERFACE;
+
+ // Undocumented interfaces that are queried by some games
+ if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}})
+ return E_NOINTERFACE;
+
+ Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetParent(
+ REFIID riid,
+ void** ppParent) {
+ return m_dxgiAdapter->QueryInterface(riid, ppParent);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::CreateSurface(
+ const DXGI_SURFACE_DESC* pDesc,
+ UINT NumSurfaces,
+ DXGI_USAGE Usage,
+ const DXGI_SHARED_RESOURCE* pSharedResource,
+ IDXGISurface** ppSurface) {
+ if (!pDesc || (NumSurfaces && !ppSurface))
+ return E_INVALIDARG;
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = pDesc->SampleDesc;
+ desc.BindFlags = 0;
+ desc.MiscFlags = 0;
+
+ // Handle bind flags
+ if (Usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
+ desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
+
+ if (Usage & DXGI_USAGE_SHADER_INPUT)
+ desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+
+ if (Usage & DXGI_USAGE_UNORDERED_ACCESS)
+ desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
+ // Handle CPU access flags
+ switch (Usage & DXGI_CPU_ACCESS_FIELD) {
+ case DXGI_CPU_ACCESS_NONE:
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.CPUAccessFlags = 0;
+ break;
+
+ case DXGI_CPU_ACCESS_DYNAMIC:
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ break;
+
+ case DXGI_CPU_ACCESS_READ_WRITE:
+ case DXGI_CPU_ACCESS_SCRATCH:
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ // Restrictions and limitations of CreateSurface are not
+ // well-documented, so we'll be a lenient on validation.
+ HRESULT hr = m_d3d11Device.CreateTexture2D(&desc, nullptr, nullptr);
+
+ if (FAILED(hr))
+ return hr;
+
+ // We don't support shared resources
+ if (NumSurfaces && pSharedResource)
+ Logger::err("D3D11: CreateSurface: Shared surfaces not supported");
+
+ // Try to create the given number of surfaces
+ uint32_t surfacesCreated = 0;
+ hr = S_OK;
+
+ for (uint32_t i = 0; i < NumSurfaces; i++) {
+ Com<ID3D11Texture2D> texture;
+
+ hr = m_d3d11Device.CreateTexture2D(&desc, nullptr, &texture);
+
+ if (SUCCEEDED(hr)) {
+ hr = texture->QueryInterface(__uuidof(IDXGISurface),
+ reinterpret_cast<void**>(&ppSurface[i]));
+ surfacesCreated = i + 1;
+ }
+
+ if (FAILED(hr))
+ break;
+ }
+
+ // Don't leak surfaces if we failed to create one
+ if (FAILED(hr)) {
+ for (uint32_t i = 0; i < surfacesCreated; i++)
+ ppSurface[i]->Release();
+ }
+
+ return hr;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetAdapter(
+ IDXGIAdapter** pAdapter) {
+ if (pAdapter == nullptr)
+ return DXGI_ERROR_INVALID_CALL;
+
+ *pAdapter = m_dxgiAdapter.ref();
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetGPUThreadPriority(
+ INT* pPriority) {
+ *pPriority = 0;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryResourceResidency(
+ IUnknown* const* ppResources,
+ DXGI_RESIDENCY* pResidencyStatus,
+ UINT NumResources) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::err("D3D11DXGIDevice::QueryResourceResidency: Stub");
+
+ if (!ppResources || !pResidencyStatus)
+ return E_INVALIDARG;
+
+ for (uint32_t i = 0; i < NumResources; i++)
+ pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT;
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetGPUThreadPriority(
+ INT Priority) {
+ if (Priority < -7 || Priority > 7)
+ return E_INVALIDARG;
+
+ Logger::err("DXGI: SetGPUThreadPriority: Ignoring");
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetMaximumFrameLatency(
+ UINT* pMaxLatency) {
+ if (!pMaxLatency)
+ return DXGI_ERROR_INVALID_CALL;
+
+ *pMaxLatency = m_frameLatency;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetMaximumFrameLatency(
+ UINT MaxLatency) {
+ if (MaxLatency == 0)
+ MaxLatency = DefaultFrameLatency;
+
+ if (MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS)
+ return DXGI_ERROR_INVALID_CALL;
+
+ m_frameLatency = MaxLatency;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_OFFER_RESOURCE_PRIORITY Priority) {
+ return OfferResources1(NumResources, ppResources, Priority, 0);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources1(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_OFFER_RESOURCE_PRIORITY Priority,
+ UINT Flags) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11DXGIDevice::OfferResources1: Stub");
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ BOOL* pDiscarded) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11DXGIDevice::ReclaimResources: Stub");
+
+ if (pDiscarded)
+ *pDiscarded = false;
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources1(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_RECLAIM_RESOURCE_RESULTS* pResults) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11DXGIDevice::ReclaimResources1: Stub");
+
+ if (pResults) {
+ for (uint32_t i = 0; i < NumResources; i++)
+ pResults[i] = DXGI_RECLAIM_RESOURCE_RESULT_OK;
+ }
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
+ Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented");
+ return DXGI_ERROR_UNSUPPORTED;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DXGIDevice::Trim() {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11DXGIDevice::Trim: Stub");
+ }
+
+
+ Rc<DxvkDevice> STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() {
+ return m_dxvkDevice;
+ }
+
+
+ Rc<DxvkDevice> D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) {
+ DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter, FeatureLevel);
+ return m_dxvkAdapter->createDevice(m_dxvkInstance, deviceFeatures);
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.h
new file mode 100644
index 00000000..7de5cf91
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device.h
@@ -0,0 +1,857 @@
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+#include "../dxbc/dxbc_options.h"
+
+#include "../dxgi/dxgi_object.h"
+#include "../dxgi/dxgi_interfaces.h"
+
+#include "../dxvk/dxvk_cs.h"
+
+#include "../d3d10/d3d10_device.h"
+
+#include "../util/com/com_private_data.h"
+
+#include "d3d11_cmdlist.h"
+#include "d3d11_cuda.h"
+#include "d3d11_initializer.h"
+#include "d3d11_interfaces.h"
+#include "d3d11_interop.h"
+#include "d3d11_options.h"
+#include "d3d11_shader.h"
+#include "d3d11_state.h"
+#include "d3d11_util.h"
+
+namespace dxvk {
+ class DxgiAdapter;
+
+ class D3D11Buffer;
+ class D3D11CommonShader;
+ class D3D11CommonTexture;
+ class D3D11Counter;
+ class D3D11DeviceContext;
+ class D3D11DXGIDevice;
+ class D3D11ImmediateContext;
+ class D3D11Predicate;
+ class D3D11Query;
+ class D3D11Texture1D;
+ class D3D11Texture2D;
+ class D3D11Texture3D;
+
+ /**
+ * \brief D3D11 device implementation
+ *
+ * Implements the ID3D11Device interfaces
+ * as part of a \ref D3D11DeviceContainer.
+ */
+ class D3D11Device final : public ID3D11Device5 {
+ /// Maximum number of resource init commands per command buffer
+ constexpr static uint64_t InitCommandThreshold = 50;
+ public:
+
+ D3D11Device(
+ D3D11DXGIDevice* pContainer,
+ D3D_FEATURE_LEVEL FeatureLevel,
+ UINT FeatureFlags);
+
+ ~D3D11Device();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE CreateBuffer(
+ const D3D11_BUFFER_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Buffer** ppBuffer);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture1D(
+ const D3D11_TEXTURE1D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture1D** ppTexture1D);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture2D(
+ const D3D11_TEXTURE2D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture2D** ppTexture2D);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture2D1(
+ const D3D11_TEXTURE2D_DESC1* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture2D1** ppTexture2D);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture3D(
+ const D3D11_TEXTURE3D_DESC* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture3D** ppTexture3D);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture3D1(
+ const D3D11_TEXTURE3D_DESC1* pDesc,
+ const D3D11_SUBRESOURCE_DATA* pInitialData,
+ ID3D11Texture3D1** ppTexture3D);
+
+ HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ ID3D11ShaderResourceView** ppSRView);
+
+ HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
+ ID3D11ShaderResourceView1** ppSRView);
+
+ HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ ID3D11UnorderedAccessView** ppUAView);
+
+ HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView1(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
+ ID3D11UnorderedAccessView1** ppUAView);
+
+ HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
+ ID3D11RenderTargetView** ppRTView);
+
+ HRESULT STDMETHODCALLTYPE CreateRenderTargetView1(
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc,
+ ID3D11RenderTargetView1** ppRTView);
+
+ HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
+ ID3D11Resource* pResource,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
+ ID3D11DepthStencilView** ppDepthStencilView);
+
+ HRESULT STDMETHODCALLTYPE CreateInputLayout(
+ const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
+ UINT NumElements,
+ const void* pShaderBytecodeWithInputSignature,
+ SIZE_T BytecodeLength,
+ ID3D11InputLayout** ppInputLayout);
+
+ HRESULT STDMETHODCALLTYPE CreateVertexShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11VertexShader** ppVertexShader);
+
+ HRESULT STDMETHODCALLTYPE CreateGeometryShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11GeometryShader** ppGeometryShader);
+
+ HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
+ UINT NumEntries,
+ const UINT* pBufferStrides,
+ UINT NumStrides,
+ UINT RasterizedStream,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11GeometryShader** ppGeometryShader);
+
+ HRESULT STDMETHODCALLTYPE CreatePixelShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11PixelShader** ppPixelShader);
+
+ HRESULT STDMETHODCALLTYPE CreateHullShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11HullShader** ppHullShader);
+
+ HRESULT STDMETHODCALLTYPE CreateDomainShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11DomainShader** ppDomainShader);
+
+ HRESULT STDMETHODCALLTYPE CreateComputeShader(
+ const void* pShaderBytecode,
+ SIZE_T BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ ID3D11ComputeShader** ppComputeShader);
+
+ HRESULT STDMETHODCALLTYPE CreateClassLinkage(
+ ID3D11ClassLinkage** ppLinkage);
+
+ HRESULT STDMETHODCALLTYPE CreateBlendState(
+ const D3D11_BLEND_DESC* pBlendStateDesc,
+ ID3D11BlendState** ppBlendState);
+
+ HRESULT STDMETHODCALLTYPE CreateBlendState1(
+ const D3D11_BLEND_DESC1* pBlendStateDesc,
+ ID3D11BlendState1** ppBlendState);
+
+ HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
+ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
+ ID3D11DepthStencilState** ppDepthStencilState);
+
+ HRESULT STDMETHODCALLTYPE CreateRasterizerState(
+ const D3D11_RASTERIZER_DESC* pRasterizerDesc,
+ ID3D11RasterizerState** ppRasterizerState);
+
+ HRESULT STDMETHODCALLTYPE CreateRasterizerState1(
+ const D3D11_RASTERIZER_DESC1* pRasterizerDesc,
+ ID3D11RasterizerState1** ppRasterizerState);
+
+ HRESULT STDMETHODCALLTYPE CreateRasterizerState2(
+ const D3D11_RASTERIZER_DESC2* pRasterizerDesc,
+ ID3D11RasterizerState2** ppRasterizerState);
+
+ HRESULT STDMETHODCALLTYPE CreateSamplerState(
+ const D3D11_SAMPLER_DESC* pSamplerDesc,
+ ID3D11SamplerState** ppSamplerState);
+
+ HRESULT STDMETHODCALLTYPE CreateQuery(
+ const D3D11_QUERY_DESC* pQueryDesc,
+ ID3D11Query** ppQuery);
+
+ HRESULT STDMETHODCALLTYPE CreateQuery1(
+ const D3D11_QUERY_DESC1* pQueryDesc,
+ ID3D11Query1** ppQuery);
+
+ HRESULT STDMETHODCALLTYPE CreatePredicate(
+ const D3D11_QUERY_DESC* pPredicateDesc,
+ ID3D11Predicate** ppPredicate);
+
+ HRESULT STDMETHODCALLTYPE CreateCounter(
+ const D3D11_COUNTER_DESC* pCounterDesc,
+ ID3D11Counter** ppCounter);
+
+ HRESULT STDMETHODCALLTYPE CreateDeferredContext(
+ UINT ContextFlags,
+ ID3D11DeviceContext** ppDeferredContext);
+
+ HRESULT STDMETHODCALLTYPE CreateDeferredContext1(
+ UINT ContextFlags,
+ ID3D11DeviceContext1** ppDeferredContext);
+
+ HRESULT STDMETHODCALLTYPE CreateDeferredContext2(
+ UINT ContextFlags,
+ ID3D11DeviceContext2** ppDeferredContext);
+
+ HRESULT STDMETHODCALLTYPE CreateDeferredContext3(
+ UINT ContextFlags,
+ ID3D11DeviceContext3** ppDeferredContext);
+
+ HRESULT STDMETHODCALLTYPE CreateDeviceContextState(
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ REFIID EmulatedInterface,
+ D3D_FEATURE_LEVEL* pChosenFeatureLevel,
+ ID3DDeviceContextState** ppContextState);
+
+ HRESULT STDMETHODCALLTYPE CreateFence(
+ UINT64 InitialValue,
+ D3D11_FENCE_FLAG Flags,
+ REFIID ReturnedInterface,
+ void** ppFence);
+
+ void STDMETHODCALLTYPE ReadFromSubresource(
+ void* pDstData,
+ UINT DstRowPitch,
+ UINT DstDepthPitch,
+ ID3D11Resource* pSrcResource,
+ UINT SrcSubresource,
+ const D3D11_BOX* pSrcBox);
+
+ void STDMETHODCALLTYPE WriteToSubresource(
+ ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch);
+
+ HRESULT STDMETHODCALLTYPE OpenSharedResource(
+ HANDLE hResource,
+ REFIID ReturnedInterface,
+ void** ppResource);
+
+ HRESULT STDMETHODCALLTYPE OpenSharedResource1(
+ HANDLE hResource,
+ REFIID returnedInterface,
+ void** ppResource);
+
+ HRESULT STDMETHODCALLTYPE OpenSharedResourceByName(
+ LPCWSTR lpName,
+ DWORD dwDesiredAccess,
+ REFIID returnedInterface,
+ void** ppResource);
+
+ HRESULT STDMETHODCALLTYPE OpenSharedFence(
+ HANDLE hFence,
+ REFIID ReturnedInterface,
+ void** ppFence);
+
+ HRESULT STDMETHODCALLTYPE CheckFormatSupport(
+ DXGI_FORMAT Format,
+ UINT* pFormatSupport);
+
+ HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
+ DXGI_FORMAT Format,
+ UINT SampleCount,
+ UINT* pNumQualityLevels);
+
+ HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels1(
+ DXGI_FORMAT Format,
+ UINT SampleCount,
+ UINT Flags,
+ UINT* pNumQualityLevels);
+
+ void STDMETHODCALLTYPE CheckCounterInfo(
+ D3D11_COUNTER_INFO* pCounterInfo);
+
+ HRESULT STDMETHODCALLTYPE CheckCounter(
+ const D3D11_COUNTER_DESC* pDesc,
+ D3D11_COUNTER_TYPE* pType,
+ UINT* pActiveCounters,
+ LPSTR szName,
+ UINT* pNameLength,
+ LPSTR szUnits,
+ UINT* pUnitsLength,
+ LPSTR szDescription,
+ UINT* pDescriptionLength);
+
+ HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
+ D3D11_FEATURE Feature,
+ void* pFeatureSupportData,
+ UINT FeatureSupportDataSize);
+
+ HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID Name,
+ UINT *pDataSize,
+ void *pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void *pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown *pUnknown);
+
+ D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel();
+
+ UINT STDMETHODCALLTYPE GetCreationFlags();
+
+ HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason();
+
+ void STDMETHODCALLTYPE GetImmediateContext(
+ ID3D11DeviceContext** ppImmediateContext);
+
+ void STDMETHODCALLTYPE GetImmediateContext1(
+ ID3D11DeviceContext1** ppImmediateContext);
+
+ void STDMETHODCALLTYPE GetImmediateContext2(
+ ID3D11DeviceContext2** ppImmediateContext);
+
+ void STDMETHODCALLTYPE GetImmediateContext3(
+ ID3D11DeviceContext3** ppImmediateContext);
+
+ HRESULT STDMETHODCALLTYPE SetExceptionMode(UINT RaiseFlags);
+
+ UINT STDMETHODCALLTYPE GetExceptionMode();
+
+ void STDMETHODCALLTYPE GetResourceTiling(
+ ID3D11Resource* pTiledResource,
+ UINT* pNumTilesForEntireResource,
+ D3D11_PACKED_MIP_DESC* pPackedMipDesc,
+ D3D11_TILE_SHAPE* pStandardTileShapeForNonPackedMips,
+ UINT* pNumSubresourceTilings,
+ UINT FirstSubresourceTilingToGet,
+ D3D11_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips);
+
+ HRESULT STDMETHODCALLTYPE RegisterDeviceRemovedEvent(
+ HANDLE hEvent,
+ DWORD* pdwCookie);
+
+ void STDMETHODCALLTYPE UnregisterDeviceRemoved(
+ DWORD dwCookie);
+
+ Rc<DxvkDevice> GetDXVKDevice() {
+ return m_dxvkDevice;
+ }
+
+ void FlushInitContext();
+
+ VkPipelineStageFlags GetEnabledShaderStages() const {
+ return m_dxvkDevice->getShaderPipelineStages();
+ }
+
+ DXGI_VK_FORMAT_INFO LookupFormat(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const;
+
+ DXGI_VK_FORMAT_INFO LookupPackedFormat(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const;
+
+ DXGI_VK_FORMAT_FAMILY LookupFamily(
+ DXGI_FORMAT Format,
+ DXGI_VK_FORMAT_MODE Mode) const;
+
+ DxvkCsChunkRef AllocCsChunk(DxvkCsChunkFlags flags) {
+ DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags);
+ return DxvkCsChunkRef(chunk, &m_csChunkPool);
+ }
+
+ const D3D11Options* GetOptions() const {
+ return &m_d3d11Options;
+ }
+
+ D3D10Device* GetD3D10Interface() const {
+ return m_d3d10Device;
+ }
+
+ static bool CheckFeatureLevelSupport(
+ const Rc<DxvkInstance>& instance,
+ const Rc<DxvkAdapter>& adapter,
+ D3D_FEATURE_LEVEL featureLevel);
+
+ static DxvkDeviceFeatures GetDeviceFeatures(
+ const Rc<DxvkAdapter>& adapter,
+ D3D_FEATURE_LEVEL featureLevel);
+
+ private:
+
+ IDXGIObject* m_container;
+
+ D3D_FEATURE_LEVEL m_featureLevel;
+ UINT m_featureFlags;
+
+ const Rc<DxvkDevice> m_dxvkDevice;
+ const Rc<DxvkAdapter> m_dxvkAdapter;
+
+ const DXGIVkFormatTable m_d3d11Formats;
+ const D3D11Options m_d3d11Options;
+ const DxbcOptions m_dxbcOptions;
+
+ DxvkCsChunkPool m_csChunkPool;
+
+ D3D11Initializer* m_initializer = nullptr;
+ D3D10Device* m_d3d10Device = nullptr;
+ Com<D3D11ImmediateContext, false> m_context;
+
+ D3D11StateObjectSet<D3D11BlendState> m_bsStateObjects;
+ D3D11StateObjectSet<D3D11DepthStencilState> m_dsStateObjects;
+ D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
+ D3D11StateObjectSet<D3D11SamplerState> m_samplerObjects;
+ D3D11ShaderModuleSet m_shaderModules;
+
+ HRESULT CreateShaderModule(
+ D3D11CommonShader* pShaderModule,
+ DxvkShaderKey ShaderKey,
+ const void* pShaderBytecode,
+ size_t BytecodeLength,
+ ID3D11ClassLinkage* pClassLinkage,
+ const DxbcModuleInfo* pModuleInfo);
+
+ HRESULT GetFormatSupportFlags(
+ DXGI_FORMAT Format,
+ UINT* pFlags1,
+ UINT* pFlags2) const;
+
+ BOOL GetImageTypeSupport(
+ VkFormat Format,
+ VkImageType Type) const;
+
+ uint32_t GetViewPlaneIndex(
+ ID3D11Resource* pResource,
+ DXGI_FORMAT ViewFormat);
+
+ template<typename Void>
+ void CopySubresourceData(
+ Void* pData,
+ UINT RowPitch,
+ UINT DepthPitch,
+ ID3D11Resource* pResource,
+ UINT Subresource,
+ const D3D11_BOX* pBox);
+
+ static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
+ const Rc<DxvkInstance>& pInstance);
+
+ };
+
+
+ /**
+ * \brief Extended D3D11 device
+ */
+ class D3D11DeviceExt : public ID3D11VkExtDevice1 {
+
+ public:
+
+ D3D11DeviceExt(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice);
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ BOOL STDMETHODCALLTYPE GetExtensionSupport(
+ D3D11_VK_EXTENSION Extension);
+
+ bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
+ uint32_t srvDriverHandle,
+ uint32_t samplerDriverHandle,
+ uint32_t* pCudaTextureHandle);
+
+ bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
+ const void* pCubin,
+ uint32_t size,
+ uint32_t blockX,
+ uint32_t blockY,
+ uint32_t blockZ,
+ const char* pShaderName,
+ IUnknown** phShader);
+
+ bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
+ void* hObject,
+ uint64_t* gpuVAStart,
+ uint64_t* gpuVASize);
+
+ bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ ID3D11UnorderedAccessView** ppUAV,
+ uint32_t* pDriverHandle);
+
+ bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ ID3D11ShaderResourceView** ppSRV,
+ uint32_t* pDriverHandle);
+
+ bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
+ const D3D11_SAMPLER_DESC* pSamplerDesc,
+ ID3D11SamplerState** ppSamplerState,
+ uint32_t* pDriverHandle);
+
+ private:
+
+ D3D11DXGIDevice* m_container;
+ D3D11Device* m_device;
+
+ void AddSamplerAndHandleNVX(
+ ID3D11SamplerState* pSampler,
+ uint32_t Handle);
+
+ ID3D11SamplerState* HandleToSamplerNVX(
+ uint32_t Handle);
+
+ void AddSrvAndHandleNVX(
+ ID3D11ShaderResourceView* pSrv,
+ uint32_t Handle);
+
+ ID3D11ShaderResourceView* HandleToSrvNVX(
+ uint32_t Handle);
+
+ dxvk::mutex m_mapLock;
+ std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr;
+ std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
+ };
+
+
+ /**
+ * \brief D3D11 video device
+ */
+ class D3D11VideoDevice : public ID3D11VideoDevice {
+
+ public:
+
+ D3D11VideoDevice(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice);
+
+ ~D3D11VideoDevice();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoDecoder(
+ const D3D11_VIDEO_DECODER_DESC* pVideoDesc,
+ const D3D11_VIDEO_DECODER_CONFIG* pConfig,
+ ID3D11VideoDecoder** ppDecoder);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoProcessor(
+ ID3D11VideoProcessorEnumerator* pEnum,
+ UINT RateConversionIndex,
+ ID3D11VideoProcessor** ppVideoProcessor);
+
+ HRESULT STDMETHODCALLTYPE CreateAuthenticatedChannel(
+ D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType,
+ ID3D11AuthenticatedChannel** ppAuthenticatedChannel);
+
+ HRESULT STDMETHODCALLTYPE CreateCryptoSession(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ const GUID* pKeyExchangeType,
+ ID3D11CryptoSession** ppCryptoSession);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoDecoderOutputView(
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc,
+ ID3D11VideoDecoderOutputView** ppVDOVView);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoProcessorInputView(
+ ID3D11Resource* pResource,
+ ID3D11VideoProcessorEnumerator* pEnum,
+ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc,
+ ID3D11VideoProcessorInputView** ppVPIView);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoProcessorOutputView(
+ ID3D11Resource* pResource,
+ ID3D11VideoProcessorEnumerator* pEnum,
+ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc,
+ ID3D11VideoProcessorOutputView** ppVPOView);
+
+ HRESULT STDMETHODCALLTYPE CreateVideoProcessorEnumerator(
+ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc,
+ ID3D11VideoProcessorEnumerator** ppEnum);
+
+ UINT STDMETHODCALLTYPE GetVideoDecoderProfileCount();
+
+ HRESULT STDMETHODCALLTYPE GetVideoDecoderProfile(
+ UINT Index,
+ GUID* pDecoderProfile);
+
+ HRESULT STDMETHODCALLTYPE CheckVideoDecoderFormat(
+ const GUID* pDecoderProfile,
+ DXGI_FORMAT Format,
+ BOOL* pSupported);
+
+ HRESULT STDMETHODCALLTYPE GetVideoDecoderConfigCount(
+ const D3D11_VIDEO_DECODER_DESC* pDesc,
+ UINT* pCount);
+
+ HRESULT STDMETHODCALLTYPE GetVideoDecoderConfig(
+ const D3D11_VIDEO_DECODER_DESC* pDesc,
+ UINT Index,
+ D3D11_VIDEO_DECODER_CONFIG* pConfig);
+
+ HRESULT STDMETHODCALLTYPE GetContentProtectionCaps(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps);
+
+ HRESULT STDMETHODCALLTYPE CheckCryptoKeyExchange(
+ const GUID* pCryptoType,
+ const GUID* pDecoderProfile,
+ UINT Index,
+ GUID* pKeyExchangeType);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pData);
+
+ private:
+
+ D3D11DXGIDevice* m_container;
+ D3D11Device* m_device;
+
+ };
+
+
+ /**
+ * \brief DXGI swap chain factory
+ */
+ class WineDXGISwapChainFactory : public IWineDXGISwapChainFactory {
+
+ public:
+
+ WineDXGISwapChainFactory(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice);
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd(
+ IDXGIFactory* pFactory,
+ HWND hWnd,
+ const DXGI_SWAP_CHAIN_DESC1* pDesc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
+ IDXGIOutput* pRestrictToOutput,
+ IDXGISwapChain1** ppSwapChain);
+
+ private:
+
+ D3D11DXGIDevice* m_container;
+ D3D11Device* m_device;
+
+ };
+
+
+ /**
+ * \brief D3D11 device metadata shenanigans
+ */
+ class DXGIDXVKDevice : public IDXGIDXVKDevice {
+
+ public:
+
+ DXGIDXVKDevice(D3D11DXGIDevice* pContainer);
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE SetAPIVersion(
+ UINT Version);
+
+ UINT STDMETHODCALLTYPE GetAPIVersion();
+
+ private:
+
+ D3D11DXGIDevice* m_container;
+ UINT m_apiVersion;
+
+ };
+
+
+ /**
+ * \brief D3D11 device container
+ *
+ * Stores all the objects that contribute to the D3D11
+ * device implementation, including the DXGI device.
+ */
+ class D3D11DXGIDevice : public DxgiObject<IDXGIDevice4> {
+ constexpr static uint32_t DefaultFrameLatency = 3;
+ public:
+
+ D3D11DXGIDevice(
+ IDXGIAdapter* pAdapter,
+ const Rc<DxvkInstance>& pDxvkInstance,
+ const Rc<DxvkAdapter>& pDxvkAdapter,
+ D3D_FEATURE_LEVEL FeatureLevel,
+ UINT FeatureFlags);
+
+ ~D3D11DXGIDevice();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetParent(
+ REFIID riid,
+ void** ppParent);
+
+ HRESULT STDMETHODCALLTYPE CreateSurface(
+ const DXGI_SURFACE_DESC* pDesc,
+ UINT NumSurfaces,
+ DXGI_USAGE Usage,
+ const DXGI_SHARED_RESOURCE* pSharedResource,
+ IDXGISurface** ppSurface) final;
+
+ HRESULT STDMETHODCALLTYPE GetAdapter(
+ IDXGIAdapter** pAdapter) final;
+
+ HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(
+ INT* pPriority) final;
+
+ HRESULT STDMETHODCALLTYPE QueryResourceResidency(
+ IUnknown* const* ppResources,
+ DXGI_RESIDENCY* pResidencyStatus,
+ UINT NumResources) final;
+
+ HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(
+ INT Priority) final;
+
+ HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
+ UINT* pMaxLatency) final;
+
+ HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
+ UINT MaxLatency) final;
+
+ HRESULT STDMETHODCALLTYPE OfferResources(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_OFFER_RESOURCE_PRIORITY Priority) final;
+
+ HRESULT STDMETHODCALLTYPE OfferResources1(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_OFFER_RESOURCE_PRIORITY Priority,
+ UINT Flags) final;
+
+ HRESULT STDMETHODCALLTYPE ReclaimResources(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ BOOL* pDiscarded) final;
+
+ HRESULT STDMETHODCALLTYPE ReclaimResources1(
+ UINT NumResources,
+ IDXGIResource* const* ppResources,
+ DXGI_RECLAIM_RESOURCE_RESULTS* pResults) final;
+
+ HRESULT STDMETHODCALLTYPE EnqueueSetEvent(
+ HANDLE hEvent) final;
+
+ void STDMETHODCALLTYPE Trim() final;
+
+ Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();
+
+ private:
+
+ Com<IDXGIAdapter> m_dxgiAdapter;
+
+ Rc<DxvkInstance> m_dxvkInstance;
+ Rc<DxvkAdapter> m_dxvkAdapter;
+ Rc<DxvkDevice> m_dxvkDevice;
+
+ D3D11Device m_d3d11Device;
+ D3D11DeviceExt m_d3d11DeviceExt;
+ D3D11VkInterop m_d3d11Interop;
+ D3D11VideoDevice m_d3d11Video;
+ DXGIDXVKDevice m_metaDevice;
+
+ WineDXGISwapChainFactory m_wineFactory;
+
+ uint32_t m_frameLatency = DefaultFrameLatency;
+
+ Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device_child.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device_child.h
new file mode 100644
index 00000000..60eff07a
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_device_child.h
@@ -0,0 +1,130 @@
+#pragma once
+
+#include "d3d11_include.h"
+
+#include "../util/com/com_private_data.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ template<typename Base>
+ class D3D11DeviceObject : public Base {
+
+ public:
+
+ D3D11DeviceObject(D3D11Device* pDevice)
+ : m_parent(pDevice) {
+
+ }
+
+ HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID guid,
+ UINT *pDataSize,
+ void *pData) final {
+ return m_privateData.getData(
+ guid, pDataSize, pData);
+ }
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID guid,
+ UINT DataSize,
+ const void *pData) final {
+ return m_privateData.setData(
+ guid, DataSize, pData);
+ }
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID guid,
+ const IUnknown *pUnknown) final {
+ return m_privateData.setInterface(
+ guid, pUnknown);
+ }
+
+ void STDMETHODCALLTYPE GetDevice(
+ ID3D11Device** ppDevice) final {
+ *ppDevice = ref(GetParentInterface());
+ }
+
+ protected:
+
+ ID3D11Device* GetParentInterface() const {
+ // We don't know the definition of ID3D11Device
+ // here, because D3D11Device includes this file.
+ return reinterpret_cast<ID3D11Device*>(m_parent);
+ }
+
+ D3D11Device* const m_parent;
+
+ private:
+
+ ComPrivateData m_privateData;
+
+ };
+
+
+ template<typename Base>
+ class D3D11DeviceChild : public D3D11DeviceObject<ComObject<Base>> {
+
+ public:
+
+ D3D11DeviceChild(D3D11Device* pDevice)
+ : D3D11DeviceObject<ComObject<Base>>(pDevice) {
+
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() {
+ uint32_t refCount = this->m_refCount++;
+ if (unlikely(!refCount)) {
+ this->AddRefPrivate();
+ this->GetParentInterface()->AddRef();
+ }
+
+ return refCount + 1;
+ }
+
+ ULONG STDMETHODCALLTYPE Release() {
+ uint32_t refCount = --this->m_refCount;
+ if (unlikely(!refCount)) {
+ auto* parent = this->GetParentInterface();
+ this->ReleasePrivate();
+ parent->Release();
+ }
+ return refCount;
+ }
+
+ };
+
+ template<typename Base>
+ class D3D11StateObject : public D3D11DeviceObject<Base> {
+
+ public:
+
+ D3D11StateObject(D3D11Device* pDevice)
+ : D3D11DeviceObject<Base>(pDevice) {
+
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() {
+ uint32_t refCount = this->m_refCount++;
+ if (unlikely(!refCount))
+ this->GetParentInterface()->AddRef();
+
+ return refCount + 1;
+ }
+
+ ULONG STDMETHODCALLTYPE Release() {
+ uint32_t refCount = --this->m_refCount;
+ if (unlikely(!refCount))
+ this->GetParentInterface()->Release();
+
+ return refCount;
+ }
+
+ private:
+
+ std::atomic<uint32_t> m_refCount = { 0u };
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.cpp
new file mode 100644
index 00000000..0b9fc0f6
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.cpp
@@ -0,0 +1,14 @@
+#include "d3d11_enums.h"
+
+std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e) {
+ switch (e) {
+ ENUM_NAME(D3D_FEATURE_LEVEL_9_1);
+ ENUM_NAME(D3D_FEATURE_LEVEL_9_2);
+ ENUM_NAME(D3D_FEATURE_LEVEL_9_3);
+ ENUM_NAME(D3D_FEATURE_LEVEL_10_0);
+ ENUM_NAME(D3D_FEATURE_LEVEL_10_1);
+ ENUM_NAME(D3D_FEATURE_LEVEL_11_0);
+ ENUM_NAME(D3D_FEATURE_LEVEL_11_1);
+ ENUM_DEFAULT(e);
+ }
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.h
new file mode 100644
index 00000000..d67d0cdd
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_enums.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <ostream>
+
+#include "d3d11_include.h"
+
+std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e); \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.cpp
new file mode 100644
index 00000000..83e0618d
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.cpp
@@ -0,0 +1,208 @@
+#include "d3d11_context.h"
+#include "d3d11_device.h"
+#include "d3d11_gdi.h"
+
+#ifndef DXVK_NATIVE
+#include "../util/util_gdi.h"
+#endif
+
+namespace dxvk {
+
+ D3D11GDISurface::D3D11GDISurface(
+ ID3D11Resource* pResource,
+ UINT Subresource)
+ : m_resource (pResource),
+ m_subresource (Subresource),
+ m_readback (nullptr),
+ m_hdc (nullptr),
+ m_hbitmap (nullptr),
+ m_acquired (false) {
+ // Allocate memory for the bitmap
+ auto tex = GetCommonTexture(m_resource)->Desc();
+ m_data.resize(tex->Width * tex->Height);
+
+ // Create GDI DC
+ D3DKMT_CREATEDCFROMMEMORY desc;
+ desc.pMemory = m_data.data();
+ desc.Format = D3DFMT_A8R8G8B8;
+ desc.Width = tex->Width;
+ desc.Height = tex->Height;
+ desc.Pitch = tex->Width * sizeof(uint32_t);
+ desc.hDeviceDc = CreateCompatibleDC(nullptr);
+ desc.pColorTable = nullptr;
+ desc.hDc = nullptr;
+ desc.hBitmap = nullptr;
+
+ if (D3DKMTCreateDCFromMemory(&desc))
+ Logger::err(str::format("D3D11: Failed to create GDI DC"));
+
+ m_hdc = desc.hDc;
+ m_hbitmap = desc.hBitmap;
+ }
+
+
+ D3D11GDISurface::~D3D11GDISurface() {
+ if (m_readback)
+ m_readback->Release();
+
+ D3DKMT_DESTROYDCFROMMEMORY desc;
+ desc.hDC = m_hdc;
+ desc.hBitmap = m_hbitmap;
+ D3DKMTDestroyDCFromMemory(&desc);
+ }
+
+
+ HRESULT D3D11GDISurface::Acquire(BOOL Discard, HDC* phdc) {
+ if (!phdc)
+ return E_INVALIDARG;
+
+ *phdc = nullptr;
+
+ if (m_acquired)
+ return DXGI_ERROR_INVALID_CALL;
+
+ if (!Discard) {
+ // Create a staging resource that we can map
+ if (!m_readback && FAILED(CreateReadbackResource())) {
+ Logger::err("D3D11: Failed to create GDI readback resource");
+ return E_FAIL;
+ }
+
+ // Copy subresource to staging image
+ Com<ID3D11Device> device;
+ Com<ID3D11DeviceContext> context;
+
+ m_resource->GetDevice(&device);
+ device->GetImmediateContext(&context);
+
+ context->CopySubresourceRegion(m_readback, 0,
+ 0, 0, 0, m_resource, m_subresource, nullptr);
+
+ // Copy staging image to DC memory
+ auto tex = GetCommonTexture(m_resource)->Desc();
+ auto rowData = reinterpret_cast<char*>(m_data.data());
+ auto rowLength = sizeof(uint32_t) * tex->Width;
+
+ D3D11_MAPPED_SUBRESOURCE sr;
+ context->Map(m_readback, 0, D3D11_MAP_READ, 0, &sr);
+
+ for (uint32_t i = 0; i < tex->Height; i++) {
+ std::memcpy(rowData + rowLength * i,
+ reinterpret_cast<const char*>(sr.pData) + sr.RowPitch * i,
+ rowLength);
+ }
+
+ context->Unmap(m_readback, 0);
+ }
+
+ m_acquired = true;
+ *phdc = m_hdc;
+ return S_OK;
+ }
+
+
+ HRESULT D3D11GDISurface::Release(const RECT* pDirtyRect) {
+ if (!m_acquired)
+ return DXGI_ERROR_INVALID_CALL;
+
+ Com<ID3D11Device> device;
+ Com<ID3D11DeviceContext> context;
+
+ m_resource->GetDevice(&device);
+ device->GetImmediateContext(&context);
+
+ // Commit changes made to the DC
+ auto tex = GetCommonTexture(m_resource)->Desc();
+
+ RECT rect;
+
+ if (pDirtyRect) {
+ rect.left = std::max<LONG>(pDirtyRect->left, 0);
+ rect.top = std::max<LONG>(pDirtyRect->top, 0);
+ rect.right = std::min<LONG>(pDirtyRect->right, tex->Width);
+ rect.bottom = std::min<LONG>(pDirtyRect->bottom, tex->Height);
+ } else {
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = tex->Width;
+ rect.bottom = tex->Height;
+ }
+
+ if (rect.left < rect.right && rect.top < rect.bottom) {
+ D3D11_BOX box;
+ box.left = rect.left;
+ box.top = rect.top;
+ box.front = 0;
+ box.right = rect.right;
+ box.bottom = rect.bottom;
+ box.back = 1;
+
+ context->UpdateSubresource(m_resource, m_subresource,
+ &box, m_data.data() + rect.left,
+ sizeof(uint32_t) * tex->Width,
+ sizeof(uint32_t) * tex->Width * tex->Height);
+ }
+
+ m_acquired = false;
+ return S_OK;
+ }
+
+
+ HRESULT D3D11GDISurface::CreateReadbackResource() {
+ auto tex = GetCommonTexture(m_resource);
+
+ Com<ID3D11Device> device;
+ Com<ID3D11DeviceContext> context;
+
+ m_resource->GetDevice(&device);
+ device->GetImmediateContext(&context);
+
+ D3D11_RESOURCE_DIMENSION dim = { };
+ m_resource->GetType(&dim);
+
+ VkImageSubresource sr = tex->GetSubresourceFromIndex(
+ VK_IMAGE_ASPECT_COLOR_BIT, m_subresource);
+
+ switch (dim) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC desc;
+ desc.Width = std::max<UINT>(tex->Desc()->Width >> sr.mipLevel, 1);
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = tex->Desc()->Format;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture1D* tex1D = nullptr;
+ HRESULT hr = device->CreateTexture1D(&desc, nullptr, &tex1D);
+ m_readback = tex1D;
+ return hr;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = std::max<UINT>(tex->Desc()->Width >> sr.mipLevel, 1);
+ desc.Height = std::max<UINT>(tex->Desc()->Height >> sr.mipLevel, 1);
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = tex->Desc()->Format;
+ desc.SampleDesc= { 1, 0 };
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MiscFlags = 0;
+
+ ID3D11Texture2D* tex2D = nullptr;
+ HRESULT hr = device->CreateTexture2D(&desc, nullptr, &tex2D);
+ m_readback = tex2D;
+ return hr;
+ } break;
+
+ default:
+ return E_INVALIDARG;
+ }
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.h
new file mode 100644
index 00000000..a2656c0a
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_gdi.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <vector>
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ class D3D11GDISurface {
+
+ public:
+
+ D3D11GDISurface(
+ ID3D11Resource* pResource,
+ UINT Subresource);
+
+ ~D3D11GDISurface();
+
+ HRESULT Acquire(
+ BOOL Discard,
+ HDC* phdc);
+
+ HRESULT Release(
+ const RECT* pDirtyRect);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ uint32_t m_subresource;
+ ID3D11Resource* m_readback;
+ HDC m_hdc;
+ HANDLE m_hbitmap;
+ bool m_acquired;
+
+ std::vector<uint32_t> m_data;
+
+ HRESULT CreateReadbackResource();
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_include.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_include.h
new file mode 100644
index 00000000..1598088a
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_include.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "../dxgi/dxgi_include.h"
+
+#include <d3d11_4.h>
+
+// This is not defined in the mingw headers
+#ifndef D3D11_1_UAV_SLOT_COUNT
+#define D3D11_1_UAV_SLOT_COUNT 64
+#endif
+
+#ifndef D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL
+#define D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL 0xFFFFFFFF
+#endif
+
+#ifndef D3D11_KEEP_UNORDERED_ACCESS_VIEWS
+#define D3D11_KEEP_UNORDERED_ACCESS_VIEWS 0xFFFFFFFF
+#endif
+
+#define D3D11_DXVK_USE_REMAINING_LAYERS 0xFFFFFFFF
+#define D3D11_DXVK_USE_REMAINING_LEVELS 0xFFFFFFFF
+
+// Most of these were copied from d3d11.h
+// For some strange reason, we cannot use the structures
+// directly, although others from the same header work.
+// Some structures are missing from the mingw headers.
+#ifndef _MSC_VER
+#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9
+typedef enum D3D11_FORMAT_SUPPORT2 {
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD = 0x1,
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS = 0x2,
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 0x4,
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE = 0x8,
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX = 0x10,
+ D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 0x20,
+ D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD = 0x40,
+ D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE = 0x80,
+ D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x100,
+ D3D11_FORMAT_SUPPORT2_TILED = 0x200,
+ D3D11_FORMAT_SUPPORT2_SHAREABLE = 0x400,
+ D3D11_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x4000
+} D3D11_FORMAT_SUPPORT2;
+#define D3D11_RESOURCE_MISC_TILE_POOL (0x20000)
+#define D3D11_RESOURCE_MISC_TILED (0x40000)
+#endif // !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9
+#endif // _MSC_VER
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp
new file mode 100644
index 00000000..d1d66f19
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp
@@ -0,0 +1,290 @@
+#include <cstring>
+
+#include "d3d11_device.h"
+#include "d3d11_initializer.h"
+
+namespace dxvk {
+
+ D3D11Initializer::D3D11Initializer(
+ D3D11Device* pParent)
+ : m_parent(pParent),
+ m_device(pParent->GetDXVKDevice()),
+ m_context(m_device->createContext()) {
+ m_context->beginRecording(
+ m_device->createCommandList());
+ }
+
+
+ D3D11Initializer::~D3D11Initializer() {
+
+ }
+
+
+ void D3D11Initializer::Flush() {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ if (m_transferCommands != 0)
+ FlushInternal();
+ }
+
+ void D3D11Initializer::InitBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer()->memFlags();
+
+ (memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ ? InitHostVisibleBuffer(pBuffer, pInitialData)
+ : InitDeviceLocalBuffer(pBuffer, pInitialData);
+ }
+
+
+ void D3D11Initializer::InitTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
+ ? InitHostVisibleTexture(pTexture, pInitialData)
+ : InitDeviceLocalTexture(pTexture, pInitialData);
+ }
+
+
+ void D3D11Initializer::InitUavCounter(
+ D3D11UnorderedAccessView* pUav) {
+ auto counterBuffer = pUav->GetCounterSlice();
+
+ if (!counterBuffer.defined())
+ return;
+
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+ m_transferCommands += 1;
+
+ const uint32_t zero = 0;
+ m_context->updateBuffer(
+ counterBuffer.buffer(),
+ 0, sizeof(zero), &zero);
+
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::InitDeviceLocalBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
+
+ if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
+ m_transferMemory += bufferSlice.length();
+ m_transferCommands += 1;
+
+ m_context->uploadBuffer(
+ bufferSlice.buffer(),
+ pInitialData->pSysMem);
+ } else {
+ m_transferCommands += 1;
+
+ m_context->clearBuffer(
+ bufferSlice.buffer(),
+ bufferSlice.offset(),
+ bufferSlice.length(),
+ 0u);
+ }
+
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::InitHostVisibleBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ // If the buffer is mapped, we can write data directly
+ // to the mapped memory region instead of doing it on
+ // the GPU. Same goes for zero-initialization.
+ DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
+
+ if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
+ std::memcpy(
+ bufferSlice.mapPtr(0),
+ pInitialData->pSysMem,
+ bufferSlice.length());
+ } else {
+ std::memset(
+ bufferSlice.mapPtr(0), 0,
+ bufferSlice.length());
+ }
+ }
+
+
+ void D3D11Initializer::InitDeviceLocalTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ Rc<DxvkImage> image = pTexture->GetImage();
+
+ auto mapMode = pTexture->GetMapMode();
+ auto desc = pTexture->Desc();
+
+ VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format;
+ auto formatInfo = imageFormatInfo(packedFormat);
+
+ if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
+ // pInitialData is an array that stores an entry for
+ // every single subresource. Since we will define all
+ // subresources, this counts as initialization.
+ for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
+ for (uint32_t level = 0; level < desc->MipLevels; level++) {
+ const uint32_t id = D3D11CalcSubresource(
+ level, layer, desc->MipLevels);
+
+ VkOffset3D mipLevelOffset = { 0, 0, 0 };
+ VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(level);
+
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
+ m_transferCommands += 1;
+ m_transferMemory += pTexture->GetSubresourceLayout(formatInfo->aspectMask, id).Size;
+
+ VkImageSubresourceLayers subresourceLayers;
+ subresourceLayers.aspectMask = formatInfo->aspectMask;
+ subresourceLayers.mipLevel = level;
+ subresourceLayers.baseArrayLayer = layer;
+ subresourceLayers.layerCount = 1;
+
+ if (formatInfo->aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ m_context->uploadImage(
+ image, subresourceLayers,
+ pInitialData[id].pSysMem,
+ pInitialData[id].SysMemPitch,
+ pInitialData[id].SysMemSlicePitch);
+ } else {
+ m_context->updateDepthStencilImage(
+ image, subresourceLayers,
+ VkOffset2D { mipLevelOffset.x, mipLevelOffset.y },
+ VkExtent2D { mipLevelExtent.width, mipLevelExtent.height },
+ pInitialData[id].pSysMem,
+ pInitialData[id].SysMemPitch,
+ pInitialData[id].SysMemSlicePitch,
+ packedFormat);
+ }
+ }
+
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0),
+ pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch,
+ 0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
+ }
+ }
+ }
+ } else {
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
+ m_transferCommands += 1;
+
+ // While the Microsoft docs state that resource contents are
+ // undefined if no initial data is provided, some applications
+ // expect a resource to be pre-cleared. We can only do that
+ // for non-compressed images, but that should be fine.
+ VkImageSubresourceRange subresources;
+ subresources.aspectMask = formatInfo->aspectMask;
+ subresources.baseMipLevel = 0;
+ subresources.levelCount = desc->MipLevels;
+ subresources.baseArrayLayer = 0;
+ subresources.layerCount = desc->ArraySize;
+
+ if (formatInfo->flags.any(DxvkFormatFlag::BlockCompressed, DxvkFormatFlag::MultiPlane)) {
+ m_context->clearCompressedColorImage(image, subresources);
+ } else {
+ if (subresources.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
+ VkClearColorValue value = { };
+
+ m_context->clearColorImage(
+ image, value, subresources);
+ } else {
+ VkClearDepthStencilValue value;
+ value.depth = 0.0f;
+ value.stencil = 0;
+
+ m_context->clearDepthStencilImage(
+ image, value, subresources);
+ }
+ }
+ }
+
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) {
+ auto buffer = pTexture->GetMappedBuffer(i);
+ std::memset(buffer->mapPtr(0), 0, buffer->info().size);
+ }
+ }
+ }
+
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::InitHostVisibleTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ Rc<DxvkImage> image = pTexture->GetImage();
+
+ for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
+ for (uint32_t level = 0; level < image->info().mipLevels; level++) {
+ VkImageSubresource subresource;
+ subresource.aspectMask = image->formatInfo()->aspectMask;
+ subresource.mipLevel = level;
+ subresource.arrayLayer = layer;
+
+ VkExtent3D blockCount = util::computeBlockCount(
+ image->mipLevelExtent(level),
+ image->formatInfo()->blockSize);
+
+ VkSubresourceLayout layout = image->querySubresourceLayout(subresource);
+
+ auto initialData = pInitialData
+ ? &pInitialData[D3D11CalcSubresource(level, layer, image->info().mipLevels)]
+ : nullptr;
+
+ for (uint32_t z = 0; z < blockCount.depth; z++) {
+ for (uint32_t y = 0; y < blockCount.height; y++) {
+ auto size = blockCount.width * image->formatInfo()->elementSize;
+ auto dst = image->mapPtr(layout.offset + y * layout.rowPitch + z * layout.depthPitch);
+
+ if (initialData) {
+ auto src = reinterpret_cast<const char*>(initialData->pSysMem)
+ + y * initialData->SysMemPitch
+ + z * initialData->SysMemSlicePitch;
+ std::memcpy(dst, src, size);
+ } else {
+ std::memset(dst, 0, size);
+ }
+ }
+ }
+ }
+ }
+
+ // Initialize the image on the GPU
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ VkImageSubresourceRange subresources = image->getAvailableSubresources();
+
+ m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
+
+ m_transferCommands += 1;
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::FlushImplicit() {
+ if (m_transferCommands > MaxTransferCommands
+ || m_transferMemory > MaxTransferMemory)
+ FlushInternal();
+ }
+
+
+ void D3D11Initializer::FlushInternal() {
+ m_context->flushCommandList();
+
+ m_transferCommands = 0;
+ m_transferMemory = 0;
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.h
new file mode 100644
index 00000000..8c96babd
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "d3d11_buffer.h"
+#include "d3d11_texture.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Resource initialization context
+ *
+ * Manages a context which is used for resource
+ * initialization. This includes initialization
+ * with application-defined data, as well as
+ * zero-initialization for buffers and images.
+ */
+ class D3D11Initializer {
+ constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024;
+ constexpr static size_t MaxTransferCommands = 512;
+ public:
+
+ D3D11Initializer(
+ D3D11Device* pParent);
+
+ ~D3D11Initializer();
+
+ void Flush();
+
+ void InitBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void InitTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void InitUavCounter(
+ D3D11UnorderedAccessView* pUav);
+
+ private:
+
+ dxvk::mutex m_mutex;
+
+ D3D11Device* m_parent;
+ Rc<DxvkDevice> m_device;
+ Rc<DxvkContext> m_context;
+
+ size_t m_transferCommands = 0;
+ size_t m_transferMemory = 0;
+
+ void InitDeviceLocalBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void InitHostVisibleBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void InitDeviceLocalTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void InitHostVisibleTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData);
+
+ void FlushImplicit();
+ void FlushInternal();
+
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.cpp
new file mode 100644
index 00000000..abf3d125
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.cpp
@@ -0,0 +1,84 @@
+#include "d3d11_device.h"
+#include "d3d11_input_layout.h"
+
+namespace dxvk {
+
+ D3D11InputLayout::D3D11InputLayout(
+ D3D11Device* pDevice,
+ uint32_t numAttributes,
+ const DxvkVertexAttribute* pAttributes,
+ uint32_t numBindings,
+ const DxvkVertexBinding* pBindings)
+ : D3D11DeviceChild<ID3D11InputLayout>(pDevice),
+ m_d3d10(this) {
+ m_attributes.resize(numAttributes);
+ m_bindings.resize(numBindings);
+
+ for (uint32_t i = 0; i < numAttributes; i++)
+ m_attributes.at(i) = pAttributes[i];
+
+ for (uint32_t i = 0; i < numBindings; i++)
+ m_bindings.at(i) = pBindings[i];
+ }
+
+
+ D3D11InputLayout::~D3D11InputLayout() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11InputLayout::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11InputLayout)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10InputLayout)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void D3D11InputLayout::BindToContext(const Rc<DxvkContext>& ctx) {
+ ctx->setInputLayout(
+ m_attributes.size(),
+ m_attributes.data(),
+ m_bindings.size(),
+ m_bindings.data());
+ }
+
+
+ bool D3D11InputLayout::Compare(const D3D11InputLayout* pOther) const {
+ bool eq = m_attributes.size() == pOther->m_attributes.size()
+ && m_bindings.size() == pOther->m_bindings.size();
+
+ for (uint32_t i = 0; eq && i < m_attributes.size(); i++) {
+ eq &= m_attributes[i].location == pOther->m_attributes[i].location
+ && m_attributes[i].binding == pOther->m_attributes[i].binding
+ && m_attributes[i].format == pOther->m_attributes[i].format
+ && m_attributes[i].offset == pOther->m_attributes[i].offset;
+ }
+
+ for (uint32_t i = 0; eq && i < m_bindings.size(); i++) {
+ eq &= m_bindings[i].binding == pOther->m_bindings[i].binding
+ && m_bindings[i].fetchRate == pOther->m_bindings[i].fetchRate
+ && m_bindings[i].inputRate == pOther->m_bindings[i].inputRate;
+ }
+
+ return eq;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.h
new file mode 100644
index 00000000..8e472e2e
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_input_layout.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "d3d11_device_child.h"
+
+#include "../d3d10/d3d10_input_layout.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11InputLayout : public D3D11DeviceChild<ID3D11InputLayout> {
+
+ public:
+
+ D3D11InputLayout(
+ D3D11Device* pDevice,
+ uint32_t numAttributes,
+ const DxvkVertexAttribute* pAttributes,
+ uint32_t numBindings,
+ const DxvkVertexBinding* pBindings);
+
+ ~D3D11InputLayout();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void BindToContext(
+ const Rc<DxvkContext>& ctx);
+
+ bool Compare(
+ const D3D11InputLayout* pOther) const;
+
+ D3D10InputLayout* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ private:
+
+ std::vector<DxvkVertexAttribute> m_attributes;
+ std::vector<DxvkVertexBinding> m_bindings;
+
+ D3D10InputLayout m_d3d10;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interfaces.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interfaces.h
new file mode 100644
index 00000000..3b0629bb
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interfaces.h
@@ -0,0 +1,176 @@
+#pragma once
+
+#include "../dxgi/dxgi_interfaces.h"
+
+#include "d3d11_include.h"
+
+/**
+ * \brief D3D11 extension
+ *
+ * Lists D3D11 extensions supported by DXVK.
+ */
+enum D3D11_VK_EXTENSION : uint32_t {
+ D3D11_VK_EXT_MULTI_DRAW_INDIRECT = 0,
+ D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT = 1,
+ D3D11_VK_EXT_DEPTH_BOUNDS = 2,
+ D3D11_VK_EXT_BARRIER_CONTROL = 3,
+ D3D11_VK_NVX_BINARY_IMPORT = 4,
+ D3D11_VK_NVX_IMAGE_VIEW_HANDLE = 5,
+};
+
+
+/**
+ * \brief Barrier control flags
+ */
+enum D3D11_VK_BARRIER_CONTROL : uint32_t {
+ D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE = 1 << 0,
+ D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV = 1 << 1,
+};
+
+
+/**
+ * \brief Extended D3D11 device
+ *
+ * Introduces a method to check for extension support.
+ */
+MIDL_INTERFACE("8a6e3c42-f74c-45b7-8265-a231b677ca17")
+ID3D11VkExtDevice : public IUnknown {
+ /**
+ * \brief Checks whether an extension is supported
+ *
+ * \param [in] Extension The extension to check
+ * \returns \c TRUE if the extension is supported
+ */
+ virtual BOOL STDMETHODCALLTYPE GetExtensionSupport(
+ D3D11_VK_EXTENSION Extension) = 0;
+
+};
+
+
+/**
+ * \brief Extended extended D3D11 device
+ *
+ * Introduces methods to get virtual addresses and driver
+ * handles for resources, and create and destroy objects
+ * for D3D11-Cuda interop.
+ */
+MIDL_INTERFACE("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")
+ID3D11VkExtDevice1 : public ID3D11VkExtDevice {
+
+ virtual bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
+ void* hObject,
+ uint64_t* gpuVAStart,
+ uint64_t* gpuVASize) = 0;
+
+ virtual bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ ID3D11UnorderedAccessView** ppUAV,
+ uint32_t* pDriverHandle) = 0;
+
+ virtual bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ ID3D11ShaderResourceView** ppSRV,
+ uint32_t* pDriverHandle) = 0;
+
+ virtual bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
+ const D3D11_SAMPLER_DESC* pSamplerDesc,
+ ID3D11SamplerState** ppSamplerState,
+ uint32_t* pDriverHandle) = 0;
+
+ virtual bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
+ const void* pCubin,
+ uint32_t size,
+ uint32_t blockX,
+ uint32_t blockY,
+ uint32_t blockZ,
+ const char* pShaderName,
+ IUnknown** phShader) = 0;
+
+ virtual bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
+ uint32_t srvDriverHandle,
+ uint32_t samplerDriverHandle,
+ uint32_t* pCudaTextureHandle) = 0;
+};
+
+
+/**
+ * \brief Extended D3D11 context
+ *
+ * Provides functionality for various D3D11
+ * extensions.
+ */
+MIDL_INTERFACE("fd0bca13-5cb6-4c3a-987e-4750de2ca791")
+ID3D11VkExtContext : public IUnknown {
+ virtual void STDMETHODCALLTYPE MultiDrawIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) = 0;
+
+ virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirect(
+ UINT DrawCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) = 0;
+
+ virtual void STDMETHODCALLTYPE MultiDrawIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) = 0;
+
+ virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirectCount(
+ UINT MaxDrawCount,
+ ID3D11Buffer* pBufferForCount,
+ UINT ByteOffsetForCount,
+ ID3D11Buffer* pBufferForArgs,
+ UINT ByteOffsetForArgs,
+ UINT ByteStrideForArgs) = 0;
+
+ virtual void STDMETHODCALLTYPE SetDepthBoundsTest(
+ BOOL Enable,
+ FLOAT MinDepthBounds,
+ FLOAT MaxDepthBounds) = 0;
+
+ virtual void STDMETHODCALLTYPE SetBarrierControl(
+ UINT ControlFlags) = 0;
+};
+
+
+/**
+ * \brief Extended extended D3D11 context
+ *
+ * Provides functionality to launch a Cuda kernel
+ */
+MIDL_INTERFACE("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")
+ID3D11VkExtContext1 : public ID3D11VkExtContext {
+
+ virtual bool STDMETHODCALLTYPE LaunchCubinShaderNVX(
+ IUnknown* hShader,
+ uint32_t gridX,
+ uint32_t gridY,
+ uint32_t gridZ,
+ const void* pParams,
+ uint32_t paramSize,
+ void* const* pReadResources,
+ uint32_t numReadResources,
+ void* const* pWriteResources,
+ uint32_t numWriteResources) = 0;
+};
+
+
+#ifdef _MSC_VER
+struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice;
+struct __declspec(uuid("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")) ID3D11VkExtDevice1;
+struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext;
+struct __declspec(uuid("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")) ID3D11VkExtContext1;
+#else
+__CRT_UUID_DECL(ID3D11VkExtDevice, 0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17);
+__CRT_UUID_DECL(ID3D11VkExtDevice1, 0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06);
+__CRT_UUID_DECL(ID3D11VkExtContext, 0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91);
+__CRT_UUID_DECL(ID3D11VkExtContext1, 0x874b09b2,0xae0b,0x41d8,0x84,0x76,0x5f,0x3b,0x7a,0x0e,0x87,0x9d);
+#endif
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.cpp
new file mode 100644
index 00000000..9584b6ab
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.cpp
@@ -0,0 +1,166 @@
+#include "d3d11_context_imm.h"
+#include "d3d11_interop.h"
+#include "d3d11_device.h"
+
+#include "../dxvk/dxvk_adapter.h"
+#include "../dxvk/dxvk_device.h"
+#include "../dxvk/dxvk_instance.h"
+
+namespace dxvk {
+
+ D3D11VkInterop::D3D11VkInterop(
+ IDXGIObject* pContainer,
+ D3D11Device* pDevice)
+ : m_container (pContainer),
+ m_device (pDevice) { }
+
+
+ D3D11VkInterop::~D3D11VkInterop() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VkInterop::AddRef() {
+ return m_container->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VkInterop::Release() {
+ return m_container->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VkInterop::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_container->QueryInterface(riid, ppvObject);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::GetVulkanHandles(
+ VkInstance* pInstance,
+ VkPhysicalDevice* pPhysDev,
+ VkDevice* pDevice) {
+ auto device = m_device->GetDXVKDevice();
+ auto adapter = device->adapter();
+ auto instance = device->instance();
+
+ if (pDevice != nullptr)
+ *pDevice = device->handle();
+
+ if (pPhysDev != nullptr)
+ *pPhysDev = adapter->handle();
+
+ if (pInstance != nullptr)
+ *pInstance = instance->handle();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue(
+ VkQueue* pQueue,
+ uint32_t* pQueueFamilyIndex) {
+ auto device = static_cast<D3D11Device*>(m_device)->GetDXVKDevice();
+ DxvkDeviceQueue queue = device->queues().graphics;
+
+ if (pQueue != nullptr)
+ *pQueue = queue.queueHandle;
+
+ if (pQueueFamilyIndex != nullptr)
+ *pQueueFamilyIndex = queue.queueFamily;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::TransitionSurfaceLayout(
+ IDXGIVkInteropSurface* pSurface,
+ const VkImageSubresourceRange* pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout) {
+ Com<ID3D11DeviceContext> deviceContext = nullptr;
+ m_device->GetImmediateContext(&deviceContext);
+
+ auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
+
+ immediateContext->TransitionSurfaceLayout(
+ pSurface, pSubresources, OldLayout, NewLayout);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() {
+ Com<ID3D11DeviceContext> deviceContext = nullptr;
+ m_device->GetImmediateContext(&deviceContext);
+
+ auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
+ immediateContext->Flush();
+ immediateContext->SynchronizeCsThread();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::LockSubmissionQueue() {
+ m_device->GetDXVKDevice()->lockSubmission();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::ReleaseSubmissionQueue() {
+ m_device->GetDXVKDevice()->unlockSubmission();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue1(
+ VkQueue* pQueue,
+ uint32_t* pQueueIndex,
+ uint32_t* pQueueFamilyIndex) {
+ auto device = static_cast<D3D11Device*>(m_device)->GetDXVKDevice();
+ DxvkDeviceQueue queue = device->queues().graphics;
+
+ if (pQueue != nullptr)
+ *pQueue = queue.queueHandle;
+
+ if (pQueueIndex != nullptr)
+ *pQueueIndex = queue.queueIndex;
+
+ if (pQueueFamilyIndex != nullptr)
+ *pQueueFamilyIndex = queue.queueFamily;
+ }
+
+ HRESULT STDMETHODCALLTYPE D3D11VkInterop::CreateTexture2DFromVkImage(
+ const D3D11_TEXTURE2D_DESC1 *pDesc,
+ VkImage vkImage,
+ ID3D11Texture2D **ppTexture2D) {
+
+ InitReturnPtr(ppTexture2D);
+
+ if (!pDesc)
+ return E_INVALIDARG;
+
+ D3D11_COMMON_TEXTURE_DESC desc;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.Depth = 1;
+ desc.MipLevels = pDesc->MipLevels;
+ desc.ArraySize = pDesc->ArraySize;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = pDesc->SampleDesc;
+ desc.Usage = pDesc->Usage;
+ desc.BindFlags = pDesc->BindFlags;
+ desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ desc.MiscFlags = pDesc->MiscFlags;
+ desc.TextureLayout = pDesc->TextureLayout;
+
+ HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!ppTexture2D)
+ return S_FALSE;
+
+ try {
+ Com<D3D11Texture2D> texture = new D3D11Texture2D(m_device, &desc, 0, vkImage);
+ *ppTexture2D = texture.ref();
+ return S_OK;
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.h
new file mode 100644
index 00000000..48ee4c3b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_interop.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "../dxgi/dxgi_interfaces.h"
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11VkInterop : public ComObject<IDXGIVkInteropDevice1> {
+
+ public:
+
+ D3D11VkInterop(
+ IDXGIObject* pContainer,
+ D3D11Device* pDevice);
+
+ ~D3D11VkInterop();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE GetVulkanHandles(
+ VkInstance* pInstance,
+ VkPhysicalDevice* pPhysDev,
+ VkDevice* pDevice);
+
+ void STDMETHODCALLTYPE GetSubmissionQueue(
+ VkQueue* pQueue,
+ uint32_t* pQueueFamilyIndex);
+
+ void STDMETHODCALLTYPE TransitionSurfaceLayout(
+ IDXGIVkInteropSurface* pSurface,
+ const VkImageSubresourceRange* pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout);
+
+ void STDMETHODCALLTYPE FlushRenderingCommands();
+
+ void STDMETHODCALLTYPE LockSubmissionQueue();
+
+ void STDMETHODCALLTYPE ReleaseSubmissionQueue();
+
+ void STDMETHODCALLTYPE GetSubmissionQueue1(
+ VkQueue* pQueue,
+ uint32_t* pQueueIndex,
+ uint32_t* pQueueFamilyIndex);
+
+ HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage(
+ const D3D11_TEXTURE2D_DESC1* pDesc,
+ VkImage vkImage,
+ ID3D11Texture2D** ppTexture2D);
+
+ private:
+
+ IDXGIObject* m_container;
+ D3D11Device* m_device;
+
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_main.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_main.cpp
new file mode 100644
index 00000000..c0be5283
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_main.cpp
@@ -0,0 +1,247 @@
+#include <array>
+
+#include "../dxgi/dxgi_adapter.h"
+
+#include "../dxvk/dxvk_instance.h"
+
+#include "d3d11_device.h"
+#include "d3d11_enums.h"
+#include "d3d11_interop.h"
+
+namespace dxvk {
+#ifndef VBOX
+ Logger Logger::s_instance("d3d11.log");
+#endif
+}
+
+extern "C" {
+ using namespace dxvk;
+
+ DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice(
+ IDXGIFactory* pFactory,
+ IDXGIAdapter* pAdapter,
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ ID3D11Device** ppDevice) {
+ InitReturnPtr(ppDevice);
+
+ Rc<DxvkAdapter> dxvkAdapter;
+ Rc<DxvkInstance> dxvkInstance;
+
+ Com<IDXGIDXVKAdapter> dxgiVkAdapter;
+
+ // Try to find the corresponding Vulkan device for the DXGI adapter
+ if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIDXVKAdapter), reinterpret_cast<void**>(&dxgiVkAdapter)))) {
+ dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter();
+ dxvkInstance = dxgiVkAdapter->GetDXVKInstance();
+ } else {
+ Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter");
+ DXGI_ADAPTER_DESC desc;
+ pAdapter->GetDesc(&desc);
+
+ dxvkInstance = new DxvkInstance();
+ dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid);
+
+ if (dxvkAdapter == nullptr)
+ dxvkAdapter = dxvkInstance->findAdapterByDeviceId(desc.VendorId, desc.DeviceId);
+
+ if (dxvkAdapter == nullptr)
+ dxvkAdapter = dxvkInstance->enumAdapters(0);
+
+ if (dxvkAdapter == nullptr)
+ return E_FAIL;
+ }
+
+ // Feature levels to probe if the
+ // application does not specify any.
+ std::array<D3D_FEATURE_LEVEL, 6> defaultFeatureLevels = {
+ D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1,
+ };
+
+ if (pFeatureLevels == nullptr || FeatureLevels == 0) {
+ pFeatureLevels = defaultFeatureLevels.data();
+ FeatureLevels = defaultFeatureLevels.size();
+ }
+
+ // Find the highest feature level supported by the device.
+ // This works because the feature level array is ordered.
+ UINT flId;
+
+ for (flId = 0 ; flId < FeatureLevels; flId++) {
+ Logger::info(str::format("D3D11CoreCreateDevice: Probing ", pFeatureLevels[flId]));
+
+ if (D3D11Device::CheckFeatureLevelSupport(dxvkInstance, dxvkAdapter, pFeatureLevels[flId]))
+ break;
+ }
+
+ if (flId == FeatureLevels) {
+ Logger::err("D3D11CoreCreateDevice: Requested feature level not supported");
+ return E_INVALIDARG;
+ }
+
+ // Try to create the device with the given parameters.
+ const D3D_FEATURE_LEVEL fl = pFeatureLevels[flId];
+
+ try {
+ Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", fl));
+ Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
+ pAdapter, dxvkInstance, dxvkAdapter, fl, Flags);
+
+ return device->QueryInterface(
+ __uuidof(ID3D11Device),
+ reinterpret_cast<void**>(ppDevice));
+ } catch (const DxvkError& e) {
+ Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device");
+ return E_FAIL;
+ }
+ }
+
+
+ static HRESULT D3D11InternalCreateDeviceAndSwapChain(
+ IDXGIAdapter* pAdapter,
+ D3D_DRIVER_TYPE DriverType,
+ HMODULE Software,
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
+ IDXGISwapChain** ppSwapChain,
+ ID3D11Device** ppDevice,
+ D3D_FEATURE_LEVEL* pFeatureLevel,
+ ID3D11DeviceContext** ppImmediateContext) {
+ InitReturnPtr(ppDevice);
+ InitReturnPtr(ppSwapChain);
+ InitReturnPtr(ppImmediateContext);
+
+ if (pFeatureLevel)
+ *pFeatureLevel = D3D_FEATURE_LEVEL(0);
+
+ HRESULT hr;
+
+ Com<IDXGIFactory> dxgiFactory = nullptr;
+ Com<IDXGIAdapter> dxgiAdapter = pAdapter;
+ Com<ID3D11Device> device = nullptr;
+
+ if (ppSwapChain && !pSwapChainDesc)
+ return E_INVALIDARG;
+
+ if (!pAdapter) {
+ // We'll treat everything as hardware, even if the
+ // Vulkan device is actually a software device.
+ if (DriverType != D3D_DRIVER_TYPE_HARDWARE)
+ Logger::warn("D3D11CreateDevice: Unsupported driver type");
+
+ // We'll use the first adapter returned by a DXGI factory
+ hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory));
+
+ if (FAILED(hr)) {
+ Logger::err("D3D11CreateDevice: Failed to create a DXGI factory");
+ return hr;
+ }
+
+ hr = dxgiFactory->EnumAdapters(0, &dxgiAdapter);
+
+ if (FAILED(hr)) {
+ Logger::err("D3D11CreateDevice: No default adapter available");
+ return hr;
+ }
+ } else {
+ // We should be able to query the DXGI factory from the adapter
+ if (FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory)))) {
+ Logger::err("D3D11CreateDevice: Failed to query DXGI factory from DXGI adapter");
+ return E_INVALIDARG;
+ }
+
+ // In theory we could ignore these, but the Microsoft docs explicitly
+ // state that we need to return E_INVALIDARG in case the arguments are
+ // invalid. Both the driver type and software parameter can only be
+ // set if the adapter itself is unspecified.
+ // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx
+ if (DriverType != D3D_DRIVER_TYPE_UNKNOWN || Software)
+ return E_INVALIDARG;
+ }
+
+ // Create the actual device
+ hr = D3D11CoreCreateDevice(
+ dxgiFactory.ptr(), dxgiAdapter.ptr(),
+ Flags, pFeatureLevels, FeatureLevels,
+ &device);
+
+ if (FAILED(hr))
+ return hr;
+
+ // Create the swap chain, if requested
+ if (ppSwapChain) {
+ DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc;
+ hr = dxgiFactory->CreateSwapChain(device.ptr(), &desc, ppSwapChain);
+
+ if (FAILED(hr)) {
+ Logger::err("D3D11CreateDevice: Failed to create swap chain");
+ return hr;
+ }
+ }
+
+ // Write back whatever info the application requested
+ if (pFeatureLevel)
+ *pFeatureLevel = device->GetFeatureLevel();
+
+ if (ppDevice)
+ *ppDevice = device.ref();
+
+ if (ppImmediateContext)
+ device->GetImmediateContext(ppImmediateContext);
+
+ // If we were unable to write back the device and the
+ // swap chain, the application has no way of working
+ // with the device so we should report S_FALSE here.
+ if (!ppDevice && !ppImmediateContext && !ppSwapChain)
+ return S_FALSE;
+
+ return S_OK;
+ }
+
+
+ DLLEXPORT HRESULT __stdcall D3D11CreateDevice(
+ IDXGIAdapter* pAdapter,
+ D3D_DRIVER_TYPE DriverType,
+ HMODULE Software,
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ ID3D11Device** ppDevice,
+ D3D_FEATURE_LEVEL* pFeatureLevel,
+ ID3D11DeviceContext** ppImmediateContext) {
+ return D3D11InternalCreateDeviceAndSwapChain(
+ pAdapter, DriverType, Software, Flags,
+ pFeatureLevels, FeatureLevels, SDKVersion,
+ nullptr, nullptr,
+ ppDevice, pFeatureLevel, ppImmediateContext);
+ }
+
+
+ DLLEXPORT HRESULT __stdcall D3D11CreateDeviceAndSwapChain(
+ IDXGIAdapter* pAdapter,
+ D3D_DRIVER_TYPE DriverType,
+ HMODULE Software,
+ UINT Flags,
+ const D3D_FEATURE_LEVEL* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
+ IDXGISwapChain** ppSwapChain,
+ ID3D11Device** ppDevice,
+ D3D_FEATURE_LEVEL* pFeatureLevel,
+ ID3D11DeviceContext** ppImmediateContext) {
+ return D3D11InternalCreateDeviceAndSwapChain(
+ pAdapter, DriverType, Software, Flags,
+ pFeatureLevels, FeatureLevels, SDKVersion,
+ pSwapChainDesc, ppSwapChain,
+ ppDevice, pFeatureLevel, ppImmediateContext);
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.cpp
new file mode 100644
index 00000000..3bef2365
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.cpp
@@ -0,0 +1,44 @@
+#include <unordered_map>
+
+#include "d3d11_options.h"
+
+namespace dxvk {
+
+ D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
+ const DxvkDeviceInfo& devInfo = device->properties();
+
+ this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
+ this->enableRtOutputNanFixup = config.getOption<bool>("d3d11.enableRtOutputNanFixup", false);
+ this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
+ this->forceTgsmBarriers = config.getOption<bool>("d3d11.forceTgsmBarriers", false);
+ this->relaxedBarriers = config.getOption<bool>("d3d11.relaxedBarriers", false);
+ this->ignoreGraphicsBarriers = config.getOption<bool>("d3d11.ignoreGraphicsBarriers", false);
+ this->maxTessFactor = config.getOption<int32_t>("d3d11.maxTessFactor", 0);
+ this->samplerAnisotropy = config.getOption<int32_t>("d3d11.samplerAnisotropy", -1);
+ this->invariantPosition = config.getOption<bool>("d3d11.invariantPosition", true);
+ this->floatControls = config.getOption<bool>("d3d11.floatControls", true);
+ this->disableMsaa = config.getOption<bool>("d3d11.disableMsaa", false);
+ this->deferSurfaceCreation = config.getOption<bool>("dxgi.deferSurfaceCreation", false);
+ this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
+ this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
+ this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
+ this->syncInterval = config.getOption<int32_t>("dxgi.syncInterval", -1);
+ this->tearFree = config.getOption<Tristate>("dxgi.tearFree", Tristate::Auto);
+
+ this->constantBufferRangeCheck = config.getOption<bool>("d3d11.constantBufferRangeCheck", false)
+ && DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd;
+
+ bool apitraceAttached = false;
+ #if !defined(DXVK_NATIVE)
+ apitraceAttached = ::GetModuleHandle("dxgitrace.dll") != nullptr;
+ #endif
+
+ this->apitraceMode = config.getOption<bool>("d3d11.apitraceMode", apitraceAttached);
+
+ // Inform user in case they have the option enabled or a game
+ // ships a file called dxgitrace.dll for whatever reason.
+ if (this->apitraceMode)
+ Logger::warn("D3D11: Apitrace mode enabled, may affect performance!");
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.h
new file mode 100644
index 00000000..40a76aca
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_options.h
@@ -0,0 +1,109 @@
+#pragma once
+
+#include "../util/config/config.h"
+
+#include "../dxgi/dxgi_options.h"
+
+#include "../dxvk/dxvk_device.h"
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ struct D3D11Options {
+ D3D11Options(const Config& config, const Rc<DxvkDevice>& device);
+
+ /// Enables speed hack for mapping on deferred contexts
+ ///
+ /// This can substantially speed up some games, but may
+ /// cause issues if the game submits command lists more
+ /// than once.
+ bool dcSingleUseMode;
+
+ /// Enables workaround to replace NaN render target
+ /// outputs with zero
+ bool enableRtOutputNanFixup;
+
+ /// Enables out-of-bounds access check for constant
+ /// buffers. Workaround for a few broken games that
+ /// access random data inside their shaders.
+ bool constantBufferRangeCheck;
+
+ /// Zero-initialize workgroup memory
+ ///
+ /// Workargound for games that don't initialize
+ /// TGSM in compute shaders before reading it.
+ bool zeroInitWorkgroupMemory;
+
+ /// Force thread-group shared memory barriers
+ ///
+ /// Workaround for compute shaders that read and
+ /// write from the same shared memory location
+ /// without explicit synchronization.
+ bool forceTgsmBarriers;
+
+ /// Use relaxed memory barriers
+ ///
+ /// May improve performance in some games,
+ /// but might also cause rendering issues.
+ bool relaxedBarriers;
+
+ /// Ignore graphics barriers
+ ///
+ /// May improve performance in some games,
+ /// but might also cause rendering issues.
+ bool ignoreGraphicsBarriers;
+
+ /// Maximum tessellation factor.
+ ///
+ /// Limits tessellation factors in tessellation
+ /// control shaders. Values from 8 to 64 are
+ /// supported, other values will be ignored.
+ int32_t maxTessFactor;
+
+ /// Anisotropic filter override
+ ///
+ /// Enforces anisotropic filtering with the
+ /// given anisotropy value for all samplers.
+ int32_t samplerAnisotropy;
+
+ /// Declare vertex positions in shaders as invariant
+ bool invariantPosition;
+
+ /// Enable float control bits
+ bool floatControls;
+
+ /// Back buffer count for the Vulkan swap chain.
+ /// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount.
+ int32_t numBackBuffers;
+
+ /// Sync interval. Overrides the value
+ /// passed to IDXGISwapChain::Present.
+ int32_t syncInterval;
+
+ /// Tear-free mode if vsync is disabled
+ /// Tearing mode if vsync is enabled
+ Tristate tearFree;
+
+ /// Override maximum frame latency if the app specifies
+ /// a higher value. May help with frame timing issues.
+ int32_t maxFrameLatency;
+
+ /// Limit frame rate
+ int32_t maxFrameRate;
+
+ /// Defer surface creation until first present call. This
+ /// fixes issues with games that create multiple swap chains
+ /// for a single window that may interfere with each other.
+ bool deferSurfaceCreation;
+
+ /// Forces the sample count of all textures to be 1, and
+ /// performs the required shader and resolve fixups.
+ bool disableMsaa;
+
+ /// Apitrace mode: Maps all buffers in cached memory.
+ /// Enabled automatically if dxgitrace.dll is attached.
+ bool apitraceMode;
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.cpp
new file mode 100644
index 00000000..b7145739
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.cpp
@@ -0,0 +1,352 @@
+#include "d3d11_device.h"
+#include "d3d11_query.h"
+
+namespace dxvk {
+
+ D3D11Query::D3D11Query(
+ D3D11Device* device,
+ const D3D11_QUERY_DESC1& desc)
+ : D3D11DeviceChild<ID3D11Query1>(device),
+ m_desc(desc),
+ m_state(D3D11_VK_QUERY_INITIAL),
+ m_d3d10(this) {
+ Rc<DxvkDevice> dxvkDevice = m_parent->GetDXVKDevice();
+
+ switch (m_desc.Query) {
+ case D3D11_QUERY_EVENT:
+ m_event[0] = dxvkDevice->createGpuEvent();
+ break;
+
+ case D3D11_QUERY_OCCLUSION:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_OCCLUSION,
+ VK_QUERY_CONTROL_PRECISE_BIT, 0);
+ break;
+
+ case D3D11_QUERY_OCCLUSION_PREDICATE:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_OCCLUSION, 0, 0);
+ break;
+
+ case D3D11_QUERY_TIMESTAMP:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TIMESTAMP, 0, 0);
+ break;
+
+ case D3D11_QUERY_TIMESTAMP_DISJOINT:
+ for (uint32_t i = 0; i < 2; i++) {
+ m_query[i] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TIMESTAMP, 0, 0);
+ }
+ break;
+
+ case D3D11_QUERY_PIPELINE_STATISTICS:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0);
+ break;
+
+ case D3D11_QUERY_SO_STATISTICS:
+ case D3D11_QUERY_SO_STATISTICS_STREAM0:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
+ // FIXME it is technically incorrect to map
+ // SO_OVERFLOW_PREDICATE to the first stream,
+ // but this is good enough for D3D10 behaviour
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 0);
+ break;
+
+ case D3D11_QUERY_SO_STATISTICS_STREAM1:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 1);
+ break;
+
+ case D3D11_QUERY_SO_STATISTICS_STREAM2:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 2);
+ break;
+
+ case D3D11_QUERY_SO_STATISTICS_STREAM3:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3:
+ m_query[0] = dxvkDevice->createGpuQuery(
+ VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 3);
+ break;
+
+ default:
+ throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query));
+ }
+ }
+
+
+ D3D11Query::~D3D11Query() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Query::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11Asynchronous)
+ || riid == __uuidof(ID3D11Query)
+ || riid == __uuidof(ID3D11Query1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10Asynchronous)
+ || riid == __uuidof(ID3D10Query)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ if (m_desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) {
+ if (riid == __uuidof(ID3D11Predicate)) {
+ *ppvObject = AsPredicate(ref(this));
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10Predicate)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+ }
+
+ Logger::warn("D3D11Query: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Query::GetDataSize() {
+ switch (m_desc.Query) {
+ case D3D11_QUERY_EVENT:
+ return sizeof(BOOL);
+
+ case D3D11_QUERY_OCCLUSION:
+ return sizeof(UINT64);
+
+ case D3D11_QUERY_TIMESTAMP:
+ return sizeof(UINT64);
+
+ case D3D11_QUERY_TIMESTAMP_DISJOINT:
+ return sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT);
+
+ case D3D11_QUERY_PIPELINE_STATISTICS:
+ return sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS);
+
+ case D3D11_QUERY_OCCLUSION_PREDICATE:
+ return sizeof(BOOL);
+
+ case D3D11_QUERY_SO_STATISTICS:
+ case D3D11_QUERY_SO_STATISTICS_STREAM0:
+ case D3D11_QUERY_SO_STATISTICS_STREAM1:
+ case D3D11_QUERY_SO_STATISTICS_STREAM2:
+ case D3D11_QUERY_SO_STATISTICS_STREAM3:
+ return sizeof(D3D11_QUERY_DATA_SO_STATISTICS);
+
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3:
+ return sizeof(BOOL);
+ }
+
+ Logger::err("D3D11Query: Failed to query data size");
+ return 0;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Query::GetDesc(D3D11_QUERY_DESC* pDesc) {
+ pDesc->Query = m_desc.Query;
+ pDesc->MiscFlags = m_desc.MiscFlags;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Query::GetDesc1(D3D11_QUERY_DESC1* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ void D3D11Query::Begin(DxvkContext* ctx) {
+ switch (m_desc.Query) {
+ case D3D11_QUERY_EVENT:
+ case D3D11_QUERY_TIMESTAMP:
+ break;
+
+ case D3D11_QUERY_TIMESTAMP_DISJOINT:
+ ctx->writeTimestamp(m_query[1]);
+ break;
+
+ default:
+ ctx->beginQuery(m_query[0]);
+ }
+ }
+
+
+ void D3D11Query::End(DxvkContext* ctx) {
+ switch (m_desc.Query) {
+ case D3D11_QUERY_EVENT:
+ ctx->signalGpuEvent(m_event[0]);
+ break;
+
+ case D3D11_QUERY_TIMESTAMP:
+ case D3D11_QUERY_TIMESTAMP_DISJOINT:
+ ctx->writeTimestamp(m_query[0]);
+ break;
+
+ default:
+ ctx->endQuery(m_query[0]);
+ }
+
+ m_resetCtr.fetch_sub(1, std::memory_order_release);
+ }
+
+
+ bool STDMETHODCALLTYPE D3D11Query::DoBegin() {
+ if (!IsScoped() || m_state == D3D11_VK_QUERY_BEGUN)
+ return false;
+
+ m_state = D3D11_VK_QUERY_BEGUN;
+ return true;
+ }
+
+ bool STDMETHODCALLTYPE D3D11Query::DoEnd() {
+ // Apparently the D3D11 runtime implicitly begins the query
+ // if it is in the wrong state at the time End is called, so
+ // let the caller react to it instead of just failing here.
+ bool result = m_state == D3D11_VK_QUERY_BEGUN || !IsScoped();
+
+ m_state = D3D11_VK_QUERY_ENDED;
+ m_resetCtr.fetch_add(1, std::memory_order_acquire);
+ return result;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Query::GetData(
+ void* pData,
+ UINT GetDataFlags) {
+ if (m_state != D3D11_VK_QUERY_ENDED)
+ return DXGI_ERROR_INVALID_CALL;
+
+ if (m_resetCtr != 0u)
+ return S_FALSE;
+
+ if (m_desc.Query == D3D11_QUERY_EVENT) {
+ DxvkGpuEventStatus status = m_event[0]->test();
+
+ if (status == DxvkGpuEventStatus::Invalid)
+ return DXGI_ERROR_INVALID_CALL;
+
+ bool signaled = status == DxvkGpuEventStatus::Signaled;
+
+ if (pData != nullptr)
+ *static_cast<BOOL*>(pData) = signaled;
+
+ return signaled ? S_OK : S_FALSE;
+ } else {
+ std::array<DxvkQueryData, MaxGpuQueries> queryData = { };
+
+ for (uint32_t i = 0; i < MaxGpuQueries && m_query[i] != nullptr; i++) {
+ DxvkGpuQueryStatus status = m_query[i]->getData(queryData[i]);
+
+ if (status == DxvkGpuQueryStatus::Invalid
+ || status == DxvkGpuQueryStatus::Failed)
+ return DXGI_ERROR_INVALID_CALL;
+
+ if (status == DxvkGpuQueryStatus::Pending)
+ return S_FALSE;
+ }
+
+ if (pData == nullptr)
+ return S_OK;
+
+ switch (m_desc.Query) {
+ case D3D11_QUERY_OCCLUSION:
+ *static_cast<UINT64*>(pData) = queryData[0].occlusion.samplesPassed;
+ return S_OK;
+
+ case D3D11_QUERY_OCCLUSION_PREDICATE:
+ *static_cast<BOOL*>(pData) = queryData[0].occlusion.samplesPassed != 0;
+ return S_OK;
+
+ case D3D11_QUERY_TIMESTAMP:
+ *static_cast<UINT64*>(pData) = queryData[0].timestamp.time;
+ return S_OK;
+
+ case D3D11_QUERY_TIMESTAMP_DISJOINT: {
+ auto data = static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData);
+ data->Frequency = GetTimestampQueryFrequency();
+ data->Disjoint = queryData[0].timestamp.time < queryData[1].timestamp.time;
+ } return S_OK;
+
+ case D3D11_QUERY_PIPELINE_STATISTICS: {
+ auto data = static_cast<D3D11_QUERY_DATA_PIPELINE_STATISTICS*>(pData);
+ data->IAVertices = queryData[0].statistic.iaVertices;
+ data->IAPrimitives = queryData[0].statistic.iaPrimitives;
+ data->VSInvocations = queryData[0].statistic.vsInvocations;
+ data->GSInvocations = queryData[0].statistic.gsInvocations;
+ data->GSPrimitives = queryData[0].statistic.gsPrimitives;
+ data->CInvocations = queryData[0].statistic.clipInvocations;
+ data->CPrimitives = queryData[0].statistic.clipPrimitives;
+ data->PSInvocations = queryData[0].statistic.fsInvocations;
+ data->HSInvocations = queryData[0].statistic.tcsPatches;
+ data->DSInvocations = queryData[0].statistic.tesInvocations;
+ data->CSInvocations = queryData[0].statistic.csInvocations;
+ } return S_OK;
+
+ case D3D11_QUERY_SO_STATISTICS:
+ case D3D11_QUERY_SO_STATISTICS_STREAM0:
+ case D3D11_QUERY_SO_STATISTICS_STREAM1:
+ case D3D11_QUERY_SO_STATISTICS_STREAM2:
+ case D3D11_QUERY_SO_STATISTICS_STREAM3: {
+ auto data = static_cast<D3D11_QUERY_DATA_SO_STATISTICS*>(pData);
+ data->NumPrimitivesWritten = queryData[0].xfbStream.primitivesWritten;
+ data->PrimitivesStorageNeeded = queryData[0].xfbStream.primitivesNeeded;
+ } return S_OK;
+
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: {
+ auto data = static_cast<BOOL*>(pData);
+ *data = queryData[0].xfbStream.primitivesNeeded
+ > queryData[0].xfbStream.primitivesWritten;
+ } return S_OK;
+
+ default:
+ Logger::err(str::format("D3D11: Unhandled query type in GetData: ", m_desc.Query));
+ return E_INVALIDARG;
+ }
+ }
+ }
+
+
+ UINT64 D3D11Query::GetTimestampQueryFrequency() const {
+ Rc<DxvkDevice> device = m_parent->GetDXVKDevice();
+ Rc<DxvkAdapter> adapter = device->adapter();
+
+ VkPhysicalDeviceLimits limits = adapter->deviceProperties().limits;
+ return uint64_t(1'000'000'000.0f / limits.timestampPeriod);
+ }
+
+
+ HRESULT D3D11Query::ValidateDesc(const D3D11_QUERY_DESC1* pDesc) {
+ if (pDesc->Query >= D3D11_QUERY_PIPELINE_STATISTICS
+ && pDesc->ContextType > D3D11_CONTEXT_TYPE_3D)
+ return E_INVALIDARG;
+
+ return S_OK;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.h
new file mode 100644
index 00000000..06ac4a1a
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_query.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include "../dxvk/dxvk_gpu_event.h"
+#include "../dxvk/dxvk_gpu_query.h"
+
+#include "../d3d10/d3d10_query.h"
+
+#include "d3d11_device_child.h"
+
+namespace dxvk {
+
+ enum D3D11_VK_QUERY_STATE : uint32_t {
+ D3D11_VK_QUERY_INITIAL,
+ D3D11_VK_QUERY_BEGUN,
+ D3D11_VK_QUERY_ENDED,
+ };
+
+ class D3D11Query : public D3D11DeviceChild<ID3D11Query1> {
+ constexpr static uint32_t MaxGpuQueries = 2;
+ constexpr static uint32_t MaxGpuEvents = 1;
+ public:
+
+ D3D11Query(
+ D3D11Device* device,
+ const D3D11_QUERY_DESC1& desc);
+
+ ~D3D11Query();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ UINT STDMETHODCALLTYPE GetDataSize();
+
+ void STDMETHODCALLTYPE GetDesc(D3D11_QUERY_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(D3D11_QUERY_DESC1* pDesc) final;
+
+ void Begin(DxvkContext* ctx);
+
+ void End(DxvkContext* ctx);
+
+ bool STDMETHODCALLTYPE DoBegin();
+
+ bool STDMETHODCALLTYPE DoEnd();
+
+ HRESULT STDMETHODCALLTYPE GetData(
+ void* pData,
+ UINT GetDataFlags);
+
+ void DoDeferredEnd() {
+ m_state = D3D11_VK_QUERY_ENDED;
+ m_resetCtr.fetch_add(1, std::memory_order_acquire);
+ }
+
+ bool IsScoped() const {
+ return m_desc.Query != D3D11_QUERY_EVENT
+ && m_desc.Query != D3D11_QUERY_TIMESTAMP;
+ }
+
+ bool IsEvent() const {
+ return m_desc.Query == D3D11_QUERY_EVENT;
+ }
+
+ bool IsStalling() const {
+ return m_stallFlag;
+ }
+
+ void NotifyEnd() {
+ m_stallMask <<= 1;
+ }
+
+ void NotifyStall() {
+ m_stallMask |= 1;
+ m_stallFlag |= bit::popcnt(m_stallMask) >= 16;
+ }
+
+ D3D10Query* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT ValidateDesc(const D3D11_QUERY_DESC1* pDesc);
+
+ static ID3D11Predicate* AsPredicate(ID3D11Query* pQuery) {
+ // ID3D11Predicate and ID3D11Query have the same vtable. This
+ // saves us some headache in all query-related functions.
+ return static_cast<ID3D11Predicate*>(pQuery);
+ }
+
+ static D3D11Query* FromPredicate(ID3D11Predicate* pPredicate) {
+ return static_cast<D3D11Query*>(static_cast<ID3D11Query*>(pPredicate));
+ }
+
+ private:
+
+ D3D11_QUERY_DESC1 m_desc;
+
+ D3D11_VK_QUERY_STATE m_state;
+
+ std::array<Rc<DxvkGpuQuery>, MaxGpuQueries> m_query;
+ std::array<Rc<DxvkGpuEvent>, MaxGpuEvents> m_event;
+
+ D3D10Query m_d3d10;
+
+ uint32_t m_stallMask = 0;
+ bool m_stallFlag = false;
+
+ std::atomic<uint32_t> m_resetCtr = { 0u };
+
+ UINT64 GetTimestampQueryFrequency() const;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.cpp
new file mode 100644
index 00000000..6d70847e
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.cpp
@@ -0,0 +1,195 @@
+#include "d3d11_device.h"
+#include "d3d11_rasterizer.h"
+
+namespace dxvk {
+
+ D3D11RasterizerState::D3D11RasterizerState(
+ D3D11Device* device,
+ const D3D11_RASTERIZER_DESC2& desc)
+ : D3D11StateObject<ID3D11RasterizerState2>(device),
+ m_desc(desc), m_d3d10(this) {
+ // Polygon mode. Determines whether the rasterizer fills
+ // a polygon or renders lines connecting the vertices.
+ switch (desc.FillMode) {
+ default:
+ case D3D11_FILL_SOLID: m_state.polygonMode = VK_POLYGON_MODE_FILL; break;
+ case D3D11_FILL_WIREFRAME: m_state.polygonMode = VK_POLYGON_MODE_LINE; break;
+ }
+
+ // Face culling properties. The rasterizer may discard
+ // polygons that are facing towards or away from the
+ // viewer, depending on the options below.
+ switch (desc.CullMode) {
+ default:
+ case D3D11_CULL_NONE: m_state.cullMode = VK_CULL_MODE_NONE; break;
+ case D3D11_CULL_FRONT: m_state.cullMode = VK_CULL_MODE_FRONT_BIT; break;
+ case D3D11_CULL_BACK: m_state.cullMode = VK_CULL_MODE_BACK_BIT; break;
+ }
+
+ m_state.frontFace = desc.FrontCounterClockwise
+ ? VK_FRONT_FACE_COUNTER_CLOCKWISE
+ : VK_FRONT_FACE_CLOCKWISE;
+
+ // In the backend we treat depth bias as a dynamic state because
+ // some games like to put random/uninitialized numbers here, but
+ // we do not need to enable it in case the parameters are both 0.
+ m_state.depthBiasEnable = desc.DepthBias != 0 || desc.SlopeScaledDepthBias != 0.0f;
+ m_state.depthClipEnable = desc.DepthClipEnable;
+ m_state.conservativeMode = DecodeConservativeRasterizationMode(desc.ConservativeRaster);
+ m_state.sampleCount = VkSampleCountFlags(desc.ForcedSampleCount);
+
+ m_depthBias.depthBiasConstant = float(desc.DepthBias);
+ m_depthBias.depthBiasSlope = desc.SlopeScaledDepthBias;
+ m_depthBias.depthBiasClamp = desc.DepthBiasClamp;
+
+ if (desc.AntialiasedLineEnable)
+ Logger::err("D3D11RasterizerState: Antialiased lines not supported");
+ }
+
+
+ D3D11RasterizerState::~D3D11RasterizerState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11RasterizerState::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11RasterizerState)
+ || riid == __uuidof(ID3D11RasterizerState1)
+ || riid == __uuidof(ID3D11RasterizerState2)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10RasterizerState)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11RasterizerState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc(D3D11_RASTERIZER_DESC* pDesc) {
+ pDesc->FillMode = m_desc.FillMode;
+ pDesc->CullMode = m_desc.CullMode;
+ pDesc->FrontCounterClockwise = m_desc.FrontCounterClockwise;
+ pDesc->DepthBias = m_desc.DepthBias;
+ pDesc->DepthBiasClamp = m_desc.DepthBiasClamp;
+ pDesc->SlopeScaledDepthBias = m_desc.SlopeScaledDepthBias;
+ pDesc->DepthClipEnable = m_desc.DepthClipEnable;
+ pDesc->ScissorEnable = m_desc.ScissorEnable;
+ pDesc->MultisampleEnable = m_desc.MultisampleEnable;
+ pDesc->AntialiasedLineEnable = m_desc.AntialiasedLineEnable;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc1(D3D11_RASTERIZER_DESC1* pDesc) {
+ pDesc->FillMode = m_desc.FillMode;
+ pDesc->CullMode = m_desc.CullMode;
+ pDesc->FrontCounterClockwise = m_desc.FrontCounterClockwise;
+ pDesc->DepthBias = m_desc.DepthBias;
+ pDesc->DepthBiasClamp = m_desc.DepthBiasClamp;
+ pDesc->SlopeScaledDepthBias = m_desc.SlopeScaledDepthBias;
+ pDesc->DepthClipEnable = m_desc.DepthClipEnable;
+ pDesc->ScissorEnable = m_desc.ScissorEnable;
+ pDesc->MultisampleEnable = m_desc.MultisampleEnable;
+ pDesc->AntialiasedLineEnable = m_desc.AntialiasedLineEnable;
+ pDesc->ForcedSampleCount = m_desc.ForcedSampleCount;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc2(D3D11_RASTERIZER_DESC2* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ void D3D11RasterizerState::BindToContext(const Rc<DxvkContext>& ctx) {
+ ctx->setRasterizerState(m_state);
+
+ if (m_state.depthBiasEnable)
+ ctx->setDepthBias(m_depthBias);
+ }
+
+
+ D3D11_RASTERIZER_DESC2 D3D11RasterizerState::PromoteDesc(
+ const D3D11_RASTERIZER_DESC* pSrcDesc) {
+ D3D11_RASTERIZER_DESC2 dstDesc;
+ dstDesc.FillMode = pSrcDesc->FillMode;
+ dstDesc.CullMode = pSrcDesc->CullMode;
+ dstDesc.FrontCounterClockwise = pSrcDesc->FrontCounterClockwise;
+ dstDesc.DepthBias = pSrcDesc->DepthBias;
+ dstDesc.DepthBiasClamp = pSrcDesc->DepthBiasClamp;
+ dstDesc.SlopeScaledDepthBias = pSrcDesc->SlopeScaledDepthBias;
+ dstDesc.DepthClipEnable = pSrcDesc->DepthClipEnable;
+ dstDesc.ScissorEnable = pSrcDesc->ScissorEnable;
+ dstDesc.MultisampleEnable = pSrcDesc->MultisampleEnable;
+ dstDesc.AntialiasedLineEnable = pSrcDesc->AntialiasedLineEnable;
+ dstDesc.ForcedSampleCount = 0;
+ dstDesc.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+ return dstDesc;
+ }
+
+
+ D3D11_RASTERIZER_DESC2 D3D11RasterizerState::PromoteDesc(
+ const D3D11_RASTERIZER_DESC1* pSrcDesc) {
+ D3D11_RASTERIZER_DESC2 dstDesc;
+ dstDesc.FillMode = pSrcDesc->FillMode;
+ dstDesc.CullMode = pSrcDesc->CullMode;
+ dstDesc.FrontCounterClockwise = pSrcDesc->FrontCounterClockwise;
+ dstDesc.DepthBias = pSrcDesc->DepthBias;
+ dstDesc.DepthBiasClamp = pSrcDesc->DepthBiasClamp;
+ dstDesc.SlopeScaledDepthBias = pSrcDesc->SlopeScaledDepthBias;
+ dstDesc.DepthClipEnable = pSrcDesc->DepthClipEnable;
+ dstDesc.ScissorEnable = pSrcDesc->ScissorEnable;
+ dstDesc.MultisampleEnable = pSrcDesc->MultisampleEnable;
+ dstDesc.AntialiasedLineEnable = pSrcDesc->AntialiasedLineEnable;
+ dstDesc.ForcedSampleCount = 0;
+ dstDesc.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+ return dstDesc;
+ }
+
+
+ HRESULT D3D11RasterizerState::NormalizeDesc(
+ D3D11_RASTERIZER_DESC2* pDesc) {
+ if (pDesc->FillMode < D3D11_FILL_WIREFRAME
+ || pDesc->FillMode > D3D11_FILL_SOLID)
+ return E_INVALIDARG;
+
+ if (pDesc->CullMode < D3D11_CULL_NONE
+ || pDesc->CullMode > D3D11_CULL_BACK)
+ return E_INVALIDARG;
+
+ if (pDesc->FrontCounterClockwise)
+ pDesc->FrontCounterClockwise = TRUE;
+
+ if (pDesc->DepthClipEnable)
+ pDesc->DepthClipEnable = TRUE;
+
+ if (pDesc->ScissorEnable)
+ pDesc->ScissorEnable = TRUE;
+
+ if (pDesc->MultisampleEnable)
+ pDesc->MultisampleEnable = TRUE;
+
+ if (pDesc->AntialiasedLineEnable)
+ pDesc->AntialiasedLineEnable = TRUE;
+
+ if (pDesc->ForcedSampleCount != 0) {
+ if (FAILED(DecodeSampleCount(pDesc->ForcedSampleCount, nullptr)))
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.h
new file mode 100644
index 00000000..7b542f2c
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_rasterizer.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_rasterizer.h"
+
+#include "d3d11_device_child.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11RasterizerState : public D3D11StateObject<ID3D11RasterizerState2> {
+
+ public:
+
+ using DescType = D3D11_RASTERIZER_DESC2;
+
+ D3D11RasterizerState(
+ D3D11Device* device,
+ const D3D11_RASTERIZER_DESC2& desc);
+ ~D3D11RasterizerState();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_RASTERIZER_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(
+ D3D11_RASTERIZER_DESC1* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc2(
+ D3D11_RASTERIZER_DESC2* pDesc) final;
+
+ const D3D11_RASTERIZER_DESC2* Desc() const {
+ return &m_desc;
+ }
+
+ void BindToContext(
+ const Rc<DxvkContext>& ctx);
+
+ D3D10RasterizerState* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static D3D11_RASTERIZER_DESC2 PromoteDesc(
+ const D3D11_RASTERIZER_DESC* pDesc);
+
+ static D3D11_RASTERIZER_DESC2 PromoteDesc(
+ const D3D11_RASTERIZER_DESC1* pDesc);
+
+ static HRESULT NormalizeDesc(
+ D3D11_RASTERIZER_DESC2* pDesc);
+
+ private:
+
+ D3D11_RASTERIZER_DESC2 m_desc;
+ DxvkRasterizerState m_state;
+ DxvkDepthBias m_depthBias;
+ D3D10RasterizerState m_d3d10;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.cpp
new file mode 100644
index 00000000..7ba71367
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.cpp
@@ -0,0 +1,228 @@
+#include "d3d11_buffer.h"
+#include "d3d11_texture.h"
+#include "d3d11_resource.h"
+
+namespace dxvk {
+
+ D3D11DXGIResource::D3D11DXGIResource(
+ ID3D11Resource* pResource)
+ : m_resource(pResource) {
+
+ }
+
+
+ D3D11DXGIResource::~D3D11DXGIResource() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DXGIResource::AddRef() {
+ return m_resource->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DXGIResource::Release() {
+ return m_resource->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_resource->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData) {
+ return m_resource->GetPrivateData(Name, pDataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData) {
+ return m_resource->SetPrivateData(Name, DataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown) {
+ return m_resource->SetPrivateDataInterface(Name, pUnknown);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetParent(
+ REFIID riid,
+ void** ppParent) {
+ return GetDevice(riid, ppParent);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetDevice(
+ REFIID riid,
+ void** ppDevice) {
+ Com<ID3D11Device> device;
+ m_resource->GetDevice(&device);
+ return device->QueryInterface(riid, ppDevice);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetEvictionPriority(
+ UINT* pEvictionPriority) {
+ *pEvictionPriority = m_resource->GetEvictionPriority();
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle(
+ HANDLE* pSharedHandle) {
+ InitReturnPtr(pSharedHandle);
+ Logger::err("D3D11DXGIResource::GetSharedHandle: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetUsage(
+ DXGI_USAGE* pUsage) {
+ D3D11_COMMON_RESOURCE_DESC desc;
+
+ HRESULT hr = GetCommonResourceDesc(m_resource, &desc);
+
+ if (FAILED(hr))
+ return hr;
+
+ DXGI_USAGE usage = desc.DxgiUsage;
+
+ switch (desc.Usage) {
+ case D3D11_USAGE_IMMUTABLE: usage |= DXGI_CPU_ACCESS_NONE; break;
+ case D3D11_USAGE_DEFAULT: usage |= DXGI_CPU_ACCESS_NONE; break;
+ case D3D11_USAGE_DYNAMIC: usage |= DXGI_CPU_ACCESS_DYNAMIC; break;
+ case D3D11_USAGE_STAGING: usage |= DXGI_CPU_ACCESS_READ_WRITE; break;
+ }
+
+ // TODO add flags for swap chain back buffers
+ if (desc.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_CONSTANT_BUFFER))
+ usage |= DXGI_USAGE_SHADER_INPUT;
+
+ if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
+ usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
+
+ if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
+ usage |= DXGI_USAGE_UNORDERED_ACCESS;
+
+ *pUsage = usage;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetEvictionPriority(
+ UINT EvictionPriority) {
+ m_resource->SetEvictionPriority(EvictionPriority);
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::CreateSharedHandle(
+ const SECURITY_ATTRIBUTES* pAttributes,
+ DWORD dwAccess,
+ LPCWSTR lpName,
+ HANDLE* pHandle) {
+ InitReturnPtr(pHandle);
+ Logger::err("D3D11DXGIResource::CreateSharedHandle: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGIResource::CreateSubresourceSurface(
+ UINT index,
+ IDXGISurface2** ppSurface) {
+ InitReturnPtr(ppSurface);
+ Logger::err("D3D11DXGIResource::CreateSubresourceSurface: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT GetCommonResourceDesc(
+ ID3D11Resource* pResource,
+ D3D11_COMMON_RESOURCE_DESC* pDesc) {
+ auto buffer = GetCommonBuffer (pResource);
+ auto texture = GetCommonTexture(pResource);
+
+ if (buffer != nullptr) {
+ pDesc->Dim = D3D11_RESOURCE_DIMENSION_BUFFER;
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->Usage = buffer->Desc()->Usage;
+ pDesc->BindFlags = buffer->Desc()->BindFlags;
+ pDesc->CPUAccessFlags = buffer->Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = buffer->Desc()->MiscFlags;
+ pDesc->DxgiUsage = 0;
+ return S_OK;
+ } else if (texture != nullptr) {
+ pResource->GetType(&pDesc->Dim);
+ pDesc->Format = texture->Desc()->Format;
+ pDesc->Usage = texture->Desc()->Usage;
+ pDesc->BindFlags = texture->Desc()->BindFlags;
+ pDesc->CPUAccessFlags = texture->Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = texture->Desc()->MiscFlags;
+ pDesc->DxgiUsage = texture->GetDxgiUsage();
+ return S_OK;
+ } else {
+ pDesc->Dim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->Usage = D3D11_USAGE_DEFAULT;
+ pDesc->BindFlags = 0;
+ pDesc->CPUAccessFlags = 0;
+ pDesc->MiscFlags = 0;
+ pDesc->DxgiUsage = 0;
+ return E_INVALIDARG;
+ }
+ }
+
+
+ BOOL CheckResourceViewCompatibility(
+ ID3D11Resource* pResource,
+ UINT BindFlags,
+ DXGI_FORMAT Format,
+ UINT Plane) {
+ auto texture = GetCommonTexture(pResource);
+ auto buffer = GetCommonBuffer (pResource);
+
+ return texture != nullptr
+ ? texture->CheckViewCompatibility(BindFlags, Format, Plane)
+ : buffer ->CheckViewCompatibility(BindFlags, Format);
+ }
+
+
+ HRESULT ResourceAddRefPrivate(ID3D11Resource* pResource) {
+ D3D11_RESOURCE_DIMENSION dim;
+ pResource->GetType(&dim);
+
+ switch (dim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: static_cast<D3D11Buffer*> (pResource)->AddRefPrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: static_cast<D3D11Texture1D*>(pResource)->AddRefPrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: static_cast<D3D11Texture2D*>(pResource)->AddRefPrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: static_cast<D3D11Texture3D*>(pResource)->AddRefPrivate(); return S_OK;
+ default: return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT ResourceReleasePrivate(ID3D11Resource* pResource) {
+ D3D11_RESOURCE_DIMENSION dim;
+ pResource->GetType(&dim);
+
+ switch (dim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: static_cast<D3D11Buffer*> (pResource)->ReleasePrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: static_cast<D3D11Texture1D*>(pResource)->ReleasePrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: static_cast<D3D11Texture2D*>(pResource)->ReleasePrivate(); return S_OK;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: static_cast<D3D11Texture3D*>(pResource)->ReleasePrivate(); return S_OK;
+ default: return E_INVALIDARG;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.h
new file mode 100644
index 00000000..7d91a305
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_resource.h
@@ -0,0 +1,147 @@
+#pragma once
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ /**
+ * \brief Common resource description
+ *
+ * Stores the usage and bind flags of a resource
+ * Can be used to quickly determine whether it is
+ * legal to create a view for a given resource.
+ */
+ struct D3D11_COMMON_RESOURCE_DESC {
+ D3D11_RESOURCE_DIMENSION Dim;
+ DXGI_FORMAT Format;
+ D3D11_USAGE Usage;
+ UINT BindFlags;
+ UINT CPUAccessFlags;
+ UINT MiscFlags;
+ UINT DxgiUsage;
+ };
+
+
+ /**
+ * \brief IDXGIResource implementation for D3D11 resources
+ */
+ class D3D11DXGIResource : public IDXGIResource1 {
+
+ public:
+
+ D3D11DXGIResource(
+ ID3D11Resource* pResource);
+
+ ~D3D11DXGIResource();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown);
+
+ HRESULT STDMETHODCALLTYPE GetParent(
+ REFIID riid,
+ void** ppParent);
+
+ HRESULT STDMETHODCALLTYPE GetDevice(
+ REFIID riid,
+ void** ppDevice);
+
+ HRESULT STDMETHODCALLTYPE GetEvictionPriority(
+ UINT* pEvictionPriority);
+
+ HRESULT STDMETHODCALLTYPE GetSharedHandle(
+ HANDLE* pSharedHandle);
+
+ HRESULT STDMETHODCALLTYPE GetUsage(
+ DXGI_USAGE* pUsage);
+
+ HRESULT STDMETHODCALLTYPE SetEvictionPriority(
+ UINT EvictionPriority);
+
+ HRESULT STDMETHODCALLTYPE CreateSharedHandle(
+ const SECURITY_ATTRIBUTES* pAttributes,
+ DWORD dwAccess,
+ LPCWSTR lpName,
+ HANDLE* pHandle);
+
+ HRESULT STDMETHODCALLTYPE CreateSubresourceSurface(
+ UINT index,
+ IDXGISurface2** ppSurface);
+
+ private:
+
+ ID3D11Resource* m_resource;
+
+ };
+
+
+ /**
+ * \brief Queries common resource description
+ *
+ * \param [in] pResource The resource to query
+ * \param [out] pDesc Resource description
+ * \returns \c S_OK on success, or \c E_INVALIDARG
+ */
+ HRESULT GetCommonResourceDesc(
+ ID3D11Resource* pResource,
+ D3D11_COMMON_RESOURCE_DESC* pDesc);
+
+ /**
+ * \brief Checks whether a format can be used to view a resource
+ *
+ * Depending on whether the resource is a buffer or a
+ * texture, certain restrictions apply on which formats
+ * can be used to view the resource.
+ * \param [in] pResource The resource to check
+ * \param [in] BindFlags Bind flags required for the view
+ * \param [in] Format The desired view format
+ * \param [in] Plane Plane slice for planar formats
+ * \returns \c true if the format is compatible
+ */
+ BOOL CheckResourceViewCompatibility(
+ ID3D11Resource* pResource,
+ UINT BindFlags,
+ DXGI_FORMAT Format,
+ UINT Plane);
+
+ /**
+ * \brief Increments private reference count of a resource
+ *
+ * Helper method that figures out the exact type of
+ * the resource and calls its \c AddRefPrivate method.
+ * \param [in] pResource The resource to reference
+ * \returns \c S_OK, or \c E_INVALIDARG for an invalid resource
+ */
+ HRESULT ResourceAddRefPrivate(
+ ID3D11Resource* pResource);
+
+ /**
+ * \brief Decrements private reference count of a resource
+ *
+ * Helper method that figures out the exact type of
+ * the resource and calls its \c ReleasePrivate method.
+ * \param [in] pResource The resource to reference
+ * \returns \c S_OK, or \c E_INVALIDARG for an invalid resource
+ */
+ HRESULT ResourceReleasePrivate(
+ ID3D11Resource* pResource);
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp
new file mode 100644
index 00000000..397dc47b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp
@@ -0,0 +1,147 @@
+#include "d3d11_device.h"
+#include "d3d11_sampler.h"
+#include "d3d11_util.h"
+
+namespace dxvk {
+
+ D3D11SamplerState::D3D11SamplerState(
+ D3D11Device* device,
+ const D3D11_SAMPLER_DESC& desc)
+ : D3D11StateObject<ID3D11SamplerState>(device),
+ m_desc(desc), m_d3d10(this) {
+ DxvkSamplerCreateInfo info;
+
+ // While D3D11_FILTER is technically an enum, its value bits
+ // can be used to decode the filter properties more efficiently.
+ const uint32_t filterBits = uint32_t(desc.Filter);
+ info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
+ info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
+
+ // Set up the remaining properties, which are
+ // stored directly in the sampler description
+ info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ info.mipmapLodBias = desc.MipLODBias;
+ info.mipmapLodMin = desc.MinLOD;
+ info.mipmapLodMax = desc.MaxLOD;
+
+ info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE;
+ info.maxAnisotropy = float(desc.MaxAnisotropy);
+
+ info.addressModeU = DecodeAddressMode(desc.AddressU);
+ info.addressModeV = DecodeAddressMode(desc.AddressV);
+ info.addressModeW = DecodeAddressMode(desc.AddressW);
+
+ info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE;
+ info.compareOp = DecodeCompareOp(desc.ComparisonFunc);
+
+ for (uint32_t i = 0; i < 4; i++)
+ info.borderColor.float32[i] = desc.BorderColor[i];
+
+ info.usePixelCoord = VK_FALSE; // Not supported in D3D11
+
+ // Make sure to use a valid anisotropy value
+ if (desc.MaxAnisotropy < 1) info.maxAnisotropy = 1.0f;
+ if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f;
+
+ // Enforce anisotropy specified in the device options
+ int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
+
+ if (samplerAnisotropyOption >= 0) {
+ info.useAnisotropy = samplerAnisotropyOption > 0;
+ info.maxAnisotropy = float(samplerAnisotropyOption);
+ }
+
+ m_sampler = device->GetDXVKDevice()->createSampler(info);
+ }
+
+
+ D3D11SamplerState::~D3D11SamplerState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SamplerState::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11SamplerState)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10SamplerState)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11SamplerState::GetDesc(D3D11_SAMPLER_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11SamplerState::NormalizeDesc(D3D11_SAMPLER_DESC* pDesc) {
+ const uint32_t filterBits = uint32_t(pDesc->Filter);
+
+ if (filterBits & 0xFFFFFF2A) {
+ Logger::err(str::format(
+ "D3D11SamplerState: Unhandled filter: ", filterBits));
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->MaxAnisotropy < 0
+ || pDesc->MaxAnisotropy > 16) {
+ return E_INVALIDARG;
+ } else if ((filterBits & 0x40) == 0 /* not anisotropic */) {
+ // Reset anisotropy if it is not used
+ pDesc->MaxAnisotropy = 0;
+ }
+
+ if (filterBits & 0x80 /* compare-to-depth */) {
+ if (!ValidateComparisonFunc(pDesc->ComparisonFunc))
+ return E_INVALIDARG;
+ } else {
+ // Reset compare func if it is not used
+ pDesc->ComparisonFunc = D3D11_COMPARISON_NEVER;
+ }
+
+ if (!ValidateAddressMode(pDesc->AddressU)
+ || !ValidateAddressMode(pDesc->AddressV)
+ || !ValidateAddressMode(pDesc->AddressW))
+ return E_INVALIDARG;
+
+ // Clear BorderColor to 0 if none of the address
+ // modes are D3D11_TEXTURE_ADDRESS_BORDER
+ if (pDesc->AddressU != D3D11_TEXTURE_ADDRESS_BORDER
+ && pDesc->AddressV != D3D11_TEXTURE_ADDRESS_BORDER
+ && pDesc->AddressW != D3D11_TEXTURE_ADDRESS_BORDER) {
+ for (int i = 0; i < 4; i++)
+ pDesc->BorderColor[i] = 0.0f;
+ }
+
+ return S_OK;
+ }
+
+
+ bool D3D11SamplerState::ValidateAddressMode(D3D11_TEXTURE_ADDRESS_MODE Mode) {
+ return Mode >= D3D11_TEXTURE_ADDRESS_WRAP
+ && Mode <= D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
+ }
+
+
+ bool D3D11SamplerState::ValidateComparisonFunc(D3D11_COMPARISON_FUNC Comparison) {
+ return Comparison >= D3D11_COMPARISON_NEVER
+ && Comparison <= D3D11_COMPARISON_ALWAYS;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.h
new file mode 100644
index 00000000..57fa139b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_sampler.h"
+
+#include "d3d11_device_child.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ class D3D11SamplerState : public D3D11StateObject<ID3D11SamplerState> {
+
+ public:
+
+ using DescType = D3D11_SAMPLER_DESC;
+
+ D3D11SamplerState(
+ D3D11Device* device,
+ const D3D11_SAMPLER_DESC& desc);
+ ~D3D11SamplerState();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_SAMPLER_DESC* pDesc) final;
+
+ Rc<DxvkSampler> GetDXVKSampler() const {
+ return m_sampler;
+ }
+
+ D3D10SamplerState* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT NormalizeDesc(
+ D3D11_SAMPLER_DESC* pDesc);
+
+ private:
+
+ D3D11_SAMPLER_DESC m_desc;
+ Rc<DxvkSampler> m_sampler;
+ D3D10SamplerState m_d3d10;
+
+ std::atomic<uint32_t> m_refCount = { 0u };
+
+ static bool ValidateAddressMode(
+ D3D11_TEXTURE_ADDRESS_MODE Mode);
+
+ static bool ValidateComparisonFunc(
+ D3D11_COMPARISON_FUNC Comparison);
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.cpp
new file mode 100644
index 00000000..056044dd
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.cpp
@@ -0,0 +1,140 @@
+#include "d3d11_device.h"
+#include "d3d11_shader.h"
+
+namespace dxvk {
+
+ D3D11CommonShader:: D3D11CommonShader() { }
+ D3D11CommonShader::~D3D11CommonShader() { }
+
+
+ D3D11CommonShader::D3D11CommonShader(
+ D3D11Device* pDevice,
+ const DxvkShaderKey* pShaderKey,
+ const DxbcModuleInfo* pDxbcModuleInfo,
+ const void* pShaderBytecode,
+ size_t BytecodeLength) {
+ const std::string name = pShaderKey->toString();
+ Logger::debug(str::format("Compiling shader ", name));
+
+ DxbcReader reader(
+ reinterpret_cast<const char*>(pShaderBytecode),
+ BytecodeLength);
+
+ DxbcModule module(reader);
+
+ // If requested by the user, dump both the raw DXBC
+ // shader and the compiled SPIR-V module to a file.
+ const std::string dumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH");
+
+ if (dumpPath.size() != 0) {
+#ifdef _WIN32
+ reader.store(std::ofstream(str::tows(str::format(dumpPath, "/", name, ".dxbc").c_str()).c_str(),
+ std::ios_base::binary | std::ios_base::trunc));
+#else
+ reader.store(std::ofstream(str::format(dumpPath, "/", name, ".dxbc").c_str(),
+ std::ios_base::binary | std::ios_base::trunc));
+#endif
+ }
+
+ // Decide whether we need to create a pass-through
+ // geometry shader for vertex shader stream output
+ bool passthroughShader = pDxbcModuleInfo->xfb != nullptr
+ && (module.programInfo().type() == DxbcProgramType::VertexShader
+ || module.programInfo().type() == DxbcProgramType::DomainShader);
+
+ if (module.programInfo().shaderStage() != pShaderKey->type() && !passthroughShader)
+ throw DxvkError("Mismatching shader type.");
+
+ m_shader = passthroughShader
+ ? module.compilePassthroughShader(*pDxbcModuleInfo, name)
+ : module.compile (*pDxbcModuleInfo, name);
+ m_shader->setShaderKey(*pShaderKey);
+
+ if (dumpPath.size() != 0) {
+#ifdef _WIN32
+ std::ofstream dumpStream(
+ str::tows(str::format(dumpPath, "/", name, ".spv").c_str()).c_str(),
+ std::ios_base::binary | std::ios_base::trunc);
+#else
+ std::ofstream dumpStream(
+ str::format(dumpPath, "/", name, ".spv").c_str(),
+ std::ios_base::binary | std::ios_base::trunc);
+#endif
+
+ m_shader->dump(dumpStream);
+ }
+
+ // Create shader constant buffer if necessary
+ if (m_shader->shaderConstants().data() != nullptr) {
+ DxvkBufferCreateInfo info;
+ info.size = m_shader->shaderConstants().sizeInBytes();
+ info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ info.stages = util::pipelineStages(m_shader->stage());
+ info.access = VK_ACCESS_UNIFORM_READ_BIT;
+
+ VkMemoryPropertyFlags memFlags
+ = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
+ | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+ m_buffer = pDevice->GetDXVKDevice()->createBuffer(info, memFlags);
+
+ std::memcpy(m_buffer->mapPtr(0),
+ m_shader->shaderConstants().data(),
+ m_shader->shaderConstants().sizeInBytes());
+ }
+
+ pDevice->GetDXVKDevice()->registerShader(m_shader);
+ }
+
+
+ D3D11ShaderModuleSet:: D3D11ShaderModuleSet() { }
+ D3D11ShaderModuleSet::~D3D11ShaderModuleSet() { }
+
+
+ HRESULT D3D11ShaderModuleSet::GetShaderModule(
+ D3D11Device* pDevice,
+ const DxvkShaderKey* pShaderKey,
+ const DxbcModuleInfo* pDxbcModuleInfo,
+ const void* pShaderBytecode,
+ size_t BytecodeLength,
+ D3D11CommonShader* pShader) {
+ // Use the shader's unique key for the lookup
+ { std::unique_lock<dxvk::mutex> lock(m_mutex);
+
+ auto entry = m_modules.find(*pShaderKey);
+ if (entry != m_modules.end()) {
+ *pShader = entry->second;
+ return S_OK;
+ }
+ }
+
+ // This shader has not been compiled yet, so we have to create a
+ // new module. This takes a while, so we won't lock the structure.
+ D3D11CommonShader module;
+
+ try {
+ module = D3D11CommonShader(pDevice, pShaderKey,
+ pDxbcModuleInfo, pShaderBytecode, BytecodeLength);
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ return E_INVALIDARG;
+ }
+
+ // Insert the new module into the lookup table. If another thread
+ // has compiled the same shader in the meantime, we should return
+ // that object instead and discard the newly created module.
+ { std::unique_lock<dxvk::mutex> lock(m_mutex);
+
+ auto status = m_modules.insert({ *pShaderKey, module });
+ if (!status.second) {
+ *pShader = status.first->second;
+ return S_OK;
+ }
+ }
+
+ *pShader = std::move(module);
+ return S_OK;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.h
new file mode 100644
index 00000000..3ab16854
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_shader.h
@@ -0,0 +1,158 @@
+#pragma once
+
+#include <mutex>
+#include <unordered_map>
+
+#include "../dxbc/dxbc_module.h"
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_shader.h"
+
+#include "../util/sha1/sha1_util.h"
+
+#include "../util/util_env.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_interfaces.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Common shader object
+ *
+ * Stores the compiled SPIR-V shader and the SHA-1
+ * hash of the original DXBC shader, which can be
+ * used to identify the shader.
+ */
+ class D3D11CommonShader {
+
+ public:
+
+ D3D11CommonShader();
+ D3D11CommonShader(
+ D3D11Device* pDevice,
+ const DxvkShaderKey* pShaderKey,
+ const DxbcModuleInfo* pDxbcModuleInfo,
+ const void* pShaderBytecode,
+ size_t BytecodeLength);
+ ~D3D11CommonShader();
+
+ Rc<DxvkShader> GetShader() const {
+ return m_shader;
+ }
+
+ Rc<DxvkBuffer> GetIcb() const {
+ return m_buffer;
+ }
+
+ std::string GetName() const {
+ return m_shader->debugName();
+ }
+
+ private:
+
+ Rc<DxvkShader> m_shader;
+ Rc<DxvkBuffer> m_buffer;
+
+ };
+
+
+ /**
+ * \brief Common shader interface
+ *
+ * Implements methods for all D3D11*Shader
+ * interfaces and stores the actual shader
+ * module object.
+ */
+ template<typename D3D11Interface, typename D3D10Interface>
+ class D3D11Shader : public D3D11DeviceChild<D3D11Interface> {
+ using D3D10ShaderClass = D3D10Shader<D3D10Interface, D3D11Interface>;
+ public:
+
+ D3D11Shader(D3D11Device* device, const D3D11CommonShader& shader)
+ : D3D11DeviceChild<D3D11Interface>(device),
+ m_shader(shader), m_d3d10(this) { }
+
+ ~D3D11Shader() { }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final {
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(D3D11Interface)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(D3D10Interface)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11Shader::QueryInterface: Unknown interface query");
+ return E_NOINTERFACE;
+ }
+
+ const D3D11CommonShader* GetCommonShader() const {
+ return &m_shader;
+ }
+
+ D3D10ShaderClass* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ private:
+
+ D3D11CommonShader m_shader;
+ D3D10ShaderClass m_d3d10;
+
+ };
+
+ using D3D11VertexShader = D3D11Shader<ID3D11VertexShader, ID3D10VertexShader>;
+ using D3D11HullShader = D3D11Shader<ID3D11HullShader, ID3D10DeviceChild>;
+ using D3D11DomainShader = D3D11Shader<ID3D11DomainShader, ID3D10DeviceChild>;
+ using D3D11GeometryShader = D3D11Shader<ID3D11GeometryShader, ID3D10GeometryShader>;
+ using D3D11PixelShader = D3D11Shader<ID3D11PixelShader, ID3D10PixelShader>;
+ using D3D11ComputeShader = D3D11Shader<ID3D11ComputeShader, ID3D10DeviceChild>;
+
+
+ /**
+ * \brief Shader module set
+ *
+ * Some applications may compile the same shader multiple
+ * times, so we should cache the resulting shader modules
+ * and reuse them rather than creating new ones. This
+ * class is thread-safe.
+ */
+ class D3D11ShaderModuleSet {
+
+ public:
+
+ D3D11ShaderModuleSet();
+ ~D3D11ShaderModuleSet();
+
+ HRESULT GetShaderModule(
+ D3D11Device* pDevice,
+ const DxvkShaderKey* pShaderKey,
+ const DxbcModuleInfo* pDxbcModuleInfo,
+ const void* pShaderBytecode,
+ size_t BytecodeLength,
+ D3D11CommonShader* pShader);
+
+ private:
+
+ dxvk::mutex m_mutex;
+
+ std::unordered_map<
+ DxvkShaderKey,
+ D3D11CommonShader,
+ DxvkHash, DxvkEq> m_modules;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.cpp
new file mode 100644
index 00000000..161566c0
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.cpp
@@ -0,0 +1,199 @@
+#include "d3d11_state.h"
+
+namespace dxvk {
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_BLEND_DESC1& desc) const {
+ DxvkHashState hash;
+ hash.add(desc.AlphaToCoverageEnable);
+ hash.add(desc.IndependentBlendEnable);
+
+ // Render targets 1 to 7 are ignored and may contain
+ // undefined data if independent blend is disabled
+ const uint32_t usedRenderTargets = desc.IndependentBlendEnable ? 8 : 1;
+
+ for (uint32_t i = 0; i < usedRenderTargets; i++)
+ hash.add(this->operator () (desc.RenderTarget[i]));
+
+ return hash;
+ }
+
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_DEPTH_STENCILOP_DESC& desc) const {
+ DxvkHashState hash;
+ hash.add(desc.StencilFunc);
+ hash.add(desc.StencilDepthFailOp);
+ hash.add(desc.StencilPassOp);
+ hash.add(desc.StencilFailOp);
+ return hash;
+ }
+
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_DEPTH_STENCIL_DESC& desc) const {
+ DxvkHashState hash;
+ hash.add(desc.DepthEnable);
+ hash.add(desc.DepthWriteMask);
+ hash.add(desc.DepthFunc);
+ hash.add(desc.StencilEnable);
+ hash.add(desc.StencilReadMask);
+ hash.add(desc.StencilWriteMask);
+ hash.add(this->operator () (desc.FrontFace));
+ hash.add(this->operator () (desc.BackFace));
+ return hash;
+ }
+
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_RASTERIZER_DESC2& desc) const {
+ std::hash<float> fhash;
+
+ DxvkHashState hash;
+ hash.add(desc.FillMode);
+ hash.add(desc.CullMode);
+ hash.add(desc.FrontCounterClockwise);
+ hash.add(desc.DepthBias);
+ hash.add(fhash(desc.SlopeScaledDepthBias));
+ hash.add(fhash(desc.DepthBiasClamp));
+ hash.add(desc.DepthClipEnable);
+ hash.add(desc.ScissorEnable);
+ hash.add(desc.MultisampleEnable);
+ hash.add(desc.AntialiasedLineEnable);
+ hash.add(desc.ForcedSampleCount);
+ hash.add(desc.ConservativeRaster);
+ return hash;
+ }
+
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_RENDER_TARGET_BLEND_DESC1& desc) const {
+ DxvkHashState hash;
+ hash.add(desc.BlendEnable);
+ hash.add(desc.LogicOpEnable);
+ hash.add(desc.SrcBlend);
+ hash.add(desc.DestBlend);
+ hash.add(desc.BlendOp);
+ hash.add(desc.SrcBlendAlpha);
+ hash.add(desc.DestBlendAlpha);
+ hash.add(desc.BlendOpAlpha);
+ hash.add(desc.LogicOp);
+ hash.add(desc.RenderTargetWriteMask);
+ return hash;
+ }
+
+
+ size_t D3D11StateDescHash::operator () (
+ const D3D11_SAMPLER_DESC& desc) const {
+ std::hash<float> fhash;
+
+ DxvkHashState hash;
+ hash.add(desc.Filter);
+ hash.add(desc.AddressU);
+ hash.add(desc.AddressV);
+ hash.add(desc.AddressW);
+ hash.add(fhash(desc.MipLODBias));
+ hash.add(desc.MaxAnisotropy);
+ hash.add(desc.ComparisonFunc);
+ for (uint32_t i = 0; i < 4; i++)
+ hash.add(fhash(desc.BorderColor[i]));
+ hash.add(fhash(desc.MinLOD));
+ hash.add(fhash(desc.MaxLOD));
+ return hash;
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_BLEND_DESC1& a,
+ const D3D11_BLEND_DESC1& b) const {
+ bool eq = a.AlphaToCoverageEnable == b.AlphaToCoverageEnable
+ && a.IndependentBlendEnable == b.IndependentBlendEnable;
+
+ // Render targets 1 to 7 are ignored and may contain
+ // undefined data if independent blend is disabled
+ const uint32_t usedRenderTargets = a.IndependentBlendEnable ? 8 : 1;
+
+ for (uint32_t i = 0; eq && (i < usedRenderTargets); i++)
+ eq &= this->operator () (a.RenderTarget[i], b.RenderTarget[i]);
+
+ return eq;
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_DEPTH_STENCILOP_DESC& a,
+ const D3D11_DEPTH_STENCILOP_DESC& b) const {
+ return a.StencilFunc == b.StencilFunc
+ && a.StencilDepthFailOp == b.StencilDepthFailOp
+ && a.StencilPassOp == b.StencilPassOp
+ && a.StencilFailOp == b.StencilFailOp;
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_DEPTH_STENCIL_DESC& a,
+ const D3D11_DEPTH_STENCIL_DESC& b) const {
+ return a.DepthEnable == b.DepthEnable
+ && a.DepthWriteMask == b.DepthWriteMask
+ && a.DepthFunc == b.DepthFunc
+ && a.StencilEnable == b.StencilEnable
+ && a.StencilReadMask == b.StencilReadMask
+ && a.StencilWriteMask == b.StencilWriteMask
+ && this->operator () (a.FrontFace, b.FrontFace)
+ && this->operator () (a.BackFace, b.BackFace);
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_RASTERIZER_DESC2& a,
+ const D3D11_RASTERIZER_DESC2& b) const {
+ return a.FillMode == b.FillMode
+ && a.CullMode == b.CullMode
+ && a.FrontCounterClockwise == b.FrontCounterClockwise
+ && a.DepthBias == b.DepthBias
+ && a.SlopeScaledDepthBias == b.SlopeScaledDepthBias
+ && a.DepthBiasClamp == b.DepthBiasClamp
+ && a.DepthClipEnable == b.DepthClipEnable
+ && a.ScissorEnable == b.ScissorEnable
+ && a.MultisampleEnable == b.MultisampleEnable
+ && a.AntialiasedLineEnable == b.AntialiasedLineEnable
+ && a.ForcedSampleCount == b.ForcedSampleCount
+ && a.ConservativeRaster == b.ConservativeRaster;
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_RENDER_TARGET_BLEND_DESC1& a,
+ const D3D11_RENDER_TARGET_BLEND_DESC1& b) const {
+ return a.BlendEnable == b.BlendEnable
+ && a.LogicOpEnable == b.LogicOpEnable
+ && a.SrcBlend == b.SrcBlend
+ && a.DestBlend == b.DestBlend
+ && a.BlendOp == b.BlendOp
+ && a.SrcBlendAlpha == b.SrcBlendAlpha
+ && a.DestBlendAlpha == b.DestBlendAlpha
+ && a.BlendOpAlpha == b.BlendOpAlpha
+ && a.LogicOp == b.LogicOp
+ && a.RenderTargetWriteMask == b.RenderTargetWriteMask;
+ }
+
+
+ bool D3D11StateDescEqual::operator () (
+ const D3D11_SAMPLER_DESC& a,
+ const D3D11_SAMPLER_DESC& b) const {
+ return a.Filter == b.Filter
+ && a.AddressU == b.AddressU
+ && a.AddressV == b.AddressV
+ && a.AddressW == b.AddressW
+ && a.MipLODBias == b.MipLODBias
+ && a.MaxAnisotropy == b.MaxAnisotropy
+ && a.ComparisonFunc == b.ComparisonFunc
+ && a.BorderColor[0] == b.BorderColor[0]
+ && a.BorderColor[1] == b.BorderColor[1]
+ && a.BorderColor[2] == b.BorderColor[2]
+ && a.BorderColor[3] == b.BorderColor[3]
+ && a.MinLOD == b.MinLOD
+ && a.MaxLOD == b.MaxLOD;
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.h
new file mode 100644
index 00000000..e807d1ad
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <unordered_map>
+
+#include "d3d11_blend.h"
+#include "d3d11_depth_stencil.h"
+#include "d3d11_rasterizer.h"
+#include "d3d11_sampler.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ struct D3D11StateDescHash {
+ size_t operator () (const D3D11_BLEND_DESC1& desc) const;
+ size_t operator () (const D3D11_DEPTH_STENCILOP_DESC& desc) const;
+ size_t operator () (const D3D11_DEPTH_STENCIL_DESC& desc) const;
+ size_t operator () (const D3D11_RASTERIZER_DESC2& desc) const;
+ size_t operator () (const D3D11_RENDER_TARGET_BLEND_DESC1& desc) const;
+ size_t operator () (const D3D11_SAMPLER_DESC& desc) const;
+ };
+
+
+ struct D3D11StateDescEqual {
+ bool operator () (const D3D11_BLEND_DESC1& a, const D3D11_BLEND_DESC1& b) const;
+ bool operator () (const D3D11_DEPTH_STENCILOP_DESC& a, const D3D11_DEPTH_STENCILOP_DESC& b) const;
+ bool operator () (const D3D11_DEPTH_STENCIL_DESC& a, const D3D11_DEPTH_STENCIL_DESC& b) const;
+ bool operator () (const D3D11_RASTERIZER_DESC2& a, const D3D11_RASTERIZER_DESC2& b) const;
+ bool operator () (const D3D11_RENDER_TARGET_BLEND_DESC1& a, const D3D11_RENDER_TARGET_BLEND_DESC1& b) const;
+ bool operator () (const D3D11_SAMPLER_DESC& a, const D3D11_SAMPLER_DESC& b) const;
+ };
+
+
+ /**
+ * \brief Unique state object set
+ *
+ * When creating state objects, D3D11 first checks if
+ * an object with the same description already exists
+ * and returns it if that is the case. This class
+ * implements that behaviour.
+ */
+ template<typename T>
+ class D3D11StateObjectSet {
+ using DescType = typename T::DescType;
+ public:
+
+ /**
+ * \brief Retrieves a state object
+ *
+ * Returns an object with the same description or
+ * creates a new one if no such object exists.
+ * \param [in] device The calling D3D11 device
+ * \param [in] desc State object description
+ * \returns Pointer to the state object
+ */
+ T* Create(D3D11Device* device, const DescType& desc) {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ auto entry = m_objects.find(desc);
+
+ if (entry != m_objects.end())
+ return ref(&entry->second);
+
+ auto result = m_objects.emplace(
+ std::piecewise_construct,
+ std::tuple(desc),
+ std::tuple(device, desc));
+ return ref(&result.first->second);
+ }
+
+ private:
+
+ dxvk::mutex m_mutex;
+ std::unordered_map<DescType, T,
+ D3D11StateDescHash, D3D11StateDescEqual> m_objects;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.cpp
new file mode 100644
index 00000000..33cc8a33
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.cpp
@@ -0,0 +1,37 @@
+#include "d3d11_state_object.h"
+
+namespace dxvk {
+
+ D3D11DeviceContextState::D3D11DeviceContextState(
+ D3D11Device* pDevice)
+ : D3D11DeviceChild<ID3DDeviceContextState>(pDevice) {
+
+ }
+
+
+ D3D11DeviceContextState::~D3D11DeviceContextState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DeviceContextState::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3DDeviceContextState)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11DeviceContextState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.h
new file mode 100644
index 00000000..775a0951
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_state_object.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "d3d11_device.h"
+#include "d3d11_context_state.h"
+#include "d3d11_device_child.h"
+
+namespace dxvk {
+
+ /**
+ * \brief Device context state implementation
+ *
+ * This is an opaque interface in D3D11, and we only
+ * implement the state block-like functionality, not
+ * the methods to disable certain context and device
+ * interfaces based on the emulated device IID.
+ */
+ class D3D11DeviceContextState : public D3D11DeviceChild<ID3DDeviceContextState> {
+
+ public:
+
+ D3D11DeviceContextState(
+ D3D11Device* pDevice);
+
+ ~D3D11DeviceContextState();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void SetState(const D3D11ContextState& State) {
+ m_state = State;
+ }
+
+ void GetState(D3D11ContextState& State) const {
+ State = m_state;
+ }
+
+ private:
+
+ D3D11ContextState m_state;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.cpp
new file mode 100644
index 00000000..d7483593
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.cpp
@@ -0,0 +1,681 @@
+#include "d3d11_context_imm.h"
+#include "d3d11_device.h"
+#include "d3d11_swapchain.h"
+
+namespace dxvk {
+
+ static uint16_t MapGammaControlPoint(float x) {
+ if (x < 0.0f) x = 0.0f;
+ if (x > 1.0f) x = 1.0f;
+ return uint16_t(65535.0f * x);
+ }
+
+
+ D3D11SwapChain::D3D11SwapChain(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice,
+ HWND hWnd,
+ const DXGI_SWAP_CHAIN_DESC1* pDesc)
+ : m_dxgiDevice(pContainer),
+ m_parent (pDevice),
+ m_window (hWnd),
+ m_desc (*pDesc),
+ m_device (pDevice->GetDXVKDevice()),
+ m_context (m_device->createContext()),
+ m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) {
+ CreateFrameLatencyEvent();
+
+ if (!pDevice->GetOptions()->deferSurfaceCreation)
+ CreatePresenter();
+
+ CreateBackBuffer();
+ CreateBlitter();
+ CreateHud();
+ }
+
+
+ D3D11SwapChain::~D3D11SwapChain() {
+ m_device->waitForSubmission(&m_presentStatus);
+ m_device->waitForIdle();
+
+ if (m_backBuffer)
+ m_backBuffer->ReleasePrivate();
+
+ DestroyFrameLatencyEvent();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ InitReturnPtr(ppvObject);
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(IDXGIVkSwapChain)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11SwapChain::QueryInterface: Unknown interface query");
+ return E_NOINTERFACE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetDesc(
+ DXGI_SWAP_CHAIN_DESC1* pDesc) {
+ *pDesc = m_desc;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetAdapter(
+ REFIID riid,
+ void** ppvObject) {
+ return m_dxgiDevice->GetParent(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetDevice(
+ REFIID riid,
+ void** ppDevice) {
+ return m_dxgiDevice->QueryInterface(riid, ppDevice);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetImage(
+ UINT BufferId,
+ REFIID riid,
+ void** ppBuffer) {
+ InitReturnPtr(ppBuffer);
+
+ if (BufferId > 0) {
+ Logger::err("D3D11: GetImage: BufferId > 0 not supported");
+ return DXGI_ERROR_UNSUPPORTED;
+ }
+
+ return m_backBuffer->QueryInterface(riid, ppBuffer);
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11SwapChain::GetImageIndex() {
+ return 0;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatency() {
+ return m_frameLatency;
+ }
+
+
+ HANDLE STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatencyEvent() {
+ return m_frameLatencyEvent;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::ChangeProperties(
+ const DXGI_SWAP_CHAIN_DESC1* pDesc) {
+
+ m_dirty |= m_desc.Format != pDesc->Format
+ || m_desc.Width != pDesc->Width
+ || m_desc.Height != pDesc->Height
+ || m_desc.BufferCount != pDesc->BufferCount
+ || m_desc.Flags != pDesc->Flags;
+
+ m_desc = *pDesc;
+ CreateBackBuffer();
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetPresentRegion(
+ const RECT* pRegion) {
+ // TODO implement
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetGammaControl(
+ UINT NumControlPoints,
+ const DXGI_RGB* pControlPoints) {
+ bool isIdentity = true;
+
+ if (NumControlPoints > 1) {
+ std::array<DxvkGammaCp, 1025> cp;
+
+ if (NumControlPoints > cp.size())
+ return E_INVALIDARG;
+
+ for (uint32_t i = 0; i < NumControlPoints; i++) {
+ uint16_t identity = MapGammaControlPoint(float(i) / float(NumControlPoints - 1));
+
+ cp[i].r = MapGammaControlPoint(pControlPoints[i].Red);
+ cp[i].g = MapGammaControlPoint(pControlPoints[i].Green);
+ cp[i].b = MapGammaControlPoint(pControlPoints[i].Blue);
+ cp[i].a = 0;
+
+ isIdentity &= cp[i].r == identity
+ && cp[i].g == identity
+ && cp[i].b == identity;
+ }
+
+ if (!isIdentity)
+ m_blitter->setGammaRamp(NumControlPoints, cp.data());
+ }
+
+ if (isIdentity)
+ m_blitter->setGammaRamp(0, nullptr);
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetFrameLatency(
+ UINT MaxLatency) {
+ if (MaxLatency == 0 || MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS)
+ return DXGI_ERROR_INVALID_CALL;
+
+#ifdef _WIN32
+ if (m_frameLatencyEvent) {
+ // Windows DXGI does not seem to handle the case where the new maximum
+ // latency is less than the current value, and some games relying on
+ // this behaviour will hang if we attempt to decrement the semaphore.
+ // Thus, only increment the semaphore as necessary.
+ if (MaxLatency > m_frameLatency)
+ ReleaseSemaphore(m_frameLatencyEvent, MaxLatency - m_frameLatency, nullptr);
+ }
+#endif
+
+ m_frameLatency = MaxLatency;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SwapChain::Present(
+ UINT SyncInterval,
+ UINT PresentFlags,
+ const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
+ auto options = m_parent->GetOptions();
+
+ if (options->syncInterval >= 0)
+ SyncInterval = options->syncInterval;
+
+ if (!(PresentFlags & DXGI_PRESENT_TEST)) {
+ bool vsync = SyncInterval != 0;
+
+ m_dirty |= vsync != m_vsync;
+ m_vsync = vsync;
+ }
+
+ if (m_presenter == nullptr)
+ CreatePresenter();
+
+ HRESULT hr = S_OK;
+
+ if (!m_presenter->hasSwapChain()) {
+ RecreateSwapChain(m_vsync);
+ m_dirty = false;
+ }
+
+ if (!m_presenter->hasSwapChain())
+ hr = DXGI_STATUS_OCCLUDED;
+
+ if (m_device->getDeviceStatus() != VK_SUCCESS)
+ hr = DXGI_ERROR_DEVICE_RESET;
+
+ if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK)
+ return hr;
+
+ if (std::exchange(m_dirty, false))
+ RecreateSwapChain(m_vsync);
+
+ try {
+ PresentImage(SyncInterval);
+ } catch (const DxvkError& e) {
+ Logger::err(e.message());
+ hr = E_FAIL;
+ }
+
+ return hr;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11SwapChain::NotifyModeChange(
+ BOOL Windowed,
+ const DXGI_MODE_DESC* pDisplayMode) {
+ if (Windowed || !pDisplayMode) {
+ // Display modes aren't meaningful in windowed mode
+ m_displayRefreshRate = 0.0;
+ } else {
+ DXGI_RATIONAL rate = pDisplayMode->RefreshRate;
+ m_displayRefreshRate = double(rate.Numerator) / double(rate.Denominator);
+ }
+
+ if (m_presenter != nullptr)
+ m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate);
+ }
+
+
+ HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
+ Com<ID3D11DeviceContext> deviceContext = nullptr;
+ m_parent->GetImmediateContext(&deviceContext);
+
+ // Flush pending rendering commands before
+ auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
+ immediateContext->Flush();
+
+ // Bump our frame id.
+ ++m_frameId;
+
+ for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
+ SynchronizePresent();
+
+ if (!m_presenter->hasSwapChain())
+ return DXGI_STATUS_OCCLUDED;
+
+ // Presentation semaphores and WSI swap chain image
+ vk::PresenterInfo info = m_presenter->info();
+ vk::PresenterSync sync;
+
+ uint32_t imageIndex = 0;
+
+ VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
+
+ while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
+ RecreateSwapChain(m_vsync);
+
+ if (!m_presenter->hasSwapChain())
+ return DXGI_STATUS_OCCLUDED;
+
+ info = m_presenter->info();
+ status = m_presenter->acquireNextImage(sync, imageIndex);
+ }
+
+ // Resolve back buffer if it is multisampled. We
+ // only have to do it only for the first frame.
+ m_context->beginRecording(
+ m_device->createCommandList());
+
+ m_blitter->presentImage(m_context.ptr(),
+ m_imageViews.at(imageIndex), VkRect2D(),
+ m_swapImageView, VkRect2D());
+
+ if (m_hud != nullptr)
+ m_hud->render(m_context, info.format, info.imageExtent);
+
+ if (i + 1 >= SyncInterval)
+ m_context->signal(m_frameLatencySignal, m_frameId);
+
+ SubmitPresent(immediateContext, sync, i);
+ }
+
+ SyncFrameLatency();
+ return S_OK;
+ }
+
+
+ void D3D11SwapChain::SubmitPresent(
+ D3D11ImmediateContext* pContext,
+ const vk::PresenterSync& Sync,
+ uint32_t FrameId) {
+ auto lock = pContext->LockContext();
+
+ // Present from CS thread so that we don't
+ // have to synchronize with it first.
+ m_presentStatus.result = VK_NOT_READY;
+
+ pContext->EmitCs([this,
+ cFrameId = FrameId,
+ cSync = Sync,
+ cHud = m_hud,
+ cCommandList = m_context->endRecording()
+ ] (DxvkContext* ctx) {
+ m_device->submitCommandList(cCommandList,
+ cSync.acquire, cSync.present);
+
+ if (cHud != nullptr && !cFrameId)
+ cHud->update();
+
+ m_device->presentImage(m_presenter, &m_presentStatus);
+ });
+
+ pContext->FlushCsChunk();
+ }
+
+
+ void D3D11SwapChain::SynchronizePresent() {
+ // Recreate swap chain if the previous present call failed
+ VkResult status = m_device->waitForSubmission(&m_presentStatus);
+
+ if (status != VK_SUCCESS)
+ RecreateSwapChain(m_vsync);
+ }
+
+
+ void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) {
+ // Ensure that we can safely destroy the swap chain
+ m_device->waitForSubmission(&m_presentStatus);
+ m_device->waitForIdle();
+
+ m_presentStatus.result = VK_SUCCESS;
+
+ vk::PresenterDesc presenterDesc;
+ presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
+ presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
+ presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
+ presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
+ presenterDesc.fullScreenExclusive = PickFullscreenMode();
+
+ if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS)
+ throw DxvkError("D3D11SwapChain: Failed to recreate swap chain");
+
+ CreateRenderTargetViews();
+ }
+
+
+ void D3D11SwapChain::CreateFrameLatencyEvent() {
+ m_frameLatencySignal = new sync::CallbackFence(m_frameId);
+
+ if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) {
+#ifndef DXVK_NATIVE
+ m_frameLatencyEvent = CreateEvent(nullptr, false, true, nullptr);
+#else
+ throw DxvkError("DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT not supported on this platform.");
+#endif
+ }
+ }
+
+
+ void D3D11SwapChain::CreatePresenter() {
+ DxvkDeviceQueue graphicsQueue = m_device->queues().graphics;
+
+ vk::PresenterDevice presenterDevice;
+ presenterDevice.queueFamily = graphicsQueue.queueFamily;
+ presenterDevice.queue = graphicsQueue.queueHandle;
+ presenterDevice.adapter = m_device->adapter()->handle();
+ presenterDevice.features.fullScreenExclusive = m_device->extensions().extFullScreenExclusive;
+
+ vk::PresenterDesc presenterDesc;
+ presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
+ presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
+ presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
+ presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
+ presenterDesc.fullScreenExclusive = PickFullscreenMode();
+
+ m_presenter = new vk::Presenter(m_window,
+ m_device->adapter()->vki(),
+ m_device->vkd(),
+ presenterDevice,
+ presenterDesc);
+
+ m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
+ m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate);
+
+ CreateRenderTargetViews();
+ }
+
+
+ void D3D11SwapChain::CreateRenderTargetViews() {
+ vk::PresenterInfo info = m_presenter->info();
+
+ m_imageViews.clear();
+ m_imageViews.resize(info.imageCount);
+
+ DxvkImageCreateInfo imageInfo;
+ imageInfo.type = VK_IMAGE_TYPE_2D;
+ imageInfo.format = info.format.format;
+ imageInfo.flags = 0;
+ imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 };
+ imageInfo.numLayers = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ imageInfo.stages = 0;
+ imageInfo.access = 0;
+ imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ imageInfo.shared = VK_TRUE;
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = info.format.format;
+ viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+
+ for (uint32_t i = 0; i < info.imageCount; i++) {
+ VkImage imageHandle = m_presenter->getImage(i).image;
+
+ Rc<DxvkImage> image = new DxvkImage(
+ m_device->vkd(), imageInfo, imageHandle);
+
+ m_imageViews[i] = new DxvkImageView(
+ m_device->vkd(), image, viewInfo);
+ }
+ }
+
+
+ void D3D11SwapChain::CreateBackBuffer() {
+ // Explicitly destroy current swap image before
+ // creating a new one to free up resources
+ if (m_backBuffer)
+ m_backBuffer->ReleasePrivate();
+
+ m_swapImage = nullptr;
+ m_swapImageView = nullptr;
+ m_backBuffer = nullptr;
+
+ // Create new back buffer
+ D3D11_COMMON_TEXTURE_DESC desc;
+ desc.Width = std::max(m_desc.Width, 1u);
+ desc.Height = std::max(m_desc.Height, 1u);
+ desc.Depth = 1;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = m_desc.Format;
+ desc.SampleDesc = m_desc.SampleDesc;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+ desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
+
+ if (m_desc.BufferUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
+ desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
+
+ if (m_desc.BufferUsage & DXGI_USAGE_SHADER_INPUT)
+ desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+
+ if (m_desc.BufferUsage & DXGI_USAGE_UNORDERED_ACCESS)
+ desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
+ if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE)
+ desc.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
+
+ DXGI_USAGE dxgiUsage = DXGI_USAGE_BACK_BUFFER;
+
+ if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD
+ || m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
+ dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT;
+
+ m_backBuffer = new D3D11Texture2D(m_parent, &desc, dxgiUsage, VK_NULL_HANDLE);
+ m_backBuffer->AddRefPrivate();
+
+ m_swapImage = GetCommonTexture(m_backBuffer)->GetImage();
+
+ // Create an image view that allows the
+ // image to be bound as a shader resource.
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = m_swapImage->info().format;
+ viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
+ viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ m_swapImageView = m_device->createImageView(m_swapImage, viewInfo);
+
+ // Initialize the image so that we can use it. Clearing
+ // to black prevents garbled output for the first frame.
+ VkImageSubresourceRange subresources;
+ subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ subresources.baseMipLevel = 0;
+ subresources.levelCount = 1;
+ subresources.baseArrayLayer = 0;
+ subresources.layerCount = 1;
+
+ VkClearColorValue clearColor;
+ clearColor.float32[0] = 0.0f;
+ clearColor.float32[1] = 0.0f;
+ clearColor.float32[2] = 0.0f;
+ clearColor.float32[3] = 0.0f;
+
+ m_context->beginRecording(
+ m_device->createCommandList());
+
+ m_context->clearColorImage(
+ m_swapImage, clearColor, subresources);
+
+ m_device->submitCommandList(
+ m_context->endRecording(),
+ VK_NULL_HANDLE,
+ VK_NULL_HANDLE);
+ }
+
+
+ void D3D11SwapChain::CreateBlitter() {
+ m_blitter = new DxvkSwapchainBlitter(m_device);
+ }
+
+
+ void D3D11SwapChain::CreateHud() {
+ m_hud = hud::Hud::createHud(m_device);
+
+ if (m_hud != nullptr)
+ m_hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
+ }
+
+
+ void D3D11SwapChain::DestroyFrameLatencyEvent() {
+#ifndef DXVK_NATIVE
+ CloseHandle(m_frameLatencyEvent);
+#endif
+ }
+
+
+ void D3D11SwapChain::SyncFrameLatency() {
+ // Wait for the sync event so that we respect the maximum frame latency
+ m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
+
+#ifndef DXVK_NATIVE
+ if (m_frameLatencyEvent) {
+ m_frameLatencySignal->setCallback(m_frameId, [cFrameLatencyEvent = m_frameLatencyEvent] () {
+ ReleaseSemaphore(cFrameLatencyEvent, 1, nullptr);
+ });
+ }
+#endif
+ }
+
+
+ uint32_t D3D11SwapChain::GetActualFrameLatency() {
+ uint32_t maxFrameLatency = m_frameLatency;
+
+ if (!(m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
+ m_dxgiDevice->GetMaximumFrameLatency(&maxFrameLatency);
+
+ if (m_frameLatencyCap)
+ maxFrameLatency = std::min(maxFrameLatency, m_frameLatencyCap);
+
+ maxFrameLatency = std::min(maxFrameLatency, m_desc.BufferCount + 1);
+ return maxFrameLatency;
+ }
+
+
+ uint32_t D3D11SwapChain::PickFormats(
+ DXGI_FORMAT Format,
+ VkSurfaceFormatKHR* pDstFormats) {
+ uint32_t n = 0;
+
+ switch (Format) {
+ default:
+ Logger::warn(str::format("D3D11SwapChain: Unexpected format: ", m_desc.Format));
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM: {
+ pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ } break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: {
+ pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ } break;
+
+ case DXGI_FORMAT_R10G10B10A2_UNORM: {
+ pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ } break;
+
+ case DXGI_FORMAT_R16G16B16A16_FLOAT: {
+ pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+ } break;
+ }
+
+ return n;
+ }
+
+
+ uint32_t D3D11SwapChain::PickPresentModes(
+ BOOL Vsync,
+ VkPresentModeKHR* pDstModes) {
+ uint32_t n = 0;
+
+ if (Vsync) {
+ if (m_parent->GetOptions()->tearFree == Tristate::False)
+ pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
+ pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR;
+ } else {
+ if (m_parent->GetOptions()->tearFree != Tristate::True)
+ pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR;
+ pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR;
+ }
+
+ return n;
+ }
+
+
+ uint32_t D3D11SwapChain::PickImageCount(
+ UINT Preferred) {
+ int32_t option = m_parent->GetOptions()->numBackBuffers;
+ return option > 0 ? uint32_t(option) : uint32_t(Preferred);
+ }
+
+
+ VkFullScreenExclusiveEXT D3D11SwapChain::PickFullscreenMode() {
+ return m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
+ ? VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT
+ : VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
+ }
+
+
+ std::string D3D11SwapChain::GetApiName() const {
+ Com<IDXGIDXVKDevice> device;
+ m_parent->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast<void**>(&device));
+
+ uint32_t apiVersion = device->GetAPIVersion();
+ uint32_t featureLevel = m_parent->GetFeatureLevel();
+
+ uint32_t flHi = (featureLevel >> 12);
+ uint32_t flLo = (featureLevel >> 8) & 0x7;
+
+ return str::format("D3D", apiVersion, " FL", flHi, "_", flLo);
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.h
new file mode 100644
index 00000000..8fc9fe10
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_swapchain.h
@@ -0,0 +1,164 @@
+#pragma once
+
+#include "d3d11_texture.h"
+
+#include "../dxvk/hud/dxvk_hud.h"
+
+#include "../dxvk/dxvk_swapchain_blitter.h"
+
+#include "../util/sync/sync_signal.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+ class D3D11DXGIDevice;
+
+ class D3D11SwapChain : public ComObject<IDXGIVkSwapChain> {
+ constexpr static uint32_t DefaultFrameLatency = 1;
+ public:
+
+ D3D11SwapChain(
+ D3D11DXGIDevice* pContainer,
+ D3D11Device* pDevice,
+ HWND hWnd,
+ const DXGI_SWAP_CHAIN_DESC1* pDesc);
+
+ ~D3D11SwapChain();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetDesc(
+ DXGI_SWAP_CHAIN_DESC1* pDesc);
+
+ HRESULT STDMETHODCALLTYPE GetAdapter(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetDevice(
+ REFIID riid,
+ void** ppDevice);
+
+ HRESULT STDMETHODCALLTYPE GetImage(
+ UINT BufferId,
+ REFIID riid,
+ void** ppBuffer);
+
+ UINT STDMETHODCALLTYPE GetImageIndex();
+
+ UINT STDMETHODCALLTYPE GetFrameLatency();
+
+ HANDLE STDMETHODCALLTYPE GetFrameLatencyEvent();
+
+ HRESULT STDMETHODCALLTYPE ChangeProperties(
+ const DXGI_SWAP_CHAIN_DESC1* pDesc);
+
+ HRESULT STDMETHODCALLTYPE SetPresentRegion(
+ const RECT* pRegion);
+
+ HRESULT STDMETHODCALLTYPE SetGammaControl(
+ UINT NumControlPoints,
+ const DXGI_RGB* pControlPoints);
+
+ HRESULT STDMETHODCALLTYPE SetFrameLatency(
+ UINT MaxLatency);
+
+ HRESULT STDMETHODCALLTYPE Present(
+ UINT SyncInterval,
+ UINT PresentFlags,
+ const DXGI_PRESENT_PARAMETERS* pPresentParameters);
+
+ void STDMETHODCALLTYPE NotifyModeChange(
+ BOOL Windowed,
+ const DXGI_MODE_DESC* pDisplayMode);
+
+ private:
+
+ enum BindingIds : uint32_t {
+ Image = 0,
+ Gamma = 1,
+ };
+
+ Com<D3D11DXGIDevice, false> m_dxgiDevice;
+
+ D3D11Device* m_parent;
+ HWND m_window;
+
+ DXGI_SWAP_CHAIN_DESC1 m_desc;
+
+ Rc<DxvkDevice> m_device;
+ Rc<DxvkContext> m_context;
+
+ Rc<vk::Presenter> m_presenter;
+
+ Rc<DxvkImage> m_swapImage;
+ Rc<DxvkImageView> m_swapImageView;
+ Rc<DxvkSwapchainBlitter> m_blitter;
+
+ Rc<hud::Hud> m_hud;
+
+ D3D11Texture2D* m_backBuffer = nullptr;
+ DxvkSubmitStatus m_presentStatus;
+
+ std::vector<Rc<DxvkImageView>> m_imageViews;
+
+ uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS;
+ uint32_t m_frameLatency = DefaultFrameLatency;
+ uint32_t m_frameLatencyCap = 0;
+ HANDLE m_frameLatencyEvent = nullptr;
+ Rc<sync::CallbackFence> m_frameLatencySignal;
+
+ bool m_dirty = true;
+ bool m_vsync = true;
+
+ double m_displayRefreshRate = 0.0;
+
+ HRESULT PresentImage(UINT SyncInterval);
+
+ void SubmitPresent(
+ D3D11ImmediateContext* pContext,
+ const vk::PresenterSync& Sync,
+ uint32_t FrameId);
+
+ void SynchronizePresent();
+
+ void RecreateSwapChain(
+ BOOL Vsync);
+
+ void CreateFrameLatencyEvent();
+
+ void CreatePresenter();
+
+ void CreateRenderTargetViews();
+
+ void CreateBackBuffer();
+
+ void CreateBlitter();
+
+ void CreateHud();
+
+ void DestroyFrameLatencyEvent();
+
+ void SyncFrameLatency();
+
+ uint32_t GetActualFrameLatency();
+
+ uint32_t PickFormats(
+ DXGI_FORMAT Format,
+ VkSurfaceFormatKHR* pDstFormats);
+
+ uint32_t PickPresentModes(
+ BOOL Vsync,
+ VkPresentModeKHR* pDstModes);
+
+ uint32_t PickImageCount(
+ UINT Preferred);
+
+ VkFullScreenExclusiveEXT PickFullscreenMode();
+
+ std::string GetApiName() const;
+
+ };
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.cpp
new file mode 100644
index 00000000..35c6afd8
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.cpp
@@ -0,0 +1,1269 @@
+#include "d3d11_device.h"
+#include "d3d11_gdi.h"
+#include "d3d11_texture.h"
+
+namespace dxvk {
+
+ D3D11CommonTexture::D3D11CommonTexture(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc,
+ D3D11_RESOURCE_DIMENSION Dimension,
+ DXGI_USAGE DxgiUsage,
+ VkImage vkImage)
+ : m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) {
+ DXGI_VK_FORMAT_MODE formatMode = GetFormatMode();
+ DXGI_VK_FORMAT_INFO formatInfo = m_device->LookupFormat(m_desc.Format, formatMode);
+ DXGI_VK_FORMAT_FAMILY formatFamily = m_device->LookupFamily(m_desc.Format, formatMode);
+ DXGI_VK_FORMAT_INFO formatPacked = m_device->LookupPackedFormat(m_desc.Format, formatMode);
+ m_packedFormat = formatPacked.Format;
+
+ DxvkImageCreateInfo imageInfo;
+ imageInfo.type = GetVkImageType();
+ imageInfo.format = formatInfo.Format;
+ imageInfo.flags = 0;
+ imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.extent.width = m_desc.Width;
+ imageInfo.extent.height = m_desc.Height;
+ imageInfo.extent.depth = m_desc.Depth;
+ imageInfo.numLayers = m_desc.ArraySize;
+ imageInfo.mipLevels = m_desc.MipLevels;
+ imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+ | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_TRANSFER_WRITE_BIT;
+ imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ imageInfo.shared = vkImage != VK_NULL_HANDLE;
+
+ if (!pDevice->GetOptions()->disableMsaa)
+ DecodeSampleCount(m_desc.SampleDesc.Count, &imageInfo.sampleCount);
+
+ // Integer clear operations on UAVs are implemented using
+ // a view with a bit-compatible integer format, so we'll
+ // have to include that format in the format family
+ if (m_desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
+ DXGI_VK_FORMAT_INFO formatBase = m_device->LookupFormat(
+ m_desc.Format, DXGI_VK_FORMAT_MODE_RAW);
+
+ if (formatBase.Format != formatInfo.Format
+ && formatBase.Format != VK_FORMAT_UNDEFINED) {
+ formatFamily.Add(formatBase.Format);
+ formatFamily.Add(formatInfo.Format);
+ }
+ }
+
+ // The image must be marked as mutable if it can be reinterpreted
+ // by a view with a different format. Depth-stencil formats cannot
+ // be reinterpreted in Vulkan, so we'll ignore those.
+ auto formatProperties = imageFormatInfo(formatInfo.Format);
+
+ bool isTypeless = formatInfo.Aspect == 0;
+ bool isMutable = formatFamily.FormatCount > 1;
+ bool isMultiPlane = (formatProperties->aspectMask & VK_IMAGE_ASPECT_PLANE_0_BIT) != 0;
+ bool isColorFormat = (formatProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
+
+ if (isMutable && (isColorFormat || isMultiPlane)) {
+ imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+ // Typeless UAV images have relaxed reinterpretation rules
+ if (!isTypeless || !(m_desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)) {
+ imageInfo.viewFormatCount = formatFamily.FormatCount;
+ imageInfo.viewFormats = formatFamily.Formats;
+ }
+ }
+
+ // Adjust image flags based on the corresponding D3D flags
+ if (m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) {
+ imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ imageInfo.stages |= pDevice->GetEnabledShaderStages();
+ imageInfo.access |= VK_ACCESS_SHADER_READ_BIT;
+ }
+
+ if (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) {
+ imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
+ | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ }
+
+ if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) {
+ imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
+ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ }
+
+ if (m_desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
+ imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
+ imageInfo.stages |= pDevice->GetEnabledShaderStages();
+ imageInfo.access |= VK_ACCESS_SHADER_READ_BIT
+ | VK_ACCESS_SHADER_WRITE_BIT;
+
+ // UAVs are not supported for sRGB formats on most drivers,
+ // but we can still create linear views for the image
+ if (formatProperties->flags.test(DxvkFormatFlag::ColorSpaceSrgb))
+ imageInfo.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
+ }
+
+ // Multi-plane formats need views to be created with color formats, and
+ // may not report all relevant usage flags as supported on their own.
+ // Also, enable sampled bit to enable use with video processor APIs.
+ if (isMultiPlane) {
+ imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
+ | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
+ }
+
+ // Access pattern for meta-resolve operations
+ if (imageInfo.sampleCount != VK_SAMPLE_COUNT_1_BIT && isColorFormat) {
+ imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ imageInfo.stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ imageInfo.access |= VK_ACCESS_SHADER_READ_BIT;
+ }
+
+ if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
+ imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+
+ if (Dimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D &&
+ (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET))
+ imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
+
+ // Swap chain back buffers need to be shader readable
+ if (DxgiUsage & DXGI_USAGE_BACK_BUFFER) {
+ imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ imageInfo.stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ imageInfo.access |= VK_ACCESS_SHADER_READ_BIT;
+ imageInfo.shared = VK_TRUE;
+ }
+
+ // Some image formats (i.e. the R32G32B32 ones) are
+ // only supported with linear tiling on most GPUs
+ if (!CheckImageSupport(&imageInfo, VK_IMAGE_TILING_OPTIMAL))
+ imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+
+ // Determine map mode based on our findings
+ m_mapMode = DetermineMapMode(&imageInfo);
+
+ // If the image is mapped directly to host memory, we need
+ // to enable linear tiling, and DXVK needs to be aware that
+ // the image can be accessed by the host.
+ if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
+ imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ }
+
+ // If necessary, create the mapped linear buffer
+ if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ for (uint32_t i = 0; i < m_desc.ArraySize; i++) {
+ for (uint32_t j = 0; j < m_desc.MipLevels; j++) {
+ if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
+ m_buffers.push_back(CreateMappedBuffer(j));
+
+ m_mapTypes.push_back(D3D11_MAP(~0u));
+ }
+ }
+ }
+
+ // Skip image creation if possible
+ if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING)
+ return;
+
+ // We must keep LINEAR images in GENERAL layout, but we
+ // can choose a better layout for the image based on how
+ // it is going to be used by the game.
+ if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && !isMultiPlane)
+ imageInfo.layout = OptimizeLayout(imageInfo.usage);
+
+ // For some formats, we need to enable sampled and/or
+ // render target capabilities if available, but these
+ // should in no way affect the default image layout
+ imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling);
+ imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags);
+
+ // Check if we can actually create the image
+ if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
+ throw DxvkError(str::format(
+ "D3D11: Cannot create texture:",
+ "\n Format: ", m_desc.Format,
+ "\n Extent: ", m_desc.Width,
+ "x", m_desc.Height,
+ "x", m_desc.Depth,
+ "\n Samples: ", m_desc.SampleDesc.Count,
+ "\n Layers: ", m_desc.ArraySize,
+ "\n Levels: ", m_desc.MipLevels,
+ "\n Usage: ", std::hex, m_desc.BindFlags,
+ "\n Flags: ", std::hex, m_desc.MiscFlags));
+ }
+
+ // Create the image on a host-visible memory type
+ // in case it is going to be mapped directly.
+ VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+ if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) {
+ memoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ }
+
+ if (vkImage == VK_NULL_HANDLE)
+ m_image = m_device->GetDXVKDevice()->createImage(imageInfo, memoryProperties);
+ else
+ m_image = m_device->GetDXVKDevice()->createImageFromVkImage(imageInfo, vkImage);
+ }
+
+
+ D3D11CommonTexture::~D3D11CommonTexture() {
+
+ }
+
+
+ VkDeviceSize D3D11CommonTexture::ComputeMappedOffset(UINT Subresource, UINT Plane, VkOffset3D Offset) const {
+ auto packedFormatInfo = imageFormatInfo(m_packedFormat);
+
+ VkImageAspectFlags aspectMask = packedFormatInfo->aspectMask;
+ VkDeviceSize elementSize = packedFormatInfo->elementSize;
+
+ if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
+ auto plane = &packedFormatInfo->planes[Plane];
+ elementSize = plane->elementSize;
+ Offset.x /= plane->blockSize.width;
+ Offset.y /= plane->blockSize.height;
+ aspectMask = vk::getPlaneAspect(Plane);
+ }
+
+ auto layout = GetSubresourceLayout(aspectMask, Subresource);
+ auto blockOffset = util::computeBlockOffset(Offset, packedFormatInfo->blockSize);
+
+ return VkDeviceSize(blockOffset.z) * layout.DepthPitch
+ + VkDeviceSize(blockOffset.y) * layout.RowPitch
+ + VkDeviceSize(blockOffset.x) * elementSize
+ + VkDeviceSize(layout.Offset);
+ }
+
+
+ VkImageSubresource D3D11CommonTexture::GetSubresourceFromIndex(
+ VkImageAspectFlags Aspect,
+ UINT Subresource) const {
+ VkImageSubresource result;
+ result.aspectMask = Aspect;
+ result.mipLevel = Subresource % m_desc.MipLevels;
+ result.arrayLayer = Subresource / m_desc.MipLevels;
+ return result;
+ }
+
+
+ D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::GetSubresourceLayout(
+ VkImageAspectFlags AspectMask,
+ UINT Subresource) const {
+ VkImageSubresource subresource = GetSubresourceFromIndex(AspectMask, Subresource);
+ D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { };
+
+ switch (m_mapMode) {
+ case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT: {
+ auto vkLayout = m_image->querySubresourceLayout(subresource);
+ layout.Offset = vkLayout.offset;
+ layout.Size = vkLayout.size;
+ layout.RowPitch = vkLayout.rowPitch;
+ layout.DepthPitch = vkLayout.depthPitch;
+ } break;
+
+ case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER:
+ case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: {
+ auto packedFormatInfo = imageFormatInfo(m_packedFormat);
+
+ VkImageAspectFlags aspects = packedFormatInfo->aspectMask;
+ VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel);
+
+ while (aspects) {
+ auto aspect = vk::getNextAspect(aspects);
+ auto extent = mipExtent;
+ auto elementSize = packedFormatInfo->elementSize;
+
+ if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
+ auto plane = &packedFormatInfo->planes[vk::getPlaneIndex(aspect)];
+ extent.width /= plane->blockSize.width;
+ extent.height /= plane->blockSize.height;
+ elementSize = plane->elementSize;
+ }
+
+ auto blockCount = util::computeBlockCount(extent, packedFormatInfo->blockSize);
+
+ if (!layout.RowPitch) {
+ layout.RowPitch = elementSize * blockCount.width;
+ layout.DepthPitch = elementSize * blockCount.width * blockCount.height;
+ }
+
+ VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth;
+
+ if (aspect & AspectMask)
+ layout.Size += size;
+ else if (!layout.Size)
+ layout.Offset += size;
+ }
+ } break;
+
+ case D3D11_COMMON_TEXTURE_MAP_MODE_NONE:
+ break; /* no op */
+ }
+
+ // D3D wants us to return the total subresource size in some instances
+ if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE2D) layout.RowPitch = layout.Size;
+ if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE3D) layout.DepthPitch = layout.Size;
+ return layout;
+ }
+
+
+ DXGI_VK_FORMAT_MODE D3D11CommonTexture::GetFormatMode() const {
+ if (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET)
+ return DXGI_VK_FORMAT_MODE_COLOR;
+
+ if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
+ return DXGI_VK_FORMAT_MODE_DEPTH;
+
+ return DXGI_VK_FORMAT_MODE_ANY;
+ }
+
+
+ uint32_t D3D11CommonTexture::GetPlaneCount() const {
+ return vk::getPlaneCount(m_image->formatInfo()->aspectMask);
+ }
+
+
+ bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format, UINT Plane) const {
+ const DxvkImageCreateInfo& imageInfo = m_image->info();
+
+ // Check whether the given bind flags are supported
+ if ((m_desc.BindFlags & BindFlags) != BindFlags)
+ return false;
+
+ // Check whether the view format is compatible
+ DXGI_VK_FORMAT_MODE formatMode = GetFormatMode();
+ DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, formatMode);
+ DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode);
+
+ // Check whether the plane index is valid for the given format
+ uint32_t planeCount = GetPlaneCount();
+
+ if (Plane >= planeCount)
+ return false;
+
+ if (imageInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
+ // Check whether the given combination of image
+ // view type and view format is actually supported
+ VkFormatFeatureFlags features = GetImageFormatFeatures(BindFlags);
+
+ if (!CheckFormatFeatureSupport(viewFormat.Format, features))
+ return false;
+
+ // Using the image format itself is supported for non-planar formats
+ if (viewFormat.Format == baseFormat.Format && planeCount == 1)
+ return true;
+
+ // If there is a list of compatible formats, the view format must be
+ // included in that list. For planar formats, the list is laid out in
+ // such a way that the n-th format is supported for the n-th plane.
+ for (size_t i = Plane; i < imageInfo.viewFormatCount; i += planeCount) {
+ if (imageInfo.viewFormats[i] == viewFormat.Format) {
+ return true;
+ }
+ }
+
+ // Otherwise, all bit-compatible formats can be used.
+ if (imageInfo.viewFormatCount == 0 && planeCount == 1) {
+ auto baseFormatInfo = imageFormatInfo(baseFormat.Format);
+ auto viewFormatInfo = imageFormatInfo(viewFormat.Format);
+
+ return baseFormatInfo->aspectMask == viewFormatInfo->aspectMask
+ && baseFormatInfo->elementSize == viewFormatInfo->elementSize;
+ }
+
+ return false;
+ } else {
+ // For non-mutable images, the view format
+ // must be identical to the image format.
+ return viewFormat.Format == baseFormat.Format && planeCount == 1;
+ }
+ }
+
+
+ HRESULT D3D11CommonTexture::NormalizeTextureProperties(D3D11_COMMON_TEXTURE_DESC* pDesc) {
+ if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0 || pDesc->ArraySize == 0)
+ return E_INVALIDARG;
+
+ if (FAILED(DecodeSampleCount(pDesc->SampleDesc.Count, nullptr)))
+ return E_INVALIDARG;
+
+ if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
+ && (pDesc->Usage == D3D11_USAGE_STAGING
+ || (pDesc->Format != DXGI_FORMAT_B8G8R8A8_TYPELESS
+ && pDesc->Format != DXGI_FORMAT_B8G8R8A8_UNORM
+ && pDesc->Format != DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)))
+ return E_INVALIDARG;
+
+ if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)
+ && (pDesc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET))
+ != (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET))
+ return E_INVALIDARG;
+
+ // TILE_POOL is invalid, but we don't support TILED either
+ if (pDesc->MiscFlags & (D3D11_RESOURCE_MISC_TILE_POOL | D3D11_RESOURCE_MISC_TILED))
+ return E_INVALIDARG;
+
+ // Use the maximum possible mip level count if the supplied
+ // mip level count is either unspecified (0) or invalid
+ const uint32_t maxMipLevelCount = pDesc->SampleDesc.Count <= 1
+ ? util::computeMipLevelCount({ pDesc->Width, pDesc->Height, pDesc->Depth })
+ : 1u;
+
+ if (pDesc->MipLevels == 0 || pDesc->MipLevels > maxMipLevelCount)
+ pDesc->MipLevels = maxMipLevelCount;
+
+ // Row-major is only supported for textures with one single
+ // subresource and one sample and cannot have bind flags.
+ if (pDesc->TextureLayout == D3D11_TEXTURE_LAYOUT_ROW_MAJOR
+ && (pDesc->MipLevels != 1 || pDesc->SampleDesc.Count != 1 || pDesc->BindFlags))
+ return E_INVALIDARG;
+
+ // Standard swizzle is unsupported
+ if (pDesc->TextureLayout == D3D11_TEXTURE_LAYOUT_64K_STANDARD_SWIZZLE)
+ return E_INVALIDARG;
+
+ return S_OK;
+ }
+
+
+ BOOL D3D11CommonTexture::CheckImageSupport(
+ const DxvkImageCreateInfo* pImageInfo,
+ VkImageTiling Tiling) const {
+ const Rc<DxvkAdapter> adapter = m_device->GetDXVKDevice()->adapter();
+
+ VkImageUsageFlags usage = pImageInfo->usage;
+
+ if (pImageInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
+ usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ VkImageFormatProperties formatProps = { };
+ VkResult status = adapter->imageFormatProperties(
+ pImageInfo->format, pImageInfo->type, Tiling,
+ usage, pImageInfo->flags, formatProps);
+
+ if (status != VK_SUCCESS)
+ return FALSE;
+
+ return (pImageInfo->extent.width <= formatProps.maxExtent.width)
+ && (pImageInfo->extent.height <= formatProps.maxExtent.height)
+ && (pImageInfo->extent.depth <= formatProps.maxExtent.depth)
+ && (pImageInfo->numLayers <= formatProps.maxArrayLayers)
+ && (pImageInfo->mipLevels <= formatProps.maxMipLevels)
+ && (pImageInfo->sampleCount & formatProps.sampleCounts);
+ }
+
+
+ BOOL D3D11CommonTexture::CheckFormatFeatureSupport(
+ VkFormat Format,
+ VkFormatFeatureFlags Features) const {
+ VkFormatProperties properties = m_device->GetDXVKDevice()->adapter()->formatProperties(Format);
+
+ return (properties.linearTilingFeatures & Features) == Features
+ || (properties.optimalTilingFeatures & Features) == Features;
+ }
+
+
+ VkImageUsageFlags D3D11CommonTexture::EnableMetaCopyUsage(
+ VkFormat Format,
+ VkImageTiling Tiling) const {
+ VkFormatFeatureFlags requestedFeatures = 0;
+
+ if (Format == VK_FORMAT_D16_UNORM || Format == VK_FORMAT_D32_SFLOAT) {
+ requestedFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+ | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ }
+
+ if (Format == VK_FORMAT_R16_UNORM || Format == VK_FORMAT_R32_SFLOAT) {
+ requestedFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+ | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ }
+
+ if (Format == VK_FORMAT_D32_SFLOAT_S8_UINT || Format == VK_FORMAT_D24_UNORM_S8_UINT)
+ requestedFeatures |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ if (requestedFeatures == 0)
+ return 0;
+
+ // Enable usage flags for all supported and requested features
+ VkFormatProperties properties = m_device->GetDXVKDevice()->adapter()->formatProperties(Format);
+
+ requestedFeatures &= Tiling == VK_IMAGE_TILING_OPTIMAL
+ ? properties.optimalTilingFeatures
+ : properties.linearTilingFeatures;
+
+ VkImageUsageFlags requestedUsage = 0;
+
+ if (requestedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
+ requestedUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+
+ if (requestedFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ requestedUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ if (requestedFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
+ requestedUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ return requestedUsage;
+ }
+
+
+ VkImageUsageFlags D3D11CommonTexture::EnableMetaPackUsage(
+ VkFormat Format,
+ UINT CpuAccess) const {
+ if ((CpuAccess & D3D11_CPU_ACCESS_READ) == 0)
+ return 0;
+
+ const auto dsMask = VK_IMAGE_ASPECT_DEPTH_BIT
+ | VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ auto formatInfo = imageFormatInfo(Format);
+
+ return formatInfo->aspectMask == dsMask
+ ? VK_IMAGE_USAGE_SAMPLED_BIT
+ : 0;
+ }
+
+
+ D3D11_COMMON_TEXTURE_MAP_MODE D3D11CommonTexture::DetermineMapMode(
+ const DxvkImageCreateInfo* pImageInfo) const {
+ // Don't map an image unless the application requests it
+ if (!m_desc.CPUAccessFlags)
+ return D3D11_COMMON_TEXTURE_MAP_MODE_NONE;
+
+ // If the resource cannot be used in the actual rendering pipeline, we
+ // do not need to create an actual image and can instead implement copy
+ // functions as buffer-to-image and image-to-buffer copies.
+ if (!m_desc.BindFlags && m_desc.Usage != D3D11_USAGE_DEFAULT)
+ return D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
+
+ // Write-only images should go through a buffer for multiple reasons:
+ // 1. Some games do not respect the row and depth pitch that is returned
+ // by the Map() method, which leads to incorrect rendering (e.g. Nier)
+ // 2. Since the image will most likely be read for rendering by the GPU,
+ // writing the image to device-local image may be more efficient than
+ // reading its contents from host memory.
+ if (m_desc.Usage == D3D11_USAGE_DYNAMIC
+ && m_desc.TextureLayout != D3D11_TEXTURE_LAYOUT_ROW_MAJOR)
+ return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
+
+ // Depth-stencil formats in D3D11 can be mapped and follow special
+ // packing rules, so we need to copy that data into a buffer first
+ if (GetPackedDepthStencilFormat(m_desc.Format))
+ return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
+
+ // Multi-plane images have a special memory layout in D3D11
+ if (imageFormatInfo(pImageInfo->format)->flags.test(DxvkFormatFlag::MultiPlane))
+ return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
+
+ // Images that can be read by the host should be mapped directly in
+ // order to avoid expensive synchronization with the GPU. This does
+ // however require linear tiling, which may not be supported for all
+ // combinations of image parameters.
+ return this->CheckImageSupport(pImageInfo, VK_IMAGE_TILING_LINEAR)
+ ? D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT
+ : D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER;
+ }
+
+
+ D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const {
+ const DxvkFormatInfo* formatInfo = imageFormatInfo(
+ m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format);
+
+ DxvkBufferCreateInfo info;
+ info.size = GetSubresourceLayout(formatInfo->aspectMask, MipLevel).Size;
+ info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+ | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
+ | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
+ | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
+ | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ info.access = VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_TRANSFER_WRITE_BIT
+ | VK_ACCESS_SHADER_READ_BIT
+ | VK_ACCESS_SHADER_WRITE_BIT;
+
+ VkMemoryPropertyFlags memType = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+ if (m_desc.Usage == D3D11_USAGE_STAGING)
+ memType |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+
+ MappedBuffer result;
+ result.buffer = m_device->GetDXVKDevice()->createBuffer(info, memType);
+ result.slice = result.buffer->getSliceHandle();
+ return result;
+ }
+
+
+ VkImageType D3D11CommonTexture::GetImageTypeFromResourceDim(D3D11_RESOURCE_DIMENSION Dimension) {
+ switch (Dimension) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: return VK_IMAGE_TYPE_1D;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: return VK_IMAGE_TYPE_2D;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: return VK_IMAGE_TYPE_3D;
+ default: throw DxvkError("D3D11CommonTexture: Unhandled resource dimension");
+ }
+ }
+
+
+ VkImageLayout D3D11CommonTexture::OptimizeLayout(VkImageUsageFlags Usage) {
+ const VkImageUsageFlags usageFlags = Usage;
+
+ // Filter out unnecessary flags. Transfer operations
+ // are handled by the backend in a transparent manner.
+ Usage &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT
+ | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+
+ // If the image is used only as an attachment, we never
+ // have to transform the image back to a different layout
+ if (Usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
+ return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ if (Usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ Usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+ | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+
+ // If the image is used for reading but not as a storage
+ // image, we can optimize the image for texture access
+ if (Usage == VK_IMAGE_USAGE_SAMPLED_BIT) {
+ return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
+ ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
+ : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ }
+
+ // Otherwise, we have to stick with the default layout
+ return VK_IMAGE_LAYOUT_GENERAL;
+ }
+
+
+
+
+ D3D11DXGISurface::D3D11DXGISurface(
+ ID3D11Resource* pResource,
+ D3D11CommonTexture* pTexture)
+ : m_resource (pResource),
+ m_texture (pTexture),
+ m_gdiSurface(nullptr) {
+#ifndef DXVK_NATIVE
+ if (pTexture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
+ m_gdiSurface = new D3D11GDISurface(m_resource, 0);
+#endif
+ }
+
+
+ D3D11DXGISurface::~D3D11DXGISurface() {
+#ifndef DXVK_NATIVE
+ if (m_gdiSurface)
+ delete m_gdiSurface;
+#endif
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DXGISurface::AddRef() {
+ return m_resource->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11DXGISurface::Release() {
+ return m_resource->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_resource->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData) {
+ return m_resource->GetPrivateData(Name, pDataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData) {
+ return m_resource->SetPrivateData(Name, DataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown) {
+ return m_resource->SetPrivateDataInterface(Name, pUnknown);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetParent(
+ REFIID riid,
+ void** ppParent) {
+ return GetDevice(riid, ppParent);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDevice(
+ REFIID riid,
+ void** ppDevice) {
+ Com<ID3D11Device> device;
+ m_resource->GetDevice(&device);
+ return device->QueryInterface(riid, ppDevice);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDesc(
+ DXGI_SURFACE_DESC* pDesc) {
+ if (!pDesc)
+ return DXGI_ERROR_INVALID_CALL;
+
+ auto desc = m_texture->Desc();
+ pDesc->Width = desc->Width;
+ pDesc->Height = desc->Height;
+ pDesc->Format = desc->Format;
+ pDesc->SampleDesc = desc->SampleDesc;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::Map(
+ DXGI_MAPPED_RECT* pLockedRect,
+ UINT MapFlags) {
+ Com<ID3D11Device> device;
+ Com<ID3D11DeviceContext> context;
+
+ m_resource->GetDevice(&device);
+ device->GetImmediateContext(&context);
+
+ if (pLockedRect) {
+ pLockedRect->Pitch = 0;
+ pLockedRect->pBits = nullptr;
+ }
+
+ D3D11_MAP mapType;
+
+ if (MapFlags & (DXGI_MAP_READ | DXGI_MAP_WRITE))
+ mapType = D3D11_MAP_READ_WRITE;
+ else if (MapFlags & DXGI_MAP_READ)
+ mapType = D3D11_MAP_READ;
+ else if (MapFlags & (DXGI_MAP_WRITE | DXGI_MAP_DISCARD))
+ mapType = D3D11_MAP_WRITE_DISCARD;
+ else if (MapFlags & DXGI_MAP_WRITE)
+ mapType = D3D11_MAP_WRITE;
+ else
+ return DXGI_ERROR_INVALID_CALL;
+
+ D3D11_MAPPED_SUBRESOURCE sr;
+ HRESULT hr = context->Map(m_resource, 0,
+ mapType, 0, pLockedRect ? &sr : nullptr);
+
+ if (hr != S_OK)
+ return hr;
+
+ pLockedRect->Pitch = sr.RowPitch;
+ pLockedRect->pBits = reinterpret_cast<unsigned char*>(sr.pData);
+ return hr;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::Unmap() {
+ Com<ID3D11Device> device;
+ Com<ID3D11DeviceContext> context;
+
+ m_resource->GetDevice(&device);
+ device->GetImmediateContext(&context);
+
+ context->Unmap(m_resource, 0);
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDC(
+ BOOL Discard,
+ HDC* phdc) {
+#ifndef DXVK_NATIVE
+ if (m_gdiSurface)
+ return m_gdiSurface->Acquire(Discard, phdc);
+#endif
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::ReleaseDC(
+ RECT* pDirtyRect) {
+#ifndef DXVK_NATIVE
+ if (m_gdiSurface)
+ return m_gdiSurface->Release(pDirtyRect);
+#endif
+
+ return DXGI_ERROR_INVALID_CALL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetResource(
+ REFIID riid,
+ void** ppParentResource,
+ UINT* pSubresourceIndex) {
+ HRESULT hr = m_resource->QueryInterface(riid, ppParentResource);
+ if (pSubresourceIndex)
+ *pSubresourceIndex = 0;
+ return hr;
+ }
+
+
+ bool D3D11DXGISurface::isSurfaceCompatible() const {
+ auto desc = m_texture->Desc();
+
+ return desc->ArraySize == 1
+ && desc->MipLevels == 1;
+ }
+
+
+
+
+ D3D11VkInteropSurface::D3D11VkInteropSurface(
+ ID3D11Resource* pResource,
+ D3D11CommonTexture* pTexture)
+ : m_resource(pResource),
+ m_texture (pTexture) {
+
+ }
+
+
+ D3D11VkInteropSurface::~D3D11VkInteropSurface() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::AddRef() {
+ return m_resource->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::Release() {
+ return m_resource->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_resource->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::GetDevice(
+ IDXGIVkInteropDevice** ppDevice) {
+ Com<ID3D11Device> device;
+ m_resource->GetDevice(&device);
+
+ return device->QueryInterface(
+ __uuidof(IDXGIVkInteropDevice),
+ reinterpret_cast<void**>(ppDevice));
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::GetVulkanImageInfo(
+ VkImage* pHandle,
+ VkImageLayout* pLayout,
+ VkImageCreateInfo* pInfo) {
+ const Rc<DxvkImage> image = m_texture->GetImage();
+ const DxvkImageCreateInfo& info = image->info();
+
+ if (pHandle != nullptr)
+ *pHandle = image->handle();
+
+ if (pLayout != nullptr)
+ *pLayout = info.layout;
+
+ if (pInfo != nullptr) {
+ // We currently don't support any extended structures
+ if (pInfo->sType != VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
+ || pInfo->pNext != nullptr)
+ return E_INVALIDARG;
+
+ pInfo->flags = 0;
+ pInfo->imageType = info.type;
+ pInfo->format = info.format;
+ pInfo->extent = info.extent;
+ pInfo->mipLevels = info.mipLevels;
+ pInfo->arrayLayers = info.numLayers;
+ pInfo->samples = info.sampleCount;
+ pInfo->tiling = info.tiling;
+ pInfo->usage = info.usage;
+ pInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ pInfo->queueFamilyIndexCount = 0;
+ pInfo->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ }
+
+ return S_OK;
+ }
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 1 D
+ D3D11Texture1D::D3D11Texture1D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc)
+ : D3D11DeviceChild<ID3D11Texture1D>(pDevice),
+ m_texture (pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE),
+ m_interop (this, &m_texture),
+ m_surface (this, &m_texture),
+ m_resource(this),
+ m_d3d10 (this) {
+
+ }
+
+
+ D3D11Texture1D::~D3D11Texture1D() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Texture1D::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11Resource)
+ || riid == __uuidof(ID3D11Texture1D)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10Resource)
+ || riid == __uuidof(ID3D10Texture1D)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ if (m_surface.isSurfaceCompatible()
+ && (riid == __uuidof(IDXGISurface)
+ || riid == __uuidof(IDXGISurface1)
+ || riid == __uuidof(IDXGISurface2))) {
+ *ppvObject = ref(&m_surface);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIObject)
+ || riid == __uuidof(IDXGIDeviceSubObject)
+ || riid == __uuidof(IDXGIResource)
+ || riid == __uuidof(IDXGIResource1)) {
+ *ppvObject = ref(&m_resource);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIVkInteropSurface)) {
+ *ppvObject = ref(&m_interop);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11Texture1D::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture1D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) {
+ *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Texture1D::GetEvictionPriority() {
+ return DXGI_RESOURCE_PRIORITY_NORMAL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture1D::SetEvictionPriority(UINT EvictionPriority) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11Texture1D::SetEvictionPriority: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture1D::GetDesc(D3D11_TEXTURE1D_DESC *pDesc) {
+ pDesc->Width = m_texture.Desc()->Width;
+ pDesc->MipLevels = m_texture.Desc()->MipLevels;
+ pDesc->ArraySize = m_texture.Desc()->ArraySize;
+ pDesc->Format = m_texture.Desc()->Format;
+ pDesc->Usage = m_texture.Desc()->Usage;
+ pDesc->BindFlags = m_texture.Desc()->BindFlags;
+ pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
+ }
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 2 D
+ D3D11Texture2D::D3D11Texture2D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc)
+ : D3D11DeviceChild<ID3D11Texture2D1>(pDevice),
+ m_texture (pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE),
+ m_interop (this, &m_texture),
+ m_surface (this, &m_texture),
+ m_resource(this),
+ m_d3d10 (this) {
+
+ }
+
+
+ D3D11Texture2D::D3D11Texture2D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc,
+ DXGI_USAGE DxgiUsage,
+ VkImage vkImage)
+ : D3D11DeviceChild<ID3D11Texture2D1>(pDevice),
+ m_texture (pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage),
+ m_interop (this, &m_texture),
+ m_surface (this, &m_texture),
+ m_resource(this),
+ m_d3d10 (this) {
+
+ }
+
+
+ D3D11Texture2D::~D3D11Texture2D() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Texture2D::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11Resource)
+ || riid == __uuidof(ID3D11Texture2D)
+ || riid == __uuidof(ID3D11Texture2D1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10Resource)
+ || riid == __uuidof(ID3D10Texture2D)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ if (m_surface.isSurfaceCompatible()
+ && (riid == __uuidof(IDXGISurface)
+ || riid == __uuidof(IDXGISurface1)
+ || riid == __uuidof(IDXGISurface2))) {
+ *ppvObject = ref(&m_surface);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIObject)
+ || riid == __uuidof(IDXGIDeviceSubObject)
+ || riid == __uuidof(IDXGIResource)
+ || riid == __uuidof(IDXGIResource1)) {
+ *ppvObject = ref(&m_resource);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIVkInteropSurface)) {
+ *ppvObject = ref(&m_interop);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture2D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) {
+ *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Texture2D::GetEvictionPriority() {
+ return DXGI_RESOURCE_PRIORITY_NORMAL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture2D::SetEvictionPriority(UINT EvictionPriority) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11Texture2D::SetEvictionPriority: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture2D::GetDesc(D3D11_TEXTURE2D_DESC* pDesc) {
+ pDesc->Width = m_texture.Desc()->Width;
+ pDesc->Height = m_texture.Desc()->Height;
+ pDesc->MipLevels = m_texture.Desc()->MipLevels;
+ pDesc->ArraySize = m_texture.Desc()->ArraySize;
+ pDesc->Format = m_texture.Desc()->Format;
+ pDesc->SampleDesc = m_texture.Desc()->SampleDesc;
+ pDesc->Usage = m_texture.Desc()->Usage;
+ pDesc->BindFlags = m_texture.Desc()->BindFlags;
+ pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture2D::GetDesc1(D3D11_TEXTURE2D_DESC1* pDesc) {
+ pDesc->Width = m_texture.Desc()->Width;
+ pDesc->Height = m_texture.Desc()->Height;
+ pDesc->MipLevels = m_texture.Desc()->MipLevels;
+ pDesc->ArraySize = m_texture.Desc()->ArraySize;
+ pDesc->Format = m_texture.Desc()->Format;
+ pDesc->SampleDesc = m_texture.Desc()->SampleDesc;
+ pDesc->Usage = m_texture.Desc()->Usage;
+ pDesc->BindFlags = m_texture.Desc()->BindFlags;
+ pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
+ pDesc->TextureLayout = m_texture.Desc()->TextureLayout;
+ }
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 3 D
+ D3D11Texture3D::D3D11Texture3D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc)
+ : D3D11DeviceChild<ID3D11Texture3D1>(pDevice),
+ m_texture (pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE),
+ m_interop (this, &m_texture),
+ m_resource(this),
+ m_d3d10 (this) {
+
+ }
+
+
+ D3D11Texture3D::~D3D11Texture3D() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11Texture3D::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11Resource)
+ || riid == __uuidof(ID3D11Texture3D)
+ || riid == __uuidof(ID3D11Texture3D1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10Resource)
+ || riid == __uuidof(ID3D10Texture3D)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIObject)
+ || riid == __uuidof(IDXGIDeviceSubObject)
+ || riid == __uuidof(IDXGIResource)
+ || riid == __uuidof(IDXGIResource1)) {
+ *ppvObject = ref(&m_resource);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(IDXGIVkInteropSurface)) {
+ *ppvObject = ref(&m_interop);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11Texture3D::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture3D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) {
+ *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
+ }
+
+
+ UINT STDMETHODCALLTYPE D3D11Texture3D::GetEvictionPriority() {
+ return DXGI_RESOURCE_PRIORITY_NORMAL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture3D::SetEvictionPriority(UINT EvictionPriority) {
+ static bool s_errorShown = false;
+
+ if (!std::exchange(s_errorShown, true))
+ Logger::warn("D3D11Texture3D::SetEvictionPriority: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture3D::GetDesc(D3D11_TEXTURE3D_DESC* pDesc) {
+ pDesc->Width = m_texture.Desc()->Width;
+ pDesc->Height = m_texture.Desc()->Height;
+ pDesc->Depth = m_texture.Desc()->Depth;
+ pDesc->MipLevels = m_texture.Desc()->MipLevels;
+ pDesc->Format = m_texture.Desc()->Format;
+ pDesc->Usage = m_texture.Desc()->Usage;
+ pDesc->BindFlags = m_texture.Desc()->BindFlags;
+ pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11Texture3D::GetDesc1(D3D11_TEXTURE3D_DESC1* pDesc) {
+ pDesc->Width = m_texture.Desc()->Width;
+ pDesc->Height = m_texture.Desc()->Height;
+ pDesc->Depth = m_texture.Desc()->Depth;
+ pDesc->MipLevels = m_texture.Desc()->MipLevels;
+ pDesc->Format = m_texture.Desc()->Format;
+ pDesc->Usage = m_texture.Desc()->Usage;
+ pDesc->BindFlags = m_texture.Desc()->BindFlags;
+ pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags;
+ pDesc->MiscFlags = m_texture.Desc()->MiscFlags;
+ }
+
+
+ D3D11CommonTexture* GetCommonTexture(ID3D11Resource* pResource) {
+ D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&dimension);
+
+ switch (dimension) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ return static_cast<D3D11Texture1D*>(pResource)->GetCommonTexture();
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ return static_cast<D3D11Texture2D*>(pResource)->GetCommonTexture();
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ return static_cast<D3D11Texture3D*>(pResource)->GetCommonTexture();
+
+ default:
+ return nullptr;
+ }
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.h
new file mode 100644
index 00000000..80901a85
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_texture.h
@@ -0,0 +1,628 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_texture.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_interfaces.h"
+#include "d3d11_resource.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+ class D3D11GDISurface;
+
+ /**
+ * \brief Image memory mapping mode
+ *
+ * Determines how exactly \c Map will
+ * behave when mapping an image.
+ */
+ enum D3D11_COMMON_TEXTURE_MAP_MODE {
+ D3D11_COMMON_TEXTURE_MAP_MODE_NONE, ///< Not mapped
+ D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, ///< Mapped through buffer
+ D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, ///< Directly mapped to host mem
+ D3D11_COMMON_TEXTURE_MAP_MODE_STAGING, ///< Buffer only, no image
+ };
+
+
+ /**
+ * \brief Common texture description
+ *
+ * Contains all members that can be
+ * defined for 1D, 2D and 3D textures.
+ */
+ struct D3D11_COMMON_TEXTURE_DESC {
+ UINT Width;
+ UINT Height;
+ UINT Depth;
+ UINT MipLevels;
+ UINT ArraySize;
+ DXGI_FORMAT Format;
+ DXGI_SAMPLE_DESC SampleDesc;
+ D3D11_USAGE Usage;
+ UINT BindFlags;
+ UINT CPUAccessFlags;
+ UINT MiscFlags;
+ D3D11_TEXTURE_LAYOUT TextureLayout;
+ };
+
+
+ /**
+ * \brief Packed subresource layout
+ */
+ struct D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT {
+ UINT64 Offset;
+ UINT64 Size;
+ UINT RowPitch;
+ UINT DepthPitch;
+ };
+
+
+ /**
+ * \brief D3D11 common texture object
+ *
+ * This class implements common texture methods and
+ * aims to work around the issue that there are three
+ * different interfaces for basically the same thing.
+ */
+ class D3D11CommonTexture {
+
+ public:
+
+ D3D11CommonTexture(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc,
+ D3D11_RESOURCE_DIMENSION Dimension,
+ DXGI_USAGE DxgiUsage,
+ VkImage vkImage);
+
+ ~D3D11CommonTexture();
+
+ /**
+ * \brief Texture properties
+ *
+ * The returned data can be used to fill in
+ * \c D3D11_TEXTURE2D_DESC and similar structs.
+ * \returns Pointer to texture description
+ */
+ const D3D11_COMMON_TEXTURE_DESC* Desc() const {
+ return &m_desc;
+ }
+
+ /**
+ * \brief Retrieves Vulkan image type
+ *
+ * Returns the image type based on the D3D11 resource
+ * dimension. Also works if there is no actual image.
+ * \returns Vulkan image type
+ */
+ VkImageType GetVkImageType() const {
+ return GetImageTypeFromResourceDim(m_dimension);
+ }
+
+ /**
+ * \brief Computes extent of a given mip level
+ *
+ * This also works for staging resources that have no image.
+ * \param [in] Level Mip level to compute the size of
+ */
+ VkExtent3D MipLevelExtent(uint32_t Level) const {
+ return util::computeMipLevelExtent(
+ VkExtent3D { m_desc.Width, m_desc.Height, m_desc.Depth }, Level);
+ }
+
+ /**
+ * \brief Special DXGI usage flags
+ *
+ * Flags that are set in addition to the bind
+ * flags. Zero for application-created textures.
+ * \returns DXGI usage flags
+ */
+ DXGI_USAGE GetDxgiUsage() const {
+ return m_dxgiUsage;
+ }
+
+ /**
+ * \brief Counts number of subresources
+ * \returns Number of subresources
+ */
+ UINT CountSubresources() const {
+ return m_desc.ArraySize * m_desc.MipLevels;
+ }
+
+ /**
+ * \brief Map mode
+ * \returns Map mode
+ */
+ D3D11_COMMON_TEXTURE_MAP_MODE GetMapMode() const {
+ return m_mapMode;
+ }
+
+ /**
+ * \brief Map type of a given subresource
+ *
+ * \param [in] Subresource Subresource index
+ * \returns Current map mode of that subresource
+ */
+ D3D11_MAP GetMapType(UINT Subresource) const {
+ return Subresource < m_mapTypes.size()
+ ? D3D11_MAP(m_mapTypes[Subresource])
+ : D3D11_MAP(~0u);
+ }
+
+ /**
+ * \brief Sets map type for a given subresource
+ *
+ * \param [in] Subresource The subresource
+ * \param [in] MapType The map type
+ */
+ void SetMapType(UINT Subresource, D3D11_MAP MapType) {
+ if (Subresource < m_mapTypes.size())
+ m_mapTypes[Subresource] = MapType;
+ }
+
+ /**
+ * \brief The DXVK image
+ * \returns The DXVK image
+ */
+ Rc<DxvkImage> GetImage() const {
+ return m_image;
+ }
+
+ /**
+ * \brief Mapped subresource buffer
+ *
+ * \param [in] Subresource Subresource index
+ * \returns Mapped subresource buffer
+ */
+ Rc<DxvkBuffer> GetMappedBuffer(UINT Subresource) const {
+ return Subresource < m_buffers.size()
+ ? m_buffers[Subresource].buffer
+ : Rc<DxvkBuffer>();
+ }
+
+ /**
+ * \brief Discards mapped buffer slice for a given subresource
+ *
+ * \param [in] Subresource Subresource to discard
+ * \returns Newly allocated mapped buffer slice
+ */
+ DxvkBufferSliceHandle DiscardSlice(UINT Subresource) {
+ if (Subresource < m_buffers.size()) {
+ DxvkBufferSliceHandle slice = m_buffers[Subresource].buffer->allocSlice();
+ m_buffers[Subresource].slice = slice;
+ return slice;
+ } else {
+ return DxvkBufferSliceHandle();
+ }
+ }
+
+ /**
+ * \brief Retrieves mapped buffer slice for a given subresource
+ *
+ * \param [in] Subresource Subresource index to query
+ * \returns Currently mapped buffer slice
+ */
+ DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) const {
+ return Subresource < m_buffers.size()
+ ? m_buffers[Subresource].slice
+ : DxvkBufferSliceHandle();
+ }
+
+ /**
+ * \brief Returns underlying packed Vulkan format
+ *
+ * This works even for staging resources that have no image.
+ * Note that for depth-stencil resources, the returned format
+ * may be different from the image format on some systems.
+ * \returns Packed Vulkan format
+ */
+ VkFormat GetPackedFormat() const {
+ return m_packedFormat;
+ }
+
+ /**
+ * \brief Computes pixel offset into mapped buffer
+ *
+ * \param [in] Subresource Subresource index
+ * \param [in] Subresource Plane index
+ * \param [in] Offset Pixel coordinate to compute offset for
+ * \returns Offset into mapped subresource buffer, in pixels
+ */
+ VkDeviceSize ComputeMappedOffset(UINT Subresource, UINT Plane, VkOffset3D Offset) const;
+
+ /**
+ * \brief Computes subresource from the subresource index
+ *
+ * Used by some functions that operate on only
+ * one subresource, such as \c UpdateSubresource.
+ * \param [in] Aspect The image aspect
+ * \param [in] Subresource Subresource index
+ * \returns The Vulkan image subresource
+ */
+ VkImageSubresource GetSubresourceFromIndex(
+ VkImageAspectFlags Aspect,
+ UINT Subresource) const;
+
+ /**
+ * \brief Computes subresource layout for the given subresource
+ *
+ * \param [in] AspectMask The image aspect
+ * \param [in] Subresource Subresource index
+ * \returns Memory layout of the mapped subresource
+ */
+ D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT GetSubresourceLayout(
+ VkImageAspectFlags AspectMask,
+ UINT Subresource) const;
+
+ /**
+ * \brief Format mode
+ *
+ * Determines whether the image is going to
+ * be used as a color image or a depth image.
+ * \returns Format mode
+ */
+ DXGI_VK_FORMAT_MODE GetFormatMode() const;
+
+ /**
+ * \brief Computes plane count
+ *
+ * For non-planar formats, the plane count will be 1.
+ * \returns Image plane count
+ */
+ uint32_t GetPlaneCount() const;
+
+ /**
+ * \brief Checks whether a view can be created for this textue
+ *
+ * View formats are only compatible if they are either identical
+ * or from the same family of typeless formats, where the resource
+ * format must be typeless and the view format must be typed. This
+ * will also check whether the required bind flags are supported.
+ * \param [in] BindFlags Bind flags for the view
+ * \param [in] Format The desired view format
+ * \param [in] Plane Plane slice for planar formats
+ * \returns \c true if the format is compatible
+ */
+ bool CheckViewCompatibility(
+ UINT BindFlags,
+ DXGI_FORMAT Format,
+ UINT Plane) const;
+
+ /**
+ * \brief Normalizes and validates texture description
+ *
+ * Fills in undefined values and validates the texture
+ * parameters. Any error returned by this method should
+ * be forwarded to the application.
+ * \param [in,out] pDesc Texture description
+ * \returns \c S_OK if the parameters are valid
+ */
+ static HRESULT NormalizeTextureProperties(
+ D3D11_COMMON_TEXTURE_DESC* pDesc);
+
+ private:
+
+ struct MappedBuffer {
+ Rc<DxvkBuffer> buffer;
+ DxvkBufferSliceHandle slice;
+ };
+
+ D3D11Device* const m_device;
+ D3D11_RESOURCE_DIMENSION m_dimension;
+ D3D11_COMMON_TEXTURE_DESC m_desc;
+ D3D11_COMMON_TEXTURE_MAP_MODE m_mapMode;
+ DXGI_USAGE m_dxgiUsage;
+ VkFormat m_packedFormat;
+
+ Rc<DxvkImage> m_image;
+ std::vector<MappedBuffer> m_buffers;
+ std::vector<D3D11_MAP> m_mapTypes;
+
+ MappedBuffer CreateMappedBuffer(
+ UINT MipLevel) const;
+
+ BOOL CheckImageSupport(
+ const DxvkImageCreateInfo* pImageInfo,
+ VkImageTiling Tiling) const;
+
+ BOOL CheckFormatFeatureSupport(
+ VkFormat Format,
+ VkFormatFeatureFlags Features) const;
+
+ VkImageUsageFlags EnableMetaCopyUsage(
+ VkFormat Format,
+ VkImageTiling Tiling) const;
+
+ VkImageUsageFlags EnableMetaPackUsage(
+ VkFormat Format,
+ UINT CpuAccess) const;
+
+ D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode(
+ const DxvkImageCreateInfo* pImageInfo) const;
+
+ static VkImageType GetImageTypeFromResourceDim(
+ D3D11_RESOURCE_DIMENSION Dimension);
+
+ static VkImageLayout OptimizeLayout(
+ VkImageUsageFlags Usage);
+
+ };
+
+
+ /**
+ * \brief IDXGISurface implementation for D3D11 textures
+ *
+ * Provides an implementation for 2D textures that
+ * have only one array layer and one mip level.
+ */
+ class D3D11DXGISurface : public IDXGISurface2 {
+
+ public:
+
+ D3D11DXGISurface(
+ ID3D11Resource* pResource,
+ D3D11CommonTexture* pTexture);
+
+ ~D3D11DXGISurface();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown);
+
+ HRESULT STDMETHODCALLTYPE GetParent(
+ REFIID riid,
+ void** ppParent);
+
+ HRESULT STDMETHODCALLTYPE GetDevice(
+ REFIID riid,
+ void** ppDevice);
+
+ HRESULT STDMETHODCALLTYPE GetDesc(
+ DXGI_SURFACE_DESC* pDesc);
+
+ HRESULT STDMETHODCALLTYPE Map(
+ DXGI_MAPPED_RECT* pLockedRect,
+ UINT MapFlags);
+
+ HRESULT STDMETHODCALLTYPE Unmap();
+
+ HRESULT STDMETHODCALLTYPE GetDC(
+ BOOL Discard,
+ HDC* phdc);
+
+ HRESULT STDMETHODCALLTYPE ReleaseDC(
+ RECT* pDirtyRect);
+
+ HRESULT STDMETHODCALLTYPE GetResource(
+ REFIID riid,
+ void** ppParentResource,
+ UINT* pSubresourceIndex);
+
+ bool isSurfaceCompatible() const;
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11CommonTexture* m_texture;
+ D3D11GDISurface* m_gdiSurface;
+
+ };
+
+
+ /**
+ * \brief Common texture interop class
+ *
+ * Provides access to the underlying Vulkan
+ * texture to external Vulkan libraries.
+ */
+ class D3D11VkInteropSurface : public IDXGIVkInteropSurface {
+
+ public:
+
+ D3D11VkInteropSurface(
+ ID3D11Resource* pResource,
+ D3D11CommonTexture* pTexture);
+
+ ~D3D11VkInteropSurface();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetDevice(
+ IDXGIVkInteropDevice** ppDevice);
+
+ HRESULT STDMETHODCALLTYPE GetVulkanImageInfo(
+ VkImage* pHandle,
+ VkImageLayout* pLayout,
+ VkImageCreateInfo* pInfo);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11CommonTexture* m_texture;
+
+ };
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 1 D
+ class D3D11Texture1D : public D3D11DeviceChild<ID3D11Texture1D> {
+
+ public:
+
+ D3D11Texture1D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc);
+
+ ~D3D11Texture1D();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetType(
+ D3D11_RESOURCE_DIMENSION *pResourceDimension) final;
+
+ UINT STDMETHODCALLTYPE GetEvictionPriority() final;
+
+ void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_TEXTURE1D_DESC *pDesc) final;
+
+ D3D11CommonTexture* GetCommonTexture() {
+ return &m_texture;
+ }
+
+ D3D10Texture1D* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ private:
+
+ D3D11CommonTexture m_texture;
+ D3D11VkInteropSurface m_interop;
+ D3D11DXGISurface m_surface;
+ D3D11DXGIResource m_resource;
+ D3D10Texture1D m_d3d10;
+
+ };
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 2 D
+ class D3D11Texture2D : public D3D11DeviceChild<ID3D11Texture2D1> {
+
+ public:
+
+ D3D11Texture2D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc);
+
+ D3D11Texture2D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc,
+ DXGI_USAGE DxgiUsage,
+ VkImage vkImage);
+
+ ~D3D11Texture2D();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetType(
+ D3D11_RESOURCE_DIMENSION *pResourceDimension) final;
+
+ UINT STDMETHODCALLTYPE GetEvictionPriority() final;
+
+ void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_TEXTURE2D_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(
+ D3D11_TEXTURE2D_DESC1* pDesc) final;
+
+ D3D11CommonTexture* GetCommonTexture() {
+ return &m_texture;
+ }
+
+ D3D10Texture2D* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ private:
+
+ D3D11CommonTexture m_texture;
+ D3D11VkInteropSurface m_interop;
+ D3D11DXGISurface m_surface;
+ D3D11DXGIResource m_resource;
+ D3D10Texture2D m_d3d10;
+
+ };
+
+
+ ///////////////////////////////////////////
+ // D 3 D 1 1 T E X T U R E 3 D
+ class D3D11Texture3D : public D3D11DeviceChild<ID3D11Texture3D1> {
+
+ public:
+
+ D3D11Texture3D(
+ D3D11Device* pDevice,
+ const D3D11_COMMON_TEXTURE_DESC* pDesc);
+
+ ~D3D11Texture3D();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetType(
+ D3D11_RESOURCE_DIMENSION *pResourceDimension) final;
+
+ UINT STDMETHODCALLTYPE GetEvictionPriority() final;
+
+ void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final;
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_TEXTURE3D_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(
+ D3D11_TEXTURE3D_DESC1* pDesc) final;
+
+ D3D11CommonTexture* GetCommonTexture() {
+ return &m_texture;
+ }
+
+ D3D10Texture3D* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ private:
+
+ D3D11CommonTexture m_texture;
+ D3D11VkInteropSurface m_interop;
+ D3D11DXGIResource m_resource;
+ D3D10Texture3D m_d3d10;
+
+ };
+
+
+ /**
+ * \brief Retrieves texture from resource pointer
+ *
+ * \param [in] pResource The resource to query
+ * \returns Pointer to texture info, or \c nullptr
+ */
+ D3D11CommonTexture* GetCommonTexture(
+ ID3D11Resource* pResource);
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.cpp
new file mode 100644
index 00000000..d4448c54
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.cpp
@@ -0,0 +1,141 @@
+#include "d3d11_util.h"
+
+namespace dxvk {
+
+ HRESULT DecodeSampleCount(UINT Count, VkSampleCountFlagBits* pCount) {
+ VkSampleCountFlagBits flag;
+
+ switch (Count) {
+ case 1: flag = VK_SAMPLE_COUNT_1_BIT; break;
+ case 2: flag = VK_SAMPLE_COUNT_2_BIT; break;
+ case 4: flag = VK_SAMPLE_COUNT_4_BIT; break;
+ case 8: flag = VK_SAMPLE_COUNT_8_BIT; break;
+ case 16: flag = VK_SAMPLE_COUNT_16_BIT; break;
+ default: return E_INVALIDARG;
+ }
+
+ if (pCount != nullptr) {
+ *pCount = flag;
+ return S_OK;
+ } return S_FALSE;
+ }
+
+
+ VkSamplerAddressMode DecodeAddressMode(
+ D3D11_TEXTURE_ADDRESS_MODE mode) {
+ switch (mode) {
+ case D3D11_TEXTURE_ADDRESS_WRAP:
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+
+ case D3D11_TEXTURE_ADDRESS_MIRROR:
+ return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+
+ case D3D11_TEXTURE_ADDRESS_CLAMP:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+
+ case D3D11_TEXTURE_ADDRESS_BORDER:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+
+ case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE:
+ return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
+
+ default:
+ Logger::err(str::format("D3D11: Unsupported address mode: ", mode));
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ }
+ }
+
+
+ VkCompareOp DecodeCompareOp(D3D11_COMPARISON_FUNC Mode) {
+ switch (Mode) {
+ case D3D11_COMPARISON_NEVER: return VK_COMPARE_OP_NEVER;
+ case D3D11_COMPARISON_LESS: return VK_COMPARE_OP_LESS;
+ case D3D11_COMPARISON_EQUAL: return VK_COMPARE_OP_EQUAL;
+ case D3D11_COMPARISON_LESS_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
+ case D3D11_COMPARISON_GREATER: return VK_COMPARE_OP_GREATER;
+ case D3D11_COMPARISON_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL;
+ case D3D11_COMPARISON_GREATER_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case D3D11_COMPARISON_ALWAYS: return VK_COMPARE_OP_ALWAYS;
+ }
+
+ if (Mode != 0) // prevent log spamming when apps use ZeroMemory
+ Logger::err(str::format("D3D11: Unsupported compare op: ", Mode));
+ return VK_COMPARE_OP_NEVER;
+ }
+
+
+ VkConservativeRasterizationModeEXT DecodeConservativeRasterizationMode(
+ D3D11_CONSERVATIVE_RASTERIZATION_MODE Mode) {
+ switch (Mode) {
+ case D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF:
+ return VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
+ case D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON:
+ return VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
+ }
+
+ Logger::err(str::format("D3D11: Unsupported conservative raster mode: ", Mode));
+ return VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
+ }
+
+
+ VkShaderStageFlagBits GetShaderStage(DxbcProgramType ProgramType) {
+ switch (ProgramType) {
+ case DxbcProgramType::VertexShader: return VK_SHADER_STAGE_VERTEX_BIT;
+ case DxbcProgramType::HullShader: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case DxbcProgramType::DomainShader: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ case DxbcProgramType::GeometryShader: return VK_SHADER_STAGE_GEOMETRY_BIT;
+ case DxbcProgramType::PixelShader: return VK_SHADER_STAGE_FRAGMENT_BIT;
+ case DxbcProgramType::ComputeShader: return VK_SHADER_STAGE_COMPUTE_BIT;
+ default: return VkShaderStageFlagBits(0);
+ }
+ }
+
+
+ VkFormatFeatureFlags GetBufferFormatFeatures(UINT BindFlags) {
+ VkFormatFeatureFlags features = 0;
+
+ if (BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ features |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
+ if (BindFlags & D3D11_BIND_UNORDERED_ACCESS)
+ features |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
+
+ return features;
+ }
+
+
+ VkFormatFeatureFlags GetImageFormatFeatures(UINT BindFlags) {
+ VkFormatFeatureFlags features = 0;
+
+ if (BindFlags & D3D11_BIND_DEPTH_STENCIL)
+ features |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ if (BindFlags & D3D11_BIND_RENDER_TARGET)
+ features |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ if (BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
+ if (BindFlags & D3D11_BIND_UNORDERED_ACCESS)
+ features |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+
+ return features;
+ }
+
+
+ VkFormat GetPackedDepthStencilFormat(DXGI_FORMAT Format) {
+ switch (Format) {
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return VK_FORMAT_D24_UNORM_S8_UINT;
+
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return VK_FORMAT_D32_SFLOAT_S8_UINT;
+
+ default:
+ return VK_FORMAT_UNDEFINED;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.h
new file mode 100644
index 00000000..749dc8be
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_util.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../dxbc/dxbc_util.h"
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ template<typename T>
+ UINT CompactSparseList(T* pData, UINT Mask) {
+ uint32_t count = 0;
+
+ for (uint32_t id : bit::BitMask(Mask))
+ pData[count++] = pData[id];
+
+ return count;
+ }
+
+ HRESULT DecodeSampleCount(
+ UINT Count,
+ VkSampleCountFlagBits* pCount);
+
+ VkSamplerAddressMode DecodeAddressMode(
+ D3D11_TEXTURE_ADDRESS_MODE mode);
+
+ VkCompareOp DecodeCompareOp(
+ D3D11_COMPARISON_FUNC Mode);
+
+ VkConservativeRasterizationModeEXT DecodeConservativeRasterizationMode(
+ D3D11_CONSERVATIVE_RASTERIZATION_MODE Mode);
+
+ VkShaderStageFlagBits GetShaderStage(
+ DxbcProgramType ProgramType);
+
+ VkFormatFeatureFlags GetBufferFormatFeatures(
+ UINT BindFlags);
+
+ VkFormatFeatureFlags GetImageFormatFeatures(
+ UINT BindFlags);
+
+ VkFormat GetPackedDepthStencilFormat(
+ DXGI_FORMAT Format);
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.cpp
new file mode 100644
index 00000000..db534659
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.cpp
@@ -0,0 +1,1303 @@
+#include <algorithm>
+
+#include "d3d11_context.h"
+#include "d3d11_context_imm.h"
+#include "d3d11_video.h"
+
+#include <d3d11_video_blit_frag.h>
+#include <d3d11_video_blit_vert.h>
+
+namespace dxvk {
+
+ D3D11VideoProcessorEnumerator::D3D11VideoProcessorEnumerator(
+ D3D11Device* pDevice,
+ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC& Desc)
+ : D3D11DeviceChild<ID3D11VideoProcessorEnumerator>(pDevice),
+ m_desc(Desc) {
+
+ }
+
+
+ D3D11VideoProcessorEnumerator::~D3D11VideoProcessorEnumerator() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11VideoProcessorEnumerator)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11VideoProcessorEnumerator::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorContentDesc(
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pContentDesc) {
+ *pContentDesc = m_desc;
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat(
+ DXGI_FORMAT Format,
+ UINT* pFlags) {
+ Logger::err("D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCaps(
+ D3D11_VIDEO_PROCESSOR_CAPS* pCaps) {
+ Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCaps: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps(
+ UINT TypeIndex,
+ D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps) {
+ Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate(
+ UINT TypeIndex,
+ UINT CustomRateIndex,
+ D3D11_VIDEO_PROCESSOR_CUSTOM_RATE* pRate) {
+ Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange(
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ D3D11_VIDEO_PROCESSOR_FILTER_RANGE* pRange) {
+ Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange: Stub");
+ return E_NOTIMPL;
+ }
+
+
+
+
+ D3D11VideoProcessor::D3D11VideoProcessor(
+ D3D11Device* pDevice,
+ D3D11VideoProcessorEnumerator* pEnumerator,
+ UINT RateConversionIndex)
+ : D3D11DeviceChild<ID3D11VideoProcessor>(pDevice),
+ m_enumerator(pEnumerator), m_rateConversionIndex(RateConversionIndex) {
+
+ }
+
+
+ D3D11VideoProcessor::~D3D11VideoProcessor() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessor::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11VideoProcessor)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11VideoProcessor::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessor::GetContentDesc(
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC *pDesc) {
+ m_enumerator->GetVideoProcessorContentDesc(pDesc);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessor::GetRateConversionCaps(
+ D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps) {
+ m_enumerator->GetVideoProcessorRateConversionCaps(m_rateConversionIndex, pCaps);
+ }
+
+
+
+
+ D3D11VideoProcessorInputView::D3D11VideoProcessorInputView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC& Desc)
+ : D3D11DeviceChild<ID3D11VideoProcessorInputView>(pDevice),
+ m_resource(pResource), m_desc(Desc) {
+ D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
+
+ if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
+ DxvkImageCreateInfo info = dxvkImage->info();
+ info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
+ info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ info.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
+ info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ info.shared = VK_FALSE;
+ dxvkImage = m_copy = pDevice->GetDXVKDevice()->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ }
+
+ DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
+ DXGI_VK_FORMAT_FAMILY formatFamily = pDevice->LookupFamily(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
+
+ VkImageAspectFlags aspectMask = imageFormatInfo(formatInfo.Format)->aspectMask;
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = formatInfo.Format;
+ viewInfo.swizzle = formatInfo.Swizzle;
+ viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
+
+ switch (m_desc.ViewDimension) {
+ case D3D11_VPIV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = m_desc.Texture2D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ throw DxvkError("Invalid view dimension");
+ }
+
+ m_subresources.aspectMask = aspectMask;
+ m_subresources.baseArrayLayer = viewInfo.minLayer;
+ m_subresources.layerCount = viewInfo.numLayers;
+ m_subresources.mipLevel = viewInfo.minLevel;
+
+ for (uint32_t i = 0; aspectMask && i < m_views.size(); i++) {
+ viewInfo.aspect = vk::getNextAspect(aspectMask);
+
+ if (viewInfo.aspect != VK_IMAGE_ASPECT_COLOR_BIT)
+ viewInfo.format = formatFamily.Formats[i];
+
+ m_views[i] = pDevice->GetDXVKDevice()->createImageView(dxvkImage, viewInfo);
+ }
+
+ m_isYCbCr = IsYCbCrFormat(resourceDesc.Format);
+ }
+
+
+ D3D11VideoProcessorInputView::~D3D11VideoProcessorInputView() {
+
+ }
+
+
+ bool D3D11VideoProcessorInputView::IsYCbCrFormat(DXGI_FORMAT Format) {
+ static const std::array<DXGI_FORMAT, 3> s_formats = {{
+ DXGI_FORMAT_NV12,
+ DXGI_FORMAT_YUY2,
+ DXGI_FORMAT_AYUV,
+ }};
+
+ return std::find(s_formats.begin(), s_formats.end(), Format) != s_formats.end();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorInputView::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11VideoProcessorInputView)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11VideoProcessorInputView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetResource(
+ ID3D11Resource** ppResource) {
+ *ppResource = m_resource.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetDesc(
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+
+ D3D11VideoProcessorOutputView::D3D11VideoProcessorOutputView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC& Desc)
+ : D3D11DeviceChild<ID3D11VideoProcessorOutputView>(pDevice),
+ m_resource(pResource), m_desc(Desc) {
+ D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(
+ resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR);
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = formatInfo.Format;
+ viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
+ viewInfo.swizzle = formatInfo.Swizzle;
+ viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ switch (m_desc.ViewDimension) {
+ case D3D11_VPOV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = m_desc.Texture2D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_VPOV_DIMENSION_TEXTURE2DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = m_desc.Texture2DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = m_desc.Texture2DArray.FirstArraySlice;
+ viewInfo.numLayers = m_desc.Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ throw DxvkError("Invalid view dimension");
+ }
+
+ m_view = pDevice->GetDXVKDevice()->createImageView(
+ GetCommonTexture(pResource)->GetImage(), viewInfo);
+ }
+
+
+ D3D11VideoProcessorOutputView::~D3D11VideoProcessorOutputView() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoProcessorOutputView::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11VideoProcessorOutputView)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11VideoProcessorOutputView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetResource(
+ ID3D11Resource** ppResource) {
+ *ppResource = m_resource.ref();
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetDesc(
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+
+ D3D11VideoContext::D3D11VideoContext(
+ D3D11ImmediateContext* pContext,
+ const Rc<DxvkDevice>& Device)
+ : m_ctx(pContext) {
+ const SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
+ const SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
+
+ const std::array<DxvkResourceSlot, 4> fsResourceSlots = {{
+ { 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC },
+ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
+ { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
+ { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
+ }};
+
+ m_vs = Device->createShader(
+ VK_SHADER_STAGE_VERTEX_BIT,
+ 0, nullptr, { 0u, 1u },
+ vsCode);
+
+ m_fs = Device->createShader(
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fsResourceSlots.size(),
+ fsResourceSlots.data(),
+ { 1u, 1u, 0u, 0u },
+ fsCode);
+
+ DxvkSamplerCreateInfo samplerInfo;
+ samplerInfo.magFilter = VK_FILTER_LINEAR;
+ samplerInfo.minFilter = VK_FILTER_LINEAR;
+ samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ samplerInfo.mipmapLodBias = 0.0f;
+ samplerInfo.mipmapLodMin = 0.0f;
+ samplerInfo.mipmapLodMax = 0.0f;
+ samplerInfo.useAnisotropy = VK_FALSE;
+ samplerInfo.maxAnisotropy = 1.0f;
+ samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.compareToDepth = VK_FALSE;
+ samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
+ samplerInfo.borderColor = VkClearColorValue();
+ samplerInfo.usePixelCoord = VK_FALSE;
+ m_sampler = Device->createSampler(samplerInfo);
+
+ DxvkBufferCreateInfo bufferInfo;
+ bufferInfo.size = sizeof(UboData);
+ bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ bufferInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT;
+ m_ubo = Device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ }
+
+
+ D3D11VideoContext::~D3D11VideoContext() {
+
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VideoContext::AddRef() {
+ return m_ctx->AddRef();
+ }
+
+
+ ULONG STDMETHODCALLTYPE D3D11VideoContext::Release() {
+ return m_ctx->Release();
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryInterface(
+ REFIID riid,
+ void** ppvObject) {
+ return m_ctx->QueryInterface(riid, ppvObject);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData) {
+ return m_ctx->GetPrivateData(Name, pDataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData) {
+ return m_ctx->SetPrivateData(Name, DataSize, pData);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown) {
+ return m_ctx->SetPrivateDataInterface(Name, pUnknown);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::GetDevice(
+ ID3D11Device** ppDevice) {
+ return m_ctx->GetDevice(ppDevice);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetDecoderBuffer(
+ ID3D11VideoDecoder* pDecoder,
+ D3D11_VIDEO_DECODER_BUFFER_TYPE Type,
+ UINT* BufferSize,
+ void** ppBuffer) {
+ Logger::err("D3D11VideoContext::GetDecoderBuffer: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::ReleaseDecoderBuffer(
+ ID3D11VideoDecoder* pDecoder,
+ D3D11_VIDEO_DECODER_BUFFER_TYPE Type) {
+ Logger::err("D3D11VideoContext::ReleaseDecoderBuffer: Stub");
+ return E_NOTIMPL;
+ }
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderBeginFrame(
+ ID3D11VideoDecoder* pDecoder,
+ ID3D11VideoDecoderOutputView* pView,
+ UINT KeySize,
+ const void* pKey) {
+ Logger::err("D3D11VideoContext::DecoderBeginFrame: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderEndFrame(
+ ID3D11VideoDecoder* pDecoder) {
+ Logger::err("D3D11VideoContext::DecoderEndFrame: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::SubmitDecoderBuffers(
+ ID3D11VideoDecoder* pDecoder,
+ UINT BufferCount,
+ const D3D11_VIDEO_DECODER_BUFFER_DESC* pBufferDescs) {
+ Logger::err("D3D11VideoContext::SubmitDecoderBuffers: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderExtension(
+ ID3D11VideoDecoder* pDecoder,
+ const D3D11_VIDEO_DECODER_EXTENSION* pExtension) {
+ Logger::err("D3D11VideoContext::DecoderExtension: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputTargetRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable,
+ const RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+ state->outputTargetRectEnabled = Enable;
+
+ if (Enable)
+ state->outputTargetRect = *pRect;
+
+ static bool errorShown = false;
+
+ if (!std::exchange(errorShown, true))
+ Logger::err("D3D11VideoContext::VideoProcessorSetOutputTargetRect: Stub.");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputBackgroundColor(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL YCbCr,
+ const D3D11_VIDEO_COLOR* pColor) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+ state->outputBackgroundColorIsYCbCr = YCbCr;
+ state->outputBackgroundColor = *pColor;
+
+ static bool errorShown = false;
+
+ if (!std::exchange(errorShown, true))
+ Logger::err("D3D11VideoContext::VideoProcessorSetOutputBackgroundColor: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+ state->outputColorSpace = *pColorSpace;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE AlphaFillMode,
+ UINT StreamIndex) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputConstriction(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable,
+ SIZE Size) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetOutputConstriction: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputStereoMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+ state->outputStereoModeEnabled = Enable;
+
+ if (Enable)
+ Logger::err("D3D11VideoContext: Stereo output not supported");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetOutputExtension: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFrameFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_FRAME_FORMAT Format) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->frameFormat = Format;
+
+ if (Format != D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE)
+ Logger::err(str::format("D3D11VideoContext: Unsupported frame format: ", Format));
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->colorSpace = *pColorSpace;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamOutputRate(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate,
+ BOOL Repeat,
+ const DXGI_RATIONAL* CustomRate) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamOutputRate: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamSourceRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->srcRectEnabled = Enable;
+
+ if (Enable)
+ state->srcRect = *pRect;
+
+ static bool errorShown = false;
+
+ if (!std::exchange(errorShown, true))
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamSourceRect: Stub.");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamDestRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->dstRectEnabled = Enable;
+
+ if (Enable)
+ state->dstRect = *pRect;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAlpha(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ FLOAT Alpha) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamAlpha: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPalette(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ UINT EntryCount,
+ const UINT* pEntries) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamPalette: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const DXGI_RATIONAL* pSrcAspectRatio,
+ const DXGI_RATIONAL* pDstAspectRatio) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamLumaKey(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ FLOAT Lower,
+ FLOAT Upper) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamLumaKey: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamStereoFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ D3D11_VIDEO_PROCESSOR_STEREO_FORMAT Format,
+ BOOL LeftViewFrame0,
+ BOOL BaseViewFrame0,
+ D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE FlipMode,
+ int MonoOffset) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamStereoFormat: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAutoProcessingMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->autoProcessingEnabled = Enable;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFilter(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ BOOL Enable,
+ int Level) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamFilter: Stub");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::VideoProcessorSetStreamExtension: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamRotation(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ D3D11_VIDEO_PROCESSOR_ROTATION Rotation) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ state->rotationEnabled = Enable;
+ state->rotation = Rotation;
+
+ if (Enable && Rotation != D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY)
+ Logger::err(str::format("D3D11VideoContext: Unsupported rotation: ", Rotation));
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputTargetRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled,
+ RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+
+ if (pEnabled)
+ *pEnabled = state->outputTargetRectEnabled;
+
+ if (pRect)
+ *pRect = state->outputTargetRect;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputBackgroundColor(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pYCbCr,
+ D3D11_VIDEO_COLOR* pColor) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+
+ if (pYCbCr)
+ *pYCbCr = state->outputBackgroundColorIsYCbCr;
+
+ if (pColor)
+ *pColor = state->outputBackgroundColor;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+
+ if (pColorSpace)
+ *pColorSpace = state->outputColorSpace;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE* pAlphaFillMode,
+ UINT* pStreamIndex) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputConstriction(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled,
+ SIZE* pSize) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetOutputConstriction: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputStereoMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
+
+ if (pEnabled)
+ *pEnabled = state->outputStereoModeEnabled;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetOutputExtension: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFrameFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_FRAME_FORMAT* pFormat) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ if (pFormat)
+ *pFormat = state->frameFormat;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ if (pColorSpace)
+ *pColorSpace = state->colorSpace;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamOutputRate(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_OUTPUT_RATE* pRate,
+ BOOL* pRepeat,
+ DXGI_RATIONAL* pCustomRate) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamOutputRate: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamSourceRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ if (pEnabled)
+ *pEnabled = state->srcRectEnabled;
+
+ if (pRect)
+ *pRect = state->srcRect;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamDestRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ RECT* pRect) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ if (pEnabled)
+ *pEnabled = state->dstRectEnabled;
+
+ if (pRect)
+ *pRect = state->dstRect;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAlpha(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ FLOAT* pAlpha) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamAlpha: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPalette(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ UINT EntryCount,
+ UINT* pEntries) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamPalette: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ DXGI_RATIONAL* pSrcAspectRatio,
+ DXGI_RATIONAL* pDstAspectRatio) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamLumaKey(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ FLOAT* pLower,
+ FLOAT* pUpper) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamLumaKey: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamStereoFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ D3D11_VIDEO_PROCESSOR_STEREO_FORMAT* pFormat,
+ BOOL* pLeftViewFrame0,
+ BOOL* pBaseViewFrame0,
+ D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE* pFlipMode,
+ int* pMonoOffset) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamStereoFormat: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAutoProcessingMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ *pEnabled = state->autoProcessingEnabled;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFilter(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ BOOL* pEnabled,
+ int* pLevel) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamFilter: Stub");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::VideoProcessorGetStreamExtension: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamRotation(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnable,
+ D3D11_VIDEO_PROCESSOR_ROTATION* pRotation) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
+
+ if (!state)
+ return;
+
+ if (pEnable)
+ *pEnable = state->rotationEnabled;
+
+ if (pRotation)
+ *pRotation = state->rotation;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorBlt(
+ ID3D11VideoProcessor* pVideoProcessor,
+ ID3D11VideoProcessorOutputView* pOutputView,
+ UINT FrameIdx,
+ UINT StreamCount,
+ const D3D11_VIDEO_PROCESSOR_STREAM* pStreams) {
+ D3D10DeviceLock lock = m_ctx->LockContext();
+
+ auto videoProcessor = static_cast<D3D11VideoProcessor*>(pVideoProcessor);
+ bool hasStreamsEnabled = false;
+
+ // Resetting and restoring all context state incurs
+ // a lot of overhead, so only do it as necessary
+ for (uint32_t i = 0; i < StreamCount; i++) {
+ auto streamState = videoProcessor->GetStreamState(i);
+
+ if (!pStreams[i].Enable || !streamState)
+ continue;
+
+ if (!hasStreamsEnabled) {
+ m_ctx->ResetState();
+ BindOutputView(pOutputView);
+ hasStreamsEnabled = true;
+ }
+
+ BlitStream(streamState, &pStreams[i]);
+ }
+
+ if (hasStreamsEnabled)
+ m_ctx->RestoreState();
+
+ return S_OK;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateCryptoSessionKeyExchange(
+ ID3D11CryptoSession* pSession,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::NegotiateCryptoSessionKeyExchange: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::EncryptionBlt(
+ ID3D11CryptoSession* pSession,
+ ID3D11Texture2D* pSrcSurface,
+ ID3D11Texture2D* pDstSurface,
+ UINT IVSize,
+ void* pIV) {
+ Logger::err("D3D11VideoContext::EncryptionBlt: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::DecryptionBlt(
+ ID3D11CryptoSession* pSession,
+ ID3D11Texture2D* pSrcSurface,
+ ID3D11Texture2D* pDstSurface,
+ D3D11_ENCRYPTED_BLOCK_INFO* pBlockInfo,
+ UINT KeySize,
+ const void* pKey,
+ UINT IVSize,
+ void* pIV) {
+ Logger::err("D3D11VideoContext::DecryptionBlt: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::StartSessionKeyRefresh(
+ ID3D11CryptoSession* pSession,
+ UINT RandomNumberSize,
+ void* pRandomNumber) {
+ Logger::err("D3D11VideoContext::StartSessionKeyRefresh: Stub");
+ }
+
+
+ void STDMETHODCALLTYPE D3D11VideoContext::FinishSessionKeyRefresh(
+ ID3D11CryptoSession* pSession) {
+ Logger::err("D3D11VideoContext::FinishSessionKeyRefresh: Stub");
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetEncryptionBltKey(
+ ID3D11CryptoSession* pSession,
+ UINT KeySize,
+ void* pKey) {
+ Logger::err("D3D11VideoContext::GetEncryptionBltKey: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT DataSize,
+ void* pData) {
+ Logger::err("D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryAuthenticatedChannel(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT InputSize,
+ const void* pInput,
+ UINT OutputSize,
+ void* pOutput) {
+ Logger::err("D3D11VideoContext::QueryAuthenticatedChannel: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11VideoContext::ConfigureAuthenticatedChannel(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT InputSize,
+ const void* pInput,
+ D3D11_AUTHENTICATED_CONFIGURE_OUTPUT* pOutput) {
+ Logger::err("D3D11VideoContext::ConfigureAuthenticatedChannel: Stub");
+ return E_NOTIMPL;
+ }
+
+
+ void D3D11VideoContext::ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]) {
+ float result[3][4];
+
+ for (uint32_t i = 0; i < 3; i++) {
+ for (uint32_t j = 0; j < 4; j++) {
+ result[i][j] = pSrc[i][0] * pDst[0][j]
+ + pSrc[i][1] * pDst[1][j]
+ + pSrc[i][2] * pDst[2][j]
+ + pSrc[i][3] * float(j == 3);
+ }
+ }
+
+ memcpy(pDst, &result[0][0], sizeof(result));
+ }
+
+
+ void D3D11VideoContext::ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709) {
+ static const float pretransform[3][4] = {
+ { 0.0f, 1.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f, -0.5f },
+ { 1.0f, 0.0f, 0.0f, -0.5f },
+ };
+
+ static const float bt601[3][4] = {
+ { 1.0f, 0.000000f, 1.402000f, 0.0f },
+ { 1.0f, -0.344136f, -0.714136f, 0.0f },
+ { 1.0f, 1.772000f, 0.000000f, 0.0f },
+ };
+
+ static const float bt709[3][4] = {
+ { 1.0f, 0.000000f, 1.574800f, 0.0f },
+ { 1.0f, -0.187324f, -0.468124f, 0.0f },
+ { 1.0f, 1.855600f, 0.000000f, 0.0f },
+ };
+
+ ApplyColorMatrix(pColorMatrix, pretransform);
+ ApplyColorMatrix(pColorMatrix, UseBt709 ? bt709 : bt601);
+ }
+
+
+ void D3D11VideoContext::BindOutputView(
+ ID3D11VideoProcessorOutputView* pOutputView) {
+ auto dxvkView = static_cast<D3D11VideoProcessorOutputView*>(pOutputView)->GetView();
+
+ m_ctx->EmitCs([this, cView = dxvkView] (DxvkContext* ctx) {
+ DxvkRenderTargets rt;
+ rt.color[0].view = cView;
+ rt.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ ctx->bindRenderTargets(rt);
+ ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vs);
+ ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_fs);
+ ctx->bindResourceBuffer(0, DxvkBufferSlice(m_ubo));
+
+ DxvkInputAssemblyState iaState;
+ iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ iaState.primitiveRestart = VK_FALSE;
+ iaState.patchVertexCount = 0;
+ ctx->setInputAssemblyState(iaState);
+ });
+
+ VkExtent3D viewExtent = dxvkView->mipLevelExtent(0);
+ m_dstExtent = { viewExtent.width, viewExtent.height };
+ }
+
+
+ void D3D11VideoContext::BlitStream(
+ const D3D11VideoProcessorStreamState* pStreamState,
+ const D3D11_VIDEO_PROCESSOR_STREAM* pStream) {
+ if (pStream->PastFrames || pStream->FutureFrames)
+ Logger::err("D3D11VideoContext: Ignoring non-zero PastFrames and FutureFrames");
+
+ if (pStream->OutputIndex)
+ Logger::err("D3D11VideoContext: Ignoring non-zero OutputIndex");
+
+ if (pStream->InputFrameOrField)
+ Logger::err("D3D11VideoContext: Ignoring non-zero InputFrameOrField");
+
+ auto view = static_cast<D3D11VideoProcessorInputView*>(pStream->pInputSurface);
+
+ if (view->NeedsCopy()) {
+ m_ctx->EmitCs([
+ cDstImage = view->GetShadowCopy(),
+ cSrcImage = view->GetImage(),
+ cSrcLayers = view->GetImageSubresources()
+ ] (DxvkContext* ctx) {
+ VkImageSubresourceLayers cDstLayers;
+ cDstLayers.aspectMask = cSrcLayers.aspectMask;
+ cDstLayers.baseArrayLayer = 0;
+ cDstLayers.layerCount = cSrcLayers.layerCount;
+ cDstLayers.mipLevel = cSrcLayers.mipLevel;
+
+ ctx->copyImage(
+ cDstImage, cDstLayers, VkOffset3D(),
+ cSrcImage, cSrcLayers, VkOffset3D(),
+ cDstImage->info().extent);
+ });
+ }
+
+ m_ctx->EmitCs([this,
+ cStreamState = *pStreamState,
+ cViews = view->GetViews(),
+ cIsYCbCr = view->IsYCbCr()
+ ] (DxvkContext* ctx) {
+ VkViewport viewport;
+ viewport.x = 0.0f;
+ viewport.y = 0.0f;
+ viewport.width = float(m_dstExtent.width);
+ viewport.height = float(m_dstExtent.height);
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+
+ VkRect2D scissor;
+ scissor.offset = { 0, 0 };
+ scissor.extent = m_dstExtent;
+
+ if (cStreamState.dstRectEnabled) {
+ viewport.x = float(cStreamState.dstRect.left);
+ viewport.y = float(cStreamState.dstRect.top);
+ viewport.width = float(cStreamState.dstRect.right) - viewport.x;
+ viewport.height = float(cStreamState.dstRect.bottom) - viewport.y;
+ }
+
+ UboData uboData = { };
+ uboData.colorMatrix[0][0] = 1.0f;
+ uboData.colorMatrix[1][1] = 1.0f;
+ uboData.colorMatrix[2][2] = 1.0f;
+ uboData.coordMatrix[0][0] = 1.0f;
+ uboData.coordMatrix[1][1] = 1.0f;
+ uboData.yMin = 0.0f;
+ uboData.yMax = 1.0f;
+
+ if (cIsYCbCr)
+ ApplyYCbCrMatrix(uboData.colorMatrix, cStreamState.colorSpace.YCbCr_Matrix);
+
+ if (cStreamState.colorSpace.Nominal_Range) {
+ uboData.yMin = 0.0627451f;
+ uboData.yMax = 0.9215686f;
+ }
+
+ DxvkBufferSliceHandle uboSlice = m_ubo->allocSlice();
+ memcpy(uboSlice.mapPtr, &uboData, sizeof(uboData));
+
+ ctx->invalidateBuffer(m_ubo, uboSlice);
+ ctx->setViewports(1, &viewport, &scissor);
+ ctx->bindResourceSampler(1, m_sampler);
+
+ for (uint32_t i = 0; i < cViews.size(); i++)
+ ctx->bindResourceView(2 + i, cViews[i], nullptr);
+
+ ctx->draw(3, 1, 0, 0);
+ });
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.h
new file mode 100644
index 00000000..85979eb8
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_video.h
@@ -0,0 +1,612 @@
+#pragma once
+
+#include "d3d11_device.h"
+
+namespace dxvk {
+
+ static constexpr uint32_t D3D11_VK_VIDEO_STREAM_COUNT = 8;
+
+ class D3D11VideoProcessorEnumerator : public D3D11DeviceChild<ID3D11VideoProcessorEnumerator> {
+
+ public:
+
+ D3D11VideoProcessorEnumerator(
+ D3D11Device* pDevice,
+ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC& Desc);
+
+ ~D3D11VideoProcessorEnumerator();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetVideoProcessorContentDesc(
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pContentDesc);
+
+ HRESULT STDMETHODCALLTYPE CheckVideoProcessorFormat(
+ DXGI_FORMAT Format,
+ UINT* pFlags);
+
+ HRESULT STDMETHODCALLTYPE GetVideoProcessorCaps(
+ D3D11_VIDEO_PROCESSOR_CAPS* pCaps);
+
+ HRESULT STDMETHODCALLTYPE GetVideoProcessorRateConversionCaps(
+ UINT TypeIndex,
+ D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps);
+
+ HRESULT STDMETHODCALLTYPE GetVideoProcessorCustomRate(
+ UINT TypeIndex,
+ UINT CustomRateIndex,
+ D3D11_VIDEO_PROCESSOR_CUSTOM_RATE* pRate);
+
+ HRESULT STDMETHODCALLTYPE GetVideoProcessorFilterRange(
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ D3D11_VIDEO_PROCESSOR_FILTER_RANGE* pRange);
+
+ private:
+
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC m_desc;
+
+ };
+
+
+ struct D3D11VideoProcessorStreamState {
+ BOOL autoProcessingEnabled = TRUE;
+ BOOL dstRectEnabled = FALSE;
+ BOOL srcRectEnabled = FALSE;
+ BOOL rotationEnabled = FALSE;
+ RECT dstRect = RECT();
+ RECT srcRect = RECT();
+ D3D11_VIDEO_FRAME_FORMAT frameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+ D3D11_VIDEO_PROCESSOR_ROTATION rotation = D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY;
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE();
+ };
+
+ struct D3D11VideoProcessorState {
+ BOOL outputStereoModeEnabled = FALSE;
+ BOOL outputBackgroundColorIsYCbCr = FALSE;
+ BOOL outputTargetRectEnabled = FALSE;
+ RECT outputTargetRect = RECT();
+ D3D11_VIDEO_COLOR outputBackgroundColor = D3D11_VIDEO_COLOR();
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE outputColorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE();
+ };
+
+ class D3D11VideoProcessor : public D3D11DeviceChild<ID3D11VideoProcessor> {
+
+ public:
+
+ D3D11VideoProcessor(
+ D3D11Device* pDevice,
+ D3D11VideoProcessorEnumerator* pEnumerator,
+ UINT RateConversionIndex);
+
+ ~D3D11VideoProcessor();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE GetContentDesc(
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC *pDesc);
+
+ void STDMETHODCALLTYPE GetRateConversionCaps(
+ D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps);
+
+ D3D11VideoProcessorState* GetState() {
+ return &m_state;
+ }
+
+ D3D11VideoProcessorStreamState* GetStreamState(UINT StreamIndex) {
+ return StreamIndex < D3D11_VK_VIDEO_STREAM_COUNT
+ ? &m_streams[StreamIndex]
+ : nullptr;
+ }
+
+ private:
+
+ D3D11VideoProcessorEnumerator* m_enumerator;
+ uint32_t m_rateConversionIndex;
+ D3D11VideoProcessorState m_state;
+ D3D11VideoProcessorStreamState m_streams[D3D11_VK_VIDEO_STREAM_COUNT];
+
+ };
+
+
+
+ class D3D11VideoProcessorInputView : public D3D11DeviceChild<ID3D11VideoProcessorInputView> {
+
+ public:
+
+ D3D11VideoProcessorInputView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC& Desc);
+
+ ~D3D11VideoProcessorInputView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE GetResource(
+ ID3D11Resource** ppResource);
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc);
+
+ const bool IsYCbCr() const {
+ return m_isYCbCr;
+ }
+
+ const bool NeedsCopy() const {
+ return m_copy != nullptr;
+ }
+
+ Rc<DxvkImage> GetImage() const {
+ return GetCommonTexture(m_resource.ptr())->GetImage();
+ }
+
+ VkImageSubresourceLayers GetImageSubresources() const {
+ return m_subresources;
+ }
+
+ Rc<DxvkImage> GetShadowCopy() const {
+ return m_copy;
+ }
+
+ std::array<Rc<DxvkImageView>, 2> GetViews() const {
+ return m_views;
+ }
+
+ private:
+
+ Com<ID3D11Resource> m_resource;
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC m_desc;
+ VkImageSubresourceLayers m_subresources;
+ Rc<DxvkImage> m_copy;
+ std::array<Rc<DxvkImageView>, 2> m_views;
+ bool m_isYCbCr = false;
+
+ static bool IsYCbCrFormat(DXGI_FORMAT Format);
+
+ };
+
+
+
+ class D3D11VideoProcessorOutputView : public D3D11DeviceChild<ID3D11VideoProcessorOutputView> {
+
+ public:
+
+ D3D11VideoProcessorOutputView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC& Desc);
+
+ ~D3D11VideoProcessorOutputView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ void STDMETHODCALLTYPE GetResource(
+ ID3D11Resource** ppResource);
+
+ void STDMETHODCALLTYPE GetDesc(
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc);
+
+ Rc<DxvkImageView> GetView() const {
+ return m_view;
+ }
+
+ private:
+
+ Com<ID3D11Resource> m_resource;
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC m_desc;
+ Rc<DxvkImageView> m_view;
+
+ };
+
+
+
+ class D3D11VideoContext : public ID3D11VideoContext {
+
+ public:
+
+ D3D11VideoContext(
+ D3D11ImmediateContext* pContext,
+ const Rc<DxvkDevice>& Device);
+
+ ~D3D11VideoContext();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void** ppvObject);
+
+ HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID Name,
+ UINT* pDataSize,
+ void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID Name,
+ UINT DataSize,
+ const void* pData);
+
+ HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID Name,
+ const IUnknown* pUnknown);
+
+ void STDMETHODCALLTYPE GetDevice(
+ ID3D11Device** ppDevice);
+
+ HRESULT STDMETHODCALLTYPE GetDecoderBuffer(
+ ID3D11VideoDecoder* pDecoder,
+ D3D11_VIDEO_DECODER_BUFFER_TYPE Type,
+ UINT* BufferSize,
+ void** ppBuffer);
+
+ HRESULT STDMETHODCALLTYPE ReleaseDecoderBuffer(
+ ID3D11VideoDecoder* pDecoder,
+ D3D11_VIDEO_DECODER_BUFFER_TYPE Type);
+
+ HRESULT STDMETHODCALLTYPE DecoderBeginFrame(
+ ID3D11VideoDecoder* pDecoder,
+ ID3D11VideoDecoderOutputView* pView,
+ UINT KeySize,
+ const void* pKey);
+
+ HRESULT STDMETHODCALLTYPE DecoderEndFrame(
+ ID3D11VideoDecoder* pDecoder);
+
+ HRESULT STDMETHODCALLTYPE SubmitDecoderBuffers(
+ ID3D11VideoDecoder* pDecoder,
+ UINT BufferCount,
+ const D3D11_VIDEO_DECODER_BUFFER_DESC* pBufferDescs);
+
+ HRESULT STDMETHODCALLTYPE DecoderExtension(
+ ID3D11VideoDecoder* pDecoder,
+ const D3D11_VIDEO_DECODER_EXTENSION* pExtension);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputTargetRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable,
+ const RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputBackgroundColor(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL YCbCr,
+ const D3D11_VIDEO_COLOR* pColor);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputAlphaFillMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE AlphaFillMode,
+ UINT StreamIndex);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputConstriction(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable,
+ SIZE Size);
+
+ void STDMETHODCALLTYPE VideoProcessorSetOutputStereoMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL Enable);
+
+ HRESULT STDMETHODCALLTYPE VideoProcessorSetOutputExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamFrameFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_FRAME_FORMAT Format);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamOutputRate(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate,
+ BOOL Repeat,
+ const DXGI_RATIONAL* CustomRate);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamSourceRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamDestRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamAlpha(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ FLOAT Alpha);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamPalette(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ UINT EntryCount,
+ const UINT* pEntries);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamPixelAspectRatio(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ const DXGI_RATIONAL* pSrcAspectRatio,
+ const DXGI_RATIONAL* pDstAspectRatio);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamLumaKey(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ FLOAT Lower,
+ FLOAT Upper);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamStereoFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ D3D11_VIDEO_PROCESSOR_STEREO_FORMAT Format,
+ BOOL LeftViewFrame0,
+ BOOL BaseViewFrame0,
+ D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE FlipMode,
+ int MonoOffset);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamAutoProcessingMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamFilter(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ BOOL Enable,
+ int Level);
+
+ HRESULT STDMETHODCALLTYPE VideoProcessorSetStreamExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData);
+
+ void STDMETHODCALLTYPE VideoProcessorSetStreamRotation(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL Enable,
+ D3D11_VIDEO_PROCESSOR_ROTATION Rotation);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputTargetRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled,
+ RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputBackgroundColor(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pYCbCr,
+ D3D11_VIDEO_COLOR* pColor);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputAlphaFillMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE* pAlphaFillMode,
+ UINT* pStreamIndex);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputConstriction(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled,
+ SIZE* pSize);
+
+ void STDMETHODCALLTYPE VideoProcessorGetOutputStereoMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ BOOL* pEnabled);
+
+ HRESULT STDMETHODCALLTYPE VideoProcessorGetOutputExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamFrameFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_FRAME_FORMAT* pFormat);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamColorSpace(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamOutputRate(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_OUTPUT_RATE* pRate,
+ BOOL* pRepeat,
+ DXGI_RATIONAL* pCustomRate);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamSourceRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamDestRect(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ RECT* pRect);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamAlpha(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ FLOAT* pAlpha);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamPalette(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ UINT EntryCount,
+ UINT* pEntries);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamPixelAspectRatio(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ DXGI_RATIONAL* pSrcAspectRatio,
+ DXGI_RATIONAL* pDstAspectRatio);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamLumaKey(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ FLOAT* pLower,
+ FLOAT* pUpper);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamStereoFormat(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled,
+ D3D11_VIDEO_PROCESSOR_STEREO_FORMAT* pFormat,
+ BOOL* pLeftViewFrame0,
+ BOOL* pBaseViewFrame0,
+ D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE* pFlipMode,
+ int* pMonoOffset);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamAutoProcessingMode(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnabled);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamFilter(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ D3D11_VIDEO_PROCESSOR_FILTER Filter,
+ BOOL* pEnabled,
+ int* pLevel);
+
+ HRESULT STDMETHODCALLTYPE VideoProcessorGetStreamExtension(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ const GUID* pExtensionGuid,
+ UINT DataSize,
+ void* pData);
+
+ void STDMETHODCALLTYPE VideoProcessorGetStreamRotation(
+ ID3D11VideoProcessor* pVideoProcessor,
+ UINT StreamIndex,
+ BOOL* pEnable,
+ D3D11_VIDEO_PROCESSOR_ROTATION* pRotation);
+
+ HRESULT STDMETHODCALLTYPE VideoProcessorBlt(
+ ID3D11VideoProcessor* pVideoProcessor,
+ ID3D11VideoProcessorOutputView* pOutputView,
+ UINT FrameIdx,
+ UINT StreamCount,
+ const D3D11_VIDEO_PROCESSOR_STREAM* pStreams);
+
+ HRESULT STDMETHODCALLTYPE NegotiateCryptoSessionKeyExchange(
+ ID3D11CryptoSession* pSession,
+ UINT DataSize,
+ void* pData);
+
+ void STDMETHODCALLTYPE EncryptionBlt(
+ ID3D11CryptoSession* pSession,
+ ID3D11Texture2D* pSrcSurface,
+ ID3D11Texture2D* pDstSurface,
+ UINT IVSize,
+ void* pIV);
+
+ void STDMETHODCALLTYPE DecryptionBlt(
+ ID3D11CryptoSession* pSession,
+ ID3D11Texture2D* pSrcSurface,
+ ID3D11Texture2D* pDstSurface,
+ D3D11_ENCRYPTED_BLOCK_INFO* pBlockInfo,
+ UINT KeySize,
+ const void* pKey,
+ UINT IVSize,
+ void* pIV);
+
+ void STDMETHODCALLTYPE StartSessionKeyRefresh(
+ ID3D11CryptoSession* pSession,
+ UINT RandomNumberSize,
+ void* pRandomNumber);
+
+ void STDMETHODCALLTYPE FinishSessionKeyRefresh(
+ ID3D11CryptoSession* pSession);
+
+ HRESULT STDMETHODCALLTYPE GetEncryptionBltKey(
+ ID3D11CryptoSession* pSession,
+ UINT KeySize,
+ void* pKey);
+
+ HRESULT STDMETHODCALLTYPE NegotiateAuthenticatedChannelKeyExchange(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT DataSize,
+ void* pData);
+
+ HRESULT STDMETHODCALLTYPE QueryAuthenticatedChannel(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT InputSize,
+ const void* pInput,
+ UINT OutputSize,
+ void* pOutput);
+
+ HRESULT STDMETHODCALLTYPE ConfigureAuthenticatedChannel(
+ ID3D11AuthenticatedChannel* pChannel,
+ UINT InputSize,
+ const void* pInput,
+ D3D11_AUTHENTICATED_CONFIGURE_OUTPUT* pOutput);
+
+ private:
+
+ struct alignas(16) UboData {
+ float colorMatrix[3][4];
+ float coordMatrix[3][2];
+ float yMin, yMax;
+ };
+
+ D3D11ImmediateContext* m_ctx;
+
+ Rc<DxvkSampler> m_sampler;
+ Rc<DxvkShader> m_vs;
+ Rc<DxvkShader> m_fs;
+ Rc<DxvkBuffer> m_ubo;
+
+ VkExtent2D m_dstExtent = { 0u, 0u };
+
+ void ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]);
+
+ void ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709);
+
+ void BindOutputView(
+ ID3D11VideoProcessorOutputView* pOutputView);
+
+ void BlitStream(
+ const D3D11VideoProcessorStreamState* pStreamState,
+ const D3D11_VIDEO_PROCESSOR_STREAM* pStream);
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view.h
new file mode 100644
index 00000000..50fcef10
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "d3d11_include.h"
+
+namespace dxvk {
+
+ /**
+ * \brief Buffer view info
+ *
+ * Stores the byte range covered
+ * by a buffer view.
+ */
+ struct D3D11_VK_BUFFER_VIEW_INFO {
+ VkDeviceSize Offset;
+ VkDeviceSize Length;
+ };
+
+ /**
+ * \brief Image view info
+ *
+ * Stores the subresource range
+ * covered by an image view.
+ */
+ struct D3D11_VK_IMAGE_VIEW_INFO {
+ VkImageAspectFlags Aspects;
+ uint32_t MinLevel;
+ uint32_t MinLayer;
+ uint32_t NumLevels;
+ uint32_t NumLayers;
+ };
+
+ /**
+ * \brief Common view info
+ *
+ * Stores a pointer to the resource as
+ * well as the type-specific range that
+ * is affected by the view.
+ */
+ struct D3D11_VK_VIEW_INFO {
+ ID3D11Resource* pResource;
+ D3D11_RESOURCE_DIMENSION Dimension;
+ UINT BindFlags;
+ union {
+ D3D11_VK_BUFFER_VIEW_INFO Buffer;
+ D3D11_VK_IMAGE_VIEW_INFO Image;
+ };
+ };
+
+ /**
+ * \brief Checks whether two views overlap
+ *
+ * Overlapping views may conflict in case
+ * one or both views are used for writing.
+ * \param [in] a First view to check
+ * \param [in] b Second view to check
+ * \returns \c true if the views overlap
+ */
+ inline bool CheckViewOverlap(const D3D11_VK_VIEW_INFO& a, const D3D11_VK_VIEW_INFO b) {
+ if (likely(a.pResource != b.pResource))
+ return false;
+
+ if (a.Dimension == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ // Just check whether the buffer ranges overlap
+ return (a.Buffer.Offset < b.Buffer.Offset + b.Buffer.Length)
+ && (a.Buffer.Offset + a.Buffer.Length > b.Buffer.Offset);
+ } else {
+ // Check whether the subresource ranges overlap
+ return (a.Image.Aspects & b.Image.Aspects)
+ && (a.Image.MinLevel < b.Image.MinLevel + b.Image.NumLevels)
+ && (a.Image.MinLayer < b.Image.MinLayer + b.Image.NumLayers)
+ && (a.Image.MinLevel + a.Image.NumLevels > b.Image.MinLevel)
+ && (a.Image.MinLayer + a.Image.NumLayers > b.Image.MinLayer);
+ }
+ }
+
+ template<typename T1, typename T2>
+ bool CheckViewOverlap(const T1* a, const T2* b) {
+ return a && b && CheckViewOverlap(a->GetViewInfo(), b->GetViewInfo());
+ }
+
+} \ No newline at end of file
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.cpp
new file mode 100644
index 00000000..f0520c64
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.cpp
@@ -0,0 +1,280 @@
+#include "d3d11_device.h"
+#include "d3d11_buffer.h"
+#include "d3d11_resource.h"
+#include "d3d11_texture.h"
+#include "d3d11_view_dsv.h"
+
+namespace dxvk {
+
+ D3D11DepthStencilView::D3D11DepthStencilView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc)
+ : D3D11DeviceChild<ID3D11DepthStencilView>(pDevice),
+ m_resource(pResource), m_desc(*pDesc), m_d3d10(this) {
+ ResourceAddRefPrivate(m_resource);
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_DEPTH).Format;
+ viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
+ viewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_DSV_DIMENSION_TEXTURE1D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ viewInfo.minLevel = pDesc->Texture1D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = pDesc->Texture2D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
+ break;
+
+ default:
+ throw DxvkError("D3D11: Invalid view dimension for DSV");
+ }
+
+ // Normalize view type so that we won't accidentally
+ // bind 2D array views and 2D views at the same time
+ if (viewInfo.numLayers == 1) {
+ if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ }
+
+ // Populate view info struct
+ m_info.pResource = pResource;
+ m_info.Dimension = resourceDesc.Dim;
+ m_info.BindFlags = resourceDesc.BindFlags;
+ m_info.Image.Aspects = viewInfo.aspect;
+ m_info.Image.MinLevel = viewInfo.minLevel;
+ m_info.Image.MinLayer = viewInfo.minLayer;
+ m_info.Image.NumLevels = viewInfo.numLevels;
+ m_info.Image.NumLayers = viewInfo.numLayers;
+
+ if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH)
+ m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ if (m_desc.Flags & D3D11_DSV_READ_ONLY_STENCIL)
+ m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ // Create the underlying image view object
+ m_view = pDevice->GetDXVKDevice()->createImageView(
+ GetCommonTexture(pResource)->GetImage(), viewInfo);
+ }
+
+
+ D3D11DepthStencilView::~D3D11DepthStencilView() {
+ ResourceReleasePrivate(m_resource);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11DepthStencilView::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11DepthStencilView)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10View)
+ || riid == __uuidof(ID3D10DepthStencilView)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11DepthStencilView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DepthStencilView::GetResource(ID3D11Resource** ppResource) {
+ *ppResource = ref(m_resource);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11DepthStencilView::GetDesc(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11DepthStencilView::GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+ pDesc->Flags = 0;
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
+ pDesc->Texture1D.MipSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
+ pDesc->Texture1DArray.MipSlice = 0;
+ pDesc->Texture1DArray.FirstArraySlice = 0;
+ pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.SampleDesc.Count == 1) {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ pDesc->Texture2D.MipSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ pDesc->Texture2DArray.MipSlice = 0;
+ pDesc->Texture2DArray.FirstArraySlice = 0;
+ pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
+ }
+ } else {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ } else {
+ pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
+ pDesc->Texture2DMSArray.FirstArraySlice = 0;
+ pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
+ }
+ }
+ } return S_OK;
+
+ default:
+ Logger::err(str::format(
+ "D3D11: Unsupported dimension for depth stencil view: ",
+ resourceDim));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ HRESULT D3D11DepthStencilView::NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ uint32_t numLayers = 0;
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1D
+ && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1DARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture1D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2D
+ && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DARRAY
+ && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMS
+ && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture2D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
+ pDesc->Format = format;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice)
+ pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice)
+ pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice)
+ pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
+ break;
+
+ default:
+ break;
+ }
+
+ return S_OK;
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.h
new file mode 100644
index 00000000..41b6fcb1
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_dsv.h
@@ -0,0 +1,98 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_view_dsv.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_view.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Depth-stencil view
+ *
+ * Unordered access views are special in that they can
+ * have counters, which can be used inside shaders to
+ * atomically append or consume structures.
+ */
+ class D3D11DepthStencilView : public D3D11DeviceChild<ID3D11DepthStencilView> {
+
+ public:
+
+ D3D11DepthStencilView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc);
+
+ ~D3D11DepthStencilView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final;
+
+ void STDMETHODCALLTYPE GetDesc(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) final;
+
+ const D3D11_VK_VIEW_INFO& GetViewInfo() const {
+ return m_info;
+ }
+
+ D3D11_RESOURCE_DIMENSION GetResourceType() const {
+ D3D11_RESOURCE_DIMENSION type;
+ m_resource->GetType(&type);
+ return type;
+ }
+
+ Rc<DxvkImageView> GetImageView() const {
+ return m_view;
+ }
+
+ VkImageLayout GetRenderLayout() const {
+ if (m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL) {
+ switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) {
+ default: // case 0
+ return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ case D3D11_DSV_READ_ONLY_DEPTH:
+ return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
+ case D3D11_DSV_READ_ONLY_STENCIL:
+ return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
+ case D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL:
+ return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+ }
+ } else {
+ return VK_IMAGE_LAYOUT_GENERAL;
+ }
+ }
+
+ VkImageAspectFlags GetWritableAspectMask() const {
+ VkImageAspectFlags mask = m_view->formatInfo()->aspectMask;
+ if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH) mask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (m_desc.Flags & D3D11_DSV_READ_ONLY_STENCIL) mask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
+ return mask;
+ }
+
+ D3D10DepthStencilView* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc);
+
+ static HRESULT NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11_DEPTH_STENCIL_VIEW_DESC m_desc;
+ D3D11_VK_VIEW_INFO m_info;
+ Rc<DxvkImageView> m_view;
+ D3D10DepthStencilView m_d3d10;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.cpp
new file mode 100644
index 00000000..86460502
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.cpp
@@ -0,0 +1,440 @@
+#include "d3d11_device.h"
+#include "d3d11_buffer.h"
+#include "d3d11_resource.h"
+#include "d3d11_texture.h"
+#include "d3d11_view_rtv.h"
+
+namespace dxvk {
+
+ D3D11RenderTargetView::D3D11RenderTargetView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc)
+ : D3D11DeviceChild<ID3D11RenderTargetView1>(pDevice),
+ m_resource(pResource), m_desc(*pDesc), m_d3d10(this) {
+ ResourceAddRefPrivate(m_resource);
+
+ auto texture = GetCommonTexture(pResource);
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(
+ pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR);
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = formatInfo.Format;
+ viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
+ viewInfo.swizzle = formatInfo.Swizzle;
+ viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ viewInfo.minLevel = pDesc->Texture1D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = pDesc->Texture2D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture3D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture3D.FirstWSlice;
+ viewInfo.numLayers = pDesc->Texture3D.WSize;
+ break;
+
+ default:
+ throw DxvkError("D3D11: Invalid view dimension for RTV");
+ }
+
+ if (texture->GetPlaneCount() > 1)
+ viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
+
+ // Normalize view type so that we won't accidentally
+ // bind 2D array views and 2D views at the same time
+ if (viewInfo.numLayers == 1) {
+ if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ }
+
+ // Populate view info struct
+ m_info.pResource = pResource;
+ m_info.Dimension = resourceDesc.Dim;
+ m_info.BindFlags = resourceDesc.BindFlags;
+ m_info.Image.Aspects = viewInfo.aspect;
+ m_info.Image.MinLevel = viewInfo.minLevel;
+ m_info.Image.MinLayer = viewInfo.minLayer;
+ m_info.Image.NumLevels = viewInfo.numLevels;
+ m_info.Image.NumLayers = viewInfo.numLayers;
+
+ // Create the underlying image view object
+ m_view = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo);
+ }
+
+
+ D3D11RenderTargetView::~D3D11RenderTargetView() {
+ ResourceReleasePrivate(m_resource);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11RenderTargetView::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11RenderTargetView)
+ || riid == __uuidof(ID3D11RenderTargetView1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10View)
+ || riid == __uuidof(ID3D10RenderTargetView)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11RenderTargetView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RenderTargetView::GetResource(ID3D11Resource** ppResource) {
+ *ppResource = ref(m_resource);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RenderTargetView::GetDesc(D3D11_RENDER_TARGET_VIEW_DESC* pDesc) {
+ pDesc->Format = m_desc.Format;
+ pDesc->ViewDimension = m_desc.ViewDimension;
+
+ switch (m_desc.ViewDimension) {
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_RTV_DIMENSION_BUFFER:
+ pDesc->Buffer = m_desc.Buffer;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ pDesc->Texture1D = m_desc.Texture1D;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ pDesc->Texture1DArray = m_desc.Texture1DArray;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ pDesc->Texture2D.MipSlice = m_desc.Texture2D.MipSlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ pDesc->Texture2DArray.MipSlice = m_desc.Texture2DArray.MipSlice;
+ pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice;
+ pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ pDesc->Texture2DMS = m_desc.Texture2DMS;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ pDesc->Texture2DMSArray = m_desc.Texture2DMSArray;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ pDesc->Texture3D = m_desc.Texture3D;
+ break;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11RenderTargetView::GetDesc1(D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11RenderTargetView::GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+ pDesc->Texture1D.MipSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
+ pDesc->Texture1DArray.MipSlice = 0;
+ pDesc->Texture1DArray.FirstArraySlice = 0;
+ pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.SampleDesc.Count == 1) {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ pDesc->Texture2D.MipSlice = 0;
+ pDesc->Texture2D.PlaneSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ pDesc->Texture2DArray.MipSlice = 0;
+ pDesc->Texture2DArray.FirstArraySlice = 0;
+ pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
+ pDesc->Texture2DArray.PlaneSlice = 0;
+ }
+ } else {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ } else {
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+ pDesc->Texture2DMSArray.FirstArraySlice = 0;
+ pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
+ }
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+ pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ pDesc->Texture3D.MipSlice = 0;
+ pDesc->Texture3D.FirstWSlice = 0;
+ pDesc->Texture3D.WSize = resourceDesc.Depth;
+ } return S_OK;
+
+ default:
+ Logger::err(str::format(
+ "D3D11: Unsupported dimension for render target view: ",
+ resourceDim));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ D3D11_RENDER_TARGET_VIEW_DESC1 D3D11RenderTargetView::PromoteDesc(
+ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
+ UINT Plane) {
+ D3D11_RENDER_TARGET_VIEW_DESC1 dstDesc;
+ dstDesc.Format = pDesc->Format;
+ dstDesc.ViewDimension = pDesc->ViewDimension;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_RTV_DIMENSION_BUFFER:
+ dstDesc.Buffer = pDesc->Buffer;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ dstDesc.Texture1D = pDesc->Texture1D;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ dstDesc.Texture1DArray = pDesc->Texture1DArray;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ dstDesc.Texture2D.MipSlice = pDesc->Texture2D.MipSlice;
+ dstDesc.Texture2D.PlaneSlice = Plane;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ dstDesc.Texture2DArray.MipSlice = pDesc->Texture2DArray.MipSlice;
+ dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice;
+ dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize;
+ dstDesc.Texture2DArray.PlaneSlice = Plane;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ dstDesc.Texture2DMS = pDesc->Texture2DMS;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ dstDesc.Texture2DMSArray = pDesc->Texture2DMSArray;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ dstDesc.Texture3D = pDesc->Texture3D;
+ break;
+ }
+
+ return dstDesc;
+ }
+
+
+ HRESULT D3D11RenderTargetView::NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ uint32_t numLayers = 0;
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: {
+ if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_BUFFER) {
+ Logger::err("D3D11: Incompatible view dimension for Buffer");
+ return E_INVALIDARG;
+ }
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1D
+ && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1DARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture1D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2D
+ && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DARRAY
+ && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMS
+ && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture2D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE3D) {
+ Logger::err("D3D11: Incompatible view dimension for Texture3D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = std::max(resourceDesc.Depth >> pDesc->Texture3D.MipSlice, 1u);
+ } break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
+ pDesc->Format = format;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice)
+ pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice)
+ pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice)
+ pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ if (pDesc->Texture3D.WSize > numLayers - pDesc->Texture3D.FirstWSlice)
+ pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice;
+ break;
+
+ default:
+ break;
+ }
+
+ return S_OK;
+ }
+
+
+ UINT D3D11RenderTargetView::GetPlaneSlice(const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) {
+ switch (pDesc->ViewDimension) {
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ return pDesc->Texture2D.PlaneSlice;
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ return pDesc->Texture2DArray.PlaneSlice;
+ default:
+ return 0;
+ }
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.h
new file mode 100644
index 00000000..080146ec
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_rtv.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_view_rtv.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_view.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Render target view
+ */
+ class D3D11RenderTargetView : public D3D11DeviceChild<ID3D11RenderTargetView1> {
+
+ public:
+
+ D3D11RenderTargetView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc);
+
+ ~D3D11RenderTargetView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final;
+
+ void STDMETHODCALLTYPE GetDesc(D3D11_RENDER_TARGET_VIEW_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) final;
+
+ const D3D11_VK_VIEW_INFO& GetViewInfo() const {
+ return m_info;
+ }
+
+ BOOL HasBindFlag(UINT Flags) const {
+ return m_info.BindFlags & Flags;
+ }
+
+ D3D11_RESOURCE_DIMENSION GetResourceType() const {
+ D3D11_RESOURCE_DIMENSION type;
+ m_resource->GetType(&type);
+ return type;
+ }
+
+ Rc<DxvkImageView> GetImageView() const {
+ return m_view;
+ }
+
+ VkImageLayout GetRenderLayout() const {
+ return m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL
+ ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ : VK_IMAGE_LAYOUT_GENERAL;
+ }
+
+ D3D10RenderTargetView* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_RENDER_TARGET_VIEW_DESC1* pDesc);
+
+ static D3D11_RENDER_TARGET_VIEW_DESC1 PromoteDesc(
+ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
+ UINT Plane);
+
+ static HRESULT NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_RENDER_TARGET_VIEW_DESC1* pDesc);
+
+ static UINT GetPlaneSlice(
+ const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11_RENDER_TARGET_VIEW_DESC1 m_desc;
+ D3D11_VK_VIEW_INFO m_info;
+ Rc<DxvkImageView> m_view;
+ D3D10RenderTargetView m_d3d10;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.cpp
new file mode 100644
index 00000000..1c3d4d8d
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.cpp
@@ -0,0 +1,592 @@
+#include "d3d11_device.h"
+#include "d3d11_buffer.h"
+#include "d3d11_resource.h"
+#include "d3d11_texture.h"
+#include "d3d11_view_srv.h"
+
+namespace dxvk {
+
+ D3D11ShaderResourceView::D3D11ShaderResourceView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc)
+ : D3D11DeviceChild<ID3D11ShaderResourceView1>(pDevice),
+ m_resource(pResource), m_desc(*pDesc), m_d3d10(this) {
+ ResourceAddRefPrivate(m_resource);
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ // Basic view resource info
+ m_info.pResource = pResource;
+ m_info.Dimension = resourceDesc.Dim;
+ m_info.BindFlags = resourceDesc.BindFlags;
+
+ if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ auto buffer = static_cast<D3D11Buffer*>(pResource);
+
+ // Move buffer description to a common struct to
+ // avoid having to handle the two cases separately
+ D3D11_BUFFEREX_SRV bufInfo;
+
+ if (pDesc->ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) {
+ bufInfo.FirstElement = pDesc->BufferEx.FirstElement;
+ bufInfo.NumElements = pDesc->BufferEx.NumElements;
+ bufInfo.Flags = pDesc->BufferEx.Flags;
+ } else if (pDesc->ViewDimension == D3D11_SRV_DIMENSION_BUFFER) {
+ bufInfo.FirstElement = pDesc->Buffer.FirstElement;
+ bufInfo.NumElements = pDesc->Buffer.NumElements;
+ bufInfo.Flags = 0;
+ } else {
+ throw DxvkError("D3D11: Invalid view dimension for buffer SRV");
+ }
+
+ // Fill in buffer view info
+ DxvkBufferViewCreateInfo viewInfo;
+
+ if (bufInfo.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
+ // Raw buffer view. We'll represent this as a
+ // uniform texel buffer with UINT32 elements.
+ viewInfo.format = VK_FORMAT_R32_UINT;
+ viewInfo.rangeOffset = sizeof(uint32_t) * bufInfo.FirstElement;
+ viewInfo.rangeLength = sizeof(uint32_t) * bufInfo.NumElements;
+ } else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) {
+ // Structured buffer view
+ viewInfo.format = VK_FORMAT_R32_UINT;
+ viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * bufInfo.FirstElement;
+ viewInfo.rangeLength = buffer->Desc()->StructureByteStride * bufInfo.NumElements;
+ } else {
+ viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
+
+ const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format);
+ viewInfo.rangeOffset = formatInfo->elementSize * bufInfo.FirstElement;
+ viewInfo.rangeLength = formatInfo->elementSize * bufInfo.NumElements;
+ }
+
+ // Populate view info struct
+ m_info.Buffer.Offset = viewInfo.rangeOffset;
+ m_info.Buffer.Length = viewInfo.rangeLength;
+
+ // Create underlying buffer view object
+ m_bufferView = pDevice->GetDXVKDevice()->createBufferView(
+ buffer->GetBuffer(), viewInfo);
+ } else {
+ auto texture = GetCommonTexture(pResource);
+ auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode());
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = formatInfo.Format;
+ viewInfo.aspect = formatInfo.Aspect;
+ viewInfo.swizzle = formatInfo.Swizzle;
+ viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
+
+ // Shaders expect the stencil value in the G component
+ if (viewInfo.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ viewInfo.swizzle = VkComponentMapping {
+ VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO };
+ }
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_SRV_DIMENSION_TEXTURE1D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ viewInfo.minLevel = pDesc->Texture1D.MostDetailedMip;
+ viewInfo.numLevels = pDesc->Texture1D.MipLevels;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture1DArray.MostDetailedMip;
+ viewInfo.numLevels = pDesc->Texture1DArray.MipLevels;
+ viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = pDesc->Texture2D.MostDetailedMip;
+ viewInfo.numLevels = pDesc->Texture2D.MipLevels;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture2DArray.MostDetailedMip;
+ viewInfo.numLevels = pDesc->Texture2DArray.MipLevels;
+ viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMS:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = 0;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
+ viewInfo.minLevel = pDesc->Texture3D.MostDetailedMip;
+ viewInfo.numLevels = pDesc->Texture3D.MipLevels;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE: {
+ const bool cubeArraysEnabled = pDevice->GetDXVKDevice()->features().core.features.imageCubeArray;
+ viewInfo.type = cubeArraysEnabled ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
+ viewInfo.minLevel = pDesc->TextureCube.MostDetailedMip;
+ viewInfo.numLevels = pDesc->TextureCube.MipLevels;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 6;
+ } break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+ viewInfo.minLevel = pDesc->TextureCubeArray.MostDetailedMip;
+ viewInfo.numLevels = pDesc->TextureCubeArray.MipLevels;
+ viewInfo.minLayer = pDesc->TextureCubeArray.First2DArrayFace;
+ viewInfo.numLayers = pDesc->TextureCubeArray.NumCubes * 6;
+ break;
+
+ default:
+ throw DxvkError("D3D11: Invalid view dimension for image SRV");
+ }
+
+ if (texture->GetPlaneCount() > 1)
+ viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
+
+ // Populate view info struct
+ m_info.Image.Aspects = viewInfo.aspect;
+ m_info.Image.MinLevel = viewInfo.minLevel;
+ m_info.Image.MinLayer = viewInfo.minLayer;
+ m_info.Image.NumLevels = viewInfo.numLevels;
+ m_info.Image.NumLayers = viewInfo.numLayers;
+
+ // Create the underlying image view object
+ m_imageView = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo);
+ }
+ }
+
+
+ D3D11ShaderResourceView::~D3D11ShaderResourceView() {
+ ResourceReleasePrivate(m_resource);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11ShaderResourceView::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11ShaderResourceView)
+ || riid == __uuidof(ID3D11ShaderResourceView1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10View)
+ || riid == __uuidof(ID3D10ShaderResourceView)
+ || riid == __uuidof(ID3D10ShaderResourceView1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11ShaderResourceView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ShaderResourceView::GetResource(ID3D11Resource** ppResource) {
+ *ppResource = ref(m_resource);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ShaderResourceView::GetDesc(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) {
+ pDesc->Format = m_desc.Format;
+ pDesc->ViewDimension = m_desc.ViewDimension;
+
+ switch (m_desc.ViewDimension) {
+ case D3D11_SRV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_SRV_DIMENSION_BUFFER:
+ pDesc->Buffer = m_desc.Buffer;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1D:
+ pDesc->Texture1D = m_desc.Texture1D;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
+ pDesc->Texture1DArray = m_desc.Texture1DArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ pDesc->Texture2D.MostDetailedMip = m_desc.Texture2D.MostDetailedMip;
+ pDesc->Texture2D.MipLevels = m_desc.Texture2D.MipLevels;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ pDesc->Texture2DArray.MostDetailedMip = m_desc.Texture2DArray.MostDetailedMip;
+ pDesc->Texture2DArray.MipLevels = m_desc.Texture2DArray.MipLevels;
+ pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice;
+ pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMS:
+ pDesc->Texture2DMS = m_desc.Texture2DMS;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ pDesc->Texture2DMSArray = m_desc.Texture2DMSArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ pDesc->Texture3D = m_desc.Texture3D;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ pDesc->TextureCube = m_desc.TextureCube;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
+ pDesc->TextureCubeArray = m_desc.TextureCubeArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_BUFFEREX:
+ pDesc->BufferEx = m_desc.BufferEx;
+ break;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11ShaderResourceView::GetDesc1(D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11ShaderResourceView::GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: {
+ D3D11_BUFFER_DESC bufferDesc;
+ static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
+
+ if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ pDesc->Buffer.FirstElement = 0;
+ pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride;
+ return S_OK;
+ }
+ } return E_INVALIDARG;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+ pDesc->Texture1D.MostDetailedMip = 0;
+ pDesc->Texture1D.MipLevels = resourceDesc.MipLevels;
+ } else {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+ pDesc->Texture1DArray.MostDetailedMip = 0;
+ pDesc->Texture1DArray.MipLevels = resourceDesc.MipLevels;
+ pDesc->Texture1DArray.FirstArraySlice = 0;
+ pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.SampleDesc.Count == 1) {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ pDesc->Texture2D.MostDetailedMip = 0;
+ pDesc->Texture2D.MipLevels = resourceDesc.MipLevels;
+ pDesc->Texture2D.PlaneSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ pDesc->Texture2DArray.MostDetailedMip = 0;
+ pDesc->Texture2DArray.MipLevels = resourceDesc.MipLevels;
+ pDesc->Texture2DArray.FirstArraySlice = 0;
+ pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
+ pDesc->Texture2DArray.PlaneSlice = 0;
+ }
+ } else {
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ } else {
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ pDesc->Texture2DMSArray.FirstArraySlice = 0;
+ pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
+ }
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+ pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ pDesc->Texture3D.MostDetailedMip = 0;
+ pDesc->Texture3D.MipLevels = resourceDesc.MipLevels;
+ } return S_OK;
+
+ default:
+ Logger::err(str::format(
+ "D3D11: Unsupported dimension for shader resource view: ",
+ resourceDim));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC1 D3D11ShaderResourceView::PromoteDesc(
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ UINT Plane) {
+ D3D11_SHADER_RESOURCE_VIEW_DESC1 dstDesc;
+ dstDesc.Format = pDesc->Format;
+ dstDesc.ViewDimension = pDesc->ViewDimension;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_SRV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_SRV_DIMENSION_BUFFER:
+ dstDesc.Buffer = pDesc->Buffer;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1D:
+ dstDesc.Texture1D = pDesc->Texture1D;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
+ dstDesc.Texture1DArray = pDesc->Texture1DArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ dstDesc.Texture2D.MostDetailedMip = pDesc->Texture2D.MostDetailedMip;
+ dstDesc.Texture2D.MipLevels = pDesc->Texture2D.MipLevels;
+ dstDesc.Texture2D.PlaneSlice = Plane;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ dstDesc.Texture2DArray.MostDetailedMip = pDesc->Texture2DArray.MostDetailedMip;
+ dstDesc.Texture2DArray.MipLevels = pDesc->Texture2DArray.MipLevels;
+ dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice;
+ dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize;
+ dstDesc.Texture2DArray.PlaneSlice = Plane;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMS:
+ dstDesc.Texture2DMS = pDesc->Texture2DMS;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ dstDesc.Texture2DMSArray = pDesc->Texture2DMSArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ dstDesc.Texture3D = pDesc->Texture3D;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ dstDesc.TextureCube = pDesc->TextureCube;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
+ dstDesc.TextureCubeArray = pDesc->TextureCubeArray;
+ break;
+
+ case D3D11_SRV_DIMENSION_BUFFEREX:
+ dstDesc.BufferEx = pDesc->BufferEx;
+ break;
+ }
+
+ return dstDesc;
+ }
+
+
+ HRESULT D3D11ShaderResourceView::NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ uint32_t mipLevels = 0;
+ uint32_t numLayers = 0;
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: {
+ if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFER
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFEREX) {
+ Logger::err("D3D11: Incompatible view dimension for Buffer");
+ return E_INVALIDARG;
+ }
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1D
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1DARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture1D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ mipLevels = resourceDesc.MipLevels;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2D
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DARRAY
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMS
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBE
+ && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture2D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ mipLevels = resourceDesc.MipLevels;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE3D) {
+ Logger::err("D3D11: Incompatible view dimension for Texture3D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ mipLevels = resourceDesc.MipLevels;
+ numLayers = 1;
+ } break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
+ pDesc->Format = format;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_SRV_DIMENSION_BUFFER:
+ if (pDesc->Buffer.NumElements == 0)
+ return E_INVALIDARG;
+ break;
+
+ case D3D11_SRV_DIMENSION_BUFFEREX:
+ if (pDesc->BufferEx.NumElements == 0)
+ return E_INVALIDARG;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1D:
+ if (pDesc->Texture1D.MipLevels > mipLevels - pDesc->Texture1D.MostDetailedMip)
+ pDesc->Texture1D.MipLevels = mipLevels - pDesc->Texture1D.MostDetailedMip;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
+ if (pDesc->Texture1DArray.MipLevels > mipLevels - pDesc->Texture1DArray.MostDetailedMip)
+ pDesc->Texture1DArray.MipLevels = mipLevels - pDesc->Texture1DArray.MostDetailedMip;
+ if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice)
+ pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ if (pDesc->Texture2D.MipLevels > mipLevels - pDesc->Texture2D.MostDetailedMip)
+ pDesc->Texture2D.MipLevels = mipLevels - pDesc->Texture2D.MostDetailedMip;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ if (pDesc->Texture2DArray.MipLevels > mipLevels - pDesc->Texture2DArray.MostDetailedMip)
+ pDesc->Texture2DArray.MipLevels = mipLevels - pDesc->Texture2DArray.MostDetailedMip;
+ if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice)
+ pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice)
+ pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ if (pDesc->TextureCube.MipLevels > mipLevels - pDesc->TextureCube.MostDetailedMip)
+ pDesc->TextureCube.MipLevels = mipLevels - pDesc->TextureCube.MostDetailedMip;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
+ if (pDesc->TextureCubeArray.MipLevels > mipLevels - pDesc->TextureCubeArray.MostDetailedMip)
+ pDesc->TextureCubeArray.MipLevels = mipLevels - pDesc->TextureCubeArray.MostDetailedMip;
+ if (pDesc->TextureCubeArray.NumCubes > (numLayers - pDesc->TextureCubeArray.First2DArrayFace) / 6)
+ pDesc->TextureCubeArray.NumCubes = (numLayers - pDesc->TextureCubeArray.First2DArrayFace) / 6;
+ break;
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ if (pDesc->Texture3D.MipLevels > mipLevels - pDesc->Texture3D.MostDetailedMip)
+ pDesc->Texture3D.MipLevels = mipLevels - pDesc->Texture3D.MostDetailedMip;
+ break;
+
+ default:
+ break;
+ }
+
+ return S_OK;
+ }
+
+
+ UINT D3D11ShaderResourceView::GetPlaneSlice(const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) {
+ switch (pDesc->ViewDimension) {
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ return pDesc->Texture2D.PlaneSlice;
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ return pDesc->Texture2DArray.PlaneSlice;
+ default:
+ return 0;
+ }
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.h
new file mode 100644
index 00000000..e7c5872e
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_srv.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "../d3d10/d3d10_view_srv.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_view.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Shader resource view
+ */
+ class D3D11ShaderResourceView : public D3D11DeviceChild<ID3D11ShaderResourceView1> {
+
+ public:
+
+ D3D11ShaderResourceView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
+
+ ~D3D11ShaderResourceView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final;
+
+ void STDMETHODCALLTYPE GetDesc(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) final;
+
+ const D3D11_VK_VIEW_INFO& GetViewInfo() const {
+ return m_info;
+ }
+
+ BOOL TestHazards() const {
+ return m_info.BindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_UNORDERED_ACCESS);
+ }
+
+ D3D11_RESOURCE_DIMENSION GetResourceType() const {
+ D3D11_RESOURCE_DIMENSION type;
+ m_resource->GetType(&type);
+ return type;
+ }
+
+ D3D11_COMMON_RESOURCE_DESC GetResourceDesc() const {
+ D3D11_COMMON_RESOURCE_DESC desc;
+ GetCommonResourceDesc(m_resource, &desc);
+ return desc;
+ }
+
+ Rc<DxvkBufferView> GetBufferView() const {
+ return m_bufferView;
+ }
+
+ Rc<DxvkImageView> GetImageView() const {
+ return m_imageView;
+ }
+
+ D3D10ShaderResourceView* GetD3D10Iface() {
+ return &m_d3d10;
+ }
+
+ static HRESULT GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
+
+ static D3D11_SHADER_RESOURCE_VIEW_DESC1 PromoteDesc(
+ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
+ UINT Plane);
+
+ static HRESULT NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
+
+ static UINT GetPlaneSlice(
+ const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11_SHADER_RESOURCE_VIEW_DESC1 m_desc;
+ D3D11_VK_VIEW_INFO m_info;
+ Rc<DxvkBufferView> m_bufferView;
+ Rc<DxvkImageView> m_imageView;
+ D3D10ShaderResourceView m_d3d10;
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.cpp
new file mode 100644
index 00000000..54f826e7
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.cpp
@@ -0,0 +1,447 @@
+#include "d3d11_device.h"
+#include "d3d11_buffer.h"
+#include "d3d11_resource.h"
+#include "d3d11_texture.h"
+#include "d3d11_view_uav.h"
+
+namespace dxvk {
+
+ D3D11UnorderedAccessView::D3D11UnorderedAccessView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc)
+ : D3D11DeviceChild<ID3D11UnorderedAccessView1>(pDevice),
+ m_resource(pResource), m_desc(*pDesc) {
+ ResourceAddRefPrivate(m_resource);
+
+ D3D11_COMMON_RESOURCE_DESC resourceDesc;
+ GetCommonResourceDesc(pResource, &resourceDesc);
+
+ // Basic view resource info
+ m_info.pResource = pResource;
+ m_info.Dimension = resourceDesc.Dim;
+ m_info.BindFlags = resourceDesc.BindFlags;
+
+ if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
+ auto buffer = static_cast<D3D11Buffer*>(pResource);
+
+ DxvkBufferViewCreateInfo viewInfo;
+
+ if (pDesc->Buffer.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
+ viewInfo.format = VK_FORMAT_R32_UINT;
+ viewInfo.rangeOffset = sizeof(uint32_t) * pDesc->Buffer.FirstElement;
+ viewInfo.rangeLength = sizeof(uint32_t) * pDesc->Buffer.NumElements;
+ } else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) {
+ viewInfo.format = VK_FORMAT_R32_UINT;
+ viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * pDesc->Buffer.FirstElement;
+ viewInfo.rangeLength = buffer->Desc()->StructureByteStride * pDesc->Buffer.NumElements;
+ } else {
+ viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
+
+ const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format);
+ viewInfo.rangeOffset = formatInfo->elementSize * pDesc->Buffer.FirstElement;
+ viewInfo.rangeLength = formatInfo->elementSize * pDesc->Buffer.NumElements;
+ }
+
+ if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
+ m_counterBuffer = CreateCounterBuffer();
+
+ // Populate view info struct
+ m_info.Buffer.Offset = viewInfo.rangeOffset;
+ m_info.Buffer.Length = viewInfo.rangeLength;
+
+ m_bufferView = pDevice->GetDXVKDevice()->createBufferView(
+ buffer->GetBuffer(), viewInfo);
+ } else {
+ auto texture = GetCommonTexture(pResource);
+ auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode());
+
+ DxvkImageViewCreateInfo viewInfo;
+ viewInfo.format = formatInfo.Format;
+ viewInfo.aspect = formatInfo.Aspect;
+ viewInfo.swizzle = formatInfo.Swizzle;
+ viewInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_UAV_DIMENSION_TEXTURE1D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
+ viewInfo.minLevel = pDesc->Texture1D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture1DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture1DArray.ArraySize;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.minLevel = pDesc->Texture2D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ viewInfo.minLevel = pDesc->Texture2DArray.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice;
+ viewInfo.numLayers = pDesc->Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE3D:
+ // FIXME we actually have to map this to a
+ // 2D array view in order to support W slices
+ viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
+ viewInfo.minLevel = pDesc->Texture3D.MipSlice;
+ viewInfo.numLevels = 1;
+ viewInfo.minLayer = 0;
+ viewInfo.numLayers = 1;
+ break;
+
+ default:
+ throw DxvkError("D3D11: Invalid view dimension for image UAV");
+ }
+
+ if (texture->GetPlaneCount() > 1)
+ viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc));
+
+ // Populate view info struct
+ m_info.Image.Aspects = viewInfo.aspect;
+ m_info.Image.MinLevel = viewInfo.minLevel;
+ m_info.Image.MinLayer = viewInfo.minLayer;
+ m_info.Image.NumLevels = viewInfo.numLevels;
+ m_info.Image.NumLayers = viewInfo.numLayers;
+
+ m_imageView = pDevice->GetDXVKDevice()->createImageView(
+ GetCommonTexture(pResource)->GetImage(), viewInfo);
+ }
+ }
+
+
+ D3D11UnorderedAccessView::~D3D11UnorderedAccessView() {
+ ResourceReleasePrivate(m_resource);
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11UnorderedAccessView::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11View)
+ || riid == __uuidof(ID3D11UnorderedAccessView)
+ || riid == __uuidof(ID3D11UnorderedAccessView1)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11UnorderedAccessView::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetResource(ID3D11Resource** ppResource) {
+ *ppResource = ref(m_resource);
+ }
+
+
+ void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetDesc(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) {
+ pDesc->Format = m_desc.Format;
+ pDesc->ViewDimension = m_desc.ViewDimension;
+
+ switch (m_desc.ViewDimension) {
+ case D3D11_UAV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_UAV_DIMENSION_BUFFER:
+ pDesc->Buffer = m_desc.Buffer;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1D:
+ pDesc->Texture1D = m_desc.Texture1D;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
+ pDesc->Texture1DArray = m_desc.Texture1DArray;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ pDesc->Texture2D.MipSlice = m_desc.Texture2D.MipSlice;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ pDesc->Texture2DArray.MipSlice = m_desc.Texture2DArray.MipSlice;
+ pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice;
+ pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE3D:
+ pDesc->Texture3D = m_desc.Texture3D;
+ break;
+ }
+ }
+
+
+ void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetDesc1(D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11UnorderedAccessView::GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: {
+ D3D11_BUFFER_DESC bufferDesc;
+ static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
+
+ if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ pDesc->Buffer.FirstElement = 0;
+ pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride;
+ pDesc->Buffer.Flags = 0;
+ return S_OK;
+ }
+ } return E_INVALIDARG;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
+ pDesc->Texture1D.MipSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY;
+ pDesc->Texture1DArray.MipSlice = 0;
+ pDesc->Texture1DArray.FirstArraySlice = 0;
+ pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+
+ if (resourceDesc.ArraySize == 1) {
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+ pDesc->Texture2D.MipSlice = 0;
+ pDesc->Texture2D.PlaneSlice = 0;
+ } else {
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ pDesc->Texture2DArray.MipSlice = 0;
+ pDesc->Texture2DArray.FirstArraySlice = 0;
+ pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
+ pDesc->Texture2DArray.PlaneSlice = 0;
+ }
+ } return S_OK;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ pDesc->Format = resourceDesc.Format;
+ pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
+ pDesc->Texture3D.MipSlice = 0;
+ pDesc->Texture3D.WSize = resourceDesc.Depth;
+ } return S_OK;
+
+ default:
+ Logger::err(str::format(
+ "D3D11: Unsupported dimension for unordered access view: ",
+ resourceDim));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 D3D11UnorderedAccessView::PromoteDesc(
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ UINT Plane) {
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 dstDesc;
+ dstDesc.Format = pDesc->Format;
+ dstDesc.ViewDimension = pDesc->ViewDimension;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_UAV_DIMENSION_UNKNOWN:
+ break;
+
+ case D3D11_UAV_DIMENSION_BUFFER:
+ dstDesc.Buffer = pDesc->Buffer;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1D:
+ dstDesc.Texture1D = pDesc->Texture1D;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
+ dstDesc.Texture1DArray = pDesc->Texture1DArray;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ dstDesc.Texture2D.MipSlice = pDesc->Texture2D.MipSlice;
+ dstDesc.Texture2D.PlaneSlice = Plane;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ dstDesc.Texture2DArray.MipSlice = pDesc->Texture2DArray.MipSlice;
+ dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice;
+ dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize;
+ dstDesc.Texture2DArray.PlaneSlice = Plane;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE3D:
+ dstDesc.Texture3D = pDesc->Texture3D;
+ break;
+ }
+
+ return dstDesc;
+ }
+
+
+ HRESULT D3D11UnorderedAccessView::NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) {
+ D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&resourceDim);
+
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ uint32_t numLayers = 0;
+
+ switch (resourceDim) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER: {
+ if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_BUFFER) {
+ Logger::err("D3D11: Incompatible view dimension for Buffer");
+ return E_INVALIDARG;
+ }
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
+ D3D11_TEXTURE1D_DESC resourceDesc;
+ static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1D
+ && pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1DARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture1D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
+ D3D11_TEXTURE2D_DESC resourceDesc;
+ static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2D
+ && pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2DARRAY) {
+ Logger::err("D3D11: Incompatible view dimension for Texture2D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = resourceDesc.ArraySize;
+ } break;
+
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
+ D3D11_TEXTURE3D_DESC resourceDesc;
+ static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
+
+ if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE3D) {
+ Logger::err("D3D11: Incompatible view dimension for Texture3D");
+ return E_INVALIDARG;
+ }
+
+ format = resourceDesc.Format;
+ numLayers = std::max(resourceDesc.Depth >> pDesc->Texture3D.MipSlice, 1u);
+ } break;
+
+ default:
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
+ pDesc->Format = format;
+
+ switch (pDesc->ViewDimension) {
+ case D3D11_UAV_DIMENSION_BUFFER:
+ if (pDesc->Buffer.NumElements == 0)
+ return E_INVALIDARG;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
+ if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice)
+ pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice)
+ pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_UAV_DIMENSION_TEXTURE3D:
+ if (pDesc->Texture3D.WSize > numLayers - pDesc->Texture3D.FirstWSlice)
+ pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice;
+ break;
+
+ default:
+ break;
+ }
+
+ return S_OK;
+ }
+
+
+ UINT D3D11UnorderedAccessView::GetPlaneSlice(const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) {
+ switch (pDesc->ViewDimension) {
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ return pDesc->Texture2D.PlaneSlice;
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ return pDesc->Texture2DArray.PlaneSlice;
+ default:
+ return 0;
+ }
+ }
+
+
+ Rc<DxvkBuffer> D3D11UnorderedAccessView::CreateCounterBuffer() {
+ Rc<DxvkDevice> device = m_parent->GetDXVKDevice();
+
+ DxvkBufferCreateInfo info;
+ info.size = sizeof(uint32_t);
+ info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
+ | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+ | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
+ | device->getShaderPipelineStages();
+ info.access = VK_ACCESS_TRANSFER_WRITE_BIT
+ | VK_ACCESS_TRANSFER_READ_BIT
+ | VK_ACCESS_SHADER_WRITE_BIT
+ | VK_ACCESS_SHADER_READ_BIT;
+ return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ }
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.h b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.h
new file mode 100644
index 00000000..3076fe09
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_view_uav.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "../dxvk/dxvk_device.h"
+
+#include "d3d11_device_child.h"
+#include "d3d11_view.h"
+
+namespace dxvk {
+
+ class D3D11Device;
+
+ /**
+ * \brief Unordered access view
+ *
+ * Unordered access views are special in that they can
+ * have counters, which can be used inside shaders to
+ * atomically append or consume structures.
+ */
+ class D3D11UnorderedAccessView : public D3D11DeviceChild<ID3D11UnorderedAccessView1> {
+
+ public:
+
+ D3D11UnorderedAccessView(
+ D3D11Device* pDevice,
+ ID3D11Resource* pResource,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc);
+
+ ~D3D11UnorderedAccessView();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final;
+
+ void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final;
+
+ void STDMETHODCALLTYPE GetDesc(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) final;
+
+ void STDMETHODCALLTYPE GetDesc1(D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) final;
+
+ const D3D11_VK_VIEW_INFO& GetViewInfo() const {
+ return m_info;
+ }
+
+ BOOL HasBindFlag(UINT Flags) const {
+ return m_info.BindFlags & Flags;
+ }
+
+ D3D11_RESOURCE_DIMENSION GetResourceType() const {
+ D3D11_RESOURCE_DIMENSION type;
+ m_resource->GetType(&type);
+ return type;
+ }
+
+ Rc<DxvkBufferView> GetBufferView() const {
+ return m_bufferView;
+ }
+
+ Rc<DxvkImageView> GetImageView() const {
+ return m_imageView;
+ }
+
+ DxvkBufferSlice GetCounterSlice() const {
+ return m_counterBuffer != nullptr
+ ? DxvkBufferSlice(m_counterBuffer)
+ : DxvkBufferSlice();
+ }
+
+ static HRESULT GetDescFromResource(
+ ID3D11Resource* pResource,
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc);
+
+ static D3D11_UNORDERED_ACCESS_VIEW_DESC1 PromoteDesc(
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
+ UINT Plane);
+
+ static HRESULT NormalizeDesc(
+ ID3D11Resource* pResource,
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc);
+
+ static UINT GetPlaneSlice(
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc);
+
+ private:
+
+ ID3D11Resource* m_resource;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 m_desc;
+ D3D11_VK_VIEW_INFO m_info;
+ Rc<DxvkBufferView> m_bufferView;
+ Rc<DxvkImageView> m_imageView;
+ Rc<DxvkBuffer> m_counterBuffer;
+
+ Rc<DxvkBuffer> CreateCounterBuffer();
+
+ };
+
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/meson.build b/src/libs/dxvk-native-1.9.2a/src/d3d11/meson.build
new file mode 100644
index 00000000..ded034c9
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/meson.build
@@ -0,0 +1,88 @@
+d3d11_res = wrc_generator.process('version.rc')
+
+dxgi_common_src = [
+ '../dxgi/dxgi_format.cpp',
+ '../dxgi/dxgi_monitor.cpp',
+ '../dxgi/dxgi_swapchain.cpp',
+]
+
+d3d10_src = [
+ '../d3d10/d3d10_blend.cpp',
+ '../d3d10/d3d10_buffer.cpp',
+ '../d3d10/d3d10_depth_stencil.cpp',
+ '../d3d10/d3d10_device.cpp',
+ '../d3d10/d3d10_input_layout.cpp',
+ '../d3d10/d3d10_multithread.cpp',
+ '../d3d10/d3d10_query.cpp',
+ '../d3d10/d3d10_rasterizer.cpp',
+ '../d3d10/d3d10_sampler.cpp',
+ '../d3d10/d3d10_texture.cpp',
+ '../d3d10/d3d10_util.cpp',
+ '../d3d10/d3d10_view_dsv.cpp',
+ '../d3d10/d3d10_view_rtv.cpp',
+ '../d3d10/d3d10_view_srv.cpp',
+]
+
+d3d11_src = [
+ 'd3d11_annotation.cpp',
+ 'd3d11_blend.cpp',
+ 'd3d11_buffer.cpp',
+ 'd3d11_class_linkage.cpp',
+ 'd3d11_cmdlist.cpp',
+ 'd3d11_context.cpp',
+ 'd3d11_context_def.cpp',
+ 'd3d11_context_ext.cpp',
+ 'd3d11_context_imm.cpp',
+ 'd3d11_cuda.cpp',
+ 'd3d11_depth_stencil.cpp',
+ 'd3d11_device.cpp',
+ 'd3d11_enums.cpp',
+ 'd3d11_initializer.cpp',
+ 'd3d11_input_layout.cpp',
+ 'd3d11_interop.cpp',
+ 'd3d11_main.cpp',
+ 'd3d11_options.cpp',
+ 'd3d11_query.cpp',
+ 'd3d11_rasterizer.cpp',
+ 'd3d11_resource.cpp',
+ 'd3d11_sampler.cpp',
+ 'd3d11_shader.cpp',
+ 'd3d11_state.cpp',
+ 'd3d11_state_object.cpp',
+ 'd3d11_swapchain.cpp',
+ 'd3d11_texture.cpp',
+ 'd3d11_util.cpp',
+ 'd3d11_video.cpp',
+ 'd3d11_view_dsv.cpp',
+ 'd3d11_view_rtv.cpp',
+ 'd3d11_view_srv.cpp',
+ 'd3d11_view_uav.cpp',
+]
+
+d3d11_shaders = files([
+ 'shaders/d3d11_video_blit_frag.frag',
+ 'shaders/d3d11_video_blit_vert.vert',
+])
+
+if not dxvk_native
+ # We don't want to allow GDI interop on *any* native builds
+ # because the idea is for you to write once and run anywhere.
+ d3d11_src += 'd3d11_gdi.cpp'
+endif
+
+if dxvk_native
+ lib_dxgi = dxgi_dep
+endif
+
+d3d11_dll = shared_library(so_prefix+'d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src,
+ glsl_generator.process(d3d11_shaders), d3d11_res,
+ name_prefix : '',
+ dependencies : [ lib_dxgi, dxbc_dep, dxvk_dep, wsi_dep ],
+ include_directories : dxvk_include_path,
+ install : true,
+ vs_module_defs : 'd3d11'+def_spec_ext,
+ override_options : ['cpp_std='+dxvk_cpp_std])
+
+d3d11_dep = declare_dependency(
+ link_with : [ d3d11_dll ],
+ include_directories : [ dxvk_include_path ])
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_frag.frag b/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_frag.frag
new file mode 100644
index 00000000..d659176c
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_frag.frag
@@ -0,0 +1,56 @@
+#version 450
+
+layout(constant_id = 3) const bool c_planar = true;
+
+// Can't use matrix types here since even a two-row
+// matrix will be padded to 16 bytes per column for
+// absolutely no reason
+layout(std140, set = 0, binding = 0)
+uniform ubo_t {
+ vec4 color_matrix_r1;
+ vec4 color_matrix_r2;
+ vec4 color_matrix_r3;
+ vec2 coord_matrix_c1;
+ vec2 coord_matrix_c2;
+ vec2 coord_matrix_c3;
+ float y_min;
+ float y_max;
+};
+
+layout(location = 0) in vec2 i_texcoord;
+layout(location = 0) out vec4 o_color;
+
+layout(set = 0, binding = 1) uniform sampler s_sampler;
+layout(set = 0, binding = 2) uniform texture2D s_inputY;
+layout(set = 0, binding = 3) uniform texture2D s_inputCbCr;
+
+void main() {
+ // Transform input texture coordinates to
+ // account for rotation and source rectangle
+ mat3x2 coord_matrix = mat3x2(
+ coord_matrix_c1,
+ coord_matrix_c2,
+ coord_matrix_c3);
+
+ vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f);
+
+ // Fetch source image color
+ vec4 color = vec4(0.0f, 0.0f, 0.0f, 1.0f);
+
+ if (c_planar) {
+ color.g = texture(sampler2D(s_inputY, s_sampler), coord).r;
+ color.rb = texture(sampler2D(s_inputCbCr, s_sampler), coord).gr;
+ color.g = clamp((color.g - y_min) / (y_max - y_min), 0.0f, 1.0f);
+ } else {
+ color = texture(sampler2D(s_inputY, s_sampler), coord);
+ }
+
+ // Color space transformation
+ mat3x4 color_matrix = mat3x4(
+ color_matrix_r1,
+ color_matrix_r2,
+ color_matrix_r3);
+
+ o_color.rgb = vec4(color.rgb, 1.0f) * color_matrix;
+ o_color.a = color.a;
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_vert.vert b/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_vert.vert
new file mode 100644
index 00000000..1980b3c9
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/shaders/d3d11_video_blit_vert.vert
@@ -0,0 +1,12 @@
+#version 450
+
+layout(location = 0) out vec2 o_texcoord;
+
+void main() {
+ vec2 coord = vec2(
+ float(gl_VertexIndex & 1) * 2.0f,
+ float(gl_VertexIndex & 2));
+
+ o_texcoord = coord;
+ gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f);
+}
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/version.rc b/src/libs/dxvk-native-1.9.2a/src/d3d11/version.rc
new file mode 100644
index 00000000..060ef7bc
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/version.rc
@@ -0,0 +1,32 @@
+#include <windows.h>
+
+// DLL version information.
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 10,0,17763,1
+PRODUCTVERSION 10,0,17763,1
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEFLAGS 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "080904b0"
+ BEGIN
+ VALUE "CompanyName", "DXVK"
+ VALUE "FileDescription", "Direct3D 11 Runtime"
+ VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)"
+ VALUE "InternalName", "D3D11.dll"
+ VALUE "LegalCopyright", "zlib/libpng license"
+ VALUE "OriginalFilename", "D3D11.dll"
+ VALUE "ProductName", "DXVK"
+ VALUE "ProductVersion", "10.0.17763.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0809, 1200
+ END
+END
+