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 format;
|
||||||
GLenum type;
|
GLenum type;
|
||||||
bool compressed;
|
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 = {{
|
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_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, 1}, // B5G6R5
|
{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, 1}, // A2B10G10R10
|
{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, 16}, // DXT1
|
{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, 16}, // DXT23
|
{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, 16}, // DXT45
|
{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) {
|
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;
|
return;
|
||||||
|
|
||||||
if (gl_buffer == nullptr) {
|
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]);
|
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,
|
std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
|
||||||
bytes_per_pixel * width * height);
|
bytes_per_pixel * width * height);
|
||||||
} else {
|
} else {
|
||||||
morton_to_gl_fns[static_cast<size_t>(pixel_format)](
|
morton_to_gl_fns[static_cast<size_t>(pixel_format)](GetActualWidth(), block_height,
|
||||||
stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
|
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);
|
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
|
// Load data from memory to the surface
|
||||||
GLint x0 = static_cast<GLint>(rect.left);
|
GLint x0 = static_cast<GLint>(rect.left);
|
||||||
|
@ -583,11 +582,9 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
if (tuple.compressed) {
|
if (tuple.compressed) {
|
||||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
|
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
|
||||||
static_cast<GLsizei>(rect.GetWidth()),
|
static_cast<GLsizei>(rect.GetWidth() * GetCompresssionFactor()),
|
||||||
static_cast<GLsizei>(rect.GetHeight()), 0,
|
static_cast<GLsizei>(rect.GetHeight() * GetCompresssionFactor()), 0,
|
||||||
rect.GetWidth() * rect.GetHeight() *
|
size, &gl_buffer[buffer_offset]);
|
||||||
GetGLBytesPerPixel(pixel_format) / tuple.compression_factor,
|
|
||||||
&gl_buffer[buffer_offset]);
|
|
||||||
} else {
|
} else {
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
|
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
|
||||||
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
|
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
|
||||||
|
@ -1041,10 +1038,10 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
|
||||||
|
|
||||||
SurfaceParams params;
|
SurfaceParams params;
|
||||||
params.addr = config.tic.Address();
|
params.addr = config.tic.Address();
|
||||||
params.width = config.tic.Width();
|
|
||||||
params.height = config.tic.Height();
|
|
||||||
params.is_tiled = config.tic.IsTiled();
|
params.is_tiled = config.tic.IsTiled();
|
||||||
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
|
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.
|
// TODO(Subv): Different types per component are not supported.
|
||||||
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
||||||
|
|
|
@ -84,23 +84,49 @@ struct SurfaceParams {
|
||||||
Invalid = 4,
|
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)
|
if (format == PixelFormat::Invalid)
|
||||||
return 0;
|
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
|
32, // ABGR8
|
||||||
16, // B5G6R5
|
16, // B5G6R5
|
||||||
32, // A2B10G10R10
|
32, // A2B10G10R10
|
||||||
64, // DXT1
|
64, // DXT1
|
||||||
128, // DXT23
|
128, // DXT23
|
||||||
128, // DXT45
|
128, // DXT45
|
||||||
};
|
}};
|
||||||
|
|
||||||
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
||||||
return bpp_table[static_cast<size_t>(format)];
|
return bpp_table[static_cast<size_t>(format)];
|
||||||
}
|
}
|
||||||
unsigned int GetFormatBpp() const {
|
u32 GetFormatBpp() const {
|
||||||
return GetFormatBpp(pixel_format);
|
return GetFormatBpp(pixel_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +281,24 @@ struct SurfaceParams {
|
||||||
// Returns the region of the biggest valid rectange within interval
|
// Returns the region of the biggest valid rectange within interval
|
||||||
SurfaceInterval GetCopyableInterval(const Surface& src_surface) const;
|
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 {
|
u32 GetScaledWidth() const {
|
||||||
return width * res_scale;
|
return width * res_scale;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue