mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-16 18:18:33 -05:00
texture_cache: Handle out of bound texture blits
Some games interleave a texture blit using regions which are out-of-bounds. This addresses the interleaving to avoid oob reads from the src texture.
This commit is contained in:
@ -289,16 +289,15 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri
|
||||
device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr);
|
||||
}
|
||||
|
||||
void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region) {
|
||||
void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region,
|
||||
const Region2D& src_region) {
|
||||
const VkOffset2D offset{
|
||||
.x = std::min(dst_region[0].x, dst_region[1].x),
|
||||
.y = std::min(dst_region[0].y, dst_region[1].y),
|
||||
.x = std::min(dst_region.start.x, dst_region.end.x),
|
||||
.y = std::min(dst_region.start.y, dst_region.end.y),
|
||||
};
|
||||
const VkExtent2D extent{
|
||||
.width = static_cast<u32>(std::abs(dst_region[1].x - dst_region[0].x)),
|
||||
.height = static_cast<u32>(std::abs(dst_region[1].y - dst_region[0].y)),
|
||||
.width = static_cast<u32>(std::abs(dst_region.end.x - dst_region.start.x)),
|
||||
.height = static_cast<u32>(std::abs(dst_region.end.y - dst_region.start.y)),
|
||||
};
|
||||
const VkViewport viewport{
|
||||
.x = static_cast<float>(offset.x),
|
||||
@ -313,11 +312,12 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout,
|
||||
.offset = offset,
|
||||
.extent = extent,
|
||||
};
|
||||
const float scale_x = static_cast<float>(src_region[1].x - src_region[0].x);
|
||||
const float scale_y = static_cast<float>(src_region[1].y - src_region[0].y);
|
||||
const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x);
|
||||
const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y);
|
||||
const PushConstants push_constants{
|
||||
.tex_scale = {scale_x, scale_y},
|
||||
.tex_offset = {static_cast<float>(src_region[0].x), static_cast<float>(src_region[0].y)},
|
||||
.tex_offset = {static_cast<float>(src_region.start.x),
|
||||
static_cast<float>(src_region.start.y)},
|
||||
};
|
||||
cmdbuf.SetViewport(0, viewport);
|
||||
cmdbuf.SetScissor(0, scissor);
|
||||
@ -353,8 +353,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
|
||||
BlitImageHelper::~BlitImageHelper() = default;
|
||||
|
||||
void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation) {
|
||||
const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear;
|
||||
@ -383,8 +382,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV
|
||||
|
||||
void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
|
||||
VkImageView src_depth_view, VkImageView src_stencil_view,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation) {
|
||||
ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
using VideoCommon::Offset2D;
|
||||
using VideoCommon::Region2D;
|
||||
|
||||
class Device;
|
||||
class Framebuffer;
|
||||
@ -35,15 +35,13 @@ public:
|
||||
~BlitImageHelper();
|
||||
|
||||
void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation);
|
||||
|
||||
void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view,
|
||||
VkImageView src_stencil_view, const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
VkImageView src_stencil_view, const Region2D& dst_region,
|
||||
const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation);
|
||||
|
||||
void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
|
||||
|
@ -490,8 +490,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
|
||||
write_barrier);
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageBlit MakeImageBlit(const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
[[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region,
|
||||
const VkImageSubresourceLayers& dst_layers,
|
||||
const VkImageSubresourceLayers& src_layers) {
|
||||
return VkImageBlit{
|
||||
@ -499,13 +498,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
|
||||
.srcOffsets =
|
||||
{
|
||||
{
|
||||
.x = src_region[0].x,
|
||||
.y = src_region[0].y,
|
||||
.x = src_region.start.x,
|
||||
.y = src_region.start.y,
|
||||
.z = 0,
|
||||
},
|
||||
{
|
||||
.x = src_region[1].x,
|
||||
.y = src_region[1].y,
|
||||
.x = src_region.end.x,
|
||||
.y = src_region.end.y,
|
||||
.z = 1,
|
||||
},
|
||||
},
|
||||
@ -513,42 +512,42 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
|
||||
.dstOffsets =
|
||||
{
|
||||
{
|
||||
.x = dst_region[0].x,
|
||||
.y = dst_region[0].y,
|
||||
.x = dst_region.start.x,
|
||||
.y = dst_region.start.y,
|
||||
.z = 0,
|
||||
},
|
||||
{
|
||||
.x = dst_region[1].x,
|
||||
.y = dst_region[1].y,
|
||||
.x = dst_region.end.x,
|
||||
.y = dst_region.end.y,
|
||||
.z = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageResolve MakeImageResolve(const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
[[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region,
|
||||
const Region2D& src_region,
|
||||
const VkImageSubresourceLayers& dst_layers,
|
||||
const VkImageSubresourceLayers& src_layers) {
|
||||
return VkImageResolve{
|
||||
.srcSubresource = src_layers,
|
||||
.srcOffset =
|
||||
{
|
||||
.x = src_region[0].x,
|
||||
.y = src_region[0].y,
|
||||
.x = src_region.start.x,
|
||||
.y = src_region.start.y,
|
||||
.z = 0,
|
||||
},
|
||||
.dstSubresource = dst_layers,
|
||||
.dstOffset =
|
||||
{
|
||||
.x = dst_region[0].x,
|
||||
.y = dst_region[0].y,
|
||||
.x = dst_region.start.x,
|
||||
.y = dst_region.start.y,
|
||||
.z = 0,
|
||||
},
|
||||
.extent =
|
||||
{
|
||||
.width = static_cast<u32>(dst_region[1].x - dst_region[0].x),
|
||||
.height = static_cast<u32>(dst_region[1].y - dst_region[0].y),
|
||||
.width = static_cast<u32>(dst_region.end.x - dst_region.start.x),
|
||||
.height = static_cast<u32>(dst_region.end.y - dst_region.start.y),
|
||||
.depth = 1,
|
||||
},
|
||||
};
|
||||
@ -602,8 +601,7 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
|
||||
}
|
||||
|
||||
void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation) {
|
||||
const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format);
|
||||
|
@ -16,7 +16,7 @@ namespace Vulkan {
|
||||
|
||||
using VideoCommon::ImageId;
|
||||
using VideoCommon::NUM_RT;
|
||||
using VideoCommon::Offset2D;
|
||||
using VideoCommon::Region2D;
|
||||
using VideoCommon::RenderTargets;
|
||||
using VideoCore::Surface::PixelFormat;
|
||||
|
||||
@ -71,8 +71,7 @@ struct TextureCacheRuntime {
|
||||
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
|
||||
|
||||
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
||||
const std::array<Offset2D, 2>& dst_region,
|
||||
const std::array<Offset2D, 2>& src_region,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation);
|
||||
|
||||
|
Reference in New Issue
Block a user