summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2019-05-07 16:57:16 +0200
committerReinUsesLisp <reinuseslisp@airmail.cc>2019-06-21 02:36:12 +0200
commitbc930754cc9437ddd86e7d246b3eb4302540896a (patch)
tree75e56e5e041db7b327a13c25ab13bc524458dc29 /src/video_core/renderer_opengl
parentCorrect Surface Base and Views for new Texture Cache (diff)
downloadyuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar.gz
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar.bz2
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar.lz
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar.xz
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.tar.zst
yuzu-bc930754cc9437ddd86e7d246b3eb4302540896a.zip
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp69
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp286
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h111
-rw-r--r--src/video_core/renderer_opengl/utils.cpp23
-rw-r--r--src/video_core/renderer_opengl/utils.h6
5 files changed, 202 insertions, 293 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 027e9d293..482d0428c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -83,10 +83,10 @@ struct FramebufferCacheKey {
bool stencil_enable = false;
std::array<GLenum, Maxwell::NumRenderTargets> color_attachments{};
- std::array<CachedSurfaceView*, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
+ std::array<View, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
u32 colors_count = 0;
- CachedSurfaceView* zeta = nullptr;
+ View zeta = nullptr;
auto Tie() const {
return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count,
@@ -115,6 +115,10 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
RasterizerOpenGL::~RasterizerOpenGL() {}
+void RasterizerOpenGL::InitMemoryMananger(Tegra::MemoryManager& memory_manager) {
+ texture_cache.InitMemoryMananger(memory_manager);
+}
+
void RasterizerOpenGL::CheckExtensions() {
if (!GLAD_GL_ARB_texture_filter_anisotropic && !GLAD_GL_EXT_texture_filter_anisotropic) {
LOG_WARNING(
@@ -474,9 +478,11 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
}
current_framebuffer_config_state = fb_config_state;
- CachedSurfaceView* depth_surface{};
+ View depth_surface{};
if (using_depth_fb) {
depth_surface = texture_cache.GetDepthBufferSurface(preserve_contents);
+ } else {
+ texture_cache.SetEmptyDepthBuffer();
}
UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0);
@@ -489,38 +495,41 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
if (using_color_fb) {
if (single_color_target) {
// Used when just a single color attachment is enabled, e.g. for clearing a color buffer
- CachedSurfaceView* color_surface{
+ View color_surface{
texture_cache.GetColorBufferSurface(*single_color_target, preserve_contents)};
if (color_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even if
// the shader doesn't actually write to it.
- color_surface->MarkAsModified(true);
+ texture_cache.MarkColorBufferInUse(*single_color_target);
// Workaround for and issue in nvidia drivers
// https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
- state.framebuffer_srgb.enabled |=
- color_surface->GetSurfaceParams().GetSrgbConversion();
+ state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;
}
fbkey.is_single_buffer = true;
fbkey.color_attachments[0] =
GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target);
fbkey.colors[0] = color_surface;
+ for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
+ if (index != *single_color_target) {
+ texture_cache.SetEmptyColorBuffer(index);
+ }
+ }
} else {
// Multiple color attachments are enabled
for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
- CachedSurfaceView* color_surface{
- texture_cache.GetColorBufferSurface(index, preserve_contents)};
+ View color_surface{texture_cache.GetColorBufferSurface(index, preserve_contents)};
if (color_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even
// if the shader doesn't actually write to it.
- color_surface->MarkAsModified(true);
+ texture_cache.MarkColorBufferInUse(index);
// Enable sRGB only for supported formats
// Workaround for and issue in nvidia drivers
// https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
state.framebuffer_srgb.enabled |=
- color_surface->GetSurfaceParams().GetSrgbConversion();
+ color_surface->GetSurfaceParams().srgb_conversion;
}
fbkey.color_attachments[index] =
@@ -538,11 +547,11 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
if (depth_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even if
// the shader doesn't actually write to it.
- depth_surface->MarkAsModified(true);
+ texture_cache.MarkDepthBufferInUse();
fbkey.zeta = depth_surface;
- fbkey.stencil_enable = regs.stencil_enable && depth_surface->GetSurfaceParams().GetType() ==
- SurfaceType::DepthStencil;
+ fbkey.stencil_enable = regs.stencil_enable &&
+ depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
}
SetupCachedFramebuffer(fbkey, current_state);
@@ -728,11 +737,27 @@ void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) {
buffer_cache.InvalidateRegion(addr, size);
}
+void RasterizerOpenGL::InvalidateRegionEx(GPUVAddr gpu_addr, CacheAddr addr, u64 size) {
+ MICROPROFILE_SCOPE(OpenGL_CacheManagement);
+ if (!addr || !size) {
+ return;
+ }
+ texture_cache.InvalidateRegionEx(gpu_addr, size);
+ shader_cache.InvalidateRegion(addr, size);
+ global_cache.InvalidateRegion(addr, size);
+ buffer_cache.InvalidateRegion(addr, size);
+}
+
void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
FlushRegion(addr, size);
InvalidateRegion(addr, size);
}
+void RasterizerOpenGL::FlushAndInvalidateRegionEx(GPUVAddr gpu_addr, CacheAddr addr, u64 size) {
+ FlushRegion(addr, size);
+ InvalidateRegionEx(gpu_addr, addr, size);
+}
+
bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
const Tegra::Engines::Fermi2D::Regs::Surface& dst,
const Common::Rectangle<u32>& src_rect,
@@ -740,7 +765,7 @@ bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs
MICROPROFILE_SCOPE(OpenGL_Blits);
const auto src_surface{texture_cache.GetFermiSurface(src)};
const auto dst_surface{texture_cache.GetFermiSurface(dst)};
- blitter.Blit(src_surface, dst_surface, src_rect, dst_rect);
+ // blitter.Blit(src_surface, dst_surface, src_rect, dst_rect);
return true;
}
@@ -762,10 +787,10 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
const auto& params{surface->GetSurfaceParams()};
const auto& pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(config.pixel_format)};
- ASSERT_MSG(params.GetWidth() == config.width, "Framebuffer width is different");
- ASSERT_MSG(params.GetHeight() == config.height, "Framebuffer height is different");
+ ASSERT_MSG(params.width == config.width, "Framebuffer width is different");
+ ASSERT_MSG(params.height == config.height, "Framebuffer height is different");
- if (params.GetPixelFormat() != pixel_format) {
+ if (params.pixel_format != pixel_format) {
LOG_WARNING(Render_OpenGL, "Framebuffer pixel_format is different");
}
@@ -860,10 +885,10 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s
state.texture_units[current_bindpoint].sampler = sampler_cache.GetSampler(texture.tsc);
- if (const auto surface{texture_cache.GetTextureSurface(texture)}; surface) {
- state.texture_units[current_bindpoint].texture = surface->GetTexture(
- entry.GetType(), entry.IsArray(), texture.tic.x_source, texture.tic.y_source,
- texture.tic.z_source, texture.tic.w_source);
+ if (const auto view{texture_cache.GetTextureSurface(texture, entry)}; view) {
+ view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
+ texture.tic.w_source);
+ state.texture_units[current_bindpoint].texture = view->GetTexture();
} else {
// Can occur when texture addr is null or its memory is unmapped/invalid
state.texture_units[current_bindpoint].texture = 0;
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index f7c2f46aa..871608f6d 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -4,7 +4,9 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "core/core.h"
#include "video_core/morton.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_texture_cache.h"
@@ -22,6 +24,9 @@ using VideoCore::Surface::ComponentType;
using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::SurfaceTarget;
+MICROPROFILE_DEFINE(OpenGL_Texture_Upload, "OpenGL", "Texture Upload", MP_RGB(128, 192, 128));
+MICROPROFILE_DEFINE(OpenGL_Texture_Download, "OpenGL", "Texture Download", MP_RGB(128, 192, 128));
+
namespace {
struct FormatTuple {
@@ -129,8 +134,8 @@ const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType compon
return format;
}
-GLenum GetTextureTarget(const SurfaceParams& params) {
- switch (params.GetTarget()) {
+GLenum GetTextureTarget(const SurfaceTarget& target) {
+ switch (target) {
case SurfaceTarget::Texture1D:
return GL_TEXTURE_1D;
case SurfaceTarget::Texture2D:
@@ -175,8 +180,8 @@ void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, params.GetNumLevels() - 1);
- if (params.GetNumLevels() == 1) {
+ glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, params.num_levels - 1);
+ if (params.num_levels == 1) {
glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0f);
}
}
@@ -185,21 +190,20 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
OGLTexture texture;
texture.Create(target);
- switch (params.GetTarget()) {
+ switch (params.target) {
case SurfaceTarget::Texture1D:
- glTextureStorage1D(texture.handle, params.GetNumLevels(), internal_format,
- params.GetWidth());
+ glTextureStorage1D(texture.handle, params.num_levels, internal_format, params.width);
break;
case SurfaceTarget::Texture2D:
case SurfaceTarget::TextureCubemap:
- glTextureStorage2D(texture.handle, params.GetNumLevels(), internal_format,
- params.GetWidth(), params.GetHeight());
+ glTextureStorage2D(texture.handle, params.num_levels, internal_format, params.width,
+ params.height);
break;
case SurfaceTarget::Texture3D:
case SurfaceTarget::Texture2DArray:
case SurfaceTarget::TextureCubeArray:
- glTextureStorage3D(texture.handle, params.GetNumLevels(), internal_format,
- params.GetWidth(), params.GetHeight(), params.GetDepth());
+ glTextureStorage3D(texture.handle, params.num_levels, internal_format, params.width,
+ params.height, params.depth);
break;
default:
UNREACHABLE();
@@ -212,54 +216,72 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
} // Anonymous namespace
-CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params)
- : VideoCommon::SurfaceBase<TextureCacheOpenGL, CachedSurfaceView>{texture_cache, params} {
- const auto& tuple{GetFormatTuple(params.GetPixelFormat(), params.GetComponentType())};
+CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params)
+ : VideoCommon::SurfaceBase<View>(gpu_addr, params) {
+ const auto& tuple{GetFormatTuple(params.pixel_format, params.component_type)};
internal_format = tuple.internal_format;
format = tuple.format;
type = tuple.type;
is_compressed = tuple.compressed;
- target = GetTextureTarget(params);
+ target = GetTextureTarget(params.target);
texture = CreateTexture(params, target, internal_format);
+ DecorateSurfaceName();
+ ViewParams main{};
+ main.num_levels = params.num_levels;
+ main.base_level = 0;
+ main.base_layer = 0;
+ main.num_layers = params.is_layered ? params.depth : 1;
+ main.target = params.target;
+ main_view = CreateView(main);
+ main_view->DecorateViewName(gpu_addr, params.TargetName() + "V:" + std::to_string(view_count++));
+}
+
+CachedSurface::~CachedSurface() {
+ views.clear();
+ main_view = nullptr;
}
-CachedSurface::~CachedSurface() = default;
+void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) {
+ LOG_CRITICAL(Render_OpenGL, "Flushing");
+ MICROPROFILE_SCOPE(OpenGL_Texture_Download);
-void CachedSurface::DownloadTexture() {
// TODO(Rodrigo): Optimize alignment
glPixelStorei(GL_PACK_ALIGNMENT, 1);
SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); });
- for (u32 level = 0; level < params.GetNumLevels(); ++level) {
+ for (u32 level = 0; level < params.num_levels; ++level) {
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
+ const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level);
if (is_compressed) {
glGetCompressedTextureImage(texture.handle, level,
static_cast<GLsizei>(params.GetHostMipmapSize(level)),
- GetStagingBufferLevelData(level));
+ staging_buffer.data() + mip_offset);
} else {
glGetTextureImage(texture.handle, level, format, type,
static_cast<GLsizei>(params.GetHostMipmapSize(level)),
- GetStagingBufferLevelData(level));
+ staging_buffer.data() + mip_offset);
}
}
}
-void CachedSurface::UploadTexture() {
+void CachedSurface::UploadTexture(std::vector<u8>& staging_buffer) {
+ MICROPROFILE_SCOPE(OpenGL_Texture_Upload);
SCOPE_EXIT({ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); });
- for (u32 level = 0; level < params.GetNumLevels(); ++level) {
- UploadTextureMipmap(level);
+ for (u32 level = 0; level < params.num_levels; ++level) {
+ UploadTextureMipmap(level, staging_buffer);
}
}
-void CachedSurface::UploadTextureMipmap(u32 level) {
+void CachedSurface::UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer) {
// TODO(Rodrigo): Optimize alignment
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level)));
- u8* buffer{GetStagingBufferLevelData(level)};
+ const std::size_t mip_offset = params.GetHostMipmapLevelOffset(level);
+ u8* buffer{staging_buffer.data() + mip_offset};
if (is_compressed) {
const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))};
- switch (params.GetTarget()) {
+ switch (params.target) {
case SurfaceTarget::Texture2D:
glCompressedTextureSubImage2D(texture.handle, level, 0, 0,
static_cast<GLsizei>(params.GetMipWidth(level)),
@@ -277,7 +299,7 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
break;
case SurfaceTarget::TextureCubemap: {
const std::size_t layer_size{params.GetHostLayerSize(level)};
- for (std::size_t face = 0; face < params.GetDepth(); ++face) {
+ for (std::size_t face = 0; face < params.depth; ++face) {
glCompressedTextureSubImage3D(texture.handle, level, 0, 0, static_cast<GLint>(face),
static_cast<GLsizei>(params.GetMipWidth(level)),
static_cast<GLsizei>(params.GetMipHeight(level)), 1,
@@ -291,7 +313,7 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
UNREACHABLE();
}
} else {
- switch (params.GetTarget()) {
+ switch (params.target) {
case SurfaceTarget::Texture1D:
glTextureSubImage1D(texture.handle, level, 0, params.GetMipWidth(level), format, type,
buffer);
@@ -310,7 +332,7 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
static_cast<GLsizei>(params.GetMipDepth(level)), format, type, buffer);
break;
case SurfaceTarget::TextureCubemap:
- for (std::size_t face = 0; face < params.GetDepth(); ++face) {
+ for (std::size_t face = 0; face < params.depth; ++face) {
glTextureSubImage3D(texture.handle, level, 0, 0, static_cast<GLint>(face),
params.GetMipWidth(level), params.GetMipHeight(level), 1,
format, type, buffer);
@@ -324,61 +346,57 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
}
void CachedSurface::DecorateSurfaceName() {
- LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(),
- params.GetTarget() == SurfaceTarget::Texture3D ? "3D" : "");
+ LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName());
+}
+
+void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
+ LabelGLObject(GL_TEXTURE, texture_view.texture.handle, gpu_addr, prefix);
}
-std::unique_ptr<CachedSurfaceView> CachedSurface::CreateView(const ViewKey& view_key) {
- return std::make_unique<CachedSurfaceView>(*this, view_key);
+View CachedSurface::CreateView(const ViewParams& view_key) {
+ auto view = std::make_shared<CachedSurfaceView>(*this, view_key);
+ views[view_key] = view;
+ view->DecorateViewName(gpu_addr, params.TargetName() + "V:" + std::to_string(view_count++));
+ return view;
}
-CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, ViewKey key)
- : surface{surface}, key{key}, params{surface.GetSurfaceParams()} {}
+CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params)
+ : VideoCommon::ViewBase(params), surface{surface} {
+ target = GetTextureTarget(params.target);
+ texture_view = CreateTextureView();
+}
CachedSurfaceView::~CachedSurfaceView() = default;
void CachedSurfaceView::Attach(GLenum attachment) const {
- ASSERT(key.num_layers == 1 && key.num_levels == 1);
+ ASSERT(params.num_layers == 1 && params.num_levels == 1);
- switch (params.GetTarget()) {
+ switch (params.target) {
case SurfaceTarget::Texture1D:
- glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTarget(),
- surface.GetTexture(), key.base_level);
+ glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, attachment, target,
+ surface.GetTexture(), params.base_level);
break;
case SurfaceTarget::Texture2D:
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTarget(),
- surface.GetTexture(), key.base_level);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target,
+ surface.GetTexture(), params.base_level);
break;
case SurfaceTarget::Texture1DArray:
case SurfaceTarget::Texture2DArray:
case SurfaceTarget::TextureCubemap:
case SurfaceTarget::TextureCubeArray:
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, surface.GetTexture(),
- key.base_level, key.base_layer);
+ glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, target,
+ params.base_level, params.base_layer);
break;
default:
UNIMPLEMENTED();
}
}
-GLuint CachedSurfaceView::GetTexture(Tegra::Shader::TextureType texture_type, bool is_array,
- SwizzleSource x_source, SwizzleSource y_source,
+void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source,
SwizzleSource z_source, SwizzleSource w_source) {
- const auto [texture_view, target] = GetTextureView(texture_type, is_array);
- if (texture_view.get().texture.handle == 0) {
- texture_view.get() = std::move(CreateTextureView(target));
- }
- ApplySwizzle(texture_view, x_source, y_source, z_source, w_source);
- return texture_view.get().texture.handle;
-}
-
-void CachedSurfaceView::ApplySwizzle(TextureView& texture_view, SwizzleSource x_source,
- SwizzleSource y_source, SwizzleSource z_source,
- SwizzleSource w_source) {
- const std::array<SwizzleSource, 4> swizzle = {x_source, y_source, z_source, w_source};
- if (swizzle == texture_view.swizzle) {
+ u32 swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
+ if (swizzle == texture_view.swizzle)
return;
- }
const std::array<GLint, 4> gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source),
GetSwizzleSource(z_source),
GetSwizzleSource(w_source)};
@@ -386,38 +404,25 @@ void CachedSurfaceView::ApplySwizzle(TextureView& texture_view, SwizzleSource x_
texture_view.swizzle = swizzle;
}
-CachedSurfaceView::TextureView CachedSurfaceView::CreateTextureView(GLenum target) const {
+CachedSurfaceView::TextureView CachedSurfaceView::CreateTextureView() const {
+ const auto& owner_params = surface.GetSurfaceParams();
TextureView texture_view;
- glGenTextures(1, &texture_view.texture.handle);
+ texture_view.texture.Create();
const GLuint handle{texture_view.texture.handle};
- const FormatTuple& tuple{GetFormatTuple(params.GetPixelFormat(), params.GetComponentType())};
+ const FormatTuple& tuple{
+ GetFormatTuple(owner_params.pixel_format, owner_params.component_type)};
- glTextureView(handle, target, surface.texture.handle, tuple.internal_format, key.base_level,
- key.num_levels, key.base_layer, key.num_layers);
- ApplyTextureDefaults(params, handle);
+ glTextureView(handle, target, surface.texture.handle, tuple.internal_format, params.base_level,
+ params.num_levels, params.base_layer, params.num_layers);
- return texture_view;
-}
+ ApplyTextureDefaults(owner_params, handle);
-std::pair<std::reference_wrapper<CachedSurfaceView::TextureView>, GLenum>
-CachedSurfaceView::GetTextureView(Tegra::Shader::TextureType texture_type, bool is_array) {
- using Pair = std::pair<std::reference_wrapper<TextureView>, GLenum>;
- switch (texture_type) {
- case Tegra::Shader::TextureType::Texture1D:
- return is_array ? Pair{texture_view_1d_array, GL_TEXTURE_1D_ARRAY}
- : Pair{texture_view_1d, GL_TEXTURE_1D};
- case Tegra::Shader::TextureType::Texture2D:
- return is_array ? Pair{texture_view_2d_array, GL_TEXTURE_2D_ARRAY}
- : Pair{texture_view_2d, GL_TEXTURE_2D};
- case Tegra::Shader::TextureType::Texture3D:
- ASSERT(!is_array);
- return {texture_view_3d, GL_TEXTURE_3D};
- case Tegra::Shader::TextureType::TextureCube:
- return is_array ? Pair{texture_view_cube_array, GL_TEXTURE_CUBE_MAP_ARRAY}
- : Pair{texture_view_cube, GL_TEXTURE_CUBE_MAP};
- }
- UNREACHABLE();
+ u32 swizzle =
+ EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
+ texture_view.swizzle = swizzle;
+
+ return texture_view;
}
TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system,
@@ -426,106 +431,21 @@ TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system,
TextureCacheOpenGL::~TextureCacheOpenGL() = default;
-CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr,
- u8* host_ptr,
- const SurfaceParams& new_params,
- bool preserve_contents,
- const std::vector<Surface>& overlaps) {
- if (overlaps.size() > 1) {
- return TryCopyAsViews(gpu_addr, cpu_addr, host_ptr, new_params, overlaps);
- }
-
- const auto& old_surface{overlaps[0]};
- const auto& old_params{old_surface->GetSurfaceParams()};
- if (old_params.GetTarget() == new_params.GetTarget() &&
- old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 &&
- old_params.GetNumLevels() == new_params.GetNumLevels() &&
- old_params.GetPixelFormat() == new_params.GetPixelFormat()) {
- return SurfaceCopy(gpu_addr, cpu_addr, host_ptr, new_params, old_surface, old_params);
- }
-
- return nullptr;
-}
-
-CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
- const SurfaceParams& new_params,
- const Surface& old_surface,
- const SurfaceParams& old_params) {
- const auto new_surface{GetUncachedSurface(new_params)};
- Register(new_surface, gpu_addr, cpu_addr, host_ptr);
-
- const u32 min_width{
- std::max(old_params.GetDefaultBlockWidth(), new_params.GetDefaultBlockWidth())};
- const u32 min_height{
- std::max(old_params.GetDefaultBlockHeight(), new_params.GetDefaultBlockHeight())};
- for (u32 level = 0; level < old_params.GetNumLevels(); ++level) {
- const u32 width{std::min(old_params.GetMipWidth(level), new_params.GetMipWidth(level))};
- const u32 height{std::min(old_params.GetMipHeight(level), new_params.GetMipHeight(level))};
- if (width < min_width || height < min_height) {
- // Avoid copies that are too small to be handled in OpenGL
- break;
- }
- glCopyImageSubData(old_surface->GetTexture(), old_surface->GetTarget(), level, 0, 0, 0,
- new_surface->GetTexture(), new_surface->GetTarget(), level, 0, 0, 0,
- width, height, 1);
- }
-
- new_surface->MarkAsModified(true);
-
- // TODO(Rodrigo): Add an entry to directly get the superview
- return new_surface->GetView(gpu_addr, new_params);
-}
-
-CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(GPUVAddr gpu_addr, VAddr cpu_addr,
- u8* host_ptr, const SurfaceParams& new_params,
- const std::vector<Surface>& overlaps) {
- if (new_params.GetTarget() == SurfaceTarget::Texture1D ||
- new_params.GetTarget() == SurfaceTarget::Texture1DArray ||
- new_params.GetTarget() == SurfaceTarget::Texture3D) {
- // Non-2D textures are not handled at the moment in this fast path.
- return nullptr;
- }
-
- const auto new_surface{GetUncachedSurface(new_params)};
- // TODO(Rodrigo): Move this down
- Register(new_surface, gpu_addr, cpu_addr, host_ptr);
-
- // TODO(Rodrigo): Find a way to avoid heap allocations here.
- std::vector<CachedSurfaceView*> views;
- views.reserve(overlaps.size());
- for (const auto& overlap : overlaps) {
- const auto view{
- new_surface->TryGetView(overlap->GetGpuAddr(), overlap->GetSurfaceParams())};
- if (!view) {
- // TODO(Rodrigo): Remove this
- Unregister(new_surface);
- return nullptr;
- }
- views.push_back(view);
- }
-
- // TODO(Rodrigo): It's possible that these method leaves some unloaded textures if the data has
- // been uploaded to guest memory but not used as a surface previously.
- for (std::size_t i = 0; i < overlaps.size(); ++i) {
- const auto& overlap{overlaps[i]};
- const auto& view{views[i]};
- for (u32 overlap_level = 0; overlap_level < view->GetNumLevels(); ++overlap_level) {
- const u32 super_level{view->GetBaseLevel() + overlap_level};
- glCopyImageSubData(overlap->GetTexture(), overlap->GetTarget(), overlap_level, 0, 0, 0,
- new_surface->GetTexture(), new_surface->GetTarget(), super_level, 0,
- 0, view->GetBaseLayer(), view->GetWidth(), view->GetHeight(),
- view->GetNumLayers());
- }
- }
-
- new_surface->MarkAsModified(true);
-
- // TODO(Rodrigo): Add an entry to directly get the superview
- return new_surface->GetView(gpu_addr, new_params);
+Surface TextureCacheOpenGL::CreateSurface(GPUVAddr gpu_addr, const SurfaceParams& params) {
+ return std::make_shared<CachedSurface>(gpu_addr, params);
}
-Surface TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) {
- return std::make_unique<CachedSurface>(*this, params);
+void TextureCacheOpenGL::ImageCopy(Surface src_surface, Surface dst_surface,
+ const VideoCommon::CopyParams& copy_params) {
+ const auto src_handle = src_surface->GetTexture();
+ const auto src_target = src_surface->GetTarget();
+ const auto dst_handle = dst_surface->GetTexture();
+ const auto dst_target = dst_surface->GetTarget();
+ glCopyImageSubData(src_handle, src_target, copy_params.source_level, copy_params.source_x,
+ copy_params.source_y, copy_params.source_z, dst_handle, dst_target,
+ copy_params.dest_level, copy_params.dest_x, copy_params.dest_y,
+ copy_params.dest_z, copy_params.width, copy_params.height,
+ copy_params.depth);
}
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index c65e37153..1722c1bbc 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -19,24 +19,25 @@
namespace OpenGL {
using VideoCommon::SurfaceParams;
-using VideoCommon::ViewKey;
+using VideoCommon::ViewParams;
class CachedSurfaceView;
class CachedSurface;
class TextureCacheOpenGL;
using Surface = std::shared_ptr<CachedSurface>;
-using TextureCacheBase = VideoCommon::TextureCache<CachedSurface, CachedSurfaceView>;
+using View = std::shared_ptr<CachedSurfaceView>;
+using TextureCacheBase = VideoCommon::TextureCache<Surface, View>;
-class CachedSurface final : public VideoCommon::SurfaceBase<TextureCacheOpenGL, CachedSurfaceView> {
+class CachedSurface final : public VideoCommon::SurfaceBase<View> {
friend CachedSurfaceView;
public:
- explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params);
+ explicit CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params);
~CachedSurface();
- void UploadTexture();
- void DownloadTexture();
+ void UploadTexture(std::vector<u8>& staging_buffer) override;
+ void DownloadTexture(std::vector<u8>& staging_buffer) override;
GLenum GetTarget() const {
return target;
@@ -49,99 +50,79 @@ public:
protected:
void DecorateSurfaceName();
- std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key);
+ View CreateView(const ViewParams& view_key) override;
private:
- void UploadTextureMipmap(u32 level);
+ void UploadTextureMipmap(u32 level, std::vector<u8>& staging_buffer);
GLenum internal_format{};
GLenum format{};
GLenum type{};
bool is_compressed{};
GLenum target{};
+ u32 view_count{};
OGLTexture texture;
};
-class CachedSurfaceView final {
+class CachedSurfaceView final : public VideoCommon::ViewBase {
public:
- explicit CachedSurfaceView(CachedSurface& surface, ViewKey key);
+ explicit CachedSurfaceView(CachedSurface& surface, const ViewParams& params);
~CachedSurfaceView();
/// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
void Attach(GLenum attachment) const;
- GLuint GetTexture(Tegra::Shader::TextureType texture_type, bool is_array,
- Tegra::Texture::SwizzleSource x_source,
- Tegra::Texture::SwizzleSource y_source,
- Tegra::Texture::SwizzleSource z_source,
- Tegra::Texture::SwizzleSource w_source);
-
- void MarkAsModified(bool is_modified) {
- surface.MarkAsModified(is_modified);
+ GLuint GetTexture() {
+ return texture_view.texture.handle;
}
const SurfaceParams& GetSurfaceParams() const {
- return params;
+ return surface.GetSurfaceParams();
}
u32 GetWidth() const {
- return params.GetMipWidth(GetBaseLevel());
+ const auto owner_params = GetSurfaceParams();
+ return owner_params.GetMipWidth(params.base_level);
}
u32 GetHeight() const {
- return params.GetMipHeight(GetBaseLevel());
+ const auto owner_params = GetSurfaceParams();
+ return owner_params.GetMipHeight(params.base_level);
}
u32 GetDepth() const {
- return params.GetMipDepth(GetBaseLevel());
- }
-
- u32 GetBaseLayer() const {
- return key.base_layer;
+ const auto owner_params = GetSurfaceParams();
+ return owner_params.GetMipDepth(params.base_level);
}
- u32 GetNumLayers() const {
- return key.num_layers;
- }
-
- u32 GetBaseLevel() const {
- return key.base_level;
- }
+ void ApplySwizzle(Tegra::Texture::SwizzleSource x_source,
+ Tegra::Texture::SwizzleSource y_source,
+ Tegra::Texture::SwizzleSource z_source,
+ Tegra::Texture::SwizzleSource w_source);
- u32 GetNumLevels() const {
- return key.num_levels;
- }
+ void DecorateViewName(GPUVAddr gpu_addr, std::string prefix);
private:
struct TextureView {
- OGLTexture texture;
- std::array<Tegra::Texture::SwizzleSource, 4> swizzle{
- Tegra::Texture::SwizzleSource::R, Tegra::Texture::SwizzleSource::G,
- Tegra::Texture::SwizzleSource::B, Tegra::Texture::SwizzleSource::A};
+ OGLTextureView texture;
+ u32 swizzle;
};
- void ApplySwizzle(TextureView& texture_view, Tegra::Texture::SwizzleSource x_source,
+ u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source,
Tegra::Texture::SwizzleSource y_source,
Tegra::Texture::SwizzleSource z_source,
- Tegra::Texture::SwizzleSource w_source);
-
- TextureView CreateTextureView(GLenum target) const;
+ Tegra::Texture::SwizzleSource w_source) const {
+ return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) |
+ (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source);
+ }
- std::pair<std::reference_wrapper<TextureView>, GLenum> GetTextureView(
- Tegra::Shader::TextureType texture_type, bool is_array);
+ TextureView CreateTextureView() const;
CachedSurface& surface;
- const ViewKey key;
- const SurfaceParams params;
-
- TextureView texture_view_1d;
- TextureView texture_view_1d_array;
- TextureView texture_view_2d;
- TextureView texture_view_2d_array;
- TextureView texture_view_3d;
- TextureView texture_view_cube;
- TextureView texture_view_cube_array;
+ GLenum target{};
+
+ TextureView texture_view;
};
class TextureCacheOpenGL final : public TextureCacheBase {
@@ -150,21 +131,9 @@ public:
~TextureCacheOpenGL();
protected:
- CachedSurfaceView* TryFastGetSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
- const SurfaceParams& new_params,
- bool preserve_contents,
- const std::vector<Surface>& overlaps);
-
- Surface CreateSurface(const SurfaceParams& params);
-
-private:
- CachedSurfaceView* SurfaceCopy(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
- const SurfaceParams& new_params, const Surface& old_surface,
- const SurfaceParams& old_params);
-
- CachedSurfaceView* TryCopyAsViews(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
- const SurfaceParams& new_params,
- const std::vector<Surface>& overlaps);
+ Surface CreateSurface(GPUVAddr gpu_addr, const SurfaceParams& params) override;
+ void ImageCopy(Surface src_surface, Surface dst_surface,
+ const VideoCommon::CopyParams& copy_params) override;
};
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/utils.cpp b/src/video_core/renderer_opengl/utils.cpp
index 5994c0c61..a9fa539a5 100644
--- a/src/video_core/renderer_opengl/utils.cpp
+++ b/src/video_core/renderer_opengl/utils.cpp
@@ -56,8 +56,7 @@ SurfaceBlitter::SurfaceBlitter() {
SurfaceBlitter::~SurfaceBlitter() = default;
-void SurfaceBlitter::Blit(CachedSurfaceView* src, CachedSurfaceView* dst,
- const Common::Rectangle<u32>& src_rect,
+void SurfaceBlitter::Blit(View src, View dst, const Common::Rectangle<u32>& src_rect,
const Common::Rectangle<u32>& dst_rect) const {
const auto& src_params{src->GetSurfaceParams()};
const auto& dst_params{dst->GetSurfaceParams()};
@@ -72,17 +71,13 @@ void SurfaceBlitter::Blit(CachedSurfaceView* src, CachedSurfaceView* dst,
u32 buffers{};
- UNIMPLEMENTED_IF(src_params.GetTarget() != SurfaceTarget::Texture2D);
- UNIMPLEMENTED_IF(dst_params.GetTarget() != SurfaceTarget::Texture2D);
+ UNIMPLEMENTED_IF(src_params.target != SurfaceTarget::Texture2D);
+ UNIMPLEMENTED_IF(dst_params.target != SurfaceTarget::Texture2D);
- const auto GetTexture = [](CachedSurfaceView* view) {
- return view->GetTexture(TextureType::Texture2D, false, SwizzleSource::R, SwizzleSource::G,
- SwizzleSource::B, SwizzleSource::A);
- };
- const GLuint src_texture{GetTexture(src)};
- const GLuint dst_texture{GetTexture(dst)};
+ const GLuint src_texture{src->GetTexture()};
+ const GLuint dst_texture{dst->GetTexture()};
- if (src_params.GetType() == SurfaceType::ColorTexture) {
+ if (src_params.type == SurfaceType::ColorTexture) {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
src_texture, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
@@ -94,7 +89,7 @@ void SurfaceBlitter::Blit(CachedSurfaceView* src, CachedSurfaceView* dst,
0);
buffers = GL_COLOR_BUFFER_BIT;
- } else if (src_params.GetType() == SurfaceType::Depth) {
+ } else if (src_params.type == SurfaceType::Depth) {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_texture,
0);
@@ -106,7 +101,7 @@ void SurfaceBlitter::Blit(CachedSurfaceView* src, CachedSurfaceView* dst,
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
buffers = GL_DEPTH_BUFFER_BIT;
- } else if (src_params.GetType() == SurfaceType::DepthStencil) {
+ } else if (src_params.type == 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,
src_texture, 0);
@@ -148,4 +143,4 @@ void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_vie
glObjectLabel(identifier, handle, -1, static_cast<const GLchar*>(object_label.c_str()));
}
-} // namespace OpenGL \ No newline at end of file
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/utils.h b/src/video_core/renderer_opengl/utils.h
index e7726d14e..8977d2383 100644
--- a/src/video_core/renderer_opengl/utils.h
+++ b/src/video_core/renderer_opengl/utils.h
@@ -39,8 +39,8 @@ public:
explicit SurfaceBlitter();
~SurfaceBlitter();
- void Blit(CachedSurfaceView* src, CachedSurfaceView* dst,
- const Common::Rectangle<u32>& src_rect, const Common::Rectangle<u32>& dst_rect) const;
+ void Blit(View src, View dst, const Common::Rectangle<u32>& src_rect,
+ const Common::Rectangle<u32>& dst_rect) const;
private:
OGLFramebuffer src_framebuffer;
@@ -49,4 +49,4 @@ private:
void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info = {});
-} // namespace OpenGL \ No newline at end of file
+} // namespace OpenGL