rasterizer_cache: Improve TextureRuntime API

* This makes every operation more explicit and mimics more the Vulkan API
This commit is contained in:
emufan4568
2022-09-09 00:42:14 +03:00
committed by GPUCode
parent e30e977140
commit 68ca206d53
5 changed files with 248 additions and 162 deletions

View File

@ -337,17 +337,21 @@ void CachedSurface::UploadGLTexture(Common::Rectangle<u32> rect) {
const Common::Rectangle<u32> from_rect{0, height, width, 0};
if (is_custom || !owner.texture_filterer->Filter(unscaled_tex, from_rect, texture, scaled_rect, type)) {
const Subresource src_subresource = {
.type = type,
.region = from_rect
const TextureBlit texture_blit = {
.surface_type = type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {0, 0},
.end = {width, height}
},
.dst_region = Region2D{
.start = {rect.left, rect.bottom},
.end = {rect.right, rect.top}
}
};
const Subresource dst_subresource = {
.type = type,
.region = scaled_rect
};
runtime.BlitTextures(unscaled_tex, src_subresource, texture, dst_subresource);
runtime.BlitTextures(unscaled_tex, texture, texture_blit);
}
}
@ -363,8 +367,10 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
MICROPROFILE_SCOPE(RasterizerCache_TextureDL);
const u32 download_size = width * height * GetBytesPerPixel(pixel_format);
if (gl_buffer.empty()) {
gl_buffer.resize(width * height * GetBytesPerPixel(pixel_format));
gl_buffer.resize(download_size);
}
OpenGLState state = OpenGLState::GetCurState();
@ -374,10 +380,7 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
// Ensure no bad interactions with GL_PACK_ALIGNMENT
ASSERT(stride * GetBytesPerPixel(pixel_format) % 4 == 0);
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(stride));
const std::size_t buffer_offset =
(rect.bottom * stride + rect.left) * GetBytesPerPixel(pixel_format);
const FormatTuple& tuple = GetFormatTuple(pixel_format);
const u32 buffer_offset = (rect.bottom * stride + rect.left) * GetBytesPerPixel(pixel_format);
// If not 1x scale, blit scaled texture to a new 1x texture and use that to flush
if (res_scale != 1) {
@ -390,23 +393,29 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
const Common::Rectangle<u32> unscaled_tex_rect{0, rect.GetHeight(), rect.GetWidth(), 0};
auto unscaled_tex = owner.AllocateSurfaceTexture(pixel_format, rect.GetWidth(), rect.GetHeight());
const Subresource src_subresource = {
.type = type,
.region = scaled_rect
};
const Subresource dst_subresource = {
.type = type,
.region = unscaled_tex_rect
const TextureBlit texture_blit = {
.surface_type = type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {scaled_rect.left, scaled_rect.bottom},
.end = {scaled_rect.right, scaled_rect.top}
},
.dst_region = Region2D{
.start = {unscaled_tex_rect.left, unscaled_tex_rect.bottom},
.end = {unscaled_tex_rect.right, unscaled_tex_rect.top}
}
};
// Blit scaled texture to the unscaled one
runtime.BlitTextures(texture, src_subresource, unscaled_tex, dst_subresource);
runtime.BlitTextures(texture, unscaled_tex, texture_blit);
state.texture_units[0].texture_2d = unscaled_tex.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);
const FormatTuple& tuple = GetFormatTuple(pixel_format);
if (GLES) {
owner.texture_downloader_es->GetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type,
rect.GetHeight(), rect.GetWidth(),
@ -415,12 +424,18 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, &gl_buffer[buffer_offset]);
}
} else {
const Subresource subresource = {
.type = type,
.region = rect
const BufferTextureCopy texture_download = {
.buffer_offset = buffer_offset,
.buffer_size = download_size,
.buffer_row_length = stride,
.buffer_height = height,
.surface_type = type,
.texture_level = 0,
.texture_offset = {rect.bottom, rect.left},
.texture_extent = {rect.GetWidth(), rect.GetHeight()}
};
runtime.ReadTexture(texture, subresource, tuple, (u8*)gl_buffer.data());
runtime.ReadTexture(texture, texture_download, pixel_format, gl_buffer);
}
glPixelStorei(GL_PACK_ROW_LENGTH, 0);

View File

@ -49,11 +49,7 @@ void RasterizerCache::CopySurface(const Surface& src_surface, const Surface& dst
SurfaceParams subrect_params = dst_surface->FromInterval(copy_interval);
ASSERT(subrect_params.GetInterval() == copy_interval && src_surface != dst_surface);
const Subresource dst_subresource = {
.type = dst_surface->type,
.region = dst_surface->GetScaledSubRect(subrect_params)
};
const auto dst_rect = dst_surface->GetScaledSubRect(subrect_params);
if (src_surface->type == SurfaceType::Fill) {
// FillSurface needs a 4 bytes buffer
const u32 fill_offset =
@ -68,18 +64,36 @@ void RasterizerCache::CopySurface(const Surface& src_surface, const Surface& dst
const ClearValue clear_value =
MakeClearValue(dst_surface->type, dst_surface->pixel_format, fill_buffer.data());
runtime.ClearTexture(dst_surface->texture, dst_subresource, clear_value);
const ClearRect clear_rect = {
.surface_type = dst_surface->type,
.texture_level = 0,
.rect = Rect2D{
.offset = {dst_rect.left, dst_rect.bottom},
.extent = {dst_rect.GetWidth(), dst_rect.GetHeight()}
}
};
runtime.ClearTexture(dst_surface->texture, clear_rect, clear_value);
return;
}
if (src_surface->CanSubRect(subrect_params)) {
const Subresource src_subresource = {
.type = src_surface->type,
.region = src_surface->GetScaledSubRect(subrect_params)
const auto src_rect = src_surface->GetScaledSubRect(subrect_params);
const TextureBlit texture_blit = {
.surface_type = src_surface->type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {src_rect.left, src_rect.bottom},
.end = {src_rect.right, src_rect.top}
},
.dst_region = Region2D{
.start = {dst_rect.left, dst_rect.bottom},
.end = {dst_rect.right, dst_rect.top}
}
};
runtime.BlitTextures(src_surface->texture, src_subresource, dst_surface->texture,
dst_subresource);
runtime.BlitTextures(src_surface->texture, dst_surface->texture, texture_blit);
return;
}
@ -210,18 +224,21 @@ bool RasterizerCache::BlitSurfaces(const Surface& src_surface,
if (CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format)) {
dst_surface->InvalidateAllWatcher();
const Subresource src_subresource = {
.type = src_surface->type,
.region = src_rect
const TextureBlit texture_blit = {
.surface_type = src_surface->type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {src_rect.left, src_rect.bottom},
.end = {src_rect.right, src_rect.top}
},
.dst_region = Region2D{
.start = {dst_rect.left, dst_rect.bottom},
.end = {dst_rect.right, dst_rect.top}
}
};
const Subresource dst_subresource = {
.type = dst_surface->type,
.region = dst_rect
};
return runtime.BlitTextures(src_surface->texture, src_subresource,
dst_surface->texture, dst_subresource);
return runtime.BlitTextures(src_surface->texture, dst_surface->texture, texture_blit);
}
return false;
@ -441,19 +458,23 @@ Surface RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo& inf
}
if (!surface->is_custom && texture_filterer->IsNull()) {
const Subresource src_subresource = {
.type = surface->type,
.region = level_surface->GetScaledRect()
const auto src_rect = level_surface->GetScaledRect();
const auto dst_rect = surface_params.GetScaledRect();
const TextureBlit texture_blit = {
.surface_type = surface->type,
.src_level = 0,
.dst_level = level,
.src_region = Region2D{
.start = {src_rect.left, src_rect.bottom},
.end = {src_rect.right, src_rect.top}
},
.dst_region = Region2D{
.start = {dst_rect.left, dst_rect.bottom},
.end = {dst_rect.right, dst_rect.top}
}
};
const Subresource dst_subresource = {
.type = surface->type,
.region = surface_params.GetScaledRect(),
.level = level
};
runtime.BlitTextures(level_surface->texture, src_subresource,
surface->texture, dst_subresource);
runtime.BlitTextures(level_surface->texture, surface->texture, texture_blit);
}
watcher->Validate();
@ -530,19 +551,22 @@ const CachedTextureCube& RasterizerCache::GetTextureCube(const TextureCubeConfig
ValidateSurface(surface, surface->addr, surface->size);
}
const Subresource src_subresource = {
.type = surface->type,
.region = surface->GetScaledRect()
const auto src_rect = surface->GetScaledRect();
const TextureBlit texture_blit = {
.surface_type = surface->type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {src_rect.left, src_rect.bottom},
.end = {src_rect.right, src_rect.top}
},
.dst_region = Region2D{
.start = {0, 0},
.end = {scaled_size, scaled_size}
}
};
const Subresource dst_subresource = {
.type = surface->type,
.region = Common::Rectangle<u32>{0, scaled_size, scaled_size, 0}
};
runtime.BlitTextures(surface->texture, src_subresource,
cube.texture, dst_subresource);
runtime.BlitTextures(surface->texture, cube.texture, texture_blit);
face.watcher->Validate();
}
}
@ -857,22 +881,24 @@ bool RasterizerCache::ValidateByReinterpretation(const Surface& surface,
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, tmp_tex,
tmp_rect);
if (!texture_filterer->Filter(tmp_tex, tmp_rect, surface->texture, dest_rect,
type)) {
const Subresource src_subresource = {
.type = type,
.region = tmp_rect
if (!texture_filterer->Filter(tmp_tex, tmp_rect, surface->texture, dest_rect, type)) {
const TextureBlit texture_blit = {
.surface_type = type,
.src_level = 0,
.dst_level = 0,
.src_region = Region2D{
.start = {0, 0},
.end = {width, height}
},
.dst_region = Region2D{
.start = {dest_rect.left, dest_rect.bottom},
.end = {dest_rect.right, dest_rect.top}
}
};
const Subresource dst_subresource = {
.type = type,
.region = dest_rect
};
runtime.BlitTextures(tmp_tex, src_subresource,
surface->texture, dst_subresource);
runtime.BlitTextures(tmp_tex, surface->texture, texture_blit);
}
} else {
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, surface->texture,
dest_rect);

View File

@ -31,70 +31,69 @@ TextureRuntime::TextureRuntime() {
draw_fbo.Create();
}
void TextureRuntime::ReadTexture(const OGLTexture& tex, Subresource subresource,
const FormatTuple& tuple, u8* pixels) {
void TextureRuntime::ReadTexture(OGLTexture& texture, const BufferTextureCopy& copy,
PixelFormat format, std::span<std::byte> pixels) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state;
state.ResetTexture(tex.handle);
OpenGLState state{};
state.ResetTexture(texture.handle);
state.draw.read_framebuffer = read_fbo.handle;
state.Apply();
const u32 level = subresource.level;
switch (subresource.type) {
switch (copy.surface_type) {
case SurfaceType::Color:
case SurfaceType::Texture:
case SurfaceType::Fill:
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.handle,
level);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.handle,
copy.texture_level);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
0);
break;
case SurfaceType::Depth:
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex.handle,
level);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture.handle,
copy.texture_level);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
break;
case SurfaceType::DepthStencil:
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
tex.handle, level);
texture.handle, copy.texture_level);
break;
default:
UNREACHABLE_MSG("Invalid surface type!");
}
const auto& rect = subresource.region;
glReadPixels(rect.left, rect.bottom, rect.GetWidth(), rect.GetHeight(), tuple.format,
tuple.type, pixels);
// TODO: Use PBO here
const FormatTuple& tuple = GetFormatTuple(format);
glReadPixels(copy.texture_offset.x, copy.texture_offset.y,
copy.texture_offset.x + copy.texture_extent.width,
copy.texture_offset.y + copy.texture_extent.height,
tuple.format, tuple.type, pixels.data() + copy.buffer_offset);
}
bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource,
ClearValue value) {
bool TextureRuntime::ClearTexture(OGLTexture& texture, const ClearRect& rect, ClearValue value) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
// Setup scissor rectangle according to the clear rectangle
const auto& clear_rect = subresource.region;
OpenGLState state;
OpenGLState state{};
state.scissor.enabled = true;
state.scissor.x = clear_rect.left;
state.scissor.y = clear_rect.bottom;
state.scissor.width = clear_rect.GetWidth();
state.scissor.height = clear_rect.GetHeight();
state.scissor.x = rect.rect.offset.x;
state.scissor.y = rect.rect.offset.y;
state.scissor.width = rect.rect.extent.width;
state.scissor.height = rect.rect.extent.height;
state.draw.draw_framebuffer = draw_fbo.handle;
state.Apply();
const u32 level = subresource.level;
switch (subresource.type) {
switch (rect.surface_type) {
case SurfaceType::Color:
case SurfaceType::Texture:
case SurfaceType::Fill:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.handle,
level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.handle,
rect.texture_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
0);
@ -108,8 +107,8 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource
break;
case SurfaceType::Depth:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex.handle,
level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture.handle,
rect.texture_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
state.depth.write_mask = GL_TRUE;
@ -120,7 +119,7 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource
case SurfaceType::DepthStencil:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
tex.handle, level);
texture.handle, rect.texture_level);
state.depth.write_mask = GL_TRUE;
state.stencil.write_mask = -1;
@ -135,50 +134,42 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource
return true;
}
bool TextureRuntime::CopyTextures(const OGLTexture& src_tex, Subresource src_subresource,
const OGLTexture& dst_tex, Subresource dst_subresource) {
bool TextureRuntime::CopyTextures(OGLTexture& source, OGLTexture& dest, const TextureCopy& copy) {
return true;
}
bool TextureRuntime::BlitTextures(const OGLTexture& src_tex, Subresource src_subresource,
const OGLTexture& dst_tex, Subresource dst_subresource,
bool dst_cube) {
bool TextureRuntime::BlitTextures(OGLTexture& source, OGLTexture& dest, const TextureBlit& blit) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state;
OpenGLState state{};
state.draw.read_framebuffer = read_fbo.handle;
state.draw.draw_framebuffer = draw_fbo.handle;
state.Apply();
auto BindAttachment =
[dst_cube, src_level = src_subresource.level, dst_level = dst_subresource.level,
dst_layer = dst_subresource.layer](GLenum target, u32 src_tex, u32 dst_tex) -> void {
GLenum dst_target = dst_cube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + dst_layer : GL_TEXTURE_2D;
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, target, GL_TEXTURE_2D, src_tex, src_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, target, dst_target, dst_tex, dst_level);
auto BindAttachment = [&blit](GLenum target, u32 src_tex, u32 dst_tex) -> void {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, target, GL_TEXTURE_2D, src_tex, blit.src_level);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, target, GL_TEXTURE_2D, dst_tex, blit.dst_level);
};
// Sanity check; Can't blit a color texture to a depth buffer
ASSERT(src_subresource.type == dst_subresource.type);
switch (src_subresource.type) {
switch (blit.surface_type) {
case SurfaceType::Color:
case SurfaceType::Texture:
case SurfaceType::Fill:
// Bind only color
BindAttachment(GL_COLOR_ATTACHMENT0, src_tex.handle, dst_tex.handle);
BindAttachment(GL_COLOR_ATTACHMENT0, source.handle, dest.handle);
BindAttachment(GL_DEPTH_STENCIL_ATTACHMENT, 0, 0);
break;
case SurfaceType::Depth:
// Bind only depth
BindAttachment(GL_COLOR_ATTACHMENT0, 0, 0);
BindAttachment(GL_DEPTH_ATTACHMENT, src_tex.handle, dst_tex.handle);
BindAttachment(GL_DEPTH_ATTACHMENT, source.handle, dest.handle);
BindAttachment(GL_STENCIL_ATTACHMENT, 0, 0);
break;
case SurfaceType::DepthStencil:
// Bind to combined depth + stencil
BindAttachment(GL_COLOR_ATTACHMENT0, 0, 0);
BindAttachment(GL_DEPTH_STENCIL_ATTACHMENT, src_tex.handle, dst_tex.handle);
BindAttachment(GL_DEPTH_STENCIL_ATTACHMENT, source.handle, dest.handle);
break;
default:
UNREACHABLE_MSG("Invalid surface type!");
@ -189,23 +180,23 @@ bool TextureRuntime::BlitTextures(const OGLTexture& src_tex, Subresource src_sub
// doing linear intepolation componentwise would cause incorrect value. However, for a
// well-programmed game this code path should be rarely executed for shadow map with
// inconsistent scale.
const GLbitfield buffer_mask = MakeBufferMask(src_subresource.type);
const GLbitfield buffer_mask = MakeBufferMask(blit.surface_type);
const GLenum filter = buffer_mask == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST;
const auto& src_rect = src_subresource.region;
const auto& dst_rect = dst_subresource.region;
glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left,
dst_rect.bottom, dst_rect.right, dst_rect.top,
glBlitFramebuffer(blit.src_region.start.x, blit.src_region.start.y,
blit.src_region.end.x, blit.src_region.end.y,
blit.dst_region.start.x, blit.dst_region.start.y,
blit.dst_region.end.x, blit.dst_region.end.y,
buffer_mask, filter);
return true;
}
void TextureRuntime::GenerateMipmaps(const OGLTexture& tex, u32 max_level) {
void TextureRuntime::GenerateMipmaps(OGLTexture& texture, u32 max_level) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state;
state.texture_units[0].texture_2d = tex.handle;
OpenGLState state{};
state.texture_units[0].texture_2d = texture.handle;
state.Apply();
glActiveTexture(GL_TEXTURE0);

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#pragma once
#include <span>
#include "video_core/rasterizer_cache/types.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
@ -19,26 +20,21 @@ public:
TextureRuntime();
~TextureRuntime() = default;
// Copies the GPU pixel data to the provided pixels buffer
void ReadTexture(const OGLTexture& tex, Subresource subresource, const FormatTuple& tuple,
u8* pixels);
/// Copies the GPU pixel data to the provided pixels buffer
void ReadTexture(OGLTexture& texture, const BufferTextureCopy& copy,
PixelFormat format, std::span<std::byte> pixels);
// Fills the rectangle of the texture with the clear value provided
bool ClearTexture(const OGLTexture& texture, Subresource subresource, ClearValue value);
/// Fills the rectangle of the texture with the clear value provided
bool ClearTexture(OGLTexture& texture, const ClearRect& rect, ClearValue value);
// Copies a rectangle of src_tex to another rectange of dst_rect
// NOTE: The width and height of the rectangles must be equal
bool CopyTextures(const OGLTexture& src_tex, Subresource src_subresource,
const OGLTexture& dst_tex, Subresource dst_subresource);
/// Copies a rectangle of src_tex to another rectange of dst_rect
bool CopyTextures(OGLTexture& source, OGLTexture& dest, const TextureCopy& copy);
// Copies a rectangle of src_tex to another rectange of dst_rect performing
// scaling and format conversions
bool BlitTextures(const OGLTexture& src_tex, Subresource src_subresource,
const OGLTexture& dst_tex, Subresource dst_subresource,
bool dst_cube = false);
/// Blits a rectangle of src_tex to another rectange of dst_rect
bool BlitTextures(OGLTexture& source, OGLTexture& dest, const TextureBlit& blit);
// Generates mipmaps for all the available levels of the texture
void GenerateMipmaps(const OGLTexture& tex, u32 max_level);
/// Generates mipmaps for all the available levels of the texture
void GenerateMipmaps(OGLTexture& texture, u32 max_level);
private:
OGLFramebuffer read_fbo, draw_fbo;

View File

@ -3,13 +3,40 @@
// Refer to the license.txt file included.
#pragma once
#include "common/math_util.h"
#include "common/common_types.h"
#include "common/vector_math.h"
#include "video_core/rasterizer_cache/pixel_format.h"
namespace OpenGL {
// A union for both color and depth/stencil clear values
struct Offset {
constexpr auto operator<=>(const Offset&) const noexcept = default;
u32 x = 0;
u32 y = 0;
};
struct Extent {
constexpr auto operator<=>(const Extent&) const noexcept = default;
u32 width = 1;
u32 height = 1;
};
struct Rect2D {
constexpr auto operator<=>(const Rect2D&) const noexcept = default;
Offset offset;
Extent extent;
};
struct Region2D {
constexpr auto operator<=>(const Region2D&) const noexcept = default;
Offset start;
Offset end;
};
union ClearValue {
Common::Vec4f color;
struct {
@ -18,13 +45,44 @@ union ClearValue {
};
};
struct Subresource {
auto operator<=>(const Subresource&) const = default;
struct ClearRect {
SurfaceType surface_type;
u32 texture_level;
Rect2D rect;
};
SurfaceType type;
Common::Rectangle<u32> region;
u32 level = 0;
u32 layer = 0;
struct TextureCopy {
SurfaceType surface_type;
u32 src_level;
u32 dst_level;
Offset src_offset;
Offset dst_offset;
Extent extent;
};
struct TextureBlit {
SurfaceType surface_type;
u32 src_level;
u32 dst_level;
Region2D src_region;
Region2D dst_region;
};
struct BufferTextureCopy {
u32 buffer_offset;
u32 buffer_size;
u32 buffer_row_length;
u32 buffer_height;
SurfaceType surface_type;
u32 texture_level;
Offset texture_offset;
Extent texture_extent;
};
struct BufferCopy {
u32 src_offset;
u32 dst_offset;
u32 size;
};
} // namespace OpenGL