summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_texture_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_texture_cache.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp103
1 files changed, 69 insertions, 34 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 2f7d98d8b..14e6522f2 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -9,6 +9,7 @@
#include <glad/glad.h>
+#include "common/bit_util.h"
#include "common/literals.h"
#include "common/settings.h"
#include "video_core/renderer_opengl/gl_device.h"
@@ -148,6 +149,8 @@ GLenum AttachmentType(PixelFormat format) {
switch (const SurfaceType type = VideoCore::Surface::GetFormatType(format); type) {
case SurfaceType::Depth:
return GL_DEPTH_ATTACHMENT;
+ case SurfaceType::Stencil:
+ return GL_STENCIL_ATTACHMENT;
case SurfaceType::DepthStencil:
return GL_DEPTH_STENCIL_ATTACHMENT;
default:
@@ -317,13 +320,12 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
}
}
-OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format) {
+OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format,
+ GLsizei gl_num_levels) {
const GLenum target = ImageTarget(info);
const GLsizei width = info.size.width;
const GLsizei height = info.size.height;
const GLsizei depth = info.size.depth;
- const int max_host_mip_levels = std::bit_width(info.size.width);
- const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels);
const GLsizei num_layers = info.resources.layers;
const GLsizei num_samples = info.num_samples;
@@ -335,10 +337,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
}
switch (target) {
case GL_TEXTURE_1D_ARRAY:
- glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers);
+ glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, num_layers);
break;
case GL_TEXTURE_2D_ARRAY:
- glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers);
+ glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, num_layers);
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
// TODO: Where should 'fixedsamplelocations' come from?
@@ -348,10 +350,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
break;
}
case GL_TEXTURE_RECTANGLE:
- glTextureStorage2D(handle, num_levels, gl_internal_format, width, height);
+ glTextureStorage2D(handle, gl_num_levels, gl_internal_format, width, height);
break;
case GL_TEXTURE_3D:
- glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth);
+ glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, depth);
break;
case GL_TEXTURE_BUFFER:
UNREACHABLE();
@@ -396,6 +398,7 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
UNREACHABLE_MSG("Invalid image format={}", format);
return GL_R32UI;
}
+
} // Anonymous namespace
ImageBufferMap::~ImageBufferMap() {
@@ -522,6 +525,12 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image,
}
}
+void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
+ std::span<const VideoCommon::ImageCopy> copies) {
+ LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format);
+ format_conversion_pass.ConvertImage(dst, src, copies);
+}
+
bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) {
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
return false;
@@ -538,7 +547,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src,
ASSERT(src.info.type == ImageType::e3D);
util_shaders.CopyBC4(dst, src, copies);
} else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
- bgr_copy_pass.CopyBGR(dst, src, copies);
+ format_conversion_pass.ConvertImage(dst, src, copies);
} else {
UNREACHABLE();
}
@@ -686,7 +695,9 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
gl_format = tuple.format;
gl_type = tuple.type;
}
- texture = MakeImage(info, gl_internal_format);
+ const int max_host_mip_levels = std::bit_width(info.size.width);
+ gl_num_levels = std::min(info.resources.levels, max_host_mip_levels);
+ texture = MakeImage(info, gl_internal_format, gl_num_levels);
current_texture = texture.handle;
if (runtime->device.HasDebuggingToolAttached()) {
const std::string name = VideoCommon::Name(*this);
@@ -714,6 +725,9 @@ void Image::UploadMemory(const ImageBufferMap& map,
u32 current_image_height = std::numeric_limits<u32>::max();
for (const VideoCommon::BufferImageCopy& copy : copies) {
+ if (copy.image_subresource.base_level >= gl_num_levels) {
+ continue;
+ }
if (current_row_length != copy.buffer_row_length) {
current_row_length = copy.buffer_row_length;
glPixelStorei(GL_UNPACK_ROW_LENGTH, current_row_length);
@@ -743,6 +757,9 @@ void Image::DownloadMemory(ImageBufferMap& map,
u32 current_image_height = std::numeric_limits<u32>::max();
for (const VideoCommon::BufferImageCopy& copy : copies) {
+ if (copy.image_subresource.base_level >= gl_num_levels) {
+ continue;
+ }
if (current_row_length != copy.buffer_row_length) {
current_row_length = copy.buffer_row_length;
glPixelStorei(GL_PACK_ROW_LENGTH, current_row_length);
@@ -782,7 +799,7 @@ GLuint Image::StorageHandle() noexcept {
}
store_view.Create();
glTextureView(store_view.handle, ImageTarget(info), current_texture, GL_RGBA8, 0,
- info.resources.levels, 0, info.resources.layers);
+ gl_num_levels, 0, info.resources.layers);
return store_view.handle;
default:
return current_texture;
@@ -897,6 +914,8 @@ void Image::Scale(bool up_scale) {
return GL_COLOR_ATTACHMENT0;
case SurfaceType::Depth:
return GL_DEPTH_ATTACHMENT;
+ case SurfaceType::Stencil:
+ return GL_STENCIL_ATTACHMENT;
case SurfaceType::DepthStencil:
return GL_DEPTH_STENCIL_ATTACHMENT;
default:
@@ -910,8 +929,10 @@ void Image::Scale(bool up_scale) {
return GL_COLOR_BUFFER_BIT;
case SurfaceType::Depth:
return GL_DEPTH_BUFFER_BIT;
+ case SurfaceType::Stencil:
+ return GL_STENCIL_BUFFER_BIT;
case SurfaceType::DepthStencil:
- return GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
default:
UNREACHABLE();
return GL_COLOR_BUFFER_BIT;
@@ -923,8 +944,10 @@ void Image::Scale(bool up_scale) {
return 0;
case SurfaceType::Depth:
return 1;
- case SurfaceType::DepthStencil:
+ case SurfaceType::Stencil:
return 2;
+ case SurfaceType::DepthStencil:
+ return 3;
default:
UNREACHABLE();
return 0;
@@ -946,7 +969,7 @@ void Image::Scale(bool up_scale) {
auto dst_info = info;
dst_info.size.width = scaled_width;
dst_info.size.height = scaled_height;
- upscaled_backup = MakeImage(dst_info, gl_internal_format);
+ upscaled_backup = MakeImage(dst_info, gl_internal_format, gl_num_levels);
}
const u32 src_width = up_scale ? original_width : scaled_width;
const u32 src_height = up_scale ? original_height : scaled_height;
@@ -1254,10 +1277,20 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
}
if (const ImageView* const image_view = depth_buffer; image_view) {
- if (GetFormatType(image_view->format) == SurfaceType::DepthStencil) {
+ switch (GetFormatType(image_view->format)) {
+ case SurfaceType::Depth:
+ buffer_bits |= GL_DEPTH_BUFFER_BIT;
+ break;
+ case SurfaceType::Stencil:
+ buffer_bits |= GL_STENCIL_BUFFER_BIT;
+ break;
+ case SurfaceType::DepthStencil:
buffer_bits |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
- } else {
+ break;
+ default:
+ UNREACHABLE();
buffer_bits |= GL_DEPTH_BUFFER_BIT;
+ break;
}
const GLenum attachment = AttachmentType(image_view->format);
AttachTexture(handle, attachment, image_view);
@@ -1286,35 +1319,37 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
Framebuffer::~Framebuffer() = default;
-void BGRCopyPass::CopyBGR(Image& dst_image, Image& src_image,
- std::span<const VideoCommon::ImageCopy> copies) {
- static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0};
+void FormatConversionPass::ConvertImage(Image& dst_image, Image& src_image,
+ std::span<const VideoCommon::ImageCopy> copies) {
+ const GLenum dst_target = ImageTarget(dst_image.info);
+ const GLenum src_target = ImageTarget(src_image.info);
const u32 img_bpp = BytesPerBlock(src_image.info.format);
for (const ImageCopy& copy : copies) {
- ASSERT(copy.src_offset == zero_offset);
- ASSERT(copy.dst_offset == zero_offset);
- const u32 num_src_layers = static_cast<u32>(copy.src_subresource.num_layers);
- const u32 copy_size = copy.extent.width * copy.extent.height * num_src_layers * img_bpp;
- if (bgr_pbo_size < copy_size) {
- bgr_pbo.Create();
- bgr_pbo_size = copy_size;
- glNamedBufferData(bgr_pbo.handle, bgr_pbo_size, nullptr, GL_STREAM_COPY);
+ const auto src_origin = MakeCopyOrigin(copy.src_offset, copy.src_subresource, src_target);
+ const auto dst_origin = MakeCopyOrigin(copy.dst_offset, copy.dst_subresource, dst_target);
+ const auto region = MakeCopyRegion(copy.extent, copy.dst_subresource, dst_target);
+ const u32 copy_size = region.width * region.height * region.depth * img_bpp;
+ if (pbo_size < copy_size) {
+ intermediate_pbo.Create();
+ pbo_size = Common::NextPow2(copy_size);
+ glNamedBufferData(intermediate_pbo.handle, pbo_size, nullptr, GL_STREAM_COPY);
}
// Copy from source to PBO
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width);
- glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr_pbo.handle);
- glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
- num_src_layers, src_image.GlFormat(), src_image.GlType(),
- static_cast<GLsizei>(bgr_pbo_size), nullptr);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, intermediate_pbo.handle);
+ glGetTextureSubImage(src_image.Handle(), src_origin.level, src_origin.x, src_origin.y,
+ src_origin.z, region.width, region.height, region.depth,
+ src_image.GlFormat(), src_image.GlType(),
+ static_cast<GLsizei>(pbo_size), nullptr);
// Copy from PBO to destination in desired GL format
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr_pbo.handle);
- glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
- copy.dst_subresource.num_layers, dst_image.GlFormat(),
- dst_image.GlType(), nullptr);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, intermediate_pbo.handle);
+ glTextureSubImage3D(dst_image.Handle(), dst_origin.level, dst_origin.x, dst_origin.y,
+ dst_origin.z, region.width, region.height, region.depth,
+ dst_image.GlFormat(), dst_image.GlType(), nullptr);
}
}