vk/gl: Do not sample currently bound render targets

- Create temporary copies for use with the draw call instead
This commit is contained in:
kd-11 2017-06-14 01:38:39 +03:00
parent db1a90d828
commit 0cb6dee474
5 changed files with 123 additions and 15 deletions

View file

@ -663,15 +663,32 @@ namespace gl
/**
* Check for sampleable rtts from previous render passes
*/
gl::texture *texptr = nullptr;
gl::render_target *texptr = nullptr;
if (texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
{
for (auto tex : m_rtts.m_bound_render_targets)
{
if (std::get<0>(tex) == texaddr)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height());
return;
}
}
texptr->bind();
return;
}
if (texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
{
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height());
return;
}
texptr->bind();
return;
}

View file

@ -123,10 +123,10 @@ namespace vk
case VK_FORMAT_R32G32B32A32_SFLOAT:
color_format_idx = 3;
break;
case VK_FORMAT_R8_UINT:
case VK_FORMAT_R8_UNORM:
color_format_idx = 4;
break;
case VK_FORMAT_R8G8_UINT:
case VK_FORMAT_R8G8_UNORM:
color_format_idx = 5;
break;
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
@ -359,7 +359,7 @@ namespace
std::array<VkRenderPass, 120> result = {};
const std::array<VkFormat, 3> depth_format_list = { VK_FORMAT_UNDEFINED, VK_FORMAT_D16_UNORM, gpu_format_support.d24_unorm_s8 ? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT };
const std::array<VkFormat, 8> color_format_list = { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_R32_SFLOAT };
const std::array<VkFormat, 8> color_format_list = { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_R32_SFLOAT };
for (const VkFormat &color_format : color_format_list)
@ -1265,6 +1265,7 @@ void VKGSRender::process_swap_request()
//m_texture_cache.merge_dirty_textures(m_rtts.invalidated_resources);
m_rtts.invalidated_resources.clear();
m_rtts.invalidate_surface_cache_data(&*m_current_command_buffer);
m_texture_cache.flush();
m_buffer_view_to_clean.clear();

View file

@ -255,6 +255,12 @@ namespace vk
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
}
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout, VkImageSubresourceRange range)
{
change_image_layout(cmd, image->value, image->current_layout, new_layout, range);
image->current_layout = new_layout;
}
void enter_uninterruptible()
{
g_cb_no_interrupt_flag = true;

View file

@ -56,6 +56,7 @@ namespace vk
class swap_chain_image;
class physical_device;
class command_buffer;
struct image;
vk::context *get_current_thread_ctx();
void set_current_thread_ctx(const vk::context &ctx);
@ -73,6 +74,7 @@ namespace vk
void destroy_global_resources();
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range);
void change_image_layout(VkCommandBuffer cmd, vk::image *image, VkImageLayout new_layout, VkImageSubresourceRange range);
void copy_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 width, u32 height, u32 mipmaps, VkImageAspectFlagBits aspect);
void copy_scaled_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height, u32 mipmaps, VkImageAspectFlagBits aspect);
@ -358,7 +360,8 @@ namespace vk
struct image
{
VkImage value;
VkComponentMapping native_layout = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkComponentMapping native_component_map = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
VkImageLayout current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageCreateInfo info = {};
std::shared_ptr<vk::memory_block> memory;
@ -416,6 +419,21 @@ namespace vk
image(const image&) = delete;
image(image&&) = delete;
u32 width() const
{
return info.extent.width;
}
u32 height() const
{
return info.extent.height;
}
u32 depth() const
{
return info.extent.depth;
}
private:
VkDevice m_device;
};

View file

@ -128,8 +128,7 @@ namespace vk
return (protection == utils::protection::rw && uploaded_image_view.get() == nullptr && managed_texture.get() == nullptr);
}
void copy_texture(vk::command_buffer& cmd, u32 heap_index, VkQueue submit_queue,
bool manage_cb_lifetime = false, VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
void copy_texture(vk::command_buffer& cmd, u32 heap_index, VkQueue submit_queue, bool manage_cb_lifetime = false)
{
if (m_device == nullptr)
{
@ -172,9 +171,10 @@ namespace vk
VkImageSubresourceRange subresource_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
change_image_layout(cmd, vram_texture->value, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
VkImageLayout layout = vram_texture->current_layout;
change_image_layout(cmd, vram_texture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
vkCmdCopyImageToBuffer(cmd, vram_texture->value, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dma_buffer->value, 1, &copyRegion);
change_image_layout(cmd, vram_texture->value, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout, subresource_range);
change_image_layout(cmd, vram_texture, layout, subresource_range);
if (manage_cb_lifetime)
{
@ -227,7 +227,7 @@ namespace vk
if (!synchronized)
{
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
copy_texture(cmd, heap_index, submit_queue, true, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
copy_texture(cmd, heap_index, submit_queue, true);
}
protect(utils::protection::rw);
@ -297,7 +297,7 @@ namespace vk
return tex;
else
{
LOG_ERROR(RSX, "Cached object for address 0x%X was found, but it does not match stored parameters.");
LOG_ERROR(RSX, "Cached object for address 0x%X was found, but it does not match stored parameters.", rsx_address);
LOG_ERROR(RSX, "%d x %d vs %d x %d", width, height, tex.get_width(), tex.get_height());
}
}
@ -396,6 +396,57 @@ namespace vk
return { mapping[1], mapping[2], mapping[3], mapping[0] };
}
vk::image_view* create_temporary_subresource(vk::command_buffer& cmd, vk::image* source, u32 x, u32 y, u32 w, u32 h, const vk::memory_type_mapping &memory_type_mapping)
{
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
switch (source->info.format)
{
case VK_FORMAT_D16_UNORM:
aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
break;
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
break;
}
VkImageSubresourceRange subresource_range = { aspect, 0, 1, 0, 1 };
std::unique_ptr<vk::image> image;
std::unique_ptr<vk::image_view> view;
image.reset(new vk::image(*vk::get_current_renderer(), memory_type_mapping.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
source->info.imageType,
source->info.format,
source->width(), source->height(), source->depth(), 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, source->info.flags));
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_2D, source->info.format, source->native_component_map, view_range));
VkImageLayout old_src_layout = source->current_layout;
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_GENERAL, subresource_range);
vk::change_image_layout(cmd, source, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
VkImageCopy copy_rgn;
copy_rgn.srcOffset = { (s32)x, (s32)y, 0 };
copy_rgn.dstOffset = { (s32)x, (s32)y, 0 };
copy_rgn.dstSubresource = { aspect, 0, 0, 1 };
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
copy_rgn.extent = { w, h, 1 };
vkCmdCopyImage(cmd, source->value, source->current_layout, image->value, image->current_layout, 1, &copy_rgn);
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
vk::change_image_layout(cmd, source, old_src_layout, subresource_range);
m_dirty_textures.push_back(std::move(image));
m_temporary_image_view.push_back(std::move(view));
return m_temporary_image_view.back().get();
}
public:
texture_cache() {}
@ -422,16 +473,31 @@ namespace vk
vk::image *rtt_texture = nullptr;
if (rtt_texture = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
{
for (auto tex : m_rtts.m_bound_render_targets)
{
if (std::get<0>(tex) == texaddr)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping);
}
}
m_temporary_image_view.push_back(std::make_unique<vk::image_view>(*vk::get_current_renderer(), rtt_texture->value, VK_IMAGE_VIEW_TYPE_2D, rtt_texture->info.format,
rtt_texture->native_layout,
rtt_texture->native_component_map,
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT)));
return m_temporary_image_view.back().get();
}
if (rtt_texture = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
if (std::get<0>(m_rtts.m_bound_depth_stencil) == texaddr)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping);
}
m_temporary_image_view.push_back(std::make_unique<vk::image_view>(*vk::get_current_renderer(), rtt_texture->value, VK_IMAGE_VIEW_TYPE_2D, rtt_texture->info.format,
rtt_texture->native_layout,
rtt_texture->native_component_map,
vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_DEPTH_BIT)));
return m_temporary_image_view.back().get();
}
@ -501,7 +567,7 @@ namespace vk
vk_format,
tex.width(), height, depth, tex.get_exact_mipmap_count(), layer, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0);
change_image_layout(cmd, image->value, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
change_image_layout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
vk::image_view *view = new vk::image_view(*vk::get_current_renderer(), image->value, image_view_type, vk_format,
mapping,
@ -513,7 +579,7 @@ namespace vk
copy_mipmaped_image_using_buffer(cmd, image->value, get_subresources_layout(tex), format, !(tex.format() & CELL_GCM_TEXTURE_LN), tex.get_exact_mipmap_count(),
upload_heap, upload_buffer);
change_image_layout(cmd, image->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
change_image_layout(cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
vk::leave_uninterruptible();