mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
rsx: Texture format fixes
- Implement SRGB (gamma corrected) textures (DXT1, DXT3, DXT5, RGBA8 only) - Fix channel map decode for XY data texture formats - Fix remap layout for X16 textures (verified with Mass Effect 3)
This commit is contained in:
parent
a35bcb131e
commit
5817f9fe3f
10 changed files with 92 additions and 24 deletions
|
@ -15,6 +15,12 @@ namespace rsx
|
|||
framebuffer_storage = 3
|
||||
};
|
||||
|
||||
enum texture_colorspace
|
||||
{
|
||||
rgb_linear = 0,
|
||||
srgb_nonlinear = 1
|
||||
};
|
||||
|
||||
//Sampled image descriptor
|
||||
struct sampled_image_descriptor_base
|
||||
{
|
||||
|
|
|
@ -378,9 +378,9 @@ namespace rsx
|
|||
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 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, 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 std::pair<std::array<u8, 4>, std::array<u8, 4>>& 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, 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 std::pair<std::array<u8, 4>, std::array<u8, 4>>& 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 insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0;
|
||||
|
@ -1708,9 +1708,10 @@ namespace rsx
|
|||
//Invalidate with writing=false, discard=false, rebuild=false, native_flush=true
|
||||
invalidate_range_impl_base(texaddr, tex_size, false, false, false, true, std::forward<Args>(extras)...);
|
||||
|
||||
const auto colorspace = tex.gamma() ? rsx::texture_colorspace::srgb_nonlinear : rsx::texture_colorspace::rgb_linear;
|
||||
m_texture_memory_in_use += (tex_pitch * tex_height);
|
||||
return{ upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
|
||||
texture_upload_context::shader_read, subresources_layout, extended_dimension, is_swizzled, remap_vector)->get_raw_view(),
|
||||
texture_upload_context::shader_read, subresources_layout, extended_dimension, colorspace, is_swizzled, remap_vector)->get_raw_view(),
|
||||
texture_upload_context::shader_read, is_depth_format, scale_x, scale_y, extended_dimension };
|
||||
}
|
||||
|
||||
|
@ -1940,7 +1941,7 @@ namespace rsx
|
|||
|
||||
const u32 gcm_format = src_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5;
|
||||
vram_texture = upload_image_from_cpu(cmd, src_address, src.width, src.slice_h, 1, 1, src.pitch, gcm_format, texture_upload_context::blit_engine_src,
|
||||
subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, dst.swizzled, default_remap_vector)->get_raw_texture();
|
||||
subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, rsx::texture_colorspace::rgb_linear, dst.swizzled, default_remap_vector)->get_raw_texture();
|
||||
|
||||
m_texture_memory_in_use += src.pitch * src.slice_h;
|
||||
}
|
||||
|
@ -2054,7 +2055,7 @@ namespace rsx
|
|||
dest_texture = create_new_texture(cmd, dst.rsx_address, dst.pitch * dst_dimensions.height,
|
||||
dst_dimensions.width, dst_dimensions.height, 1, 1,
|
||||
gcm_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d,
|
||||
channel_order, default_remap_vector)->get_raw_texture();
|
||||
channel_order, rsx::texture_colorspace::rgb_linear, default_remap_vector)->get_raw_texture();
|
||||
|
||||
m_texture_memory_in_use += dst.pitch * dst_dimensions.height;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,24 @@ namespace gl
|
|||
fmt::throw_exception("Compressed or unknown texture format 0x%x" HERE, texture_format);
|
||||
}
|
||||
|
||||
GLenum get_srgb_format(GLenum in_format)
|
||||
{
|
||||
switch (in_format)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||
case GL_RGBA8:
|
||||
return GL_SRGB8_ALPHA8;
|
||||
default:
|
||||
//LOG_ERROR(RSX, "No gamma coversion for format 0x%X", in_format);
|
||||
return in_format;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum wrap_mode(rsx::texture_wrap_mode wrap)
|
||||
{
|
||||
switch (wrap)
|
||||
|
@ -288,7 +306,8 @@ namespace gl
|
|||
return{ GL_ONE, GL_RED, GL_RED, GL_RED };
|
||||
|
||||
case CELL_GCM_TEXTURE_X16:
|
||||
return{ GL_RED, GL_ONE, GL_RED, GL_ONE };
|
||||
//Blue component is also R (Mass Effect 3)
|
||||
return{ GL_RED, GL_ONE, GL_RED, GL_RED };
|
||||
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
return{ GL_RED, GL_RED, GL_RED, GL_RED };
|
||||
|
@ -317,7 +336,8 @@ namespace gl
|
|||
fmt::throw_exception("Unknown format 0x%x" HERE, texture_format);
|
||||
}
|
||||
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type)
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps,
|
||||
rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace)
|
||||
{
|
||||
if (is_compressed_format(gcm_format))
|
||||
{
|
||||
|
@ -331,6 +351,9 @@ namespace gl
|
|||
GLenum target;
|
||||
GLenum internal_format = get_sized_internal_format(gcm_format);
|
||||
|
||||
if (colorspace != rsx::texture_colorspace::rgb_linear)
|
||||
internal_format = get_srgb_format(internal_format);
|
||||
|
||||
glGenTextures(1, &id);
|
||||
|
||||
switch (type)
|
||||
|
@ -507,7 +530,8 @@ namespace gl
|
|||
}
|
||||
|
||||
void upload_texture(GLuint id, u32 texaddr, u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type,
|
||||
const std::vector<rsx_subresource_layout>& subresources_layout, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state)
|
||||
const std::vector<rsx_subresource_layout>& subresources_layout, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state,
|
||||
rsx::texture_colorspace colorspace)
|
||||
{
|
||||
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap;
|
||||
|
||||
|
@ -564,7 +588,7 @@ namespace gl
|
|||
|
||||
//The rest of sampler state is now handled by sampler state objects
|
||||
const auto format_type = get_format_type(gcm_format);
|
||||
const GLenum gl_format = std::get<0>(format_type);
|
||||
const GLenum gl_format = (colorspace == rsx::texture_colorspace::rgb_linear)? std::get<0>(format_type) : get_srgb_format(std::get<0>(format_type));
|
||||
const GLenum gl_type = std::get<1>(format_type);
|
||||
fill_texture(type, mipmaps, gcm_format, width, height, depth, subresources_layout, is_swizzled, gl_format, gl_type, data_upload_buf);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace gl
|
|||
float max_aniso(rsx::texture_max_anisotropy aniso);
|
||||
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format);
|
||||
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type);
|
||||
GLuint create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace);
|
||||
|
||||
/**
|
||||
* is_swizzled - determines whether input bytes are in morton order
|
||||
|
@ -28,7 +28,8 @@ namespace gl
|
|||
* static_state - set up the texture without consideration for sampler state (useful for vertex textures which have no real sampler state on RSX)
|
||||
*/
|
||||
void upload_texture(GLuint id, u32 texaddr, u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type,
|
||||
const std::vector<rsx_subresource_layout>& subresources_layout, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state);
|
||||
const std::vector<rsx_subresource_layout>& subresources_layout, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap, bool static_state,
|
||||
rsx::texture_colorspace colorspace);
|
||||
|
||||
void apply_swizzle_remap(GLenum target, const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap);
|
||||
|
||||
|
|
|
@ -847,9 +847,9 @@ 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,
|
||||
const std::pair<std::array<u8, 4>, std::array<u8, 4>>& /*remap_vector*/) override
|
||||
rsx::texture_colorspace colorspace, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& /*remap_vector*/) override
|
||||
{
|
||||
u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type);
|
||||
u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type, colorspace);
|
||||
bool depth_flag = false;
|
||||
|
||||
switch (gcm_format)
|
||||
|
@ -918,12 +918,12 @@ 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, bool swizzled,
|
||||
const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
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
|
||||
{
|
||||
void* unused = nullptr;
|
||||
auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type,
|
||||
rsx::texture_create_flags::default_component_order, remap_vector);
|
||||
rsx::texture_create_flags::default_component_order, colorspace, remap_vector);
|
||||
|
||||
bool input_swizzled = swizzled;
|
||||
if (context == rsx::texture_upload_context::blit_engine_src)
|
||||
|
@ -938,7 +938,8 @@ namespace gl
|
|||
section->set_sampler_status(rsx::texture_sampler_status::status_ready);
|
||||
}
|
||||
|
||||
gl::upload_texture(section->get_raw_texture(), rsx_address, gcm_format, width, height, depth, mipmaps, input_swizzled, type, subresource_layout, remap_vector, false);
|
||||
gl::upload_texture(section->get_raw_texture(), rsx_address, gcm_format, width, height, depth, mipmaps,
|
||||
input_swizzled, type, subresource_layout, remap_vector, false, colorspace);
|
||||
return section;
|
||||
}
|
||||
|
||||
|
|
|
@ -193,10 +193,19 @@ namespace rsx
|
|||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
|
||||
//Low bit in remap control affects whether the G component should read from first or second component
|
||||
{
|
||||
//Low bit in remap control affects whether the G component should match R and B components
|
||||
//Components are usually interleaved R-G-R-G unless flag is set, then its R-R-R-G (Virtua Fighter 5)
|
||||
remap_ctl = (remap_override) ?(0b01010110 | (remap_ctl & 0xFF00)): (0b01100110 | (remap_ctl & 0xFF00));
|
||||
//NOTE: The remap vector can also read from B-A-B-A in some cases (Mass Effect 3)
|
||||
if (remap_override)
|
||||
{
|
||||
auto r_component = (remap_ctl >> 2) & 3;
|
||||
remap_ctl = remap_ctl & ~(3 << 4) | r_component << 4;
|
||||
}
|
||||
|
||||
remap_ctl &= 0xFFFF;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,8 @@ std::array<VkComponentSwizzle, 4> get_component_mapping(u32 format)
|
|||
mapping = { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X16:
|
||||
mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE }; break;
|
||||
//Blue component is also R (Mass Effect 3)
|
||||
mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; break;
|
||||
|
|
|
@ -144,6 +144,23 @@ namespace vk
|
|||
fmt::throw_exception("Invalid or unsupported sampler format for texture format (0x%x)" HERE, format);
|
||||
}
|
||||
|
||||
VkFormat get_compatible_srgb_format(VkFormat rgb_format)
|
||||
{
|
||||
switch (rgb_format)
|
||||
{
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
return VK_FORMAT_B8G8R8A8_SRGB;
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
|
||||
return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
|
||||
case VK_FORMAT_BC2_UNORM_BLOCK:
|
||||
return VK_FORMAT_BC2_SRGB_BLOCK;
|
||||
case VK_FORMAT_BC3_UNORM_BLOCK:
|
||||
return VK_FORMAT_BC3_SRGB_BLOCK;
|
||||
default:
|
||||
return rgb_format;
|
||||
}
|
||||
}
|
||||
|
||||
u8 get_format_texel_width(const VkFormat format)
|
||||
{
|
||||
switch (format)
|
||||
|
@ -167,9 +184,13 @@ namespace vk
|
|||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC2_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC3_UNORM_BLOCK:
|
||||
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC2_SRGB_BLOCK:
|
||||
case VK_FORMAT_BC3_SRGB_BLOCK:
|
||||
return 4;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
return 8;
|
||||
|
|
|
@ -94,6 +94,7 @@ namespace vk
|
|||
void copy_scaled_image(VkCommandBuffer cmd, VkImage &src, VkImage &dst, VkImageLayout srcLayout, VkImageLayout dstLayout, u32 src_x_offset, u32 src_y_offset, u32 src_width, u32 src_height, u32 dst_x_offset, u32 dst_y_offset, u32 dst_width, u32 dst_height, u32 mipmaps, VkImageAspectFlagBits aspect, bool compatible_formats);
|
||||
|
||||
VkFormat get_compatible_sampler_format(u32 format);
|
||||
VkFormat get_compatible_srgb_format(VkFormat rgb_format);
|
||||
u8 get_format_texel_width(const VkFormat format);
|
||||
std::pair<VkFormat, VkComponentMapping> get_compatible_surface_format(rsx::surface_color_format color_format);
|
||||
size_t get_render_pass_location(VkFormat color_surface_format, VkFormat depth_stencil_format, u8 color_surface_count);
|
||||
|
|
|
@ -800,7 +800,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,
|
||||
const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
rsx::texture_colorspace colorspace, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
{
|
||||
const u16 section_depth = depth;
|
||||
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap;
|
||||
|
@ -855,6 +855,9 @@ namespace vk
|
|||
default:
|
||||
aspect_flags = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
vk_format = get_compatible_sampler_format(gcm_format);
|
||||
|
||||
if (colorspace != rsx::texture_colorspace::rgb_linear)
|
||||
vk_format = get_compatible_srgb_format(vk_format);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -898,11 +901,11 @@ 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, bool swizzled,
|
||||
const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
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
|
||||
{
|
||||
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, remap_vector);
|
||||
rsx::texture_create_flags::default_component_order, colorspace, remap_vector);
|
||||
|
||||
auto image = section->get_raw_texture();
|
||||
auto subres_range = section->get_raw_view()->info.subresourceRange;
|
||||
|
|
Loading…
Add table
Reference in a new issue