summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp103
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h27
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h1
3 files changed, 87 insertions, 44 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);
}
}
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 1bb762568..37d5e6a6b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -52,17 +52,17 @@ struct FormatProperties {
bool is_compressed;
};
-class BGRCopyPass {
+class FormatConversionPass {
public:
- BGRCopyPass() = default;
- ~BGRCopyPass() = default;
+ FormatConversionPass() = default;
+ ~FormatConversionPass() = default;
- void CopyBGR(Image& dst_image, Image& src_image,
- std::span<const VideoCommon::ImageCopy> copies);
+ void ConvertImage(Image& dst_image, Image& src_image,
+ std::span<const VideoCommon::ImageCopy> copies);
private:
- OGLBuffer bgr_pbo;
- size_t bgr_pbo_size{};
+ OGLBuffer intermediate_pbo;
+ size_t pbo_size{};
};
class TextureCacheRuntime {
@@ -84,8 +84,14 @@ public:
u64 GetDeviceLocalMemory() const;
+ bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) {
+ return true;
+ }
+
void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
+ void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
+
void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) {
UNIMPLEMENTED();
}
@@ -144,7 +150,7 @@ private:
const Device& device;
StateTracker& state_tracker;
UtilShaders util_shaders;
- BGRCopyPass bgr_copy_pass;
+ FormatConversionPass format_conversion_pass;
std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties;
bool has_broken_texture_view_formats = false;
@@ -162,8 +168,8 @@ private:
std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{};
- std::array<OGLFramebuffer, 3> rescale_draw_fbos;
- std::array<OGLFramebuffer, 3> rescale_read_fbos;
+ std::array<OGLFramebuffer, 4> rescale_draw_fbos;
+ std::array<OGLFramebuffer, 4> rescale_read_fbos;
const Settings::ResolutionScalingInfo& resolution;
};
@@ -219,6 +225,7 @@ private:
GLenum gl_internal_format = GL_NONE;
GLenum gl_format = GL_NONE;
GLenum gl_type = GL_NONE;
+ GLsizei gl_num_levels{};
TextureCacheRuntime* runtime{};
GLuint current_texture{};
};
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 39158aa3e..daba42ed9 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -108,6 +108,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB
{GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT
{GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM
+ {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM
{GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,