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; u16 h;
}; };
using texture_channel_remap_t = std::pair<std::array<u8, 4>, std::array<u8, 4>>;
struct deferred_subresource struct deferred_subresource
{ {
image_resource_type external_handle = 0; image_resource_type external_handle = 0;
std::array<image_resource_type, 6> external_cubemap_sources; std::array<image_resource_type, 6> external_cubemap_sources;
std::vector<copy_region_descriptor> sections_to_copy; std::vector<copy_region_descriptor> sections_to_copy;
texture_channel_remap_t remap;
u32 base_address = 0; u32 base_address = 0;
u32 gcm_format = 0; u32 gcm_format = 0;
u16 x = 0; u16 x = 0;
@ -280,8 +282,8 @@ namespace rsx
deferred_subresource() deferred_subresource()
{} {}
deferred_subresource(image_resource_type _res, u32 _addr, u32 _fmt, u16 _x, u16 _y, u16 _w, u16 _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) 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, 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; image_handle = 0;
upload_context = ctx; upload_context = ctx;
@ -336,7 +338,7 @@ namespace rsx
}; };
protected: 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_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 } { 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 */ /* Helpers */
virtual void free_texture_section(section_storage_type&) = 0; 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_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) = 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, 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, 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 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 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_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) = 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 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; 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; image_view_type result = 0;
if (desc.is_copy_cmd) 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) 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 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) if (result)
{ {
@ -1288,7 +1290,7 @@ namespace rsx
template <typename render_target_type, typename surface_store_type> 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, 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 u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
const auto surface_width = texptr->get_surface_width(); 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), 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::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); desc.set_external_cubemap_resources(image_array);
return desc; return desc;
@ -1383,7 +1385,7 @@ namespace rsx
sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h, sampled_image_descriptor result = { texptr->get_surface(), texaddr, format, 0, 0, w, h,
texture_upload_context::framebuffer_storage, is_depth, scale_x, scale_y, 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.is_copy_cmd = true;
result.external_subresource_desc.sections_to_copy.reserve(overlapping.size()); 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); 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, 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; result.external_subresource_desc.update_cached = update_subresource_cache;
return result; 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> template <typename RsxTextureType, typename surface_store_type, typename ...Args>
@ -1527,7 +1529,8 @@ namespace rsx
{ {
if (test_framebuffer(texaddr)) 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 else
{ {
@ -1540,7 +1543,8 @@ namespace rsx
{ {
if (test_framebuffer(texaddr)) 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 else
{ {
@ -1559,17 +1563,11 @@ namespace rsx
if (!is_compressed_format) if (!is_compressed_format)
{ {
/* Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise // 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
*/
const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch); const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch);
if (rsc.surface) if (rsc.surface)
{ {
//TODO: Check that this region is not cpu-dirty before doing a copy
if (!test_framebuffer(rsc.base_address)) if (!test_framebuffer(rsc.base_address))
{ {
m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface); m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface);
@ -1587,23 +1585,10 @@ namespace rsx
u16 internal_height = tex_height; u16 internal_height = tex_height;
get_native_dimensions(internal_width, internal_height, rsc.surface); 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) //Full sized hit from the surface cache. This should have been already found before getting here
{ fmt::throw_exception("Unreachable" HERE);
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);
} }
internal_width = rsx::apply_resolution_scale(internal_width, true); 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), 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, 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(); 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, 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; u16 surface_pixel_size = 0;
texture::internal_format compatible_internal_format = texture::internal_format::rgba8; texture::internal_format compatible_internal_format = texture::internal_format::rgba8;
std::array<GLenum, 4> native_component_mapping;
public: public:
render_target *old_contents = nullptr; render_target *old_contents = nullptr;
@ -116,8 +116,10 @@ namespace gl
return id(); 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(); return id();
} }
@ -137,6 +139,12 @@ namespace gl
internal_height = height(); internal_height = height();
surface_width = rsx::apply_inverse_resolution_scale(internal_width, true); surface_width = rsx::apply_inverse_resolution_scale(internal_width, true);
surface_height = rsx::apply_inverse_resolution_scale(internal_height, 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 bool matches_dimensions(u16 _width, u16 _height) const

View File

@ -654,7 +654,8 @@ namespace gl
m_temporary_surfaces.resize(0); 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; 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); 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; 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: protected:
void free_texture_section(cached_texture_section& tex) override void free_texture_section(cached_texture_section& tex) override
@ -772,24 +789,28 @@ namespace gl
tex.destroy(); 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)) 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 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); const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
GLuint dst_id = 0; GLuint dst_id = 0;
@ -826,9 +847,10 @@ namespace gl
return dst_id; 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) 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, 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_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); u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace);
bool depth_flag = false; 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, 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_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; void* unused = nullptr;
auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type, 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); 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; set_up_remap_vector(section.get_raw_texture(), GL_TEXTURE_2D, remap_vector);
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);
section.set_sampler_status(rsx::texture_sampler_status::status_ready); section.set_sampler_status(rsx::texture_sampler_status::status_ready);
} }

View File

@ -75,6 +75,7 @@ namespace vk
bool sanitize_fp_values(); bool sanitize_fp_values();
VkComponentMapping default_component_map(); 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(); 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); 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; u16 surface_height = 0;
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT; 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 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 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) 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() vk::image_view* get_view()
{ {
if (!view) if (views.empty())
view = std::make_unique<vk::image_view>(*vk::get_current_renderer(), value, VK_IMAGE_VIEW_TYPE_2D, info.format, {
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))); 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 vk::image* get_surface() const override

View File

@ -180,4 +180,29 @@ namespace vk
mipmap_level++; 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; 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) VkComponentMapping apply_component_mapping_flags(u32 gcm_format, rsx::texture_create_flags flags, const texture_channel_remap_t& 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)
{ {
//NOTE: Depth textures should always read RRRR //NOTE: Depth textures should always read RRRR
switch (gcm_format) switch (gcm_format)
@ -535,7 +510,7 @@ namespace vk
{ {
case rsx::texture_create_flags::default_component_order: 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; break;
} }
case rsx::texture_create_flags::native_component_order: case rsx::texture_create_flags::native_component_order:
@ -564,7 +539,8 @@ namespace vk
tex.destroy(); 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; 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, 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)); 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; VkComponentMapping view_swizzle = source->native_component_map;
if (dst_format != source->info.format) if (dst_format != source->info.format)
{ {
//This is a data cast operation //This is a data cast operation
//Use native mapping for the new type //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); const auto remap = get_component_mapping(gcm_format);
view_swizzle = { remap[1], remap[2], remap[3], remap[0] }; 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 }; 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)); 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(); 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> image;
std::unique_ptr<vk::image_view> view; std::unique_ptr<vk::image_view> view;
@ -719,10 +705,11 @@ namespace vk
return m_discardable_storage.back().view.get(); 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, 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; VkImage dst = result->info.image;
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; 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, 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_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 u16 section_depth = depth;
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap; 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, 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_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, 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); 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); 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& view = section.get_view();
auto& original_remap = view->info.components; auto& original_remap = view->info.components;
std::array<VkComponentSwizzle, 4> base_remap = {original_remap.a, original_remap.r, original_remap.g, original_remap.b}; 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 || if (final_remap.a != original_remap.a ||
final_remap.r != original_remap.r || final_remap.r != original_remap.r ||
final_remap.g != original_remap.g || final_remap.g != original_remap.g ||