mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 18:39:57 +00:00
rsx: Use a proper struct to wrap around channel remap operations
This commit is contained in:
parent
b1b0ac4433
commit
826f805902
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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 };
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
227
rpcs3/Emu/RSX/color_utils.h
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user