diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 38 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 5 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 57 | ||||
| -rw-r--r-- | src/video_core/texture_cache/types.h | 7 |
8 files changed, 99 insertions, 61 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 623b43d8a..ffe9edc1b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -543,8 +543,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, |
| 546 | const std::array<Offset2D, 2>& dst_region, | 546 | const Region2D& dst_region, const Region2D& src_region, |
| 547 | const std::array<Offset2D, 2>& src_region, | ||
| 548 | Tegra::Engines::Fermi2D::Filter filter, | 547 | Tegra::Engines::Fermi2D::Filter filter, |
| 549 | Tegra::Engines::Fermi2D::Operation operation) { | 548 | Tegra::Engines::Fermi2D::Operation operation) { |
| 550 | state_tracker.NotifyScissor0(); | 549 | state_tracker.NotifyScissor0(); |
| @@ -560,9 +559,9 @@ void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | |||
| 560 | const GLbitfield buffer_bits = dst->BufferBits(); | 559 | const GLbitfield buffer_bits = dst->BufferBits(); |
| 561 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; | 560 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; |
| 562 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 561 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| 563 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region[0].x, src_region[0].y, | 562 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region.start.x, src_region.start.y, |
| 564 | src_region[1].x, src_region[1].y, dst_region[0].x, dst_region[0].y, | 563 | src_region.end.x, src_region.end.y, dst_region.start.x, |
| 565 | dst_region[1].x, dst_region[1].y, buffer_bits, | 564 | dst_region.start.y, dst_region.end.x, dst_region.end.y, buffer_bits, |
| 566 | is_linear ? GL_LINEAR : GL_NEAREST); | 565 | is_linear ? GL_LINEAR : GL_NEAREST); |
| 567 | } | 566 | } |
| 568 | 567 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3c871541b..df8be12ff 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -28,7 +28,7 @@ using VideoCommon::ImageId; | |||
| 28 | using VideoCommon::ImageViewId; | 28 | using VideoCommon::ImageViewId; |
| 29 | using VideoCommon::ImageViewType; | 29 | using VideoCommon::ImageViewType; |
| 30 | using VideoCommon::NUM_RT; | 30 | using VideoCommon::NUM_RT; |
| 31 | using VideoCommon::Offset2D; | 31 | using VideoCommon::Region2D; |
| 32 | using VideoCommon::RenderTargets; | 32 | using VideoCommon::RenderTargets; |
| 33 | 33 | ||
| 34 | struct ImageBufferMap { | 34 | struct ImageBufferMap { |
| @@ -73,10 +73,8 @@ public: | |||
| 73 | 73 | ||
| 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 75 | 75 | ||
| 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, const Region2D& dst_region, |
| 77 | const std::array<Offset2D, 2>& dst_region, | 77 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 78 | const std::array<Offset2D, 2>& src_region, | ||
| 79 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 80 | Tegra::Engines::Fermi2D::Operation operation); | 78 | Tegra::Engines::Fermi2D::Operation operation); |
| 81 | 79 | ||
| 82 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, | 80 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 1f6a169ae..b7f5b8bc2 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -289,16 +289,15 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri | |||
| 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); | 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, |
| 293 | const std::array<Offset2D, 2>& dst_region, | 293 | const Region2D& src_region) { |
| 294 | const std::array<Offset2D, 2>& src_region) { | ||
| 295 | const VkOffset2D offset{ | 294 | const VkOffset2D offset{ |
| 296 | .x = std::min(dst_region[0].x, dst_region[1].x), | 295 | .x = std::min(dst_region.start.x, dst_region.end.x), |
| 297 | .y = std::min(dst_region[0].y, dst_region[1].y), | 296 | .y = std::min(dst_region.start.y, dst_region.end.y), |
| 298 | }; | 297 | }; |
| 299 | const VkExtent2D extent{ | 298 | const VkExtent2D extent{ |
| 300 | .width = static_cast<u32>(std::abs(dst_region[1].x - dst_region[0].x)), | 299 | .width = static_cast<u32>(std::abs(dst_region.end.x - dst_region.start.x)), |
| 301 | .height = static_cast<u32>(std::abs(dst_region[1].y - dst_region[0].y)), | 300 | .height = static_cast<u32>(std::abs(dst_region.end.y - dst_region.start.y)), |
| 302 | }; | 301 | }; |
| 303 | const VkViewport viewport{ | 302 | const VkViewport viewport{ |
| 304 | .x = static_cast<float>(offset.x), | 303 | .x = static_cast<float>(offset.x), |
| @@ -313,11 +312,12 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | |||
| 313 | .offset = offset, | 312 | .offset = offset, |
| 314 | .extent = extent, | 313 | .extent = extent, |
| 315 | }; | 314 | }; |
| 316 | const float scale_x = static_cast<float>(src_region[1].x - src_region[0].x); | 315 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x); |
| 317 | const float scale_y = static_cast<float>(src_region[1].y - src_region[0].y); | 316 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y); |
| 318 | const PushConstants push_constants{ | 317 | const PushConstants push_constants{ |
| 319 | .tex_scale = {scale_x, scale_y}, | 318 | .tex_scale = {scale_x, scale_y}, |
| 320 | .tex_offset = {static_cast<float>(src_region[0].x), static_cast<float>(src_region[0].y)}, | 319 | .tex_offset = {static_cast<float>(src_region.start.x), |
| 320 | static_cast<float>(src_region.start.y)}, | ||
| 321 | }; | 321 | }; |
| 322 | cmdbuf.SetViewport(0, viewport); | 322 | cmdbuf.SetViewport(0, viewport); |
| 323 | cmdbuf.SetScissor(0, scissor); | 323 | cmdbuf.SetScissor(0, scissor); |
| @@ -353,8 +353,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 353 | BlitImageHelper::~BlitImageHelper() = default; | 353 | BlitImageHelper::~BlitImageHelper() = default; |
| 354 | 354 | ||
| 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 356 | const std::array<Offset2D, 2>& dst_region, | 356 | const Region2D& dst_region, const Region2D& src_region, |
| 357 | const std::array<Offset2D, 2>& src_region, | ||
| 358 | Tegra::Engines::Fermi2D::Filter filter, | 357 | Tegra::Engines::Fermi2D::Filter filter, |
| 359 | Tegra::Engines::Fermi2D::Operation operation) { | 358 | Tegra::Engines::Fermi2D::Operation operation) { |
| 360 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 359 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| @@ -383,8 +382,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 383 | 382 | ||
| 384 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | 383 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, |
| 385 | VkImageView src_depth_view, VkImageView src_stencil_view, | 384 | VkImageView src_depth_view, VkImageView src_stencil_view, |
| 386 | const std::array<Offset2D, 2>& dst_region, | 385 | const Region2D& dst_region, const Region2D& src_region, |
| 387 | const std::array<Offset2D, 2>& src_region, | ||
| 388 | Tegra::Engines::Fermi2D::Filter filter, | 386 | Tegra::Engines::Fermi2D::Filter filter, |
| 389 | Tegra::Engines::Fermi2D::Operation operation) { | 387 | Tegra::Engines::Fermi2D::Operation operation) { |
| 390 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); | 388 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 43fd3d737..0d81a06ed 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Vulkan { | 14 | namespace Vulkan { |
| 15 | 15 | ||
| 16 | using VideoCommon::Offset2D; | 16 | using VideoCommon::Region2D; |
| 17 | 17 | ||
| 18 | class Device; | 18 | class Device; |
| 19 | class Framebuffer; | 19 | class Framebuffer; |
| @@ -35,15 +35,13 @@ public: | |||
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 38 | const std::array<Offset2D, 2>& dst_region, | 38 | const Region2D& dst_region, const Region2D& src_region, |
| 39 | const std::array<Offset2D, 2>& src_region, | ||
| 40 | Tegra::Engines::Fermi2D::Filter filter, | 39 | Tegra::Engines::Fermi2D::Filter filter, |
| 41 | Tegra::Engines::Fermi2D::Operation operation); | 40 | Tegra::Engines::Fermi2D::Operation operation); |
| 42 | 41 | ||
| 43 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, | 42 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, |
| 44 | VkImageView src_stencil_view, const std::array<Offset2D, 2>& dst_region, | 43 | VkImageView src_stencil_view, const Region2D& dst_region, |
| 45 | const std::array<Offset2D, 2>& src_region, | 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 46 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 47 | Tegra::Engines::Fermi2D::Operation operation); | 45 | Tegra::Engines::Fermi2D::Operation operation); |
| 48 | 46 | ||
| 49 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); | 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 017348e05..bdd0ce8bc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -490,8 +490,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 490 | write_barrier); | 490 | write_barrier); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const std::array<Offset2D, 2>& dst_region, | 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, |
| 494 | const std::array<Offset2D, 2>& src_region, | ||
| 495 | const VkImageSubresourceLayers& dst_layers, | 494 | const VkImageSubresourceLayers& dst_layers, |
| 496 | const VkImageSubresourceLayers& src_layers) { | 495 | const VkImageSubresourceLayers& src_layers) { |
| 497 | return VkImageBlit{ | 496 | return VkImageBlit{ |
| @@ -499,13 +498,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 499 | .srcOffsets = | 498 | .srcOffsets = |
| 500 | { | 499 | { |
| 501 | { | 500 | { |
| 502 | .x = src_region[0].x, | 501 | .x = src_region.start.x, |
| 503 | .y = src_region[0].y, | 502 | .y = src_region.start.y, |
| 504 | .z = 0, | 503 | .z = 0, |
| 505 | }, | 504 | }, |
| 506 | { | 505 | { |
| 507 | .x = src_region[1].x, | 506 | .x = src_region.end.x, |
| 508 | .y = src_region[1].y, | 507 | .y = src_region.end.y, |
| 509 | .z = 1, | 508 | .z = 1, |
| 510 | }, | 509 | }, |
| 511 | }, | 510 | }, |
| @@ -513,42 +512,42 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 513 | .dstOffsets = | 512 | .dstOffsets = |
| 514 | { | 513 | { |
| 515 | { | 514 | { |
| 516 | .x = dst_region[0].x, | 515 | .x = dst_region.start.x, |
| 517 | .y = dst_region[0].y, | 516 | .y = dst_region.start.y, |
| 518 | .z = 0, | 517 | .z = 0, |
| 519 | }, | 518 | }, |
| 520 | { | 519 | { |
| 521 | .x = dst_region[1].x, | 520 | .x = dst_region.end.x, |
| 522 | .y = dst_region[1].y, | 521 | .y = dst_region.end.y, |
| 523 | .z = 1, | 522 | .z = 1, |
| 524 | }, | 523 | }, |
| 525 | }, | 524 | }, |
| 526 | }; | 525 | }; |
| 527 | } | 526 | } |
| 528 | 527 | ||
| 529 | [[nodiscard]] VkImageResolve MakeImageResolve(const std::array<Offset2D, 2>& dst_region, | 528 | [[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, |
| 530 | const std::array<Offset2D, 2>& src_region, | 529 | const Region2D& src_region, |
| 531 | const VkImageSubresourceLayers& dst_layers, | 530 | const VkImageSubresourceLayers& dst_layers, |
| 532 | const VkImageSubresourceLayers& src_layers) { | 531 | const VkImageSubresourceLayers& src_layers) { |
| 533 | return VkImageResolve{ | 532 | return VkImageResolve{ |
| 534 | .srcSubresource = src_layers, | 533 | .srcSubresource = src_layers, |
| 535 | .srcOffset = | 534 | .srcOffset = |
| 536 | { | 535 | { |
| 537 | .x = src_region[0].x, | 536 | .x = src_region.start.x, |
| 538 | .y = src_region[0].y, | 537 | .y = src_region.start.y, |
| 539 | .z = 0, | 538 | .z = 0, |
| 540 | }, | 539 | }, |
| 541 | .dstSubresource = dst_layers, | 540 | .dstSubresource = dst_layers, |
| 542 | .dstOffset = | 541 | .dstOffset = |
| 543 | { | 542 | { |
| 544 | .x = dst_region[0].x, | 543 | .x = dst_region.start.x, |
| 545 | .y = dst_region[0].y, | 544 | .y = dst_region.start.y, |
| 546 | .z = 0, | 545 | .z = 0, |
| 547 | }, | 546 | }, |
| 548 | .extent = | 547 | .extent = |
| 549 | { | 548 | { |
| 550 | .width = static_cast<u32>(dst_region[1].x - dst_region[0].x), | 549 | .width = static_cast<u32>(dst_region.end.x - dst_region.start.x), |
| 551 | .height = static_cast<u32>(dst_region[1].y - dst_region[0].y), | 550 | .height = static_cast<u32>(dst_region.end.y - dst_region.start.y), |
| 552 | .depth = 1, | 551 | .depth = 1, |
| 553 | }, | 552 | }, |
| 554 | }; | 553 | }; |
| @@ -602,8 +601,7 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 602 | } | 601 | } |
| 603 | 602 | ||
| 604 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 603 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 605 | const std::array<Offset2D, 2>& dst_region, | 604 | const Region2D& dst_region, const Region2D& src_region, |
| 606 | const std::array<Offset2D, 2>& src_region, | ||
| 607 | Tegra::Engines::Fermi2D::Filter filter, | 605 | Tegra::Engines::Fermi2D::Filter filter, |
| 608 | Tegra::Engines::Fermi2D::Operation operation) { | 606 | Tegra::Engines::Fermi2D::Operation operation) { |
| 609 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); | 607 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 628785d5e..4a57d378b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -16,7 +16,7 @@ namespace Vulkan { | |||
| 16 | 16 | ||
| 17 | using VideoCommon::ImageId; | 17 | using VideoCommon::ImageId; |
| 18 | using VideoCommon::NUM_RT; | 18 | using VideoCommon::NUM_RT; |
| 19 | using VideoCommon::Offset2D; | 19 | using VideoCommon::Region2D; |
| 20 | using VideoCommon::RenderTargets; | 20 | using VideoCommon::RenderTargets; |
| 21 | using VideoCore::Surface::PixelFormat; | 21 | using VideoCore::Surface::PixelFormat; |
| 22 | 22 | ||
| @@ -71,8 +71,7 @@ struct TextureCacheRuntime { | |||
| 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); |
| 72 | 72 | ||
| 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 74 | const std::array<Offset2D, 2>& dst_region, | 74 | const Region2D& dst_region, const Region2D& src_region, |
| 75 | const std::array<Offset2D, 2>& src_region, | ||
| 76 | Tegra::Engines::Fermi2D::Filter filter, | 75 | Tegra::Engines::Fermi2D::Filter filter, |
| 77 | Tegra::Engines::Fermi2D::Operation operation); | 76 | Tegra::Engines::Fermi2D::Operation operation); |
| 78 | 77 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 98e33c3a0..59b7c678b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -148,7 +148,9 @@ public: | |||
| 148 | /// Blit an image with the given parameters | 148 | /// Blit an image with the given parameters |
| 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 150 | const Tegra::Engines::Fermi2D::Surface& src, | 150 | const Tegra::Engines::Fermi2D::Surface& src, |
| 151 | const Tegra::Engines::Fermi2D::Config& copy); | 151 | const Tegra::Engines::Fermi2D::Config& copy, |
| 152 | std::optional<Region2D> src_region_override = {}, | ||
| 153 | std::optional<Region2D> dst_region_override = {}); | ||
| 152 | 154 | ||
| 153 | /// Invalidate the contents of the color buffer index | 155 | /// Invalidate the contents of the color buffer index |
| 154 | /// These contents become unspecified, the cache can assume aggressive optimizations. | 156 | /// These contents become unspecified, the cache can assume aggressive optimizations. |
| @@ -615,7 +617,9 @@ void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | |||
| 615 | template <class P> | 617 | template <class P> |
| 616 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 618 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 617 | const Tegra::Engines::Fermi2D::Surface& src, | 619 | const Tegra::Engines::Fermi2D::Surface& src, |
| 618 | const Tegra::Engines::Fermi2D::Config& copy) { | 620 | const Tegra::Engines::Fermi2D::Config& copy, |
| 621 | std::optional<Region2D> src_override, | ||
| 622 | std::optional<Region2D> dst_override) { | ||
| 619 | const BlitImages images = GetBlitImages(dst, src); | 623 | const BlitImages images = GetBlitImages(dst, src); |
| 620 | const ImageId dst_id = images.dst_id; | 624 | const ImageId dst_id = images.dst_id; |
| 621 | const ImageId src_id = images.src_id; | 625 | const ImageId src_id = images.src_id; |
| @@ -631,20 +635,42 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 631 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); | 635 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); |
| 632 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); | 636 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); |
| 633 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); | 637 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); |
| 634 | const std::array src_region{ | 638 | |
| 635 | Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, | 639 | // out of bounds texture blit checking |
| 636 | Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, | 640 | const bool use_override = src_override.has_value(); |
| 641 | const s32 src_x0 = copy.src_x0 >> src_samples_x; | ||
| 642 | s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x; | ||
| 643 | const s32 src_y0 = copy.src_y0 >> src_samples_y; | ||
| 644 | const s32 src_y1 = copy.src_y1 >> src_samples_y; | ||
| 645 | |||
| 646 | const auto src_width = static_cast<s32>(src_image.info.size.width); | ||
| 647 | const bool width_oob = src_x1 > src_width; | ||
| 648 | const auto width_diff = width_oob ? src_x1 - src_width : 0; | ||
| 649 | if (width_oob) { | ||
| 650 | src_x1 = src_width; | ||
| 651 | } | ||
| 652 | |||
| 653 | const Region2D src_dimensions{ | ||
| 654 | Offset2D{.x = src_x0, .y = src_y0}, | ||
| 655 | Offset2D{.x = src_x1, .y = src_y1}, | ||
| 637 | }; | 656 | }; |
| 657 | const auto src_region = use_override ? *src_override : src_dimensions; | ||
| 638 | 658 | ||
| 639 | const std::optional src_base = src_image.TryFindBase(src.Address()); | 659 | const std::optional src_base = src_image.TryFindBase(src.Address()); |
| 640 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; | 660 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; |
| 641 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); | 661 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); |
| 642 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); | 662 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); |
| 643 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); | 663 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); |
| 644 | const std::array dst_region{ | 664 | |
| 645 | Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, | 665 | const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; |
| 646 | Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, | 666 | const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; |
| 667 | const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; | ||
| 668 | const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; | ||
| 669 | const Region2D dst_dimensions{ | ||
| 670 | Offset2D{.x = dst_x0, .y = dst_y0}, | ||
| 671 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, | ||
| 647 | }; | 672 | }; |
| 673 | const auto dst_region = use_override ? *dst_override : dst_dimensions; | ||
| 648 | 674 | ||
| 649 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. | 675 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. |
| 650 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; | 676 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; |
| @@ -661,6 +687,21 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 661 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, | 687 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, |
| 662 | copy.operation); | 688 | copy.operation); |
| 663 | } | 689 | } |
| 690 | |||
| 691 | if (width_oob) { | ||
| 692 | // Continue copy of the oob region of the texture on the next row | ||
| 693 | auto oob_src = src; | ||
| 694 | oob_src.height++; | ||
| 695 | const Region2D src_region_override{ | ||
| 696 | Offset2D{.x = 0, .y = src_y0 + 1}, | ||
| 697 | Offset2D{.x = width_diff, .y = src_y1 + 1}, | ||
| 698 | }; | ||
| 699 | const Region2D dst_region_override{ | ||
| 700 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y0}, | ||
| 701 | Offset2D{.x = dst_x1, .y = dst_y1}, | ||
| 702 | }; | ||
| 703 | BlitImage(dst, oob_src, copy, src_region_override, dst_region_override); | ||
| 704 | } | ||
| 664 | } | 705 | } |
| 665 | 706 | ||
| 666 | template <class P> | 707 | template <class P> |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 2ad2d72a6..c9571f7e4 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -64,6 +64,13 @@ struct Offset3D { | |||
| 64 | s32 z; | 64 | s32 z; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct Region2D { | ||
| 68 | constexpr auto operator<=>(const Region2D&) const noexcept = default; | ||
| 69 | |||
| 70 | Offset2D start; | ||
| 71 | Offset2D end; | ||
| 72 | }; | ||
| 73 | |||
| 67 | struct Extent2D { | 74 | struct Extent2D { |
| 68 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; | 75 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; |
| 69 | 76 | ||