diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 3481db1a8d..2749a6592f 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -292,7 +292,7 @@ namespace rsx const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool swizzled, const std::pair, std::array>& remap_vector) = 0; virtual void enforce_surface_creation_type(section_storage_type& section, u32 gcm_format, texture_create_flags expected) = 0; virtual void set_up_remap_vector(section_storage_type& section, const std::pair, std::array>& remap_vector) = 0; - virtual void insert_texture_barrier() = 0; + virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0; virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array& sources) = 0; constexpr u32 get_block_size() const { return 0x1000000; } @@ -1120,7 +1120,7 @@ namespace rsx } template - sampled_image_descriptor process_framebuffer_resource(render_target_type texptr, u32 texaddr, u32 gcm_format, surface_store_type& m_rtts, + sampled_image_descriptor process_framebuffer_resource(commandbuffer_type& cmd, render_target_type texptr, u32 texaddr, u32 gcm_format, surface_store_type& m_rtts, u16 tex_width, u16 tex_height, rsx::texture_dimension_extended extended_dimension, bool is_depth) { const u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); @@ -1244,7 +1244,7 @@ namespace rsx else { //issue a texture barrier to ensure previous writes are visible - insert_texture_barrier(); + insert_texture_barrier(cmd, texptr); break; } } @@ -1262,7 +1262,7 @@ namespace rsx else { //issue a texture barrier to ensure previous writes are visible - insert_texture_barrier(); + insert_texture_barrier(cmd, texptr); } } } @@ -1324,7 +1324,7 @@ namespace rsx { if (test_framebuffer(texaddr + texptr->raster_address_offset)) { - return process_framebuffer_resource(texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, extended_dimension, false); + return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, extended_dimension, false); } else { @@ -1337,7 +1337,7 @@ namespace rsx { if (test_framebuffer(texaddr + texptr->raster_address_offset)) { - return process_framebuffer_resource(texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, extended_dimension, true); + return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, extended_dimension, true); } else { @@ -1395,7 +1395,7 @@ namespace rsx if (rsc.is_bound) { LOG_WARNING(RSX, "Sampling from a currently bound render target @ 0x%x", texaddr); - insert_texture_barrier(); + insert_texture_barrier(cmd, rsc.surface); } return{ rsc.surface->get_view(), texture_upload_context::framebuffer_storage, rsc.is_depth_surface, diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 47edcb05ab..263ef35adb 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -837,7 +837,7 @@ namespace gl section.set_sampler_status(rsx::texture_sampler_status::status_ready); } - void insert_texture_barrier() override + void insert_texture_barrier(void*&, gl::texture*) override { auto &caps = gl::get_driver_caps(); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 0d8dad1ca2..d7044f3daf 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -388,6 +388,45 @@ namespace vk image->current_layout = new_layout; } + void insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout layout, VkImageSubresourceRange range) + { + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.newLayout = layout; + barrier.oldLayout = layout; + barrier.image = image; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange = range; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + VkPipelineStageFlags src_stage; + if (range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) + { + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } + else + { + barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + } + + vkCmdPipelineBarrier(cmd, src_stage, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); + } + + void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image) + { + if (image->info.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + { + insert_texture_barrier(cmd, image->value, image->current_layout, { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 }); + } + else + { + insert_texture_barrier(cmd, image->value, image->current_layout, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); + } + } + void enter_uninterruptible() { g_cb_no_interrupt_flag = true; diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index f0400d2188..f69ff3decf 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -90,6 +90,10 @@ namespace vk std::pair get_compatible_surface_format(rsx::surface_color_format color_format); size_t get_render_pass_location(VkFormat color_surface_format, VkFormat depth_stencil_format, u8 color_surface_count); + //Texture barrier applies to a texture to ensure writes to it are finished before any reads are attempted to avoid RAW hazards + void insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout layout, VkImageSubresourceRange range); + void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image); + void enter_uninterruptible(); void leave_uninterruptible(); bool is_uninterruptible(); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 2917e0fffb..ca9f2f6562 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -831,8 +831,10 @@ namespace vk section.set_sampler_status(rsx::texture_sampler_status::status_ready); } - void insert_texture_barrier() override - {} + void insert_texture_barrier(vk::command_buffer& cmd, vk::image* tex) override + { + vk::insert_texture_barrier(cmd, tex); + } public: