From 6850533b50a6717cf2dc62bd2c8ab76608284f7d Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 9 Aug 2020 16:28:13 +0300 Subject: [PATCH] rsx: Unify composite texture creation and management - Some texture accesses require image compositing steps to assemble the requested image from existing subresources. Handle all the common routines in a unified manner to avoid having one broken path (e.g mipmap gather not supporting bitcast operations) --- rpcs3/Emu/RSX/GL/GLTextureCache.h | 73 ++++----------- rpcs3/Emu/RSX/VK/VKTextureCache.h | 143 ++++++++++-------------------- 2 files changed, 66 insertions(+), 150 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 8b096bb45529..3385f191e2a3 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -515,14 +515,14 @@ namespace gl } gl::texture_view* create_temporary_subresource_impl(gl::command_context& cmd, gl::texture* src, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format, - u16 x, u16 y, u16 width, u16 height, const rsx::texture_channel_remap_t& remap, bool copy) + u16 x, u16 y, u16 width, u16 height, u16 depth, u8 mipmaps, const rsx::texture_channel_remap_t& remap, bool copy) { if (sized_internal_fmt == GL_NONE) { sized_internal_fmt = gl::get_sized_internal_format(gcm_format); } - std::unique_ptr dst = std::make_unique(dst_type, width, height, 1, 1, sized_internal_fmt); + std::unique_ptr dst = std::make_unique(dst_type, width, height, depth, mipmaps, sized_internal_fmt); if (copy) { @@ -736,57 +736,31 @@ namespace gl gl::texture_view* create_temporary_subresource_view(gl::command_context &cmd, gl::texture** src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const rsx::texture_channel_remap_t& remap_vector) override { - return create_temporary_subresource_impl(cmd, *src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true); + return create_temporary_subresource_impl(cmd, *src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, 1, 1, remap_vector, true); } gl::texture_view* create_temporary_subresource_view(gl::command_context &cmd, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const rsx::texture_channel_remap_t& remap_vector) override { return create_temporary_subresource_impl(cmd, src, static_cast(src->get_internal_format()), - GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true); + GL_TEXTURE_2D, gcm_format, x, y, w, h, 1, 1, remap_vector, true); } - gl::texture_view* generate_cubemap_from_images(gl::command_context& cmd, u32 gcm_format, u16 size, const std::vector& sources, const rsx::texture_channel_remap_t& /*remap_vector*/) override + gl::texture_view* generate_cubemap_from_images(gl::command_context& cmd, u32 gcm_format, u16 size, const std::vector& sources, const rsx::texture_channel_remap_t& remap_vector) override { - const GLenum ifmt = gl::get_sized_internal_format(gcm_format); - std::unique_ptr dst_image = std::make_unique(GL_TEXTURE_CUBE_MAP, size, size, 1, 1, ifmt); - auto view = std::make_unique(dst_image.get(), GL_TEXTURE_CUBE_MAP, ifmt); + auto _template = get_template_from_collection_impl(sources); + auto result = create_temporary_subresource_impl(cmd, _template, GL_NONE, GL_TEXTURE_3D, gcm_format, 0, 0, size, size, 1, 1, remap_vector, false); - //Empty GL_ERROR - glGetError(); - - copy_transfer_regions_impl(cmd, dst_image.get(), sources); - - if (GLenum err = glGetError()) - { - rsx_log.warning("Failed to copy image subresource with GL error 0x%X", err); - return nullptr; - } - - auto result = view.get(); - m_temporary_surfaces.emplace_back(dst_image, view); + copy_transfer_regions_impl(cmd, result->image(), sources); return result; } - gl::texture_view* generate_3d_from_2d_images(gl::command_context& cmd, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector& sources, const rsx::texture_channel_remap_t& /*remap_vector*/) override + gl::texture_view* generate_3d_from_2d_images(gl::command_context& cmd, u32 gcm_format, u16 width, u16 height, u16 depth, const std::vector& sources, const rsx::texture_channel_remap_t& remap_vector) override { - const GLenum ifmt = gl::get_sized_internal_format(gcm_format); - std::unique_ptr dst_image = std::make_unique(GL_TEXTURE_3D, width, height, depth, 1, ifmt); - auto view = std::make_unique(dst_image.get(), GL_TEXTURE_3D, ifmt); - - //Empty GL_ERROR - glGetError(); - - copy_transfer_regions_impl(cmd, dst_image.get(), sources); + auto _template = get_template_from_collection_impl(sources); + auto result = create_temporary_subresource_impl(cmd, _template, GL_NONE, GL_TEXTURE_3D, gcm_format, 0, 0, width, height, depth, 1, remap_vector, false); - if (GLenum err = glGetError()) - { - rsx_log.warning("Failed to copy image subresource with GL error 0x%X", err); - return nullptr; - } - - auto result = view.get(); - m_temporary_surfaces.emplace_back(dst_image, view); + copy_transfer_regions_impl(cmd, result->image(), sources); return result; } @@ -794,30 +768,21 @@ namespace gl const rsx::texture_channel_remap_t& remap_vector) override { auto _template = get_template_from_collection_impl(sections_to_copy); - auto result = create_temporary_subresource_impl(cmd, _template, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false); + auto result = create_temporary_subresource_impl(cmd, _template, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, 1, 1, remap_vector, false); copy_transfer_regions_impl(cmd, result->image(), sections_to_copy); return result; } - gl::texture_view* generate_2d_mipmaps_from_images(gl::command_context& cmd, u32 /*gcm_format*/, u16 width, u16 height, const std::vector& sections_to_copy, + gl::texture_view* generate_2d_mipmaps_from_images(gl::command_context& cmd, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& remap_vector) override { - const auto _template = sections_to_copy.front().src; - const GLenum ifmt = static_cast(_template->get_internal_format()); - const u8 mipmaps = ::narrow(sections_to_copy.size()); - const auto swizzle = _template->get_native_component_layout(); - - auto image_ptr = new gl::viewable_image(GL_TEXTURE_2D, width, height, 1, mipmaps, ifmt); - image_ptr->set_native_component_layout(swizzle); - - copy_transfer_regions_impl(cmd, image_ptr, sections_to_copy); - - auto view = image_ptr->get_view(get_remap_encoding(remap_vector), remap_vector); + const auto mipmaps = ::narrow(sections_to_copy.size()); + auto _template = get_template_from_collection_impl(sections_to_copy); + auto result = create_temporary_subresource_impl(cmd, _template, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, 1, mipmaps, remap_vector, false); - std::unique_ptr dst_image(image_ptr); - m_temporary_surfaces.emplace_back(dst_image); - return view; + copy_transfer_regions_impl(cmd, result->image(), sections_to_copy); + return result; } void release_temporary_subresource(gl::texture_view* view) override diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 1ea7c2a0fb70..805071f91f1f 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -866,20 +866,22 @@ namespace vk protected: vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, - u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const rsx::texture_channel_remap_t& remap_vector, bool copy) + u32 gcm_format, u16 x, u16 y, u16 w, u16 h, u16 d, u8 mips, const rsx::texture_channel_remap_t& remap_vector, bool copy) { std::unique_ptr image; VkImageCreateFlags image_flags = (view_type == VK_IMAGE_VIEW_TYPE_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); + u16 layers = 1; if (!image_flags) [[likely]] { - image = find_temporary_image(dst_format, w, h, 1, 1); + image = find_temporary_image(dst_format, w, h, 1, mips); } else { image = find_temporary_cubemap(dst_format, w); + layers = 6; } if (!image) @@ -887,7 +889,7 @@ namespace vk image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image_type, dst_format, - w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + w, h, d, mips, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags); } @@ -938,7 +940,7 @@ namespace vk u16 x, u16 y, u16 w, u16 h, const rsx::texture_channel_remap_t& remap_vector) override { return create_temporary_subresource_view_impl(cmd, source, source->info.imageType, VK_IMAGE_VIEW_TYPE_2D, - gcm_format, x, y, w, h, remap_vector, true); + gcm_format, x, y, w, h, 1, 1, remap_vector, true); } vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, @@ -948,33 +950,16 @@ namespace vk } vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size, - const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& /*remap_vector*/) override + const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& remap_vector) override { - std::unique_ptr image; - VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); - VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format); - - if (image = find_temporary_cubemap(dst_format, size); !image) - { - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_IMAGE_TYPE_2D, - dst_format, - size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT); - } - else if (auto src = sections_to_copy[0].src; src && src->format() == dst_format) - { - image->set_native_component_layout(src->native_component_map); - } - else - { - image->set_native_component_layout({ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }); - } - - auto view = image->get_view(0xAAE4, rsx::default_remap_vector); + auto _template = get_template_from_collection_impl(sections_to_copy); + auto result = create_temporary_subresource_view_impl(cmd, _template, VK_IMAGE_TYPE_2D, + VK_IMAGE_VIEW_TYPE_CUBE, gcm_format, 0, 0, size, size, 1, 1, remap_vector, false); + const auto image = result->image(); + VkImageAspectFlags dst_aspect = vk::get_aspect_flags(result->info.format); VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 6 }; - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); if (!(dst_aspect & VK_IMAGE_ASPECT_DEPTH_BIT)) { @@ -987,46 +972,23 @@ namespace vk vkCmdClearDepthStencilImage(cmd, image->value, image->current_layout, &clear, 1, &dst_range); } - copy_transfer_regions_impl(cmd, image.get(), sections_to_copy); - - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); - - const u32 resource_memory = size * size * 6 * 4; //Rough approximate - m_temporary_storage.emplace_back(image); - m_temporary_storage.back().block_size = resource_memory; - m_temporary_memory_size += resource_memory; + copy_transfer_regions_impl(cmd, image, sections_to_copy); - return view; + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); + return result; } vk::image_view* generate_3d_from_2d_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, u16 depth, - const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& /*remap_vector*/) override + const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& remap_vector) override { - std::unique_ptr image; - VkFormat dst_format = vk::get_compatible_sampler_format(m_formats_support, gcm_format); - VkImageAspectFlags dst_aspect = vk::get_aspect_flags(dst_format); - - if (image = find_temporary_image(dst_format, width, height, depth, 1); !image) - { - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_IMAGE_TYPE_3D, - dst_format, - width, height, 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, 0); - } - else if (auto src = sections_to_copy[0].src; src && src->format() == dst_format) - { - image->set_native_component_layout(src->native_component_map); - } - else - { - image->set_native_component_layout({ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }); - } - - auto view = image->get_view(0xAAE4, rsx::default_remap_vector); + auto _template = get_template_from_collection_impl(sections_to_copy); + auto result = create_temporary_subresource_view_impl(cmd, _template, VK_IMAGE_TYPE_3D, + VK_IMAGE_VIEW_TYPE_3D, gcm_format, 0, 0, width, height, depth, 1, remap_vector, false); + const auto image = result->image(); + VkImageAspectFlags dst_aspect = vk::get_aspect_flags(result->info.format); VkImageSubresourceRange dst_range = { dst_aspect, 0, 1, 0, 1 }; - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); if (!(dst_aspect & VK_IMAGE_ASPECT_DEPTH_BIT)) { @@ -1039,16 +1001,10 @@ namespace vk vkCmdClearDepthStencilImage(cmd, image->value, image->current_layout, &clear, 1, &dst_range); } - copy_transfer_regions_impl(cmd, image.get(), sections_to_copy); - - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); - - const u32 resource_memory = width * height * depth * 4; //Rough approximate - m_temporary_storage.emplace_back(image); - m_temporary_storage.back().block_size = resource_memory; - m_temporary_memory_size += resource_memory; + copy_transfer_regions_impl(cmd, image, sections_to_copy); - return view; + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); + return result; } vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, @@ -1056,7 +1012,7 @@ namespace vk { auto _template = get_template_from_collection_impl(sections_to_copy); auto result = create_temporary_subresource_view_impl(cmd, _template, VK_IMAGE_TYPE_2D, - VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, remap_vector, false); + VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, 1, 1, remap_vector, false); const auto image = result->image(); VkImageAspectFlags dst_aspect = vk::get_aspect_flags(result->info.format); @@ -1080,39 +1036,34 @@ namespace vk return result; } - vk::image_view* generate_2d_mipmaps_from_images(vk::command_buffer& cmd, u32 /*gcm_format*/, u16 width, u16 height, + vk::image_view* generate_2d_mipmaps_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, const std::vector& sections_to_copy, const rsx::texture_channel_remap_t& remap_vector) override { - const auto _template = sections_to_copy.front().src; const auto mipmaps = ::narrow(sections_to_copy.size()); + auto _template = get_template_from_collection_impl(sections_to_copy); + auto result = create_temporary_subresource_view_impl(cmd, _template, VK_IMAGE_TYPE_2D, + VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, 1, mipmaps, remap_vector, false); - std::unique_ptr image; - if (image = find_temporary_image(_template->format(), width, height, 1, mipmaps); !image) - { - image = std::make_unique(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - _template->info.imageType, - _template->info.format, - width, height, 1, mipmaps, 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); + const auto image = result->image(); + VkImageAspectFlags dst_aspect = vk::get_aspect_flags(result->info.format); + VkImageSubresourceRange dst_range = { dst_aspect, 0, mipmaps, 0, 1 }; + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); - image->set_native_component_layout(_template->native_component_map); + if (!(dst_aspect & VK_IMAGE_ASPECT_DEPTH_BIT)) + { + VkClearColorValue clear = {}; + vkCmdClearColorImage(cmd, image->value, image->current_layout, &clear, 1, &dst_range); + } + else + { + VkClearDepthStencilValue clear = { 1.f, 0 }; + vkCmdClearDepthStencilImage(cmd, image->value, image->current_layout, &clear, 1, &dst_range); } - auto view = image->get_view(get_remap_encoding(remap_vector), remap_vector); - - VkImageSubresourceRange dst_range = { _template->aspect(), 0, mipmaps, 0, 1 }; - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_range); - - copy_transfer_regions_impl(cmd, image.get(), sections_to_copy); - - vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); - - const u32 resource_memory = width * height * 2 * 4; // Rough approximate - m_temporary_storage.emplace_back(image); - m_temporary_storage.back().block_size = resource_memory; - m_temporary_memory_size += resource_memory; + copy_transfer_regions_impl(cmd, image, sections_to_copy); - return view; + vk::change_image_layout(cmd, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, dst_range); + return result; } void release_temporary_subresource(vk::image_view* view) override