diff --git a/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.cpp b/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.cpp index 6773a4d78f..f4253e1d51 100644 --- a/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.cpp +++ b/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.cpp @@ -50,7 +50,7 @@ namespace vk idx++; - bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; bindings[idx].descriptorCount = 1; bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; bindings[idx].binding = binding_table.vertex_constant_buffers_bind_slot; @@ -101,7 +101,8 @@ namespace vk return bindings; } - std::tuple get_common_pipeline_layout(VkDevice dev) + std::tuple> + get_common_pipeline_layout(VkDevice dev) { const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table(); auto bindings = get_common_binding_table(); @@ -155,6 +156,25 @@ namespace vk VkPipelineLayout result; CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result)); - return std::make_tuple(result, set_layout); + return std::make_tuple(result, set_layout, bindings); + } + + rsx::simple_array get_descriptor_pool_sizes(const rsx::simple_array& bindings) + { + // Compile descriptor pool sizes + const u32 num_ubo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? y.descriptorCount : 0))); + const u32 num_texel_buffers = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? y.descriptorCount : 0))); + const u32 num_combined_image_sampler = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? y.descriptorCount : 0))); + const u32 num_ssbo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? y.descriptorCount : 0))); + + ensure(num_ubo > 0 && num_texel_buffers > 0 && num_combined_image_sampler > 0 && num_ssbo > 0); + + return + { + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , num_ubo }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , num_texel_buffers }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , num_combined_image_sampler }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_ssbo } + }; } } diff --git a/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.h b/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.h index 7c64d67982..371d0ebf76 100644 --- a/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.h +++ b/rpcs3/Emu/RSX/VK/VKCommonPipelineLayout.h @@ -7,8 +7,11 @@ namespace vk { // Grab standard layout for decompiled RSX programs. Also used by the interpreter. // FIXME: This generates a bloated monstrosity that needs to die. - std::tuple get_common_pipeline_layout(VkDevice dev); + std::tuple> get_common_pipeline_layout(VkDevice dev); // Returns the standard binding layout without texture slots. Those have special handling depending on the consumer. rsx::simple_array get_common_binding_table(); + + // Returns an array of pool sizes that can be used to generate a proper descriptor pool + rsx::simple_array get_descriptor_pool_sizes(const rsx::simple_array& bindings); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index dd9d080ecd..d58212a1aa 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -491,7 +491,8 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) m_secondary_cb_list.create(m_secondary_command_buffer_pool, vk::command_buffer::access_type_hint::all); //Precalculated stuff - std::tie(m_pipeline_layout, m_descriptor_layouts) = vk::get_common_pipeline_layout(*m_device); + rsx::simple_array binding_layout; + std::tie(m_pipeline_layout, m_descriptor_layouts, binding_layout) = vk::get_common_pipeline_layout(*m_device); //Occlusion m_occlusion_query_manager = std::make_unique(*m_device, VK_QUERY_TYPE_OCCLUSION, OCCLUSION_MAX_POOL_SIZE); @@ -507,18 +508,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) // Generate frame contexts const u32 max_draw_calls = m_device->get_descriptor_max_draw_calls(); - const auto& binding_table = m_device->get_pipeline_binding_table(); - const u32 num_fs_samplers = binding_table.vertex_textures_first_bind_slot - binding_table.textures_first_bind_slot; - - rsx::simple_array descriptor_type_sizes = - { - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 6 }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , 3 }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , (num_fs_samplers + 4) }, - - // Conditional rendering predicate slot; refactor to allow skipping this when not needed - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 } - }; + const auto descriptor_type_sizes = vk::get_descriptor_pool_sizes(binding_layout); m_descriptor_pool.create(*m_device, descriptor_type_sizes, max_draw_calls); VkSemaphoreCreateInfo semaphore_info = {}; @@ -531,7 +521,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) 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_UNIFORM_TEXEL_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer", 0x10000, VK_TRUE); m_fragment_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment constants buffer"); - m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer"); + m_transform_constants_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer"); m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer"); m_texture_upload_buffer_ring_info.create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M * 0x100000, "texture upload buffer", 32 * 0x100000); m_raster_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "raster env buffer"); @@ -2107,7 +2097,7 @@ void VKGSRender::load_program_env() usz mem_offset = 0; auto alloc_storage = [&](usz size) -> std::pair { - const auto alignment = m_device->gpu().get_limits().minUniformBufferOffsetAlignment; + const auto alignment = m_device->gpu().get_limits().minStorageBufferOffsetAlignment; mem_offset = m_transform_constants_ring_info.alloc<1>(utils::align(size, alignment)); return std::make_pair(m_transform_constants_ring_info.map(mem_offset, size), size); }; @@ -2225,7 +2215,7 @@ void VKGSRender::load_program_env() const auto& binding_table = m_device->get_pipeline_binding_table(); m_program->bind_uniform(m_vertex_env_buffer_info, binding_table.vertex_params_bind_slot, m_current_frame->descriptor_set); - m_program->bind_uniform(m_vertex_constants_buffer_info, binding_table.vertex_constant_buffers_bind_slot, m_current_frame->descriptor_set); + m_program->bind_buffer(m_vertex_constants_buffer_info, binding_table.vertex_constant_buffers_bind_slot, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_current_frame->descriptor_set); m_program->bind_uniform(m_fragment_env_buffer_info, binding_table.fragment_state_bind_slot, m_current_frame->descriptor_set); m_program->bind_uniform(m_fragment_texture_params_buffer_info, binding_table.fragment_texture_params_bind_slot, m_current_frame->descriptor_set); m_program->bind_uniform(m_raster_env_buffer_info, binding_table.rasterizer_env_bind_slot, m_current_frame->descriptor_set); diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp index c0a713ec00..3c9188fd60 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp @@ -330,21 +330,7 @@ namespace vk idx++; bindings.resize(idx); - // Compile descriptor pool sizes - const u32 num_ubo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? y.descriptorCount : 0))); - const u32 num_texel_buffers = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? y.descriptorCount : 0))); - const u32 num_combined_image_sampler = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? y.descriptorCount : 0))); - const u32 num_ssbo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? y.descriptorCount : 0))); - - ensure(num_ubo > 0 && num_texel_buffers > 0 && num_combined_image_sampler > 0 && num_ssbo > 0); - - m_descriptor_pool_sizes = - { - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , num_ubo }, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , num_texel_buffers }, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , num_combined_image_sampler }, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_ssbo } - }; + m_descriptor_pool_sizes = get_descriptor_pool_sizes(bindings); std::array push_constants; push_constants[0].offset = 0; diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 0e88dab75d..8dbb9c968a 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -115,15 +115,15 @@ void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std { if (!(m_prog.ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS)) { - OS << "layout(std140, set=0, binding=" << static_cast(m_binding_table.vertex_constant_buffers_bind_slot) << ") uniform VertexConstantsBuffer\n"; + OS << "layout(std430, set=0, binding=" << static_cast(m_binding_table.vertex_constant_buffers_bind_slot) << ") readonly buffer VertexConstantsBuffer\n"; OS << "{\n"; - OS << " vec4 " << PI.name << ";\n"; + OS << " vec4 vc[];\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; + in.type = vk::glsl::input_type_storage_buffer; inputs.push_back(in); continue;