diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 13ae39366..551c4035e 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -1226,8 +1226,16 @@ bool GPU_HW::CompilePipelines(Error* error) batch_fragment_shaders.enumerate(destroy_shader); }); + GPU_HW_ShaderGen::BatchVertexShaderSelector vssel = {}; + vssel.upscaled = upscaled; + vssel.msaa = msaa; + vssel.per_sample_shading = per_sample_shading; + vssel.pgxp_depth = m_pgxp_depth_buffer; + vssel.disable_color_perspective = disable_color_perspective; for (u8 textured = 0; textured < 2; textured++) { + vssel.textured = (textured != 0); + for (u8 palette = 0; palette < 3; palette++) { if (palette && !textured) @@ -1235,17 +1243,18 @@ bool GPU_HW::CompilePipelines(Error* error) if (palette == 2 && !needs_page_texture) continue; + vssel.palette = (palette == 1); + vssel.page_texture = (palette == 2); + for (u8 sprite = 0; sprite < 2; sprite++) { if (sprite && (!textured || !m_allow_sprite_mode)) continue; - const bool uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering); - const std::string vs = shadergen.GenerateBatchVertexShader( - upscaled, msaa, per_sample_shading, textured != 0, palette == 1, palette == 2, uv_limits, - !sprite && force_round_texcoords, m_pgxp_depth_buffer, disable_color_perspective); - if (!(batch_vertex_shaders[textured][palette][sprite] = - g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs, error))) + vssel.uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering); + vssel.force_round_texcoords = !sprite && force_round_texcoords; + if (!(batch_vertex_shaders[textured][palette][sprite] = g_gpu_device->CreateShader( + GPUShaderStage::Vertex, shadergen.GetLanguage(), shadergen.GenerateBatchVertexShader(vssel), error))) { return false; } @@ -1256,6 +1265,15 @@ bool GPU_HW::CompilePipelines(Error* error) } } + GPU_HW_ShaderGen::BatchFragmentShaderSelector fssel = {}; + fssel.upscaled = upscaled; + fssel.msaa = msaa; + fssel.per_sample_shading = per_sample_shading; + fssel.modulation_crop = modulation_crop; + fssel.true_color = true_color; + fssel.disable_color_perspective = disable_color_perspective; + fssel.write_mask_as_depth = m_write_mask_as_depth; + for (u8 depth_test = 0; depth_test < 2; depth_test++) { if (depth_test && !needs_rov_depth) @@ -1266,6 +1284,8 @@ bool GPU_HW::CompilePipelines(Error* error) for (u8 render_mode = 0; render_mode < 5; render_mode++) { + fssel.render_mode = static_cast(render_mode); + for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++) { if ( @@ -1290,6 +1310,12 @@ bool GPU_HW::CompilePipelines(Error* error) continue; } + fssel.transparency = static_cast(transparency_mode); + fssel.use_rov = (fssel.render_mode == BatchRenderMode::ShaderBlend && m_use_rov_for_shader_blend); + fssel.use_rov_depth = (fssel.use_rov && needs_rov_depth); + fssel.rov_depth_test = (fssel.use_rov && depth_test != 0); + fssel.rov_depth_write = (fssel.rov_depth_test && fssel.transparency == GPUTransparencyMode::Disabled); + for (u8 texture_mode = 0; texture_mode < max_active_texture_modes; texture_mode++) { if (!needs_page_texture && (texture_mode == static_cast(BatchTextureMode::PageTexture) || @@ -1298,6 +1324,15 @@ bool GPU_HW::CompilePipelines(Error* error) continue; } + const bool sprite = (static_cast(texture_mode) >= BatchTextureMode::SpriteStart); + fssel.uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering); + fssel.force_round_texcoords = !sprite && force_round_texcoords; + fssel.texture_mode = + static_cast(texture_mode - (sprite ? static_cast(BatchTextureMode::SpriteStart) : 0)); + fssel.texture_filtering = sprite ? m_sprite_texture_filtering : m_texture_filtering; + fssel.is_blended_texture_filtering = + (fssel.texture_mode != BatchTextureMode::Disabled && IsBlendedTextureFiltering(fssel.texture_filtering)); + for (u8 check_mask = 0; check_mask < 2; check_mask++) { if (check_mask && render_mode != static_cast(BatchRenderMode::ShaderBlend)) @@ -1312,41 +1347,30 @@ bool GPU_HW::CompilePipelines(Error* error) continue; } + fssel.check_mask = ConvertToBoolUnchecked(check_mask); + for (u8 dithering = 0; dithering < 2; dithering++) { // Never going to draw with dithering on in true color. if (dithering && true_color) continue; + fssel.dithering = ConvertToBoolUnchecked(dithering); + fssel.scaled_dithering = (fssel.dithering && scaled_dithering); + for (u8 interlacing = 0; interlacing < 2; interlacing++) { // Never going to draw with line skipping in force progressive. if (interlacing && force_progressive_scan) continue; - const bool sprite = (static_cast(texture_mode) >= BatchTextureMode::SpriteStart); - const bool uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering); - const BatchTextureMode shader_texmode = static_cast( - texture_mode - (sprite ? static_cast(BatchTextureMode::SpriteStart) : 0)); - const GPUTextureFilter texture_filter = sprite ? m_sprite_texture_filtering : m_texture_filtering; - const bool texture_filter_is_blended = - (shader_texmode != BatchTextureMode::Disabled && IsBlendedTextureFiltering(texture_filter)); - const bool use_rov = - (render_mode == static_cast(BatchRenderMode::ShaderBlend) && m_use_rov_for_shader_blend); - const bool rov_depth_test = (use_rov && depth_test != 0); - const bool rov_depth_write = (rov_depth_test && static_cast(transparency_mode) == - GPUTransparencyMode::Disabled); - const std::string fs = shadergen.GenerateBatchFragmentShader( - static_cast(render_mode), static_cast(transparency_mode), - shader_texmode, texture_filter, texture_filter_is_blended, upscaled, msaa, per_sample_shading, - uv_limits, !sprite && force_round_texcoords, modulation_crop, true_color, - ConvertToBoolUnchecked(dithering), scaled_dithering, disable_color_perspective, - ConvertToBoolUnchecked(interlacing), scaled_interlacing, ConvertToBoolUnchecked(check_mask), - m_write_mask_as_depth, use_rov, needs_rov_depth, rov_depth_test, rov_depth_write); + fssel.interlacing = ConvertToBoolUnchecked(interlacing); + fssel.scaled_interlacing = (fssel.interlacing && scaled_interlacing); if (!(batch_fragment_shaders[depth_test][render_mode][transparency_mode][texture_mode][check_mask] [dithering][interlacing] = g_gpu_device->CreateShader( - GPUShaderStage::Fragment, shadergen.GetLanguage(), fs, error))) + GPUShaderStage::Fragment, shadergen.GetLanguage(), + shadergen.GenerateBatchFragmentShader(fssel), error))) { return false; } diff --git a/src/core/gpu_hw_shadergen.cpp b/src/core/gpu_hw_shadergen.cpp index c049e50d5..8d37f8a83 100644 --- a/src/core/gpu_hw_shadergen.cpp +++ b/src/core/gpu_hw_shadergen.cpp @@ -72,58 +72,56 @@ std::string GPU_HW_ShaderGen::GenerateScreenVertexShader() const return std::move(ss).str(); } -std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool upscaled, bool msaa, bool per_sample_shading, - bool textured, bool palette, bool page_texture, bool uv_limits, - bool force_round_texcoords, bool pgxp_depth, - bool disable_color_perspective) const +std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(const BatchVertexShaderSelector sel) const { std::stringstream ss; WriteHeader(ss); - DefineMacro(ss, "TEXTURED", textured); - DefineMacro(ss, "PALETTE", palette); - DefineMacro(ss, "PAGE_TEXTURE", page_texture); - DefineMacro(ss, "UV_LIMITS", uv_limits); - DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords); - DefineMacro(ss, "PGXP_DEPTH", pgxp_depth); - DefineMacro(ss, "UPSCALED", upscaled); + DefineMacro(ss, "TEXTURED", sel.textured); + DefineMacro(ss, "PALETTE", sel.palette); + DefineMacro(ss, "PAGE_TEXTURE", sel.page_texture); + DefineMacro(ss, "UV_LIMITS", sel.uv_limits); + DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", sel.force_round_texcoords); + DefineMacro(ss, "PGXP_DEPTH", sel.pgxp_depth); + DefineMacro(ss, "UPSCALED", sel.upscaled); WriteBatchUniformBuffer(ss); - if (textured && page_texture) + if (sel.textured && sel.page_texture) { - if (uv_limits) + if (sel.uv_limits) { DeclareVertexEntryPoint( ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage", "float4 a_uv_limits"}, 1, 1, - {{"nointerpolation", "float4 v_uv_limits"}}, false, "", msaa, per_sample_shading, disable_color_perspective); + {{"nointerpolation", "float4 v_uv_limits"}}, false, "", sel.msaa, sel.per_sample_shading, + sel.disable_color_perspective); } else { DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage"}, 1, 1, {}, - false, "", msaa, per_sample_shading, disable_color_perspective); + false, "", sel.msaa, sel.per_sample_shading, sel.disable_color_perspective); } } - else if (textured) + else if (sel.textured) { - if (uv_limits) + if (sel.uv_limits) { DeclareVertexEntryPoint( ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage", "float4 a_uv_limits"}, 1, 1, - {{"nointerpolation", palette ? "uint4 v_texpage" : "uint2 v_texpage"}, + {{"nointerpolation", sel.palette ? "uint4 v_texpage" : "uint2 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}}, - false, "", msaa, per_sample_shading, disable_color_perspective); + false, "", sel.msaa, sel.per_sample_shading, sel.disable_color_perspective); } else { DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage"}, 1, 1, - {{"nointerpolation", palette ? "uint4 v_texpage" : "uint2 v_texpage"}}, false, "", msaa, - per_sample_shading, disable_color_perspective); + {{"nointerpolation", sel.palette ? "uint4 v_texpage" : "uint2 v_texpage"}}, false, "", + sel.msaa, sel.per_sample_shading, sel.disable_color_perspective); } } else { - DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0"}, 1, 0, {}, false, "", msaa, per_sample_shading, - disable_color_perspective); + DeclareVertexEntryPoint(ss, {"float4 a_pos", "float4 a_col0"}, 1, 0, {}, false, "", sel.msaa, + sel.per_sample_shading, sel.disable_color_perspective); } ss << R"( @@ -2142,59 +2140,54 @@ void FilteredSampleFromVRAM(TEXPAGE_VALUE texpage, float2 coords, float4 uv_limi } } -std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader( - GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency, GPU_HW::BatchTextureMode texture_mode, - GPUTextureFilter texture_filtering, bool is_blended_texture_filtering, bool upscaled, bool msaa, - bool per_sample_shading, bool uv_limits, bool force_round_texcoords, bool modulation_crop, bool true_color, - bool dithering, bool scaled_dithering, bool disable_color_perspective, bool interlacing, bool scaled_interlacing, - bool check_mask, bool write_mask_as_depth, bool use_rov, bool use_rov_depth, bool rov_depth_test, - bool rov_depth_write) const +std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(const BatchFragmentShaderSelector sel) const { - DebugAssert(!true_color || !dithering); // Should not be doing dithering+true color. + DebugAssert(!sel.true_color || !sel.dithering); // Should not be doing dithering+true color. - DebugAssert(transparency == GPUTransparencyMode::Disabled || render_mode == GPU_HW::BatchRenderMode::ShaderBlend); - DebugAssert((!rov_depth_test && !rov_depth_write) || (use_rov && use_rov_depth)); + DebugAssert(sel.transparency == GPUTransparencyMode::Disabled || + sel.render_mode == GPU_HW::BatchRenderMode::ShaderBlend); + DebugAssert((!sel.rov_depth_test && !sel.rov_depth_write) || (sel.use_rov && sel.use_rov_depth)); - const bool textured = (texture_mode != GPU_HW::BatchTextureMode::Disabled); - const bool palette = - (texture_mode == GPU_HW::BatchTextureMode::Palette4Bit || texture_mode == GPU_HW::BatchTextureMode::Palette8Bit); - const bool page_texture = (texture_mode == GPU_HW::BatchTextureMode::PageTexture); - const bool shader_blending = (render_mode == GPU_HW::BatchRenderMode::ShaderBlend); - const bool use_dual_source = (!shader_blending && !use_rov && m_supports_dual_source_blend && - ((render_mode != GPU_HW::BatchRenderMode::TransparencyDisabled && - render_mode != GPU_HW::BatchRenderMode::OnlyOpaque) || - is_blended_texture_filtering)); + const bool textured = (sel.texture_mode != GPU_HW::BatchTextureMode::Disabled); + const bool palette = (sel.texture_mode == GPU_HW::BatchTextureMode::Palette4Bit || + sel.texture_mode == GPU_HW::BatchTextureMode::Palette8Bit); + const bool page_texture = (sel.texture_mode == GPU_HW::BatchTextureMode::PageTexture); + const bool shader_blending = (sel.render_mode == GPU_HW::BatchRenderMode::ShaderBlend); + const bool use_dual_source = (!shader_blending && !sel.use_rov && m_supports_dual_source_blend && + ((sel.render_mode != GPU_HW::BatchRenderMode::TransparencyDisabled && + sel.render_mode != GPU_HW::BatchRenderMode::OnlyOpaque) || + sel.is_blended_texture_filtering)); std::stringstream ss; - WriteHeader(ss, use_rov, shader_blending && !use_rov, use_dual_source); - DefineMacro(ss, "TRANSPARENCY", render_mode != GPU_HW::BatchRenderMode::TransparencyDisabled); - DefineMacro(ss, "TRANSPARENCY_ONLY_OPAQUE", render_mode == GPU_HW::BatchRenderMode::OnlyOpaque); - DefineMacro(ss, "TRANSPARENCY_ONLY_TRANSPARENT", render_mode == GPU_HW::BatchRenderMode::OnlyTransparent); - DefineMacro(ss, "TRANSPARENCY_MODE", static_cast(transparency)); + WriteHeader(ss, sel.use_rov, shader_blending && !sel.use_rov, use_dual_source); + DefineMacro(ss, "TRANSPARENCY", sel.render_mode != GPU_HW::BatchRenderMode::TransparencyDisabled); + DefineMacro(ss, "TRANSPARENCY_ONLY_OPAQUE", sel.render_mode == GPU_HW::BatchRenderMode::OnlyOpaque); + DefineMacro(ss, "TRANSPARENCY_ONLY_TRANSPARENT", sel.render_mode == GPU_HW::BatchRenderMode::OnlyTransparent); + DefineMacro(ss, "TRANSPARENCY_MODE", static_cast(sel.transparency)); DefineMacro(ss, "SHADER_BLENDING", shader_blending); - DefineMacro(ss, "CHECK_MASK_BIT", check_mask); + DefineMacro(ss, "CHECK_MASK_BIT", sel.check_mask); DefineMacro(ss, "TEXTURED", textured); DefineMacro(ss, "PALETTE", palette); - DefineMacro(ss, "PALETTE_4_BIT", texture_mode == GPU_HW::BatchTextureMode::Palette4Bit); - DefineMacro(ss, "PALETTE_8_BIT", texture_mode == GPU_HW::BatchTextureMode::Palette8Bit); + DefineMacro(ss, "PALETTE_4_BIT", sel.texture_mode == GPU_HW::BatchTextureMode::Palette4Bit); + DefineMacro(ss, "PALETTE_8_BIT", sel.texture_mode == GPU_HW::BatchTextureMode::Palette8Bit); DefineMacro(ss, "PAGE_TEXTURE", page_texture); - DefineMacro(ss, "DITHERING", dithering); - DefineMacro(ss, "DITHERING_SCALED", dithering && scaled_dithering); - DefineMacro(ss, "INTERLACING", interlacing); - DefineMacro(ss, "INTERLACING_SCALED", interlacing && scaled_interlacing); - DefineMacro(ss, "MODULATION_CROP", modulation_crop); - DefineMacro(ss, "TRUE_COLOR", true_color); - DefineMacro(ss, "TEXTURE_FILTERING", texture_filtering != GPUTextureFilter::Nearest); - DefineMacro(ss, "TEXTURE_ALPHA_BLENDING", is_blended_texture_filtering); - DefineMacro(ss, "UV_LIMITS", uv_limits); - DefineMacro(ss, "USE_ROV", use_rov); - DefineMacro(ss, "USE_ROV_DEPTH", use_rov_depth); - DefineMacro(ss, "ROV_DEPTH_TEST", rov_depth_test); - DefineMacro(ss, "ROV_DEPTH_WRITE", rov_depth_write); + DefineMacro(ss, "DITHERING", sel.dithering); + DefineMacro(ss, "DITHERING_SCALED", sel.dithering && sel.scaled_dithering); + DefineMacro(ss, "INTERLACING", sel.interlacing); + DefineMacro(ss, "INTERLACING_SCALED", sel.interlacing && sel.scaled_interlacing); + DefineMacro(ss, "MODULATION_CROP", sel.modulation_crop); + DefineMacro(ss, "TRUE_COLOR", sel.true_color); + DefineMacro(ss, "TEXTURE_FILTERING", sel.texture_filtering != GPUTextureFilter::Nearest); + DefineMacro(ss, "TEXTURE_ALPHA_BLENDING", sel.is_blended_texture_filtering); + DefineMacro(ss, "UV_LIMITS", sel.uv_limits); + DefineMacro(ss, "USE_ROV", sel.use_rov); + DefineMacro(ss, "USE_ROV_DEPTH", sel.use_rov_depth); + DefineMacro(ss, "ROV_DEPTH_TEST", sel.rov_depth_test); + DefineMacro(ss, "ROV_DEPTH_WRITE", sel.rov_depth_write); DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source); - DefineMacro(ss, "WRITE_MASK_AS_DEPTH", write_mask_as_depth); - DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords); - DefineMacro(ss, "UPSCALED", upscaled); + DefineMacro(ss, "WRITE_MASK_AS_DEPTH", sel.write_mask_as_depth); + DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", sel.force_round_texcoords); + DefineMacro(ss, "UPSCALED", sel.upscaled); // Used for converting to normalized coordinates for sampling. ss << "CONSTANT float2 RCP_VRAM_SIZE = float2(1.0 / float(" << VRAM_WIDTH << "), 1.0 / float(" << VRAM_HEIGHT @@ -2204,10 +2197,10 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader( WriteBatchUniformBuffer(ss); DeclareTexture(ss, "samp0", 0); - if (use_rov) + if (sel.use_rov) { DeclareImage(ss, "rov_color", 0); - if (use_rov_depth) + if (sel.use_rov_depth) DeclareImage(ss, "rov_depth", 1, true); } @@ -2369,51 +2362,52 @@ float4 SampleFromVRAM(TEXPAGE_VALUE texpage, DECLARE_UV_LIMITS(float2 coords, fl #endif // TEXTURED )"; - const u32 num_fragment_outputs = use_rov ? 0 : (use_dual_source ? 2 : 1); + const u32 num_fragment_outputs = sel.use_rov ? 0 : (use_dual_source ? 2 : 1); if (textured && page_texture) { - if (texture_filtering != GPUTextureFilter::Nearest) - WriteBatchTextureFilter(ss, texture_filtering); + if (sel.texture_filtering != GPUTextureFilter::Nearest) + WriteBatchTextureFilter(ss, sel.texture_filtering); - if (uv_limits) + if (sel.uv_limits) { DeclareFragmentEntryPoint(ss, 1, 1, {{"nointerpolation", "float4 v_uv_limits"}}, true, num_fragment_outputs, - use_dual_source, write_mask_as_depth, msaa, per_sample_shading, false, - disable_color_perspective, shader_blending && !use_rov, use_rov); + use_dual_source, sel.write_mask_as_depth, sel.msaa, sel.per_sample_shading, false, + sel.disable_color_perspective, shader_blending && !sel.use_rov, sel.use_rov); } else { - DeclareFragmentEntryPoint(ss, 1, 1, {}, true, num_fragment_outputs, use_dual_source, write_mask_as_depth, msaa, - per_sample_shading, false, disable_color_perspective, shader_blending && !use_rov, - use_rov); + DeclareFragmentEntryPoint(ss, 1, 1, {}, true, num_fragment_outputs, use_dual_source, sel.write_mask_as_depth, + sel.msaa, sel.per_sample_shading, false, sel.disable_color_perspective, + shader_blending && !sel.use_rov, sel.use_rov); } } else if (textured) { - if (texture_filtering != GPUTextureFilter::Nearest) - WriteBatchTextureFilter(ss, texture_filtering); + if (sel.texture_filtering != GPUTextureFilter::Nearest) + WriteBatchTextureFilter(ss, sel.texture_filtering); - if (uv_limits) + if (sel.uv_limits) { DeclareFragmentEntryPoint(ss, 1, 1, {{"nointerpolation", palette ? "uint4 v_texpage" : "uint2 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}}, - true, num_fragment_outputs, use_dual_source, write_mask_as_depth, msaa, - per_sample_shading, false, disable_color_perspective, shader_blending && !use_rov, - use_rov); + true, num_fragment_outputs, use_dual_source, sel.write_mask_as_depth, sel.msaa, + sel.per_sample_shading, false, sel.disable_color_perspective, + shader_blending && !sel.use_rov, sel.use_rov); } else { DeclareFragmentEntryPoint(ss, 1, 1, {{"nointerpolation", palette ? "uint4 v_texpage" : "uint2 v_texpage"}}, true, - num_fragment_outputs, use_dual_source, write_mask_as_depth, msaa, per_sample_shading, - false, disable_color_perspective, shader_blending && !use_rov, use_rov); + num_fragment_outputs, use_dual_source, sel.write_mask_as_depth, sel.msaa, + sel.per_sample_shading, false, sel.disable_color_perspective, + shader_blending && !sel.use_rov, sel.use_rov); } } else { - DeclareFragmentEntryPoint(ss, 1, 0, {}, true, num_fragment_outputs, use_dual_source, write_mask_as_depth, msaa, - per_sample_shading, false, disable_color_perspective, shader_blending && !use_rov, - use_rov); + DeclareFragmentEntryPoint(ss, 1, 0, {}, true, num_fragment_outputs, use_dual_source, sel.write_mask_as_depth, + sel.msaa, sel.per_sample_shading, false, sel.disable_color_perspective, + shader_blending && !sel.use_rov, sel.use_rov); } ss << R"( diff --git a/src/core/gpu_hw_shadergen.h b/src/core/gpu_hw_shadergen.h index 707ca770c..02919adb5 100644 --- a/src/core/gpu_hw_shadergen.h +++ b/src/core/gpu_hw_shadergen.h @@ -9,23 +9,56 @@ class GPU_HW_ShaderGen : public ShaderGen { +public: + struct BatchVertexShaderSelector + { + bool upscaled : 1; + bool msaa : 1; + bool per_sample_shading : 1; + bool textured : 1; + bool palette : 1; + bool page_texture : 1; + bool uv_limits : 1; + bool force_round_texcoords : 1; + bool pgxp_depth : 1; + bool disable_color_perspective : 1; + }; + + struct BatchFragmentShaderSelector + { + GPU_HW::BatchRenderMode render_mode; + GPUTransparencyMode transparency; + GPU_HW::BatchTextureMode texture_mode; + GPUTextureFilter texture_filtering; + bool is_blended_texture_filtering; + bool upscaled : 1; + bool msaa : 1; + bool per_sample_shading : 1; + bool uv_limits : 1; + bool force_round_texcoords : 1; + bool modulation_crop : 1; + bool true_color : 1; + bool dithering : 1; + bool scaled_dithering : 1; + bool disable_color_perspective : 1; + bool interlacing : 1; + bool scaled_interlacing : 1; + bool check_mask : 1; + bool write_mask_as_depth : 1; + bool use_rov : 1; + bool use_rov_depth : 1; + bool rov_depth_test : 1; + bool rov_depth_write : 1; + }; + public: GPU_HW_ShaderGen(RenderAPI render_api, bool supports_dual_source_blend, bool supports_framebuffer_fetch); ~GPU_HW_ShaderGen(); std::string GenerateScreenVertexShader() const; - std::string GenerateBatchVertexShader(bool upscaled, bool msaa, bool per_sample_shading, bool textured, bool palette, - bool page_texture, bool uv_limits, bool force_round_texcoords, bool pgxp_depth, - bool disable_color_perspective) const; - std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency, - GPU_HW::BatchTextureMode texture_mode, GPUTextureFilter texture_filtering, - bool is_blended_texture_filtering, bool upscaled, bool msaa, - bool per_sample_shading, bool uv_limits, bool force_round_texcoords, - bool modulation_crop, bool true_color, bool dithering, bool scaled_dithering, - bool disable_color_perspective, bool interlacing, bool scaled_interlacing, - bool check_mask, bool write_mask_as_depth, bool use_rov, bool use_rov_depth, - bool rov_depth_test, bool rov_depth_write) const; + std::string GenerateBatchVertexShader(const BatchVertexShaderSelector sel) const; + std::string GenerateBatchFragmentShader(const BatchFragmentShaderSelector sel) const; std::string GenerateWireframeGeometryShader() const; std::string GenerateWireframeFragmentShader() const; std::string GenerateVRAMReadFragmentShader(u32 resolution_scale, u32 multisamples) const;