gl_rasterizer_cache: Handle compressed texture sizes.
This commit is contained in:
parent
4415e00181
commit
bc0f1896fc
2 changed files with 65 additions and 24 deletions
|
@ -41,18 +41,15 @@ struct FormatTuple {
|
|||
GLenum format;
|
||||
GLenum type;
|
||||
bool compressed;
|
||||
// How many pixels in the original texture are equivalent to one pixel in the compressed
|
||||
// texture.
|
||||
u32 compression_factor;
|
||||
};
|
||||
|
||||
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
|
||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8
|
||||
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1}, // B5G6R5
|
||||
{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, 1}, // A2B10G10R10
|
||||
{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
|
||||
{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
|
||||
{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
|
||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8
|
||||
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false}, // B5G6R5
|
||||
{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false}, // A2B10G10R10
|
||||
{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1
|
||||
{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23
|
||||
{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45
|
||||
}};
|
||||
|
||||
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
||||
|
@ -476,7 +473,7 @@ void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr loa
|
|||
return;
|
||||
|
||||
if (gl_buffer == nullptr) {
|
||||
gl_buffer_size = width * height * GetGLBytesPerPixel(pixel_format);
|
||||
gl_buffer_size = GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format);
|
||||
gl_buffer.reset(new u8[gl_buffer_size]);
|
||||
}
|
||||
|
||||
|
@ -491,8 +488,9 @@ void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr loa
|
|||
std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
|
||||
bytes_per_pixel * width * height);
|
||||
} else {
|
||||
morton_to_gl_fns[static_cast<size_t>(pixel_format)](
|
||||
stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
|
||||
morton_to_gl_fns[static_cast<size_t>(pixel_format)](GetActualWidth(), block_height,
|
||||
GetActualHeight(), &gl_buffer[0], addr,
|
||||
load_start, load_end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,7 +546,8 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
|
|||
|
||||
MICROPROFILE_SCOPE(OpenGL_TextureUL);
|
||||
|
||||
ASSERT(gl_buffer_size == width * height * GetGLBytesPerPixel(pixel_format));
|
||||
ASSERT(gl_buffer_size ==
|
||||
GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format));
|
||||
|
||||
// Load data from memory to the surface
|
||||
GLint x0 = static_cast<GLint>(rect.left);
|
||||
|
@ -583,11 +582,9 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
if (tuple.compressed) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
|
||||
static_cast<GLsizei>(rect.GetWidth()),
|
||||
static_cast<GLsizei>(rect.GetHeight()), 0,
|
||||
rect.GetWidth() * rect.GetHeight() *
|
||||
GetGLBytesPerPixel(pixel_format) / tuple.compression_factor,
|
||||
&gl_buffer[buffer_offset]);
|
||||
static_cast<GLsizei>(rect.GetWidth() * GetCompresssionFactor()),
|
||||
static_cast<GLsizei>(rect.GetHeight() * GetCompresssionFactor()), 0,
|
||||
size, &gl_buffer[buffer_offset]);
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
|
||||
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
|
||||
|
@ -1041,10 +1038,10 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
|
|||
|
||||
SurfaceParams params;
|
||||
params.addr = config.tic.Address();
|
||||
params.width = config.tic.Width();
|
||||
params.height = config.tic.Height();
|
||||
params.is_tiled = config.tic.IsTiled();
|
||||
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
|
||||
params.width = config.tic.Width() / params.GetCompresssionFactor();
|
||||
params.height = config.tic.Height() / params.GetCompresssionFactor();
|
||||
|
||||
// TODO(Subv): Different types per component are not supported.
|
||||
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
||||
|
|
|
@ -84,23 +84,49 @@ struct SurfaceParams {
|
|||
Invalid = 4,
|
||||
};
|
||||
|
||||
static constexpr unsigned int GetFormatBpp(PixelFormat format) {
|
||||
/**
|
||||
* Gets the compression factor for the specified PixelFormat. This applies to just the
|
||||
* "compressed width" and "compressed height", not the overall compression factor of a
|
||||
* compressed image. This is used for maintaining proper surface sizes for compressed texture
|
||||
* formats.
|
||||
*/
|
||||
static constexpr u32 GetCompresssionFactor(PixelFormat format) {
|
||||
if (format == PixelFormat::Invalid)
|
||||
return 0;
|
||||
|
||||
constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
|
||||
constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{
|
||||
1, // ABGR8
|
||||
1, // B5G6R5
|
||||
1, // A2B10G10R10
|
||||
4, // DXT1
|
||||
4, // DXT23
|
||||
4, // DXT45
|
||||
}};
|
||||
|
||||
ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
|
||||
return compression_factor_table[static_cast<size_t>(format)];
|
||||
}
|
||||
u32 GetCompresssionFactor() const {
|
||||
return GetCompresssionFactor(pixel_format);
|
||||
}
|
||||
|
||||
static constexpr u32 GetFormatBpp(PixelFormat format) {
|
||||
if (format == PixelFormat::Invalid)
|
||||
return 0;
|
||||
|
||||
constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
|
||||
32, // ABGR8
|
||||
16, // B5G6R5
|
||||
32, // A2B10G10R10
|
||||
64, // DXT1
|
||||
128, // DXT23
|
||||
128, // DXT45
|
||||
};
|
||||
}};
|
||||
|
||||
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
||||
return bpp_table[static_cast<size_t>(format)];
|
||||
}
|
||||
unsigned int GetFormatBpp() const {
|
||||
u32 GetFormatBpp() const {
|
||||
return GetFormatBpp(pixel_format);
|
||||
}
|
||||
|
||||
|
@ -255,6 +281,24 @@ struct SurfaceParams {
|
|||
// Returns the region of the biggest valid rectange within interval
|
||||
SurfaceInterval GetCopyableInterval(const Surface& src_surface) const;
|
||||
|
||||
/**
|
||||
* Gets the actual width (in pixels) of the surface. This is provided because `width` is used
|
||||
* for tracking the surface region in memory, which may be compressed for certain formats. In
|
||||
* this scenario, `width` is actually the compressed width.
|
||||
*/
|
||||
u32 GetActualWidth() const {
|
||||
return width * GetCompresssionFactor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual height (in pixels) of the surface. This is provided because `height` is used
|
||||
* for tracking the surface region in memory, which may be compressed for certain formats. In
|
||||
* this scenario, `height` is actually the compressed height.
|
||||
*/
|
||||
u32 GetActualHeight() const {
|
||||
return height * GetCompresssionFactor();
|
||||
}
|
||||
|
||||
u32 GetScaledWidth() const {
|
||||
return width * res_scale;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue