vulkan: implement proper texture read barriers

This commit is contained in:
kd-11 2018-02-01 10:44:57 +03:00
parent b9cca71c47
commit eeb6e29e39
5 changed files with 55 additions and 10 deletions

View File

@ -292,7 +292,7 @@ namespace rsx
const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, bool swizzled, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& 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<u8, 4>, std::array<u8, 4>>& 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<image_resource_type, 6>& sources) = 0;
constexpr u32 get_block_size() const { return 0x1000000; }
@ -1120,7 +1120,7 @@ namespace rsx
}
template <typename render_target_type, typename surface_store_type>
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,

View File

@ -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();

View File

@ -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;

View File

@ -90,6 +90,10 @@ namespace vk
std::pair<VkFormat, VkComponentMapping> 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();

View File

@ -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: