diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index a2d66b9a86..f3bd46dd4b 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -17,6 +17,11 @@ #include "GLRenderManager.h" #include "DataFormatGL.h" +// These are the same value, alias for simplicity. +#if defined(GL_CLIP_DISTANCE0_EXT) && !defined(GL_CLIP_DISTANCE0) +#define GL_CLIP_DISTANCE0 GL_CLIP_DISTANCE0_EXT +#endif + static constexpr int TEXCACHE_NAME_CACHE_SIZE = 16; #if PPSSPP_PLATFORM(IOS) @@ -798,6 +803,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last int logicOp = -1; bool logicEnabled = false; #endif + bool clipDistance0Enabled = false; GLuint blendEqColor = (GLuint)-1; GLuint blendEqAlpha = (GLuint)-1; @@ -1106,6 +1112,13 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last { if (curProgram != c.program.program) { glUseProgram(c.program.program->program); + if (c.program.program->use_clip_distance0 != clipDistance0Enabled) { + if (c.program.program->use_clip_distance0) + glEnable(GL_CLIP_DISTANCE0); + else + glDisable(GL_CLIP_DISTANCE0); + clipDistance0Enabled = c.program.program->use_clip_distance0; + } curProgram = c.program.program; } CHECK_GL_ERROR_IF_DEBUG(); @@ -1340,6 +1353,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glDisable(GL_COLOR_LOGIC_OP); } #endif + if (clipDistance0Enabled) + glDisable(GL_CLIP_DISTANCE0); if ((colorMask & 15) != 15) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); CHECK_GL_ERROR_IF_DEBUG(); diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index b4c3378739..110704bab2 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -119,6 +119,7 @@ public: std::vector semantics_; std::vector queries_; std::vector initialize_; + bool use_clip_distance0 = false; struct UniformInfo { int loc_; @@ -422,13 +423,14 @@ public: // not be an active render pass. GLRProgram *CreateProgram( std::vector shaders, std::vector semantics, std::vector queries, - std::vector initalizers, bool supportDualSource) { + std::vector initalizers, bool supportDualSource, bool useClipDistance0) { GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; _assert_(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); step.create_program.program = new GLRProgram(); step.create_program.program->semantics_ = semantics; step.create_program.program->queries_ = queries; step.create_program.program->initialize_ = initalizers; + step.create_program.program->use_clip_distance0 = useClipDistance0; step.create_program.support_dual_source = supportDualSource; _assert_msg_(shaders.size() > 0, "Can't create a program with zero shaders"); for (size_t i = 0; i < shaders.size(); i++) { diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 83102c8898..ab4bb24161 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -1163,7 +1163,7 @@ bool OpenGLPipeline::LinkShaders() { std::vector initialize; for (int i = 0; i < MAX_TEXTURE_SLOTS; ++i) initialize.push_back({ &samplerLocs_[i], 0, i }); - program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false); + program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false, false); return true; } diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index d969a719c2..4e90be2e53 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -141,6 +141,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag if (gl_extensions.EXT_gpu_shader4) { gl_exts.push_back("#extension GL_EXT_gpu_shader4 : enable"); } + if (gl_extensions.EXT_clip_cull_distance && id.Bit(VS_BIT_VERTEX_RANGE_CULLING)) { + gl_exts.push_back("#extension GL_EXT_clip_cull_distance : enable"); + } } ShaderWriter p(buffer, compat, ShaderStage::Vertex, gl_exts.data(), gl_exts.size()); @@ -1110,7 +1113,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, " }\n"); WRITE(p, " }\n"); - if (compat.shaderLanguage == GLSL_VULKAN && gstate_c.Supports(GPU_SUPPORTS_CLIP_CULL_DISTANCE)) { + if (gstate_c.Supports(GPU_SUPPORTS_CLIP_CULL_DISTANCE) && (compat.shaderLanguage == GLSL_VULKAN || ShaderLanguageIsOpenGL(compat.shaderLanguage))) { // TODO: Not rectangles... WRITE(p, " %sgl_ClipDistance[0] = projZ * outPos.w + outPos.w;\n", compat.vsOutPrefix); } diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 47ddfa1907..fbf544f1ca 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -183,7 +183,7 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf std::vector shaders{ vertexShader_, fragShader }; - GLRProgram *program = render_->CreateProgram(shaders, semantics, queries, initializer, false); + GLRProgram *program = render_->CreateProgram(shaders, semantics, queries, initializer, false, false); depal->program = program; depal->fragShader = fragShader; diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index 7eae61caa6..d262713721 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -116,7 +116,7 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int queries.push_back({ &u_depthDownloadTo8, "u_depthTo8" }); std::vector inits; inits.push_back({ &u_depthDownloadTex, 0, TEX_SLOT_PSP_TEXTURE }); - depthDownloadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false); + depthDownloadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false, false); for (auto iter : shaders) { render_->DeleteShader(iter); } diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index f28b4f7016..56672127d9 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -87,7 +87,7 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { std::vector semantics; semantics.push_back({ 0, "a_position" }); semantics.push_back({ 1, "a_texcoord0" }); - draw2dprogram_ = render_->CreateProgram(shaders, semantics, queries, initializers, false); + draw2dprogram_ = render_->CreateProgram(shaders, semantics, queries, initializers, false, false); for (auto shader : shaders) render_->DeleteShader(shader); } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index bc086b01df..a25231c232 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -51,10 +51,10 @@ using namespace Lin; -Shader::Shader(GLRenderManager *render, const char *code, const std::string &desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask) - : render_(render), failed_(false), useHWTransform_(useHWTransform), attrMask_(attrMask), uniformMask_(uniformMask) { +Shader::Shader(GLRenderManager *render, const char *code, const std::string &desc, const ShaderDescGLES ¶ms) + : render_(render), useHWTransform_(params.useHWTransform), attrMask_(params.attrMask), uniformMask_(params.uniformMask) { PROFILE_THIS_SCOPE("shadercomp"); - isFragment_ = glShaderType == GL_FRAGMENT_SHADER; + isFragment_ = params.glShaderType == GL_FRAGMENT_SHADER; source_ = code; #ifdef SHADERLOG #ifdef _WIN32 @@ -63,7 +63,7 @@ Shader::Shader(GLRenderManager *render, const char *code, const std::string &des printf("%s\n", code); #endif #endif - shader = render->CreateShader(glShaderType, source_, desc); + shader = render->CreateShader(params.glShaderType, source_, desc); } Shader::~Shader() { @@ -182,7 +182,9 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, initialize.push_back({ &u_tess_weights_u, 0, 5 }); initialize.push_back({ &u_tess_weights_v, 0, 6 }); - program = render->CreateProgram(shaders, semantics, queries, initialize, gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND); + bool useDualSource = (gstate_c.featureFlags & GPU_SUPPORTS_DUALSOURCE_BLEND) != 0; + bool useClip0 = VSID.Bit(VS_BIT_VERTEX_RANGE_CULLING) && gstate_c.Supports(GPU_SUPPORTS_CLIP_CULL_DISTANCE); + program = render->CreateProgram(shaders, semantics, queries, initialize, useDualSource, useClip0); // The rest, use the "dirty" mechanism. dirtyUniforms = DIRTY_ALL_UNIFORMS; @@ -633,7 +635,8 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { return nullptr; } std::string desc = FragmentShaderDesc(FSID); - return new Shader(render_, codeBuffer_, desc, GL_FRAGMENT_SHADER, false, 0, uniformMask); + ShaderDescGLES params{ GL_FRAGMENT_SHADER, 0, uniformMask }; + return new Shader(render_, codeBuffer_, desc, params); } Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { @@ -646,7 +649,9 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { return nullptr; } std::string desc = VertexShaderDesc(VSID); - return new Shader(render_, codeBuffer_, desc, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask); + ShaderDescGLES params{ GL_VERTEX_SHADER, attrMask, uniformMask }; + params.useHWTransform = useHWTransform; + return new Shader(render_, codeBuffer_, desc, params); } Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, VShaderID *VSID) { diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index c49b6700c0..24ef3e42f1 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -114,9 +114,16 @@ public: // Real public interface +struct ShaderDescGLES { + uint32_t glShaderType; + uint32_t attrMask; + uint64_t uniformMask; + bool useHWTransform; +}; + class Shader { public: - Shader(GLRenderManager *render, const char *code, const std::string &desc, uint32_t glShaderType, bool useHWTransform, uint32_t attrMask, uint64_t uniformMask); + Shader(GLRenderManager *render, const char *code, const std::string &desc, const ShaderDescGLES ¶ms); ~Shader(); GLRShader *shader; @@ -131,7 +138,7 @@ public: private: GLRenderManager *render_; std::string source_; - bool failed_; + bool failed_ = false; bool useHWTransform_; bool isFragment_; uint32_t attrMask_; // only used in vertex shaders diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 480690b930..7ea535925f 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -147,7 +147,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, StencilUplo queries.push_back({ &u_stencilValue, "u_stencilValue" }); std::vector inits; inits.push_back({ &u_stencilUploadTex, 0, TEX_SLOT_PSP_TEXTURE }); - stencilUploadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false); + stencilUploadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false, false); for (auto iter : shaders) { render_->DeleteShader(iter); }