mirror of
https://github.com/yuzu-mirror/yuzu.git
synced 2024-11-20 07:49:59 +00:00
gl_rasterizer_cache: Keep track of surface 2D size separately from total size.
This commit is contained in:
parent
f8e46d335f
commit
ce452049d3
2 changed files with 46 additions and 32 deletions
|
@ -71,7 +71,8 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes_total = params.SizeInBytesTotal();
|
||||||
|
params.size_in_bytes_2d = params.SizeInBytes2D();
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +90,8 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
params.unaligned_height = config.height;
|
params.unaligned_height = config.height;
|
||||||
params.target = SurfaceTarget::Texture2D;
|
params.target = SurfaceTarget::Texture2D;
|
||||||
params.depth = 1;
|
params.depth = 1;
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes_total = params.SizeInBytesTotal();
|
||||||
|
params.size_in_bytes_2d = params.SizeInBytes2D();
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +110,8 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
|
||||||
params.unaligned_height = zeta_height;
|
params.unaligned_height = zeta_height;
|
||||||
params.target = SurfaceTarget::Texture2D;
|
params.target = SurfaceTarget::Texture2D;
|
||||||
params.depth = 1;
|
params.depth = 1;
|
||||||
params.size_in_bytes = params.SizeInBytes();
|
params.size_in_bytes_total = params.SizeInBytesTotal();
|
||||||
|
params.size_in_bytes_2d = params.SizeInBytes2D();
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,10 +588,13 @@ void CachedSurface::LoadGLBuffer() {
|
||||||
|
|
||||||
const u32 bytes_per_pixel = GetGLBytesPerPixel(params.pixel_format);
|
const u32 bytes_per_pixel = GetGLBytesPerPixel(params.pixel_format);
|
||||||
const u32 copy_size = params.width * params.height * bytes_per_pixel;
|
const u32 copy_size = params.width * params.height * bytes_per_pixel;
|
||||||
|
const std::size_t total_size = copy_size * params.depth;
|
||||||
|
|
||||||
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
|
MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
|
||||||
|
|
||||||
if (params.is_tiled) {
|
if (params.is_tiled) {
|
||||||
|
gl_buffer.resize(total_size);
|
||||||
|
|
||||||
// TODO(bunnei): This only unswizzles and copies a 2D texture - we do not yet know how to do
|
// TODO(bunnei): This only unswizzles and copies a 2D texture - we do not yet know how to do
|
||||||
// this for 3D textures, etc.
|
// this for 3D textures, etc.
|
||||||
switch (params.target) {
|
switch (params.target) {
|
||||||
|
@ -601,13 +607,11 @@ void CachedSurface::LoadGLBuffer() {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_buffer.resize(static_cast<std::size_t>(params.depth) * copy_size);
|
|
||||||
morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)](
|
morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)](
|
||||||
params.width, params.block_height, params.height, gl_buffer.data(), copy_size,
|
params.width, params.block_height, params.height, gl_buffer.data(), copy_size,
|
||||||
params.addr);
|
params.addr);
|
||||||
} else {
|
} else {
|
||||||
const u8* const texture_src_data_end{texture_src_data +
|
const u8* const texture_src_data_end{texture_src_data + total_size};
|
||||||
(static_cast<std::size_t>(params.depth) * copy_size)};
|
|
||||||
gl_buffer.assign(texture_src_data, texture_src_data_end);
|
gl_buffer.assign(texture_src_data, texture_src_data_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,15 +667,15 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
|
||||||
glCompressedTexImage2D(
|
glCompressedTexImage2D(
|
||||||
SurfaceTargetToGL(params.target), 0, tuple.internal_format,
|
SurfaceTargetToGL(params.target), 0, tuple.internal_format,
|
||||||
static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0,
|
static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0,
|
||||||
static_cast<GLsizei>(params.size_in_bytes), &gl_buffer[buffer_offset]);
|
static_cast<GLsizei>(params.size_in_bytes_2d), &gl_buffer[buffer_offset]);
|
||||||
break;
|
break;
|
||||||
case SurfaceParams::SurfaceTarget::Texture3D:
|
case SurfaceParams::SurfaceTarget::Texture3D:
|
||||||
case SurfaceParams::SurfaceTarget::Texture2DArray:
|
case SurfaceParams::SurfaceTarget::Texture2DArray:
|
||||||
glCompressedTexImage3D(
|
glCompressedTexImage3D(
|
||||||
SurfaceTargetToGL(params.target), 0, tuple.internal_format,
|
SurfaceTargetToGL(params.target), 0, tuple.internal_format,
|
||||||
static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height),
|
static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height),
|
||||||
static_cast<GLsizei>(params.depth), 0, static_cast<GLsizei>(params.size_in_bytes),
|
static_cast<GLsizei>(params.depth), 0,
|
||||||
&gl_buffer[buffer_offset]);
|
static_cast<GLsizei>(params.size_in_bytes_total), &gl_buffer[buffer_offset]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
|
||||||
|
@ -679,8 +683,8 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
glCompressedTexImage2D(
|
glCompressedTexImage2D(
|
||||||
GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width),
|
GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width),
|
||||||
static_cast<GLsizei>(params.height), 0, static_cast<GLsizei>(params.size_in_bytes),
|
static_cast<GLsizei>(params.height), 0,
|
||||||
&gl_buffer[buffer_offset]);
|
static_cast<GLsizei>(params.size_in_bytes_2d), &gl_buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -811,15 +815,15 @@ Surface RasterizerCacheOpenGL::GetUncachedSurface(const SurfaceParams& params) {
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
|
||||||
const SurfaceParams& new_params) {
|
const SurfaceParams& new_params) {
|
||||||
// Verify surface is compatible for blitting
|
// Verify surface is compatible for blitting
|
||||||
const auto& params{surface->GetSurfaceParams()};
|
const auto& old_params{old_surface->GetSurfaceParams()};
|
||||||
|
|
||||||
// Get a new surface with the new parameters, and blit the previous surface to it
|
// Get a new surface with the new parameters, and blit the previous surface to it
|
||||||
Surface new_surface{GetUncachedSurface(new_params)};
|
Surface new_surface{GetUncachedSurface(new_params)};
|
||||||
|
|
||||||
if (params.pixel_format == new_params.pixel_format ||
|
if (old_params.pixel_format == new_params.pixel_format ||
|
||||||
!Settings::values.use_accurate_framebuffers) {
|
!Settings::values.use_accurate_framebuffers) {
|
||||||
// If the format is the same, just do a framebuffer blit. This is significantly faster than
|
// If the format is the same, just do a framebuffer blit. This is significantly faster than
|
||||||
// using PBOs. The is also likely less accurate, as textures will be converted rather than
|
// using PBOs. The is also likely less accurate, as textures will be converted rather than
|
||||||
|
@ -833,24 +837,26 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
// where pixels are reinterpreted as a new format (without conversion). This code path uses
|
// where pixels are reinterpreted as a new format (without conversion). This code path uses
|
||||||
// OpenGL PBOs and is quite slow.
|
// OpenGL PBOs and is quite slow.
|
||||||
|
|
||||||
auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
|
auto source_format = GetFormatTuple(old_params.pixel_format, old_params.component_type);
|
||||||
auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
|
auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
|
||||||
|
|
||||||
std::size_t buffer_size = std::max(params.SizeInBytes(), new_params.SizeInBytes());
|
std::size_t buffer_size =
|
||||||
|
std::max(old_params.size_in_bytes_total, new_params.size_in_bytes_total);
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo.handle);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo.handle);
|
||||||
glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
|
glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
|
||||||
if (source_format.compressed) {
|
if (source_format.compressed) {
|
||||||
glGetCompressedTextureImage(surface->Texture().handle, 0,
|
glGetCompressedTextureImage(old_surface->Texture().handle, 0,
|
||||||
static_cast<GLsizei>(params.SizeInBytes()), nullptr);
|
static_cast<GLsizei>(old_params.size_in_bytes_total),
|
||||||
|
nullptr);
|
||||||
} else {
|
} else {
|
||||||
glGetTextureImage(surface->Texture().handle, 0, source_format.format,
|
glGetTextureImage(old_surface->Texture().handle, 0, source_format.format,
|
||||||
source_format.type, static_cast<GLsizei>(params.SizeInBytes()),
|
source_format.type,
|
||||||
nullptr);
|
static_cast<GLsizei>(old_params.size_in_bytes_total), nullptr);
|
||||||
}
|
}
|
||||||
// If the new texture is bigger than the previous one, we need to fill in the rest with data
|
// If the new texture is bigger than the previous one, we need to fill in the rest with data
|
||||||
// from the CPU.
|
// from the CPU.
|
||||||
if (params.SizeInBytes() < new_params.SizeInBytes()) {
|
if (old_params.size_in_bytes_total < new_params.size_in_bytes_total) {
|
||||||
// Upload the rest of the memory.
|
// Upload the rest of the memory.
|
||||||
if (new_params.is_tiled) {
|
if (new_params.is_tiled) {
|
||||||
// TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest
|
// TODO(Subv): We might have to de-tile the subtexture and re-tile it with the rest
|
||||||
|
@ -860,10 +866,12 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during "
|
LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during "
|
||||||
"reinterpretation but the texture is tiled.");
|
"reinterpretation but the texture is tiled.");
|
||||||
}
|
}
|
||||||
std::size_t remaining_size = new_params.SizeInBytes() - params.SizeInBytes();
|
std::size_t remaining_size =
|
||||||
|
new_params.size_in_bytes_total - old_params.size_in_bytes_total;
|
||||||
std::vector<u8> data(remaining_size);
|
std::vector<u8> data(remaining_size);
|
||||||
Memory::ReadBlock(new_params.addr + params.SizeInBytes(), data.data(), data.size());
|
Memory::ReadBlock(new_params.addr + old_params.size_in_bytes_total, data.data(),
|
||||||
glBufferSubData(GL_PIXEL_PACK_BUFFER, params.SizeInBytes(), remaining_size,
|
data.size());
|
||||||
|
glBufferSubData(GL_PIXEL_PACK_BUFFER, old_params.size_in_bytes_total, remaining_size,
|
||||||
data.data());
|
data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +906,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
|
||||||
static_cast<u32>(params.target));
|
static_cast<u32>(new_params.target));
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -689,13 +689,18 @@ struct SurfaceParams {
|
||||||
/// Returns the rectangle corresponding to this surface
|
/// Returns the rectangle corresponding to this surface
|
||||||
MathUtil::Rectangle<u32> GetRect() const;
|
MathUtil::Rectangle<u32> GetRect() const;
|
||||||
|
|
||||||
/// Returns the size of this surface in bytes, adjusted for compression
|
/// Returns the size of this surface as a 2D texture in bytes, adjusted for compression
|
||||||
std::size_t SizeInBytes() const {
|
std::size_t SizeInBytes2D() const {
|
||||||
const u32 compression_factor{GetCompressionFactor(pixel_format)};
|
const u32 compression_factor{GetCompressionFactor(pixel_format)};
|
||||||
ASSERT(width % compression_factor == 0);
|
ASSERT(width % compression_factor == 0);
|
||||||
ASSERT(height % compression_factor == 0);
|
ASSERT(height % compression_factor == 0);
|
||||||
return (width / compression_factor) * (height / compression_factor) *
|
return (width / compression_factor) * (height / compression_factor) *
|
||||||
GetFormatBpp(pixel_format) * depth / CHAR_BIT;
|
GetFormatBpp(pixel_format) / CHAR_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total size of this surface in bytes, adjusted for compression
|
||||||
|
std::size_t SizeInBytesTotal() const {
|
||||||
|
return SizeInBytes2D() * depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates SurfaceParams from a texture configuration
|
/// Creates SurfaceParams from a texture configuration
|
||||||
|
@ -725,7 +730,8 @@ struct SurfaceParams {
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 depth;
|
u32 depth;
|
||||||
u32 unaligned_height;
|
u32 unaligned_height;
|
||||||
std::size_t size_in_bytes;
|
std::size_t size_in_bytes_total;
|
||||||
|
std::size_t size_in_bytes_2d;
|
||||||
SurfaceTarget target;
|
SurfaceTarget target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -759,7 +765,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSizeInBytes() const {
|
std::size_t GetSizeInBytes() const {
|
||||||
return params.size_in_bytes;
|
return params.size_in_bytes_total;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OGLTexture& Texture() const {
|
const OGLTexture& Texture() const {
|
||||||
|
@ -822,7 +828,7 @@ private:
|
||||||
Surface GetUncachedSurface(const SurfaceParams& params);
|
Surface GetUncachedSurface(const SurfaceParams& params);
|
||||||
|
|
||||||
/// Recreates a surface with new parameters
|
/// Recreates a surface with new parameters
|
||||||
Surface RecreateSurface(const Surface& surface, const SurfaceParams& new_params);
|
Surface RecreateSurface(const Surface& old_surface, const SurfaceParams& new_params);
|
||||||
|
|
||||||
/// Reserves a unique surface that can be reused later
|
/// Reserves a unique surface that can be reused later
|
||||||
void ReserveSurface(const Surface& surface);
|
void ReserveSurface(const Surface& surface);
|
||||||
|
|
Loading…
Reference in a new issue