mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
rsx: Refactor and improve image memory manipulation routines
This commit is contained in:
parent
f6c6c04648
commit
65ead08880
File diff suppressed because it is too large
Load Diff
@ -43,19 +43,31 @@ namespace rsx
|
||||
transfer = 2
|
||||
};
|
||||
|
||||
enum format_type : u8
|
||||
// Defines how the underlying PS3-visible memory backed by a texture is accessed
|
||||
namespace format_class_
|
||||
{
|
||||
color = 0,
|
||||
depth_uint = 1,
|
||||
depth_float = 2
|
||||
};
|
||||
// TODO: Remove when enum import is supported by GCC
|
||||
enum format_class : u8
|
||||
{
|
||||
RSX_FORMAT_CLASS_UNDEFINED = 0,
|
||||
RSX_FORMAT_CLASS_COLOR = 1,
|
||||
RSX_FORMAT_CLASS_DEPTH16_UNORM = 2,
|
||||
RSX_FORMAT_CLASS_DEPTH16_FLOAT = 4,
|
||||
RSX_FORMAT_CLASS_DEPTH24_UNORM_X8_PACK32 = 8,
|
||||
RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32 = 16,
|
||||
|
||||
RSX_FORMAT_CLASS_DEPTH_FLOAT_MASK = (RSX_FORMAT_CLASS_DEPTH16_FLOAT | RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32)
|
||||
};
|
||||
}
|
||||
|
||||
using namespace format_class_;
|
||||
|
||||
//Sampled image descriptor
|
||||
struct sampled_image_descriptor_base
|
||||
{
|
||||
texture_upload_context upload_context = texture_upload_context::shader_read;
|
||||
rsx::texture_dimension_extended image_type = texture_dimension_extended::texture_dimension_2d;
|
||||
rsx::format_type format_class = rsx::format_type::color;
|
||||
rsx::format_class format_class = RSX_FORMAT_CLASS_UNDEFINED;
|
||||
bool is_cyclic_reference = false;
|
||||
f32 scale_x = 1.f;
|
||||
f32 scale_y = 1.f;
|
||||
@ -82,88 +94,91 @@ namespace rsx
|
||||
|
||||
void analyse();
|
||||
};
|
||||
|
||||
struct subresource_layout
|
||||
{
|
||||
gsl::span<const std::byte> data;
|
||||
u16 width_in_texel;
|
||||
u16 height_in_texel;
|
||||
u16 width_in_block;
|
||||
u16 height_in_block;
|
||||
u16 depth;
|
||||
u16 level;
|
||||
u16 layer;
|
||||
u8 border;
|
||||
u8 reserved;
|
||||
u32 pitch_in_block;
|
||||
};
|
||||
|
||||
struct texture_memory_info
|
||||
{
|
||||
int element_size;
|
||||
int block_length;
|
||||
bool require_swap;
|
||||
bool require_deswizzle;
|
||||
};
|
||||
|
||||
struct texture_uploader_capabilities
|
||||
{
|
||||
bool supports_byteswap;
|
||||
bool supports_vtc_decoding;
|
||||
bool supports_hw_deswizzle;
|
||||
size_t alignment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get size to store texture in a linear fashion.
|
||||
* Storage is assumed to use a rowPitchAlignment boundary for every row of texture.
|
||||
*/
|
||||
size_t get_placed_texture_storage_size(u16 width, u16 height, u32 depth, u8 format, u16 mipmap, bool cubemap, size_t row_pitch_alignment, size_t mipmap_alignment);
|
||||
size_t get_placed_texture_storage_size(const rsx::fragment_texture &texture, size_t row_pitch_alignment, size_t mipmap_alignment = 0x200);
|
||||
size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_t row_pitch_alignment, size_t mipmap_alignment = 0x200);
|
||||
|
||||
/**
|
||||
* get all rsx::subresource_layout for texture.
|
||||
* The subresources are ordered per layer then per mipmap level (as in rsx memory).
|
||||
*/
|
||||
std::vector<subresource_layout> get_subresources_layout(const rsx::fragment_texture &texture);
|
||||
std::vector<subresource_layout> get_subresources_layout(const rsx::vertex_texture &texture);
|
||||
|
||||
texture_memory_info upload_texture_subresource(gsl::span<std::byte> dst_buffer, const subresource_layout &src_layout, int format, bool is_swizzled, const texture_uploader_capabilities& caps);
|
||||
|
||||
u8 get_format_block_size_in_bytes(int format);
|
||||
u8 get_format_block_size_in_texel(int format);
|
||||
u8 get_format_block_size_in_bytes(rsx::surface_color_format format);
|
||||
u8 get_format_block_size_in_bytes(rsx::surface_depth_format2 format);
|
||||
|
||||
u8 get_format_sample_count(rsx::surface_antialiasing antialias);
|
||||
u32 get_max_depth_value(rsx::surface_depth_format2 format);
|
||||
bool is_depth_stencil_format(rsx::surface_depth_format2 format);
|
||||
|
||||
/**
|
||||
* Returns number of texel rows encoded in one pitch-length line of bytes
|
||||
*/
|
||||
u8 get_format_texel_rows_per_line(u32 format);
|
||||
|
||||
/**
|
||||
* Get number of bytes occupied by texture in RSX mem
|
||||
*/
|
||||
size_t get_texture_size(const rsx::fragment_texture &texture);
|
||||
size_t get_texture_size(const rsx::vertex_texture &texture);
|
||||
|
||||
/**
|
||||
* Get packed pitch
|
||||
*/
|
||||
u32 get_format_packed_pitch(u32 format, u16 width, bool border = false, bool swizzled = false);
|
||||
|
||||
/**
|
||||
* Reverse encoding
|
||||
*/
|
||||
u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap);
|
||||
|
||||
/**
|
||||
* Get gcm texel layout. Returns <format, byteswapped>
|
||||
*/
|
||||
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_color_format format);
|
||||
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_depth_format2 format);
|
||||
|
||||
format_class classify_format(rsx::surface_depth_format2 format);
|
||||
format_class classify_format(u32 gcm_format);
|
||||
}
|
||||
|
||||
struct rsx_subresource_layout
|
||||
{
|
||||
gsl::span<const std::byte> data;
|
||||
u16 width_in_texel;
|
||||
u16 height_in_texel;
|
||||
u16 width_in_block;
|
||||
u16 height_in_block;
|
||||
u16 depth;
|
||||
u16 level;
|
||||
u16 layer;
|
||||
u8 border;
|
||||
u8 reserved;
|
||||
u32 pitch_in_block;
|
||||
};
|
||||
|
||||
struct texture_memory_info
|
||||
{
|
||||
int element_size;
|
||||
int block_length;
|
||||
bool require_swap;
|
||||
bool require_deswizzle;
|
||||
};
|
||||
|
||||
struct texture_uploader_capabilities
|
||||
{
|
||||
bool supports_byteswap;
|
||||
bool supports_vtc_decoding;
|
||||
bool supports_hw_deswizzle;
|
||||
size_t alignment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get size to store texture in a linear fashion.
|
||||
* Storage is assumed to use a rowPitchAlignment boundary for every row of texture.
|
||||
*/
|
||||
size_t get_placed_texture_storage_size(u16 width, u16 height, u32 depth, u8 format, u16 mipmap, bool cubemap, size_t row_pitch_alignment, size_t mipmap_alignment);
|
||||
size_t get_placed_texture_storage_size(const rsx::fragment_texture &texture, size_t row_pitch_alignment, size_t mipmap_alignment = 0x200);
|
||||
size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_t row_pitch_alignment, size_t mipmap_alignment = 0x200);
|
||||
|
||||
/**
|
||||
* get all rsx_subresource_layout for texture.
|
||||
* The subresources are ordered per layer then per mipmap level (as in rsx memory).
|
||||
*/
|
||||
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::fragment_texture &texture);
|
||||
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::vertex_texture &texture);
|
||||
|
||||
texture_memory_info upload_texture_subresource(gsl::span<std::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, const texture_uploader_capabilities& caps);
|
||||
|
||||
u8 get_format_block_size_in_bytes(int format);
|
||||
u8 get_format_block_size_in_texel(int format);
|
||||
u8 get_format_block_size_in_bytes(rsx::surface_color_format format);
|
||||
u8 get_format_block_size_in_bytes(rsx::surface_depth_format2 format);
|
||||
|
||||
u8 get_format_sample_count(rsx::surface_antialiasing antialias);
|
||||
u32 get_max_depth_value(rsx::surface_depth_format2 format);
|
||||
bool is_depth_stencil_format(rsx::surface_depth_format2 format);
|
||||
|
||||
/**
|
||||
* Returns number of texel rows encoded in one pitch-length line of bytes
|
||||
*/
|
||||
u8 get_format_texel_rows_per_line(u32 format);
|
||||
|
||||
/**
|
||||
* Get number of bytes occupied by texture in RSX mem
|
||||
*/
|
||||
size_t get_texture_size(const rsx::fragment_texture &texture);
|
||||
size_t get_texture_size(const rsx::vertex_texture &texture);
|
||||
|
||||
/**
|
||||
* Get packed pitch
|
||||
*/
|
||||
u32 get_format_packed_pitch(u32 format, u16 width, bool border = false, bool swizzled = false);
|
||||
|
||||
/**
|
||||
* Reverse encoding
|
||||
*/
|
||||
u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap);
|
||||
|
||||
/**
|
||||
* Get gcm texel layout. Returns <format, byteswapped>
|
||||
*/
|
||||
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_color_format format);
|
||||
std::pair<u32, bool> get_compatible_gcm_format(rsx::surface_depth_format2 format);
|
||||
|
@ -135,8 +135,6 @@ namespace rsx
|
||||
u8 samples_x = 1;
|
||||
u8 samples_y = 1;
|
||||
|
||||
format_type format_class = format_type::color;
|
||||
|
||||
std::unique_ptr<typename std::remove_pointer<image_storage_type>::type> resolve_surface;
|
||||
surface_sample_layout sample_layout = surface_sample_layout::null;
|
||||
surface_raster_type raster_type = surface_raster_type::linear;
|
||||
@ -266,15 +264,6 @@ namespace rsx
|
||||
void set_format(rsx::surface_depth_format2 format)
|
||||
{
|
||||
format_info.gcm_depth_format = format;
|
||||
|
||||
if (format >= rsx::surface_depth_format2::z16_float)
|
||||
{
|
||||
format_class = rsx::format_type::depth_float;
|
||||
}
|
||||
else
|
||||
{
|
||||
format_class = rsx::format_type::depth_uint;
|
||||
}
|
||||
}
|
||||
|
||||
rsx::surface_color_format get_surface_color_format() const
|
||||
@ -287,11 +276,6 @@ namespace rsx
|
||||
return format_info.gcm_depth_format;
|
||||
}
|
||||
|
||||
rsx::format_type get_format_type() const
|
||||
{
|
||||
return format_class;
|
||||
}
|
||||
|
||||
bool dirty() const
|
||||
{
|
||||
return (state_flags != rsx::surface_state_flags::ready) || !old_contents.empty();
|
||||
|
@ -169,7 +169,7 @@ namespace rsx
|
||||
|
||||
sampled_image_descriptor() = default;
|
||||
|
||||
sampled_image_descriptor(image_view_type handle, texture_upload_context ctx, format_type ftype,
|
||||
sampled_image_descriptor(image_view_type handle, texture_upload_context ctx, rsx::format_class ftype,
|
||||
size2f scale, rsx::texture_dimension_extended type, bool cyclic_reference = false)
|
||||
{
|
||||
image_handle = handle;
|
||||
@ -183,7 +183,7 @@ namespace rsx
|
||||
|
||||
sampled_image_descriptor(image_resource_type external_handle, deferred_request_command reason,
|
||||
const image_section_attributes_t& attr, position2u src_offset,
|
||||
texture_upload_context ctx, format_type ftype, size2f scale,
|
||||
texture_upload_context ctx, rsx::format_class ftype, size2f scale,
|
||||
rsx::texture_dimension_extended type, const texture_channel_remap_t& remap)
|
||||
{
|
||||
external_subresource_desc = { external_handle, reason, attr, src_offset, remap };
|
||||
@ -320,7 +320,7 @@ namespace rsx
|
||||
virtual section_storage_type* create_new_texture(commandbuffer_type&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format,
|
||||
rsx::texture_upload_context context, rsx::texture_dimension_extended type, bool swizzled, texture_create_flags flags) = 0;
|
||||
virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, const address_range &rsx_range, 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) = 0;
|
||||
const std::vector<rsx::subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) = 0;
|
||||
virtual section_storage_type* create_nul_section(commandbuffer_type&, const address_range &rsx_range, bool memory_load) = 0;
|
||||
virtual void enforce_surface_creation_type(section_storage_type& section, u32 gcm_format, texture_create_flags expected) = 0;
|
||||
virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0;
|
||||
@ -1516,7 +1516,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_type(), scale, cached_texture->get_image_type() };
|
||||
return{ cached_texture->get_view(encoded_remap, remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1605,7 +1605,7 @@ namespace rsx
|
||||
continue;
|
||||
}
|
||||
|
||||
return{ cached_texture->get_view(encoded_remap, remap), cached_texture->get_context(), cached_texture->get_format_type(), scale, cached_texture->get_image_type() };
|
||||
return{ cached_texture->get_view(encoded_remap, remap), cached_texture->get_context(), cached_texture->get_format_class(), scale, cached_texture->get_image_type() };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1677,7 +1677,7 @@ namespace rsx
|
||||
new_attr.gcm_format = gcm_format;
|
||||
|
||||
return { last->get_raw_texture(), deferred_request_command::copy_image_static, new_attr, {},
|
||||
last->get_context(), helpers::get_format_class(gcm_format), scale, extended_dimension, remap };
|
||||
last->get_context(), classify_format(gcm_format), scale, extended_dimension, remap };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1936,7 +1936,7 @@ namespace rsx
|
||||
|
||||
// Do direct upload from CPU as the last resort
|
||||
const auto subresources_layout = get_subresources_layout(tex);
|
||||
const auto format_class = helpers::get_format_class(attributes.gcm_format);
|
||||
const auto format_class = classify_format(attributes.gcm_format);
|
||||
|
||||
if (!tex_size)
|
||||
{
|
||||
@ -2544,8 +2544,8 @@ namespace rsx
|
||||
image_height = src_h;
|
||||
}
|
||||
|
||||
std::vector<rsx_subresource_layout> subresource_layout;
|
||||
rsx_subresource_layout subres = {};
|
||||
std::vector<rsx::subresource_layout> subresource_layout;
|
||||
rsx::subresource_layout subres = {};
|
||||
subres.width_in_block = subres.width_in_texel = image_width;
|
||||
subres.height_in_block = subres.height_in_texel = image_height;
|
||||
subres.pitch_in_block = full_width;
|
||||
@ -2676,8 +2676,8 @@ namespace rsx
|
||||
utils::memory_protect(vm::base(prot_range.start), prot_range.length(), utils::protection::no);
|
||||
|
||||
const u16 pitch_in_block = dst.pitch / dst_bpp;
|
||||
std::vector<rsx_subresource_layout> subresource_layout;
|
||||
rsx_subresource_layout subres = {};
|
||||
std::vector<rsx::subresource_layout> subresource_layout;
|
||||
rsx::subresource_layout subres = {};
|
||||
subres.width_in_block = subres.width_in_texel = dst_dimensions.width;
|
||||
subres.height_in_block = subres.height_in_texel = dst_dimensions.height;
|
||||
subres.pitch_in_block = pitch_in_block;
|
||||
|
@ -164,21 +164,6 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
static inline format_type get_format_class(u32 gcm_format)
|
||||
{
|
||||
switch (gcm_format)
|
||||
{
|
||||
default:
|
||||
return format_type::color;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
return format_type::depth_uint;
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return format_type::depth_float;
|
||||
}
|
||||
}
|
||||
|
||||
static blit_target_properties get_optimal_blit_target_properties(
|
||||
bool src_is_render_target,
|
||||
address_range dst_range,
|
||||
@ -556,7 +541,7 @@ namespace rsx
|
||||
const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true);
|
||||
const auto scaled_h = rsx::apply_resolution_scale(attr2.height, true);
|
||||
|
||||
const auto format_class = (force_convert) ? get_format_class(attr2.gcm_format) : texptr->get_format_type();
|
||||
const auto format_class = (force_convert) ? classify_format(attr2.gcm_format) : texptr->format_class();
|
||||
const auto command = surface_is_rop_target ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static;
|
||||
|
||||
attr2.width = scaled_w;
|
||||
@ -568,7 +553,7 @@ namespace rsx
|
||||
}
|
||||
|
||||
return{ texptr->get_view(encoded_remap, decoded_remap), texture_upload_context::framebuffer_storage,
|
||||
texptr->get_format_type(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target };
|
||||
texptr->format_class(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target };
|
||||
}
|
||||
|
||||
const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true);
|
||||
@ -578,7 +563,7 @@ namespace rsx
|
||||
{
|
||||
return{ texptr->get_surface(rsx::surface_access::read), deferred_request_command::_3d_unwrap,
|
||||
attr2, {},
|
||||
texture_upload_context::framebuffer_storage, texptr->get_format_type(), scale,
|
||||
texture_upload_context::framebuffer_storage, texptr->format_class(), scale,
|
||||
rsx::texture_dimension_extended::texture_dimension_3d, decoded_remap };
|
||||
}
|
||||
|
||||
@ -589,7 +574,7 @@ namespace rsx
|
||||
|
||||
return{ texptr->get_surface(rsx::surface_access::read), deferred_request_command::cubemap_unwrap,
|
||||
attr2, {},
|
||||
texture_upload_context::framebuffer_storage, texptr->get_format_type(), scale,
|
||||
texture_upload_context::framebuffer_storage, texptr->format_class(), scale,
|
||||
rsx::texture_dimension_extended::texture_dimension_cubemap, decoded_remap };
|
||||
}
|
||||
|
||||
@ -659,7 +644,7 @@ namespace rsx
|
||||
// If this method was called, there is no easy solution, likely means atlas gather is needed
|
||||
auto scaled_w = rsx::apply_resolution_scale(attr2.width, true);
|
||||
auto scaled_h = rsx::apply_resolution_scale(attr2.height, true);
|
||||
const auto format_class = get_format_class(attr2.gcm_format);
|
||||
const auto format_class = classify_format(attr2.gcm_format);
|
||||
|
||||
if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap)
|
||||
{
|
||||
|
@ -1673,21 +1673,9 @@ namespace rsx
|
||||
return sync_timestamp;
|
||||
}
|
||||
|
||||
format_type get_format_type() const
|
||||
rsx::format_class get_format_class() const
|
||||
{
|
||||
switch (gcm_format)
|
||||
{
|
||||
default:
|
||||
return format_type::color;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
return format_type::depth_uint;
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return format_type::depth_float;
|
||||
case 0:
|
||||
fmt::throw_exception("Unreachable" HERE);
|
||||
}
|
||||
return classify_format(gcm_format);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,6 +40,9 @@
|
||||
|
||||
inline static void _SelectTexture(int unit) { glActiveTexture(GL_TEXTURE0 + unit); }
|
||||
|
||||
//using enum rsx::format_class;
|
||||
using namespace ::rsx::format_class_;
|
||||
|
||||
namespace gl
|
||||
{
|
||||
//Function call wrapped in ARB_DSA vs EXT_DSA compat check
|
||||
@ -1516,18 +1519,6 @@ namespace gl
|
||||
ref_to_texture = GL_COMPARE_REF_TO_TEXTURE
|
||||
};
|
||||
|
||||
enum class compare_func
|
||||
{
|
||||
never = GL_NEVER,
|
||||
less = GL_LESS,
|
||||
equal = GL_EQUAL,
|
||||
lequal = GL_LEQUAL,
|
||||
greater = GL_GREATER,
|
||||
notequal = GL_NOTEQUAL,
|
||||
gequal = GL_GEQUAL,
|
||||
always = GL_ALWAYS
|
||||
};
|
||||
|
||||
enum class target
|
||||
{
|
||||
texture1D = GL_TEXTURE_1D,
|
||||
@ -1537,25 +1528,6 @@ namespace gl
|
||||
textureBuffer = GL_TEXTURE_BUFFER
|
||||
};
|
||||
|
||||
enum class channel_type
|
||||
{
|
||||
none = GL_NONE,
|
||||
signed_normalized = GL_SIGNED_NORMALIZED,
|
||||
unsigned_normalized = GL_UNSIGNED_NORMALIZED,
|
||||
float_ = GL_FLOAT,
|
||||
int_ = GL_INT,
|
||||
uint_ = GL_UNSIGNED_INT
|
||||
};
|
||||
|
||||
enum class channel_name
|
||||
{
|
||||
red = GL_TEXTURE_RED_TYPE,
|
||||
green = GL_TEXTURE_GREEN_TYPE,
|
||||
blue = GL_TEXTURE_BLUE_TYPE,
|
||||
alpha = GL_TEXTURE_ALPHA_TYPE,
|
||||
depth = GL_TEXTURE_DEPTH_TYPE
|
||||
};
|
||||
|
||||
protected:
|
||||
GLuint m_id = GL_NONE;
|
||||
GLuint m_width = 0;
|
||||
@ -1570,6 +1542,8 @@ namespace gl
|
||||
internal_format m_internal_format = internal_format::rgba8;
|
||||
std::array<GLenum, 4> m_component_layout;
|
||||
|
||||
rsx::format_class m_format_class = RSX_FORMAT_CLASS_UNDEFINED;
|
||||
|
||||
private:
|
||||
class save_binding_state
|
||||
{
|
||||
@ -1612,7 +1586,8 @@ namespace gl
|
||||
texture(const texture&) = delete;
|
||||
texture(texture&& texture_) = delete;
|
||||
|
||||
texture(GLenum target, GLuint width, GLuint height, GLuint depth, GLuint mipmaps, GLenum sized_format)
|
||||
texture(GLenum target, GLuint width, GLuint height, GLuint depth, GLuint mipmaps, GLenum sized_format,
|
||||
rsx::format_class format_class = rsx::RSX_FORMAT_CLASS_UNDEFINED)
|
||||
{
|
||||
save_binding_state save(target);
|
||||
glGenTextures(1, &m_id);
|
||||
@ -1705,9 +1680,22 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
if (format_class == RSX_FORMAT_CLASS_UNDEFINED)
|
||||
{
|
||||
if (m_aspect_flags != image_aspect::color)
|
||||
{
|
||||
rsx_log.error("Undefined format class for depth texture is not allowed");
|
||||
}
|
||||
else
|
||||
{
|
||||
format_class = RSX_FORMAT_CLASS_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
m_target = static_cast<texture::target>(target);
|
||||
m_internal_format = static_cast<internal_format>(sized_format);
|
||||
m_component_layout = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
|
||||
m_format_class = format_class;
|
||||
}
|
||||
|
||||
virtual ~texture()
|
||||
@ -1791,6 +1779,11 @@ namespace gl
|
||||
return m_aspect_flags;
|
||||
}
|
||||
|
||||
rsx::format_class format_class() const
|
||||
{
|
||||
return m_format_class;
|
||||
}
|
||||
|
||||
sizeu size2D() const
|
||||
{
|
||||
return{ m_width, m_height };
|
||||
|
@ -10,7 +10,7 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons
|
||||
|
||||
// Check the surface store first
|
||||
gl::command_context cmd = { gl_state };
|
||||
const auto format_bpp = get_format_block_size_in_bytes(info->format);
|
||||
const auto format_bpp = rsx::get_format_block_size_in_bytes(info->format);
|
||||
const auto overlap_info = m_rtts.get_merged_texture_memory_region(cmd,
|
||||
info->address, info->width, info->height, info->pitch, format_bpp, rsx::surface_access::read);
|
||||
|
||||
|
@ -458,7 +458,7 @@ void gl::render_target::load_memory(gl::command_context& cmd)
|
||||
get_compatible_gcm_format(format_info.gcm_depth_format).first :
|
||||
get_compatible_gcm_format(format_info.gcm_color_format).first;
|
||||
|
||||
rsx_subresource_layout subres{};
|
||||
rsx::subresource_layout subres{};
|
||||
subres.width_in_block = subres.width_in_texel = surface_width * samples_x;
|
||||
subres.height_in_block = subres.height_in_texel = surface_height * samples_y;
|
||||
subres.pitch_in_block = rsx_pitch / get_bpp();
|
||||
|
@ -480,9 +480,9 @@ namespace gl
|
||||
}
|
||||
|
||||
void fill_texture(rsx::texture_dimension_extended dim, u16 mipmap_count, int format, u16 width, u16 height, u16 depth,
|
||||
const std::vector<rsx_subresource_layout> &input_layouts, bool is_swizzled, GLenum gl_format, GLenum gl_type, std::vector<std::byte>& staging_buffer)
|
||||
const std::vector<rsx::subresource_layout> &input_layouts, bool is_swizzled, GLenum gl_format, GLenum gl_type, std::vector<std::byte>& staging_buffer)
|
||||
{
|
||||
texture_uploader_capabilities caps{ true, false, false, 4 };
|
||||
rsx::texture_uploader_capabilities caps{ true, false, false, 4 };
|
||||
|
||||
pixel_unpack_settings unpack_settings;
|
||||
unpack_settings.row_length(0).alignment(4);
|
||||
@ -496,7 +496,7 @@ namespace gl
|
||||
|
||||
const GLsizei format_block_size = (format == CELL_GCM_TEXTURE_COMPRESSED_DXT1) ? 8 : 16;
|
||||
|
||||
for (const rsx_subresource_layout& layout : input_layouts)
|
||||
for (const rsx::subresource_layout& layout : input_layouts)
|
||||
{
|
||||
upload_texture_subresource(staging_buffer, layout, format, is_swizzled, caps);
|
||||
const sizei image_size{ align(layout.width_in_texel, 4), align(layout.height_in_texel, 4) };
|
||||
@ -561,7 +561,7 @@ namespace gl
|
||||
unpack_settings.apply();
|
||||
}
|
||||
|
||||
for (const rsx_subresource_layout& layout : input_layouts)
|
||||
for (const rsx::subresource_layout& layout : input_layouts)
|
||||
{
|
||||
auto op = upload_texture_subresource(staging_buffer, layout, format, is_swizzled, caps);
|
||||
if (apply_settings)
|
||||
@ -627,7 +627,7 @@ namespace gl
|
||||
}
|
||||
|
||||
void upload_texture(GLuint id, 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::vector<rsx::subresource_layout>& subresources_layout)
|
||||
{
|
||||
GLenum target;
|
||||
switch (type)
|
||||
@ -652,7 +652,7 @@ namespace gl
|
||||
// The rest of sampler state is now handled by sampler state objects
|
||||
|
||||
// Calculate staging buffer size
|
||||
const u32 aligned_pitch = align<u32>(width * get_format_block_size_in_bytes(gcm_format), 4);
|
||||
const u32 aligned_pitch = align<u32>(width * rsx::get_format_block_size_in_bytes(gcm_format), 4);
|
||||
size_t texture_data_sz = depth * height * aligned_pitch;
|
||||
std::vector<std::byte> data_upload_buf(texture_data_sz);
|
||||
|
||||
|
@ -44,7 +44,7 @@ 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 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::vector<rsx::subresource_layout>& subresources_layout);
|
||||
|
||||
class sampler_state
|
||||
{
|
||||
|
@ -895,7 +895,7 @@ namespace gl
|
||||
}
|
||||
|
||||
cached_texture_section* upload_image_from_cpu(gl::command_context &cmd, const utils::address_range& rsx_range, 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 input_swizzled) override
|
||||
rsx::texture_upload_context context, const std::vector<rsx::subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, bool input_swizzled) override
|
||||
{
|
||||
auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, pitch, gcm_format, context, type, input_swizzled,
|
||||
rsx::texture_create_flags::default_component_order);
|
||||
|
@ -1830,7 +1830,7 @@ namespace rsx
|
||||
if (raw_format & CELL_GCM_TEXTURE_UN)
|
||||
result.unnormalized_coords |= (1 << i);
|
||||
|
||||
if (sampler_descriptors[i]->format_class != format_type::color)
|
||||
if (sampler_descriptors[i]->format_class != RSX_FORMAT_CLASS_COLOR)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
@ -1844,7 +1844,7 @@ namespace rsx
|
||||
{
|
||||
// Reading depth data as XRGB8 is supported with in-shader conversion
|
||||
// TODO: Optionally add support for 16-bit formats (not necessary since type casts are easy with that)
|
||||
u32 control_bits = sampler_descriptors[i]->format_class == format_type::depth_float? (1u << 16) : 0u;
|
||||
u32 control_bits = sampler_descriptors[i]->format_class == RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32? (1u << 16) : 0u;
|
||||
control_bits |= tex.remap() & 0xFFFF;
|
||||
result.redirected_textures |= (1 << i);
|
||||
result.texture_scale[i][2] = std::bit_cast<f32>(control_bits);
|
||||
|
@ -198,7 +198,7 @@ void VKGSRender::load_texture_env()
|
||||
|
||||
// Check if non-point filtering can even be used on this format
|
||||
bool can_sample_linear;
|
||||
if (sampler_state->format_class == rsx::format_type::color) [[likely]]
|
||||
if (sampler_state->format_class == RSX_FORMAT_CLASS_COLOR) [[likely]]
|
||||
{
|
||||
// Most PS3-like formats can be linearly filtered without problem
|
||||
can_sample_linear = true;
|
||||
|
@ -487,4 +487,16 @@ namespace vk
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool formats_are_bitcast_compatible(image* image1, image* image2)
|
||||
{
|
||||
if (const u32 transfer_class = image1->format_class() | image2->format_class();
|
||||
transfer_class & RSX_FORMAT_CLASS_DEPTH_FLOAT_MASK)
|
||||
{
|
||||
// If any one of the two images is a depth float, the other must match exactly or bust
|
||||
return (image1->format_class() == image2->format_class());
|
||||
}
|
||||
|
||||
return formats_are_bitcast_compatible(image1->format(), image2->format());
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ namespace vk
|
||||
std::pair<u8, u8> get_format_element_size(VkFormat format);
|
||||
std::pair<bool, u32> get_format_convert_flags(VkFormat format);
|
||||
bool formats_are_bitcast_compatible(VkFormat format1, VkFormat format2);
|
||||
bool formats_are_bitcast_compatible(image* image1, image* image2);
|
||||
|
||||
minification_filter get_min_filter(rsx::texture_minify_filter min_filter);
|
||||
VkFilter get_mag_filter(rsx::texture_magnify_filter mag_filter);
|
||||
|
@ -344,7 +344,7 @@ namespace vk
|
||||
return tex->get_view(VK_REMAP_IDENTITY, rsx::default_remap_vector);
|
||||
}
|
||||
|
||||
vk::image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height)
|
||||
vk::image* get_typeless_helper(VkFormat format, rsx::format_class format_class, u32 requested_width, u32 requested_height)
|
||||
{
|
||||
auto create_texture = [&]()
|
||||
{
|
||||
@ -356,7 +356,9 @@ namespace vk
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0);
|
||||
};
|
||||
|
||||
auto& ptr = g_typeless_textures[+format];
|
||||
const u32 key = (format_class << 24u) | format;
|
||||
auto& ptr = g_typeless_textures[key];
|
||||
|
||||
if (!ptr || ptr->width() < requested_width || ptr->height() < requested_height)
|
||||
{
|
||||
if (ptr)
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define FRAME_PRESENT_TIMEOUT 10000000ull // 10 seconds
|
||||
#define GENERAL_WAIT_TIMEOUT 2000000ull // 2 seconds
|
||||
|
||||
//using enum rsx::format_class;
|
||||
using namespace ::rsx::format_class_;
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
class fragment_texture;
|
||||
@ -145,7 +148,7 @@ namespace vk
|
||||
|
||||
VkSampler null_sampler();
|
||||
image_view* null_image_view(vk::command_buffer&, VkImageViewType type);
|
||||
image* get_typeless_helper(VkFormat format, u32 requested_width, u32 requested_height);
|
||||
image* get_typeless_helper(VkFormat format, rsx::format_class format_class, u32 requested_width, u32 requested_height);
|
||||
buffer* get_scratch_buffer(u32 min_required_size = 0);
|
||||
data_heap* get_upload_heap();
|
||||
|
||||
@ -180,7 +183,7 @@ namespace vk
|
||||
* dst_image must be in TRANSFER_DST_OPTIMAL layout and upload_buffer have TRANSFER_SRC_BIT usage flag.
|
||||
*/
|
||||
void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, vk::image* dst_image,
|
||||
const std::vector<rsx_subresource_layout>& subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
|
||||
const std::vector<rsx::subresource_layout>& subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
|
||||
VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align = 0);
|
||||
|
||||
//Other texture management helpers
|
||||
@ -192,16 +195,15 @@ namespace vk
|
||||
void copy_buffer_to_image(VkCommandBuffer cmd, const vk::buffer* src, const vk::image* dst, const VkBufferImageCopy& region);
|
||||
|
||||
void copy_image_typeless(const command_buffer &cmd, image *src, image *dst, const areai& src_rect, const areai& dst_rect,
|
||||
u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF);
|
||||
u32 mipmaps, VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF);
|
||||
|
||||
void copy_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
void copy_image(const vk::command_buffer& cmd, vk::image* src, vk::image* dst,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps,
|
||||
VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF);
|
||||
|
||||
void copy_scaled_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags aspect, bool compatible_formats,
|
||||
VkFilter filter = VK_FILTER_LINEAR, VkFormat src_format = VK_FORMAT_UNDEFINED, VkFormat dst_format = VK_FORMAT_UNDEFINED);
|
||||
void copy_scaled_image(const vk::command_buffer& cmd, vk::image* src, vk::image* dst,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps,
|
||||
bool compatible_formats, VkFilter filter = VK_FILTER_LINEAR);
|
||||
|
||||
std::pair<VkFormat, VkComponentMapping> get_compatible_surface_format(rsx::surface_color_format color_format);
|
||||
|
||||
@ -1385,6 +1387,7 @@ private:
|
||||
std::stack<VkImageLayout> m_layout_stack;
|
||||
VkImageAspectFlags m_storage_aspect = 0;
|
||||
|
||||
rsx::format_class m_format_class = RSX_FORMAT_CLASS_UNDEFINED;
|
||||
public:
|
||||
VkImage value = VK_NULL_HANDLE;
|
||||
VkComponentMapping native_component_map = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
|
||||
@ -1403,7 +1406,8 @@ private:
|
||||
VkImageLayout initial_layout,
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags image_flags)
|
||||
VkImageCreateFlags image_flags,
|
||||
rsx::format_class format_class = RSX_FORMAT_CLASS_UNDEFINED)
|
||||
: current_layout(initial_layout)
|
||||
, m_device(dev)
|
||||
{
|
||||
@ -1437,6 +1441,20 @@ private:
|
||||
CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()));
|
||||
|
||||
m_storage_aspect = get_aspect_flags(format);
|
||||
|
||||
if (format_class == RSX_FORMAT_CLASS_UNDEFINED)
|
||||
{
|
||||
if (m_storage_aspect != VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
{
|
||||
rsx_log.error("Depth/stencil textures must have format class explicitly declared");
|
||||
}
|
||||
else
|
||||
{
|
||||
format_class = RSX_FORMAT_CLASS_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
m_format_class = format_class;
|
||||
}
|
||||
|
||||
// TODO: Ctor that uses a provided memory heap
|
||||
@ -1489,6 +1507,11 @@ private:
|
||||
return m_storage_aspect;
|
||||
}
|
||||
|
||||
rsx::format_class format_class() const
|
||||
{
|
||||
return m_format_class;
|
||||
}
|
||||
|
||||
void push_layout(VkCommandBuffer cmd, VkImageLayout layout)
|
||||
{
|
||||
m_layout_stack.push(current_layout);
|
||||
|
@ -275,7 +275,7 @@ vk::image* VKGSRender::get_present_source(vk::present_surface_info* info, const
|
||||
vk::image* image_to_flip = nullptr;
|
||||
|
||||
// Check the surface store first
|
||||
const auto format_bpp = get_format_block_size_in_bytes(info->format);
|
||||
const auto format_bpp = rsx::get_format_block_size_in_bytes(info->format);
|
||||
const auto overlap_info = m_rtts.get_merged_texture_memory_region(*m_current_command_buffer,
|
||||
info->address, info->width, info->height, info->pitch, format_bpp, rsx::surface_access::read);
|
||||
|
||||
@ -601,8 +601,26 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
|
||||
if (calibration_src.empty()) [[likely]]
|
||||
{
|
||||
vk::copy_scaled_image(*m_current_command_buffer, image_to_flip->value, target_image, image_to_flip->current_layout, target_layout,
|
||||
{ 0, 0, static_cast<s32>(buffer_width), static_cast<s32>(buffer_height) }, aspect_ratio, 1, VK_IMAGE_ASPECT_COLOR_BIT, false);
|
||||
// Do raw transfer here as there is no image object associated with textures owned by the driver (TODO)
|
||||
const areai dst_rect = aspect_ratio;
|
||||
VkImageBlit rgn = {};
|
||||
|
||||
rgn.srcSubresource = { image_to_flip->aspect(), 0, 0, 1 };
|
||||
rgn.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
rgn.srcOffsets[0] = { 0, 0, 0 };
|
||||
rgn.srcOffsets[1] = { s32(buffer_width), s32(buffer_height), 1 };
|
||||
rgn.dstOffsets[0] = { dst_rect.x1, dst_rect.y1, 0 };
|
||||
rgn.dstOffsets[1] = { dst_rect.x2, dst_rect.y2, 1 };
|
||||
|
||||
image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
if (target_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||
{
|
||||
vk::change_image_layout(*m_current_command_buffer, target_image, target_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
|
||||
target_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
}
|
||||
|
||||
vkCmdBlitImage(*m_current_command_buffer, image_to_flip->value, image_to_flip->current_layout, target_image, target_layout, 1, &rgn, VK_FILTER_LINEAR);
|
||||
image_to_flip->pop_layout(*m_current_command_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -243,7 +243,7 @@ namespace vk
|
||||
gcm_format = get_compatible_gcm_format(format_info.gcm_color_format).first;
|
||||
}
|
||||
|
||||
rsx_subresource_layout subres{};
|
||||
rsx::subresource_layout subres{};
|
||||
subres.width_in_block = subres.width_in_texel = surface_width * samples_x;
|
||||
subres.height_in_block = subres.height_in_texel = surface_height * samples_y;
|
||||
subres.pitch_in_block = rsx_pitch / get_bpp();
|
||||
@ -273,7 +273,7 @@ namespace vk
|
||||
}
|
||||
else
|
||||
{
|
||||
content = vk::get_typeless_helper(format(), subres.width_in_block, subres.height_in_block);
|
||||
content = vk::get_typeless_helper(format(), rsx::classify_format(gcm_format), subres.width_in_block, subres.height_in_block);
|
||||
content->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
}
|
||||
|
||||
@ -286,10 +286,10 @@ namespace vk
|
||||
// Avoid layout push/pop on scratch memory by setting explicit layout here
|
||||
content->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
vk::copy_scaled_image(cmd, content->value, final_dst->value, content->current_layout, final_dst->current_layout,
|
||||
{ 0, 0, subres.width_in_block, subres.height_in_block }, { 0, 0, static_cast<s32>(final_dst->width()), static_cast<s32>(final_dst->height()) },
|
||||
1, aspect(), true, aspect() == VK_IMAGE_ASPECT_COLOR_BIT ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
|
||||
format(), format());
|
||||
vk::copy_scaled_image(cmd, content, final_dst,
|
||||
{ 0, 0, subres.width_in_block, subres.height_in_block },
|
||||
{ 0, 0, static_cast<s32>(final_dst->width()), static_cast<s32>(final_dst->height()) },
|
||||
1, true, aspect() == VK_IMAGE_ASPECT_COLOR_BIT ? VK_FILTER_LINEAR : VK_FILTER_NEAREST);
|
||||
}
|
||||
|
||||
final_dst->pop_layout(cmd);
|
||||
@ -670,7 +670,7 @@ namespace rsx
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0);
|
||||
0, RSX_FORMAT_CLASS_COLOR);
|
||||
|
||||
rtt->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
@ -728,7 +728,7 @@ namespace rsx
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
usage_flags,
|
||||
0);
|
||||
0, rsx::classify_format(format));
|
||||
|
||||
ds->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
|
@ -118,8 +118,7 @@ namespace vk
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_gather_d24x8<false>>();
|
||||
}
|
||||
else if (auto dsv = dynamic_cast<const vk::render_target*>(src);
|
||||
dsv && dsv->get_format_type() == rsx::format_type::depth_float)
|
||||
else if (src->format_class() == RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32)
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_gather_d32x8<false, true>>();
|
||||
}
|
||||
@ -134,8 +133,7 @@ namespace vk
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_gather_d24x8<true>>();
|
||||
}
|
||||
else if (auto dsv = dynamic_cast<const vk::render_target*>(src);
|
||||
dsv && dsv->get_format_type() == rsx::format_type::depth_float)
|
||||
else if (src->format_class() == RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32)
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_gather_d32x8<true, true>>();
|
||||
}
|
||||
@ -211,8 +209,7 @@ namespace vk
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_scatter_d24x8>();
|
||||
}
|
||||
else if (auto dsv = dynamic_cast<const vk::render_target*>(dst);
|
||||
dsv && dsv->get_format_type() == rsx::format_type::depth_float)
|
||||
else if (dst->format_class() == RSX_FORMAT_CLASS_DEPTH24_FLOAT_X8_PACK32)
|
||||
{
|
||||
job = vk::get_compute_task<vk::cs_scatter_d32x8<true>>();
|
||||
}
|
||||
@ -241,11 +238,11 @@ namespace vk
|
||||
}
|
||||
|
||||
void copy_image_typeless(const vk::command_buffer& cmd, vk::image* src, vk::image* dst, const areai& src_rect, const areai& dst_rect,
|
||||
u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect, VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
u32 mipmaps, VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
{
|
||||
if (src->info.format == dst->info.format)
|
||||
{
|
||||
copy_image(cmd, src->value, dst->value, src->current_layout, dst->current_layout, src_rect, dst_rect, mipmaps, src_aspect, dst_aspect, src_transfer_mask, dst_transfer_mask);
|
||||
copy_image(cmd, src, dst, src_rect, dst_rect, mipmaps, src_transfer_mask, dst_transfer_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -267,11 +264,11 @@ namespace vk
|
||||
VkBufferImageCopy src_copy{}, dst_copy{};
|
||||
src_copy.imageExtent = { u32(src_rect.x2 - src_rect.x1), u32(src_rect.y2 - src_rect.y1), 1 };
|
||||
src_copy.imageOffset = { src_rect.x1, src_rect.y1, 0 };
|
||||
src_copy.imageSubresource = { src_aspect & src_transfer_mask, 0, 0, 1 };
|
||||
src_copy.imageSubresource = { src->aspect() & src_transfer_mask, 0, 0, 1 };
|
||||
|
||||
dst_copy.imageExtent = { u32(dst_rect.x2 - dst_rect.x1), u32(dst_rect.y2 - dst_rect.y1), 1 };
|
||||
dst_copy.imageOffset = { dst_rect.x1, dst_rect.y1, 0 };
|
||||
dst_copy.imageSubresource = { dst_aspect & dst_transfer_mask, 0, 0, 1 };
|
||||
dst_copy.imageSubresource = { dst->aspect() & dst_transfer_mask, 0, 0, 1 };
|
||||
|
||||
const auto src_texel_size = vk::get_format_texel_width(src->info.format);
|
||||
const auto src_length = src_texel_size * src_copy.imageExtent.width * src_copy.imageExtent.height;
|
||||
@ -346,21 +343,28 @@ namespace vk
|
||||
if (src != dst) dst->pop_layout(cmd);
|
||||
}
|
||||
|
||||
void copy_image(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_aspect, VkImageAspectFlags dst_aspect,
|
||||
void copy_image(const vk::command_buffer& cmd, vk::image* src, vk::image* dst,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps,
|
||||
VkImageAspectFlags src_transfer_mask, VkImageAspectFlags dst_transfer_mask)
|
||||
{
|
||||
// NOTE: src_aspect should match dst_aspect according to spec but drivers seem to work just fine with the mismatch
|
||||
// TODO: Implement separate pixel transfer for drivers that refuse this workaround
|
||||
if ((src->aspect() & VK_IMAGE_ASPECT_DEPTH_BIT) != 0 &&
|
||||
src->format() != dst->format())
|
||||
{
|
||||
// Copying between depth formats must match
|
||||
copy_image_typeless(cmd, src, dst, src_rect, dst_rect, mipmaps);
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageSubresourceLayers a_src = {}, a_dst = {};
|
||||
a_src.aspectMask = src_aspect & src_transfer_mask;
|
||||
a_src.aspectMask = src->aspect() & src_transfer_mask;
|
||||
a_src.baseArrayLayer = 0;
|
||||
a_src.layerCount = 1;
|
||||
a_src.mipLevel = 0;
|
||||
|
||||
a_dst = a_src;
|
||||
a_dst.aspectMask = dst_aspect & dst_transfer_mask;
|
||||
a_dst.aspectMask = dst->aspect() & dst_transfer_mask;
|
||||
|
||||
VkImageCopy rgn = {};
|
||||
rgn.extent.depth = 1;
|
||||
@ -371,64 +375,61 @@ namespace vk
|
||||
rgn.srcSubresource = a_src;
|
||||
rgn.dstSubresource = a_dst;
|
||||
|
||||
auto preferred_src_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
auto preferred_dst_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
if (vk::is_renderpass_open(cmd))
|
||||
{
|
||||
vk::end_renderpass(cmd);
|
||||
}
|
||||
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, srcLayout, preferred_src_format, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format && src != dst)
|
||||
change_image_layout(cmd, dst, dstLayout, preferred_dst_format, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
if (src != dst)
|
||||
{
|
||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
dst->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
|
||||
for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level)
|
||||
{
|
||||
vkCmdCopyImage(cmd, src, preferred_src_format, dst, preferred_dst_format, 1, &rgn);
|
||||
vkCmdCopyImage(cmd, src->value, src->current_layout, dst->value, dst->current_layout, 1, &rgn);
|
||||
|
||||
rgn.srcSubresource.mipLevel++;
|
||||
rgn.dstSubresource.mipLevel++;
|
||||
}
|
||||
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, preferred_src_format, srcLayout, vk::get_image_subresource_range(0, 0, 1, 1, src_aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format && src != dst)
|
||||
change_image_layout(cmd, dst, preferred_dst_format, dstLayout, vk::get_image_subresource_range(0, 0, 1, 1, dst_aspect));
|
||||
src->pop_layout(cmd);
|
||||
if (src != dst) dst->pop_layout(cmd);
|
||||
}
|
||||
|
||||
void copy_scaled_image(VkCommandBuffer cmd,
|
||||
VkImage src, VkImage dst,
|
||||
VkImageLayout srcLayout, VkImageLayout dstLayout,
|
||||
const areai& src_rect, const areai& dst_rect,
|
||||
u32 mipmaps, VkImageAspectFlags aspect, bool compatible_formats,
|
||||
VkFilter filter, VkFormat src_format, VkFormat dst_format)
|
||||
void copy_scaled_image(const vk::command_buffer& cmd,
|
||||
vk::image* src, vk::image* dst,
|
||||
const areai& src_rect, const areai& dst_rect, u32 mipmaps,
|
||||
bool compatible_formats, VkFilter filter)
|
||||
{
|
||||
VkImageSubresourceLayers a_src = {}, a_dst = {};
|
||||
a_src.aspectMask = aspect;
|
||||
a_src.aspectMask = src->aspect();
|
||||
a_src.baseArrayLayer = 0;
|
||||
a_src.layerCount = 1;
|
||||
a_src.mipLevel = 0;
|
||||
|
||||
a_dst = a_src;
|
||||
|
||||
auto preferred_src_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
auto preferred_dst_format = (src == dst) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
if (vk::is_renderpass_open(cmd))
|
||||
{
|
||||
vk::end_renderpass(cmd);
|
||||
}
|
||||
|
||||
//TODO: Use an array of offsets/dimensions for mipmapped blits (mipmap count > 1) since subimages will have different dimensions
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, srcLayout, preferred_src_format, vk::get_image_subresource_range(0, 0, 1, 1, aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format && src != dst)
|
||||
change_image_layout(cmd, dst, dstLayout, preferred_dst_format, vk::get_image_subresource_range(0, 0, 1, 1, aspect));
|
||||
if (src != dst)
|
||||
{
|
||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
dst->push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
src->push_layout(cmd, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
|
||||
if (compatible_formats && !src_rect.is_flipped() && !dst_rect.is_flipped() &&
|
||||
src_rect.width() == dst_rect.width() && src_rect.height() == dst_rect.height())
|
||||
@ -436,24 +437,27 @@ namespace vk
|
||||
VkImageCopy copy_rgn;
|
||||
copy_rgn.srcOffset = { src_rect.x1, src_rect.y1, 0 };
|
||||
copy_rgn.dstOffset = { dst_rect.x1, dst_rect.y1, 0 };
|
||||
copy_rgn.dstSubresource = { static_cast<VkImageAspectFlags>(aspect), 0, 0, 1 };
|
||||
copy_rgn.srcSubresource = { static_cast<VkImageAspectFlags>(aspect), 0, 0, 1 };
|
||||
copy_rgn.dstSubresource = { dst->aspect(), 0, 0, 1 };
|
||||
copy_rgn.srcSubresource = { src->aspect(), 0, 0, 1 };
|
||||
copy_rgn.extent = { static_cast<u32>(src_rect.width()), static_cast<u32>(src_rect.height()), 1 };
|
||||
|
||||
vkCmdCopyImage(cmd, src, preferred_src_format, dst, preferred_dst_format, 1, ©_rgn);
|
||||
vkCmdCopyImage(cmd, src->value, src->current_layout, dst->value, dst->current_layout, 1, ©_rgn);
|
||||
}
|
||||
else if ((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
|
||||
else if ((src->aspect() & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0)
|
||||
{
|
||||
//Most depth/stencil formats cannot be scaled using hw blit
|
||||
if (src_format == VK_FORMAT_UNDEFINED)
|
||||
if (src->format() != dst->format())
|
||||
{
|
||||
rsx_log.error("Could not blit depth/stencil image. src_fmt=0x%x", static_cast<u32>(src_format));
|
||||
// Can happen because of depth float mismatch. Format width should be equal RSX-side
|
||||
auto typeless = vk::get_typeless_helper(dst->format(), dst->format_class(), src_rect.width(), src_rect.height());
|
||||
copy_image_typeless(cmd, src, typeless, src_rect, src_rect, mipmaps);
|
||||
copy_scaled_image(cmd, typeless, dst, src_rect, dst_rect, mipmaps, true, filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(HERE), !dst_rect.is_flipped();
|
||||
|
||||
auto stretch_image_typeless_unsafe = [&cmd, preferred_src_format, preferred_dst_format, filter](VkImage src, VkImage dst, VkImage typeless,
|
||||
auto stretch_image_typeless_unsafe = [&cmd, filter](vk::image* src, vk::image* dst, vk::image* typeless,
|
||||
const areai& src_rect, const areai& dst_rect, VkImageAspectFlags aspect, VkImageAspectFlags transfer_flags = 0xFF)
|
||||
{
|
||||
const auto src_w = src_rect.width();
|
||||
@ -466,19 +470,16 @@ namespace vk
|
||||
// NOTE: Tranfers of single aspect D/S from Nvidia's D24S8 is very slow
|
||||
|
||||
//1. Copy unscaled to typeless surface
|
||||
copy_image(cmd, src, typeless, preferred_src_format, VK_IMAGE_LAYOUT_GENERAL,
|
||||
src_rect, { 0, 0, src_w, src_h }, 1, aspect, VK_IMAGE_ASPECT_COLOR_BIT, transfer_flags, 0xFF);
|
||||
copy_image(cmd, src, typeless, src_rect, { 0, 0, src_w, src_h }, 1, transfer_flags, 0xFF);
|
||||
|
||||
//2. Blit typeless surface to self
|
||||
copy_scaled_image(cmd, typeless, typeless, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
{ 0, 0, src_w, src_h }, { 0, src_h, dst_w, (src_h + dst_h) }, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT, filter);
|
||||
copy_scaled_image(cmd, typeless, typeless, { 0, 0, src_w, src_h }, { 0, src_h, dst_w, (src_h + dst_h) }, 1, true, filter);
|
||||
|
||||
//3. Copy back the aspect bits
|
||||
copy_image(cmd, typeless, dst, VK_IMAGE_LAYOUT_GENERAL, preferred_dst_format,
|
||||
{0, src_h, dst_w, (src_h + dst_h) }, dst_rect, 1, VK_IMAGE_ASPECT_COLOR_BIT, aspect, 0xFF, transfer_flags);
|
||||
copy_image(cmd, typeless, dst, {0, src_h, dst_w, (src_h + dst_h) }, dst_rect, 1, 0xFF, transfer_flags);
|
||||
};
|
||||
|
||||
auto stretch_image_typeless_safe = [&cmd, preferred_src_format, preferred_dst_format, filter](VkImage src, VkImage dst, VkImage typeless,
|
||||
auto stretch_image_typeless_safe = [&cmd, filter](vk::image* src, vk::image* dst, vk::image* typeless,
|
||||
const areai& src_rect, const areai& dst_rect, VkImageAspectFlags aspect, VkImageAspectFlags transfer_flags = 0xFF)
|
||||
{
|
||||
const auto src_w = src_rect.width();
|
||||
@ -494,27 +495,26 @@ namespace vk
|
||||
info.imageExtent = { static_cast<u32>(src_w), static_cast<u32>(src_h), 1 };
|
||||
info.imageSubresource = { aspect & transfer_flags, 0, 0, 1 };
|
||||
|
||||
vkCmdCopyImageToBuffer(cmd, src, preferred_src_format, scratch_buf->value, 1, &info);
|
||||
vkCmdCopyImageToBuffer(cmd, src->value, src->current_layout, scratch_buf->value, 1, &info);
|
||||
insert_buffer_memory_barrier(cmd, scratch_buf->value, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
info.imageOffset = {};
|
||||
info.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, typeless, VK_IMAGE_LAYOUT_GENERAL, 1, &info);
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, typeless->value, VK_IMAGE_LAYOUT_GENERAL, 1, &info);
|
||||
|
||||
//2. Blit typeless surface to self and apply transform if necessary
|
||||
areai src_rect2 = { 0, 0, src_w, src_h };
|
||||
if (src_rect.x1 > src_rect.x2) src_rect2.flip_horizontal();
|
||||
if (src_rect.y1 > src_rect.y2) src_rect2.flip_vertical();
|
||||
|
||||
insert_image_memory_barrier(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
insert_image_memory_barrier(cmd, typeless->value, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
|
||||
|
||||
copy_scaled_image(cmd, typeless, typeless, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
src_rect2, { 0, src_h, dst_w, (src_h + dst_h) }, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT, filter);
|
||||
copy_scaled_image(cmd, typeless, typeless, src_rect2, { 0, src_h, dst_w, (src_h + dst_h) }, 1, true, filter);
|
||||
|
||||
insert_image_memory_barrier(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
insert_image_memory_barrier(cmd, typeless->value, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
|
||||
@ -523,31 +523,31 @@ namespace vk
|
||||
info.imageExtent = { static_cast<u32>(dst_w), static_cast<u32>(dst_h), 1 };
|
||||
info.imageOffset = { 0, src_h, 0 };
|
||||
|
||||
vkCmdCopyImageToBuffer(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL, scratch_buf->value, 1, &info);
|
||||
vkCmdCopyImageToBuffer(cmd, typeless->value, VK_IMAGE_LAYOUT_GENERAL, scratch_buf->value, 1, &info);
|
||||
insert_buffer_memory_barrier(cmd, scratch_buf->value, 0, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
info.imageOffset = { dst_rect.x1, dst_rect.y1, 0 };
|
||||
info.imageSubresource = { aspect & transfer_flags, 0, 0, 1 };
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, dst, preferred_dst_format, 1, &info);
|
||||
vkCmdCopyBufferToImage(cmd, scratch_buf->value, dst->value, dst->current_layout, 1, &info);
|
||||
};
|
||||
|
||||
const u32 typeless_w = std::max(dst_rect.width(), src_rect.width());
|
||||
const u32 typeless_h = src_rect.height() + dst_rect.height();
|
||||
|
||||
switch (src_format)
|
||||
switch (src->format())
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
{
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_R16_UNORM, typeless_w, typeless_h);
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_R16_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
change_image_layout(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless->value, src_rect, dst_rect, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless, src_rect, dst_rect, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
break;
|
||||
}
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
{
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_R32_SFLOAT, typeless_w, typeless_h);
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_R32_SFLOAT, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
change_image_layout(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless->value, src_rect, dst_rect, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless, src_rect, dst_rect, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
break;
|
||||
}
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
@ -556,19 +556,19 @@ namespace vk
|
||||
if (const auto chip_family = vk::get_chip_family();
|
||||
chip_family > vk::chip_class::NV_generic && chip_family < vk::chip_class::NV_turing)
|
||||
{
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, typeless_w, typeless_h);
|
||||
auto typeless = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
change_image_layout(cmd, typeless, VK_IMAGE_LAYOUT_GENERAL);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless->value, src_rect, dst_rect, depth_stencil);
|
||||
stretch_image_typeless_unsafe(src, dst, typeless, src_rect, dst_rect, depth_stencil);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto typeless_depth = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, typeless_w, typeless_h);
|
||||
auto typeless_stencil = vk::get_typeless_helper(VK_FORMAT_R8_UNORM, typeless_w, typeless_h);
|
||||
auto typeless_depth = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
auto typeless_stencil = vk::get_typeless_helper(VK_FORMAT_R8_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
change_image_layout(cmd, typeless_depth, VK_IMAGE_LAYOUT_GENERAL);
|
||||
change_image_layout(cmd, typeless_stencil, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
stretch_image_typeless_safe(src, dst, typeless_depth->value, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_stencil->value, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_depth, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_stencil, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -581,14 +581,14 @@ namespace vk
|
||||
// NOTE: While it may seem intuitive to use R32_SFLOAT as the carrier for the depth aspect, this does not work properly
|
||||
// Floating point interpolation is non-linear from a bit-by-bit perspective and generates undesirable effects
|
||||
|
||||
auto typeless_depth = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, typeless_w, typeless_h);
|
||||
auto typeless_stencil = vk::get_typeless_helper(VK_FORMAT_R8_UNORM, typeless_w, typeless_h);
|
||||
auto typeless_depth = vk::get_typeless_helper(VK_FORMAT_B8G8R8A8_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
auto typeless_stencil = vk::get_typeless_helper(VK_FORMAT_R8_UNORM, RSX_FORMAT_CLASS_COLOR, typeless_w, typeless_h);
|
||||
change_image_layout(cmd, typeless_depth, VK_IMAGE_LAYOUT_GENERAL);
|
||||
change_image_layout(cmd, typeless_stencil, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
const VkImageAspectFlags depth_stencil = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
stretch_image_typeless_safe(src, dst, typeless_depth->value, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_stencil->value, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_depth, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
stretch_image_typeless_safe(src, dst, typeless_stencil, src_rect, dst_rect, depth_stencil, VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -609,18 +609,15 @@ namespace vk
|
||||
|
||||
for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level)
|
||||
{
|
||||
vkCmdBlitImage(cmd, src, preferred_src_format, dst, preferred_dst_format, 1, &rgn, filter);
|
||||
vkCmdBlitImage(cmd, src->value, src->current_layout, dst->value, dst->current_layout, 1, &rgn, filter);
|
||||
|
||||
rgn.srcSubresource.mipLevel++;
|
||||
rgn.dstSubresource.mipLevel++;
|
||||
}
|
||||
}
|
||||
|
||||
if (srcLayout != preferred_src_format)
|
||||
change_image_layout(cmd, src, preferred_src_format, srcLayout, vk::get_image_subresource_range(0, 0, 1, 1, aspect));
|
||||
|
||||
if (dstLayout != preferred_dst_format && src != dst)
|
||||
change_image_layout(cmd, dst, preferred_dst_format, dstLayout, vk::get_image_subresource_range(0, 0, 1, 1, aspect));
|
||||
src->pop_layout(cmd);
|
||||
if (src != dst) dst->pop_layout(cmd);
|
||||
}
|
||||
|
||||
void gpu_deswizzle_sections_impl(VkCommandBuffer cmd, vk::buffer* scratch_buf, u32 dst_offset, int word_size, int word_count, bool swap_bytes, std::vector<VkBufferImageCopy>& sections)
|
||||
@ -756,14 +753,14 @@ namespace vk
|
||||
}
|
||||
|
||||
void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, vk::image* dst_image,
|
||||
const std::vector<rsx_subresource_layout>& subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
|
||||
const std::vector<rsx::subresource_layout>& subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
|
||||
VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align)
|
||||
{
|
||||
u32 block_in_pixel = get_format_block_size_in_texel(format);
|
||||
u8 block_size_in_bytes = get_format_block_size_in_bytes(format);
|
||||
u32 block_in_pixel = rsx::get_format_block_size_in_texel(format);
|
||||
u8 block_size_in_bytes = rsx::get_format_block_size_in_bytes(format);
|
||||
|
||||
texture_uploader_capabilities caps{ true, false, true, heap_align };
|
||||
texture_memory_info opt{};
|
||||
rsx::texture_uploader_capabilities caps{ true, false, true, heap_align };
|
||||
rsx::texture_memory_info opt{};
|
||||
bool check_caps = true;
|
||||
|
||||
vk::buffer* scratch_buf = nullptr;
|
||||
@ -779,7 +776,7 @@ namespace vk
|
||||
vk::end_renderpass(cmd);
|
||||
}
|
||||
|
||||
for (const rsx_subresource_layout &layout : subresource_layout)
|
||||
for (const rsx::subresource_layout &layout : subresource_layout)
|
||||
{
|
||||
if (!heap_align) [[likely]]
|
||||
{
|
||||
@ -959,12 +956,11 @@ namespace vk
|
||||
// Final dimensions are a match
|
||||
if (xfer_info.src_is_typeless || xfer_info.dst_is_typeless)
|
||||
{
|
||||
vk::copy_image_typeless(cmd, src, dst, src_area, dst_area, 1, src->aspect(), dst->aspect());
|
||||
vk::copy_image_typeless(cmd, src, dst, src_area, dst_area, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_image(cmd, src->value, dst->value, src->current_layout, dst->current_layout,
|
||||
src_area, dst_area, 1, src->aspect(), dst->aspect());
|
||||
copy_image(cmd, src, dst, src_area, dst_area, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -983,11 +979,10 @@ namespace vk
|
||||
const auto aspect = vk::get_aspect_flags(format);
|
||||
|
||||
// Transfer bits from src to typeless src
|
||||
real_src = vk::get_typeless_helper(format, static_cast<u32>(internal_width), src->height());
|
||||
real_src = vk::get_typeless_helper(format, rsx::classify_format(xfer_info.src_gcm_format), static_cast<u32>(internal_width), src->height());
|
||||
vk::change_image_layout(cmd, real_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 });
|
||||
|
||||
vk::copy_image_typeless(cmd, src, real_src, { 0, 0, static_cast<s32>(src->width()), static_cast<s32>(src->height()) }, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(src->height()) }, 1,
|
||||
vk::get_aspect_flags(src->info.format), aspect);
|
||||
vk::copy_image_typeless(cmd, src, real_src, { 0, 0, static_cast<s32>(src->width()), static_cast<s32>(src->height()) }, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(src->height()) }, 1);
|
||||
|
||||
src_area.x1 = static_cast<u16>(src_area.x1 * xfer_info.src_scaling_hint);
|
||||
src_area.x2 = static_cast<u16>(src_area.x2 * xfer_info.src_scaling_hint);
|
||||
@ -1006,11 +1001,10 @@ namespace vk
|
||||
const auto aspect = vk::get_aspect_flags(format);
|
||||
|
||||
// Transfer bits from dst to typeless dst
|
||||
real_dst = vk::get_typeless_helper(format, static_cast<u32>(internal_width), dst->height());
|
||||
real_dst = vk::get_typeless_helper(format, rsx::classify_format(xfer_info.dst_gcm_format), static_cast<u32>(internal_width), dst->height());
|
||||
vk::change_image_layout(cmd, real_dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 });
|
||||
|
||||
vk::copy_image_typeless(cmd, dst, real_dst, { 0, 0, static_cast<s32>(dst->width()), static_cast<s32>(dst->height()) }, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(dst->height()) }, 1,
|
||||
vk::get_aspect_flags(dst->info.format), aspect);
|
||||
vk::copy_image_typeless(cmd, dst, real_dst, { 0, 0, static_cast<s32>(dst->width()), static_cast<s32>(dst->height()) }, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(dst->height()) }, 1);
|
||||
|
||||
dst_area.x1 = static_cast<u16>(dst_area.x1 * xfer_info.dst_scaling_hint);
|
||||
dst_area.x2 = static_cast<u16>(dst_area.x2 * xfer_info.dst_scaling_hint);
|
||||
@ -1048,15 +1042,14 @@ namespace vk
|
||||
|
||||
verify("Incompatible source and destination format!" HERE), real_src->aspect() == real_dst->aspect();
|
||||
|
||||
copy_scaled_image(cmd, real_src->value, real_dst->value, real_src->current_layout, real_dst->current_layout,
|
||||
src_area, dst_area, 1, real_src->aspect(), real_src->info.format == real_dst->info.format,
|
||||
interpolate ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, real_src->info.format, real_dst->info.format);
|
||||
copy_scaled_image(cmd, real_src, real_dst, src_area, dst_area, 1,
|
||||
formats_are_bitcast_compatible(real_src, real_dst),
|
||||
interpolate ? VK_FILTER_LINEAR : VK_FILTER_NEAREST);
|
||||
|
||||
if (real_dst != dst)
|
||||
{
|
||||
auto internal_width = dst->width() * xfer_info.dst_scaling_hint;
|
||||
vk::copy_image_typeless(cmd, real_dst, dst, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(dst->height()) }, { 0, 0, static_cast<s32>(dst->width()), static_cast<s32>(dst->height()) }, 1,
|
||||
vk::get_aspect_flags(real_dst->info.format), vk::get_aspect_flags(dst->info.format));
|
||||
vk::copy_image_typeless(cmd, real_dst, dst, { 0, 0, static_cast<s32>(internal_width), static_cast<s32>(dst->height()) }, { 0, 0, static_cast<s32>(dst->width()), static_cast<s32>(dst->height()) }, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,15 +353,16 @@ namespace vk
|
||||
if (transfer_width != locked_resource->width() || transfer_height != locked_resource->height())
|
||||
{
|
||||
// TODO: Synchronize access to typeles textures
|
||||
target = vk::get_typeless_helper(vram_texture->info.format, transfer_width, transfer_height);
|
||||
target = vk::get_typeless_helper(vram_texture->format(), vram_texture->format_class(), transfer_width, transfer_height);
|
||||
target->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
// Allow bilinear filtering on color textures where compatibility is likely
|
||||
const auto filter = (target->aspect() == VK_IMAGE_ASPECT_COLOR_BIT) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
|
||||
vk::copy_scaled_image(cmd, locked_resource->value, target->value, locked_resource->current_layout, target->current_layout,
|
||||
{ 0, 0, static_cast<s32>(locked_resource->width()), static_cast<s32>(locked_resource->height()) }, { 0, 0, static_cast<s32>(transfer_width), static_cast<s32>(transfer_height) },
|
||||
1, target->aspect(), true, filter, vram_texture->format(), target->format());
|
||||
vk::copy_scaled_image(cmd, locked_resource, target,
|
||||
{ 0, 0, static_cast<s32>(locked_resource->width()), static_cast<s32>(locked_resource->height()) },
|
||||
{ 0, 0, static_cast<s32>(transfer_width), static_cast<s32>(transfer_height) },
|
||||
1, true, filter);
|
||||
|
||||
target->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
}
|
||||
@ -612,7 +613,7 @@ namespace vk
|
||||
continue;
|
||||
|
||||
const bool typeless = section.src->aspect() != dst_aspect ||
|
||||
!formats_are_bitcast_compatible(dst->format(), section.src->format());
|
||||
!formats_are_bitcast_compatible(dst, section.src);
|
||||
|
||||
// Avoid inserting unnecessary barrier GENERAL->TRANSFER_SRC->GENERAL in active render targets
|
||||
const auto preferred_layout = (section.src->current_layout != VK_IMAGE_LAYOUT_GENERAL) ?
|
||||
@ -656,18 +657,18 @@ namespace vk
|
||||
// TODO: Handle level and layer offsets
|
||||
const areai src_rect = coordi{{ src_x, src_y }, { src_w, src_h }};
|
||||
const areai dst_rect = coordi{{ section.dst_x, section.dst_y }, { section.dst_w, section.dst_h }};
|
||||
vk::copy_image_typeless(cmd, section.src, dst, src_rect, dst_rect, 1, section.src->aspect(), dst_aspect);
|
||||
vk::copy_image_typeless(cmd, section.src, dst, src_rect, dst_rect, 1);
|
||||
|
||||
section.src->pop_layout(cmd);
|
||||
continue;
|
||||
}
|
||||
|
||||
src_image = vk::get_typeless_helper(dst->info.format, convert_x + convert_w, src_y + src_h);
|
||||
src_image = vk::get_typeless_helper(dst->format(), dst->format_class(), convert_x + convert_w, src_y + src_h);
|
||||
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
const areai src_rect = coordi{{ src_x, src_y }, { src_w, src_h }};
|
||||
const areai dst_rect = coordi{{ convert_x, src_y }, { convert_w, src_h }};
|
||||
vk::copy_image_typeless(cmd, section.src, src_image, src_rect, dst_rect, 1, section.src->aspect(), dst_aspect);
|
||||
vk::copy_image_typeless(cmd, section.src, src_image, src_rect, dst_rect, 1);
|
||||
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
src_x = convert_x;
|
||||
@ -714,17 +715,17 @@ namespace vk
|
||||
else
|
||||
{
|
||||
// Either a bitcast is required or a scale+copy to mipmap level
|
||||
_dst = vk::get_typeless_helper(src_image->info.format, dst->width(), dst->height() * 2);
|
||||
_dst = vk::get_typeless_helper(src_image->format(), src_image->format_class(), dst->width(), dst->height() * 2);
|
||||
_dst->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
}
|
||||
|
||||
if (transform == rsx::surface_transform::identity)
|
||||
{
|
||||
vk::copy_scaled_image(cmd, src_image->value, _dst->value, section.src->current_layout, _dst->current_layout,
|
||||
vk::copy_scaled_image(cmd, src_image, _dst,
|
||||
coordi{ { src_x, src_y }, { src_w, src_h } },
|
||||
coordi{ { section.dst_x, section.dst_y }, { section.dst_w, section.dst_h } },
|
||||
1, src_image->aspect(), src_image->info.format == _dst->info.format,
|
||||
VK_FILTER_NEAREST, src_image->info.format, _dst->info.format);
|
||||
1, src_image->format() == _dst->format(),
|
||||
VK_FILTER_NEAREST);
|
||||
}
|
||||
else if (transform == rsx::surface_transform::argb_to_bgra)
|
||||
{
|
||||
@ -746,7 +747,7 @@ namespace vk
|
||||
vk::insert_buffer_memory_barrier(cmd, scratch_buf->value, 0, mem_length, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
auto tmp = vk::get_typeless_helper(src_image->info.format, section.dst_x + section.dst_w, section.dst_y + section.dst_h);
|
||||
auto tmp = vk::get_typeless_helper(src_image->format(), src_image->format_class(), section.dst_x + section.dst_w, section.dst_y + section.dst_h);
|
||||
tmp->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
copy.imageOffset = { 0, 0, 0 };
|
||||
@ -763,11 +764,11 @@ namespace vk
|
||||
dst_y = src_h;
|
||||
}
|
||||
|
||||
vk::copy_scaled_image(cmd, tmp->value, _dst->value, tmp->current_layout, _dst->current_layout,
|
||||
vk::copy_scaled_image(cmd, tmp, _dst,
|
||||
areai{ 0, 0, src_w, static_cast<s32>(src_h) },
|
||||
coordi{ { dst_x, dst_y }, { section.dst_w, section.dst_h } },
|
||||
1, new_src_aspect, tmp->info.format == _dst->info.format,
|
||||
VK_FILTER_NEAREST, tmp->info.format, _dst->info.format);
|
||||
1, tmp->info.format == _dst->info.format,
|
||||
VK_FILTER_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -890,7 +891,8 @@ namespace vk
|
||||
image_type,
|
||||
dst_format,
|
||||
w, h, d, mips, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags);
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags,
|
||||
rsx::classify_format(gcm_format));
|
||||
}
|
||||
|
||||
//This method is almost exclusively used to work on framebuffer resources
|
||||
@ -910,7 +912,7 @@ namespace vk
|
||||
}
|
||||
|
||||
image->set_native_component_layout(view_swizzle);
|
||||
auto view = image->get_view(get_remap_encoding(remap_vector), remap_vector);
|
||||
auto view = image->get_view(rsx::get_remap_encoding(remap_vector), remap_vector);
|
||||
|
||||
if (copy)
|
||||
{
|
||||
@ -1144,7 +1146,8 @@ namespace vk
|
||||
image_type,
|
||||
vk_format,
|
||||
width, height, depth, mipmaps, layer, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, usage_flags, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0);
|
||||
VK_IMAGE_TILING_OPTIMAL, usage_flags, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0,
|
||||
rsx::classify_format(gcm_format));
|
||||
|
||||
image->native_component_map = apply_component_mapping_flags(gcm_format, flags, rsx::default_remap_vector);
|
||||
|
||||
@ -1209,7 +1212,7 @@ namespace vk
|
||||
}
|
||||
|
||||
cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range& rsx_range, 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) override
|
||||
rsx::texture_upload_context context, const std::vector<rsx::subresource_layout>& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) override
|
||||
{
|
||||
auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, pitch, gcm_format, context, type, swizzled,
|
||||
rsx::texture_create_flags::default_component_order);
|
||||
|
Loading…
Reference in New Issue
Block a user