aboutsummaryrefslogtreecommitdiff
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_global_cache.cpp24
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.h60
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp14
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h10
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp73
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h32
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h4
8 files changed, 181 insertions, 42 deletions
diff --git a/src/video_core/renderer_opengl/gl_global_cache.cpp b/src/video_core/renderer_opengl/gl_global_cache.cpp
new file mode 100644
index 000000000..7992b82c4
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_global_cache.cpp
@@ -0,0 +1,24 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <glad/glad.h>
+
+#include "video_core/renderer_opengl/gl_global_cache.h"
+#include "video_core/renderer_opengl/gl_rasterizer.h"
+#include "video_core/renderer_opengl/utils.h"
+
+namespace OpenGL {
+
+CachedGlobalRegion::CachedGlobalRegion(VAddr addr, u32 size) : addr{addr}, size{size} {
+ buffer.Create();
+ // Bind and unbind the buffer so it gets allocated by the driver
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+ LabelGLObject(GL_BUFFER, buffer.handle, addr, "GlobalMemory");
+}
+
+GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer)
+ : RasterizerCache{rasterizer} {}
+
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_global_cache.h b/src/video_core/renderer_opengl/gl_global_cache.h
new file mode 100644
index 000000000..406a735bc
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_global_cache.h
@@ -0,0 +1,60 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <glad/glad.h>
+
+#include "common/common_types.h"
+#include "video_core/rasterizer_cache.h"
+#include "video_core/renderer_opengl/gl_resource_manager.h"
+
+namespace OpenGL {
+
+namespace GLShader {
+class GlobalMemoryEntry;
+} // namespace GLShader
+
+class RasterizerOpenGL;
+class CachedGlobalRegion;
+using GlobalRegion = std::shared_ptr<CachedGlobalRegion>;
+
+class CachedGlobalRegion final : public RasterizerCacheObject {
+public:
+ explicit CachedGlobalRegion(VAddr addr, u32 size);
+
+ /// Gets the address of the shader in guest memory, required for cache management
+ VAddr GetAddr() const {
+ return addr;
+ }
+
+ /// Gets the size of the shader in guest memory, required for cache management
+ std::size_t GetSizeInBytes() const {
+ return size;
+ }
+
+ /// Gets the GL program handle for the buffer
+ GLuint GetBufferHandle() const {
+ return buffer.handle;
+ }
+
+ // TODO(Rodrigo): When global memory is written (STG), implement flushing
+ void Flush() override {
+ UNIMPLEMENTED();
+ }
+
+private:
+ VAddr addr{};
+ u32 size{};
+
+ OGLBuffer buffer;
+};
+
+class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> {
+public:
+ explicit GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer);
+};
+
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 2b29fc45f..73567eb8c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -101,7 +101,7 @@ struct FramebufferCacheKey {
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info)
: res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info},
- buffer_cache(*this, STREAM_BUFFER_SIZE) {
+ buffer_cache(*this, STREAM_BUFFER_SIZE), global_cache{*this} {
// Create sampler objects
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
@@ -293,7 +293,7 @@ DrawParameters RasterizerOpenGL::SetupDraw() {
void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
MICROPROFILE_SCOPE(OpenGL_Shader);
- const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
+ auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
// Next available bindpoints to use when uploading the const buffers and textures to the GLSL
// shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
@@ -376,6 +376,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
}
SyncClipEnabled(clip_distances);
+
+ gpu.dirty_flags.shaders = false;
}
void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey,
@@ -761,6 +763,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
res_cache.InvalidateRegion(addr, size);
shader_cache.InvalidateRegion(addr, size);
+ global_cache.InvalidateRegion(addr, size);
buffer_cache.InvalidateRegion(addr, size);
}
@@ -1014,8 +1017,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
Surface surface = res_cache.GetTextureSurface(texture, entry);
if (surface != nullptr) {
- state.texture_units[current_bindpoint].texture = surface->Texture().handle;
- state.texture_units[current_bindpoint].target = surface->Target();
+ const GLuint handle =
+ entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
+ const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
+ state.texture_units[current_bindpoint].texture = handle;
+ state.texture_units[current_bindpoint].target = target;
state.texture_units[current_bindpoint].swizzle.r =
MaxwellToGL::SwizzleSource(texture.tic.x_source);
state.texture_units[current_bindpoint].swizzle.g =
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 8a891ffc7..a53edee6d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -23,6 +23,7 @@
#include "video_core/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
+#include "video_core/renderer_opengl/gl_global_cache.h"
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
@@ -66,6 +67,10 @@ public:
static_assert(MaxConstbufferSize % sizeof(GLvec4) == 0,
"The maximum size of a constbuffer must be a multiple of the size of GLvec4");
+ static constexpr std::size_t MaxGlobalMemorySize = 0x10000;
+ static_assert(MaxGlobalMemorySize % sizeof(float) == 0,
+ "The maximum size of a global memory must be a multiple of the size of float");
+
private:
class SamplerInfo {
public:
@@ -105,7 +110,7 @@ private:
bool using_depth_fb = true, bool preserve_contents = true,
std::optional<std::size_t> single_color_target = {});
- /*
+ /**
* Configures the current constbuffers to use for the draw command.
* @param stage The shader stage to configure buffers for.
* @param shader The shader object that contains the specified stage.
@@ -115,7 +120,7 @@ private:
u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
GLenum primitive_mode, u32 current_bindpoint);
- /*
+ /**
* Configures the current textures to use for the draw command.
* @param stage The shader stage to configure textures for.
* @param shader The shader object that contains the specified stage.
@@ -185,6 +190,7 @@ private:
RasterizerCacheOpenGL res_cache;
ShaderCacheOpenGL shader_cache;
+ GlobalRegionCacheOpenGL global_cache;
Core::Frontend::EmuWindow& emu_window;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 7ea07631a..bff0c65cd 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -44,6 +44,17 @@ struct FormatTuple {
bool compressed;
};
+static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1);
+ if (max_mip_level == 1) {
+ glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0);
+ }
+}
+
void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
@@ -288,8 +299,6 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
{GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::Float,
true}, // BC6H_SF16
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
- {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8U
- {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // G8R8S
{GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8
{GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F
{GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F
@@ -443,7 +452,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
const std::size_t buffer_size = std::max(src_params.size_in_bytes, dst_params.size_in_bytes);
glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo_handle);
- glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW);
+ glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_COPY);
if (source_format.compressed) {
glGetCompressedTextureImage(src_surface->Texture().handle, src_attachment,
static_cast<GLsizei>(src_params.size_in_bytes), nullptr);
@@ -532,6 +541,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
glActiveTexture(GL_TEXTURE0);
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
+ gl_internal_format = format_tuple.internal_format;
+ gl_is_compressed = format_tuple.compressed;
+
if (!format_tuple.compressed) {
// Only pre-create the texture for non-compressed textures.
switch (params.target) {
@@ -560,15 +572,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
}
}
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL,
- params.max_mip_level - 1);
- if (params.max_mip_level == 1) {
- glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0);
- }
+ ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level);
LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
SurfaceParams::SurfaceTargetName(params.target));
@@ -620,18 +624,6 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bo
}
}
-static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
- constexpr auto bpp{GetBytesPerPixel(PixelFormat::G8R8U)};
- for (std::size_t y = 0; y < height; ++y) {
- for (std::size_t x = 0; x < width; ++x) {
- const std::size_t offset{bpp * (y * width + x)};
- const u8 temp{data[offset]};
- data[offset] = data[offset + 1];
- data[offset + 1] = temp;
- }
- }
-}
-
/**
* Helper function to perform software conversion (as needed) when loading a buffer from Switch
* memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with
@@ -664,12 +656,6 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
// Convert the S8Z24 depth format to Z24S8, as OpenGL does not support S8Z24.
ConvertS8Z24ToZ24S8(data, width, height, false);
break;
-
- case PixelFormat::G8R8U:
- case PixelFormat::G8R8S:
- // Convert the G8R8 color format to R8G8, as OpenGL does not support G8R8.
- ConvertG8R8ToR8G8(data, width, height);
- break;
}
}
@@ -681,8 +667,6 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
u32 width, u32 height) {
switch (pixel_format) {
- case PixelFormat::G8R8U:
- case PixelFormat::G8R8S:
case PixelFormat::ASTC_2D_4X4:
case PixelFormat::ASTC_2D_8X8:
case PixelFormat::ASTC_2D_4X4_SRGB:
@@ -886,6 +870,31 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
+void CachedSurface::EnsureTextureView() {
+ if (texture_view.handle != 0)
+ return;
+ // Compressed texture are not being created with immutable storage
+ UNIMPLEMENTED_IF(gl_is_compressed);
+
+ const GLenum target{TargetLayer()};
+
+ texture_view.Create();
+ glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0,
+ params.max_mip_level, 0, 1);
+
+ OpenGLState cur_state = OpenGLState::GetCurState();
+ const auto& old_tex = cur_state.texture_units[0];
+ SCOPE_EXIT({
+ cur_state.texture_units[0] = old_tex;
+ cur_state.Apply();
+ });
+ cur_state.texture_units[0].texture = texture_view.handle;
+ cur_state.texture_units[0].target = target;
+ cur_state.Apply();
+
+ ApplyTextureDefaults(target, params.max_mip_level);
+}
+
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
if (params.type == SurfaceType::Fill)
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index c710aa245..7223700c4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -293,10 +293,31 @@ public:
return texture;
}
+ const OGLTexture& TextureLayer() {
+ if (params.is_layered) {
+ return Texture();
+ }
+ EnsureTextureView();
+ return texture_view;
+ }
+
GLenum Target() const {
return gl_target;
}
+ GLenum TargetLayer() const {
+ using VideoCore::Surface::SurfaceTarget;
+ switch (params.target) {
+ case SurfaceTarget::Texture1D:
+ return GL_TEXTURE_1D_ARRAY;
+ case SurfaceTarget::Texture2D:
+ return GL_TEXTURE_2D_ARRAY;
+ case SurfaceTarget::TextureCubemap:
+ return GL_TEXTURE_CUBE_MAP_ARRAY;
+ }
+ return Target();
+ }
+
const SurfaceParams& GetSurfaceParams() const {
return params;
}
@@ -311,11 +332,16 @@ public:
private:
void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
+ void EnsureTextureView();
+
OGLTexture texture;
+ OGLTexture texture_view;
std::vector<std::vector<u8>> gl_buffer;
- SurfaceParams params;
- GLenum gl_target;
- std::size_t cached_size_in_bytes;
+ SurfaceParams params{};
+ GLenum gl_target{};
+ GLenum gl_internal_format{};
+ bool gl_is_compressed{};
+ std::size_t cached_size_in_bytes{};
};
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index aea6bf1af..c785fffa3 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -188,6 +188,10 @@ void CachedShader::CalculateProperties() {
ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {}
Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
+ if (!Core::System::GetInstance().GPU().Maxwell3D().dirty_flags.shaders) {
+ return last_shaders[static_cast<u32>(program)];
+ }
+
const VAddr program_addr{GetShaderAddress(program)};
// Look up shader in the cache based on address
@@ -199,7 +203,7 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
Register(shader);
}
- return shader;
+ return last_shaders[static_cast<u32>(program)] = shader;
}
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index de3671acf..768747968 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -4,6 +4,7 @@
#pragma once
+#include <array>
#include <map>
#include <memory>
@@ -115,6 +116,9 @@ public:
/// Gets the current specified shader stage program
Shader GetStageProgram(Maxwell::ShaderProgram program);
+
+private:
+ std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
};
} // namespace OpenGL