TextureCache: Fix rescaling of ImageCopies
This commit is contained in:
parent
778700ff9d
commit
8704c93913
3 changed files with 67 additions and 18 deletions
|
@ -136,6 +136,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||||
if (info.type == ImageType::e3D) {
|
if (info.type == ImageType::e3D) {
|
||||||
flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||||
}
|
}
|
||||||
|
const auto scale_up = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
|
||||||
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);
|
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);
|
||||||
const bool is_2d = info.type == ImageType::e2D;
|
const bool is_2d = info.type == ImageType::e2D;
|
||||||
return VkImageCreateInfo{
|
return VkImageCreateInfo{
|
||||||
|
@ -145,8 +146,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||||
.imageType = ConvertImageType(info.type),
|
.imageType = ConvertImageType(info.type),
|
||||||
.format = format_info.format,
|
.format = format_info.format,
|
||||||
.extent{
|
.extent{
|
||||||
.width = ((info.size.width * up) >> down) >> samples_x,
|
.width = scale_up(info.size.width) >> samples_x,
|
||||||
.height = (is_2d ? ((info.size.height * up) >> down) : info.size.height) >> samples_y,
|
.height = (is_2d ? scale_up(info.size.height) : info.size.height) >> samples_y,
|
||||||
.depth = info.size.depth,
|
.depth = info.size.depth,
|
||||||
},
|
},
|
||||||
.mipLevels = static_cast<u32>(info.resources.levels),
|
.mipLevels = static_cast<u32>(info.resources.levels),
|
||||||
|
@ -1078,12 +1079,35 @@ bool Image::ScaleUp(bool save_as_backup) {
|
||||||
MemoryCommit new_commit(
|
MemoryCommit new_commit(
|
||||||
runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal));
|
runtime->memory_allocator.Commit(rescaled_image, MemoryUsage::DeviceLocal));
|
||||||
|
|
||||||
|
SCOPE_EXIT({
|
||||||
|
if (save_as_backup) {
|
||||||
|
backup_image = std::move(image);
|
||||||
|
backup_commit = std::move(commit);
|
||||||
|
has_backup = true;
|
||||||
|
} else {
|
||||||
|
runtime->prescaled_images.Push(std::move(image));
|
||||||
|
runtime->prescaled_commits.Push(std::move(commit));
|
||||||
|
}
|
||||||
|
image = std::move(rescaled_image);
|
||||||
|
commit = std::move(new_commit);
|
||||||
|
});
|
||||||
|
|
||||||
|
const PixelFormat format = StorageFormat(info.format);
|
||||||
|
const auto format_info =
|
||||||
|
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, false, format);
|
||||||
|
const auto similar = runtime->device.GetSupportedFormat(
|
||||||
|
format_info.format, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT),
|
||||||
|
FormatType::Optimal);
|
||||||
|
|
||||||
|
if (similar != format_info.format) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (aspect_mask == 0) {
|
if (aspect_mask == 0) {
|
||||||
aspect_mask = ImageAspectMask(info.format);
|
aspect_mask = ImageAspectMask(info.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto scale_up = [&](u32 value) {
|
const auto scale_up = [&](u32 value) {
|
||||||
return (value * resolution.up_scale) >> resolution.down_shift;
|
return std::max<u32>((value * resolution.up_scale) >> resolution.down_shift, 1U);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool is_2d = info.type == ImageType::e2D;
|
const bool is_2d = info.type == ImageType::e2D;
|
||||||
|
@ -1130,16 +1154,6 @@ bool Image::ScaleUp(bool save_as_backup) {
|
||||||
vkRegions.push_back(blit);
|
vkRegions.push_back(blit);
|
||||||
}
|
}
|
||||||
BlitScale(*scheduler, *image, *rescaled_image, vkRegions, aspect_mask);
|
BlitScale(*scheduler, *image, *rescaled_image, vkRegions, aspect_mask);
|
||||||
if (save_as_backup) {
|
|
||||||
backup_image = std::move(image);
|
|
||||||
backup_commit = std::move(commit);
|
|
||||||
has_backup = true;
|
|
||||||
} else {
|
|
||||||
runtime->prescaled_images.Push(std::move(image));
|
|
||||||
runtime->prescaled_commits.Push(std::move(commit));
|
|
||||||
}
|
|
||||||
image = std::move(rescaled_image);
|
|
||||||
commit = std::move(new_commit);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -929,8 +929,8 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
|
||||||
LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented");
|
LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented");
|
||||||
} else {
|
} else {
|
||||||
const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value();
|
const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value();
|
||||||
const auto copies = MakeShrinkImageCopies(new_info, overlap.info, base);
|
auto copies = MakeShrinkImageCopies(new_info, overlap.info, base);
|
||||||
runtime.CopyImage(new_image, overlap, copies);
|
runtime.CopyImage(new_image, overlap, std::move(copies));
|
||||||
}
|
}
|
||||||
if (True(overlap.flags & ImageFlagBits::Tracked)) {
|
if (True(overlap.flags & ImageFlagBits::Tracked)) {
|
||||||
UntrackImage(overlap, overlap_id);
|
UntrackImage(overlap, overlap_id);
|
||||||
|
@ -1569,9 +1569,33 @@ void TextureCache<P>::PrepareImageView(ImageViewId image_view_id, bool is_modifi
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::span<const ImageCopy> copies) {
|
void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<ImageCopy> copies) {
|
||||||
Image& dst = slot_images[dst_id];
|
Image& dst = slot_images[dst_id];
|
||||||
Image& src = slot_images[src_id];
|
Image& src = slot_images[src_id];
|
||||||
|
const bool is_rescaled = True(src.flags & ImageFlagBits::Rescaled);
|
||||||
|
if (is_rescaled) {
|
||||||
|
ASSERT(True(dst.flags & ImageFlagBits::Rescaled));
|
||||||
|
const bool both_2d{src.info.type == ImageType::e2D && dst.info.type == ImageType::e2D};
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
const auto scale_up = [&](u32 value) -> u32 {
|
||||||
|
if (value == 0) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
return std::max<u32>((value * resolution.up_scale) >> resolution.down_shift, 1U);
|
||||||
|
};
|
||||||
|
for (auto& copy : copies) {
|
||||||
|
copy.src_offset.x = scale_up(copy.src_offset.x);
|
||||||
|
|
||||||
|
copy.dst_offset.x = scale_up(copy.dst_offset.x);
|
||||||
|
|
||||||
|
copy.extent.width = scale_up(copy.extent.width);
|
||||||
|
if (both_2d) {
|
||||||
|
copy.src_offset.y = scale_up(copy.src_offset.y);
|
||||||
|
copy.dst_offset.y = scale_up(copy.dst_offset.y);
|
||||||
|
copy.extent.height = scale_up(copy.extent.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const auto dst_format_type = GetFormatType(dst.info.format);
|
const auto dst_format_type = GetFormatType(dst.info.format);
|
||||||
const auto src_format_type = GetFormatType(src.info.format);
|
const auto src_format_type = GetFormatType(src.info.format);
|
||||||
if (src_format_type == dst_format_type) {
|
if (src_format_type == dst_format_type) {
|
||||||
|
@ -1639,10 +1663,21 @@ std::pair<FramebufferId, ImageViewId> TextureCache<P>::RenderTargetFromImage(
|
||||||
ImageId image_id, const ImageViewInfo& view_info) {
|
ImageId image_id, const ImageViewInfo& view_info) {
|
||||||
const ImageViewId view_id = FindOrEmplaceImageView(image_id, view_info);
|
const ImageViewId view_id = FindOrEmplaceImageView(image_id, view_info);
|
||||||
const ImageBase& image = slot_images[image_id];
|
const ImageBase& image = slot_images[image_id];
|
||||||
|
const bool is_rescaled = True(image.flags & ImageFlagBits::Rescaled);
|
||||||
const bool is_color = GetFormatType(image.info.format) == SurfaceType::ColorTexture;
|
const bool is_color = GetFormatType(image.info.format) == SurfaceType::ColorTexture;
|
||||||
const ImageViewId color_view_id = is_color ? view_id : ImageViewId{};
|
const ImageViewId color_view_id = is_color ? view_id : ImageViewId{};
|
||||||
const ImageViewId depth_view_id = is_color ? ImageViewId{} : view_id;
|
const ImageViewId depth_view_id = is_color ? ImageViewId{} : view_id;
|
||||||
const Extent3D extent = MipSize(image.info.size, view_info.range.base.level);
|
Extent3D extent = MipSize(image.info.size, view_info.range.base.level);
|
||||||
|
if (is_rescaled) {
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
const auto scale_up = [&](u32 value) {
|
||||||
|
return std::max<u32>((value * resolution.up_scale) >> resolution.down_shift, 1U);
|
||||||
|
};
|
||||||
|
extent.width = scale_up(extent.width);
|
||||||
|
if (image.info.type == ImageType::e2D) {
|
||||||
|
extent.height = scale_up(extent.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
const u32 num_samples = image.info.num_samples;
|
const u32 num_samples = image.info.num_samples;
|
||||||
const auto [samples_x, samples_y] = SamplesLog2(num_samples);
|
const auto [samples_x, samples_y] = SamplesLog2(num_samples);
|
||||||
const FramebufferId framebuffer_id = GetFramebufferId(RenderTargets{
|
const FramebufferId framebuffer_id = GetFramebufferId(RenderTargets{
|
||||||
|
|
|
@ -316,7 +316,7 @@ private:
|
||||||
void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate);
|
void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate);
|
||||||
|
|
||||||
/// Execute copies from one image to the other, even if they are incompatible
|
/// Execute copies from one image to the other, even if they are incompatible
|
||||||
void CopyImage(ImageId dst_id, ImageId src_id, std::span<const ImageCopy> copies);
|
void CopyImage(ImageId dst_id, ImageId src_id, std::vector<ImageCopy> copies);
|
||||||
|
|
||||||
/// Bind an image view as render target, downloading resources preemtively if needed
|
/// Bind an image view as render target, downloading resources preemtively if needed
|
||||||
void BindRenderTarget(ImageViewId* old_id, ImageViewId new_id);
|
void BindRenderTarget(ImageViewId* old_id, ImageViewId new_id);
|
||||||
|
|
Loading…
Reference in a new issue