summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/fermi_2d.cpp22
-rw-r--r--src/video_core/texture_cache/texture_cache.h71
2 files changed, 35 insertions, 58 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 0f640fdae..f26530ede 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -7,6 +7,10 @@
7#include "video_core/engines/fermi_2d.h" 7#include "video_core/engines/fermi_2d.h"
8#include "video_core/memory_manager.h" 8#include "video_core/memory_manager.h"
9#include "video_core/rasterizer_interface.h" 9#include "video_core/rasterizer_interface.h"
10#include "video_core/surface.h"
11
12using VideoCore::Surface::BytesPerBlock;
13using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
10 14
11namespace Tegra::Engines { 15namespace Tegra::Engines {
12 16
@@ -49,7 +53,7 @@ void Fermi2D::Blit() {
49 UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); 53 UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled");
50 54
51 const auto& args = regs.pixels_from_memory; 55 const auto& args = regs.pixels_from_memory;
52 const Config config{ 56 Config config{
53 .operation = regs.operation, 57 .operation = regs.operation,
54 .filter = args.sample_mode.filter, 58 .filter = args.sample_mode.filter,
55 .dst_x0 = args.dst_x0, 59 .dst_x0 = args.dst_x0,
@@ -61,7 +65,21 @@ void Fermi2D::Blit() {
61 .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32), 65 .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32),
62 .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32), 66 .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32),
63 }; 67 };
64 if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, config)) { 68 Surface src = regs.src;
69 const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
70 const auto need_align_to_pitch =
71 src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch &&
72 static_cast<s32>(src.width) == config.src_x1 &&
73 config.src_x1 > static_cast<s32>(src.pitch / bytes_per_pixel) && config.src_x0 > 0;
74 if (need_align_to_pitch) {
75 auto address = src.Address() + config.src_x0 * bytes_per_pixel;
76 src.addr_upper = static_cast<u32>(address >> 32);
77 src.addr_lower = static_cast<u32>(address);
78 src.width -= config.src_x0;
79 config.src_x1 -= config.src_x0;
80 config.src_x0 = 0;
81 }
82 if (!rasterizer->AccelerateSurfaceCopy(src, regs.dst, config)) {
65 UNIMPLEMENTED(); 83 UNIMPLEMENTED();
66 } 84 }
67} 85}
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index e3542301e..01de2d498 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -159,9 +159,7 @@ public:
159 /// Blit an image with the given parameters 159 /// Blit an image with the given parameters
160 void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, 160 void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
161 const Tegra::Engines::Fermi2D::Surface& src, 161 const Tegra::Engines::Fermi2D::Surface& src,
162 const Tegra::Engines::Fermi2D::Config& copy, 162 const Tegra::Engines::Fermi2D::Config& copy);
163 std::optional<Region2D> src_region_override = {},
164 std::optional<Region2D> dst_region_override = {});
165 163
166 /// Invalidate the contents of the color buffer index 164 /// Invalidate the contents of the color buffer index
167 /// These contents become unspecified, the cache can assume aggressive optimizations. 165 /// These contents become unspecified, the cache can assume aggressive optimizations.
@@ -760,9 +758,7 @@ void TextureCache<P>::UnmapGPUMemory(GPUVAddr gpu_addr, size_t size) {
760template <class P> 758template <class P>
761void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, 759void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
762 const Tegra::Engines::Fermi2D::Surface& src, 760 const Tegra::Engines::Fermi2D::Surface& src,
763 const Tegra::Engines::Fermi2D::Config& copy, 761 const Tegra::Engines::Fermi2D::Config& copy) {
764 std::optional<Region2D> src_override,
765 std::optional<Region2D> dst_override) {
766 const BlitImages images = GetBlitImages(dst, src); 762 const BlitImages images = GetBlitImages(dst, src);
767 const ImageId dst_id = images.dst_id; 763 const ImageId dst_id = images.dst_id;
768 const ImageId src_id = images.src_id; 764 const ImageId src_id = images.src_id;
@@ -773,47 +769,25 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
773 const ImageBase& src_image = slot_images[src_id]; 769 const ImageBase& src_image = slot_images[src_id];
774 770
775 // TODO: Deduplicate 771 // TODO: Deduplicate
776 const std::optional dst_base = dst_image.TryFindBase(dst.Address());
777 const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}};
778 const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range);
779 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
780 const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples);
781
782 // out of bounds texture blit checking
783 const bool use_override = src_override.has_value();
784 const s32 src_x0 = copy.src_x0 >> src_samples_x;
785 s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x;
786 const s32 src_y0 = copy.src_y0 >> src_samples_y;
787 const s32 src_y1 = copy.src_y1 >> src_samples_y;
788
789 const auto src_width = static_cast<s32>(src_image.info.size.width);
790 const bool width_oob = src_x1 > src_width;
791 const auto width_diff = width_oob ? src_x1 - src_width : 0;
792 if (width_oob) {
793 src_x1 = src_width;
794 }
795
796 const Region2D src_dimensions{
797 Offset2D{.x = src_x0, .y = src_y0},
798 Offset2D{.x = src_x1, .y = src_y1},
799 };
800 const auto src_region = use_override ? *src_override : src_dimensions;
801
802 const std::optional src_base = src_image.TryFindBase(src.Address()); 772 const std::optional src_base = src_image.TryFindBase(src.Address());
803 const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; 773 const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}};
804 const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); 774 const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range);
805 const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); 775 const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info);
806 const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); 776 const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples);
777 const Region2D src_region{
778 Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y},
779 Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y},
780 };
807 781
808 const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; 782 const std::optional dst_base = dst_image.TryFindBase(dst.Address());
809 const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; 783 const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}};
810 const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; 784 const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range);
811 const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; 785 const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
812 const Region2D dst_dimensions{ 786 const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples);
813 Offset2D{.x = dst_x0, .y = dst_y0}, 787 const Region2D dst_region{
814 Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, 788 Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y},
789 Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y},
815 }; 790 };
816 const auto dst_region = use_override ? *dst_override : dst_dimensions;
817 791
818 // Always call this after src_framebuffer_id was queried, as the address might be invalidated. 792 // Always call this after src_framebuffer_id was queried, as the address might be invalidated.
819 Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; 793 Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
@@ -830,21 +804,6 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
830 runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, 804 runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter,
831 copy.operation); 805 copy.operation);
832 } 806 }
833
834 if (width_oob) {
835 // Continue copy of the oob region of the texture on the next row
836 auto oob_src = src;
837 oob_src.height++;
838 const Region2D src_region_override{
839 Offset2D{.x = 0, .y = src_y0 + 1},
840 Offset2D{.x = width_diff, .y = src_y1 + 1},
841 };
842 const Region2D dst_region_override{
843 Offset2D{.x = dst_x1 - width_diff, .y = dst_y0},
844 Offset2D{.x = dst_x1, .y = dst_y1},
845 };
846 BlitImage(dst, oob_src, copy, src_region_override, dst_region_override);
847 }
848} 807}
849 808
850template <class P> 809template <class P>