diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index 706f43d86590..fdf79d5c6835 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -19,6 +19,7 @@ #include #include +#include // DbgNew is not compatible with Glslang #ifdef DBG_NEW @@ -26,6 +27,8 @@ #endif #include "base/logging.h" +#include "base/basictypes.h" +#include "base/stringutil.h" #include "ShaderTranslation.h" #include "ext/glslang/SPIRV/GlslangToSpv.h" #include "thin3d/thin3d.h" @@ -51,8 +54,117 @@ static EShLanguage GetLanguage(const Draw::ShaderStage stage) { } } +void ShaderTranslationInit() { + glslang::InitializeProcess(); +} +void ShaderTranslationShutdown() { + glslang::FinalizeProcess(); +} + +std::string Preprocess(std::string code, ShaderLanguage lang, Draw::ShaderStage stage) { + // This takes GL up to the version we need. + return code; +} + +struct Builtin { + const char *needle; + const char *replacement; +}; + +// Workaround for deficiency in SPIRV-Cross +static const Builtin builtins[] = { + {"lessThan", + R"( + bool2 lessThan(float2 a, float2 b) { return bool2(a.x < b.x, a.y < b.y); } + bool3 lessThan(float3 a, float3 b) { return bool3(a.x < b.x, a.y < b.y, a.z < b.z); } + bool4 lessThan(float4 a, float4 b) { return bool4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w); } + )"}, + { "lessThanEqual", + R"( + bool2 lessThanEqual(float2 a, float2 b) { return bool2(a.x <= b.x, a.y <= b.y); } + bool3 lessThanEqual(float3 a, float3 b) { return bool3(a.x <= b.x, a.y <= b.y, a.z <= b.z); } + bool4 lessThanEqual(float4 a, float4 b) { return bool4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w); } + )" }, + { "greaterThan", + R"( + bool2 greaterThan(float2 a, float2 b) { return bool2(a.x > b.x, a.y > b.y); } + bool3 greaterThan(float3 a, float3 b) { return bool3(a.x > b.x, a.y > b.y, a.z > b.z); } + bool4 greaterThan(float4 a, float4 b) { return bool4(a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w); } + )" }, + { "greaterThanEqual", + R"( + bool2 greaterThanEqual(float2 a, float2 b) { return bool2(a.x >= b.x, a.y >= b.y); } + bool3 greaterThanEqual(float3 a, float3 b) { return bool3(a.x >= b.x, a.y >= b.y, a.z >= b.z); } + bool4 greaterThanEqual(float4 a, float4 b) { return bool4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w); } + )" }, + { "equal", + R"( + bool2 equal(float2 a, float2 b) { return bool2(a.x == b.x, a.y == b.y); } + bool3 equal(float3 a, float3 b) { return bool3(a.x == b.x, a.y == b.y, a.z == b.z); } + bool4 equal(float4 a, float4 b) { return bool4(a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w); } + )" }, + { "notEqual", + R"( + bool2 notEqual(float2 a, float2 b) { return bool2(a.x != b.x, a.y != b.y); } + bool3 notEqual(float3 a, float3 b) { return bool3(a.x != b.x, a.y != b.y, a.z != b.z); } + bool4 notEqual(float4 a, float4 b) { return bool4(a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w); } + )" }, +}; + +static const Builtin replacements[] = { + { "mix(", "lerp(" }, + { "fract(", "frac(" }, +}; + +static const char *cbufferDecl = R"( +cbuffer data : register(b0) { + float2 u_texelDelta; + float2 u_pixelDelta; + float4 u_time; +}; +)"; + +// SPIRV-Cross' HLSL output has some deficiencies we need to work around. +// Also we need to rip out single uniforms and replace them with blocks. +// Should probably do it in the source shader instead and then back translate to old style GLSL, but +// SPIRV-Cross currently won't compile with the Android NDK so I can't be bothered. +std::string Postprocess(std::string code, ShaderLanguage lang, Draw::ShaderStage stage) { + if (lang != HLSL_D3D11) + return code; + + std::stringstream out; + + // Output the uniform buffer. + out << cbufferDecl; + + // Add the builtins if required. + for (int i = 0; i < ARRAY_SIZE(builtins); i++) { + if (!builtins[i].needle) + continue; + if (code.find(builtins[i].needle) != std::string::npos) { + out << builtins[i].replacement; + } + } + + // Perform some replacements + for (int i = 0; i < ARRAY_SIZE(replacements); i++) { + code = ReplaceAll(code, replacements[i].needle, replacements[i].replacement); + } + + // Alright, now let's go through it line by line and zap the single uniforms. + std::string line; + std::stringstream instream(code); + while (std::getline(instream, line)) { + if (line.find("uniform float") != std::string::npos) + continue; + out << line << "\n"; + } + std::string output = out.str(); + return output; +} + 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 +174,16 @@ 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); + std::string preprocessed = Preprocess(src, srcLang, stage); + 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,11 +229,20 @@ 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; hlsl.set_options(options); - *dest = hlsl.compile(); + std::string raw = hlsl.compile(); + *dest = Postprocess(raw, destLang, stage); return true; } #endif diff --git a/GPU/Common/ShaderTranslation.h b/GPU/Common/ShaderTranslation.h index ae048c224a8a..f382f4694aff 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/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index af83807c70c2..35923a68c9da 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -9,10 +9,10 @@ #include "D3D11Util.h" -static std::vector CompileShaderToBytecode(const char *code, size_t codeSize, const char *target) { +static std::vector CompileShaderToBytecode(const char *code, size_t codeSize, const char *target, UINT flags) { ID3DBlob *compiledCode = nullptr; ID3DBlob *errorMsgs = nullptr; - HRESULT result = ptr_D3DCompile(code, codeSize, nullptr, nullptr, nullptr, "main", target, 0, 0, &compiledCode, &errorMsgs); + HRESULT result = ptr_D3DCompile(code, codeSize, nullptr, nullptr, nullptr, "main", target, flags, 0, &compiledCode, &errorMsgs); std::string errors; if (errorMsgs) { errors = std::string((const char *)errorMsgs->GetBufferPointer(), errorMsgs->GetBufferSize()); @@ -26,12 +26,11 @@ static std::vector CompileShaderToBytecode(const char *code, size_t cod compiledCode->Release(); return compiled; } - Crash(); return std::vector(); } -ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "vs_5_0"); +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); if (byteCode.empty()) return nullptr; @@ -42,8 +41,8 @@ ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *co return vs; } -ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "ps_5_0"); +ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { + std::vector byteCode = CompileShaderToBytecode(code, codeSize, "ps_5_0", flags); if (byteCode.empty()) return nullptr; @@ -52,8 +51,8 @@ ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code return ps; } -ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize) { - std::vector byteCode = CompileShaderToBytecode(code, codeSize, "cs_5_0"); +ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { + std::vector byteCode = CompileShaderToBytecode(code, codeSize, "cs_5_0", flags); if (byteCode.empty()) return nullptr; @@ -62,6 +61,17 @@ ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char * return cs; } +ID3D11GeometryShader *CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, UINT flags) { + std::vector byteCode = CompileShaderToBytecode(code, codeSize, "gs_5_0", flags); + if (byteCode.empty()) + return nullptr; + + ID3D11GeometryShader *gs; + device->CreateGeometryShader(byteCode.data(), byteCode.size(), nullptr, &gs); + 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 1329b1339918..2e0abcdeb67a 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -64,9 +64,10 @@ class PushBufferD3D11 { bool nextMapDiscard_ = false; }; -ID3D11VertexShader *CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut); -ID3D11PixelShader *CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize); -ID3D11ComputeShader *CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize); +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); class StockObjectsD3D11 { public: diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 1a273ad3d37b..25015fb0a1b7 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -15,11 +15,18 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include +#include + #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 "i18n/i18n.h" #include "Common/ColorConv.h" +#include "Common/MathUtil.h" #include "Core/Host.h" #include "Core/MemMap.h" #include "Core/Config.h" @@ -30,12 +37,16 @@ #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" #include "GPU/D3D11/DrawEngineD3D11.h" +#include "UI/OnScreenDisplay.h" + #include "ext/native/thin3d/thin3d.h" #include @@ -76,6 +87,13 @@ const D3D11_INPUT_ELEMENT_DESC FramebufferManagerD3D11::g_QuadVertexElements[2] { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, }, }; +// The current simple shader translator outputs everything as semantic texcoords, so let's just play along +// for simplicity. +const D3D11_INPUT_ELEMENT_DESC FramebufferManagerD3D11::g_PostVertexElements[2] = { + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 12, }, +}; + FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); @@ -105,6 +123,14 @@ 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; + vb.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + device_->CreateBuffer(&vb, nullptr, &postConstants_); + + ShaderTranslationInit(); + + CompilePostShader(); D3D11_TEXTURE2D_DESC packDesc{}; packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; @@ -121,6 +147,8 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) FramebufferManagerD3D11::~FramebufferManagerD3D11() { packTexture_->Release(); + ShaderTranslationShutdown(); + // Drawing cleanup if (quadVertexShader_) quadVertexShader_->Release(); @@ -129,12 +157,23 @@ FramebufferManagerD3D11::~FramebufferManagerD3D11() { quadInputLayout_->Release(); quadBuffer_->Release(); fsQuadBuffer_->Release(); + postConstants_->Release(); if (drawPixelsTex_) drawPixelsTex_->Release(); if (drawPixelsTexView_) drawPixelsTexView_->Release(); + if (postVertexShader_) { + postVertexShader_->Release(); + } + if (postPixelShader_) { + postPixelShader_->Release(); + } + if (postInputLayout_) { + postInputLayout_->Release(); + } + // FBO cleanup for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) { it->second.fbo->Release(); @@ -176,6 +215,75 @@ void FramebufferManagerD3D11::DisableState() { context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); } +void FramebufferManagerD3D11::CompilePostShader() { + SetNumExtraFBOs(0); + + std::string vsSource; + std::string psSource; + + if (postVertexShader_) { + postVertexShader_->Release(); + postVertexShader_ = nullptr; + } + if (postPixelShader_) { + postPixelShader_->Release(); + postPixelShader_ = nullptr; + } + if (postInputLayout_) { + postInputLayout_->Release(); + postInputLayout_ = nullptr; + } + + const ShaderInfo *shaderInfo = 0; + if (g_Config.sPostShaderName == "Off") { + usePostShader_ = false; + return; + } + + usePostShader_ = false; + + 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; + } + I18NCategory *gr = GetI18NCategory("Graphics"); + + UINT flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; + std::vector byteCode; + postVertexShader_ = CreateVertexShaderD3D11(device_, vsSource.data(), vsSource.size(), &byteCode, flags); + if (!postVertexShader_) { + return; + } + postPixelShader_ = CreatePixelShaderD3D11(device_, psSource.data(), psSource.size(), flags); + if (!postPixelShader_) { + postVertexShader_->Release(); + return; + } + device_->CreateInputLayout(g_PostVertexElements, 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 +442,27 @@ 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); + + D3D11_MAPPED_SUBRESOURCE map; + context_->Map(postConstants_, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + memcpy(map.pData, &uniforms, sizeof(uniforms)); + context_->Unmap(postConstants_, 0); + context_->VSSetConstantBuffers(0, 1, &postConstants_); // Probably not necessary + context_->PSSetConstantBuffers(0, 1, &postConstants_); } void FramebufferManagerD3D11::RebindFramebuffer() { @@ -741,18 +866,27 @@ void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, in void FramebufferManagerD3D11::EndFrame() { if (resized_) { DestroyAllFBOs(false); + + // Check if postprocessing shader is doing upscaling as it requires native resolution + const ShaderInfo *shaderInfo = 0; + if (g_Config.sPostShaderName != "Off") { + shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName); + } + + postShaderIsUpscalingFilter_ = shaderInfo ? shaderInfo->isUpscalingFilter : false; + // Actually, auto mode should be more granular... // Round up to a zoom factor for the render size. int zoom = g_Config.iInternalResolution; - if (zoom == 0) { // auto mode - // Use the longest dimension + if (zoom == 0) { + // auto mode, use the longest dimension if (!g_Config.IsPortrait()) { zoom = (PSP_CoreParameter().pixelWidth + 479) / 480; } else { zoom = (PSP_CoreParameter().pixelHeight + 479) / 480; } } - if (zoom <= 1) + if (zoom <= 1 || postShaderIsUpscalingFilter_) zoom = 1; if (g_Config.IsPortrait()) { @@ -769,6 +903,9 @@ void FramebufferManagerD3D11::EndFrame() { ShowScreenResolution(); } resized_ = false; + + // Might have a new post shader - let's compile it. + CompilePostShader(); } } diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index fb46b0a0d30f..56c9014cda83 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -94,6 +94,7 @@ class FramebufferManagerD3D11 : public FramebufferManagerCommon { 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; @@ -137,10 +138,18 @@ class FramebufferManagerD3D11 : public FramebufferManagerCommon { 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; + static const D3D11_INPUT_ELEMENT_DESC g_PostVertexElements[2]; + // Used by post-processing shader std::vector extraFBOs_; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 1b910e93eaa3..838c88477631 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -123,62 +123,65 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { glsl_bind(draw2dprogram_); glUniform1i(draw2dprogram_->sampler0, 0); } + CompilePostShader(); + } +} - SetNumExtraFBOs(0); - const ShaderInfo *shaderInfo = 0; - if (g_Config.sPostShaderName != "Off") { - shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName); - } +void FramebufferManagerGLES::CompilePostShader() { + SetNumExtraFBOs(0); + const ShaderInfo *shaderInfo = 0; + if (g_Config.sPostShaderName != "Off") { + shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName); + } - if (shaderInfo) { - postShaderAtOutputResolution_ = shaderInfo->outputResolution; - postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), &errorString); - if (!postShaderProgram_) { - // DO NOT turn this into a report, as it will pollute our logs with all kinds of - // user shader experiments. - ERROR_LOG(G3D, "Failed to build post-processing program from %s and %s!\n%s", shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), errorString.c_str()); - // let's show the first line of the error string as an OSM. - std::set blacklistedLines; - // These aren't useful to show, skip to the first interesting line. - blacklistedLines.insert("Fragment shader failed to compile with the following errors:"); - blacklistedLines.insert("Vertex shader failed to compile with the following errors:"); - blacklistedLines.insert("Compile failed."); - blacklistedLines.insert(""); - - std::string firstLine; - size_t start = 0; - for (size_t i = 0; i < errorString.size(); i++) { - if (errorString[i] == '\n') { - firstLine = errorString.substr(start, i - start); - if (blacklistedLines.find(firstLine) == blacklistedLines.end()) { - break; - } - start = i + 1; - firstLine.clear(); + if (shaderInfo) { + std::string errorString; + postShaderAtOutputResolution_ = shaderInfo->outputResolution; + postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), &errorString); + if (!postShaderProgram_) { + // DO NOT turn this into a report, as it will pollute our logs with all kinds of + // user shader experiments. + ERROR_LOG(G3D, "Failed to build post-processing program from %s and %s!\n%s", shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), errorString.c_str()); + // let's show the first line of the error string as an OSM. + std::set blacklistedLines; + // These aren't useful to show, skip to the first interesting line. + blacklistedLines.insert("Fragment shader failed to compile with the following errors:"); + blacklistedLines.insert("Vertex shader failed to compile with the following errors:"); + blacklistedLines.insert("Compile failed."); + blacklistedLines.insert(""); + + std::string firstLine; + size_t start = 0; + for (size_t i = 0; i < errorString.size(); i++) { + if (errorString[i] == '\n') { + firstLine = errorString.substr(start, i - start); + if (blacklistedLines.find(firstLine) == blacklistedLines.end()) { + break; } + start = i + 1; + firstLine.clear(); } - if (!firstLine.empty()) { - host->NotifyUserMessage("Post-shader error: " + firstLine + "...", 10.0f, 0xFF3090FF); - } else { - host->NotifyUserMessage("Post-shader error, see log for details", 10.0f, 0xFF3090FF); - } - usePostShader_ = false; + } + if (!firstLine.empty()) { + host->NotifyUserMessage("Post-shader error: " + firstLine + "...", 10.0f, 0xFF3090FF); } else { - glsl_bind(postShaderProgram_); - glUniform1i(postShaderProgram_->sampler0, 0); - SetNumExtraFBOs(1); - deltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_texelDelta"); - pixelDeltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); - timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); - usePostShader_ = true; + host->NotifyUserMessage("Post-shader error, see log for details", 10.0f, 0xFF3090FF); } - } else { - postShaderProgram_ = nullptr; usePostShader_ = false; + } else { + glsl_bind(postShaderProgram_); + glUniform1i(postShaderProgram_->sampler0, 0); + SetNumExtraFBOs(1); + deltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_texelDelta"); + pixelDeltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); + timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); + usePostShader_ = true; } - - glsl_unbind(); + } else { + postShaderProgram_ = nullptr; + usePostShader_ = false; } + glsl_unbind(); } void FramebufferManagerGLES::Bind2DShader() { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 260141d234e2..958189a97817 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -112,6 +112,7 @@ class FramebufferManagerGLES : public FramebufferManagerCommon { void BindPostShader(const PostShaderUniforms &uniforms) override; void CompileDraw2DProgram(); void DestroyDraw2DProgram(); + void CompilePostShader(); void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h); diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index b62126b72842..dcd2afd30437 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -977,7 +977,6 @@ namespace MainWindow { g_Config.sPostShaderName = availableShaders[index]; NativeMessageReceived("gpu resized", ""); - break; } diff --git a/ext/SPIRV-Cross.vcxproj b/ext/SPIRV-Cross.vcxproj index ff6a10c202c4..81a914672c5f 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