TextureCache: fix rescaling in aliases and overlap joins.
This commit is contained in:
parent
7506ac4118
commit
d37d10e7a7
|
@ -63,7 +63,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
|
||||||
const auto conv = [scale](float value) {
|
const auto conv = [scale](float value) {
|
||||||
float new_value = value * scale;
|
float new_value = value * scale;
|
||||||
if (scale < 1.0f) {
|
if (scale < 1.0f) {
|
||||||
bool sign = std::signbit(new_value);
|
const bool sign = std::signbit(value);
|
||||||
new_value = std::round(std::abs(new_value));
|
new_value = std::round(std::abs(new_value));
|
||||||
new_value = sign ? -new_value : new_value;
|
new_value = sign ? -new_value : new_value;
|
||||||
}
|
}
|
||||||
|
@ -96,21 +96,22 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
|
||||||
VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) {
|
VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) {
|
||||||
const auto& src = regs.scissor_test[index];
|
const auto& src = regs.scissor_test[index];
|
||||||
VkRect2D scissor;
|
VkRect2D scissor;
|
||||||
const auto scale_up = [&](u32 value) -> u32 {
|
const auto scale_up = [&](s32 value) -> s32 {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
const u32 upset = value * up_scale;
|
const s32 upset = value * up_scale;
|
||||||
u32 acumm = 0;
|
s32 acumm = 0;
|
||||||
if ((up_scale >> down_shift) == 0) {
|
if ((up_scale >> down_shift) == 0) {
|
||||||
acumm = upset & 0x1;
|
acumm = upset % 2;
|
||||||
}
|
}
|
||||||
const u32 converted_value = (value * up_scale) >> down_shift;
|
const s32 converted_value = (value * up_scale) >> down_shift;
|
||||||
return std::max<u32>(converted_value + acumm, 1U);
|
return value < 0 ? std::min<s32>(converted_value - acumm, -1)
|
||||||
|
: std::max<s32>(converted_value + acumm, 1);
|
||||||
};
|
};
|
||||||
if (src.enable) {
|
if (src.enable) {
|
||||||
scissor.offset.x = static_cast<s32>(scale_up(src.min_x));
|
scissor.offset.x = scale_up(static_cast<s32>(src.min_x));
|
||||||
scissor.offset.y = static_cast<s32>(scale_up(src.min_y));
|
scissor.offset.y = scale_up(static_cast<s32>(src.min_y));
|
||||||
scissor.extent.width = scale_up(src.max_x - src.min_x);
|
scissor.extent.width = scale_up(src.max_x - src.min_x);
|
||||||
scissor.extent.height = scale_up(src.max_y - src.min_y);
|
scissor.extent.height = scale_up(src.max_y - src.min_y);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1037,8 +1037,11 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
|
||||||
if (overlap.info.num_samples != new_image.info.num_samples) {
|
if (overlap.info.num_samples != new_image.info.num_samples) {
|
||||||
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 auto& resolution = Settings::values.resolution_info;
|
||||||
const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value();
|
const SubresourceBase base = new_image.TryFindBase(overlap.gpu_addr).value();
|
||||||
auto copies = MakeShrinkImageCopies(new_info, overlap.info, base);
|
const u32 up_scale = can_rescale ? resolution.up_scale : 1;
|
||||||
|
const u32 down_shift = can_rescale ? resolution.down_shift : 0;
|
||||||
|
auto copies = MakeShrinkImageCopies(new_info, overlap.info, base, up_scale, down_shift);
|
||||||
runtime.CopyImage(new_image, overlap, std::move(copies));
|
runtime.CopyImage(new_image, overlap, std::move(copies));
|
||||||
}
|
}
|
||||||
if (True(overlap.flags & ImageFlagBits::Tracked)) {
|
if (True(overlap.flags & ImageFlagBits::Tracked)) {
|
||||||
|
@ -1659,19 +1662,35 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
|
||||||
const ImageBase& rhs_image = slot_images[rhs->id];
|
const ImageBase& rhs_image = slot_images[rhs->id];
|
||||||
return lhs_image.modification_tick < rhs_image.modification_tick;
|
return lhs_image.modification_tick < rhs_image.modification_tick;
|
||||||
});
|
});
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
for (const AliasedImage* const aliased : aliased_images) {
|
for (const AliasedImage* const aliased : aliased_images) {
|
||||||
if (any_rescaled) {
|
if (!resolution.active | !any_rescaled) {
|
||||||
Image& aliased_image = slot_images[aliased->id];
|
CopyImage(image_id, aliased->id, aliased->copies);
|
||||||
if (can_rescale) {
|
continue;
|
||||||
ScaleUp(aliased_image);
|
}
|
||||||
} else {
|
Image& aliased_image = slot_images[aliased->id];
|
||||||
ScaleDown(aliased_image);
|
if (!can_rescale) {
|
||||||
if (any_blacklisted) {
|
ScaleDown(aliased_image);
|
||||||
aliased_image.flags |= ImageFlagBits::Blacklisted;
|
if (any_blacklisted) {
|
||||||
}
|
aliased_image.flags |= ImageFlagBits::Blacklisted;
|
||||||
|
}
|
||||||
|
CopyImage(image_id, aliased->id, aliased->copies);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ScaleUp(aliased_image);
|
||||||
|
|
||||||
|
const bool both_2d{image.info.type == ImageType::e2D &&
|
||||||
|
aliased_image.info.type == ImageType::e2D};
|
||||||
|
auto copies = aliased->copies;
|
||||||
|
for (auto copy : copies) {
|
||||||
|
copy.extent.width = std::max<u32>(
|
||||||
|
(copy.extent.width * resolution.up_scale) >> resolution.down_shift, 1);
|
||||||
|
if (both_2d) {
|
||||||
|
copy.extent.height = std::max<u32>(
|
||||||
|
(copy.extent.height * resolution.up_scale) >> resolution.down_shift, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CopyImage(image_id, aliased->id, aliased->copies);
|
CopyImage(image_id, aliased->id, copies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -723,7 +723,7 @@ ImageViewType RenderTargetImageViewType(const ImageInfo& info) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst, const ImageInfo& src,
|
std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst, const ImageInfo& src,
|
||||||
SubresourceBase base) {
|
SubresourceBase base, u32 up_scale, u32 down_shift) {
|
||||||
ASSERT(dst.resources.levels >= src.resources.levels);
|
ASSERT(dst.resources.levels >= src.resources.levels);
|
||||||
ASSERT(dst.num_samples == src.num_samples);
|
ASSERT(dst.num_samples == src.num_samples);
|
||||||
|
|
||||||
|
@ -732,7 +732,7 @@ std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst, const ImageIn
|
||||||
ASSERT(src.type == ImageType::e3D);
|
ASSERT(src.type == ImageType::e3D);
|
||||||
ASSERT(src.resources.levels == 1);
|
ASSERT(src.resources.levels == 1);
|
||||||
}
|
}
|
||||||
|
const bool both_2d{src.type == ImageType::e2D && dst.type == ImageType::e2D};
|
||||||
std::vector<ImageCopy> copies;
|
std::vector<ImageCopy> copies;
|
||||||
copies.reserve(src.resources.levels);
|
copies.reserve(src.resources.levels);
|
||||||
for (s32 level = 0; level < src.resources.levels; ++level) {
|
for (s32 level = 0; level < src.resources.levels; ++level) {
|
||||||
|
@ -762,6 +762,10 @@ std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst, const ImageIn
|
||||||
if (is_dst_3d) {
|
if (is_dst_3d) {
|
||||||
copy.extent.depth = src.size.depth;
|
copy.extent.depth = src.size.depth;
|
||||||
}
|
}
|
||||||
|
copy.extent.width = std::max<u32>((copy.extent.width * up_scale) >> down_shift, 1);
|
||||||
|
if (both_2d) {
|
||||||
|
copy.extent.height = std::max<u32>((copy.extent.height * up_scale) >> down_shift, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return copies;
|
return copies;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@ struct OverlapResult {
|
||||||
|
|
||||||
[[nodiscard]] std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst,
|
[[nodiscard]] std::vector<ImageCopy> MakeShrinkImageCopies(const ImageInfo& dst,
|
||||||
const ImageInfo& src,
|
const ImageInfo& src,
|
||||||
SubresourceBase base);
|
SubresourceBase base, u32 up_scale = 1,
|
||||||
|
u32 down_shift = 0);
|
||||||
|
|
||||||
[[nodiscard]] bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config);
|
[[nodiscard]] bool IsValidEntry(const Tegra::MemoryManager& gpu_memory, const TICEntry& config);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue