From d057ffe80f74aca648b5733230495a5d86c2810b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 23 Mar 2022 23:59:42 +0300 Subject: [PATCH] rsx: Fix program generation and compact referenced data blocks --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 7 +++- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 22 +++++++---- rpcs3/Emu/RSX/Program/ShaderParam.h | 3 +- .../RSX/Program/VertexProgramDecompiler.cpp | 12 +++--- .../Emu/RSX/Program/VertexProgramDecompiler.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 8 ++-- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 11 ++++-- rpcs3/Emu/RSX/VK/VKVertexProgram.cpp | 37 +++++++++++-------- 8 files changed, 61 insertions(+), 41 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index e7d4660e55..1655dd5f98 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -800,11 +800,14 @@ void GLGSRender::load_program_env() if (update_transform_constants) { // Vertex constants - auto mapping = m_transform_constants_buffer->alloc_from_heap(8192, m_uniform_buffer_offset_align); + const std::vector& constant_ids = m_vertex_prog ? m_vertex_prog->constant_ids : std::vector{}; + const usz transform_constants_size = constant_ids.empty() ? 8192 : constant_ids.size() * 16; + + auto mapping = m_transform_constants_buffer->alloc_from_heap(transform_constants_size, m_uniform_buffer_offset_align); auto buf = static_cast(mapping.first); fill_vertex_program_constants_data(buf, m_vertex_prog ? m_vertex_prog->constant_ids : std::vector{}); - m_transform_constants_buffer->bind_range(GL_VERTEX_CONSTANT_BUFFERS_BIND_SLOT, mapping.second, 8192); + m_transform_constants_buffer->bind_range(GL_VERTEX_CONSTANT_BUFFERS_BIND_SLOT, mapping.second, transform_constants_size); } if (update_fragment_constants && !update_instruction_buffers) diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index df895a25e6..9ebb5c0507 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -58,17 +58,21 @@ void GLVertexDecompilerThread::insertInputs(std::stringstream& OS, const std::ve void GLVertexDecompilerThread::insertConstants(std::stringstream& OS, const std::vector& constants) { - OS << "layout(std140, binding = 2) uniform VertexConstantsBuffer\n"; - OS << "{\n"; - OS << " vec4 vc[468];\n"; - OS << "};\n\n"; + for (const ParamType &PT: constants) { for (const ParamItem &PI : PT.items) { - if (PI.name == "vc[468]") + if (PI.name.starts_with("vc[")) + { + OS << "layout(std140, binding = 2) uniform VertexConstantsBuffer\n"; + OS << "{\n"; + OS << " vec4 " << PI.name << ";\n"; + OS << "};\n\n"; + continue; + } OS << "uniform " << PT.type << " " << PI.name << ";\n"; } @@ -272,10 +276,14 @@ void GLVertexProgram::Decompile(const RSXVertexProgram& prog) GLVertexDecompilerThread decompiler(prog, source, parr); decompiler.Task(); + if (has_indexed_constants = decompiler.properties.has_indexed_constants; + !has_indexed_constants) + { + constant_ids = std::vector(decompiler.m_constant_ids.begin(), decompiler.m_constant_ids.end()); + } + shader.create(::glsl::program_domain::glsl_vertex_program, source); id = shader.id(); - has_indexed_constants = decompiler.properties.has_indexed_constants; - constant_ids = std::move(decompiler.m_constant_ids); } void GLVertexProgram::Delete() diff --git a/rpcs3/Emu/RSX/Program/ShaderParam.h b/rpcs3/Emu/RSX/Program/ShaderParam.h index 8eb51611ca..a0fc26a2a7 100644 --- a/rpcs3/Emu/RSX/Program/ShaderParam.h +++ b/rpcs3/Emu/RSX/Program/ShaderParam.h @@ -145,7 +145,7 @@ struct ParamType std::vector new_list; for (const auto& it : items) { - if (it.name != item.name) + if (it.name != name) { new_list.emplace_back(it.name, it.location, it.value); } @@ -156,6 +156,7 @@ struct ParamType } std::swap(items, new_list); + return true; } items.push_back(item); diff --git a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp index 459aafe132..d1846aba0e 100644 --- a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.cpp @@ -127,7 +127,7 @@ std::string VertexProgramDecompiler::GetSRC(const u32 n) case RSX_VP_REGISTER_TYPE_CONSTANT: m_parr.AddParam(PF_PARAM_UNIFORM, getFloatTypeName(4), std::string("vc[468]")); properties.has_indexed_constants |= !!d3.index_const; - m_constant_ids.push_back(d1.const_src); + m_constant_ids.insert(static_cast(d1.const_src)); ret += std::string("vc[") + std::to_string(d1.const_src) + (d3.index_const ? " + " + AddAddrReg() : "") + "]"; break; @@ -399,20 +399,20 @@ std::string VertexProgramDecompiler::BuildCode() std::vector> reloc_table; reloc_table.reserve(m_constant_ids.size()); - // First sort the data in ascending order - std::sort(m_constant_ids.begin(), m_constant_ids.end()); - // Build the string lookup table + int offset = 0; for (const auto& index : m_constant_ids) { - reloc_table.emplace_back(fmt::format("vc[%d]", index), fmt::format("vc[%llu]", reloc_table.size())); + const auto i = offset++; + if (i == index) continue; // Replace with self + reloc_table.emplace_back(fmt::format("vc[%d]", index), fmt::format("vc[%d]", i)); } // One-time patch main_body = fmt::replace_all(main_body, reloc_table); // Rename the array type - auto type_list = ensure(m_parr.SearchParam(PF_PARAM_CONST, getFloatTypeName(4))); + auto type_list = ensure(m_parr.SearchParam(PF_PARAM_UNIFORM, getFloatTypeName(4))); const auto item = ParamItem(fmt::format("vc[%llu]", m_constant_ids.size()), -1); type_list->ReplaceOrInsert("vc[468]", item); } diff --git a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h index 7d74d58973..2065e2ead7 100644 --- a/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Program/VertexProgramDecompiler.h @@ -63,7 +63,7 @@ struct VertexProgramDecompiler const RSXVertexProgram& m_prog; ParamArray m_parr; - std::vector m_constant_ids; + std::set m_constant_ids; static std::string NotZeroPositive(const std::string& code); std::string GetMask(bool is_sca) const; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 835cf35c2a..bc931c887b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -863,10 +863,6 @@ namespace rsx void thread::fill_vertex_program_constants_data(void* buffer, const std::vector& reloc_table) { if (!reloc_table.empty()) [[ likely ]] - { - memcpy(buffer, rsx::method_registers.transform_constants.data(), 468 * 4 * sizeof(float)); - } - else { char* dst = reinterpret_cast(buffer); for (const auto& index : reloc_table) @@ -875,6 +871,10 @@ namespace rsx dst += 16; } } + else + { + memcpy(buffer, rsx::method_registers.transform_constants.data(), 468 * 4 * sizeof(float)); + } } void thread::fill_fragment_state_buffer(void* buffer, const RSXFragmentProgram& /*fragment_program*/) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index b810ec1555..65b206e688 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1955,12 +1955,15 @@ void VKGSRender::load_program_env() check_heap_status(VK_HEAP_CHECK_TRANSFORM_CONSTANTS_STORAGE); // Transform constants - auto mem = m_transform_constants_ring_info.alloc<256>(8192); - auto buf = m_transform_constants_ring_info.map(mem, 8192); + const std::vector& constant_ids = m_vertex_prog ? m_vertex_prog->constant_ids : std::vector{}; + const usz transform_constants_size = constant_ids.empty() ? 8192 : utils::align(constant_ids.size() * 16, m_device->gpu().get_limits().minUniformBufferOffsetAlignment); - fill_vertex_program_constants_data(buf, m_vertex_prog ? m_vertex_prog->constant_ids : std::vector{}); + auto mem = m_transform_constants_ring_info.alloc<1>(transform_constants_size); + auto buf = m_transform_constants_ring_info.map(mem, transform_constants_size); + + fill_vertex_program_constants_data(buf, constant_ids); m_transform_constants_ring_info.unmap(); - m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, mem, 8192 }; + m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, mem, transform_constants_size }; } if (update_fragment_constants && !update_instruction_buffers) diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index d031528762..2b278cedac 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -101,27 +101,28 @@ void VKVertexDecompilerThread::insertInputs(std::stringstream& OS, const std::ve void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std::vector & constants) { - OS << "layout(std140, set=0, binding = 1) uniform VertexConstantsBuffer\n"; - OS << "{\n"; - OS << " vec4 vc[468];\n"; - OS << "};\n\n"; - vk::glsl::program_input in; - in.location = m_binding_table.vertex_constant_buffers_bind_slot; - in.domain = glsl::glsl_vertex_program; - in.name = "VertexConstantsBuffer"; - in.type = vk::glsl::input_type_uniform_buffer; - - inputs.push_back(in); - - u32 location = m_binding_table.vertex_textures_first_bind_slot; + for (const ParamType &PT : constants) { for (const ParamItem &PI : PT.items) { - if (PI.name == "vc[468]") + if (PI.name.starts_with("vc[")) + { + OS << "layout(std140, set=0, binding = " << static_cast(m_binding_table.vertex_constant_buffers_bind_slot) << ") uniform VertexConstantsBuffer\n"; + OS << "{\n"; + OS << " vec4 " << PI.name << ";\n"; + OS << "};\n\n"; + + in.location = m_binding_table.vertex_constant_buffers_bind_slot; + in.domain = glsl::glsl_vertex_program; + in.name = "VertexConstantsBuffer"; + in.type = vk::glsl::input_type_uniform_buffer; + + inputs.push_back(in); continue; + } if (PT.type == "sampler2D" || PT.type == "samplerCube" || @@ -349,9 +350,13 @@ void VKVertexProgram::Decompile(const RSXVertexProgram& prog) VKVertexDecompilerThread decompiler(prog, source, parr, *this); decompiler.Task(); + if (has_indexed_constants = decompiler.properties.has_indexed_constants; + !has_indexed_constants) + { + constant_ids = std::vector(decompiler.m_constant_ids.begin(), decompiler.m_constant_ids.end()); + } + shader.create(::glsl::program_domain::glsl_vertex_program, source); - has_indexed_constants = decompiler.properties.has_indexed_constants; - constant_ids = std::move(decompiler.m_constant_ids); } void VKVertexProgram::Compile()