diff --git a/rpcs3/Emu/RSX/Program/GLSLInterpreter/FragmentInterpreter.glsl b/rpcs3/Emu/RSX/Program/GLSLInterpreter/FragmentInterpreter.glsl index e06110f0a6..fb5e5854ab 100644 --- a/rpcs3/Emu/RSX/Program/GLSLInterpreter/FragmentInterpreter.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLInterpreter/FragmentInterpreter.glsl @@ -552,6 +552,9 @@ void main() ur1 = ur0 & 31u; // address % 32 -> fetch bit offset ur1 = (1u << ur1); // address mask uvr0.x = (ur0 >> 7u); // address to uvec4 row (each row has 32x4 bits) +#ifdef VULKAN + uvr0.x += fs_stipple_pattern_array_offset; // Address base offset. Only applies to vulkan. +#endif ur0 = (ur0 >> 5u) & 3u; // address to uvec4 word (address / 32) % 4 if ((stipple_pattern[uvr0.x][ur0] & ur1) == 0u) diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl index df3add46e5..62ec4a06c0 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXDefines2.glsl @@ -32,6 +32,8 @@ struct draw_parameters_t uint fs_constants_offset; uint fs_context_offset; uint fs_texture_base_index; + uint fs_stipple_pattern_offset; + uint reserved; uvec2 attrib_data[16]; }; diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPPrologue.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPPrologue.glsl index e39f3481c8..02e3ba9b75 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPPrologue.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPPrologue.glsl @@ -7,7 +7,12 @@ R"( const uvec2 stipple_coord = uvec2(gl_FragCoord.xy) % uvec2(32, 32); const uint address = stipple_coord.y * 32u + stipple_coord.x; const uint bit_offset = (address & 31u); + #ifdef VULKAN + // In vulkan we have a unified array with a dynamic offset + const uint word_index = _get_bits(address, 7, 3) + fs_stipple_pattern_array_offset; + #else const uint word_index = _get_bits(address, 7, 3); + #endif const uint sub_index = _get_bits(address, 5, 2); if (!_test_bit(stipple_pattern[word_index][sub_index], int(bit_offset))) diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 62863c6194..ff233e3a04 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -820,8 +820,8 @@ void VKGSRender::emit_geometry(u32 sub_index) update_descriptors = true; // Allocate stream layout memory for this batch - const u64 alloc_size = rsx::method_registers.current_draw_clause.pass_count() * 160; - m_vertex_layout_dynamic_offset = m_vertex_layout_ring_info.alloc<16>(alloc_size); + const u64 alloc_size = rsx::method_registers.current_draw_clause.pass_count() * 168; + m_vertex_layout_dynamic_offset = m_vertex_layout_ring_info.alloc<8>(alloc_size); } // Update vertex fetch parameters diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 7d5a90ef6e..979f22d58f 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -235,7 +235,8 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) "#define get_draw_params() draw_parameters[draw_parameters_offset]\n" "#define fs_constants_offset get_draw_params().fs_constants_offset\n" "#define fs_context_offset get_draw_params().fs_context_offset\n" - "#define fs_texture_base_index get_draw_params().fs_texture_base_index\n\n"; + "#define fs_texture_base_index get_draw_params().fs_texture_base_index\n" + "#define fs_stipple_pattern_array_offset get_draw_params().fs_stipple_pattern_offset\n\n"; if (!properties.constant_offsets.empty()) { @@ -257,9 +258,9 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) OS << " sampler_info texture_parameters[];\n"; OS << "};\n\n"; - OS << "layout(std140, set=1, binding=" << vk_prog->binding_table.polygon_stipple_params_location << ") uniform RasterizerHeap\n"; + OS << "layout(std430, set=1, binding=" << vk_prog->binding_table.polygon_stipple_params_location << ") readonly buffer RasterizerHeap\n"; OS << "{\n"; - OS << " uvec4 stipple_pattern[8];\n"; + OS << " uvec4 stipple_pattern[];\n"; OS << "};\n\n"; vk::glsl::program_input in @@ -287,7 +288,7 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) inputs.push_back(in); in.location = vk_prog->binding_table.polygon_stipple_params_location; - in.type = vk::glsl::input_type_uniform_buffer; + in.type = vk::glsl::input_type_storage_buffer; in.name = "RasterizerHeap"; inputs.push_back(in); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cd9d591b5e..c7c53489ef 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -555,7 +555,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) 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, VK_WHOLE_SIZE }; m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, VK_WHOLE_SIZE }; - m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, 128 }; + m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_vertex_layout_stream_info = { m_vertex_layout_ring_info.heap->value, 0, VK_WHOLE_SIZE }; m_fragment_constants_buffer_info = { m_fragment_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE }; @@ -2038,12 +2038,11 @@ void VKGSRender::load_program_env() if (update_raster_env) { - auto mem = m_raster_env_ring_info.static_alloc<256>(); - auto buf = m_raster_env_ring_info.map(mem, 128); + m_stipple_array_dynamic_offset = m_raster_env_ring_info.static_alloc<128>(); + auto buf = m_raster_env_ring_info.map(m_stipple_array_dynamic_offset, 128); std::memcpy(buf, ctx->polygon_stipple_pattern(), 128); m_raster_env_ring_info.unmap(); - m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, mem, 128 }; m_graphics_state.clear(rsx::pipeline_state::polygon_stipple_pattern_dirty); } @@ -2194,6 +2193,8 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ u32 fs_constants_offset; u32 fs_context_offset; u32 fs_texture_base_index; + u32 fs_stipple_pattern_offset; + u32 reserved; s32 attrib_data[1]; }; #pragma pack(pop) @@ -2201,12 +2202,13 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ // Actual allocation must have been done previously const u32 vs_constant_id_offset = static_cast(m_xform_constants_dynamic_offset) / 16u; 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) / 160u; + const u32 vertex_layout_offset = static_cast(m_vertex_layout_dynamic_offset) / 168u; 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; const u32 fs_texture_base_index = static_cast(m_texture_parameters_dynamic_offset) / 48u; + const u32 fs_stipple_pattern_offset = static_cast(m_stipple_array_dynamic_offset) / 16u; - auto buf = m_vertex_layout_ring_info.map(m_vertex_layout_dynamic_offset + (160u * id), 160u); + auto buf = m_vertex_layout_ring_info.map(m_vertex_layout_dynamic_offset + (168u * id), 168u); auto dst = reinterpret_cast(buf); // Pack @@ -2220,6 +2222,7 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ dst->fs_constants_offset = fs_constant_id_offset; dst->fs_context_offset = fs_context_offset; dst->fs_texture_base_index = fs_texture_base_index; + dst->fs_stipple_pattern_offset = fs_stipple_pattern_offset; const u32 push_val = vertex_layout_offset + id; vkCmdPushConstants( diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index f26ef515b4..1b6ff56c5d 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -156,6 +156,7 @@ private: u64 m_fragment_constants_dynamic_offset = 0; u64 m_fragment_env_dynamic_offset = 0; u64 m_texture_parameters_dynamic_offset = 0; + u64 m_stipple_array_dynamic_offset = 0; std::array frame_context_storage; //Temp frame context to use if the real frame queue is overburdened. Only used for storage