diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index 1626abdaf3..de7b4f8cf7 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -108,7 +108,7 @@ class program_state_cache } }; -private: +protected: size_t m_next_id = 0; binary_to_vertex_program m_vertex_shader_cache; binary_to_fragment_program m_fragment_shader_cache; diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 0765f8f0d6..29cd880657 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -52,6 +52,9 @@ void VKFragmentDecompilerThread::insertHeader(std::stringstream & OS) void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS) { + //It is possible for the two_sided_enabled flag to be set without actual 2-sided outputs + bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output); + for (const ParamType& PT : m_parr.params[PF_PARAM_IN]) { for (const ParamItem& PI : PT.items) @@ -62,7 +65,7 @@ void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS) const vk::varying_register_t ® = vk::get_varying_register(PI.name); std::string var_name = PI.name; - if (m_prog.front_back_color_enabled) + if (two_sided_enabled) { if (m_prog.back_color_diffuse_output && var_name == "diff_color") var_name = "back_diff_color"; @@ -78,15 +81,16 @@ void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS) } } - if (m_prog.front_back_color_enabled) + if (two_sided_enabled) { - if (m_prog.front_color_diffuse_output) + //Only include the front counterparts if the default output is for back only and exists. + if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output) { const vk::varying_register_t ® = vk::get_varying_register("front_diff_color"); OS << "layout(location=" << reg.reg_location << ") in vec4 front_diff_color;" << std::endl; } - if (m_prog.front_color_specular_output) + if (m_prog.front_color_specular_output && m_prog.back_color_specular_output) { const vk::varying_register_t ® = vk::get_varying_register("front_spec_color"); OS << "layout(location=" << reg.reg_location << ") in vec4 front_spec_color;" << std::endl; @@ -221,22 +225,48 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS) OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n"; - // search if there is fogc in inputs + bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output); + + //Some registers require redirection for (const ParamType& PT : m_parr.params[PF_PARAM_IN]) { for (const ParamItem& PI : PT.items) { - if (m_prog.front_back_color_enabled) + if (two_sided_enabled) { - if (PI.name == "spec_color" && m_prog.back_color_specular_output && m_prog.front_color_specular_output) + if (PI.name == "spec_color") { - OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n"; + //Only redirect/rename variables if the back_color exists + if (m_prog.back_color_specular_output) + { + if (m_prog.back_color_specular_output && m_prog.front_color_specular_output) + { + OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n"; + } + else + { + OS << " vec4 spec_color = back_spec_color;\n"; + } + } + continue; } - if (PI.name == "diff_color" && m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output) + else if (PI.name == "diff_color") { - OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n"; + //Only redirect/rename variables if the back_color exists + if (m_prog.back_color_diffuse_output) + { + if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output) + { + OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n"; + } + else + { + OS << " vec4 diff_color = back_diff_color;\n"; + } + } + continue; } } @@ -372,16 +402,9 @@ void VKFragmentProgram::Delete() if (handle) { - if (Emu.IsStopped()) - { - LOG_WARNING(RSX, "VKFragmentProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle); - } - else - { - VkDevice dev = (VkDevice)*vk::get_current_renderer(); - vkDestroyShaderModule(dev, handle, NULL); - handle = nullptr; - } + VkDevice dev = (VkDevice)*vk::get_current_renderer(); + vkDestroyShaderModule(dev, handle, NULL); + handle = nullptr; } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index e8218a704a..aa58f7a252 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -512,46 +512,66 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan) VKGSRender::~VKGSRender() { + //Wait for queue vkQueueWaitIdle(m_swap_chain->get_present_queue()); + //Sync objects if (m_present_semaphore) { vkDestroySemaphore((*m_device), m_present_semaphore, nullptr); m_present_semaphore = nullptr; } - vk::destroy_global_resources(); + if (m_submit_fence) + { + vkDestroyFence(*m_device, m_submit_fence, nullptr); + m_submit_fence = nullptr; + } - //TODO: Properly destroy shader modules instead of calling clear... + //Shaders m_prog_buffer.clear(); - m_index_buffer_ring_info.heap.release(); - m_uniform_buffer_ring_info.heap.release(); - m_attrib_ring_info.heap.release(); - m_texture_upload_buffer_ring_info.heap.release(); - null_buffer.release(); - null_buffer_view.release(); + //Global resources + vk::destroy_global_resources(); + + //Data heaps/buffers + m_index_buffer_ring_info.heap.reset(); + m_uniform_buffer_ring_info.heap.reset(); + m_attrib_ring_info.heap.reset(); + m_texture_upload_buffer_ring_info.heap.reset(); + + //Fallback bindables + null_buffer.reset(); + null_buffer_view.reset(); + + //Temporary objects m_buffer_view_to_clean.clear(); m_sampler_to_clean.clear(); m_framebuffer_to_clean.clear(); + //Render passes for (auto &render_pass : m_render_passes) if (render_pass) vkDestroyRenderPass(*m_device, render_pass, nullptr); + //Textures m_rtts.destroy(); + m_texture_cache.destroy(); + //Pipeline descriptors vkDestroyPipelineLayout(*m_device, pipeline_layout, nullptr); vkDestroyDescriptorSetLayout(*m_device, descriptor_layouts, nullptr); descriptor_pool.destroy(); + //Command buffer m_command_buffer.destroy(); m_command_buffer_pool.destroy(); + //Device handles/contexts m_swap_chain->destroy(); - m_thread_context.close(); + delete m_swap_chain; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 368fc6f9f0..7abb005dca 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -103,7 +103,7 @@ private: * Creates and fills an index buffer emulating unsupported primitive type. * Returns index_count and (offset_in_index_buffer, index_type) */ - std::tuple > generate_emulating_index_buffer(const rsx::draw_clause &clause); + std::tuple > generate_emulating_index_buffer(const rsx::draw_clause &clause, u32 vertex_count); public: bool load_program(); diff --git a/rpcs3/Emu/RSX/VK/VKProgramBuffer.h b/rpcs3/Emu/RSX/VK/VKProgramBuffer.h index 1f48a77e90..a5cd609b14 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramBuffer.h +++ b/rpcs3/Emu/RSX/VK/VKProgramBuffer.h @@ -151,4 +151,11 @@ struct VKTraits class VKProgramBuffer : public program_state_cache { +public: + void clear() + { + program_state_cache::clear(); + m_vertex_shader_cache.clear(); + m_fragment_shader_cache.clear(); + } }; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 9add90be66..f6791b898a 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -159,11 +159,11 @@ namespace rsx struct vk_render_targets : public rsx::surface_store { - void destroy() { m_render_targets_storage.clear(); m_depth_stencil_storage.clear(); + invalidated_resources.clear(); } }; } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index ff8457cf96..32372d0029 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -134,6 +134,23 @@ namespace vk unlock_memory_region(static_cast(obj.protected_rgn_start), static_cast(obj.native_rsx_size)); } + void purge_cache() + { + for (cached_texture_object &tex : m_cache) + { + if (tex.exists) + m_dirty_textures.push_back(std::move(tex.uploaded_texture)); + + if (tex.locked) + unlock_object(tex); + } + + m_temporary_image_view.clear(); + m_dirty_textures.clear(); + + m_cache.resize(0); + } + public: texture_cache() {} @@ -141,7 +158,7 @@ namespace vk void destroy() { - m_cache.resize(0); + purge_cache(); } vk::image_view* upload_texture(command_buffer cmd, rsx::texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer) diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index 8d967c41dc..84c7378fc7 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -242,7 +242,7 @@ VKGSRender::upload_vertex_data() { if (primitives_emulated) { - std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause); + std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause, rsx::method_registers.current_draw_clause.get_elements_count()); } else { @@ -256,6 +256,11 @@ VKGSRender::upload_vertex_data() if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array) { index_count = upload_inlined_array(); + + if (primitives_emulated) + { + std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause, index_count); + } } if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array || rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed) @@ -454,6 +459,7 @@ u32 VKGSRender::upload_inlined_array() m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size)); m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets); } + return vertex_draw_count; } @@ -478,10 +484,8 @@ std::tuple> VKGSRender::upl } -std::tuple > VKGSRender::generate_emulating_index_buffer(const rsx::draw_clause &clause) +std::tuple > VKGSRender::generate_emulating_index_buffer(const rsx::draw_clause &clause, u32 vertex_count) { - u32 vertex_count = clause.get_elements_count(); - u32 index_count = get_index_count(clause.primitive, vertex_count); u32 upload_size = index_count * sizeof(u16); diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 145ce7536b..876e01ac99 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -196,13 +196,9 @@ namespace vk if (real_input.location != PI.location) continue; - std::string vecType = " vec4 "; - if (real_input.int_type) - vecType = " ivec4 "; - if (!real_input.is_array) { - OS << vecType << PI.name << " = texelFetch(" << PI.name << "_buffer, 0);" << std::endl; + OS << " vec4 " << PI.name << " = vec4(texelFetch(" << PI.name << "_buffer, 0));" << std::endl; return; } @@ -210,19 +206,19 @@ namespace vk { if (real_input.is_modulo) { - OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex %" << real_input.frequency << ");" << std::endl; + OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex %" << real_input.frequency << "));" << std::endl; return; } - OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex /" << real_input.frequency << ");" << std::endl; + OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex /" << real_input.frequency << "));" << std::endl; return; } - OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba;" << std::endl; + OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba);" << std::endl; return; } - OS << " vec4 " << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba;" << std::endl; + OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba);" << std::endl; } } @@ -336,15 +332,8 @@ void VKVertexProgram::Delete() if (handle) { - if (Emu.IsStopped()) - { - LOG_WARNING(RSX, "VKVertexProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle); - } - else - { - VkDevice dev = (VkDevice)*vk::get_current_renderer(); - vkDestroyShaderModule(dev, handle, nullptr); - } + VkDevice dev = (VkDevice)*vk::get_current_renderer(); + vkDestroyShaderModule(dev, handle, nullptr); handle = nullptr; }