diff --git a/core/rend/gl4/abuffer.cpp b/core/rend/gl4/abuffer.cpp index 808c6d1de..8fafa4f6f 100644 --- a/core/rend/gl4/abuffer.cpp +++ b/core/rend/gl4/abuffer.cpp @@ -190,6 +190,8 @@ void main(void) )"; static const char *tr_modvol_shader_source = R"( +noperspective in vec3 vtx_uv; + // Must match ModifierVolumeMode enum values #define MV_XOR 0 #define MV_OR 1 @@ -198,9 +200,6 @@ static const char *tr_modvol_shader_source = R"( void main(void) { -#if MV_MODE == MV_XOR || MV_MODE == MV_OR - setFragDepth(); -#endif ivec2 coords = ivec2(gl_FragCoord.xy); uint idx = imageLoad(abufferPointerImg, coords).x; @@ -212,10 +211,10 @@ void main(void) if (getShadowEnable(pp)) { #if MV_MODE == MV_XOR - if (gl_FragDepth >= pixel.depth) + if (vtx_uv.z >= pixel.depth) atomicXor(pixels[idx].seq_num, SHADOW_STENCIL); #elif MV_MODE == MV_OR - if (gl_FragDepth >= pixel.depth) + if (vtx_uv.z >= pixel.depth) atomicOr(pixels[idx].seq_num, SHADOW_STENCIL); #elif MV_MODE == MV_INCLUSION uint prev_val = atomicAnd(pixels[idx].seq_num, ~(SHADOW_STENCIL)); @@ -318,7 +317,8 @@ void initABuffer() for (int mode = 0; mode < ModeCount; mode++) { modVolShader.setConstant("MV_MODE", mode); - gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], modVolShader.generate().c_str(), vertexShader.generate().c_str()); + g_abuffer_tr_modvol_shaders[mode].pp_Gouraud = false; + gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], modVolShader.generate().c_str(), nullptr); } } if (g_quadBuffer == 0) diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 0fe8d22e7..32ed9beff 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -54,13 +54,13 @@ static const char* VertexShaderSource = R"( #if pp_Gouraud == 0 #define INTERPOLATION flat #else -#define INTERPOLATION smooth +#define INTERPOLATION noperspective #endif -/* Vertex constants*/ -uniform vec4 scale; +// Uniforms uniform mat4 normal_matrix; -/* Vertex input */ + +// Input in vec4 in_pos; in vec4 in_base; in vec4 in_offs; @@ -68,26 +68,33 @@ in vec2 in_uv; in vec4 in_base1; in vec4 in_offs1; in vec2 in_uv1; -/* output */ + +// Output INTERPOLATION out vec4 vtx_base; INTERPOLATION out vec4 vtx_offs; - out vec2 vtx_uv; +noperspective out vec3 vtx_uv; INTERPOLATION out vec4 vtx_base1; INTERPOLATION out vec4 vtx_offs1; - out vec2 vtx_uv1; +noperspective out vec2 vtx_uv1; + void main() { + vec4 vpos = normal_matrix * in_pos; vtx_base = in_base; vtx_offs = in_offs; - vtx_uv = in_uv; + vtx_uv = vec3(in_uv * vpos.z, vpos.z); vtx_base1 = in_base1; vtx_offs1 = in_offs1; - vtx_uv1 = in_uv1; - vec4 vpos = normal_matrix * in_pos; + vtx_uv1 = in_uv1 * vpos.z; +#if pp_Gouraud == 1 + vtx_base *= vpos.z; + vtx_offs *= vpos.z; + vtx_base1 *= vpos.z; + vtx_offs1 *= vpos.z; +#endif - vpos.w = 1.0 / vpos.z; - vpos.z = vpos.w; - vpos.xy *= vpos.w; + vpos.w = 1.0; + vpos.z = 0.0; gl_Position = vpos; } )"; @@ -112,10 +119,10 @@ out vec4 FragColor; #if pp_Gouraud == 0 #define INTERPOLATION flat #else -#define INTERPOLATION smooth +#define INTERPOLATION noperspective #endif -/* Shader program params*/ +// Uniforms uniform float cp_AlphaTestValue; uniform vec4 pp_ClipTest; uniform vec3 sp_FOG_COL_RAM,sp_FOG_COL_VERT; @@ -142,13 +149,13 @@ uniform int shading_instr[2]; uniform int fog_control[2]; #endif -/* Vertex input*/ +// Input INTERPOLATION in vec4 vtx_base; INTERPOLATION in vec4 vtx_offs; - in vec2 vtx_uv; +noperspective in vec3 vtx_uv; INTERPOLATION in vec4 vtx_base1; INTERPOLATION in vec4 vtx_offs1; - in vec2 vtx_uv1; +noperspective in vec2 vtx_uv1; float fog_mode2(float w) { @@ -171,9 +178,9 @@ vec4 fog_clamp(vec4 col) #if pp_Palette == 1 -vec4 palettePixel(sampler2D tex, vec2 coords) +vec4 palettePixel(sampler2D tex, vec3 coords) { - int color_idx = int(floor(texture(tex, coords).r * 255.0 + 0.5)) + palette_index; + int color_idx = int(floor(textureProj(tex, coords).r * 255.0 + 0.5)) + palette_index; ivec2 c = ivec2(color_idx % 32, color_idx / 32); return texelFetch(palette, c, 0); } @@ -182,7 +189,7 @@ vec4 palettePixel(sampler2D tex, vec2 coords) void main() { - setFragDepth(); + setFragDepth(vtx_uv.z); #if PASS == PASS_OIT // Manual depth testing @@ -200,7 +207,6 @@ void main() vec4 color = vtx_base; vec4 offset = vtx_offs; - vec2 uv = vtx_uv; bool area1 = false; ivec2 cur_blend_mode = blend_mode[0]; @@ -214,7 +220,6 @@ void main() if (stencil.r == 0x81u) { color = vtx_base1; offset = vtx_offs1; - uv = vtx_uv1; area1 = true; cur_blend_mode = blend_mode[1]; cur_use_alpha = use_alpha[1]; @@ -224,6 +229,10 @@ void main() } #endif #endif + #if pp_Gouraud == 1 + color /= vtx_uv.z; + offset /= vtx_uv.z; + #endif #if pp_UseAlpha==0 || pp_TwoVolumes == 1 IF(!cur_use_alpha) @@ -231,27 +240,27 @@ void main() #endif #if pp_FogCtrl==3 || pp_TwoVolumes == 1 // LUT Mode 2 IF(cur_fog_control == 3) - color=vec4(sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); + color = vec4(sp_FOG_COL_RAM.rgb, fog_mode2(vtx_uv.z)); #endif #if pp_Texture==1 { vec4 texcol; #if pp_Palette == 0 if (area1) - texcol = texture(tex1, uv); + texcol = textureProj(tex1, vec3(vtx_uv1.xy, vtx_uv.z)); else - texcol = texture(tex0, uv); + texcol = textureProj(tex0, vtx_uv); #else if (area1) - texcol = palettePixel(tex1, uv); + texcol = palettePixel(tex1, vec3(vtx_uv1.xy, vtx_uv.z)); else - texcol = palettePixel(tex0, uv); + texcol = palettePixel(tex0, vtx_uv); #endif #if pp_BumpMap == 1 float s = PI / 2.0 * (texcol.a * 15.0 * 16.0 + texcol.r * 15.0) / 255.0; float r = 2.0 * PI * (texcol.g * 15.0 * 16.0 + texcol.b * 15.0) / 255.0; - texcol.a = clamp(vtx_offs.a + vtx_offs.r * sin(s) + vtx_offs.g * cos(s) * cos(r - 2.0 * PI * vtx_offs.b), 0.0, 1.0); + texcol.a = clamp(offset.a + offset.r * sin(s) + offset.g * cos(s) * cos(r - 2.0 * PI * offset.b), 0.0, 1.0); texcol.rgb = vec3(1.0, 1.0, 1.0); #else #if pp_IgnoreTexA==1 || pp_TwoVolumes == 1 @@ -309,7 +318,7 @@ void main() #if pp_FogCtrl==0 || pp_TwoVolumes == 1 // LUT IF(cur_fog_control == 0) { - color.rgb=mix(color.rgb,sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); + color.rgb = mix(color.rgb, sp_FOG_COL_RAM.rgb, fog_mode2(vtx_uv.z)); } #endif #if pp_Offset==1 && pp_BumpMap == 0 && (pp_FogCtrl == 1 || pp_TwoVolumes == 1) // Per vertex @@ -385,7 +394,7 @@ void main() Pixel pixel; pixel.color = packColors(clamp(color, vec4(0.0), vec4(1.0))); - pixel.depth = gl_FragDepth; + pixel.depth = vtx_uv.z; pixel.seq_num = uint(pp_Number); pixel.next = imageAtomicExchange(abufferPointerImg, coords, idx); pixels[idx] = pixel; @@ -402,9 +411,11 @@ void main() )"; static const char* ModifierVolumeShader = R"( +noperspective in vec3 vtx_uv; + void main() { - setFragDepth(); + setFragDepth(vtx_uv.z); } )"; @@ -558,7 +569,7 @@ static void create_modvol_shader() { if (gl4.modvol_shader.program != 0) return; - Vertex4Source vertexShader(true); + Vertex4Source vertexShader(false); OpenGl4Source fragmentShader; fragmentShader.addSource(ShaderHeader) .addSource(ModifierVolumeShader); @@ -713,8 +724,6 @@ static bool RenderFrame(int width, int height) } resize(rendering_width, rendering_height); - //DEBUG_LOG(RENDERER, "scale: %f, %f, %f, %f", gl4ShaderUniforms.scale_coefs[0], gl4ShaderUniforms.scale_coefs[1], gl4ShaderUniforms.scale_coefs[2], gl4ShaderUniforms.scale_coefs[3]); - //VERT and RAM fog color constants u8* fog_colvert_bgra=(u8*)&FOG_COL_VERT; u8* fog_colram_bgra=(u8*)&FOG_COL_RAM; @@ -774,7 +783,14 @@ static bool RenderFrame(int width, int height) if (!is_rtt) glcache.ClearColor(VO_BORDER_COL.Red / 255.f, VO_BORDER_COL.Green / 255.f, VO_BORDER_COL.Blue / 255.f, 1.f); - if (!pvrrc.isRenderFramebuffer) + if (!is_rtt && (FB_R_CTRL.fb_enable == 0 || VO_CONTROL.blank_video == 1)) + { + // Video output disabled + glBindFramebuffer(GL_FRAMEBUFFER, output_fbo); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClear(GL_COLOR_BUFFER_BIT); + } + else if (!pvrrc.isRenderFramebuffer) { //Main VBO glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); glCheck(); diff --git a/core/rend/gl4/glsl.h b/core/rend/gl4/glsl.h index 0f1eb2aed..1fda912d1 100644 --- a/core/rend/gl4/glsl.h +++ b/core/rend/gl4/glsl.h @@ -38,9 +38,9 @@ struct Pixel { \n\ #define DST_ALPHA 6 \n\ #define INVERSE_DST_ALPHA 7 \n\ \n\ -void setFragDepth(void) \n\ +void setFragDepth(float z) \n\ { \n\ - float w = 100000.0 * gl_FragCoord.w; \n\ + float w = 100000.0 * z; \n\ gl_FragDepth = log2(1.0 + w) / 34.0; \n\ } \n\ \n\ diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index e4fc3b50e..07e425594 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -68,16 +68,22 @@ const char *PixelCompatShader = R"( )"; static const char* GouraudSource = R"( -#if (TARGET_GL == GL3 || TARGET_GL == GLES3) && pp_Gouraud == 0 +#if TARGET_GL == GL3 || TARGET_GL == GLES3 +#define NOPERSPECTIVE noperspective +#if pp_Gouraud == 0 #define INTERPOLATION flat #else +#define INTERPOLATION noperspective +#endif +#else +#define NOPERSPECTIVE #define INTERPOLATION #endif )"; static const char* VertexShaderSource = R"( /* Vertex constants*/ -uniform highp vec4 depth_scale; +uniform highp vec4 depth_scale; uniform highp mat4 normal_matrix; uniform highp float sp_FOG_DENSITY; @@ -89,25 +95,27 @@ in highp vec2 in_uv; /* output */ INTERPOLATION out lowp vec4 vtx_base; INTERPOLATION out lowp vec4 vtx_offs; - out highp vec2 vtx_uv; -#if TARGET_GL == GLES2 - out highp float fog_depth; -#endif +NOPERSPECTIVE out highp vec3 vtx_uv; + void main() { + highp vec4 vpos = normal_matrix * in_pos; vtx_base = in_base; vtx_offs = in_offs; - vtx_uv = in_uv; - highp vec4 vpos = normal_matrix * in_pos; - +#if TARGET_GL == GLES2 + vtx_uv = vec3(in_uv, vpos.z * sp_FOG_DENSITY); vpos.w = 1.0 / vpos.z; -#if TARGET_GL != GLES2 - vpos.z = vpos.w; -#else - fog_depth = vpos.z * sp_FOG_DENSITY; vpos.z = depth_scale.x + depth_scale.y * vpos.w; -#endif vpos.xy *= vpos.w; +#else +#if pp_Gouraud == 1 + vtx_base *= vpos.z; + vtx_offs *= vpos.z; +#endif + vtx_uv = vec3(in_uv * vpos.z, vpos.z); + vpos.w = 1.0; + vpos.z = 0.0; +#endif gl_Position = vpos; } )"; @@ -133,15 +141,12 @@ uniform mediump int palette_index; /* Vertex input*/ INTERPOLATION in lowp vec4 vtx_base; INTERPOLATION in lowp vec4 vtx_offs; - in highp vec2 vtx_uv; -#if TARGET_GL == GLES2 - in highp float fog_depth; -#endif +NOPERSPECTIVE in highp vec3 vtx_uv; lowp float fog_mode2(highp float w) { #if TARGET_GL == GLES2 - highp float z = clamp(fog_depth, 1.0, 255.9999); + highp float z = clamp(vtx_uv.z, 1.0, 255.9999); #else highp float z = clamp(w * sp_FOG_DENSITY, 1.0, 255.9999); #endif @@ -163,13 +168,14 @@ highp vec4 fog_clamp(lowp vec4 col) #if pp_Palette == 1 -lowp vec4 palettePixel(highp vec2 coords) +lowp vec4 palettePixel(highp vec3 coords) { - highp int color_idx = int(floor(texture(tex, coords).FOG_CHANNEL * 255.0 + 0.5)) + palette_index; #if TARGET_GL == GLES2 || TARGET_GL == GL2 + highp int color_idx = int(floor(texture(tex, coords.xy).FOG_CHANNEL * 255.0 + 0.5)) + palette_index; highp vec2 c = vec2((mod(float(color_idx), 32.0) * 2.0 + 1.0) / 64.0, (float(color_idx / 32) * 2.0 + 1.0) / 64.0); return texture(palette, c); #else + highp int color_idx = int(floor(textureProj(tex, coords).FOG_CHANNEL * 255.0 + 0.5)) + palette_index; highp ivec2 c = ivec2(color_idx % 32, color_idx / 32); return texelFetch(palette, c, 0); #endif @@ -177,6 +183,12 @@ lowp vec4 palettePixel(highp vec2 coords) #endif +#if TARGET_GL == GLES2 +#define depth gl_FragCoord.w +#else +#define depth vtx_uv.z +#endif + void main() { // Clip inside the box @@ -186,17 +198,26 @@ void main() discard; #endif - lowp vec4 color=vtx_base; + lowp vec4 color = vtx_base; + lowp vec4 offset = vtx_offs; + #if pp_Gouraud == 1 && TARGET_GL != GLES2 + color /= vtx_uv.z; + offset /= vtx_uv.z; + #endif #if pp_UseAlpha==0 color.a=1.0; #endif #if pp_FogCtrl==3 - color=vec4(sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); + color = vec4(sp_FOG_COL_RAM.rgb, fog_mode2(depth)); #endif #if pp_Texture==1 { #if pp_Palette == 0 - lowp vec4 texcol = texture(tex, vtx_uv); + #if TARGET_GL == GLES2 || TARGET_GL == GL2 + lowp vec4 texcol = texture(tex, vtx_uv.xy); + #else + lowp vec4 texcol = textureProj(tex, vtx_uv); + #endif #else lowp vec4 texcol = palettePixel(vtx_uv); #endif @@ -204,7 +225,7 @@ void main() #if pp_BumpMap == 1 highp float s = PI / 2.0 * (texcol.a * 15.0 * 16.0 + texcol.r * 15.0) / 255.0; highp float r = 2.0 * PI * (texcol.g * 15.0 * 16.0 + texcol.b * 15.0) / 255.0; - texcol.a = clamp(vtx_offs.a + vtx_offs.r * sin(s) + vtx_offs.g * cos(s) * cos(r - 2.0 * PI * vtx_offs.b), 0.0, 1.0); + texcol.a = clamp(offset.a + offset.r * sin(s) + offset.g * cos(s) * cos(r - 2.0 * PI * offset.b), 0.0, 1.0); texcol.rgb = vec3(1.0, 1.0, 1.0); #else #if pp_IgnoreTexA==1 @@ -240,9 +261,7 @@ void main() #endif #if pp_Offset==1 && pp_BumpMap == 0 - { - color.rgb+=vtx_offs.rgb; - } + color.rgb += offset.rgb; #endif } #endif @@ -250,26 +269,22 @@ void main() color = fog_clamp(color); #if pp_FogCtrl == 0 - { - color.rgb=mix(color.rgb,sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); - } + color.rgb = mix(color.rgb, sp_FOG_COL_RAM.rgb, fog_mode2(depth)); #endif #if pp_FogCtrl == 1 && pp_Offset==1 && pp_BumpMap == 0 - { - color.rgb=mix(color.rgb,sp_FOG_COL_VERT.rgb,vtx_offs.a); - } + color.rgb = mix(color.rgb, sp_FOG_COL_VERT.rgb, offset.a); #endif #if pp_TriLinear == 1 color *= trilinear_alpha; #endif - //color.rgb=vec3(gl_FragCoord.w * sp_FOG_DENSITY / 128.0); + //color.rgb = vec3(vtx_uv.z * sp_FOG_DENSITY / 128.0); #if TARGET_GL != GLES2 - highp float w = gl_FragCoord.w * 100000.0; + highp float w = vtx_uv.z * 100000.0; gl_FragDepth = log2(1.0 + w) / 34.0; #endif - gl_FragColor =color; + gl_FragColor = color; } )"; @@ -277,10 +292,12 @@ static const char* ModifierVolumeShader = R"( uniform lowp float sp_ShaderColor; /* Vertex input*/ +NOPERSPECTIVE in highp vec3 vtx_uv; + void main() { #if TARGET_GL != GLES2 - highp float w = gl_FragCoord.w * 100000.0; + highp float w = vtx_uv.z * 100000.0; gl_FragDepth = log2(1.0 + w) / 34.0; #endif gl_FragColor=vec4(0.0, 0.0, 0.0, sp_ShaderColor); @@ -832,10 +849,11 @@ static void create_modvol_shader() { if (gl.modvol_shader.program != 0) return; - VertexSource vertexShader(true); + VertexSource vertexShader(false); OpenGlSource fragmentShader; fragmentShader.addSource(PixelCompatShader) + .addSource(GouraudSource) .addSource(ModifierVolumeShader); gl.modvol_shader.program = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentShader.generate().c_str()); @@ -1236,10 +1254,14 @@ bool RenderFrame(int width, int height) if (!is_rtt) glcache.ClearColor(VO_BORDER_COL.Red / 255.f, VO_BORDER_COL.Green / 255.f, VO_BORDER_COL.Blue / 255.f, 1.f); - //move vertex to gpu - - if (!pvrrc.isRenderFramebuffer) + if (!is_rtt && (FB_R_CTRL.fb_enable == 0 || VO_CONTROL.blank_video == 1)) { + // Video output disabled + glClear(GL_COLOR_BUFFER_BIT); + } + else if (!pvrrc.isRenderFramebuffer) + { + //move vertex to gpu //Main VBO glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.geometry); glCheck(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl.vbo.idxs); glCheck(); diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index 6e637e518..b4e3c6a27 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -332,6 +332,11 @@ bool Drawer::Draw(const Texture *fogTexture, const Texture *paletteTexture) currentScissor = vk::Rect2D(); vk::CommandBuffer cmdBuffer = BeginRenderPass(); + if (!pvrrc.isRTT && (FB_R_CTRL.fb_enable == 0 || VO_CONTROL.blank_video == 1)) + { + // Video output disabled + return true; + } SetProvokingVertices(); diff --git a/core/rend/vulkan/oit/oit_drawer.cpp b/core/rend/vulkan/oit/oit_drawer.cpp index 2c1b4b837..4fbe6067d 100644 --- a/core/rend/vulkan/oit/oit_drawer.cpp +++ b/core/rend/vulkan/oit/oit_drawer.cpp @@ -163,6 +163,12 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0); mod_base = -1; + if (Translucent) + { + vk::MemoryBarrier barrier(vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eShaderRead); + cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader, + vk::DependencyFlagBits::eByRegion, barrier, nullptr, nullptr); + } } } const vk::DeviceSize offset = 0; @@ -332,27 +338,35 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture) targetFramebuffer, viewport, clear_colors.size(), clear_colors.data()), vk::SubpassContents::eInline); - // Depth + stencil subpass - DrawList(cmdBuffer, ListType_Opaque, false, Pass::Depth, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count); - DrawList(cmdBuffer, ListType_Punch_Through, false, Pass::Depth, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count); + if (!pvrrc.isRTT && (FB_R_CTRL.fb_enable == 0 || VO_CONTROL.blank_video == 1)) + { + // Video output disabled + cmdBuffer.nextSubpass(vk::SubpassContents::eInline); + } + else + { + // Depth + stencil subpass + DrawList(cmdBuffer, ListType_Opaque, false, Pass::Depth, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count); + DrawList(cmdBuffer, ListType_Punch_Through, false, Pass::Depth, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count); - DrawModifierVolumes(cmdBuffer, previous_pass.mvo_count, current_pass.mvo_count - previous_pass.mvo_count); + DrawModifierVolumes(cmdBuffer, previous_pass.mvo_count, current_pass.mvo_count - previous_pass.mvo_count); - // Color subpass - cmdBuffer.nextSubpass(vk::SubpassContents::eInline); + // Color subpass + cmdBuffer.nextSubpass(vk::SubpassContents::eInline); - // OP + PT - DrawList(cmdBuffer, ListType_Opaque, false, Pass::Color, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count); - DrawList(cmdBuffer, ListType_Punch_Through, false, Pass::Color, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count); + // OP + PT + DrawList(cmdBuffer, ListType_Opaque, false, Pass::Color, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count); + DrawList(cmdBuffer, ListType_Punch_Through, false, Pass::Color, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count); - // TR - if (current_pass.autosort) - { - if (!oitBuffers->isFirstFrameAfterInit()) - DrawList(cmdBuffer, ListType_Translucent, true, Pass::OIT, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count); - } - else - DrawList(cmdBuffer, ListType_Translucent, false, Pass::Color, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count); + // TR + if (current_pass.autosort) + { + if (!oitBuffers->isFirstFrameAfterInit()) + DrawList(cmdBuffer, ListType_Translucent, true, Pass::OIT, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count); + } + else + DrawList(cmdBuffer, ListType_Translucent, false, Pass::Color, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count); + } // Final subpass cmdBuffer.nextSubpass(vk::SubpassContents::eInline); diff --git a/core/rend/vulkan/oit/oit_shaders.cpp b/core/rend/vulkan/oit/oit_shaders.cpp index 053394d8c..f4bc8713e 100644 --- a/core/rend/vulkan/oit/oit_shaders.cpp +++ b/core/rend/vulkan/oit/oit_shaders.cpp @@ -38,23 +38,28 @@ layout (location = 6) in mediump vec2 in_uv1; layout (location = 0) INTERPOLATION out lowp vec4 vtx_base; layout (location = 1) INTERPOLATION out lowp vec4 vtx_offs; -layout (location = 2) out mediump vec2 vtx_uv; +layout (location = 2) noperspective out mediump vec3 vtx_uv; layout (location = 3) INTERPOLATION out lowp vec4 vtx_base1; // New for OIT, only for OP/PT with 2-volume layout (location = 4) INTERPOLATION out lowp vec4 vtx_offs1; -layout (location = 5) out mediump vec2 vtx_uv1; +layout (location = 5) noperspective out mediump vec2 vtx_uv1; void main() { + vec4 vpos = uniformBuffer.normal_matrix * in_pos; vtx_base = vec4(in_base) / 255.0; vtx_offs = vec4(in_offs) / 255.0; - vtx_uv = in_uv; - vtx_base1 = vec4(in_base1) / 255.0; // New for OIT, only for OP/PT with 2-volume + vtx_uv = vec3(in_uv * vpos.z, vpos.z); + vtx_base1 = vec4(in_base1) / 255.0; vtx_offs1 = vec4(in_offs1) / 255.0; - vtx_uv1 = in_uv1; - vec4 vpos = uniformBuffer.normal_matrix * in_pos; - vpos.w = 1.0 / vpos.z; - vpos.z = vpos.w; - vpos.xy *= vpos.w; + vtx_uv1 = in_uv1 * vpos.z; +#if pp_Gouraud == 1 + vtx_base *= vpos.z; + vtx_offs *= vpos.z; + vtx_base1 *= vpos.z; + vtx_offs1 *= vpos.z; +#endif + vpos.w = 1.0; + vpos.z = 0.0; gl_Position = vpos; } )"; @@ -165,10 +170,10 @@ layout (input_attachment_index = 0, set = 0, binding = 5) uniform subpassInput D // Vertex input layout (location = 0) INTERPOLATION in lowp vec4 vtx_base; layout (location = 1) INTERPOLATION in lowp vec4 vtx_offs; -layout (location = 2) in mediump vec2 vtx_uv; +layout (location = 2) noperspective in mediump vec3 vtx_uv; layout (location = 3) INTERPOLATION in lowp vec4 vtx_base1; // new for OIT. Only if 2 vol layout (location = 4) INTERPOLATION in lowp vec4 vtx_offs1; -layout (location = 5) in mediump vec2 vtx_uv1; +layout (location = 5) noperspective in mediump vec2 vtx_uv1; #if pp_FogCtrl != 2 || pp_TwoVolumes == 1 layout (set = 0, binding = 2) uniform sampler2D fog_table; @@ -196,9 +201,9 @@ vec4 colorClamp(vec4 col) #if pp_Palette == 1 -vec4 palettePixel(sampler2D tex, vec2 coords) +vec4 palettePixel(sampler2D tex, vec3 coords) { - vec4 c = vec4(texture(tex, coords).r * 255.0 / 1023.0 + pushConstants.palette_index, 0.5, 0.0, 0.0); + vec4 c = vec4(textureProj(tex, coords).r * 255.0 / 1023.0 + pushConstants.palette_index, 0.5, 0.0, 0.0); return texture(palette, c.xy); } @@ -206,7 +211,7 @@ vec4 palettePixel(sampler2D tex, vec2 coords) void main() { - setFragDepth(); + setFragDepth(vtx_uv.z); #if PASS == PASS_OIT // Manual depth testing @@ -224,7 +229,6 @@ void main() highp vec4 color = vtx_base; lowp vec4 offset = vtx_offs; - mediump vec2 uv = vtx_uv; bool area1 = false; ivec2 cur_blend_mode = pushConstants.blend_mode0.xy; @@ -238,7 +242,6 @@ void main() if (stencil.r == 0x81u) { color = vtx_base1; offset = vtx_offs1; - uv = vtx_uv1; area1 = true; cur_blend_mode = pushConstants.blend_mode1.xy; cur_use_alpha = pushConstants.use_alpha1 != 0; @@ -248,6 +251,10 @@ void main() } #endif #endif + #if pp_Gouraud == 1 + color /= vtx_uv.z; + offset /= vtx_uv.z; + #endif #if pp_UseAlpha == 0 || pp_TwoVolumes == 1 IF (!cur_use_alpha) @@ -255,7 +262,7 @@ void main() #endif #if pp_FogCtrl == 3 || pp_TwoVolumes == 1 // LUT Mode 2 IF (cur_fog_control == 3) - color = vec4(uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(gl_FragCoord.w)); + color = vec4(uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(vtx_uv.z)); #endif #if pp_Texture==1 { @@ -263,21 +270,21 @@ void main() #if pp_TwoVolumes == 1 if (area1) #if pp_Palette == 0 - texcol = texture(tex1, uv); + texcol = textureProj(tex1, vec3(vtx_uv1, vtx_uv.z)); #else - texcol = palettePixel(tex1, uv); + texcol = palettePixel(tex1, vec3(vtx_uv1, vtx_uv.z)); #endif else #endif #if pp_Palette == 0 - texcol = texture(tex0, uv); + texcol = textureProj(tex0, vtx_uv); #else - texcol = palettePixel(tex0, uv); + texcol = palettePixel(tex0, vtx_uv); #endif #if pp_BumpMap == 1 highp float s = PI / 2.0 * (texcol.a * 15.0 * 16.0 + texcol.r * 15.0) / 255.0; highp float r = 2.0 * PI * (texcol.g * 15.0 * 16.0 + texcol.b * 15.0) / 255.0; - texcol.a = clamp(vtx_offs.a + vtx_offs.r * sin(s) + vtx_offs.g * cos(s) * cos(r - 2.0 * PI * vtx_offs.b), 0.0, 1.0); + texcol.a = clamp(offset.a + offset.r * sin(s) + offset.g * cos(s) * cos(r - 2.0 * PI * offset.b), 0.0, 1.0); texcol.rgb = vec3(1.0, 1.0, 1.0); #else #if pp_IgnoreTexA==1 || pp_TwoVolumes == 1 @@ -335,7 +342,7 @@ void main() #if pp_FogCtrl == 0 || pp_TwoVolumes == 1 // LUT IF(cur_fog_control == 0) { - color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(gl_FragCoord.w)); + color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(vtx_uv.z)); } #endif #if pp_Offset==1 && pp_BumpMap == 0 && (pp_FogCtrl == 1 || pp_TwoVolumes == 1) // Per vertex @@ -347,7 +354,7 @@ void main() color *= pushConstants.trilinearAlpha; - //color.rgb=vec3(gl_FragCoord.w * uniformBuffer.sp_FOG_DENSITY / 128.0); + //color.rgb = vec3(vtx_uv.z * uniformBuffer.sp_FOG_DENSITY / 128.0); #if PASS == PASS_COLOR FragColor = color; @@ -411,7 +418,7 @@ void main() Pixel pixel; pixel.color = packColors(clamp(color, vec4(0.0), vec4(1.0))); - pixel.depth = gl_FragDepth; + pixel.depth = vtx_uv.z; pixel.seq_num = uint(pushConstants.pp_Number); pixel.next = atomicExchange(abufferPointer.pointers[coords.x + coords.y * uniformBuffer.viewportWidth], idx); PixelBuffer.pixels[idx] = pixel; @@ -421,9 +428,11 @@ void main() )"; static const char OITModifierVolumeShader[] = R"( +layout (location = 0) noperspective in float depth; + void main() { - setFragDepth(); + setFragDepth(depth); } )"; @@ -584,6 +593,8 @@ void main(void) )"; static const char OITTranslucentModvolShaderSource[] = R"( +layout (location = 0) noperspective in float depth; + // Must match ModifierVolumeMode enum values #define MV_XOR 0 #define MV_OR 1 @@ -592,9 +603,6 @@ static const char OITTranslucentModvolShaderSource[] = R"( void main() { -#if MV_MODE == MV_XOR || MV_MODE == MV_OR - setFragDepth(); -#endif ivec2 coords = ivec2(gl_FragCoord.xy); uint idx = abufferPointer.pointers[coords.x + coords.y * uniformBuffer.viewportWidth]; @@ -606,10 +614,10 @@ void main() if (getShadowEnable(pp)) { #if MV_MODE == MV_XOR - if (gl_FragDepth >= pixel.depth) + if (depth >= pixel.depth) atomicXor(PixelBuffer.pixels[idx].seq_num, SHADOW_STENCIL); #elif MV_MODE == MV_OR - if (gl_FragDepth >= pixel.depth) + if (depth >= pixel.depth) atomicOr(PixelBuffer.pixels[idx].seq_num, SHADOW_STENCIL); #elif MV_MODE == MV_INCLUSION uint prev_val = atomicAnd(PixelBuffer.pixels[idx].seq_num, ~(SHADOW_STENCIL)); diff --git a/core/rend/vulkan/shaders.cpp b/core/rend/vulkan/shaders.cpp index a376366bf..58265aed3 100644 --- a/core/rend/vulkan/shaders.cpp +++ b/core/rend/vulkan/shaders.cpp @@ -36,17 +36,20 @@ layout (location = 3) in mediump vec2 in_uv; layout (location = 0) INTERPOLATION out lowp vec4 vtx_base; layout (location = 1) INTERPOLATION out lowp vec4 vtx_offs; -layout (location = 2) out mediump vec2 vtx_uv; +layout (location = 2) noperspective out mediump vec3 vtx_uv; void main() { + vec4 vpos = uniformBuffer.normal_matrix * in_pos; vtx_base = vec4(in_base) / 255.0; vtx_offs = vec4(in_offs) / 255.0; - vtx_uv = in_uv; - vec4 vpos = uniformBuffer.normal_matrix * in_pos; - vpos.w = 1.0 / vpos.z; - vpos.z = vpos.w; - vpos.xy *= vpos.w; + vtx_uv = vec3(in_uv * vpos.z, vpos.z); +#if pp_Gouraud == 1 + vtx_base *= vpos.z; + vtx_offs *= vpos.z; +#endif + vpos.w = 1.0; + vpos.z = 0.0; gl_Position = vpos; } )"; @@ -84,7 +87,7 @@ layout (set = 0, binding = 3) uniform sampler2D palette; // Vertex input layout (location = 0) INTERPOLATION in lowp vec4 vtx_base; layout (location = 1) INTERPOLATION in lowp vec4 vtx_offs; -layout (location = 2) in mediump vec2 vtx_uv; +layout (location = 2) noperspective in mediump vec3 vtx_uv; #if pp_FogCtrl != 2 layout (set = 0, binding = 2) uniform sampler2D fog_table; @@ -111,9 +114,9 @@ vec4 colorClamp(vec4 col) #if pp_Palette == 1 -vec4 palettePixel(sampler2D tex, vec2 coords) +vec4 palettePixel(sampler2D tex, vec3 coords) { - vec4 c = vec4(texture(tex, coords).r * 255.0 / 1023.0 + pushConstants.palette_index, 0.5, 0.0, 0.0); + vec4 c = vec4(textureProj(tex, coords).r * 255.0 / 1023.0 + pushConstants.palette_index, 0.5, 0.0, 0.0); return texture(palette, c.xy); } @@ -129,6 +132,11 @@ void main() #endif vec4 color = vtx_base; + vec4 offset = vtx_offs; + #if pp_Gouraud == 1 + color /= vtx_uv.z; + offset /= vtx_uv.z; + #endif #if pp_UseAlpha == 0 color.a = 1.0; #endif @@ -138,7 +146,7 @@ void main() #if pp_Texture == 1 { #if pp_Palette == 0 - vec4 texcol = texture(tex, vtx_uv); + vec4 texcol = textureProj(tex, vtx_uv); #else vec4 texcol = palettePixel(tex, vtx_uv); #endif @@ -146,7 +154,7 @@ void main() #if pp_BumpMap == 1 float s = PI / 2.0 * (texcol.a * 15.0 * 16.0 + texcol.r * 15.0) / 255.0; float r = 2.0 * PI * (texcol.g * 15.0 * 16.0 + texcol.b * 15.0) / 255.0; - texcol.a = clamp(vtx_offs.a + vtx_offs.r * sin(s) + vtx_offs.g * cos(s) * cos(r - 2.0 * PI * vtx_offs.b), 0.0, 1.0); + texcol.a = clamp(offset.a + offset.r * sin(s) + offset.g * cos(s) * cos(r - 2.0 * PI * offset.b), 0.0, 1.0); texcol.rgb = vec3(1.0, 1.0, 1.0); #else #if pp_IgnoreTexA == 1 @@ -183,7 +191,7 @@ void main() #if pp_Offset == 1 && pp_BumpMap == 0 { - color.rgb += vtx_offs.rgb; + color.rgb += offset.rgb; } #endif } @@ -193,12 +201,12 @@ void main() #if pp_FogCtrl == 0 { - color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(gl_FragCoord.w)); + color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_RAM.rgb, fog_mode2(vtx_uv.z)); } #endif #if pp_FogCtrl == 1 && pp_Offset==1 && pp_BumpMap == 0 { - color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_VERT.rgb, vtx_offs.a); + color.rgb = mix(color.rgb, uniformBuffer.sp_FOG_COL_VERT.rgb, offset.a); } #endif @@ -208,7 +216,7 @@ void main() //color.rgb = vec3(gl_FragCoord.w * uniformBuffer.sp_FOG_DENSITY / 128.0); - float w = gl_FragCoord.w * 100000.0; + float w = vtx_uv.z * 100000.0; gl_FragDepth = log2(1.0 + w) / 34.0; gl_FragColor = color; @@ -221,7 +229,8 @@ layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms mat4 normal_matrix; } uniformBuffer; -layout (location = 0) in vec4 in_pos; +layout (location = 0) in vec4 in_pos; +layout (location = 0) noperspective out float depth; void main() { @@ -233,14 +242,15 @@ void main() } vpos = uniformBuffer.normal_matrix * vpos; - vpos.w = 1.0 / vpos.z; - vpos.z = vpos.w; - vpos.xy *= vpos.w; + depth = vpos.z; + vpos.w = 1.0; + vpos.z = 0.0; gl_Position = vpos; } )"; static const char ModVolFragmentShaderSource[] = R"( +layout (location = 0) noperspective in float depth; layout (location = 0) out vec4 FragColor; layout (push_constant) uniform pushBlock @@ -250,7 +260,7 @@ layout (push_constant) uniform pushBlock void main() { - float w = gl_FragCoord.w * 100000.0; + float w = depth * 100000.0; gl_FragDepth = log2(1.0 + w) / 34.0; FragColor = vec4(0.0, 0.0, 0.0, pushConstants.sp_ShaderColor); } diff --git a/core/rend/vulkan/utils.h b/core/rend/vulkan/utils.h index 2cee43071..49fa581f9 100644 --- a/core/rend/vulkan/utils.h +++ b/core/rend/vulkan/utils.h @@ -82,7 +82,7 @@ static const char GouraudSource[] = R"( #if pp_Gouraud == 0 #define INTERPOLATION flat #else -#define INTERPOLATION smooth +#define INTERPOLATION noperspective #endif )";