diff options
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 | 71 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 29 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 4 |
5 files changed, 83 insertions, 68 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 94fbd2a22..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 | }; |
| @@ -238,6 +238,12 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte | |||
| 238 | return texture; | 238 | return texture; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | constexpr u32 EncodeSwizzle(SwizzleSource x_source, SwizzleSource y_source, SwizzleSource z_source, | ||
| 242 | SwizzleSource w_source) { | ||
| 243 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 244 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 245 | } | ||
| 246 | |||
| 241 | } // Anonymous namespace | 247 | } // Anonymous namespace |
| 242 | 248 | ||
| 243 | CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params, | 249 | CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params, |
| @@ -381,7 +387,7 @@ void CachedSurface::DecorateSurfaceName() { | |||
| 381 | } | 387 | } |
| 382 | 388 | ||
| 383 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { | 389 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { |
| 384 | LabelGLObject(GL_TEXTURE, texture_view.handle, gpu_addr, prefix); | 390 | LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix); |
| 385 | } | 391 | } |
| 386 | 392 | ||
| 387 | View CachedSurface::CreateView(const ViewParams& view_key) { | 393 | View CachedSurface::CreateView(const ViewParams& view_key) { |
| @@ -397,14 +403,13 @@ View CachedSurface::CreateViewInner(const ViewParams& view_key, const bool is_pr | |||
| 397 | } | 403 | } |
| 398 | 404 | ||
| 399 | CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params, | 405 | CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params, |
| 400 | const bool is_proxy) | 406 | bool is_proxy) |
| 401 | : VideoCommon::ViewBase(params), surface{surface}, is_proxy{is_proxy} { | 407 | : VideoCommon::ViewBase(params), surface{surface}, |
| 402 | target = GetTextureTarget(params.target); | 408 | format{GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format}, |
| 403 | format = GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format; | 409 | target{GetTextureTarget(params.target)}, is_proxy{is_proxy} { |
| 404 | if (!is_proxy) { | 410 | if (!is_proxy) { |
| 405 | texture_view = CreateTextureView(); | 411 | main_view = CreateTextureView(); |
| 406 | } | 412 | } |
| 407 | swizzle = EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A); | ||
| 408 | } | 413 | } |
| 409 | 414 | ||
| 410 | CachedSurfaceView::~CachedSurfaceView() = default; | 415 | CachedSurfaceView::~CachedSurfaceView() = default; |
| @@ -447,27 +452,49 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { | |||
| 447 | } | 452 | } |
| 448 | } | 453 | } |
| 449 | 454 | ||
| 450 | void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source, | 455 | GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_source, |
| 451 | SwizzleSource z_source, SwizzleSource w_source) { | 456 | SwizzleSource z_source, SwizzleSource w_source) { |
| 452 | u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); | 457 | if (GetSurfaceParams().IsBuffer()) { |
| 453 | if (new_swizzle == swizzle) | 458 | return GetTexture(); |
| 454 | return; | 459 | } |
| 455 | swizzle = new_swizzle; | 460 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); |
| 456 | const std::array gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source), | 461 | if (current_swizzle == new_swizzle) { |
| 457 | GetSwizzleSource(z_source), GetSwizzleSource(w_source)}; | 462 | return current_view; |
| 458 | const GLuint handle = GetTexture(); | 463 | } |
| 459 | const PixelFormat format = surface.GetSurfaceParams().pixel_format; | 464 | current_swizzle = new_swizzle; |
| 460 | switch (format) { | 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 | |||
| 475 | std::array swizzle{x_source, y_source, z_source, w_source}; | ||
| 476 | |||
| 477 | switch (const PixelFormat format = GetSurfaceParams().pixel_format) { | ||
| 461 | case PixelFormat::Z24S8: | 478 | case PixelFormat::Z24S8: |
| 462 | case PixelFormat::Z32FS8: | 479 | case PixelFormat::Z32FS8: |
| 463 | case PixelFormat::S8Z24: | 480 | case PixelFormat::S8Z24: |
| 464 | glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE, | 481 | UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); |
| 482 | glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, | ||
| 465 | GetComponent(format, x_source == SwizzleSource::R)); | 483 | GetComponent(format, x_source == SwizzleSource::R)); |
| 484 | |||
| 485 | // Make sure we sample the first component | ||
| 486 | std::transform(swizzle.begin(), swizzle.end(), swizzle.begin(), [](SwizzleSource value) { | ||
| 487 | return value == SwizzleSource::G ? SwizzleSource::R : value; | ||
| 488 | }); | ||
| 489 | [[fallthrough]]; | ||
| 490 | default: { | ||
| 491 | const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]), | ||
| 492 | GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])}; | ||
| 493 | glTextureParameteriv(view.handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data()); | ||
| 466 | break; | 494 | break; |
| 467 | default: | ||
| 468 | glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data()); | ||
| 469 | break; | ||
| 470 | } | 495 | } |
| 496 | } | ||
| 497 | return view.handle; | ||
| 471 | } | 498 | } |
| 472 | 499 | ||
| 473 | 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 02d9981a1..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 { |
| @@ -110,23 +110,19 @@ public: | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | private: | 112 | private: |
| 113 | u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, | ||
| 114 | Tegra::Texture::SwizzleSource y_source, | ||
| 115 | Tegra::Texture::SwizzleSource z_source, | ||
| 116 | Tegra::Texture::SwizzleSource w_source) const { | ||
| 117 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 118 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 119 | } | ||
| 120 | |||
| 121 | OGLTextureView CreateTextureView() const; | 113 | OGLTextureView CreateTextureView() const; |
| 122 | 114 | ||
| 123 | CachedSurface& surface; | 115 | CachedSurface& surface; |
| 124 | GLenum target{}; | 116 | const GLenum format; |
| 125 | GLenum format{}; | 117 | const GLenum target; |
| 118 | const bool is_proxy; | ||
| 119 | |||
| 120 | std::unordered_map<u32, OGLTextureView> view_cache; | ||
| 121 | OGLTextureView main_view; | ||
| 126 | 122 | ||
| 127 | OGLTextureView texture_view; | 123 | // Use an invalid default so it always fails the comparison test |
| 128 | u32 swizzle{}; | 124 | u32 current_swizzle = 0xffffffff; |
| 129 | bool is_proxy{}; | 125 | GLuint current_view = 0; |
| 130 | }; | 126 | }; |
| 131 | 127 | ||
| 132 | class TextureCacheOpenGL final : public TextureCacheBase { | 128 | class TextureCacheOpenGL final : public TextureCacheBase { |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 55f43e61b..2f1d5021d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -354,26 +354,23 @@ CachedSurfaceView::~CachedSurfaceView() = default; | |||
| 354 | 354 | ||
| 355 | VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source, | 355 | VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source, |
| 356 | SwizzleSource z_source, SwizzleSource w_source) { | 356 | SwizzleSource z_source, SwizzleSource w_source) { |
| 357 | const u32 swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); | 357 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); |
| 358 | if (last_image_view && last_swizzle == swizzle) { | 358 | if (last_image_view && last_swizzle == new_swizzle) { |
| 359 | return last_image_view; | 359 | return last_image_view; |
| 360 | } | 360 | } |
| 361 | last_swizzle = swizzle; | 361 | last_swizzle = new_swizzle; |
| 362 | 362 | ||
| 363 | const auto [entry, is_cache_miss] = view_cache.try_emplace(swizzle); | 363 | const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle); |
| 364 | auto& image_view = entry->second; | 364 | auto& image_view = entry->second; |
| 365 | if (!is_cache_miss) { | 365 | if (!is_cache_miss) { |
| 366 | return last_image_view = *image_view; | 366 | return last_image_view = *image_view; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | auto swizzle_x = MaxwellToVK::SwizzleSource(x_source); | 369 | std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source), |
| 370 | auto swizzle_y = MaxwellToVK::SwizzleSource(y_source); | 370 | MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)}; |
| 371 | auto swizzle_z = MaxwellToVK::SwizzleSource(z_source); | ||
| 372 | auto swizzle_w = MaxwellToVK::SwizzleSource(w_source); | ||
| 373 | |||
| 374 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { | 371 | if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { |
| 375 | // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. | 372 | // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. |
| 376 | std::swap(swizzle_x, swizzle_z); | 373 | std::swap(swizzle[0], swizzle[2]); |
| 377 | } | 374 | } |
| 378 | 375 | ||
| 379 | // Games can sample depth or stencil values on textures. This is decided by the swizzle value on | 376 | // Games can sample depth or stencil values on textures. This is decided by the swizzle value on |
| @@ -395,11 +392,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 395 | UNIMPLEMENTED(); | 392 | UNIMPLEMENTED(); |
| 396 | } | 393 | } |
| 397 | 394 | ||
| 398 | // Vulkan doesn't seem to understand swizzling of a depth stencil image, use identity | 395 | // Make sure we sample the first component |
| 399 | swizzle_x = VK_COMPONENT_SWIZZLE_R; | 396 | std::transform( |
| 400 | swizzle_y = VK_COMPONENT_SWIZZLE_G; | 397 | swizzle.begin(), swizzle.end(), swizzle.begin(), [](VkComponentSwizzle component) { |
| 401 | swizzle_z = VK_COMPONENT_SWIZZLE_B; | 398 | return component == VK_COMPONENT_SWIZZLE_G ? VK_COMPONENT_SWIZZLE_R : component; |
| 402 | swizzle_w = VK_COMPONENT_SWIZZLE_A; | 399 | }); |
| 403 | } | 400 | } |
| 404 | 401 | ||
| 405 | VkImageViewCreateInfo ci; | 402 | VkImageViewCreateInfo ci; |
| @@ -409,7 +406,7 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 409 | ci.image = surface.GetImageHandle(); | 406 | ci.image = surface.GetImageHandle(); |
| 410 | ci.viewType = image_view_type; | 407 | ci.viewType = image_view_type; |
| 411 | ci.format = surface.GetImage().GetFormat(); | 408 | ci.format = surface.GetImage().GetFormat(); |
| 412 | ci.components = {swizzle_x, swizzle_y, swizzle_z, swizzle_w}; | 409 | ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]}; |
| 413 | ci.subresourceRange.aspectMask = aspect; | 410 | ci.subresourceRange.aspectMask = aspect; |
| 414 | ci.subresourceRange.baseMipLevel = base_level; | 411 | ci.subresourceRange.baseMipLevel = base_level; |
| 415 | ci.subresourceRange.levelCount = num_levels; | 412 | ci.subresourceRange.levelCount = num_levels; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index d6efc34b2..8bfc541d4 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -991,7 +991,9 @@ private: | |||
| 991 | params.target = target; | 991 | params.target = target; |
| 992 | params.is_tiled = false; | 992 | params.is_tiled = false; |
| 993 | params.srgb_conversion = false; | 993 | params.srgb_conversion = false; |
| 994 | params.is_layered = false; | 994 | params.is_layered = |
| 995 | target == SurfaceTarget::Texture1DArray || target == SurfaceTarget::Texture2DArray || | ||
| 996 | target == SurfaceTarget::TextureCubemap || target == SurfaceTarget::TextureCubeArray; | ||
| 995 | params.block_width = 0; | 997 | params.block_width = 0; |
| 996 | params.block_height = 0; | 998 | params.block_height = 0; |
| 997 | params.block_depth = 0; | 999 | params.block_depth = 0; |