diff options
| author | 2020-02-24 10:14:50 -0500 | |
|---|---|---|
| committer | 2020-02-24 10:14:50 -0500 | |
| commit | e22ad52cdb18842a12037e8b85d7be854b95206c (patch) | |
| tree | f60ec07ce5a4e6f56a1c9c5e18884de52de81334 | |
| parent | Merge pull request #3424 from ReinUsesLisp/spirv-layer (diff) | |
| parent | texture_cache: Implement layered framebuffer attachments (diff) | |
| download | yuzu-e22ad52cdb18842a12037e8b85d7be854b95206c.tar.gz yuzu-e22ad52cdb18842a12037e8b85d7be854b95206c.tar.xz yuzu-e22ad52cdb18842a12037e8b85d7be854b95206c.zip | |
Merge pull request #3425 from ReinUsesLisp/layered-framebuffer
texture_cache: Implement layered framebuffer attachments
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 4 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.cpp | 47 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.h | 5 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 5 |
8 files changed, 74 insertions, 51 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 26939be3f..6ea7cc6a5 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -542,7 +542,7 @@ public: | |||
| 542 | BitField<12, 1, InvMemoryLayout> type; | 542 | BitField<12, 1, InvMemoryLayout> type; |
| 543 | } memory_layout; | 543 | } memory_layout; |
| 544 | union { | 544 | union { |
| 545 | BitField<0, 16, u32> array_mode; | 545 | BitField<0, 16, u32> layers; |
| 546 | BitField<16, 1, u32> volume; | 546 | BitField<16, 1, u32> volume; |
| 547 | }; | 547 | }; |
| 548 | u32 layer_stride; | 548 | u32 layer_stride; |
| @@ -800,8 +800,12 @@ public: | |||
| 800 | 800 | ||
| 801 | u32 zeta_width; | 801 | u32 zeta_width; |
| 802 | u32 zeta_height; | 802 | u32 zeta_height; |
| 803 | union { | ||
| 804 | BitField<0, 16, u32> zeta_layers; | ||
| 805 | BitField<16, 1, u32> zeta_volume; | ||
| 806 | }; | ||
| 803 | 807 | ||
| 804 | INSERT_UNION_PADDING_WORDS(0x27); | 808 | INSERT_UNION_PADDING_WORDS(0x26); |
| 805 | 809 | ||
| 806 | u32 depth_test_enable; | 810 | u32 depth_test_enable; |
| 807 | 811 | ||
| @@ -1507,6 +1511,7 @@ ASSERT_REG_POSITION(vertex_attrib_format, 0x458); | |||
| 1507 | ASSERT_REG_POSITION(rt_control, 0x487); | 1511 | ASSERT_REG_POSITION(rt_control, 0x487); |
| 1508 | ASSERT_REG_POSITION(zeta_width, 0x48a); | 1512 | ASSERT_REG_POSITION(zeta_width, 0x48a); |
| 1509 | ASSERT_REG_POSITION(zeta_height, 0x48b); | 1513 | ASSERT_REG_POSITION(zeta_height, 0x48b); |
| 1514 | ASSERT_REG_POSITION(zeta_layers, 0x48c); | ||
| 1510 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); | 1515 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); |
| 1511 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); | 1516 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); |
| 1512 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); | 1517 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 5c1ae1418..c4c0bd226 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -405,24 +405,36 @@ CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& p | |||
| 405 | CachedSurfaceView::~CachedSurfaceView() = default; | 405 | CachedSurfaceView::~CachedSurfaceView() = default; |
| 406 | 406 | ||
| 407 | void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { | 407 | void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { |
| 408 | ASSERT(params.num_layers == 1 && params.num_levels == 1); | 408 | ASSERT(params.num_levels == 1); |
| 409 | 409 | ||
| 410 | const auto& owner_params = surface.GetSurfaceParams(); | 410 | const GLuint texture = surface.GetTexture(); |
| 411 | if (params.num_layers > 1) { | ||
| 412 | // Layered framebuffer attachments | ||
| 413 | UNIMPLEMENTED_IF(params.base_layer != 0); | ||
| 414 | |||
| 415 | switch (params.target) { | ||
| 416 | case SurfaceTarget::Texture2DArray: | ||
| 417 | glFramebufferTexture(target, attachment, texture, params.base_level); | ||
| 418 | break; | ||
| 419 | default: | ||
| 420 | UNIMPLEMENTED(); | ||
| 421 | } | ||
| 422 | return; | ||
| 423 | } | ||
| 411 | 424 | ||
| 412 | switch (owner_params.target) { | 425 | const GLenum view_target = surface.GetTarget(); |
| 426 | switch (surface.GetSurfaceParams().target) { | ||
| 413 | case SurfaceTarget::Texture1D: | 427 | case SurfaceTarget::Texture1D: |
| 414 | glFramebufferTexture1D(target, attachment, surface.GetTarget(), surface.GetTexture(), | 428 | glFramebufferTexture1D(target, attachment, view_target, texture, params.base_level); |
| 415 | params.base_level); | ||
| 416 | break; | 429 | break; |
| 417 | case SurfaceTarget::Texture2D: | 430 | case SurfaceTarget::Texture2D: |
| 418 | glFramebufferTexture2D(target, attachment, surface.GetTarget(), surface.GetTexture(), | 431 | glFramebufferTexture2D(target, attachment, view_target, texture, params.base_level); |
| 419 | params.base_level); | ||
| 420 | break; | 432 | break; |
| 421 | case SurfaceTarget::Texture1DArray: | 433 | case SurfaceTarget::Texture1DArray: |
| 422 | case SurfaceTarget::Texture2DArray: | 434 | case SurfaceTarget::Texture2DArray: |
| 423 | case SurfaceTarget::TextureCubemap: | 435 | case SurfaceTarget::TextureCubemap: |
| 424 | case SurfaceTarget::TextureCubeArray: | 436 | case SurfaceTarget::TextureCubeArray: |
| 425 | glFramebufferTextureLayer(target, attachment, surface.GetTexture(), params.base_level, | 437 | glFramebufferTextureLayer(target, attachment, texture, params.base_level, |
| 426 | params.base_layer); | 438 | params.base_layer); |
| 427 | break; | 439 | break; |
| 428 | default: | 440 | default: |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 31c078f6a..3bf86da87 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -611,33 +611,34 @@ bool RasterizerVulkan::WalkAttachmentOverlaps(const CachedSurfaceView& attachmen | |||
| 611 | std::tuple<vk::Framebuffer, vk::Extent2D> RasterizerVulkan::ConfigureFramebuffers( | 611 | std::tuple<vk::Framebuffer, vk::Extent2D> RasterizerVulkan::ConfigureFramebuffers( |
| 612 | vk::RenderPass renderpass) { | 612 | vk::RenderPass renderpass) { |
| 613 | FramebufferCacheKey key{renderpass, std::numeric_limits<u32>::max(), | 613 | FramebufferCacheKey key{renderpass, std::numeric_limits<u32>::max(), |
| 614 | std::numeric_limits<u32>::max()}; | 614 | std::numeric_limits<u32>::max(), std::numeric_limits<u32>::max()}; |
| 615 | 615 | ||
| 616 | const auto MarkAsModifiedAndPush = [&](const View& view) { | 616 | const auto try_push = [&](const View& view) { |
| 617 | if (view == nullptr) { | 617 | if (!view) { |
| 618 | return false; | 618 | return false; |
| 619 | } | 619 | } |
| 620 | key.views.push_back(view->GetHandle()); | 620 | key.views.push_back(view->GetHandle()); |
| 621 | key.width = std::min(key.width, view->GetWidth()); | 621 | key.width = std::min(key.width, view->GetWidth()); |
| 622 | key.height = std::min(key.height, view->GetHeight()); | 622 | key.height = std::min(key.height, view->GetHeight()); |
| 623 | key.layers = std::min(key.layers, view->GetNumLayers()); | ||
| 623 | return true; | 624 | return true; |
| 624 | }; | 625 | }; |
| 625 | 626 | ||
| 626 | for (std::size_t index = 0; index < std::size(color_attachments); ++index) { | 627 | for (std::size_t index = 0; index < std::size(color_attachments); ++index) { |
| 627 | if (MarkAsModifiedAndPush(color_attachments[index])) { | 628 | if (try_push(color_attachments[index])) { |
| 628 | texture_cache.MarkColorBufferInUse(index); | 629 | texture_cache.MarkColorBufferInUse(index); |
| 629 | } | 630 | } |
| 630 | } | 631 | } |
| 631 | if (MarkAsModifiedAndPush(zeta_attachment)) { | 632 | if (try_push(zeta_attachment)) { |
| 632 | texture_cache.MarkDepthBufferInUse(); | 633 | texture_cache.MarkDepthBufferInUse(); |
| 633 | } | 634 | } |
| 634 | 635 | ||
| 635 | const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); | 636 | const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); |
| 636 | auto& framebuffer = fbentry->second; | 637 | auto& framebuffer = fbentry->second; |
| 637 | if (is_cache_miss) { | 638 | if (is_cache_miss) { |
| 638 | const vk::FramebufferCreateInfo framebuffer_ci({}, key.renderpass, | 639 | const vk::FramebufferCreateInfo framebuffer_ci( |
| 639 | static_cast<u32>(key.views.size()), | 640 | {}, key.renderpass, static_cast<u32>(key.views.size()), key.views.data(), key.width, |
| 640 | key.views.data(), key.width, key.height, 1); | 641 | key.height, key.layers); |
| 641 | const auto dev = device.GetLogical(); | 642 | const auto dev = device.GetLogical(); |
| 642 | const auto& dld = device.GetDispatchLoader(); | 643 | const auto& dld = device.GetDispatchLoader(); |
| 643 | framebuffer = dev.createFramebufferUnique(framebuffer_ci, nullptr, dld); | 644 | framebuffer = dev.createFramebufferUnique(framebuffer_ci, nullptr, dld); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 138903d60..4dc8af6e8 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -56,6 +56,7 @@ struct FramebufferCacheKey { | |||
| 56 | vk::RenderPass renderpass{}; | 56 | vk::RenderPass renderpass{}; |
| 57 | u32 width = 0; | 57 | u32 width = 0; |
| 58 | u32 height = 0; | 58 | u32 height = 0; |
| 59 | u32 layers = 0; | ||
| 59 | ImageViewsPack views; | 60 | ImageViewsPack views; |
| 60 | 61 | ||
| 61 | std::size_t Hash() const noexcept { | 62 | std::size_t Hash() const noexcept { |
| @@ -66,12 +67,17 @@ struct FramebufferCacheKey { | |||
| 66 | } | 67 | } |
| 67 | boost::hash_combine(hash, width); | 68 | boost::hash_combine(hash, width); |
| 68 | boost::hash_combine(hash, height); | 69 | boost::hash_combine(hash, height); |
| 70 | boost::hash_combine(hash, layers); | ||
| 69 | return hash; | 71 | return hash; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | bool operator==(const FramebufferCacheKey& rhs) const noexcept { | 74 | bool operator==(const FramebufferCacheKey& rhs) const noexcept { |
| 73 | return std::tie(renderpass, views, width, height) == | 75 | return std::tie(renderpass, views, width, height, layers) == |
| 74 | std::tie(rhs.renderpass, rhs.views, rhs.width, rhs.height); | 76 | std::tie(rhs.renderpass, rhs.views, rhs.width, rhs.height, rhs.layers); |
| 77 | } | ||
| 78 | |||
| 79 | bool operator!=(const FramebufferCacheKey& rhs) const noexcept { | ||
| 80 | return !operator==(rhs); | ||
| 75 | } | 81 | } |
| 76 | }; | 82 | }; |
| 77 | 83 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index d3edbe80c..22e3d34de 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -151,6 +151,10 @@ public: | |||
| 151 | return params.GetMipHeight(base_level); | 151 | return params.GetMipHeight(base_level); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | u32 GetNumLayers() const { | ||
| 155 | return num_layers; | ||
| 156 | } | ||
| 157 | |||
| 154 | bool IsBufferView() const { | 158 | bool IsBufferView() const { |
| 155 | return buffer_view; | 159 | return buffer_view; |
| 156 | } | 160 | } |
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 38b3a4ba8..f00839313 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -84,19 +84,16 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta | |||
| 84 | if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { | 84 | if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { |
| 85 | switch (params.pixel_format) { | 85 | switch (params.pixel_format) { |
| 86 | case PixelFormat::R16U: | 86 | case PixelFormat::R16U: |
| 87 | case PixelFormat::R16F: { | 87 | case PixelFormat::R16F: |
| 88 | params.pixel_format = PixelFormat::Z16; | 88 | params.pixel_format = PixelFormat::Z16; |
| 89 | break; | 89 | break; |
| 90 | } | 90 | case PixelFormat::R32F: |
| 91 | case PixelFormat::R32F: { | ||
| 92 | params.pixel_format = PixelFormat::Z32F; | 91 | params.pixel_format = PixelFormat::Z32F; |
| 93 | break; | 92 | break; |
| 94 | } | 93 | default: |
| 95 | default: { | ||
| 96 | UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", | 94 | UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", |
| 97 | static_cast<u32>(params.pixel_format)); | 95 | static_cast<u32>(params.pixel_format)); |
| 98 | } | 96 | } |
| 99 | } | ||
| 100 | params.type = GetFormatType(params.pixel_format); | 97 | params.type = GetFormatType(params.pixel_format); |
| 101 | } | 98 | } |
| 102 | params.type = GetFormatType(params.pixel_format); | 99 | params.type = GetFormatType(params.pixel_format); |
| @@ -168,27 +165,29 @@ SurfaceParams SurfaceParams::CreateForImage(const FormatLookupTable& lookup_tabl | |||
| 168 | return params; | 165 | return params; |
| 169 | } | 166 | } |
| 170 | 167 | ||
| 171 | SurfaceParams SurfaceParams::CreateForDepthBuffer( | 168 | SurfaceParams SurfaceParams::CreateForDepthBuffer(Core::System& system) { |
| 172 | Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format, | 169 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 173 | u32 block_width, u32 block_height, u32 block_depth, | 170 | regs.zeta_width, regs.zeta_height, regs.zeta.format, regs.zeta.memory_layout.type; |
| 174 | Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type) { | ||
| 175 | SurfaceParams params; | 171 | SurfaceParams params; |
| 176 | params.is_tiled = type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; | 172 | params.is_tiled = regs.zeta.memory_layout.type == |
| 173 | Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; | ||
| 177 | params.srgb_conversion = false; | 174 | params.srgb_conversion = false; |
| 178 | params.block_width = std::min(block_width, 5U); | 175 | params.block_width = std::min(regs.zeta.memory_layout.block_width.Value(), 5U); |
| 179 | params.block_height = std::min(block_height, 5U); | 176 | params.block_height = std::min(regs.zeta.memory_layout.block_height.Value(), 5U); |
| 180 | params.block_depth = std::min(block_depth, 5U); | 177 | params.block_depth = std::min(regs.zeta.memory_layout.block_depth.Value(), 5U); |
| 181 | params.tile_width_spacing = 1; | 178 | params.tile_width_spacing = 1; |
| 182 | params.pixel_format = PixelFormatFromDepthFormat(format); | 179 | params.pixel_format = PixelFormatFromDepthFormat(regs.zeta.format); |
| 183 | params.type = GetFormatType(params.pixel_format); | 180 | params.type = GetFormatType(params.pixel_format); |
| 184 | params.width = zeta_width; | 181 | params.width = regs.zeta_width; |
| 185 | params.height = zeta_height; | 182 | params.height = regs.zeta_height; |
| 186 | params.target = SurfaceTarget::Texture2D; | ||
| 187 | params.depth = 1; | ||
| 188 | params.pitch = 0; | 183 | params.pitch = 0; |
| 189 | params.num_levels = 1; | 184 | params.num_levels = 1; |
| 190 | params.emulated_levels = 1; | 185 | params.emulated_levels = 1; |
| 191 | params.is_layered = false; | 186 | |
| 187 | const bool is_layered = regs.zeta_layers > 1 && params.block_depth == 0; | ||
| 188 | params.is_layered = is_layered; | ||
| 189 | params.target = is_layered ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D; | ||
| 190 | params.depth = is_layered ? regs.zeta_layers.Value() : 1U; | ||
| 192 | return params; | 191 | return params; |
| 193 | } | 192 | } |
| 194 | 193 | ||
| @@ -214,11 +213,13 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz | |||
| 214 | params.width = params.pitch / bpp; | 213 | params.width = params.pitch / bpp; |
| 215 | } | 214 | } |
| 216 | params.height = config.height; | 215 | params.height = config.height; |
| 217 | params.depth = 1; | ||
| 218 | params.target = SurfaceTarget::Texture2D; | ||
| 219 | params.num_levels = 1; | 216 | params.num_levels = 1; |
| 220 | params.emulated_levels = 1; | 217 | params.emulated_levels = 1; |
| 221 | params.is_layered = false; | 218 | |
| 219 | const bool is_layered = config.layers > 1 && params.block_depth == 0; | ||
| 220 | params.is_layered = is_layered; | ||
| 221 | params.depth = is_layered ? config.layers.Value() : 1; | ||
| 222 | params.target = is_layered ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D; | ||
| 222 | return params; | 223 | return params; |
| 223 | } | 224 | } |
| 224 | 225 | ||
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index 9256fd6d9..995cc3818 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -35,10 +35,7 @@ public: | |||
| 35 | const VideoCommon::Shader::Image& entry); | 35 | const VideoCommon::Shader::Image& entry); |
| 36 | 36 | ||
| 37 | /// Creates SurfaceCachedParams for a depth buffer configuration. | 37 | /// Creates SurfaceCachedParams for a depth buffer configuration. |
| 38 | static SurfaceParams CreateForDepthBuffer( | 38 | static SurfaceParams CreateForDepthBuffer(Core::System& system); |
| 39 | Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format, | ||
| 40 | u32 block_width, u32 block_height, u32 block_depth, | ||
| 41 | Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type); | ||
| 42 | 39 | ||
| 43 | /// Creates SurfaceCachedParams from a framebuffer configuration. | 40 | /// Creates SurfaceCachedParams from a framebuffer configuration. |
| 44 | static SurfaceParams CreateForFramebuffer(Core::System& system, std::size_t index); | 41 | static SurfaceParams CreateForFramebuffer(Core::System& system, std::size_t index); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0d105d386..c70e4aec2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -160,10 +160,7 @@ public: | |||
| 160 | SetEmptyDepthBuffer(); | 160 | SetEmptyDepthBuffer(); |
| 161 | return {}; | 161 | return {}; |
| 162 | } | 162 | } |
| 163 | const auto depth_params{SurfaceParams::CreateForDepthBuffer( | 163 | const auto depth_params{SurfaceParams::CreateForDepthBuffer(system)}; |
| 164 | system, regs.zeta_width, regs.zeta_height, regs.zeta.format, | ||
| 165 | regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, | ||
| 166 | regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; | ||
| 167 | auto surface_view = GetSurface(gpu_addr, cache_addr, depth_params, preserve_contents, true); | 164 | auto surface_view = GetSurface(gpu_addr, cache_addr, depth_params, preserve_contents, true); |
| 168 | if (depth_buffer.target) | 165 | if (depth_buffer.target) |
| 169 | depth_buffer.target->MarkAsRenderTarget(false, NO_RT); | 166 | depth_buffer.target->MarkAsRenderTarget(false, NO_RT); |