mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
rsx: Fix texture size calculations
This commit is contained in:
parent
50c07833e4
commit
97704d1396
@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "TextureUtils.h"
|
||||
#include "../RSXThread.h"
|
||||
@ -525,6 +525,31 @@ u8 get_format_block_size_in_bytes(rsx::surface_color_format format)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of texel lines decoded in one pitch-length number of bytes
|
||||
*/
|
||||
u8 get_format_texel_rows_per_line(u32 format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
// Layout is 4x4 blocks, i.e one row of pitch bytes in length actually encodes 4 texel rows
|
||||
return 4;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_format_packed_pitch(u32 format, u16 width)
|
||||
{
|
||||
const auto texels_per_block = get_format_block_size_in_texel(format);
|
||||
const auto bytes_per_block = get_format_block_size_in_bytes(format);
|
||||
|
||||
return ((width + texels_per_block - 1) / texels_per_block) * bytes_per_block;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
format &= ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
@ -559,89 +584,39 @@ size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_
|
||||
row_pitch_alignment, mipmap_alignment);
|
||||
}
|
||||
|
||||
|
||||
static size_t get_texture_size(u32 w, u32 h, u8 format)
|
||||
static size_t get_texture_size(u32 format, u16 width, u16 height, u16 depth, u32 pitch, u16 mipmaps, u16 layers)
|
||||
{
|
||||
format &= ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
const auto gcm_format = format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
const auto texel_rows_per_line = get_format_texel_rows_per_line(gcm_format);
|
||||
|
||||
// TODO: Take mipmaps into account
|
||||
switch (format)
|
||||
if (pitch == 0)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
return w * h;
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_R6G5B5:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
|
||||
w = align(w, 4);
|
||||
h = align(h, 4);
|
||||
return w * h / 6;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
|
||||
w = align(w, 4);
|
||||
h = align(h, 4);
|
||||
return w * h / 4;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
|
||||
w = align(w, 4);
|
||||
h = align(h, 4);
|
||||
return w * h / 4;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_X16:
|
||||
return w * h * 2;
|
||||
case CELL_GCM_TEXTURE_Y16_X16:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
|
||||
return w * h * 8;
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
|
||||
return w * h * 16;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||
return w * h * 4;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
|
||||
return w * h;
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
|
||||
return w * h;
|
||||
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
|
||||
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
|
||||
return w * h * 2;
|
||||
default:
|
||||
LOG_ERROR(RSX, "Unimplemented texture size for texture format: 0x%x", format);
|
||||
return 0;
|
||||
pitch = get_format_packed_pitch(gcm_format, width);
|
||||
}
|
||||
|
||||
u32 size = 0;
|
||||
for (u32 layer = 0; layer < layers; ++layer)
|
||||
{
|
||||
u32 mip_height = (height + texel_rows_per_line - 1) / texel_rows_per_line; // Convert texels to blocks
|
||||
|
||||
for (u32 mipmap = 0; mipmap < mipmaps; ++mipmap)
|
||||
{
|
||||
size += pitch * mip_height;
|
||||
mip_height = std::max(mip_height / 2u, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_texture_size(const rsx::fragment_texture &texture)
|
||||
{
|
||||
return get_texture_size(texture.width(), texture.height(), texture.format());
|
||||
return get_texture_size(texture.format(), texture.width(), texture.height(), texture.depth(),
|
||||
texture.pitch(), texture.get_exact_mipmap_count(), texture.cubemap() ? 6 : 1);
|
||||
}
|
||||
|
||||
size_t get_texture_size(const rsx::vertex_texture &texture)
|
||||
{
|
||||
return get_texture_size(texture.width(), texture.height(), texture.format());
|
||||
return get_texture_size(texture.format(), texture.width(), texture.height(), texture.depth(),
|
||||
texture.pitch(), texture.get_exact_mipmap_count(), texture.cubemap() ? 6 : 1);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "../RSXTexture.h"
|
||||
|
||||
@ -69,4 +69,9 @@ u8 get_format_block_size_in_bytes(rsx::surface_color_format 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);
|
||||
size_t get_texture_size(const rsx::vertex_texture &texture);
|
||||
|
||||
/**
|
||||
* Get packed pitch
|
||||
*/
|
||||
u32 get_format_packed_pitch(u32 format, u16 width);
|
@ -288,7 +288,7 @@ namespace rsx
|
||||
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0;
|
||||
virtual section_storage_type* create_new_texture(commandbuffer_type&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 gcm_format,
|
||||
rsx::texture_upload_context context, rsx::texture_dimension_extended type, texture_create_flags flags) = 0;
|
||||
virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format, texture_upload_context context,
|
||||
virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, 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;
|
||||
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;
|
||||
@ -1688,18 +1688,18 @@ namespace rsx
|
||||
sampled_image_descriptor upload_texture(commandbuffer_type& cmd, RsxTextureType& tex, surface_store_type& m_rtts, Args&&... extras)
|
||||
{
|
||||
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
|
||||
const u32 tex_size = (u32)get_placed_texture_storage_size(tex, 256, 512);
|
||||
const u32 tex_size = (u32)get_texture_size(tex);
|
||||
const address_range tex_range = address_range::start_length(texaddr, tex_size);
|
||||
const u32 format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
const bool is_compressed_format = (format == CELL_GCM_TEXTURE_COMPRESSED_DXT1 || format == CELL_GCM_TEXTURE_COMPRESSED_DXT23 || format == CELL_GCM_TEXTURE_COMPRESSED_DXT45);
|
||||
|
||||
const auto extended_dimension = tex.get_extended_texture_dimension();
|
||||
u16 depth;
|
||||
u16 tex_height = (u16)tex.height();
|
||||
const u16 tex_width = tex.width();
|
||||
u16 tex_pitch = is_compressed_format? (u16)(get_texture_size(tex) / tex_height) : tex.pitch(); //NOTE: Compressed textures dont have a real pitch (tex_size = (w*h)/6)
|
||||
if (tex_pitch == 0) tex_pitch = tex_width * get_format_block_size_in_bytes(format);
|
||||
u16 tex_height = tex.height();
|
||||
u16 tex_pitch = (u16)tex.pitch();
|
||||
if (tex_pitch == 0) tex_pitch = get_format_packed_pitch(format, tex_width);
|
||||
|
||||
u16 depth;
|
||||
switch (extended_dimension)
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d:
|
||||
@ -1888,7 +1888,7 @@ namespace rsx
|
||||
invalidate_range_impl_base(tex_range, invalidation_cause::read, std::forward<Args>(extras)...);
|
||||
|
||||
//NOTE: SRGB correction is to be handled in the fragment shader; upload as linear RGB
|
||||
return{ upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
|
||||
return{ upload_image_from_cpu(cmd, tex_range, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
|
||||
texture_upload_context::shader_read, subresources_layout, extended_dimension, is_swizzled)->get_view(tex.remap(), tex.decoded_remap()),
|
||||
texture_upload_context::shader_read, is_depth_format, scale_x, scale_y, extended_dimension };
|
||||
}
|
||||
@ -2156,7 +2156,8 @@ namespace rsx
|
||||
{
|
||||
lock.upgrade();
|
||||
|
||||
invalidate_range_impl_base(address_range::start_length(src_address, src.pitch * src.slice_h), invalidation_cause::read, std::forward<Args>(extras)...);
|
||||
const auto rsx_range = address_range::start_length(src_address, src.pitch * src.slice_h);
|
||||
invalidate_range_impl_base(rsx_range, invalidation_cause::read, std::forward<Args>(extras)...);
|
||||
|
||||
const u16 pitch_in_block = src_is_argb8 ? src.pitch >> 2 : src.pitch >> 1;
|
||||
std::vector<rsx_subresource_layout> subresource_layout;
|
||||
@ -2169,7 +2170,7 @@ namespace rsx
|
||||
subresource_layout.push_back(subres);
|
||||
|
||||
const u32 gcm_format = src_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5;
|
||||
vram_texture = upload_image_from_cpu(cmd, src_address, src.width, src.slice_h, 1, 1, src.pitch, gcm_format, texture_upload_context::blit_engine_src,
|
||||
vram_texture = upload_image_from_cpu(cmd, rsx_range, src.width, src.slice_h, 1, 1, src.pitch, gcm_format, texture_upload_context::blit_engine_src,
|
||||
subresource_layout, rsx::texture_dimension_extended::texture_dimension_2d, dst.swizzled)->get_raw_texture();
|
||||
|
||||
typeless_info.src_context = texture_upload_context::blit_engine_src;
|
||||
@ -2296,7 +2297,9 @@ namespace rsx
|
||||
dst_dimensions.height = section_length / dst.pitch;
|
||||
|
||||
lock.upgrade();
|
||||
invalidate_range_impl_base(address_range::start_length(dst.rsx_address, section_length), invalidation_cause::write, std::forward<Args>(extras)...);
|
||||
|
||||
const auto rsx_range = address_range::start_length(dst.rsx_address, section_length);
|
||||
invalidate_range_impl_base(rsx_range, invalidation_cause::write, std::forward<Args>(extras)...);
|
||||
|
||||
const u16 pitch_in_block = dst_is_argb8 ? dst.pitch >> 2 : dst.pitch >> 1;
|
||||
std::vector<rsx_subresource_layout> subresource_layout;
|
||||
@ -2308,7 +2311,7 @@ namespace rsx
|
||||
subres.data = { (const gsl::byte*)dst.pixels, dst.pitch * dst_dimensions.height };
|
||||
subresource_layout.push_back(subres);
|
||||
|
||||
cached_dest = upload_image_from_cpu(cmd, dst.rsx_address, dst_dimensions.width, dst_dimensions.height, 1, 1, dst.pitch,
|
||||
cached_dest = upload_image_from_cpu(cmd, rsx_range, dst_dimensions.width, dst_dimensions.height, 1, 1, dst.pitch,
|
||||
gcm_format, rsx::texture_upload_context::blit_engine_dst, subresource_layout,
|
||||
rsx::texture_dimension_extended::texture_dimension_2d, false);
|
||||
|
||||
|
@ -573,7 +573,7 @@ namespace gl
|
||||
return remap_values;
|
||||
}
|
||||
|
||||
void upload_texture(GLuint id, u32 texaddr, u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type,
|
||||
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)
|
||||
{
|
||||
size_t texture_data_sz = get_placed_texture_storage_size(width, height, depth, gcm_format, mipmaps, type == rsx::texture_dimension_extended::texture_dimension_cubemap, 256, 512);
|
||||
|
@ -30,7 +30,7 @@ namespace gl
|
||||
* - second vector contains overrides to force the value to either 0 or 1 instead of reading from texture
|
||||
* static_state - set up the texture without consideration for sampler state (useful for vertex textures which have no real sampler state on RSX)
|
||||
*/
|
||||
void upload_texture(GLuint id, u32 texaddr, u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, bool is_swizzled, rsx::texture_dimension_extended type,
|
||||
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);
|
||||
|
||||
class sampler_state
|
||||
|
@ -998,15 +998,14 @@ namespace gl
|
||||
return &cached;
|
||||
}
|
||||
|
||||
cached_texture_section* upload_image_from_cpu(void*&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format,
|
||||
cached_texture_section* upload_image_from_cpu(void*&, 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
|
||||
{
|
||||
void* unused = nullptr;
|
||||
const utils::address_range rsx_range = utils::address_range::start_length(rsx_address, pitch * height);
|
||||
auto section = create_new_texture(unused, rsx_range, width, height, depth, mipmaps, gcm_format, context, type,
|
||||
rsx::texture_create_flags::default_component_order);
|
||||
|
||||
gl::upload_texture(section->get_raw_texture()->id(), rsx_address, gcm_format, width, height, depth, mipmaps,
|
||||
gl::upload_texture(section->get_raw_texture()->id(), gcm_format, width, height, depth, mipmaps,
|
||||
input_swizzled, type, subresource_layout);
|
||||
|
||||
return section;
|
||||
|
@ -870,10 +870,9 @@ namespace vk
|
||||
return ®ion;
|
||||
}
|
||||
|
||||
cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, u32 gcm_format,
|
||||
cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, 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
|
||||
{
|
||||
const utils::address_range rsx_range = utils::address_range::start_length(rsx_address, pitch * height);
|
||||
auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, gcm_format, context, type,
|
||||
rsx::texture_create_flags::default_component_order);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user