diff options
| author | 2020-05-26 02:17:17 -0300 | |
|---|---|---|
| committer | 2020-05-26 17:50:08 -0300 | |
| commit | b17fe82973009cc204a298bf8c345ea6eec37a17 (patch) | |
| tree | 543ae26fad2f4198f7682b44086b8dc6338f8ea0 /src | |
| parent | texture_cache: Implement depth stencil texture swizzles (diff) | |
| download | yuzu-b17fe82973009cc204a298bf8c345ea6eec37a17.tar.gz yuzu-b17fe82973009cc204a298bf8c345ea6eec37a17.tar.xz yuzu-b17fe82973009cc204a298bf8c345ea6eec37a17.zip | |
gl_texture_cache: Implement small texture view cache for swizzles
This fixes cases where the texture swizzle was applied twice on the same
draw to a texture bound to two different slots.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 18 |
3 files changed, 44 insertions, 37 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 8116a5daa..716d43e65 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -977,16 +977,12 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu | |||
| 977 | glBindTextureUnit(binding, 0); | 977 | glBindTextureUnit(binding, 0); |
| 978 | return; | 978 | return; |
| 979 | } | 979 | } |
| 980 | glBindTextureUnit(binding, view->GetTexture()); | 980 | const GLuint handle = view->GetTexture(texture.tic.x_source, texture.tic.y_source, |
| 981 | 981 | texture.tic.z_source, texture.tic.w_source); | |
| 982 | if (view->GetSurfaceParams().IsBuffer()) { | 982 | glBindTextureUnit(binding, handle); |
| 983 | return; | 983 | if (!view->GetSurfaceParams().IsBuffer()) { |
| 984 | glBindSampler(binding, sampler_cache.GetSampler(texture.tsc)); | ||
| 984 | } | 985 | } |
| 985 | // Apply swizzle to textures that are not buffers. | ||
| 986 | view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, | ||
| 987 | texture.tic.w_source); | ||
| 988 | |||
| 989 | glBindSampler(binding, sampler_cache.GetSampler(texture.tsc)); | ||
| 990 | } | 986 | } |
| 991 | 987 | ||
| 992 | void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) { | 988 | void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) { |
| @@ -1015,14 +1011,11 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t | |||
| 1015 | glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); | 1011 | glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); |
| 1016 | return; | 1012 | return; |
| 1017 | } | 1013 | } |
| 1018 | if (!tic.IsBuffer()) { | ||
| 1019 | view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | ||
| 1020 | } | ||
| 1021 | if (entry.is_written) { | 1014 | if (entry.is_written) { |
| 1022 | view->MarkAsModified(texture_cache.Tick()); | 1015 | view->MarkAsModified(texture_cache.Tick()); |
| 1023 | } | 1016 | } |
| 1024 | glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE, | 1017 | const GLuint handle = view->GetTexture(tic.x_source, tic.y_source, tic.z_source, tic.w_source); |
| 1025 | view->GetFormat()); | 1018 | glBindImageTexture(binding, handle, 0, GL_TRUE, 0, GL_READ_WRITE, view->GetFormat()); |
| 1026 | } | 1019 | } |
| 1027 | 1020 | ||
| 1028 | void RasterizerOpenGL::SyncViewport() { | 1021 | void RasterizerOpenGL::SyncViewport() { |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 7e0ffe3cd..4faa8b90c 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -35,7 +35,7 @@ MICROPROFILE_DEFINE(OpenGL_Texture_Buffer_Copy, "OpenGL", "Texture Buffer Copy", | |||
| 35 | namespace { | 35 | namespace { |
| 36 | 36 | ||
| 37 | struct FormatTuple { | 37 | struct FormatTuple { |
| 38 | GLint internal_format; | 38 | GLenum internal_format; |
| 39 | GLenum format = GL_NONE; | 39 | GLenum format = GL_NONE; |
| 40 | GLenum type = GL_NONE; | 40 | GLenum type = GL_NONE; |
| 41 | }; | 41 | }; |
| @@ -387,7 +387,7 @@ void CachedSurface::DecorateSurfaceName() { | |||
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { | 389 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { |
| 390 | LabelGLObject(GL_TEXTURE, texture_view.handle, gpu_addr, prefix); | 390 | LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | View CachedSurface::CreateView(const ViewParams& view_key) { | 393 | View CachedSurface::CreateView(const ViewParams& view_key) { |
| @@ -403,15 +403,13 @@ View CachedSurface::CreateViewInner(const ViewParams& view_key, const bool is_pr | |||
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params, | 405 | CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params, |
| 406 | const bool is_proxy) | 406 | bool is_proxy) |
| 407 | : VideoCommon::ViewBase(params), surface{surface}, is_proxy{is_proxy} { | 407 | : VideoCommon::ViewBase(params), surface{surface}, |
| 408 | target = GetTextureTarget(params.target); | 408 | format{GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format}, |
| 409 | format = GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format; | 409 | target{GetTextureTarget(params.target)}, is_proxy{is_proxy} { |
| 410 | if (!is_proxy) { | 410 | if (!is_proxy) { |
| 411 | texture_view = CreateTextureView(); | 411 | main_view = CreateTextureView(); |
| 412 | } | 412 | } |
| 413 | current_swizzle = | ||
| 414 | EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A); | ||
| 415 | } | 413 | } |
| 416 | 414 | ||
| 417 | CachedSurfaceView::~CachedSurfaceView() = default; | 415 | CachedSurfaceView::~CachedSurfaceView() = default; |
| @@ -454,23 +452,34 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { | |||
| 454 | } | 452 | } |
| 455 | } | 453 | } |
| 456 | 454 | ||
| 457 | void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source, | 455 | GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_source, |
| 458 | SwizzleSource z_source, SwizzleSource w_source) { | 456 | SwizzleSource z_source, SwizzleSource w_source) { |
| 457 | if (GetSurfaceParams().IsBuffer()) { | ||
| 458 | return GetTexture(); | ||
| 459 | } | ||
| 459 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); | 460 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); |
| 460 | if (current_swizzle == new_swizzle) { | 461 | if (current_swizzle == new_swizzle) { |
| 461 | return; | 462 | return current_view; |
| 462 | } | 463 | } |
| 463 | current_swizzle = new_swizzle; | 464 | current_swizzle = new_swizzle; |
| 464 | 465 | ||
| 466 | const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle); | ||
| 467 | OGLTextureView& view = entry->second; | ||
| 468 | if (!is_cache_miss) { | ||
| 469 | current_view = view.handle; | ||
| 470 | return view.handle; | ||
| 471 | } | ||
| 472 | view = CreateTextureView(); | ||
| 473 | current_view = view.handle; | ||
| 474 | |||
| 465 | std::array swizzle{x_source, y_source, z_source, w_source}; | 475 | std::array swizzle{x_source, y_source, z_source, w_source}; |
| 466 | 476 | ||
| 467 | const GLuint handle = GetTexture(); | 477 | switch (const PixelFormat format = GetSurfaceParams().pixel_format) { |
| 468 | switch (const PixelFormat format = surface.GetSurfaceParams().pixel_format) { | ||
| 469 | case PixelFormat::S8Z24: | ||
| 470 | case PixelFormat::Z24S8: | 478 | case PixelFormat::Z24S8: |
| 471 | case PixelFormat::Z32FS8: | 479 | case PixelFormat::Z32FS8: |
| 480 | case PixelFormat::S8Z24: | ||
| 472 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); | 481 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); |
| 473 | glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE, | 482 | glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, |
| 474 | GetComponent(format, x_source == SwizzleSource::R)); | 483 | GetComponent(format, x_source == SwizzleSource::R)); |
| 475 | 484 | ||
| 476 | // Make sure we sample the first component | 485 | // Make sure we sample the first component |
| @@ -481,10 +490,11 @@ void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_sou | |||
| 481 | default: { | 490 | default: { |
| 482 | const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]), | 491 | const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]), |
| 483 | GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])}; | 492 | GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])}; |
| 484 | glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data()); | 493 | glTextureParameteriv(view.handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data()); |
| 485 | break; | 494 | break; |
| 486 | } | 495 | } |
| 487 | } | 496 | } |
| 497 | return view.handle; | ||
| 488 | } | 498 | } |
| 489 | 499 | ||
| 490 | OGLTextureView CachedSurfaceView::CreateTextureView() const { | 500 | OGLTextureView CachedSurfaceView::CreateTextureView() const { |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 0d88d738f..8a2ac8603 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -83,7 +83,7 @@ public: | |||
| 83 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER | 83 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER |
| 84 | void Attach(GLenum attachment, GLenum target) const; | 84 | void Attach(GLenum attachment, GLenum target) const; |
| 85 | 85 | ||
| 86 | void ApplySwizzle(Tegra::Texture::SwizzleSource x_source, | 86 | GLuint GetTexture(Tegra::Texture::SwizzleSource x_source, |
| 87 | Tegra::Texture::SwizzleSource y_source, | 87 | Tegra::Texture::SwizzleSource y_source, |
| 88 | Tegra::Texture::SwizzleSource z_source, | 88 | Tegra::Texture::SwizzleSource z_source, |
| 89 | Tegra::Texture::SwizzleSource w_source); | 89 | Tegra::Texture::SwizzleSource w_source); |
| @@ -98,7 +98,7 @@ public: | |||
| 98 | if (is_proxy) { | 98 | if (is_proxy) { |
| 99 | return surface.GetTexture(); | 99 | return surface.GetTexture(); |
| 100 | } | 100 | } |
| 101 | return texture_view.handle; | 101 | return main_view.handle; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | GLenum GetFormat() const { | 104 | GLenum GetFormat() const { |
| @@ -113,12 +113,16 @@ private: | |||
| 113 | OGLTextureView CreateTextureView() const; | 113 | OGLTextureView CreateTextureView() const; |
| 114 | 114 | ||
| 115 | CachedSurface& surface; | 115 | CachedSurface& surface; |
| 116 | GLenum target{}; | 116 | const GLenum format; |
| 117 | GLenum format{}; | 117 | const GLenum target; |
| 118 | const bool is_proxy; | ||
| 119 | |||
| 120 | std::unordered_map<u32, OGLTextureView> view_cache; | ||
| 121 | OGLTextureView main_view; | ||
| 118 | 122 | ||
| 119 | OGLTextureView texture_view; | 123 | // Use an invalid default so it always fails the comparison test |
| 120 | u32 current_swizzle{}; | 124 | u32 current_swizzle = 0xffffffff; |
| 121 | bool is_proxy{}; | 125 | GLuint current_view = 0; |
| 122 | }; | 126 | }; |
| 123 | 127 | ||
| 124 | class TextureCacheOpenGL final : public TextureCacheBase { | 128 | class TextureCacheOpenGL final : public TextureCacheBase { |