vk: Propagate more information to the driver

- Pass "correct" layout to descriptors
- TODO: Fix renderpass attachment descriptors which are inadvertently doing silent transitions
This commit is contained in:
kd-11 2019-05-20 10:27:09 +03:00 committed by kd-11
parent c3b234f972
commit 46ba53f122
5 changed files with 63 additions and 38 deletions

View file

@ -1757,6 +1757,20 @@ void VKGSRender::end()
//Requires update, copy subresource //Requires update, copy subresource
view = m_texture_cache.create_temporary_subresource(*m_current_command_buffer, sampler_state->external_subresource_desc); 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)) if (LIKELY(view))
@ -1792,14 +1806,14 @@ void VKGSRender::end()
} }
else 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, i,
::glsl::program_domain::glsl_fragment_program, ::glsl::program_domain::glsl_fragment_program,
m_current_frame->descriptor_set); m_current_frame->descriptor_set);
if (current_fragment_program.redirected_textures & (1 << i)) 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, i,
::glsl::program_domain::glsl_fragment_program, ::glsl::program_domain::glsl_fragment_program,
m_current_frame->descriptor_set, m_current_frame->descriptor_set,
@ -1815,7 +1829,7 @@ void VKGSRender::end()
{ {
if (!rsx::method_registers.vertex_textures[i].enabled()) 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, i,
::glsl::program_domain::glsl_vertex_program, ::glsl::program_domain::glsl_vertex_program,
m_current_frame->descriptor_set); m_current_frame->descriptor_set);
@ -1835,10 +1849,22 @@ void VKGSRender::end()
if (!image_ptr) if (!image_ptr)
{ {
LOG_ERROR(RSX, "Texture upload failed to vtexture index %d. Binding null sampler.", i); 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; 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 }, m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, image_ptr->image()->current_layout },
i, i,
::glsl::program_domain::glsl_vertex_program, ::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); 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, m_attachment_clear_pass->run(*m_current_command_buffer, rtt,
region.rect, renderpass, m_framebuffers_to_clean); region.rect, renderpass, m_framebuffers_to_clean);
rtt->change_layout(*m_current_command_buffer, old_layout);
} }
else else
fmt::throw_exception("Unreachable" HERE); fmt::throw_exception("Unreachable" HERE);

View file

@ -152,18 +152,16 @@ namespace vk
return g_null_sampler; 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) 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, 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_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)); 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, g_null_image_view.reset(new image_view(*g_current_renderer, g_null_texture.get()));
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}));
// Initialize memory to transparent black // Initialize memory to transparent black
VkClearColorValue clear_color = {}; VkClearColorValue clear_color = {};
@ -173,7 +171,7 @@ namespace vk
// Prep for shader access // Prep for shader access
change_image_layout(cmd, g_null_texture.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range); 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) vk::image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height)
@ -562,7 +560,7 @@ namespace vk
image->current_layout = new_layout; 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 // 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 // Transition to GENERAL if this resource is both input and output
@ -573,7 +571,7 @@ namespace vk
VkPipelineStageFlags src_stage; VkPipelineStageFlags src_stage;
if (range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) 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 // Nothing to do
return; return;
@ -584,7 +582,7 @@ namespace vk
} }
else 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 // Nothing to do
return; return;
@ -596,8 +594,8 @@ namespace vk
VkImageMemoryBarrier barrier = {}; VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; barrier.newLayout = new_layout;
barrier.oldLayout = layout; barrier.oldLayout = current_layout;
barrier.image = image; barrier.image = image;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcQueueFamilyIndex = 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); 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 }); insert_texture_barrier(cmd, image->value, image->current_layout, new_layout, { image->aspect(), 0, 1, 0, 1 });
image->current_layout = VK_IMAGE_LAYOUT_GENERAL; image->current_layout = new_layout;
} }
void enter_uninterruptible() void enter_uninterruptible()

View file

@ -88,6 +88,7 @@ namespace vk
class physical_device; class physical_device;
class command_buffer; class command_buffer;
class image; class image;
struct image_view;
struct buffer; struct buffer;
struct data_heap; struct data_heap;
class mem_allocator_base; class mem_allocator_base;
@ -116,7 +117,7 @@ namespace vk
VkImageAspectFlags get_aspect_flags(VkFormat format); VkImageAspectFlags get_aspect_flags(VkFormat format);
VkSampler null_sampler(); 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); image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height);
buffer* get_scratch_buffer(); 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); 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 //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, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range);
void insert_texture_barrier(VkCommandBuffer cmd, vk::image *image); 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, 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); VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src_mask, VkAccessFlags dst_mask);

View file

@ -219,7 +219,7 @@ namespace vk
return result; return result;
} }
void load_program(vk::command_buffer cmd, VkRenderPass pass, const std::vector<VkImageView>& src) void load_program(vk::command_buffer cmd, VkRenderPass pass, const std::vector<vk::image_view*>& src)
{ {
vk::glsl::program *program = nullptr; vk::glsl::program *program = nullptr;
auto found = m_program_cache.find(pass); auto found = m_program_cache.find(pass);
@ -252,7 +252,7 @@ namespace vk
for (int n = 0; n < src.size(); ++n) 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); program->bind_uniform(info, "fs" + std::to_string(n), m_descriptor_set);
} }
@ -360,7 +360,7 @@ namespace vk
vkCmdSetScissor(cmd, 0, 1, &vs); vkCmdSetScissor(cmd, 0, 1, &vs);
} }
void run(vk::command_buffer &cmd, u16 w, u16 h, vk::framebuffer* fbo, const std::vector<VkImageView>& src, VkRenderPass render_pass) void run(vk::command_buffer &cmd, u16 w, u16 h, vk::framebuffer* fbo, const std::vector<vk::image_view*>& src, VkRenderPass render_pass)
{ {
load_program(cmd, render_pass, src); load_program(cmd, render_pass, src);
set_up_viewport(cmd, w, h); set_up_viewport(cmd, w, h);
@ -379,7 +379,7 @@ namespace vk
vkCmdEndRenderPass(cmd); vkCmdEndRenderPass(cmd);
} }
void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, const std::vector<VkImageView>& src, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources) void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, const std::vector<vk::image_view*>& src, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
{ {
vk::framebuffer *fbo = get_framebuffer(target, render_pass, framebuffer_resources); vk::framebuffer *fbo = get_framebuffer(target, render_pass, framebuffer_resources);
@ -388,15 +388,10 @@ namespace vk
static_cast<vk::framebuffer_holder*>(fbo)->release(); static_cast<vk::framebuffer_holder*>(fbo)->release();
} }
void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, VkImageView src, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
{
std::vector<VkImageView> 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<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources) void run(vk::command_buffer &cmd, u16 w, u16 h, vk::image* target, vk::image_view* src, VkRenderPass render_pass, std::list<std::unique_ptr<vk::framebuffer_holder>>& framebuffer_resources)
{ {
run(cmd, w, h, target, src->value, render_pass, framebuffer_resources); std::vector<vk::image_view*> views = { src };
run(cmd, w, h, target, views, render_pass, framebuffer_resources);
} }
}; };
@ -821,13 +816,13 @@ namespace vk
break; break;
case rsx::overlays::image_resource_id::font_file: case rsx::overlays::image_resource_id::font_file:
m_texture_type = 2; 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; break;
case rsx::overlays::image_resource_id::raw_image: 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; break;
default: default:
src = view_cache[command.config.texture_ref]->value; src = view_cache[command.config.texture_ref].get();
break; break;
} }
@ -938,7 +933,7 @@ namespace vk
region = rect; region = rect;
overlay_pass::run(cmd, target->width(), target->height(), target, 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); render_pass, framebuffer_resources);
} }
}; };

View file

@ -1043,7 +1043,7 @@ namespace vk
void insert_texture_barrier(vk::command_buffer& cmd, vk::image* tex) override 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 bool render_target_format_is_compatible(vk::image* tex, u32 gcm_format) override