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_rasterizer_cache.cpp53
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h4
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp146
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h132
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h1
5 files changed, 207 insertions, 129 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 57f501177..091d9f043 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -16,6 +16,7 @@
#include "core/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
+#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/utils.h"
#include "video_core/surface.h"
#include "video_core/textures/astc.h"
@@ -58,16 +59,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,
bool uncompressed) const {
- const u32 compression_factor{GetCompressionFactor(pixel_format)};
+ const u32 tile_x{GetDefaultBlockWidth(pixel_format)};
+ const u32 tile_y{GetDefaultBlockHeight(pixel_format)};
const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
u32 m_depth = (layer_only ? 1U : depth);
u32 m_width = MipWidth(mip_level);
u32 m_height = MipHeight(mip_level);
- m_width = uncompressed ? m_width
- : std::max(1U, (m_width + compression_factor - 1) / compression_factor);
- m_height = uncompressed
- ? m_height
- : std::max(1U, (m_height + compression_factor - 1) / compression_factor);
+ m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x);
+ m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);
m_depth = std::max(1U, m_depth >> mip_level);
u32 m_block_height = MipBlockHeight(mip_level);
u32 m_block_depth = MipBlockDepth(mip_level);
@@ -128,6 +127,13 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
params.target = SurfaceTarget::Texture2D;
}
break;
+ case SurfaceTarget::TextureCubeArray:
+ params.depth = config.tic.Depth() * 6;
+ if (!entry.IsArray()) {
+ ASSERT(params.depth == 6);
+ params.target = SurfaceTarget::TextureCubemap;
+ }
+ break;
default:
LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target));
UNREACHABLE();
@@ -305,6 +311,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
+ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5
+ {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
// Depth formats
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
@@ -334,6 +342,8 @@ static GLenum SurfaceTargetToGL(SurfaceTarget target) {
return GL_TEXTURE_2D_ARRAY;
case SurfaceTarget::TextureCubemap:
return GL_TEXTURE_CUBE_MAP;
+ case SurfaceTarget::TextureCubeArray:
+ return GL_TEXTURE_CUBE_MAP_ARRAY_ARB;
}
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
UNREACHABLE();
@@ -364,15 +374,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d
// With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
// pixel values.
- const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
+ const u32 tile_size_x{GetDefaultBlockWidth(format)};
+ const u32 tile_size_y{GetDefaultBlockHeight(format)};
if (morton_to_gl) {
- const std::vector<u8> data = Tegra::Texture::UnswizzleTexture(
- addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth);
+ const std::vector<u8> data =
+ Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel,
+ stride, height, depth, block_height, block_depth);
const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())};
memcpy(gl_buffer, data.data(), size_to_copy);
} else {
- Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth,
+ Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x,
+ (height + tile_size_y - 1) / tile_size_y, depth,
bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr),
gl_buffer, false, block_height, block_depth);
}
@@ -440,6 +453,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {
MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
+ MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
+ MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
MortonCopy<true, PixelFormat::Z32F>,
MortonCopy<true, PixelFormat::Z16>,
MortonCopy<true, PixelFormat::Z24S8>,
@@ -508,6 +523,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {
nullptr,
nullptr,
nullptr,
+ nullptr,
+ nullptr,
MortonCopy<false, PixelFormat::Z32F>,
MortonCopy<false, PixelFormat::Z16>,
MortonCopy<false, PixelFormat::Z24S8>,
@@ -754,6 +771,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
break;
case SurfaceTarget::Texture3D:
case SurfaceTarget::Texture2DArray:
+ case SurfaceTarget::TextureCubeArray:
glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height,
static_cast<GLsizei>(dst_params.depth), dest_format.format,
dest_format.type, nullptr);
@@ -806,6 +824,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
break;
case SurfaceTarget::Texture3D:
case SurfaceTarget::Texture2DArray:
+ case SurfaceTarget::TextureCubeArray:
glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level,
format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(),
params.depth);
@@ -897,21 +916,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
* typical desktop GPUs.
*/
static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
- u32 width, u32 height) {
+ u32 width, u32 height, u32 depth) {
switch (pixel_format) {
case PixelFormat::ASTC_2D_4X4:
case PixelFormat::ASTC_2D_8X8:
case PixelFormat::ASTC_2D_8X5:
case PixelFormat::ASTC_2D_5X4:
+ case PixelFormat::ASTC_2D_5X5:
case PixelFormat::ASTC_2D_4X4_SRGB:
case PixelFormat::ASTC_2D_8X8_SRGB:
case PixelFormat::ASTC_2D_8X5_SRGB:
- case PixelFormat::ASTC_2D_5X4_SRGB: {
+ case PixelFormat::ASTC_2D_5X4_SRGB:
+ case PixelFormat::ASTC_2D_5X5_SRGB: {
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
u32 block_width{};
u32 block_height{};
std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
- data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
+ data =
+ Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);
break;
}
case PixelFormat::S8Z24:
@@ -971,7 +993,7 @@ void CachedSurface::LoadGLBuffer() {
}
for (u32 i = 0; i < params.max_mip_level; i++)
ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i),
- params.MipHeight(i));
+ params.MipHeight(i), params.MipDepth(i));
}
MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
@@ -1055,6 +1077,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
&gl_buffer[mip_map][buffer_offset]);
break;
case SurfaceTarget::Texture2DArray:
+ case SurfaceTarget::TextureCubeArray:
glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
static_cast<GLsizei>(params.MipWidth(mip_map)),
static_cast<GLsizei>(params.MipHeight(mip_map)),
@@ -1104,6 +1127,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
break;
case SurfaceTarget::Texture2DArray:
+ case SurfaceTarget::TextureCubeArray:
glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
@@ -1307,6 +1331,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
case SurfaceTarget::TextureCubemap:
case SurfaceTarget::Texture3D:
case SurfaceTarget::Texture2DArray:
+ case SurfaceTarget::TextureCubeArray:
AccurateCopySurface(old_surface, new_surface);
break;
default:
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index f255f4419..c0b6bc4e6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -49,6 +49,8 @@ struct SurfaceParams {
return "Texture2DArray";
case SurfaceTarget::TextureCubemap:
return "TextureCubemap";
+ case SurfaceTarget::TextureCubeArray:
+ return "TextureCubeArray";
default:
LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
UNREACHABLE();
@@ -139,7 +141,7 @@ struct SurfaceParams {
}
u32 MipDepth(u32 mip_level) const {
- return std::max(1U, depth >> mip_level);
+ return is_layered ? depth : std::max(1U, depth >> mip_level);
}
// Auto block resizing algorithm from:
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
new file mode 100644
index 000000000..c10863337
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp
@@ -0,0 +1,146 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <utility>
+#include <glad/glad.h>
+#include "common/common_types.h"
+#include "video_core/renderer_opengl/gl_resource_manager.h"
+#include "video_core/renderer_opengl/gl_shader_util.h"
+#include "video_core/renderer_opengl/gl_state.h"
+
+namespace OpenGL {
+
+void OGLTexture::Create() {
+ if (handle != 0)
+ return;
+ glGenTextures(1, &handle);
+}
+
+void OGLTexture::Release() {
+ if (handle == 0)
+ return;
+ glDeleteTextures(1, &handle);
+ OpenGLState::GetCurState().UnbindTexture(handle).Apply();
+ handle = 0;
+}
+
+void OGLSampler::Create() {
+ if (handle != 0)
+ return;
+ glGenSamplers(1, &handle);
+}
+
+void OGLSampler::Release() {
+ if (handle == 0)
+ return;
+ glDeleteSamplers(1, &handle);
+ OpenGLState::GetCurState().ResetSampler(handle).Apply();
+ handle = 0;
+}
+
+void OGLShader::Create(const char* source, GLenum type) {
+ if (handle != 0)
+ return;
+ if (source == nullptr)
+ return;
+ handle = GLShader::LoadShader(source, type);
+}
+
+void OGLShader::Release() {
+ if (handle == 0)
+ return;
+ glDeleteShader(handle);
+ handle = 0;
+}
+
+void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shader,
+ const char* frag_shader, bool separable_program) {
+ OGLShader vert, geo, frag;
+ if (vert_shader)
+ vert.Create(vert_shader, GL_VERTEX_SHADER);
+ if (geo_shader)
+ geo.Create(geo_shader, GL_GEOMETRY_SHADER);
+ if (frag_shader)
+ frag.Create(frag_shader, GL_FRAGMENT_SHADER);
+ Create(separable_program, vert.handle, geo.handle, frag.handle);
+}
+
+void OGLProgram::Release() {
+ if (handle == 0)
+ return;
+ glDeleteProgram(handle);
+ OpenGLState::GetCurState().ResetProgram(handle).Apply();
+ handle = 0;
+}
+
+void OGLPipeline::Create() {
+ if (handle != 0)
+ return;
+ glGenProgramPipelines(1, &handle);
+}
+
+void OGLPipeline::Release() {
+ if (handle == 0)
+ return;
+ glDeleteProgramPipelines(1, &handle);
+ OpenGLState::GetCurState().ResetPipeline(handle).Apply();
+ handle = 0;
+}
+
+void OGLBuffer::Create() {
+ if (handle != 0)
+ return;
+ glGenBuffers(1, &handle);
+}
+
+void OGLBuffer::Release() {
+ if (handle == 0)
+ return;
+ glDeleteBuffers(1, &handle);
+ OpenGLState::GetCurState().ResetBuffer(handle).Apply();
+ handle = 0;
+}
+
+void OGLSync::Create() {
+ if (handle != 0)
+ return;
+ handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+void OGLSync::Release() {
+ if (handle == 0)
+ return;
+ glDeleteSync(handle);
+ handle = 0;
+}
+
+void OGLVertexArray::Create() {
+ if (handle != 0)
+ return;
+ glGenVertexArrays(1, &handle);
+}
+
+void OGLVertexArray::Release() {
+ if (handle == 0)
+ return;
+ glDeleteVertexArrays(1, &handle);
+ OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
+ handle = 0;
+}
+
+void OGLFramebuffer::Create() {
+ if (handle != 0)
+ return;
+ glGenFramebuffers(1, &handle);
+}
+
+void OGLFramebuffer::Release() {
+ if (handle == 0)
+ return;
+ glDeleteFramebuffers(1, &handle);
+ OpenGLState::GetCurState().ResetFramebuffer(handle).Apply();
+ handle = 0;
+}
+
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index 3bc1b83b5..e33f1e973 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -8,7 +8,6 @@
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
-#include "video_core/renderer_opengl/gl_state.h"
namespace OpenGL {
@@ -29,20 +28,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenTextures(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteTextures(1, &handle);
- OpenGLState::GetCurState().UnbindTexture(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -64,20 +53,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenSamplers(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteSamplers(1, &handle);
- OpenGLState::GetCurState().ResetSampler(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -98,20 +77,9 @@ public:
return *this;
}
- void Create(const char* source, GLenum type) {
- if (handle != 0)
- return;
- if (source == nullptr)
- return;
- handle = GLShader::LoadShader(source, type);
- }
+ void Create(const char* source, GLenum type);
- void Release() {
- if (handle == 0)
- return;
- glDeleteShader(handle);
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -141,25 +109,10 @@ public:
/// Creates a new internal OpenGL resource and stores the handle
void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader,
- bool separable_program = false) {
- OGLShader vert, geo, frag;
- if (vert_shader)
- vert.Create(vert_shader, GL_VERTEX_SHADER);
- if (geo_shader)
- geo.Create(geo_shader, GL_GEOMETRY_SHADER);
- if (frag_shader)
- frag.Create(frag_shader, GL_FRAGMENT_SHADER);
- Create(separable_program, vert.handle, geo.handle, frag.handle);
- }
+ bool separable_program = false);
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteProgram(handle);
- OpenGLState::GetCurState().ResetProgram(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -178,20 +131,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenProgramPipelines(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteProgramPipelines(1, &handle);
- OpenGLState::GetCurState().ResetPipeline(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -213,20 +156,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenBuffers(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteBuffers(1, &handle);
- OpenGLState::GetCurState().ResetBuffer(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -247,19 +180,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteSync(handle);
- handle = 0;
- }
+ void Release();
GLsync handle = 0;
};
@@ -281,20 +205,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenVertexArrays(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteVertexArrays(1, &handle);
- OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
@@ -316,20 +230,10 @@ public:
}
/// Creates a new internal OpenGL resource and stores the handle
- void Create() {
- if (handle != 0)
- return;
- glGenFramebuffers(1, &handle);
- }
+ void Create();
/// Deletes the internal OpenGL resource
- void Release() {
- if (handle == 0)
- return;
- glDeleteFramebuffers(1, &handle);
- OpenGLState::GetCurState().ResetFramebuffer(handle).Apply();
- handle = 0;
- }
+ void Release();
GLuint handle = 0;
};
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 36fe1f04c..2a069cdd8 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -7,6 +7,7 @@
#include <glad/glad.h>
#include "video_core/renderer_opengl/gl_resource_manager.h"
+#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/maxwell_to_gl.h"
namespace OpenGL::GLShader {