rsx/gl/vk: Obey channel remapping on framebuffer resources if requested

This commit is contained in:
kd-11 2018-03-18 14:40:26 +03:00
parent 27552891ad
commit 9f416e5ce1
7 changed files with 164 additions and 113 deletions

View File

@ -262,11 +262,13 @@ namespace rsx
u16 h;
};
using texture_channel_remap_t = std::pair<std::array<u8, 4>, std::array<u8, 4>>;
struct deferred_subresource
{
image_resource_type external_handle = 0;
std::array<image_resource_type, 6> external_cubemap_sources;
std::vector<copy_region_descriptor> sections_to_copy;
texture_channel_remap_t remap;
u32 base_address = 0;
u32 gcm_format = 0;
u16 x = 0;
@ -280,8 +282,8 @@ namespace rsx
deferred_subresource()
{}
deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h) :
external_handle(_res), base_address(_addr), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h)
deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _h, const texture_channel_remap_t& _remap) :
external_handle(_res), base_address(_addr), gcm_format(_fmt), x(_x), y(_y), width(_w), height(_h), remap(_remap)
{}
};
@ -316,9 +318,9 @@ namespace rsx
}
sampled_image_descriptor(image_resource_type external_handle, u32 base_address, u32 gcm_format, u16 x_offset, u16 y_offset, u16 width, u16 height,
texture_upload_context ctx, bool is_depth, f32 x_scale, f32 y_scale, rsx::texture_dimension_extended type)
texture_upload_context ctx, bool is_depth, f32 x_scale, f32 y_scale, rsx::texture_dimension_extended type, const texture_channel_remap_t& remap)
{
external_subresource_desc = { external_handle, base_address, gcm_format, x_offset, y_offset, width, height };
external_subresource_desc = { external_handle, base_address, gcm_format, x_offset, y_offset, width, height, remap };
image_handle = 0;
upload_context = ctx;
@ -336,7 +338,7 @@ namespace rsx
};
protected:
std::pair<std::array<u8, 4>, std::array<u8, 4>> default_remap_vector =
texture_channel_remap_t default_remap_vector =
{
{ CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B },
{ CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP }
@ -375,17 +377,17 @@ namespace rsx
/* Helpers */
virtual void free_texture_section(section_storage_type&) = 0;
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0;
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0;
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0;
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0;
virtual section_storage_type* create_new_texture(commandbuffer_type&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format,
rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags, rsx::texture_colorspace colorspace, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags, rsx::texture_colorspace colorspace, const texture_channel_remap_t& remap_vector) = 0;
virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, texture_upload_context context,
const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace, bool swizzled, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& 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 set_up_remap_vector(section_storage_type& section, const texture_channel_remap_t& remap_vector) = 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;
virtual image_view_type generate_atlas_from_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy) = 0;
virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array<image_resource_type, 6>& sources, const texture_channel_remap_t& remap_vector) = 0;
virtual image_view_type generate_atlas_from_images(commandbuffer_type&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy, const texture_channel_remap_t& remap_vector) = 0;
virtual void update_image_contents(commandbuffer_type&, image_view_type dst, image_resource_type src, u16 width, u16 height) = 0;
virtual bool render_target_format_is_compatible(image_storage_type* tex, u32 gcm_format) = 0;
@ -1267,11 +1269,11 @@ namespace rsx
image_view_type result = 0;
if (desc.is_copy_cmd)
result = generate_atlas_from_images(cmd, desc.gcm_format, desc.width, desc.height, desc.sections_to_copy);
result = generate_atlas_from_images(cmd, desc.gcm_format, desc.width, desc.height, desc.sections_to_copy, desc.remap);
else if (desc.is_cubemap)
result = generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources);
result = generate_cubemap_from_images(cmd, desc.gcm_format, desc.width, desc.external_cubemap_sources, desc.remap);
else
result = create_temporary_subresource_view(cmd, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height);
result = create_temporary_subresource_view(cmd, &desc.external_handle, desc.gcm_format, desc.x, desc.y, desc.width, desc.height, desc.remap);
if (result)
{
@ -1288,7 +1290,7 @@ namespace rsx
template <typename render_target_type, typename surface_store_type>
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, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth)
u16 tex_width, u16 tex_height, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth, const texture_channel_remap_t& remap)
{
const u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
const auto surface_width = texptr->get_surface_width();
@ -1348,7 +1350,7 @@ namespace rsx
sampled_image_descriptor desc = { texptr->get_surface(), texaddr, format, 0, 0, rsx::apply_resolution_scale(surface_width, true),
rsx::apply_resolution_scale(surface_height, true), texture_upload_context::framebuffer_storage, is_depth, 1.f, 1.f,
rsx::texture_dimension_extended::texture_dimension_cubemap };
rsx::texture_dimension_extended::texture_dimension_cubemap, remap };
desc.set_external_cubemap_resources(image_array);
return desc;
@ -1383,7 +1385,7 @@ namespace rsx
sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h,
texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y,
rsx::texture_dimension_extended::texture_dimension_2d };
rsx::texture_dimension_extended::texture_dimension_2d, remap };
result.external_subresource_desc.is_copy_cmd = true;
result.external_subresource_desc.sections_to_copy.reserve(overlapping.size());
@ -1472,13 +1474,13 @@ namespace rsx
const auto h = rsx::apply_resolution_scale(internal_height, true);
sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h, texture_upload_context::framebuffer_storage,
is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d, remap };
result.external_subresource_desc.update_cached = update_subresource_cache;
return result;
}
return{ texptr->get_view(), texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
return{ texptr->get_view(remap), texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
}
template <typename RsxTextureType, typename surface_store_type, typename ...Args>
@ -1527,7 +1529,8 @@ namespace rsx
{
if (test_framebuffer(texaddr))
{
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, tex_pitch, extended_dimension, false);
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts,
tex_width, tex_height, tex_pitch, extended_dimension, false, tex.decoded_remap());
}
else
{
@ -1540,7 +1543,8 @@ namespace rsx
{
if (test_framebuffer(texaddr))
{
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, tex_width, tex_height, tex_pitch, extended_dimension, true);
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts,
tex_width, tex_height, tex_pitch, extended_dimension, true, tex.decoded_remap());
}
else
{
@ -1559,17 +1563,11 @@ namespace rsx
if (!is_compressed_format)
{
/* Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise
* This check is much stricter than the one above
* (Turbo: Super Stunt Squad does this; bypassing the need for a sync object)
* The engine does not read back the texture resource through cell, but specifies a texture location that is
* a bound render target. We can bypass the expensive download in this case
*/
// Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise
const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch);
if (rsc.surface)
{
//TODO: Check that this region is not cpu-dirty before doing a copy
if (!test_framebuffer(rsc.base_address))
{
m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface);
@ -1587,23 +1585,10 @@ namespace rsx
u16 internal_height = tex_height;
get_native_dimensions(internal_width, internal_height, rsc.surface);
if (!rsc.is_bound || !g_cfg.video.strict_rendering_mode)
if (!rsc.x && !rsc.y && rsc.w == internal_width && rsc.h == internal_height)
{
if (!rsc.x && !rsc.y && rsc.w == internal_width && rsc.h == internal_height)
{
if (rsc.is_bound)
{
LOG_WARNING(RSX, "Sampling from a currently bound render target @ 0x%x", texaddr);
insert_texture_barrier(cmd, rsc.surface);
}
return{ rsc.surface->get_view(), texture_upload_context::framebuffer_storage, rsc.is_depth_surface,
scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
}
}
else
{
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
//Full sized hit from the surface cache. This should have been already found before getting here
fmt::throw_exception("Unreachable" HERE);
}
internal_width = rsx::apply_resolution_scale(internal_width, true);
@ -1611,7 +1596,7 @@ namespace rsx
return{ rsc.surface->get_surface(), rsc.base_address, format, rsx::apply_resolution_scale(rsc.x, false), rsx::apply_resolution_scale(rsc.y, false),
internal_width, internal_height, texture_upload_context::framebuffer_storage, rsc.is_depth_surface, scale_x, scale_y,
rsx::texture_dimension_extended::texture_dimension_2d };
rsx::texture_dimension_extended::texture_dimension_2d, tex.decoded_remap() };
}
}
}
@ -1680,7 +1665,7 @@ namespace rsx
auto src_image = surface->get_raw_texture();
return{ src_image, surface->get_section_base(), format, offset_x, offset_y, tex_width, tex_height, texture_upload_context::blit_engine_dst,
surface->is_depth_texture(), scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d };
surface->is_depth_texture(), scale_x, scale_y, rsx::texture_dimension_extended::texture_dimension_2d, default_remap_vector };
}
}
}

View File

@ -63,7 +63,7 @@ namespace gl
u16 surface_pixel_size = 0;
texture::internal_format compatible_internal_format = texture::internal_format::rgba8;
std::array<GLenum, 4> native_component_mapping;
public:
render_target *old_contents = nullptr;
@ -116,8 +116,10 @@ namespace gl
return id();
}
u32 get_view() const
u32 get_view(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap) const
{
bind();
apply_swizzle_remap(GL_TEXTURE_2D, native_component_mapping, remap);
return id();
}
@ -137,6 +139,12 @@ namespace gl
internal_height = height();
surface_width = rsx::apply_inverse_resolution_scale(internal_width, true);
surface_height = rsx::apply_inverse_resolution_scale(internal_height, true);
bind();
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&native_component_mapping[0]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&native_component_mapping[1]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&native_component_mapping[2]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&native_component_mapping[3]);
}
bool matches_dimensions(u16 _width, u16 _height) const

View File

@ -654,7 +654,8 @@ namespace gl
m_temporary_surfaces.resize(0);
}
u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format, u16 x, u16 y, u16 width, u16 height, bool copy = true)
u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, GLenum dst_type, u32 gcm_format,
u16 x, u16 y, u16 width, u16 height, const texture_channel_remap_t& remap, bool copy)
{
u32 dst_id = 0;
@ -712,6 +713,10 @@ namespace gl
apply_component_mapping_flags(dst_type, gcm_format, rsx::texture_create_flags::default_component_order);
}
if (memcmp(remap.first.data(), default_remap_vector.first.data(), 4) ||
memcmp(remap.second.data(), default_remap_vector.second.data(), 4))
set_up_remap_vector(dst_id, dst_type, remap);
return dst_id;
}
@ -765,6 +770,18 @@ namespace gl
}
}
void set_up_remap_vector(u32 texture_id, GLenum texture_type, const texture_channel_remap_t& remap_vector)
{
std::array<GLenum, 4> swizzle_remap;
glBindTexture(texture_type, texture_id);
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_A, (GLint*)&swizzle_remap[0]);
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_R, (GLint*)&swizzle_remap[1]);
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_G, (GLint*)&swizzle_remap[2]);
glGetTexParameteriv(texture_type, GL_TEXTURE_SWIZZLE_B, (GLint*)&swizzle_remap[3]);
apply_swizzle_remap(texture_type, swizzle_remap, remap_vector);
}
protected:
void free_texture_section(cached_texture_section& tex) override
@ -772,24 +789,28 @@ namespace gl
tex.destroy();
}
u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
const texture_channel_remap_t& remap_vector) override
{
return create_temporary_subresource_impl(*src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h);
return create_temporary_subresource_impl(*src, GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true);
}
u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h,
const texture_channel_remap_t& remap_vector) override
{
if (auto as_rtt = dynamic_cast<gl::render_target*>(src))
{
return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), GL_TEXTURE_2D, gcm_format, x, y, w, h);
return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(),
GL_TEXTURE_2D, gcm_format, x, y, w, h, remap_vector, true);
}
else
{
return create_temporary_subresource_impl(src->id(), GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h);
return create_temporary_subresource_impl(src->id(), GL_NONE, GL_TEXTURE_2D, gcm_format, x, y, w, h,
remap_vector, true);
}
}
u32 generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::array<u32, 6>& sources) override
u32 generate_cubemap_from_images(void*&, u32 gcm_format, u16 size, const std::array<u32, 6>& sources, const texture_channel_remap_t& remap_vector) override
{
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
GLuint dst_id = 0;
@ -826,9 +847,10 @@ namespace gl
return dst_id;
}
u32 generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy) override
u32 generate_atlas_from_images(void*&, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy,
const texture_channel_remap_t& remap_vector) override
{
auto result = create_temporary_subresource_impl(sections_to_copy.front().src, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, false);
auto result = create_temporary_subresource_impl(sections_to_copy.front().src, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false);
for (const auto &region : sections_to_copy)
{
@ -847,7 +869,7 @@ namespace gl
cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format,
rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags,
rsx::texture_colorspace colorspace, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& /*remap_vector*/) override
rsx::texture_colorspace colorspace, const texture_channel_remap_t& /*remap_vector*/) override
{
u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace);
bool depth_flag = false;
@ -919,7 +941,7 @@ namespace gl
cached_texture_section* upload_image_from_cpu(void*&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format,
rsx::texture_upload_context context, const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type,
rsx::texture_colorspace colorspace, bool swizzled, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& remap_vector) override
{
void* unused = nullptr;
auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type,
@ -955,16 +977,9 @@ namespace gl
section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized);
}
void set_up_remap_vector(cached_texture_section& section, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
void set_up_remap_vector(cached_texture_section& section, const texture_channel_remap_t& remap_vector) override
{
std::array<GLenum, 4> swizzle_remap;
glBindTexture(GL_TEXTURE_2D, section.get_raw_texture());
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, (GLint*)&swizzle_remap[0]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, (GLint*)&swizzle_remap[1]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, (GLint*)&swizzle_remap[2]);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, (GLint*)&swizzle_remap[3]);
apply_swizzle_remap(GL_TEXTURE_2D, swizzle_remap, remap_vector);
set_up_remap_vector(section.get_raw_texture(), GL_TEXTURE_2D, remap_vector);
section.set_sampler_status(rsx::texture_sampler_status::status_ready);
}

View File

@ -75,6 +75,7 @@ namespace vk
bool sanitize_fp_values();
VkComponentMapping default_component_map();
VkComponentMapping apply_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector);
VkImageSubresource default_image_subresource();
VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect);

View File

@ -20,7 +20,7 @@ namespace vk
u16 surface_height = 0;
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
std::unique_ptr<vk::image_view> view;
std::vector<std::unique_ptr<vk::image_view>> views;
render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
@ -42,13 +42,43 @@ namespace vk
mipmaps, layers, samples, initial_layout, tiling, usage, image_flags)
{}
vk::image_view* get_view(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
{
VkComponentMapping real_mapping = vk::apply_swizzle_remap
(
{native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b },
remap
);
for (const auto& view : views)
{
if (view->info.components.a == real_mapping.a &&
view->info.components.r == real_mapping.r &&
view->info.components.g == real_mapping.g &&
view->info.components.b == real_mapping.b)
{
return view.get();
}
}
auto view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format,
real_mapping, vk::get_image_subresource_range(0, 0, 1, 1, attachment_aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT)));
views.push_back(std::move(view));
return views.back().get();
}
vk::image_view* get_view()
{
if (!view)
view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format,
if (views.empty())
{
auto view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format,
native_component_map, vk::get_image_subresource_range(0, 0, 1, 1, attachment_aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT)));
return view.get();
views.push_back(std::move(view));
}
return views.back().get();
}
vk::image* get_surface() const override

View File

@ -180,4 +180,29 @@ namespace vk
mipmap_level++;
}
}
VkComponentMapping apply_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector)
{
VkComponentSwizzle final_mapping[4] = {};
for (u8 channel = 0; channel < 4; ++channel)
{
switch (remap_vector.second[channel])
{
case CELL_GCM_TEXTURE_REMAP_ONE:
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE;
break;
case CELL_GCM_TEXTURE_REMAP_ZERO:
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO;
break;
case CELL_GCM_TEXTURE_REMAP_REMAP:
final_mapping[channel] = base_remap[remap_vector.first[channel]];
break;
default:
LOG_ERROR(RSX, "Unknown remap lookup value %d", remap_vector.second[channel]);
}
}
return{ final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] };
}
}

View File

@ -489,32 +489,7 @@ namespace vk
m_discarded_memory_size = 0;
}
VkComponentMapping apply_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector)
{
VkComponentSwizzle final_mapping[4] = {};
for (u8 channel = 0; channel < 4; ++channel)
{
switch (remap_vector.second[channel])
{
case CELL_GCM_TEXTURE_REMAP_ONE:
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE;
break;
case CELL_GCM_TEXTURE_REMAP_ZERO:
final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO;
break;
case CELL_GCM_TEXTURE_REMAP_REMAP:
final_mapping[channel] = base_remap[remap_vector.first[channel]];
break;
default:
LOG_ERROR(RSX, "Unknown remap lookup value %d", remap_vector.second[channel]);
}
}
return { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] };
}
VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector)
VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const texture_channel_remap_t& remap_vector)
{
//NOTE: Depth textures should always read RRRR
switch (gcm_format)
@ -535,7 +510,7 @@ namespace vk
{
case rsx::texture_create_flags::default_component_order:
{
mapping = apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector);
mapping = vk::apply_swizzle_remap(vk::get_component_mapping(gcm_format), remap_vector);
break;
}
case rsx::texture_create_flags::native_component_order:
@ -564,7 +539,8 @@ namespace vk
tex.destroy();
}
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, bool copy = true)
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 texture_channel_remap_t& remap_vector, bool copy)
{
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
@ -597,16 +573,22 @@ namespace vk
w, h, 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, source->info.flags));
//This method is almost exclusively used to work on framebuffer resources
//Keep the original swizzle layout unless there is data format conversion
VkComponentMapping view_swizzle = source->native_component_map;
if (dst_format != source->info.format)
{
//This is a data cast operation
//Use native mapping for the new type
//TODO: Also reapply the view swizzle
//TODO: Also simlulate the readback+reupload step (very tricky)
const auto remap = get_component_mapping(gcm_format);
view_swizzle = { remap[1], remap[2], remap[3], remap[0] };
}
if (memcmp(remap_vector.first.data(), default_remap_vector.first.data(), 4) ||
memcmp(remap_vector.second.data(), default_remap_vector.second.data(), 4))
view_swizzle = vk::apply_swizzle_remap({view_swizzle.a, view_swizzle.r, view_swizzle.g, view_swizzle.b}, remap_vector);
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, view_type, dst_format, view_swizzle, view_range));
@ -637,17 +619,21 @@ namespace vk
return m_discardable_storage.back().view.get();
}
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 gcm_format,
u16 x, u16 y, u16 w, u16 h, const 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);
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);
}
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format,
u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) override
{
return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h);
return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h, remap_vector);
}
vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size, const std::array<vk::image*, 6>& sources) override
vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 size,
const std::array<vk::image*, 6>& sources, const texture_channel_remap_t& remap_vector) override
{
std::unique_ptr<vk::image> image;
std::unique_ptr<vk::image_view> view;
@ -719,10 +705,11 @@ namespace vk
return m_discardable_storage.back().view.get();
}
vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height, const std::vector<copy_region_descriptor>& sections_to_copy) override
vk::image_view* generate_atlas_from_images(vk::command_buffer& cmd, u32 gcm_format, u16 width, u16 height,
const std::vector<copy_region_descriptor>& sections_to_copy, const texture_channel_remap_t& remap_vector) override
{
auto result = create_temporary_subresource_view_impl(cmd, sections_to_copy.front().src, VK_IMAGE_TYPE_2D,
VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, false);
VK_IMAGE_VIEW_TYPE_2D, gcm_format, 0, 0, width, height, default_remap_vector, false);
VkImage dst = result->info.image;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
@ -800,7 +787,7 @@ namespace vk
cached_texture_section* create_new_texture(vk::command_buffer& cmd, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format,
rsx::texture_upload_context context, rsx::texture_dimension_extended type, rsx::texture_create_flags flags,
rsx::texture_colorspace colorspace, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
rsx::texture_colorspace colorspace, const texture_channel_remap_t& remap_vector) override
{
const u16 section_depth = depth;
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap;
@ -902,7 +889,7 @@ namespace vk
cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format,
rsx::texture_upload_context context, const std::vector<rsx_subresource_layout>& subresource_layout, rsx::texture_dimension_extended type,
rsx::texture_colorspace colorspace, bool swizzled, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
rsx::texture_colorspace colorspace, bool swizzled, const texture_channel_remap_t& remap_vector) override
{
auto section = create_new_texture(cmd, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type,
rsx::texture_create_flags::default_component_order, colorspace, remap_vector);
@ -971,13 +958,13 @@ namespace vk
section.set_sampler_status(rsx::texture_sampler_status::status_uninitialized);
}
void set_up_remap_vector(cached_texture_section& section, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
void set_up_remap_vector(cached_texture_section& section, const texture_channel_remap_t& remap_vector) override
{
auto& view = section.get_view();
auto& original_remap = view->info.components;
std::array<VkComponentSwizzle, 4> base_remap = {original_remap.a, original_remap.r, original_remap.g, original_remap.b};
auto final_remap = apply_swizzle_remap(base_remap, remap_vector);
auto final_remap = vk::apply_swizzle_remap(base_remap, remap_vector);
if (final_remap.a != original_remap.a ||
final_remap.r != original_remap.r ||
final_remap.g != original_remap.g ||