From 183acd419670ccdc0b9d49918a6deb753af12fd0 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 30 Jul 2025 02:38:52 +0300 Subject: [PATCH] vk: Move FS context vars to block format --- rpcs3/Emu/RSX/Program/GLSLCommon.cpp | 7 --- .../GLSLSnippets/RSXProg/RSXDefines2.glsl | 12 +++++ rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp | 44 +++++++++++++------ rpcs3/Emu/RSX/VK/VKGSRender.cpp | 12 ++--- rpcs3/Emu/RSX/VK/VKGSRender.h | 1 + 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index f751711c43..6d4dcffef0 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -177,13 +177,6 @@ namespace glsl enabled_options.push_back("_ENABLE_LIT_EMULATION"); } - OS << "#define _select mix\n"; - OS << "#define _saturate(x) clamp(x, 0., 1.)\n"; - OS << "#define _get_bits(x, off, count) bitfieldExtract(x, off, count)\n"; - OS << "#define _set_bits(x, y, off, count) bitfieldInsert(x, y, off, count)\n"; - OS << "#define _test_bit(x, y) (_get_bits(x, y, 1) != 0)\n"; - OS << "#define _rand(seed) fract(sin(dot(seed.xy, vec2(12.9898f, 78.233f))) * 43758.5453f)\n\n"; - if (props.require_clip_functions) { OS << diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl index a8900d7dc3..67e9e0b2c6 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl @@ -31,4 +31,16 @@ struct vertex_layout_t uvec2 attrib_data[16]; }; +struct fragment_context_t +{ + float fog_param0; + float fog_param1; + uint rop_control; + float alpha_ref; + uint reserved; + uint fog_mode; + float wpos_scale; + float wpos_bias; +}; + )" diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index d7181881ba..716b9c095d 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -227,24 +227,18 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) if (!properties.constant_offsets.empty()) { - OS << "layout(std140, set=1, binding=" << vk_prog->binding_table.cbuf_location << ") readonly buffer FragmentConstantsBuffer\n"; + OS << "layout(std430, set=1, binding=" << vk_prog->binding_table.cbuf_location << ") readonly buffer FragmentConstantsBuffer\n"; OS << "{\n"; OS << " vec4 fc[];\n"; OS << "};\n"; OS << "#define _fetch_constant(x) fc[x + fs_constants_offset]\n\n"; } - OS << "layout(std140, set=1, binding=" << vk_prog->binding_table.context_buffer_location << ") uniform FragmentStateBuffer\n"; - OS << "{\n"; - OS << " float fog_param0;\n"; - OS << " float fog_param1;\n"; - OS << " uint rop_control;\n"; - OS << " float alpha_ref;\n"; - OS << " uint reserved;\n"; - OS << " uint fog_mode;\n"; - OS << " float wpos_scale;\n"; - OS << " float wpos_bias;\n"; - OS << "};\n\n"; + OS << + "layout(std430, set=1, binding=" << vk_prog->binding_table.context_buffer_location << ") readonly buffer FragmentStateBuffer\n" + "{\n" + " fragment_context_t fs_contexts[];\n" + "};\n\n"; OS << "layout(std140, set=1, binding=" << vk_prog->binding_table.tex_param_location << ") uniform TextureParametersBuffer\n"; OS << "{\n"; @@ -272,11 +266,12 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) in.location = vk_prog->binding_table.context_buffer_location; in.name = "FragmentStateBuffer"; - in.type = vk::glsl::input_type_uniform_buffer; + in.type = vk::glsl::input_type_storage_buffer; inputs.push_back(in); in.location = vk_prog->binding_table.tex_param_location; in.name = "TextureParametersBuffer"; + in.type = vk::glsl::input_type_uniform_buffer; inputs.push_back(in); in.location = vk_prog->binding_table.polygon_stipple_params_location; @@ -287,13 +282,14 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) "layout(push_constant) uniform push_constants_block\n" "{\n" " layout(offset=12) uint fs_constants_offset;\n" + " uint fs_context_offset;\n" "};\n\n"; const vk::glsl::program_input push_constants { .domain = glsl::glsl_fragment_program, .type = vk::glsl::input_type_push_constant, - .bound_data = vk::glsl::push_constant_ref{.offset = 12, .size = 4 }, + .bound_data = vk::glsl::push_constant_ref{.offset = 12, .size = 8 }, .set = vk::glsl::binding_set_index_vertex, .location = umax, .name = "fs_push_constants_block" @@ -326,6 +322,22 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS) m_shader_props.require_tex3D_ops = properties.has_tex3D; m_shader_props.require_shadowProj_ops = properties.shadow_sampler_mask != 0 && properties.has_texShadowProj; + // Declare global constants + if (m_shader_props.require_fog_read) + { + OS << + "const float fog_param0 = fs_contexts[fs_context_offset].fog_param0;\n" + "const float fog_param1 = fs_contexts[fs_context_offset].fog_param1;\n" + "const uint fog_mode = fs_contexts[fs_context_offset].fog_mode;\n\n"; + } + + if (m_shader_props.require_wpos) + { + OS << + "const float wpos_scale fs_contexts[fs_context_offset].wpos_scale;\n" + "const float wpos_bias fs_contexts[fs_context_offset].wpos_bias;\n\n"; + } + glsl::insert_glsl_legacy_function(OS, m_shader_props); } @@ -419,6 +431,10 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) OS << "void main()\n"; OS << "{\n"; + OS << + " const uint rop_control = fs_contexts[fs_context_offset].rop_control;\n" + " const float alpha_ref = fs_contexts[fs_context_offset].alpha_ref;\n\n"; + ::glsl::insert_rop_init(OS); OS << "\n" << " fs_main();\n\n"; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index bde3db47ac..f1d105ff79 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -510,7 +510,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) // VRAM allocation m_attrib_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000, "attrib buffer", 0x400000, VK_TRUE); - m_fragment_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment env buffer"); + m_fragment_env_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment env buffer"); m_vertex_env_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex env buffer"); m_fragment_texture_params_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment texture params buffer"); m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer", 0x10000, VK_TRUE); @@ -553,7 +553,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) // Initialize optional allocation information with placeholders m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; - m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, 16 }; + m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, 16 }; m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, 128 }; m_vertex_layout_stream_info = { m_vertex_layout_ring_info.heap->value, 0, VK_WHOLE_SIZE }; @@ -2020,12 +2020,11 @@ void VKGSRender::load_program_env() if (update_fragment_env) { - auto mem = m_fragment_env_ring_info.static_alloc<256>(); - auto buf = m_fragment_env_ring_info.map(mem, 32); + m_fragment_env_dynamic_offset = m_fragment_env_ring_info.static_alloc<32>(); + auto buf = m_fragment_env_ring_info.map(m_fragment_env_dynamic_offset, 32); m_draw_processor.fill_fragment_state_buffer(buf, current_fragment_program); m_fragment_env_ring_info.unmap(); - m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, mem, 32 }; } if (update_fragment_texture_env) @@ -2196,6 +2195,7 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ struct rsx_fs_prog_push_constants_block_t { u32 fs_constants_offset; + u32 fs_context_offset; }; struct rsx_prog_vertex_layout_entry_t @@ -2213,6 +2213,7 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ const u32 vertex_context_offset = static_cast(m_vertex_env_dynamic_offset) / 96u; const u32 vertex_layout_offset = static_cast(m_vertex_layout_dynamic_offset) / 144u; const u32 fs_constant_id_offset = static_cast(m_fragment_constants_dynamic_offset) / 16u; + const u32 fs_context_offset = static_cast(m_fragment_env_dynamic_offset) / 32u; // Pack rsx_vs_prog_push_constants_block_t vs_push_constants; @@ -2222,6 +2223,7 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ rsx_fs_prog_push_constants_block_t fs_push_constants; fs_push_constants.fs_constants_offset = fs_constant_id_offset; + fs_push_constants.fs_context_offset = fs_context_offset; vkCmdPushConstants( *m_current_command_buffer, diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 77f3e1e838..f0515325de 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -154,6 +154,7 @@ private: u64 m_vertex_env_dynamic_offset = 0; u64 m_vertex_layout_dynamic_offset = 0; u64 m_fragment_constants_dynamic_offset = 0; + u64 m_fragment_env_dynamic_offset = 0; std::array frame_context_storage; //Temp frame context to use if the real frame queue is overburdened. Only used for storage