diff options
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 53 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 76 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 33 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_base.h | 13 | ||||
| -rw-r--r-- | src/video_core/texture_cache/surface_params.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 119 |
10 files changed, 205 insertions, 131 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index b827b112f..79fc9bbea 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -598,6 +598,7 @@ public: | |||
| 598 | BitField<4, 3, u32> block_height; | 598 | BitField<4, 3, u32> block_height; |
| 599 | BitField<8, 3, u32> block_depth; | 599 | BitField<8, 3, u32> block_depth; |
| 600 | BitField<12, 1, InvMemoryLayout> type; | 600 | BitField<12, 1, InvMemoryLayout> type; |
| 601 | BitField<16, 1, u32> is_3d; | ||
| 601 | } memory_layout; | 602 | } memory_layout; |
| 602 | union { | 603 | union { |
| 603 | BitField<0, 16, u32> layers; | 604 | BitField<0, 16, u32> layers; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 57db5a08b..61505879b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -263,9 +263,14 @@ CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& param | |||
| 263 | target = GetTextureTarget(params.target); | 263 | target = GetTextureTarget(params.target); |
| 264 | texture = CreateTexture(params, target, internal_format, texture_buffer); | 264 | texture = CreateTexture(params, target, internal_format, texture_buffer); |
| 265 | DecorateSurfaceName(); | 265 | DecorateSurfaceName(); |
| 266 | main_view = CreateViewInner( | 266 | |
| 267 | ViewParams(params.target, 0, params.is_layered ? params.depth : 1, 0, params.num_levels), | 267 | u32 num_layers = 1; |
| 268 | true); | 268 | if (params.is_layered || params.target == SurfaceTarget::Texture3D) { |
| 269 | num_layers = params.depth; | ||
| 270 | } | ||
| 271 | |||
| 272 | main_view = | ||
| 273 | CreateViewInner(ViewParams(params.target, 0, num_layers, 0, params.num_levels), true); | ||
| 269 | } | 274 | } |
| 270 | 275 | ||
| 271 | CachedSurface::~CachedSurface() = default; | 276 | CachedSurface::~CachedSurface() = default; |
| @@ -413,20 +418,23 @@ CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& p | |||
| 413 | 418 | ||
| 414 | CachedSurfaceView::~CachedSurfaceView() = default; | 419 | CachedSurfaceView::~CachedSurfaceView() = default; |
| 415 | 420 | ||
| 416 | void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { | 421 | void CachedSurfaceView::Attach(GLenum attachment, GLenum fb_target) const { |
| 417 | ASSERT(params.num_levels == 1); | 422 | ASSERT(params.num_levels == 1); |
| 418 | 423 | ||
| 424 | if (params.target == SurfaceTarget::Texture3D) { | ||
| 425 | if (params.num_layers > 1) { | ||
| 426 | ASSERT(params.base_layer == 0); | ||
| 427 | glFramebufferTexture(fb_target, attachment, surface.texture.handle, params.base_level); | ||
| 428 | } else { | ||
| 429 | glFramebufferTexture3D(fb_target, attachment, target, surface.texture.handle, | ||
| 430 | params.base_level, params.base_layer); | ||
| 431 | } | ||
| 432 | return; | ||
| 433 | } | ||
| 434 | |||
| 419 | if (params.num_layers > 1) { | 435 | if (params.num_layers > 1) { |
| 420 | // Layered framebuffer attachments | ||
| 421 | UNIMPLEMENTED_IF(params.base_layer != 0); | 436 | UNIMPLEMENTED_IF(params.base_layer != 0); |
| 422 | 437 | glFramebufferTexture(fb_target, attachment, GetTexture(), 0); | |
| 423 | switch (params.target) { | ||
| 424 | case SurfaceTarget::Texture2DArray: | ||
| 425 | glFramebufferTexture(target, attachment, GetTexture(), 0); | ||
| 426 | break; | ||
| 427 | default: | ||
| 428 | UNIMPLEMENTED(); | ||
| 429 | } | ||
| 430 | return; | 438 | return; |
| 431 | } | 439 | } |
| 432 | 440 | ||
| @@ -434,16 +442,16 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const { | |||
| 434 | const GLuint texture = surface.GetTexture(); | 442 | const GLuint texture = surface.GetTexture(); |
| 435 | switch (surface.GetSurfaceParams().target) { | 443 | switch (surface.GetSurfaceParams().target) { |
| 436 | case SurfaceTarget::Texture1D: | 444 | case SurfaceTarget::Texture1D: |
| 437 | glFramebufferTexture1D(target, attachment, view_target, texture, params.base_level); | 445 | glFramebufferTexture1D(fb_target, attachment, view_target, texture, params.base_level); |
| 438 | break; | 446 | break; |
| 439 | case SurfaceTarget::Texture2D: | 447 | case SurfaceTarget::Texture2D: |
| 440 | glFramebufferTexture2D(target, attachment, view_target, texture, params.base_level); | 448 | glFramebufferTexture2D(fb_target, attachment, view_target, texture, params.base_level); |
| 441 | break; | 449 | break; |
| 442 | case SurfaceTarget::Texture1DArray: | 450 | case SurfaceTarget::Texture1DArray: |
| 443 | case SurfaceTarget::Texture2DArray: | 451 | case SurfaceTarget::Texture2DArray: |
| 444 | case SurfaceTarget::TextureCubemap: | 452 | case SurfaceTarget::TextureCubemap: |
| 445 | case SurfaceTarget::TextureCubeArray: | 453 | case SurfaceTarget::TextureCubeArray: |
| 446 | glFramebufferTextureLayer(target, attachment, texture, params.base_level, | 454 | glFramebufferTextureLayer(fb_target, attachment, texture, params.base_level, |
| 447 | params.base_layer); | 455 | params.base_layer); |
| 448 | break; | 456 | break; |
| 449 | default: | 457 | default: |
| @@ -500,8 +508,13 @@ OGLTextureView CachedSurfaceView::CreateTextureView() const { | |||
| 500 | OGLTextureView texture_view; | 508 | OGLTextureView texture_view; |
| 501 | texture_view.Create(); | 509 | texture_view.Create(); |
| 502 | 510 | ||
| 503 | glTextureView(texture_view.handle, target, surface.texture.handle, format, params.base_level, | 511 | if (target == GL_TEXTURE_3D) { |
| 504 | params.num_levels, params.base_layer, params.num_layers); | 512 | glTextureView(texture_view.handle, target, surface.texture.handle, format, |
| 513 | params.base_level, params.num_levels, 0, 1); | ||
| 514 | } else { | ||
| 515 | glTextureView(texture_view.handle, target, surface.texture.handle, format, | ||
| 516 | params.base_level, params.num_levels, params.base_layer, params.num_layers); | ||
| 517 | } | ||
| 505 | ApplyTextureDefaults(surface.GetSurfaceParams(), texture_view.handle); | 518 | ApplyTextureDefaults(surface.GetSurfaceParams(), texture_view.handle); |
| 506 | 519 | ||
| 507 | return texture_view; | 520 | return texture_view; |
| @@ -544,8 +557,8 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view, | |||
| 544 | const Tegra::Engines::Fermi2D::Config& copy_config) { | 557 | const Tegra::Engines::Fermi2D::Config& copy_config) { |
| 545 | const auto& src_params{src_view->GetSurfaceParams()}; | 558 | const auto& src_params{src_view->GetSurfaceParams()}; |
| 546 | const auto& dst_params{dst_view->GetSurfaceParams()}; | 559 | const auto& dst_params{dst_view->GetSurfaceParams()}; |
| 547 | UNIMPLEMENTED_IF(src_params.target == SurfaceTarget::Texture3D); | 560 | UNIMPLEMENTED_IF(src_params.depth != 1); |
| 548 | UNIMPLEMENTED_IF(dst_params.target == SurfaceTarget::Texture3D); | 561 | UNIMPLEMENTED_IF(dst_params.depth != 1); |
| 549 | 562 | ||
| 550 | state_tracker.NotifyScissor0(); | 563 | state_tracker.NotifyScissor0(); |
| 551 | state_tracker.NotifyFramebuffer(); | 564 | state_tracker.NotifyFramebuffer(); |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 8a2ac8603..bfc4ddf5d 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -80,8 +80,10 @@ public: | |||
| 80 | explicit CachedSurfaceView(CachedSurface& surface, const ViewParams& params, bool is_proxy); | 80 | explicit CachedSurfaceView(CachedSurface& surface, const ViewParams& params, bool is_proxy); |
| 81 | ~CachedSurfaceView(); | 81 | ~CachedSurfaceView(); |
| 82 | 82 | ||
| 83 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER | 83 | /// @brief Attaches this texture view to the currently bound fb_target framebuffer |
| 84 | void Attach(GLenum attachment, GLenum target) const; | 84 | /// @param attachment Attachment to bind textures to |
| 85 | /// @param fb_target Framebuffer target to attach to (e.g. DRAW_FRAMEBUFFER) | ||
| 86 | void Attach(GLenum attachment, GLenum fb_target) const; | ||
| 85 | 87 | ||
| 86 | GLuint GetTexture(Tegra::Texture::SwizzleSource x_source, | 88 | GLuint GetTexture(Tegra::Texture::SwizzleSource x_source, |
| 87 | Tegra::Texture::SwizzleSource y_source, | 89 | Tegra::Texture::SwizzleSource y_source, |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d86c46412..19b8f9da3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -716,7 +716,7 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers( | |||
| 716 | if (!view) { | 716 | if (!view) { |
| 717 | return false; | 717 | return false; |
| 718 | } | 718 | } |
| 719 | key.views.push_back(view->GetHandle()); | 719 | key.views.push_back(view->GetAttachment()); |
| 720 | key.width = std::min(key.width, view->GetWidth()); | 720 | key.width = std::min(key.width, view->GetWidth()); |
| 721 | key.height = std::min(key.height, view->GetHeight()); | 721 | key.height = std::min(key.height, view->GetHeight()); |
| 722 | key.layers = std::min(key.layers, view->GetNumLayers()); | 722 | key.layers = std::min(key.layers, view->GetNumLayers()); |
| @@ -1137,8 +1137,8 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu | |||
| 1137 | auto view = texture_cache.GetTextureSurface(texture.tic, entry); | 1137 | auto view = texture_cache.GetTextureSurface(texture.tic, entry); |
| 1138 | ASSERT(!view->IsBufferView()); | 1138 | ASSERT(!view->IsBufferView()); |
| 1139 | 1139 | ||
| 1140 | const auto image_view = view->GetHandle(texture.tic.x_source, texture.tic.y_source, | 1140 | const VkImageView image_view = view->GetImageView(texture.tic.x_source, texture.tic.y_source, |
| 1141 | texture.tic.z_source, texture.tic.w_source); | 1141 | texture.tic.z_source, texture.tic.w_source); |
| 1142 | const auto sampler = sampler_cache.GetSampler(texture.tsc); | 1142 | const auto sampler = sampler_cache.GetSampler(texture.tsc); |
| 1143 | update_descriptor_queue.AddSampledImage(sampler, image_view); | 1143 | update_descriptor_queue.AddSampledImage(sampler, image_view); |
| 1144 | 1144 | ||
| @@ -1164,7 +1164,8 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima | |||
| 1164 | 1164 | ||
| 1165 | UNIMPLEMENTED_IF(tic.IsBuffer()); | 1165 | UNIMPLEMENTED_IF(tic.IsBuffer()); |
| 1166 | 1166 | ||
| 1167 | const auto image_view = view->GetHandle(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | 1167 | const VkImageView image_view = |
| 1168 | view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | ||
| 1168 | update_descriptor_queue.AddImage(image_view); | 1169 | update_descriptor_queue.AddImage(image_view); |
| 1169 | 1170 | ||
| 1170 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); | 1171 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index ea487b770..430031665 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -167,6 +167,7 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP | |||
| 167 | ci.extent = {params.width, params.height, 1}; | 167 | ci.extent = {params.width, params.height, 1}; |
| 168 | break; | 168 | break; |
| 169 | case SurfaceTarget::Texture3D: | 169 | case SurfaceTarget::Texture3D: |
| 170 | ci.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; | ||
| 170 | ci.extent = {params.width, params.height, params.depth}; | 171 | ci.extent = {params.width, params.height, params.depth}; |
| 171 | break; | 172 | break; |
| 172 | case SurfaceTarget::TextureBuffer: | 173 | case SurfaceTarget::TextureBuffer: |
| @@ -176,6 +177,12 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP | |||
| 176 | return ci; | 177 | return ci; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 180 | u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, Tegra::Texture::SwizzleSource y_source, | ||
| 181 | Tegra::Texture::SwizzleSource z_source, Tegra::Texture::SwizzleSource w_source) { | ||
| 182 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 183 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 184 | } | ||
| 185 | |||
| 179 | } // Anonymous namespace | 186 | } // Anonymous namespace |
| 180 | 187 | ||
| 181 | CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, | 188 | CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, |
| @@ -203,9 +210,11 @@ CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, | |||
| 203 | } | 210 | } |
| 204 | 211 | ||
| 205 | // TODO(Rodrigo): Move this to a virtual function. | 212 | // TODO(Rodrigo): Move this to a virtual function. |
| 206 | main_view = CreateViewInner( | 213 | u32 num_layers = 1; |
| 207 | ViewParams(params.target, 0, static_cast<u32>(params.GetNumLayers()), 0, params.num_levels), | 214 | if (params.is_layered || params.target == SurfaceTarget::Texture3D) { |
| 208 | true); | 215 | num_layers = params.depth; |
| 216 | } | ||
| 217 | main_view = CreateView(ViewParams(params.target, 0, num_layers, 0, params.num_levels)); | ||
| 209 | } | 218 | } |
| 210 | 219 | ||
| 211 | CachedSurface::~CachedSurface() = default; | 220 | CachedSurface::~CachedSurface() = default; |
| @@ -253,12 +262,8 @@ void CachedSurface::DecorateSurfaceName() { | |||
| 253 | } | 262 | } |
| 254 | 263 | ||
| 255 | View CachedSurface::CreateView(const ViewParams& params) { | 264 | View CachedSurface::CreateView(const ViewParams& params) { |
| 256 | return CreateViewInner(params, false); | ||
| 257 | } | ||
| 258 | |||
| 259 | View CachedSurface::CreateViewInner(const ViewParams& params, bool is_proxy) { | ||
| 260 | // TODO(Rodrigo): Add name decorations | 265 | // TODO(Rodrigo): Add name decorations |
| 261 | return views[params] = std::make_shared<CachedSurfaceView>(device, *this, params, is_proxy); | 266 | return views[params] = std::make_shared<CachedSurfaceView>(device, *this, params); |
| 262 | } | 267 | } |
| 263 | 268 | ||
| 264 | void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) { | 269 | void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) { |
| @@ -342,18 +347,27 @@ VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { | |||
| 342 | } | 347 | } |
| 343 | 348 | ||
| 344 | CachedSurfaceView::CachedSurfaceView(const VKDevice& device, CachedSurface& surface, | 349 | CachedSurfaceView::CachedSurfaceView(const VKDevice& device, CachedSurface& surface, |
| 345 | const ViewParams& params, bool is_proxy) | 350 | const ViewParams& params) |
| 346 | : VideoCommon::ViewBase{params}, params{surface.GetSurfaceParams()}, | 351 | : VideoCommon::ViewBase{params}, params{surface.GetSurfaceParams()}, |
| 347 | image{surface.GetImageHandle()}, buffer_view{surface.GetBufferViewHandle()}, | 352 | image{surface.GetImageHandle()}, buffer_view{surface.GetBufferViewHandle()}, |
| 348 | aspect_mask{surface.GetAspectMask()}, device{device}, surface{surface}, | 353 | aspect_mask{surface.GetAspectMask()}, device{device}, surface{surface}, |
| 349 | base_layer{params.base_layer}, num_layers{params.num_layers}, base_level{params.base_level}, | 354 | base_level{params.base_level}, num_levels{params.num_levels}, |
| 350 | num_levels{params.num_levels}, image_view_type{image ? GetImageViewType(params.target) | 355 | image_view_type{image ? GetImageViewType(params.target) : VK_IMAGE_VIEW_TYPE_1D} { |
| 351 | : VK_IMAGE_VIEW_TYPE_1D} {} | 356 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { |
| 357 | base_layer = 0; | ||
| 358 | num_layers = 1; | ||
| 359 | base_slice = params.base_layer; | ||
| 360 | num_slices = params.num_layers; | ||
| 361 | } else { | ||
| 362 | base_layer = params.base_layer; | ||
| 363 | num_layers = params.num_layers; | ||
| 364 | } | ||
| 365 | } | ||
| 352 | 366 | ||
| 353 | CachedSurfaceView::~CachedSurfaceView() = default; | 367 | CachedSurfaceView::~CachedSurfaceView() = default; |
| 354 | 368 | ||
| 355 | VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source, | 369 | VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSource y_source, |
| 356 | SwizzleSource z_source, SwizzleSource w_source) { | 370 | SwizzleSource z_source, SwizzleSource w_source) { |
| 357 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); | 371 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); |
| 358 | if (last_image_view && last_swizzle == new_swizzle) { | 372 | if (last_image_view && last_swizzle == new_swizzle) { |
| 359 | return last_image_view; | 373 | return last_image_view; |
| @@ -399,6 +413,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 399 | }); | 413 | }); |
| 400 | } | 414 | } |
| 401 | 415 | ||
| 416 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { | ||
| 417 | ASSERT(base_slice == 0); | ||
| 418 | ASSERT(num_slices == params.depth); | ||
| 419 | } | ||
| 420 | |||
| 402 | VkImageViewCreateInfo ci; | 421 | VkImageViewCreateInfo ci; |
| 403 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 422 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; |
| 404 | ci.pNext = nullptr; | 423 | ci.pNext = nullptr; |
| @@ -417,6 +436,35 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 417 | return last_image_view = *image_view; | 436 | return last_image_view = *image_view; |
| 418 | } | 437 | } |
| 419 | 438 | ||
| 439 | VkImageView CachedSurfaceView::GetAttachment() { | ||
| 440 | if (render_target) { | ||
| 441 | return *render_target; | ||
| 442 | } | ||
| 443 | |||
| 444 | VkImageViewCreateInfo ci; | ||
| 445 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | ||
| 446 | ci.pNext = nullptr; | ||
| 447 | ci.flags = 0; | ||
| 448 | ci.image = surface.GetImageHandle(); | ||
| 449 | ci.format = surface.GetImage().GetFormat(); | ||
| 450 | ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 451 | VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; | ||
| 452 | ci.subresourceRange.aspectMask = aspect_mask; | ||
| 453 | ci.subresourceRange.baseMipLevel = base_level; | ||
| 454 | ci.subresourceRange.levelCount = num_levels; | ||
| 455 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { | ||
| 456 | ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; | ||
| 457 | ci.subresourceRange.baseArrayLayer = base_slice; | ||
| 458 | ci.subresourceRange.layerCount = num_slices; | ||
| 459 | } else { | ||
| 460 | ci.viewType = image_view_type; | ||
| 461 | ci.subresourceRange.baseArrayLayer = base_layer; | ||
| 462 | ci.subresourceRange.layerCount = num_layers; | ||
| 463 | } | ||
| 464 | render_target = device.GetLogical().CreateImageView(ci); | ||
| 465 | return *render_target; | ||
| 466 | } | ||
| 467 | |||
| 420 | VKTextureCache::VKTextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 468 | VKTextureCache::VKTextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, |
| 421 | const VKDevice& device, VKResourceManager& resource_manager, | 469 | const VKDevice& device, VKResourceManager& resource_manager, |
| 422 | VKMemoryManager& memory_manager, VKScheduler& scheduler, | 470 | VKMemoryManager& memory_manager, VKScheduler& scheduler, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index f211ccb1e..807e26c8a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -91,7 +91,6 @@ protected: | |||
| 91 | void DecorateSurfaceName(); | 91 | void DecorateSurfaceName(); |
| 92 | 92 | ||
| 93 | View CreateView(const ViewParams& params) override; | 93 | View CreateView(const ViewParams& params) override; |
| 94 | View CreateViewInner(const ViewParams& params, bool is_proxy); | ||
| 95 | 94 | ||
| 96 | private: | 95 | private: |
| 97 | void UploadBuffer(const std::vector<u8>& staging_buffer); | 96 | void UploadBuffer(const std::vector<u8>& staging_buffer); |
| @@ -120,23 +119,20 @@ private: | |||
| 120 | class CachedSurfaceView final : public VideoCommon::ViewBase { | 119 | class CachedSurfaceView final : public VideoCommon::ViewBase { |
| 121 | public: | 120 | public: |
| 122 | explicit CachedSurfaceView(const VKDevice& device, CachedSurface& surface, | 121 | explicit CachedSurfaceView(const VKDevice& device, CachedSurface& surface, |
| 123 | const ViewParams& params, bool is_proxy); | 122 | const ViewParams& params); |
| 124 | ~CachedSurfaceView(); | 123 | ~CachedSurfaceView(); |
| 125 | 124 | ||
| 126 | VkImageView GetHandle(Tegra::Texture::SwizzleSource x_source, | 125 | VkImageView GetImageView(Tegra::Texture::SwizzleSource x_source, |
| 127 | Tegra::Texture::SwizzleSource y_source, | 126 | Tegra::Texture::SwizzleSource y_source, |
| 128 | Tegra::Texture::SwizzleSource z_source, | 127 | Tegra::Texture::SwizzleSource z_source, |
| 129 | Tegra::Texture::SwizzleSource w_source); | 128 | Tegra::Texture::SwizzleSource w_source); |
| 129 | |||
| 130 | VkImageView GetAttachment(); | ||
| 130 | 131 | ||
| 131 | bool IsSameSurface(const CachedSurfaceView& rhs) const { | 132 | bool IsSameSurface(const CachedSurfaceView& rhs) const { |
| 132 | return &surface == &rhs.surface; | 133 | return &surface == &rhs.surface; |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | VkImageView GetHandle() { | ||
| 136 | return GetHandle(Tegra::Texture::SwizzleSource::R, Tegra::Texture::SwizzleSource::G, | ||
| 137 | Tegra::Texture::SwizzleSource::B, Tegra::Texture::SwizzleSource::A); | ||
| 138 | } | ||
| 139 | |||
| 140 | u32 GetWidth() const { | 136 | u32 GetWidth() const { |
| 141 | return params.GetMipWidth(base_level); | 137 | return params.GetMipWidth(base_level); |
| 142 | } | 138 | } |
| @@ -180,14 +176,6 @@ public: | |||
| 180 | } | 176 | } |
| 181 | 177 | ||
| 182 | private: | 178 | private: |
| 183 | static u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, | ||
| 184 | Tegra::Texture::SwizzleSource y_source, | ||
| 185 | Tegra::Texture::SwizzleSource z_source, | ||
| 186 | Tegra::Texture::SwizzleSource w_source) { | ||
| 187 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 188 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 189 | } | ||
| 190 | |||
| 191 | // Store a copy of these values to avoid double dereference when reading them | 179 | // Store a copy of these values to avoid double dereference when reading them |
| 192 | const SurfaceParams params; | 180 | const SurfaceParams params; |
| 193 | const VkImage image; | 181 | const VkImage image; |
| @@ -196,15 +184,18 @@ private: | |||
| 196 | 184 | ||
| 197 | const VKDevice& device; | 185 | const VKDevice& device; |
| 198 | CachedSurface& surface; | 186 | CachedSurface& surface; |
| 199 | const u32 base_layer; | ||
| 200 | const u32 num_layers; | ||
| 201 | const u32 base_level; | 187 | const u32 base_level; |
| 202 | const u32 num_levels; | 188 | const u32 num_levels; |
| 203 | const VkImageViewType image_view_type; | 189 | const VkImageViewType image_view_type; |
| 190 | u32 base_layer = 0; | ||
| 191 | u32 num_layers = 0; | ||
| 192 | u32 base_slice = 0; | ||
| 193 | u32 num_slices = 0; | ||
| 204 | 194 | ||
| 205 | VkImageView last_image_view = nullptr; | 195 | VkImageView last_image_view = nullptr; |
| 206 | u32 last_swizzle = 0; | 196 | u32 last_swizzle = 0; |
| 207 | 197 | ||
| 198 | vk::ImageView render_target; | ||
| 208 | std::unordered_map<u32, vk::ImageView> view_cache; | 199 | std::unordered_map<u32, vk::ImageView> view_cache; |
| 209 | }; | 200 | }; |
| 210 | 201 | ||
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 715f39d0d..94d3a6ae5 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -248,12 +248,11 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager, | |||
| 248 | 248 | ||
| 249 | // Use an extra temporal buffer | 249 | // Use an extra temporal buffer |
| 250 | auto& tmp_buffer = staging_cache.GetBuffer(1); | 250 | auto& tmp_buffer = staging_cache.GetBuffer(1); |
| 251 | // Special case for 3D Texture Segments | ||
| 252 | const bool must_read_current_data = | ||
| 253 | params.block_depth > 0 && params.target == VideoCore::Surface::SurfaceTarget::Texture2D; | ||
| 254 | tmp_buffer.resize(guest_memory_size); | 251 | tmp_buffer.resize(guest_memory_size); |
| 255 | host_ptr = tmp_buffer.data(); | 252 | host_ptr = tmp_buffer.data(); |
| 256 | if (must_read_current_data) { | 253 | |
| 254 | if (params.target == SurfaceTarget::Texture3D) { | ||
| 255 | // Special case for 3D texture segments | ||
| 257 | memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); | 256 | memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size); |
| 258 | } | 257 | } |
| 259 | 258 | ||
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 79e10ffbb..173f2edba 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -217,8 +217,8 @@ public: | |||
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | bool IsProtected() const { | 219 | bool IsProtected() const { |
| 220 | // Only 3D Slices are to be protected | 220 | // Only 3D slices are to be protected |
| 221 | return is_target && params.block_depth > 0; | 221 | return is_target && params.target == SurfaceTarget::Texture3D; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | bool IsRenderTarget() const { | 224 | bool IsRenderTarget() const { |
| @@ -250,6 +250,11 @@ public: | |||
| 250 | return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels)); | 250 | return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels)); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | TView Emplace3DView(u32 slice, u32 depth, u32 base_level, u32 num_levels) { | ||
| 254 | return GetView(ViewParams(VideoCore::Surface::SurfaceTarget::Texture3D, slice, depth, | ||
| 255 | base_level, num_levels)); | ||
| 256 | } | ||
| 257 | |||
| 253 | std::optional<TView> EmplaceIrregularView(const SurfaceParams& view_params, | 258 | std::optional<TView> EmplaceIrregularView(const SurfaceParams& view_params, |
| 254 | const GPUVAddr view_addr, | 259 | const GPUVAddr view_addr, |
| 255 | const std::size_t candidate_size, const u32 mipmap, | 260 | const std::size_t candidate_size, const u32 mipmap, |
| @@ -272,8 +277,8 @@ public: | |||
| 272 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr, | 277 | std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr, |
| 273 | const std::size_t candidate_size) { | 278 | const std::size_t candidate_size) { |
| 274 | if (params.target == SurfaceTarget::Texture3D || | 279 | if (params.target == SurfaceTarget::Texture3D || |
| 275 | (params.num_levels == 1 && !params.is_layered) || | 280 | view_params.target == SurfaceTarget::Texture3D || |
| 276 | view_params.target == SurfaceTarget::Texture3D) { | 281 | (params.num_levels == 1 && !params.is_layered)) { |
| 277 | return {}; | 282 | return {}; |
| 278 | } | 283 | } |
| 279 | const auto layer_mipmap{GetLayerMipmap(view_addr)}; | 284 | const auto layer_mipmap{GetLayerMipmap(view_addr)}; |
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 884fabffe..0b2b2b8c4 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -215,10 +215,19 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz | |||
| 215 | params.num_levels = 1; | 215 | params.num_levels = 1; |
| 216 | params.emulated_levels = 1; | 216 | params.emulated_levels = 1; |
| 217 | 217 | ||
| 218 | const bool is_layered = config.layers > 1 && params.block_depth == 0; | 218 | if (config.memory_layout.is_3d != 0) { |
| 219 | params.is_layered = is_layered; | 219 | params.depth = config.layers.Value(); |
| 220 | params.depth = is_layered ? config.layers.Value() : 1; | 220 | params.is_layered = false; |
| 221 | params.target = is_layered ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D; | 221 | params.target = SurfaceTarget::Texture3D; |
| 222 | } else if (config.layers > 1) { | ||
| 223 | params.depth = config.layers.Value(); | ||
| 224 | params.is_layered = true; | ||
| 225 | params.target = SurfaceTarget::Texture2DArray; | ||
| 226 | } else { | ||
| 227 | params.depth = 1; | ||
| 228 | params.is_layered = false; | ||
| 229 | params.target = SurfaceTarget::Texture2D; | ||
| 230 | } | ||
| 222 | return params; | 231 | return params; |
| 223 | } | 232 | } |
| 224 | 233 | ||
| @@ -237,7 +246,7 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface( | |||
| 237 | params.width = config.width; | 246 | params.width = config.width; |
| 238 | params.height = config.height; | 247 | params.height = config.height; |
| 239 | params.pitch = config.pitch; | 248 | params.pitch = config.pitch; |
| 240 | // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters | 249 | // TODO(Rodrigo): Try to guess texture arrays from parameters |
| 241 | params.target = SurfaceTarget::Texture2D; | 250 | params.target = SurfaceTarget::Texture2D; |
| 242 | params.depth = 1; | 251 | params.depth = 1; |
| 243 | params.num_levels = 1; | 252 | params.num_levels = 1; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6f63217a2..b543fc8c0 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -298,15 +298,13 @@ public: | |||
| 298 | const GPUVAddr src_gpu_addr = src_config.Address(); | 298 | const GPUVAddr src_gpu_addr = src_config.Address(); |
| 299 | const GPUVAddr dst_gpu_addr = dst_config.Address(); | 299 | const GPUVAddr dst_gpu_addr = dst_config.Address(); |
| 300 | DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr); | 300 | DeduceBestBlit(src_params, dst_params, src_gpu_addr, dst_gpu_addr); |
| 301 | const std::optional<VAddr> dst_cpu_addr = | 301 | |
| 302 | system.GPU().MemoryManager().GpuToCpuAddress(dst_gpu_addr); | 302 | const auto& memory_manager = system.GPU().MemoryManager(); |
| 303 | const std::optional<VAddr> src_cpu_addr = | 303 | const std::optional<VAddr> dst_cpu_addr = memory_manager.GpuToCpuAddress(dst_gpu_addr); |
| 304 | system.GPU().MemoryManager().GpuToCpuAddress(src_gpu_addr); | 304 | const std::optional<VAddr> src_cpu_addr = memory_manager.GpuToCpuAddress(src_gpu_addr); |
| 305 | std::pair<TSurface, TView> dst_surface = | 305 | std::pair dst_surface = GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, true, false); |
| 306 | GetSurface(dst_gpu_addr, *dst_cpu_addr, dst_params, true, false); | 306 | TView src_surface = GetSurface(src_gpu_addr, *src_cpu_addr, src_params, true, false).second; |
| 307 | std::pair<TSurface, TView> src_surface = | 307 | ImageBlit(src_surface, dst_surface.second, copy_config); |
| 308 | GetSurface(src_gpu_addr, *src_cpu_addr, src_params, true, false); | ||
| 309 | ImageBlit(src_surface.second, dst_surface.second, copy_config); | ||
| 310 | dst_surface.first->MarkAsModified(true, Tick()); | 308 | dst_surface.first->MarkAsModified(true, Tick()); |
| 311 | } | 309 | } |
| 312 | 310 | ||
| @@ -508,12 +506,12 @@ private: | |||
| 508 | return RecycleStrategy::Flush; | 506 | return RecycleStrategy::Flush; |
| 509 | } | 507 | } |
| 510 | // 3D Textures decision | 508 | // 3D Textures decision |
| 511 | if (params.block_depth > 1 || params.target == SurfaceTarget::Texture3D) { | 509 | if (params.target == SurfaceTarget::Texture3D) { |
| 512 | return RecycleStrategy::Flush; | 510 | return RecycleStrategy::Flush; |
| 513 | } | 511 | } |
| 514 | for (const auto& s : overlaps) { | 512 | for (const auto& s : overlaps) { |
| 515 | const auto& s_params = s->GetSurfaceParams(); | 513 | const auto& s_params = s->GetSurfaceParams(); |
| 516 | if (s_params.block_depth > 1 || s_params.target == SurfaceTarget::Texture3D) { | 514 | if (s_params.target == SurfaceTarget::Texture3D) { |
| 517 | return RecycleStrategy::Flush; | 515 | return RecycleStrategy::Flush; |
| 518 | } | 516 | } |
| 519 | } | 517 | } |
| @@ -731,51 +729,9 @@ private: | |||
| 731 | */ | 729 | */ |
| 732 | std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(VectorSurface& overlaps, | 730 | std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(VectorSurface& overlaps, |
| 733 | const SurfaceParams& params, | 731 | const SurfaceParams& params, |
| 734 | const GPUVAddr gpu_addr, | 732 | GPUVAddr gpu_addr, VAddr cpu_addr, |
| 735 | const VAddr cpu_addr, | ||
| 736 | bool preserve_contents) { | 733 | bool preserve_contents) { |
| 737 | if (params.target == SurfaceTarget::Texture3D) { | 734 | if (params.target != SurfaceTarget::Texture3D) { |
| 738 | bool failed = false; | ||
| 739 | if (params.num_levels > 1) { | ||
| 740 | // We can't handle mipmaps in 3D textures yet, better fallback to LLE approach | ||
| 741 | return std::nullopt; | ||
| 742 | } | ||
| 743 | TSurface new_surface = GetUncachedSurface(gpu_addr, params); | ||
| 744 | bool modified = false; | ||
| 745 | for (auto& surface : overlaps) { | ||
| 746 | const SurfaceParams& src_params = surface->GetSurfaceParams(); | ||
| 747 | if (src_params.target != SurfaceTarget::Texture2D) { | ||
| 748 | failed = true; | ||
| 749 | break; | ||
| 750 | } | ||
| 751 | if (src_params.height != params.height) { | ||
| 752 | failed = true; | ||
| 753 | break; | ||
| 754 | } | ||
| 755 | if (src_params.block_depth != params.block_depth || | ||
| 756 | src_params.block_height != params.block_height) { | ||
| 757 | failed = true; | ||
| 758 | break; | ||
| 759 | } | ||
| 760 | const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr); | ||
| 761 | const auto offsets = params.GetBlockOffsetXYZ(offset); | ||
| 762 | const auto z = std::get<2>(offsets); | ||
| 763 | modified |= surface->IsModified(); | ||
| 764 | const CopyParams copy_params(0, 0, 0, 0, 0, z, 0, 0, params.width, params.height, | ||
| 765 | 1); | ||
| 766 | ImageCopy(surface, new_surface, copy_params); | ||
| 767 | } | ||
| 768 | if (failed) { | ||
| 769 | return std::nullopt; | ||
| 770 | } | ||
| 771 | for (const auto& surface : overlaps) { | ||
| 772 | Unregister(surface); | ||
| 773 | } | ||
| 774 | new_surface->MarkAsModified(modified, Tick()); | ||
| 775 | Register(new_surface); | ||
| 776 | auto view = new_surface->GetMainView(); | ||
| 777 | return {{std::move(new_surface), view}}; | ||
| 778 | } else { | ||
| 779 | for (const auto& surface : overlaps) { | 735 | for (const auto& surface : overlaps) { |
| 780 | if (!surface->MatchTarget(params.target)) { | 736 | if (!surface->MatchTarget(params.target)) { |
| 781 | if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) { | 737 | if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) { |
| @@ -791,11 +747,60 @@ private: | |||
| 791 | continue; | 747 | continue; |
| 792 | } | 748 | } |
| 793 | if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) { | 749 | if (surface->MatchesStructure(params) == MatchStructureResult::FullMatch) { |
| 794 | return {{surface, surface->GetMainView()}}; | 750 | return std::make_pair(surface, surface->GetMainView()); |
| 795 | } | 751 | } |
| 796 | } | 752 | } |
| 797 | return InitializeSurface(gpu_addr, params, preserve_contents); | 753 | return InitializeSurface(gpu_addr, params, preserve_contents); |
| 798 | } | 754 | } |
| 755 | |||
| 756 | if (params.num_levels > 1) { | ||
| 757 | // We can't handle mipmaps in 3D textures yet, better fallback to LLE approach | ||
| 758 | return std::nullopt; | ||
| 759 | } | ||
| 760 | |||
| 761 | if (overlaps.size() == 1) { | ||
| 762 | const auto& surface = overlaps[0]; | ||
| 763 | const SurfaceParams& overlap_params = surface->GetSurfaceParams(); | ||
| 764 | // Don't attempt to render to textures with more than one level for now | ||
| 765 | // The texture has to be to the right or the sample address if we want to render to it | ||
| 766 | if (overlap_params.num_levels == 1 && cpu_addr >= surface->GetCpuAddr()) { | ||
| 767 | const u32 offset = static_cast<u32>(cpu_addr - surface->GetCpuAddr()); | ||
| 768 | const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset)); | ||
| 769 | if (slice < overlap_params.depth) { | ||
| 770 | auto view = surface->Emplace3DView(slice, params.depth, 0, 1); | ||
| 771 | return std::make_pair(std::move(surface), std::move(view)); | ||
| 772 | } | ||
| 773 | } | ||
| 774 | } | ||
| 775 | |||
| 776 | TSurface new_surface = GetUncachedSurface(gpu_addr, params); | ||
| 777 | bool modified = false; | ||
| 778 | |||
| 779 | for (auto& surface : overlaps) { | ||
| 780 | const SurfaceParams& src_params = surface->GetSurfaceParams(); | ||
| 781 | if (src_params.target != SurfaceTarget::Texture2D || | ||
| 782 | src_params.height != params.height || | ||
| 783 | src_params.block_depth != params.block_depth || | ||
| 784 | src_params.block_height != params.block_height) { | ||
| 785 | return std::nullopt; | ||
| 786 | } | ||
| 787 | modified |= surface->IsModified(); | ||
| 788 | |||
| 789 | const u32 offset = static_cast<u32>(surface->GetCpuAddr() - cpu_addr); | ||
| 790 | const u32 slice = std::get<2>(params.GetBlockOffsetXYZ(offset)); | ||
| 791 | const u32 width = params.width; | ||
| 792 | const u32 height = params.height; | ||
| 793 | const CopyParams copy_params(0, 0, 0, 0, 0, slice, 0, 0, width, height, 1); | ||
| 794 | ImageCopy(surface, new_surface, copy_params); | ||
| 795 | } | ||
| 796 | for (const auto& surface : overlaps) { | ||
| 797 | Unregister(surface); | ||
| 798 | } | ||
| 799 | new_surface->MarkAsModified(modified, Tick()); | ||
| 800 | Register(new_surface); | ||
| 801 | |||
| 802 | TView view = new_surface->GetMainView(); | ||
| 803 | return std::make_pair(std::move(new_surface), std::move(view)); | ||
| 799 | } | 804 | } |
| 800 | 805 | ||
| 801 | /** | 806 | /** |
| @@ -873,7 +878,7 @@ private: | |||
| 873 | } | 878 | } |
| 874 | } | 879 | } |
| 875 | 880 | ||
| 876 | // Check if it's a 3D texture | 881 | // Manage 3D textures |
| 877 | if (params.block_depth > 0) { | 882 | if (params.block_depth > 0) { |
| 878 | auto surface = | 883 | auto surface = |
| 879 | Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents); | 884 | Manage3DSurfaces(overlaps, params, gpu_addr, cpu_addr, preserve_contents); |