From e7612c13da462efc05a5935572f3b0f9bedb6d87 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 16 Feb 2017 16:37:34 +0100 Subject: [PATCH] Initial work on post-shader translation for D3D11 --- GPU/Common/ShaderTranslation.cpp | 22 +++++-- GPU/Common/ShaderTranslation.h | 3 + GPU/D3D11/FramebufferManagerD3D11.cpp | 85 +++++++++++++++++++++++++-- GPU/D3D11/FramebufferManagerD3D11.h | 10 +++- ext/SPIRV-Cross.vcxproj | 2 - 5 files changed, 111 insertions(+), 11 deletions(-) diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index 706f43d86..92701da27 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -51,8 +51,15 @@ static EShLanguage GetLanguage(const Draw::ShaderStage stage) { } } +void ShaderTranslationInit() { + glslang::InitializeProcess(); +} +void ShaderTranslationShutdown() { + glslang::FinalizeProcess(); +} + bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShaderMetadata *destMetadata, std::string src, ShaderLanguage srcLang, Draw::ShaderStage stage, std::string *errorMessage) { - if (srcLang != GLSL_300) + if (srcLang != GLSL_300 && srcLang != GLSL_140) return false; glslang::TProgram program; @@ -62,15 +69,14 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade init_resources(Resources); // Enable SPIR-V and Vulkan rules when parsing GLSL - EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); + EShMessages messages = EShMessages::EShMsgDefault; // (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); EShLanguage shaderStage = GetLanguage(stage); glslang::TShader shader(shaderStage); shaderStrings[0] = src.c_str(); shader.setStrings(shaderStrings, 1); - - if (!shader.parse(&Resources, 100, false, messages)) { + if (!shader.parse(&Resources, 100, EProfile::ECompatibilityProfile, false, false, messages)) { ELOG("%s", shader.getInfoLog()); ELOG("%s", shader.getInfoDebugLog()); if (errorMessage) { @@ -116,6 +122,14 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade case HLSL_D3D11: { spirv_cross::CompilerHLSL hlsl(spirv); + spirv_cross::ShaderResources resources = hlsl.get_shader_resources(); + + int i = 0; + for (auto &resource : resources.sampled_images) { + // int location = hlsl.get_decoration(resource.id, spv::DecorationLocation); + hlsl.set_decoration(resource.id, spv::DecorationLocation, i); + i++; + } spirv_cross::CompilerHLSL::Options options{}; options.fixup_clipspace = true; options.shader_model = 50; diff --git a/GPU/Common/ShaderTranslation.h b/GPU/Common/ShaderTranslation.h index ae048c224..f382f4694 100644 --- a/GPU/Common/ShaderTranslation.h +++ b/GPU/Common/ShaderTranslation.h @@ -27,6 +27,9 @@ struct TranslatedShaderMetadata { }; +void ShaderTranslationInit(); +void ShaderTranslationShutdown(); + bool TranslateShader(std::string *dst, ShaderLanguage destLang, TranslatedShaderMetadata *destMetadata, std::string src, ShaderLanguage srcLang, Draw::ShaderStage stage, std::string *errorMessage); #endif \ No newline at end of file diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 6a0abae94..330dc3117 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -18,8 +18,11 @@ #include "math/lin/matrix4x4.h" #include "ext/native/thin3d/thin3d.h" #include "base/basictypes.h" +#include "file/vfs.h" +#include "file/zip_read.h" #include "Common/ColorConv.h" +#include "Common/MathUtil.h" #include "Core/Host.h" #include "Core/MemMap.h" #include "Core/Config.h" @@ -30,7 +33,9 @@ #include "GPU/Debugger/Stepping.h" #include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/ShaderTranslation.h" #include "GPU/Common/TextureDecoder.h" +#include "GPU/Common/PostShader.h" #include "GPU/D3D11/FramebufferManagerD3D11.h" #include "GPU/D3D11/ShaderManagerD3D11.h" #include "GPU/D3D11/TextureCacheD3D11.h" @@ -105,6 +110,13 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) vb.Usage = D3D11_USAGE_DYNAMIC; vb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; device_->CreateBuffer(&vb, nullptr, &quadBuffer_); + vb.ByteWidth = ROUND_UP(sizeof(PostShaderUniforms), 16); + vb.Usage = D3D11_USAGE_DYNAMIC; + device_->CreateBuffer(&vb, nullptr, &postConstants_); + + ShaderTranslationInit(); + + CompilePostShader(); D3D11_TEXTURE2D_DESC packDesc{}; packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; @@ -121,6 +133,8 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) FramebufferManagerD3D11::~FramebufferManagerD3D11() { packTexture_->Release(); + ShaderTranslationShutdown(); + // Drawing cleanup if (quadVertexShader_) quadVertexShader_->Release(); @@ -176,6 +190,59 @@ void FramebufferManagerD3D11::DisableState() { context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); } +void FramebufferManagerD3D11::CompilePostShader() { + usePostShader_ = false; + + SetNumExtraFBOs(0); + + std::string vsSource; + std::string psSource; + + const ShaderInfo *shaderInfo = 0; + if (g_Config.sPostShaderName == "Off") { + return; + } + + shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName); + if (shaderInfo) { + postShaderAtOutputResolution_ = shaderInfo->outputResolution; + size_t sz; + char *vs = (char *)VFSReadFile(shaderInfo->vertexShaderFile.c_str(), &sz); + if (!vs) + return; + char *ps = (char *)VFSReadFile(shaderInfo->fragmentShaderFile.c_str(), &sz); + if (!ps) { + free(vs); + return; + } + std::string vsSourceGLSL = vs; + std::string psSourceGLSL = ps; + free(vs); + free(ps); + TranslatedShaderMetadata metaVS, metaFS; + std::string errorVS, errorFS; + if (!TranslateShader(&vsSource, HLSL_D3D11, &metaVS, vsSourceGLSL, GLSL_140, Draw::ShaderStage::VERTEX, &errorVS)) + return; + if (!TranslateShader(&psSource, HLSL_D3D11, &metaFS, psSourceGLSL, GLSL_140, Draw::ShaderStage::FRAGMENT, &errorFS)) + return; + } else { + return; + } + + std::vector byteCode; + postVertexShader_ = CreateVertexShaderD3D11(device_, vsSource.data(), vsSource.size(), &byteCode); + if (!postVertexShader_) { + return; + } + postPixelShader_ = CreatePixelShaderD3D11(device_, psSource.data(), psSource.size()); + if (!postPixelShader_) { + postVertexShader_->Release(); + return; + } + device_->CreateInputLayout(g_QuadVertexElements, 2, byteCode.data(), byteCode.size(), &postInputLayout_); + usePostShader_ = true; +} + void FramebufferManagerD3D11::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { u8 *convBuf = NULL; @@ -334,10 +401,20 @@ void FramebufferManagerD3D11::Bind2DShader() { } void FramebufferManagerD3D11::BindPostShader(const PostShaderUniforms &uniforms) { - // TODO: Actually bind a post processing shader - context_->IASetInputLayout(quadInputLayout_); - context_->PSSetShader(quadPixelShader_, 0, 0); - context_->VSSetShader(quadVertexShader_, 0, 0); + if (!postPixelShader_) { + if (usePostShader_) { + CompilePostShader(); + } + if (!usePostShader_) { + context_->IASetInputLayout(quadInputLayout_); + context_->PSSetShader(quadPixelShader_, 0, 0); + context_->VSSetShader(quadVertexShader_, 0, 0); + return; + } + } + context_->IASetInputLayout(postInputLayout_); + context_->PSSetShader(postPixelShader_, 0, 0); + context_->VSSetShader(postVertexShader_, 0, 0); } void FramebufferManagerD3D11::RebindFramebuffer() { diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 469bad59c..4caf611c6 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -94,6 +94,7 @@ protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: + void CompilePostShader(); void BindPostShader(const PostShaderUniforms &uniforms) override; void Bind2DShader() override; void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; @@ -136,10 +137,17 @@ private: ShaderManagerD3D11 *shaderManagerD3D11_; DrawEngineD3D11 *drawEngine_; - // 1:1 Readback texture, 512x512 fixed + // Permanent 1:1 readback texture, 512x512 fixed // For larger debug readbacks, we create/destroy textures on the fly. ID3D11Texture2D *packTexture_; + // Used by post-processing shader + // Postprocessing + ID3D11VertexShader *postVertexShader_ = nullptr; + ID3D11PixelShader *postPixelShader_ = nullptr; + ID3D11InputLayout *postInputLayout_ = nullptr; + ID3D11Buffer *postConstants_ = nullptr; + // Used by post-processing shader std::vector extraFBOs_; diff --git a/ext/SPIRV-Cross.vcxproj b/ext/SPIRV-Cross.vcxproj index ff6a10c20..81a914672 100644 --- a/ext/SPIRV-Cross.vcxproj +++ b/ext/SPIRV-Cross.vcxproj @@ -36,7 +36,6 @@ StaticLibrary false v140_xp - true Unicode @@ -49,7 +48,6 @@ StaticLibrary false v140_xp - true Unicode