1
0
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:
kd-11 2018-12-13 13:23:58 +03:00 committed by kd-11
parent 50c07833e4
commit 97704d1396
7 changed files with 75 additions and 94 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -870,10 +870,9 @@ namespace vk
return &region;
}
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);