From 116edcb77a4114e5a00dfdfc12345fee8d0ea408 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 5 Mar 2017 12:26:46 +0100 Subject: [PATCH] Take the D3D11 feature level into account when creating shaders. May help #9369 --- GPU/D3D11/D3D11Util.cpp | 21 +++++++++++++-------- GPU/D3D11/D3D11Util.h | 8 ++++---- GPU/D3D11/DepalettizeShaderD3D11.cpp | 10 ++++++---- GPU/D3D11/DepalettizeShaderD3D11.h | 5 ++++- GPU/D3D11/FramebufferManagerD3D11.cpp | 9 +++++---- GPU/D3D11/FramebufferManagerD3D11.h | 1 + GPU/D3D11/GPU_D3D11.cpp | 5 +++-- GPU/D3D11/ShaderManagerD3D11.cpp | 16 ++++++++-------- GPU/D3D11/ShaderManagerD3D11.h | 7 ++++--- GPU/D3D11/StencilBufferD3D11.cpp | 4 ++-- ext/native/thin3d/thin3d.h | 1 + ext/native/thin3d/thin3d_d3d11.cpp | 2 ++ 12 files changed, 53 insertions(+), 36 deletions(-) diff --git a/GPU/D3D11/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index c14281242c..01cc7f52b2 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -37,8 +37,9 @@ static std::vector CompileShaderToBytecode(const char *code, size_t cod return std::vector(); } -ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut, UINT flags) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "vs_5_0", flags); +ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut, D3D_FEATURE_LEVEL featureLevel, UINT flags) { + const char *profile = featureLevel <= D3D_FEATURE_LEVEL_9_3 ? "vs_4_0_level_9_1" : "vs_4_0"; + std::vector byteCode = CompileShaderToBytecode(code, codeSize, profile, flags); if (byteCode.empty()) return nullptr; @@ -49,8 +50,9 @@ ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *co return vs; } -ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "ps_5_0", flags); +ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags) { + const char *profile = featureLevel <= D3D_FEATURE_LEVEL_9_3 ? "ps_4_0_level_9_1" : "ps_4_0"; + std::vector byteCode = CompileShaderToBytecode(code, codeSize, profile, flags); if (byteCode.empty()) return nullptr; @@ -59,8 +61,10 @@ ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code return ps; } -ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "cs_5_0", flags); +ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags) { + if (featureLevel <= D3D_FEATURE_LEVEL_9_3) + return nullptr; + std::vector byteCode = CompileShaderToBytecode(code, codeSize, "cs_4_0", flags); if (byteCode.empty()) return nullptr; @@ -69,7 +73,9 @@ ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char * return cs; } -ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { +ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags) { + if (featureLevel <= D3D_FEATURE_LEVEL_9_3) + return nullptr; std::vector byteCode = CompileShaderToBytecode(code, codeSize, "gs_5_0", flags); if (byteCode.empty()) return nullptr; @@ -79,7 +85,6 @@ ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char return gs; } - void StockObjectsD3D11::Create(ID3D11Device *device) { D3D11_BLEND_DESC blend_desc{}; blend_desc.RenderTarget[0].BlendEnable = false; diff --git a/GPU/D3D11/D3D11Util.h b/GPU/D3D11/D3D11Util.h index c9f3ad5566..3184053bcd 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -64,10 +64,10 @@ private: bool nextMapDiscard_ = false; }; -ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut, UINT flags = 0); -ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags = 0); -ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags = 0); -ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags = 0); +ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut, D3D_FEATURE_LEVEL featureLevel, UINT flags = 0); +ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags = 0); +ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags = 0); +ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags = 0); class StockObjectsD3D11 { public: diff --git a/GPU/D3D11/DepalettizeShaderD3D11.cpp b/GPU/D3D11/DepalettizeShaderD3D11.cpp index 313c20a039..f0833cdfd5 100644 --- a/GPU/D3D11/DepalettizeShaderD3D11.cpp +++ b/GPU/D3D11/DepalettizeShaderD3D11.cpp @@ -54,11 +54,13 @@ static const D3D11_INPUT_ELEMENT_DESC g_DepalVertexElements[] = { { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, }, }; -DepalShaderCacheD3D11::DepalShaderCacheD3D11(ID3D11Device *device, ID3D11DeviceContext *context) - : device_(device), context_(context) { +DepalShaderCacheD3D11::DepalShaderCacheD3D11(Draw::DrawContext *draw) { std::string errorMessage; std::vector vsByteCode; - vertexShader_ = CreateVertexShaderD3D11(device, depalVShaderHLSL, strlen(depalVShaderHLSL), &vsByteCode); + device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); + context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + featureLevel_ = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); + vertexShader_ = CreateVertexShaderD3D11(device_, depalVShaderHLSL, strlen(depalVShaderHLSL), &vsByteCode, featureLevel_); ASSERT_SUCCESS(device_->CreateInputLayout(g_DepalVertexElements, ARRAY_SIZE(g_DepalVertexElements), vsByteCode.data(), vsByteCode.size(), &inputLayout_)); } @@ -144,7 +146,7 @@ ID3D11PixelShader *DepalShaderCacheD3D11::GetDepalettizePixelShader(GEPaletteFor GenerateDepalShader(buffer, pixelFormat, HLSL_D3D11); - ID3D11PixelShader *pshader = CreatePixelShaderD3D11(device_, buffer, strlen(buffer)); + ID3D11PixelShader *pshader = CreatePixelShaderD3D11(device_, buffer, strlen(buffer), featureLevel_); if (!pshader) { ERROR_LOG(G3D, "Failed to compile depal pixel shader"); diff --git a/GPU/D3D11/DepalettizeShaderD3D11.h b/GPU/D3D11/DepalettizeShaderD3D11.h index 5d3db8aac1..7fdc0a620c 100644 --- a/GPU/D3D11/DepalettizeShaderD3D11.h +++ b/GPU/D3D11/DepalettizeShaderD3D11.h @@ -19,8 +19,10 @@ #include #include #include + #include "Common/CommonTypes.h" #include "GPU/ge_constants.h" +#include "thin3d/thin3d.h" class DepalShaderD3D11 { public: @@ -43,7 +45,7 @@ public: // Caches both shaders and palette textures. class DepalShaderCacheD3D11 { public: - DepalShaderCacheD3D11(ID3D11Device *device, ID3D11DeviceContext *context); + DepalShaderCacheD3D11(Draw::DrawContext *draw); ~DepalShaderCacheD3D11(); // This also uploads the palette and binds the correct texture. @@ -59,6 +61,7 @@ private: ID3D11Device *device_; ID3D11DeviceContext *context_; + D3D_FEATURE_LEVEL featureLevel_; ID3D11VertexShader *vertexShader_ = nullptr; ID3D11InputLayout *inputLayout_ = nullptr; diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 20316dd365..3b7a4eff5f 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -98,12 +98,13 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + featureLevel_ = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); std::vector bytecode; std::string errorMsg; - quadVertexShader_ = CreateVertexShaderD3D11(device_, vscode, strlen(vscode), &bytecode); - quadPixelShader_ = CreatePixelShaderD3D11(device_, pscode, strlen(pscode)); + quadVertexShader_ = CreateVertexShaderD3D11(device_, vscode, strlen(vscode), &bytecode, featureLevel_); + quadPixelShader_ = CreatePixelShaderD3D11(device_, pscode, strlen(pscode), featureLevel_); ASSERT_SUCCESS(device_->CreateInputLayout(g_QuadVertexElements, ARRAY_SIZE(g_QuadVertexElements), bytecode.data(), bytecode.size(), &quadInputLayout_)); // STRIP geometry @@ -271,11 +272,11 @@ void FramebufferManagerD3D11::CompilePostShader() { UINT flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; std::vector byteCode; - postVertexShader_ = CreateVertexShaderD3D11(device_, vsSource.data(), vsSource.size(), &byteCode, flags); + postVertexShader_ = CreateVertexShaderD3D11(device_, vsSource.data(), vsSource.size(), &byteCode, featureLevel_, flags); if (!postVertexShader_) { return; } - postPixelShader_ = CreatePixelShaderD3D11(device_, psSource.data(), psSource.size(), flags); + postPixelShader_ = CreatePixelShaderD3D11(device_, psSource.data(), psSource.size(), featureLevel_, flags); if (!postPixelShader_) { postVertexShader_->Release(); return; diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 56c9014cda..68694f9058 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -108,6 +108,7 @@ private: ID3D11Device *device_; ID3D11DeviceContext *context_; + D3D_FEATURE_LEVEL featureLevel_; // Used by DrawPixels ID3D11Texture2D *drawPixelsTex_ = nullptr; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 7a83acfeea..3e7cc45a54 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -415,18 +415,19 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT)) { device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + D3D_FEATURE_LEVEL featureLevel = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); lastVsync_ = g_Config.bVSync ? 1 : 0; stockD3D11.Create(device_); - shaderManagerD3D11_ = new ShaderManagerD3D11(device_, context_); + shaderManagerD3D11_ = new ShaderManagerD3D11(device_, context_, featureLevel); framebufferManagerD3D11_ = new FramebufferManagerD3D11(draw); framebufferManager_ = framebufferManagerD3D11_; textureCacheD3D11_ = new TextureCacheD3D11(draw); textureCache_ = textureCacheD3D11_; drawEngineCommon_ = &drawEngine_; shaderManager_ = shaderManagerD3D11_; - depalShaderCache_ = new DepalShaderCacheD3D11(device_, context_); + depalShaderCache_ = new DepalShaderCacheD3D11(draw); drawEngine_.SetShaderManager(shaderManagerD3D11_); drawEngine_.SetTextureCache(textureCacheD3D11_); drawEngine_.SetFramebufferManager(framebufferManagerD3D11_); diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 5ae80f0000..34fd80bac5 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -38,11 +38,11 @@ #include "GPU/D3D11/VertexShaderGeneratorD3D11.h" #include "GPU/D3D11/D3D11Util.h" -D3D11FragmentShader::D3D11FragmentShader(ID3D11Device *device, ShaderID id, const char *code, bool useHWTransform) +D3D11FragmentShader::D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, bool useHWTransform) : device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(0) { source_ = code; - module_ = CreatePixelShaderD3D11(device, code, strlen(code)); + module_ = CreatePixelShaderD3D11(device, code, strlen(code), featureLevel); if (!module_) failed_ = true; } @@ -63,11 +63,11 @@ std::string D3D11FragmentShader::GetShaderString(DebugShaderStringType type) con } } -D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting) +D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting) : device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(nullptr), usesLighting_(usesLighting) { source_ = code; - module_ = CreateVertexShaderD3D11(device, code, strlen(code), &bytecode_); + module_ = CreateVertexShaderD3D11(device, code, strlen(code), &bytecode_, featureLevel); if (!module_) failed_ = true; } @@ -88,8 +88,8 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const } } -ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context) - : device_(device), context_(context), lastVShader_(nullptr), lastFShader_(nullptr) { +ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel) + : device_(device), context_(context), featureLevel_(featureLevel_), lastVShader_(nullptr), lastFShader_(nullptr) { codeBuffer_ = new char[16384]; memset(&ub_base, 0, sizeof(ub_base)); memset(&ub_lights, 0, sizeof(ub_lights)); @@ -201,7 +201,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** // Vertex shader not in cache. Let's compile it. bool usesLighting; GenerateVertexShaderD3D11(VSID, codeBuffer_, &usesLighting); - vs = new D3D11VertexShader(device_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); + vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); vsCache_[VSID] = vs; } else { vs = vsIter->second; @@ -213,7 +213,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader ** if (fsIter == fsCache_.end()) { // Fragment shader not in cache. Let's compile it. GenerateFragmentShaderD3D11(FSID, codeBuffer_); - fs = new D3D11FragmentShader(device_, FSID, codeBuffer_, useHWTransform); + fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform); fsCache_[FSID] = fs; } else { fs = fsIter->second; diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index e2a22af823..5b891d8289 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -35,7 +35,7 @@ class D3D11PushBuffer; class D3D11FragmentShader { public: - D3D11FragmentShader(ID3D11Device *device, ShaderID id, const char *code, bool useHWTransform); + D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, bool useHWTransform); ~D3D11FragmentShader(); const std::string &source() const { return source_; } @@ -58,7 +58,7 @@ protected: class D3D11VertexShader { public: - D3D11VertexShader(ID3D11Device *device, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting); + D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting); ~D3D11VertexShader(); const std::string &source() const { return source_; } @@ -92,7 +92,7 @@ class D3D11PushBuffer; class ShaderManagerD3D11 : public ShaderManagerCommon { public: - ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context); + ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel); ~ShaderManagerD3D11(); void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform); @@ -126,6 +126,7 @@ private: ID3D11Device *device_; ID3D11DeviceContext *context_; + D3D_FEATURE_LEVEL featureLevel_; typedef std::map FSCache; FSCache fsCache_; diff --git a/GPU/D3D11/StencilBufferD3D11.cpp b/GPU/D3D11/StencilBufferD3D11.cpp index 5c390ced25..65bf2644c9 100644 --- a/GPU/D3D11/StencilBufferD3D11.cpp +++ b/GPU/D3D11/StencilBufferD3D11.cpp @@ -169,12 +169,12 @@ bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, bool skipZ // TODO: Helper with logging? if (!stencilUploadPS_) { std::string errorMessage; - stencilUploadPS_ = CreatePixelShaderD3D11(device_, stencil_ps, strlen(stencil_ps)); + stencilUploadPS_ = CreatePixelShaderD3D11(device_, stencil_ps, strlen(stencil_ps), featureLevel_); } if (!stencilUploadVS_) { std::string errorMessage; std::vector byteCode; - stencilUploadVS_ = CreateVertexShaderD3D11(device_, stencil_vs, strlen(stencil_vs), &byteCode); + stencilUploadVS_ = CreateVertexShaderD3D11(device_, stencil_vs, strlen(stencil_vs), &byteCode, featureLevel_); ASSERT_SUCCESS(device_->CreateInputLayout(g_QuadVertexElements, 2, byteCode.data(), byteCode.size(), &stencilUploadInputLayout_)); } if (!stencilValueBuffer_) { diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index ca6e16a6c7..306810a7dd 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -319,6 +319,7 @@ enum class NativeObject { BACKBUFFER_DEPTH_VIEW, BACKBUFFER_COLOR_TEX, BACKBUFFER_DEPTH_TEX, + FEATURE_LEVEL, }; enum FBColorDepth { diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index 5d25cc683e..a260cbc419 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -133,6 +133,8 @@ public: return (uintptr_t)bbRenderTargetView_; case NativeObject::BACKBUFFER_DEPTH_VIEW: return (uintptr_t)bbDepthStencilView_; + case NativeObject::FEATURE_LEVEL: + return (uintptr_t)featureLevel_; default: return 0; }