diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 279c342922..8541c34abe 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1757,6 +1757,20 @@ void VKGSRender::end() //Requires update, copy subresource view = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc); } + else + { + switch (view->image()->current_layout) + { + default: + //case VK_IMAGE_LAYOUT_GENERAL: + //case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + verify(HERE), sampler_state->upload_context == rsx::texture_upload_context::blit_engine_dst; + view->image()->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + break; + } + } } if (LIKELY(view)) @@ -1792,14 +1806,14 @@ void VKGSRender::end() } else { - m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, i, ::glsl::program_domain::glsl_fragment_program, m_current_frame->descriptor_set); if (current_fragment_program.redirected_textures & (1 << i)) { - m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, i, ::glsl::program_domain::glsl_fragment_program, m_current_frame->descriptor_set, @@ -1815,7 +1829,7 @@ void VKGSRender::end() { if (!rsx::method_registers.vertex_textures[i].enabled()) { - m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, i, ::glsl::program_domain::glsl_vertex_program, m_current_frame->descriptor_set); @@ -1835,10 +1849,22 @@ void VKGSRender::end() if (!image_ptr) { LOG_ERROR(RSX, "Texture upload failed to vtexture index %d. Binding null sampler.", i); - m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::vertex_texture_names[i], m_current_frame->descriptor_set); + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, rsx::constants::vertex_texture_names[i], m_current_frame->descriptor_set); continue; } + switch (image_ptr->image()->current_layout) + { + default: + //case VK_IMAGE_LAYOUT_GENERAL: + //case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + verify(HERE), sampler_state->upload_context == rsx::texture_upload_context::blit_engine_dst; + image_ptr->image()->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + break; + } + m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, image_ptr->image()->current_layout }, i, ::glsl::program_domain::glsl_vertex_program, @@ -2265,9 +2291,14 @@ void VKGSRender::clear_surface(u32 mask) { if (require_mem_load) rtt->write_barrier(*m_current_command_buffer); - vk::insert_texture_barrier(*m_current_command_buffer, rtt); + // Add a barrier to ensure previous writes are visible; also transitions into GENERAL layout + const auto old_layout = rtt->current_layout; + vk::insert_texture_barrier(*m_current_command_buffer, rtt, VK_IMAGE_LAYOUT_GENERAL); + m_attachment_clear_pass->run(*m_current_command_buffer, rtt, region.rect, renderpass, m_framebuffers_to_clean); + + rtt->change_layout(*m_current_command_buffer, old_layout); } else fmt::throw_exception("Unreachable" HERE); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 3adc3e6a03..629cdf61b6 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -152,18 +152,16 @@ namespace vk return g_null_sampler; } - VkImageView null_image_view(vk::command_buffer &cmd) + vk::image_view* null_image_view(vk::command_buffer &cmd) { if (g_null_image_view) - return g_null_image_view->value; + return g_null_image_view.get(); g_null_texture.reset(new image(*g_current_renderer, g_current_renderer->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_B8G8R8A8_UNORM, 4, 4, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0)); - g_null_image_view.reset(new image_view(*g_current_renderer, g_null_texture->value, VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_B8G8R8A8_UNORM, {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1})); + g_null_image_view.reset(new image_view(*g_current_renderer, g_null_texture.get())); // Initialize memory to transparent black VkClearColorValue clear_color = {}; @@ -173,7 +171,7 @@ namespace vk // Prep for shader access change_image_layout(cmd, g_null_texture.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range); - return g_null_image_view->value; + return g_null_image_view.get(); } vk::image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height) @@ -562,7 +560,7 @@ namespace vk image->current_layout = new_layout; } - void insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout layout, VkImageSubresourceRange range) + void insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range) { // NOTE: Sampling from an attachment in ATTACHMENT_OPTIMAL layout on some hw ends up with garbage output // Transition to GENERAL if this resource is both input and output @@ -573,7 +571,7 @@ namespace vk VkPipelineStageFlags src_stage; if (range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { - if (!rsx::method_registers.color_write_enabled() && layout == VK_IMAGE_LAYOUT_GENERAL) + if (!rsx::method_registers.color_write_enabled() && current_layout == new_layout) { // Nothing to do return; @@ -584,7 +582,7 @@ namespace vk } else { - if (!rsx::method_registers.depth_write_enabled() && layout == VK_IMAGE_LAYOUT_GENERAL) + if (!rsx::method_registers.depth_write_enabled() && current_layout == new_layout) { // Nothing to do return; @@ -596,8 +594,8 @@ namespace vk VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.oldLayout = layout; + barrier.newLayout = new_layout; + barrier.oldLayout = current_layout; barrier.image = image; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; @@ -608,10 +606,10 @@ namespace vk 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) + void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout) { - insert_texture_barrier(cmd, image->value, image->current_layout, { image->aspect(), 0, 1, 0, 1 }); - image->current_layout = VK_IMAGE_LAYOUT_GENERAL; + insert_texture_barrier(cmd, image->value, image->current_layout, new_layout, { image->aspect(), 0, 1, 0, 1 }); + image->current_layout = new_layout; } void enter_uninterruptible() diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 8136b9a089..ae2930fcb8 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -88,6 +88,7 @@ namespace vk class physical_device; class command_buffer; class image; + struct image_view; struct buffer; struct data_heap; class mem_allocator_base; @@ -116,7 +117,7 @@ namespace vk VkImageAspectFlags get_aspect_flags(VkFormat format); VkSampler null_sampler(); - VkImageView null_image_view(vk::command_buffer&); + image_view* null_image_view(vk::command_buffer&); image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height); buffer* get_scratch_buffer(); @@ -166,8 +167,8 @@ namespace vk 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 insert_texture_barrier(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range); + void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout); void insert_buffer_memory_barrier(VkCommandBuffer cmd, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize length, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src_mask, VkAccessFlags dst_mask); diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index 5a0f322ca2..af8c434033 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -219,7 +219,7 @@ namespace vk return result; } - void load_program(vk::command_buffer cmd, VkRenderPass pass, const std::vector& src) + void load_program(vk::command_buffer cmd, VkRenderPass pass, const std::vector& src) { vk::glsl::program *program = nullptr; auto found = m_program_cache.find(pass); @@ -252,7 +252,7 @@ namespace vk for (int n = 0; n < src.size(); ++n) { - VkDescriptorImageInfo info = { m_sampler->value, src[n], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; + VkDescriptorImageInfo info = { m_sampler->value, src[n]->value, src[n]->image()->current_layout }; program->bind_uniform(info, "fs" + std::to_string(n), m_descriptor_set); } @@ -360,7 +360,7 @@ namespace vk vkCmdSetScissor(cmd, 0, 1, &vs); } - void run(vk::command_buffer &cmd, u16 w, u16 h, vk::framebuffer* fbo, const std::vector& src, VkRenderPass render_pass) + void run(vk::command_buffer &cmd, u16 w, u16 h, vk::framebuffer* fbo, const std::vector& src, VkRenderPass render_pass) { load_program(cmd, render_pass, src); set_up_viewport(cmd, w, h); @@ -379,7 +379,7 @@ namespace vk vkCmdEndRenderPass(cmd); } - void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, const std::vector& src, VkRenderPass render_pass, std::list>& framebuffer_resources) + void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, const std::vector& src, VkRenderPass render_pass, std::list>& framebuffer_resources) { vk::framebuffer *fbo = get_framebuffer(target, render_pass, framebuffer_resources); @@ -388,15 +388,10 @@ namespace vk static_cast(fbo)->release(); } - void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, VkImageView src, VkRenderPass render_pass, std::list>& framebuffer_resources) - { - std::vector views = { src }; - run(cmd, w, h, target, views, render_pass, framebuffer_resources); - } - void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, vk::image_view* src, VkRenderPass render_pass, std::list>& framebuffer_resources) { - run(cmd, w, h, target, src->value, render_pass, framebuffer_resources); + std::vector views = { src }; + run(cmd, w, h, target, views, render_pass, framebuffer_resources); } }; @@ -821,13 +816,13 @@ namespace vk break; case rsx::overlays::image_resource_id::font_file: m_texture_type = 2; - src = find_font(command.config.font_ref, cmd, upload_heap)->value; + src = find_font(command.config.font_ref, cmd, upload_heap); break; case rsx::overlays::image_resource_id::raw_image: - src = find_temp_image((rsx::overlays::image_info*)command.config.external_data_ref, cmd, upload_heap, ui.uid)->value; + src = find_temp_image((rsx::overlays::image_info*)command.config.external_data_ref, cmd, upload_heap, ui.uid); break; default: - src = view_cache[command.config.texture_ref]->value; + src = view_cache[command.config.texture_ref].get(); break; } @@ -938,7 +933,7 @@ namespace vk region = rect; overlay_pass::run(cmd, target->width(), target->height(), target, - target->get_view(0xAAE4, rsx::default_remap_vector)->value, + target->get_view(0xAAE4, rsx::default_remap_vector), render_pass, framebuffer_resources); } }; diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 91494c0fce..139a75c7ac 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -1043,7 +1043,7 @@ namespace vk void insert_texture_barrier(vk::command_buffer& cmd, vk::image* tex) override { - vk::insert_texture_barrier(cmd, tex); + vk::insert_texture_barrier(cmd, tex, VK_IMAGE_LAYOUT_GENERAL); } bool render_target_format_is_compatible(vk::image* tex, u32 gcm_format) override