rsx: Use a proper struct to wrap around channel remap operations

This commit is contained in:
kd-11 2024-10-03 02:59:42 +03:00 committed by kd-11
parent b1b0ac4433
commit 826f805902
30 changed files with 317 additions and 308 deletions

View File

@ -1440,17 +1440,18 @@ namespace rsx
texture.border_type() ^ 1);
}
u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
u32 get_remap_encoding(const texture_channel_remap_t& remap)
{
u32 encode = 0;
encode |= (remap.first[0] << 0);
encode |= (remap.first[1] << 2);
encode |= (remap.first[2] << 4);
encode |= (remap.first[3] << 6);
encode |= (remap.second[0] << 8);
encode |= (remap.second[1] << 10);
encode |= (remap.second[2] << 12);
encode |= (remap.second[3] << 14);
encode |= (remap.channel_map[0] << 0);
encode |= (remap.channel_map[1] << 2);
encode |= (remap.channel_map[2] << 4);
encode |= (remap.channel_map[3] << 6);
encode |= (remap.control_map[0] << 8);
encode |= (remap.control_map[1] << 10);
encode |= (remap.control_map[2] << 12);
encode |= (remap.control_map[3] << 14);
return encode;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "io_buffer.h"
#include "../color_utils.h"
#include "../RSXTexture.h"
#include <span>
@ -276,7 +277,7 @@ namespace rsx
/**
* Reverse encoding
*/
u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap);
u32 get_remap_encoding(const texture_channel_remap_t& remap);
/**
* Get gcm texel layout. Returns <format, byteswapped>

View File

@ -1837,7 +1837,6 @@ namespace rsx
commandbuffer_type& cmd,
const image_section_attributes_t& attr,
const size3f& scale,
u32 encoded_remap,
const texture_channel_remap_t& remap,
const texture_cache_search_options& options,
const utils::address_range& memory_range,
@ -1849,7 +1848,7 @@ namespace rsx
// Most mesh textures are stored as compressed to make the most of the limited memory
if (auto cached_texture = find_texture_from_dimensions(attr.address, attr.gcm_format, attr.width, attr.height, attr.depth))
{
return{ cached_texture->get_view(encoded_remap, remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
return{ cached_texture->get_view(remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
}
}
else
@ -1863,7 +1862,7 @@ namespace rsx
const bool force_convert = !render_target_format_is_compatible(texptr, attr.gcm_format);
auto result = helpers::process_framebuffer_resource_fast<sampled_image_descriptor>(
cmd, texptr, attr, scale, extended_dimension, encoded_remap, remap, true, force_convert);
cmd, texptr, attr, scale, extended_dimension, remap, true, force_convert);
if (!options.skip_texture_barriers && result.is_cyclic_reference)
{
@ -1887,7 +1886,7 @@ namespace rsx
const bool force_convert = !render_target_format_is_compatible(last.surface, attr.gcm_format);
return helpers::process_framebuffer_resource_fast<sampled_image_descriptor>(
cmd, last.surface, attr, scale, extended_dimension, encoded_remap, remap, false, force_convert);
cmd, last.surface, attr, scale, extended_dimension, remap, false, force_convert);
}
return {};
@ -1941,7 +1940,7 @@ namespace rsx
break;
}
return{ cached_texture->get_view(encoded_remap, remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
return{ cached_texture->get_view(remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
}
}
@ -2016,7 +2015,7 @@ namespace rsx
{
// Clipped view
auto viewed_image = last->get_raw_texture();
sampled_image_descriptor result = { viewed_image->get_view(encoded_remap, remap), last->get_context(),
sampled_image_descriptor result = { viewed_image->get_view(remap), last->get_context(),
viewed_image->format_class(), scale, extended_dimension, false, viewed_image->samples() };
helpers::calculate_sample_clip_parameters(result, position2i(0, 0), size2i(attr.width, attr.height), size2i(normalized_width, last->get_height()));
@ -2029,7 +2028,7 @@ namespace rsx
}
auto result = helpers::merge_cache_resources<sampled_image_descriptor>(
cmd, overlapping_fbos, overlapping_locals, attr, scale, extended_dimension, encoded_remap, remap, _pool);
cmd, overlapping_fbos, overlapping_locals, attr, scale, extended_dimension, remap, _pool);
const bool is_simple_subresource_copy =
(result.external_subresource_desc.op == deferred_request_command::copy_image_static) ||
@ -2048,13 +2047,12 @@ namespace rsx
position2i(result.external_subresource_desc.x, result.external_subresource_desc.y),
size2i(result.external_subresource_desc.width, result.external_subresource_desc.height),
size2i(result.external_subresource_desc.external_handle->width(), result.external_subresource_desc.external_handle->height()),
encoded_remap, remap, false);
remap, false);
}
else
{
helpers::convert_image_blit_to_clip_descriptor(
result,
encoded_remap,
remap,
false);
}
@ -2348,7 +2346,7 @@ namespace rsx
const auto lookup_range = utils::address_range::start_length(attributes.address, attributes.pitch * required_surface_height);
reader_lock lock(m_cache_mutex);
auto result = fast_texture_search(cmd, attributes, scale, tex.remap(), tex.decoded_remap(),
auto result = fast_texture_search(cmd, attributes, scale, tex.decoded_remap(),
options, lookup_range, extended_dimension, m_rtts,
std::forward<Args>(extras)...);
@ -2423,7 +2421,7 @@ namespace rsx
}
const auto range = utils::address_range::start_length(attr2.address, attr2.pitch * attr2.height);
auto ret = fast_texture_search(cmd, attr2, scale, tex.remap(), tex.decoded_remap(),
auto ret = fast_texture_search(cmd, attr2, scale, tex.decoded_remap(),
options, range, extended_dimension, m_rtts, std::forward<Args>(extras)...);
if (!ret.validate() ||
@ -2488,7 +2486,7 @@ namespace rsx
auto uploaded = upload_image_from_cpu(cmd, tex_range, attributes.width, attributes.height, attributes.depth, tex.get_exact_mipmap_count(), attributes.pitch, attributes.gcm_format,
texture_upload_context::shader_read, subresources_layout, extended_dimension, attributes.swizzled);
return{ uploaded->get_view(tex.remap(), tex.decoded_remap()),
return{ uploaded->get_view(tex.decoded_remap()),
texture_upload_context::shader_read, format_class, scale, extended_dimension };
}

View File

@ -5,8 +5,6 @@
namespace rsx
{
using texture_channel_remap_t = std::pair<std::array<u8, 4>, std::array<u8, 4>>;
// Defines pixel operation to be performed on a surface before it is ready for use
enum surface_transform : u32
{
@ -551,11 +549,10 @@ namespace rsx
const position2i& offset,
const size2i& desired_dimensions,
const size2i& actual_dimensions,
u32 encoded_remap,
const texture_channel_remap_t& decoded_remap,
bool cyclic_reference)
{
desc.image_handle = desc.external_subresource_desc.as_viewable()->get_view(encoded_remap, decoded_remap);
desc.image_handle = desc.external_subresource_desc.as_viewable()->get_view(decoded_remap);
desc.ref_address = desc.external_subresource_desc.external_ref_addr;
desc.is_cyclic_reference = cyclic_reference;
desc.samples = desc.external_subresource_desc.external_handle->samples();
@ -567,7 +564,6 @@ namespace rsx
template <typename sampled_image_descriptor>
void convert_image_blit_to_clip_descriptor(
sampled_image_descriptor& desc,
u32 encoded_remap,
const texture_channel_remap_t& decoded_remap,
bool cyclic_reference)
{
@ -602,7 +598,6 @@ namespace rsx
position2i(section.src_x, section.src_y),
size2i(section.src_w, section.src_h),
size2i(surface_width, surface_height),
encoded_remap,
decoded_remap,
cyclic_reference);
}
@ -613,7 +608,7 @@ namespace rsx
const image_section_attributes_t& attr,
const size3f& scale,
texture_dimension_extended extended_dimension,
u32 encoded_remap, const texture_channel_remap_t& decoded_remap,
const texture_channel_remap_t& decoded_remap,
bool surface_is_rop_target,
bool force_convert)
{
@ -710,7 +705,7 @@ namespace rsx
texptr->memory_barrier(cmd, access_type);
auto viewed_surface = texptr->get_surface(access_type);
sampled_image_descriptor result = { viewed_surface->get_view(encoded_remap, decoded_remap), texture_upload_context::framebuffer_storage,
sampled_image_descriptor result = { viewed_surface->get_view(decoded_remap), texture_upload_context::framebuffer_storage,
texptr->format_class(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target, viewed_surface->samples() };
if (requires_clip)
@ -746,7 +741,7 @@ namespace rsx
const image_section_attributes_t& attr,
const size3f& scale,
texture_dimension_extended extended_dimension,
u32 /*encoded_remap*/, const texture_channel_remap_t& decoded_remap,
const texture_channel_remap_t& decoded_remap,
int select_hint = -1)
{
ensure((select_hint & 0x1) == select_hint);

View File

@ -344,8 +344,8 @@ namespace gl
m_program.uniforms["region_offset"] = color2i(region.x, region.y);
m_program.uniforms["region_size"] = color2i(region.width, region.height);
auto depth_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::depth);
auto stencil_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::stencil);
auto depth_view = src->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_IDENTITY), gl::image_aspect::depth);
auto stencil_view = src->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_IDENTITY), gl::image_aspect::stencil);
if (!m_sampler)
{
@ -396,7 +396,7 @@ namespace gl
m_program.uniforms["is_bgra"] = (layout.format == static_cast<GLenum>(gl::texture::format::bgra));
m_program.uniforms["block_width"] = static_cast<u32>(layout.size);
auto data_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::color);
auto data_view = src->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_IDENTITY), gl::image_aspect::color);
if (!m_sampler)
{

View File

@ -447,7 +447,7 @@ void GLGSRender::bind_texture_env()
if (current_fragment_program.texture_state.redirected_textures & (1 << i))
{
auto root_texture = static_cast<gl::viewable_image*>(view->image());
auto stencil_view = root_texture->get_view(gl::GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::stencil);
auto stencil_view = root_texture->get_view(rsx::default_remap_vector.with_encoding(gl::GL_REMAP_IDENTITY), gl::image_aspect::stencil);
stencil_view->bind(cmd, GL_STENCIL_MIRRORS_START + i);
}
}

View File

@ -807,37 +807,9 @@ namespace gl
}
}
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap)
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const rsx::texture_channel_remap_t& decoded_remap)
{
//Remapping tables; format is A-R-G-B
//Remap input table. Contains channel index to read color from
const auto remap_inputs = decoded_remap.first;
//Remap control table. Controls whether the remap value is used, or force either 0 or 1
const auto remap_lookup = decoded_remap.second;
std::array<GLenum, 4> remap_values;
for (u8 channel = 0; channel < 4; ++channel)
{
switch (remap_lookup[channel])
{
default:
rsx_log.error("Unknown remap function 0x%X", remap_lookup[channel]);
[[fallthrough]];
case CELL_GCM_TEXTURE_REMAP_REMAP:
remap_values[channel] = swizzle_remap[remap_inputs[channel]];
break;
case CELL_GCM_TEXTURE_REMAP_ZERO:
remap_values[channel] = GL_ZERO;
break;
case CELL_GCM_TEXTURE_REMAP_ONE:
remap_values[channel] = GL_ONE;
break;
}
}
return remap_values;
return decoded_remap.remap<GLenum>(swizzle_remap, GL_ZERO, GL_ONE);
}
void upload_texture(gl::command_context& cmd, texture* dst, u32 gcm_format, bool is_swizzled, const std::vector<rsx::subresource_layout>& subresources_layout)

View File

@ -181,8 +181,7 @@ namespace gl
dst->set_native_component_layout(components);
}
const auto encoding = rsx::get_remap_encoding(remap);
return dst->get_view(encoding, remap);
return dst->get_view(remap);
}
void texture_cache::copy_transfer_regions_impl(gl::command_context& cmd, gl::texture* dst_image, const std::vector<copy_region_descriptor>& sources) const

View File

@ -385,9 +385,9 @@ namespace gl
return format;
}
gl::texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
gl::texture_view* get_view(const rsx::texture_channel_remap_t& remap)
{
return vram_texture->get_view(remap_encoding, remap);
return vram_texture->get_view(remap);
}
gl::viewable_image* get_raw_texture() const
@ -402,7 +402,7 @@ namespace gl
gl::texture_view* get_raw_view()
{
return vram_texture->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector);
return vram_texture->get_view(rsx::default_remap_vector.with_encoding(GL_REMAP_IDENTITY));
}
bool is_depth_texture() const

View File

@ -306,13 +306,13 @@ namespace gl
m_id = GL_NONE;
}
texture_view* viewable_image::get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_, GLenum aspect_flags)
texture_view* viewable_image::get_view(const rsx::texture_channel_remap_t& remap_, GLenum aspect_flags)
{
auto remap = remap_;
const u64 view_aspect = static_cast<u64>(aspect_flags) & aspect();
ensure(view_aspect);
const u64 key = static_cast<u64>(remap_encoding) | (view_aspect << 32);
const u64 key = static_cast<u64>(remap.encoded) | (view_aspect << 32);
if (auto found = views.find(key);
found != views.end())
{
@ -323,7 +323,7 @@ namespace gl
std::array<GLenum, 4> mapping;
GLenum* swizzle = nullptr;
if (remap_encoding != GL_REMAP_IDENTITY)
if (remap.encoded != GL_REMAP_IDENTITY)
{
mapping = apply_swizzle_remap(get_native_component_layout(), remap);
swizzle = mapping.data();

View File

@ -459,10 +459,10 @@ namespace gl
public:
using texture::texture;
texture_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap, GLenum aspect_flags = image_aspect::color | image_aspect::depth);
texture_view* get_view(const rsx::texture_channel_remap_t& remap, GLenum aspect_flags = image_aspect::color | image_aspect::depth);
void set_native_component_layout(const std::array<GLenum, 4>& layout);
};
// Texture helpers
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& decoded_remap);
std::array<GLenum, 4> apply_swizzle_remap(const std::array<GLenum, 4>& swizzle_remap, const rsx::texture_channel_remap_t& decoded_remap);
}

View File

@ -165,7 +165,7 @@ namespace rsx
return (registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]);
}
std::pair<std::array<u8, 4>, std::array<u8, 4>> fragment_texture::decoded_remap() const
rsx::texture_channel_remap_t fragment_texture::decoded_remap() const
{
u32 remap_ctl = registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)];
u32 remap_override = (remap_ctl >> 16) & 0xFFFF;
@ -359,18 +359,14 @@ namespace rsx
return std::min(ensure(mipmap()), max_mipmap_count);
}
std::pair<std::array<u8, 4>, std::array<u8, 4>> vertex_texture::decoded_remap() const
rsx::texture_channel_remap_t vertex_texture::decoded_remap() const
{
return
{
{ 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 }
};
return rsx::default_remap_vector;
}
u32 vertex_texture::remap() const
{
//disabled
// disabled
return 0xAAE4;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "gcm_enums.h"
#include "color_utils.h"
namespace rsx
{
@ -58,14 +59,7 @@ namespace rsx
// Control1
u32 remap() const;
/**
* returns a pair of arrays
* First array is a redirection table into the channel indices
* Second array is a lookup reference deciding whether to use the redirection table or use constants 0 and 1
* Both arrays have components in A-R-G-B format
*/
std::pair<std::array<u8, 4>, std::array<u8, 4>> decoded_remap() const;
rsx::texture_channel_remap_t decoded_remap() const;
// Filter
f32 bias() const;
@ -119,7 +113,7 @@ namespace rsx
rsx::texture_wrap_mode wrap_t() const;
rsx::texture_wrap_mode wrap_r() const;
std::pair<std::array<u8, 4>, std::array<u8, 4>> decoded_remap() const;
rsx::texture_channel_remap_t decoded_remap() const;
u32 remap() const;
// Control0

View File

@ -538,7 +538,7 @@ bool VKGSRender::bind_texture_env()
{
// Stencil mirror required
auto root_image = static_cast<vk::viewable_image*>(view->image());
auto stencil_view = root_image->get_view(0xAAE4, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
auto stencil_view = root_image->get_view(rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
if (!m_stencil_mirror_sampler)
{

View File

@ -908,7 +908,7 @@ namespace vk
for (auto& img : src)
{
img->push_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
views.push_back(img->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector));
views.push_back(img->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY)));
}
if (views.size() < 2)

View File

@ -899,15 +899,15 @@ namespace vk
m_cyclic_ref_tracker.reset();
}
image_view* render_target::get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap, VkImageAspectFlags mask)
image_view* render_target::get_view(const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask)
{
if (remap_encoding == VK_REMAP_VIEW_MULTISAMPLED)
if (remap.encoded == VK_REMAP_VIEW_MULTISAMPLED)
{
// Special remap flag, intercept here
return vk::viewable_image::get_view(VK_REMAP_IDENTITY, remap, mask);
return vk::viewable_image::get_view(remap.with_encoding(VK_REMAP_IDENTITY), mask);
}
return vk::viewable_image::get_view(remap_encoding, remap, mask);
return vk::viewable_image::get_view(remap, mask);
}
void render_target::memory_barrier(vk::command_buffer& cmd, rsx::surface_access access)

View File

@ -113,7 +113,7 @@ namespace vk
bool matches_dimensions(u16 _width, u16 _height) const;
void reset_surface_counters();
image_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap,
image_view* get_view(const rsx::texture_channel_remap_t& remap,
VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) override;
// Memory management

View File

@ -119,8 +119,8 @@ namespace vk
void bind_resources() override
{
auto msaa_view = multisampled->get_view(VK_REMAP_VIEW_MULTISAMPLED, rsx::default_remap_vector);
auto resolved_view = resolve->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
auto msaa_view = multisampled->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_VIEW_MULTISAMPLED));
auto resolved_view = resolve->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
m_program->bind_uniform({ VK_NULL_HANDLE, msaa_view->value, multisampled->current_layout }, "multisampled", VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_descriptor_set);
m_program->bind_uniform({ VK_NULL_HANDLE, resolved_view->value, resolve->current_layout }, "resolve", VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_descriptor_set);
}
@ -277,7 +277,7 @@ namespace vk
void run(vk::command_buffer& cmd, vk::viewable_image* msaa_image, vk::viewable_image* resolve_image, VkRenderPass render_pass)
{
update_sample_configuration(msaa_image);
auto src_view = msaa_image->get_view(VK_REMAP_VIEW_MULTISAMPLED, rsx::default_remap_vector);
auto src_view = msaa_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_VIEW_MULTISAMPLED));
overlay_pass::run(
cmd,
@ -308,7 +308,7 @@ namespace vk
renderpass_config.set_multisample_shading_rate(1.f);
update_sample_configuration(msaa_image);
auto src_view = resolve_image->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
auto src_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
overlay_pass::run(
cmd,
@ -372,7 +372,7 @@ namespace vk
void run(vk::command_buffer& cmd, vk::viewable_image* msaa_image, vk::viewable_image* resolve_image, VkRenderPass render_pass)
{
update_sample_configuration(msaa_image);
auto stencil_view = msaa_image->get_view(VK_REMAP_VIEW_MULTISAMPLED, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
auto stencil_view = msaa_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_VIEW_MULTISAMPLED), VK_IMAGE_ASPECT_STENCIL_BIT);
region.rect.extent.width = resolve_image->width();
region.rect.extent.height = resolve_image->height();
@ -442,7 +442,7 @@ namespace vk
renderpass_config.set_multisample_shading_rate(1.f);
update_sample_configuration(msaa_image);
auto stencil_view = resolve_image->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
auto stencil_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY), VK_IMAGE_ASPECT_STENCIL_BIT);
region.rect.extent.width = resolve_image->width();
region.rect.extent.height = resolve_image->height();
@ -486,8 +486,8 @@ namespace vk
void run(vk::command_buffer& cmd, vk::viewable_image* msaa_image, vk::viewable_image* resolve_image, VkRenderPass render_pass)
{
update_sample_configuration(msaa_image);
auto depth_view = msaa_image->get_view(VK_REMAP_VIEW_MULTISAMPLED, rsx::default_remap_vector, VK_IMAGE_ASPECT_DEPTH_BIT);
auto stencil_view = msaa_image->get_view(VK_REMAP_VIEW_MULTISAMPLED, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
auto depth_view = msaa_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_VIEW_MULTISAMPLED), VK_IMAGE_ASPECT_DEPTH_BIT);
auto stencil_view = msaa_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_VIEW_MULTISAMPLED), VK_IMAGE_ASPECT_STENCIL_BIT);
overlay_pass::run(
cmd,
@ -531,8 +531,8 @@ namespace vk
renderpass_config.set_multisample_shading_rate(1.f);
update_sample_configuration(msaa_image);
auto depth_view = resolve_image->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector, VK_IMAGE_ASPECT_DEPTH_BIT);
auto stencil_view = resolve_image->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector, VK_IMAGE_ASPECT_STENCIL_BIT);
auto depth_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY), VK_IMAGE_ASPECT_DEPTH_BIT);
auto stencil_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY), VK_IMAGE_ASPECT_STENCIL_BIT);
overlay_pass::run(
cmd,

View File

@ -709,7 +709,7 @@ namespace vk
image->set_debug_name("Temp view");
image->set_native_component_layout(view_swizzle);
auto view = image->get_view(rsx::get_remap_encoding(remap_vector), remap_vector);
auto view = image->get_view(remap_vector);
if (copy)
{

View File

@ -144,16 +144,16 @@ namespace vk
return !exists() || managed_texture;
}
vk::image_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
vk::image_view* get_view(const rsx::texture_channel_remap_t& remap)
{
ensure(vram_texture != nullptr);
return vram_texture->get_view(remap_encoding, remap);
return vram_texture->get_view(remap);
}
vk::image_view* get_raw_view()
{
ensure(vram_texture != nullptr);
return vram_texture->get_view(0xAAE4, rsx::default_remap_vector);
return vram_texture->get_view(rsx::default_remap_vector);
}
vk::viewable_image* get_raw_texture()

View File

@ -117,8 +117,8 @@ namespace vk
void fsr_pass::run(const vk::command_buffer& cmd, vk::viewable_image* src, vk::viewable_image* dst, const size2u& input_size, const size2u& output_size)
{
m_input_image = src->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
m_output_image = dst->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
m_input_image = src->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
m_output_image = dst->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
m_input_size = input_size;
m_output_size = output_size;

View File

@ -411,8 +411,9 @@ namespace vk
return result;
}
image_view* viewable_image::get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap, VkImageAspectFlags mask)
image_view* viewable_image::get_view(const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask)
{
u32 remap_encoding = remap.encoded;
if (remap_encoding == VK_REMAP_IDENTITY)
{
if (native_component_map.a == VK_COMPONENT_SWIZZLE_A &&

View File

@ -134,7 +134,7 @@ namespace vk
public:
using image::image;
virtual image_view* get_view(u32 remap_encoding, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap,
virtual image_view* get_view(const rsx::texture_channel_remap_t& remap,
VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
void set_native_component_layout(VkComponentMapping new_layout);

View File

@ -3,6 +3,7 @@
#include "image.h"
#include "util/logs.hpp"
#include "../VKRenderPass.h"
#include "../../color_utils.h"
#include "../../gcm_enums.h"
namespace vk
@ -30,29 +31,10 @@ namespace vk
}
}
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_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const rsx::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:
rsx_log.error("Unknown remap lookup value %d", remap_vector.second[channel]);
}
}
return{ final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] };
const auto final_mapping = remap_vector.remap(base_remap, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE);
return { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] };
}
void change_image_layout(const vk::command_buffer& cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, const VkImageSubresourceRange& range,

View File

@ -1,6 +1,11 @@
#pragma once
#include "../VulkanAPI.h"
namespace rsx
{
struct texture_channel_remap_t;
}
namespace vk
{
class image;
@ -9,7 +14,7 @@ namespace vk
extern VkComponentMapping default_component_map;
VkImageAspectFlags get_aspect_flags(VkFormat format);
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_swizzle_remap(const std::array<VkComponentSwizzle, 4>& base_remap, const rsx::texture_channel_remap_t& remap_vector);
void change_image_layout(const vk::command_buffer& cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, const VkImageSubresourceRange& range,
u32 src_queue_family = VK_QUEUE_FAMILY_IGNORED, u32 dst_queue_family = VK_QUEUE_FAMILY_IGNORED,

View File

@ -61,7 +61,7 @@ namespace vk
if (auto found = g_null_image_views.find(type);
found != g_null_image_views.end())
{
return found->second->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
return found->second->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
}
VkImageType image_type;
@ -118,7 +118,7 @@ namespace vk
tex->change_layout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Return view
return tex->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
return tex->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY));
}
vk::image* get_typeless_helper(VkFormat format, rsx::format_class format_class, u32 requested_width, u32 requested_height)

227
rpcs3/Emu/RSX/color_utils.h Normal file
View File

@ -0,0 +1,227 @@
#pragma once
#include <util/types.hpp>
#include <Utilities/geometry.h>
#include "gcm_enums.h"
namespace rsx
{
struct texture_channel_remap_t
{
u32 encoded;
std::array<u8, 4> control_map;
std::array<u8, 4> channel_map;
template <typename T>
std::array<T, 4> remap(const std::array<T, 4>& components, T select_zero, T select_one) const
{
std::array<T, 4> remapped{};
for (u8 channel = 0; channel < 4; ++channel)
{
switch (control_map[channel])
{
default:
[[fallthrough]];
case CELL_GCM_TEXTURE_REMAP_REMAP:
remapped[channel] = components[channel_map[channel]];
break;
case CELL_GCM_TEXTURE_REMAP_ZERO:
remapped[channel] = select_zero;
break;
case CELL_GCM_TEXTURE_REMAP_ONE:
remapped[channel] = select_one;
break;
}
}
return remapped;
}
template <typename T>
requires std::is_integral_v<T> || std::is_floating_point_v<T>
std::array<T, 4> remap(const std::array<T, 4>& components) const
{
return remap(components, static_cast<T>(0), static_cast<T>(1));
}
template <typename T>
requires std::is_integral_v<T> || std::is_enum_v<T>
texture_channel_remap_t with_encoding(T encoding) const
{
texture_channel_remap_t result = *this;
result.encoded = encoding;
return result;
}
};
static const texture_channel_remap_t default_remap_vector =
{
.encoded = 0xAAE4,
.control_map = { CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP },
.channel_map = { CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B }
};
static inline texture_channel_remap_t decode_remap_encoding(u32 remap_ctl)
{
// Remapping tables; format is A-R-G-B
// Remap input table. Contains channel index to read color from
texture_channel_remap_t result =
{
.encoded = remap_ctl
};
result.channel_map =
{
static_cast<u8>(remap_ctl & 0x3),
static_cast<u8>((remap_ctl >> 2) & 0x3),
static_cast<u8>((remap_ctl >> 4) & 0x3),
static_cast<u8>((remap_ctl >> 6) & 0x3),
};
// Remap control table. Controls whether the remap value is used, or force either 0 or 1
result.control_map =
{
static_cast<u8>((remap_ctl >> 8) & 0x3),
static_cast<u8>((remap_ctl >> 10) & 0x3),
static_cast<u8>((remap_ctl >> 12) & 0x3),
static_cast<u8>((remap_ctl >> 14) & 0x3),
};
return result;
}
// Convert color write mask for G8B8 to R8G8
static inline u32 get_g8b8_r8g8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_g8b8_r8g8_colormask(bool& red, bool&/*green*/, bool& blue, bool& alpha)
{
red = blue;
blue = false;
alpha = false;
}
static inline void get_g8b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
red = blue;
}
static inline u32 get_abgr8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_RED_BIT) result |= RSX_GCM_CLEAR_BLUE_BIT;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
if (mask & RSX_GCM_CLEAR_ALPHA_BIT) result |= RSX_GCM_CLEAR_ALPHA_BIT;
return result;
}
static inline void get_abgr8_colormask(bool& red, bool& /*green*/, bool& blue, bool& /*alpha*/)
{
std::swap(red, blue);
}
static inline void get_abgr8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
std::swap(red, blue);
}
template <typename T, typename U>
requires std::is_integral_v<T>&& std::is_integral_v<U>
u8 renormalize_color8(T input, U base)
{
// Base will be some POT-1 value
const int value = static_cast<u8>(input & base);
return static_cast<u8>((value * 255) / base);
}
static inline void get_rgb565_clear_color(u8& red, u8& green, u8& blue, u8& /*alpha*/)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x3f);
red = renormalize_color8(raw_value >> 11, 0x1f);
}
static inline void get_a1rgb555_clear_color(u8& red, u8& green, u8& blue, u8& alpha, u8 alpha_override)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x1f);
red = renormalize_color8(raw_value >> 10, 0x1f);
// Alpha can technically be encoded into the clear but the format normally just injects constants.
// Will require hardware tests when possible to determine which approach makes more sense.
// alpha = static_cast<u8>((raw_value & (1 << 15)) ? 255 : 0);
alpha = alpha_override;
}
static inline u32 get_b8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_b8_colormask(bool& red, bool& green, bool& blue, bool& alpha)
{
red = blue;
green = false;
blue = false;
alpha = false;
}
static inline void get_b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
std::swap(red, blue);
}
static inline color4f decode_border_color(u32 colorref)
{
color4f result;
result.b = (colorref & 0xFF) / 255.f;
result.g = ((colorref >> 8) & 0xFF) / 255.f;
result.r = ((colorref >> 16) & 0xFF) / 255.f;
result.a = ((colorref >> 24) & 0xFF) / 255.f;
return result;
}
static inline const std::array<bool, 4> get_write_output_mask(rsx::surface_color_format format)
{
constexpr std::array<bool, 4> rgba = { true, true, true, true };
constexpr std::array<bool, 4> rgb = { true, true, true, false };
constexpr std::array<bool, 4> rg = { true, true, false, false };
constexpr std::array<bool, 4> r = { true, false, false, false };
switch (format)
{
case rsx::surface_color_format::a8r8g8b8:
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::w16z16y16x16:
case rsx::surface_color_format::w32z32y32x32:
return rgba;
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::r5g6b5:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
return rgb;
case rsx::surface_color_format::g8b8:
return rg;
case rsx::surface_color_format::b8:
case rsx::surface_color_format::x32:
return r;
default:
fmt::throw_exception("Unknown surface format 0x%x", static_cast<int>(format));
}
}
}

View File

@ -216,36 +216,6 @@ namespace rsx
bool swizzled;
};
static const std::pair<std::array<u8, 4>, std::array<u8, 4>> 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 }
};
static inline std::pair<std::array<u8, 4>, std::array<u8, 4>> decode_remap_encoding(u32 remap_ctl)
{
// Remapping tables; format is A-R-G-B
// Remap input table. Contains channel index to read color from
const std::array<u8, 4> remap_inputs =
{
static_cast<u8>(remap_ctl & 0x3),
static_cast<u8>((remap_ctl >> 2) & 0x3),
static_cast<u8>((remap_ctl >> 4) & 0x3),
static_cast<u8>((remap_ctl >> 6) & 0x3),
};
// Remap control table. Controls whether the remap value is used, or force either 0 or 1
const std::array<u8, 4> remap_lookup =
{
static_cast<u8>((remap_ctl >> 8) & 0x3),
static_cast<u8>((remap_ctl >> 10) & 0x3),
static_cast<u8>((remap_ctl >> 12) & 0x3),
static_cast<u8>((remap_ctl >> 14) & 0x3),
};
return std::make_pair(remap_inputs, remap_lookup);
}
template <typename T>
void pad_texture(void* input_pixels, void* output_pixels, u16 input_width, u16 input_height, u16 output_width, u16 /*output_height*/)
{
@ -774,142 +744,6 @@ namespace rsx
return (index + index_base) & 0x000FFFFF;
}
// Convert color write mask for G8B8 to R8G8
static inline u32 get_g8b8_r8g8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_g8b8_r8g8_colormask(bool &red, bool &/*green*/, bool &blue, bool &alpha)
{
red = blue;
blue = false;
alpha = false;
}
static inline void get_g8b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
red = blue;
}
static inline u32 get_abgr8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_RED_BIT) result |= RSX_GCM_CLEAR_BLUE_BIT;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
if (mask & RSX_GCM_CLEAR_ALPHA_BIT) result |= RSX_GCM_CLEAR_ALPHA_BIT;
return result;
}
static inline void get_abgr8_colormask(bool& red, bool& /*green*/, bool& blue, bool& /*alpha*/)
{
std::swap(red, blue);
}
static inline void get_abgr8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
std::swap(red, blue);
}
template <typename T, typename U>
requires std::is_integral_v<T> && std::is_integral_v<U>
u8 renormalize_color8(T input, U base)
{
// Base will be some POT-1 value
const int value = static_cast<u8>(input & base);
return static_cast<u8>((value * 255) / base);
}
static inline void get_rgb565_clear_color(u8& red, u8& green, u8& blue, u8& /*alpha*/)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x3f);
red = renormalize_color8(raw_value >> 11, 0x1f);
}
static inline void get_a1rgb555_clear_color(u8& red, u8& green, u8& blue, u8& alpha, u8 alpha_override)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x1f);
red = renormalize_color8(raw_value >> 10, 0x1f);
// Alpha can technically be encoded into the clear but the format normally just injects constants.
// Will require hardware tests when possible to determine which approach makes more sense.
// alpha = static_cast<u8>((raw_value & (1 << 15)) ? 255 : 0);
alpha = alpha_override;
}
static inline u32 get_b8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_b8_colormask(bool& red, bool& green, bool& blue, bool& alpha)
{
red = blue;
green = false;
blue = false;
alpha = false;
}
static inline void get_b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
std::swap(red, blue);
}
static inline color4f decode_border_color(u32 colorref)
{
color4f result;
result.b = (colorref & 0xFF) / 255.f;
result.g = ((colorref >> 8) & 0xFF) / 255.f;
result.r = ((colorref >> 16) & 0xFF) / 255.f;
result.a = ((colorref >> 24) & 0xFF) / 255.f;
return result;
}
static inline const std::array<bool, 4> get_write_output_mask(rsx::surface_color_format format)
{
constexpr std::array<bool, 4> rgba = { true, true, true, true };
constexpr std::array<bool, 4> rgb = { true, true, true, false };
constexpr std::array<bool, 4> rg = { true, true, false, false };
constexpr std::array<bool, 4> r = { true, false, false, false };
switch (format)
{
case rsx::surface_color_format::a8r8g8b8:
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::w16z16y16x16:
case rsx::surface_color_format::w32z32y32x32:
return rgba;
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::r5g6b5:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
return rgb;
case rsx::surface_color_format::g8b8:
return rg;
case rsx::surface_color_format::b8:
case rsx::surface_color_format::x32:
return r;
default:
fmt::throw_exception("Unknown surface format 0x%x", static_cast<int>(format));
}
}
template <uint integer, uint frac, bool sign = true, typename To = f32>
static inline To decode_fxp(u32 bits)
{

View File

@ -597,6 +597,7 @@
<ClInclude Include="Emu\NP\rpcn_client.h" />
<ClInclude Include="Emu\NP\rpcn_config.h" />
<ClInclude Include="Emu\perf_monitor.hpp" />
<ClInclude Include="Emu\RSX\color_utils.h" />
<ClInclude Include="Emu\RSX\Common\bitfield.hpp" />
<ClInclude Include="Emu\RSX\Common\buffer_stream.hpp" />
<ClInclude Include="Emu\RSX\Common\tiled_dma_copy.hpp" />

View File

@ -2608,6 +2608,9 @@
<ClInclude Include="Emu\RSX\display.h">
<Filter>Emu\GPU\RSX\Utils</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\color_utils.h">
<Filter>Emu\GPU\RSX\Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">