TextureCache: Modify Viewports/Scissors according to Rescale.
This commit is contained in:
parent
71ca84d829
commit
778700ff9d
|
@ -29,7 +29,8 @@ enum : u8 {
|
||||||
ColorBuffer6,
|
ColorBuffer6,
|
||||||
ColorBuffer7,
|
ColorBuffer7,
|
||||||
ZetaBuffer,
|
ZetaBuffer,
|
||||||
Rescale,
|
RescaleViewports,
|
||||||
|
RescaleScissors,
|
||||||
|
|
||||||
VertexBuffers,
|
VertexBuffers,
|
||||||
VertexBuffer0,
|
VertexBuffer0,
|
||||||
|
|
|
@ -58,19 +58,14 @@ struct DrawParams {
|
||||||
bool is_indexed;
|
bool is_indexed;
|
||||||
};
|
};
|
||||||
|
|
||||||
VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index) {
|
VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) {
|
||||||
const auto& src = regs.viewport_transform[index];
|
const auto& src = regs.viewport_transform[index];
|
||||||
const float width = src.scale_x * 2.0f;
|
const float width = src.scale_x * 2.0f * scale;
|
||||||
float y = src.translate_y - src.scale_y;
|
const float height = src.scale_y * 2.0f * scale;
|
||||||
float height = src.scale_y * 2.0f;
|
|
||||||
if (regs.screen_y_control.y_negate) {
|
|
||||||
y += height;
|
|
||||||
height = -height;
|
|
||||||
}
|
|
||||||
const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
|
const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
|
||||||
VkViewport viewport{
|
VkViewport viewport{
|
||||||
.x = src.translate_x - src.scale_x,
|
.x = (src.translate_x - src.scale_x) * scale,
|
||||||
.y = y,
|
.y = (src.translate_y - src.scale_y) * scale,
|
||||||
.width = width != 0.0f ? width : 1.0f,
|
.width = width != 0.0f ? width : 1.0f,
|
||||||
.height = height != 0.0f ? height : 1.0f,
|
.height = height != 0.0f ? height : 1.0f,
|
||||||
.minDepth = src.translate_z - src.scale_z * reduce_z,
|
.minDepth = src.translate_z - src.scale_z * reduce_z,
|
||||||
|
@ -83,14 +78,21 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
|
||||||
return viewport;
|
return viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRect2D GetScissorState(const Maxwell& regs, size_t index) {
|
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 {
|
||||||
|
if (value == 0) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
const u32 converted_value = (value * up_scale) >> down_shift;
|
||||||
|
return std::max<u32>(converted_value, 1U);
|
||||||
|
};
|
||||||
if (src.enable) {
|
if (src.enable) {
|
||||||
scissor.offset.x = static_cast<s32>(src.min_x);
|
scissor.offset.x = static_cast<s32>(scale_up(src.min_x));
|
||||||
scissor.offset.y = static_cast<s32>(src.min_y);
|
scissor.offset.y = static_cast<s32>(scale_up(src.min_y));
|
||||||
scissor.extent.width = src.max_x - src.min_x;
|
scissor.extent.width = scale_up(src.max_x - src.min_x);
|
||||||
scissor.extent.height = src.max_y - src.min_y;
|
scissor.extent.height = scale_up(src.max_y - src.min_y);
|
||||||
} else {
|
} else {
|
||||||
scissor.offset.x = 0;
|
scissor.offset.x = 0;
|
||||||
scissor.offset.y = 0;
|
scissor.offset.y = 0;
|
||||||
|
@ -214,8 +216,15 @@ void RasterizerVulkan::Clear() {
|
||||||
const VkExtent2D render_area = framebuffer->RenderArea();
|
const VkExtent2D render_area = framebuffer->RenderArea();
|
||||||
scheduler.RequestRenderpass(framebuffer);
|
scheduler.RequestRenderpass(framebuffer);
|
||||||
|
|
||||||
|
u32 up_scale = 1;
|
||||||
|
u32 down_shift = 0;
|
||||||
|
if (texture_cache.IsRescaling()) {
|
||||||
|
up_scale = Settings::values.resolution_info.up_scale;
|
||||||
|
down_shift = Settings::values.resolution_info.down_shift;
|
||||||
|
}
|
||||||
|
|
||||||
VkClearRect clear_rect{
|
VkClearRect clear_rect{
|
||||||
.rect = GetScissorState(regs, 0),
|
.rect = GetScissorState(regs, 0, up_scale, down_shift),
|
||||||
.baseArrayLayer = regs.clear_buffers.layer,
|
.baseArrayLayer = regs.clear_buffers.layer,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
|
@ -595,15 +604,17 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
|
||||||
if (!state_tracker.TouchViewports()) {
|
if (!state_tracker.TouchViewports()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const float scale =
|
||||||
|
texture_cache.IsRescaling() ? Settings::values.resolution_info.up_factor : 1.0f;
|
||||||
const std::array viewports{
|
const std::array viewports{
|
||||||
GetViewportState(device, regs, 0), GetViewportState(device, regs, 1),
|
GetViewportState(device, regs, 0, scale), GetViewportState(device, regs, 1, scale),
|
||||||
GetViewportState(device, regs, 2), GetViewportState(device, regs, 3),
|
GetViewportState(device, regs, 2, scale), GetViewportState(device, regs, 3, scale),
|
||||||
GetViewportState(device, regs, 4), GetViewportState(device, regs, 5),
|
GetViewportState(device, regs, 4, scale), GetViewportState(device, regs, 5, scale),
|
||||||
GetViewportState(device, regs, 6), GetViewportState(device, regs, 7),
|
GetViewportState(device, regs, 6, scale), GetViewportState(device, regs, 7, scale),
|
||||||
GetViewportState(device, regs, 8), GetViewportState(device, regs, 9),
|
GetViewportState(device, regs, 8, scale), GetViewportState(device, regs, 9, scale),
|
||||||
GetViewportState(device, regs, 10), GetViewportState(device, regs, 11),
|
GetViewportState(device, regs, 10, scale), GetViewportState(device, regs, 11, scale),
|
||||||
GetViewportState(device, regs, 12), GetViewportState(device, regs, 13),
|
GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale),
|
||||||
GetViewportState(device, regs, 14), GetViewportState(device, regs, 15),
|
GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale),
|
||||||
};
|
};
|
||||||
scheduler.Record([viewports](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewports); });
|
scheduler.Record([viewports](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewports); });
|
||||||
}
|
}
|
||||||
|
@ -612,13 +623,29 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
|
||||||
if (!state_tracker.TouchScissors()) {
|
if (!state_tracker.TouchScissors()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
u32 up_scale = 1;
|
||||||
|
u32 down_shift = 0;
|
||||||
|
if (texture_cache.IsRescaling()) {
|
||||||
|
up_scale = Settings::values.resolution_info.up_scale;
|
||||||
|
down_shift = Settings::values.resolution_info.down_shift;
|
||||||
|
}
|
||||||
const std::array scissors{
|
const std::array scissors{
|
||||||
GetScissorState(regs, 0), GetScissorState(regs, 1), GetScissorState(regs, 2),
|
GetScissorState(regs, 0, up_scale, down_shift),
|
||||||
GetScissorState(regs, 3), GetScissorState(regs, 4), GetScissorState(regs, 5),
|
GetScissorState(regs, 1, up_scale, down_shift),
|
||||||
GetScissorState(regs, 6), GetScissorState(regs, 7), GetScissorState(regs, 8),
|
GetScissorState(regs, 2, up_scale, down_shift),
|
||||||
GetScissorState(regs, 9), GetScissorState(regs, 10), GetScissorState(regs, 11),
|
GetScissorState(regs, 3, up_scale, down_shift),
|
||||||
GetScissorState(regs, 12), GetScissorState(regs, 13), GetScissorState(regs, 14),
|
GetScissorState(regs, 4, up_scale, down_shift),
|
||||||
GetScissorState(regs, 15),
|
GetScissorState(regs, 5, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 6, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 7, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 8, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 9, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 10, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 11, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 12, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 13, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 14, up_scale, down_shift),
|
||||||
|
GetScissorState(regs, 15, up_scale, down_shift),
|
||||||
};
|
};
|
||||||
scheduler.Record([scissors](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissors); });
|
scheduler.Record([scissors](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissors); });
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,11 +71,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TouchViewports() {
|
bool TouchViewports() {
|
||||||
return Exchange(Dirty::Viewports, false);
|
return Exchange(Dirty::Viewports, false) ||
|
||||||
|
Exchange(VideoCommon::Dirty::RescaleViewports, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TouchScissors() {
|
bool TouchScissors() {
|
||||||
return Exchange(Dirty::Scissors, false);
|
return Exchange(Dirty::Scissors, false) ||
|
||||||
|
Exchange(VideoCommon::Dirty::RescaleScissors, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TouchDepthBias() {
|
bool TouchDepthBias() {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/texture_cache/image_view_base.h"
|
#include "video_core/texture_cache/image_view_base.h"
|
||||||
|
@ -205,6 +206,7 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rescaled;
|
||||||
do {
|
do {
|
||||||
flags[Dirty::RenderTargets] = false;
|
flags[Dirty::RenderTargets] = false;
|
||||||
|
|
||||||
|
@ -243,6 +245,7 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
check_rescale(render_targets.depth_buffer_id, tmp_depth_image);
|
check_rescale(render_targets.depth_buffer_id, tmp_depth_image);
|
||||||
|
|
||||||
if (can_rescale) {
|
if (can_rescale) {
|
||||||
|
rescaled = true;
|
||||||
const auto scale_up = [this](ImageId image_id) {
|
const auto scale_up = [this](ImageId image_id) {
|
||||||
if (image_id != CORRUPT_ID) {
|
if (image_id != CORRUPT_ID) {
|
||||||
Image& image = slot_images[image_id];
|
Image& image = slot_images[image_id];
|
||||||
|
@ -254,6 +257,7 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
}
|
}
|
||||||
scale_up(tmp_depth_image);
|
scale_up(tmp_depth_image);
|
||||||
} else {
|
} else {
|
||||||
|
rescaled = false;
|
||||||
const auto scale_down = [this](ImageId image_id) {
|
const auto scale_down = [this](ImageId image_id) {
|
||||||
if (image_id != CORRUPT_ID) {
|
if (image_id != CORRUPT_ID) {
|
||||||
Image& image = slot_images[image_id];
|
Image& image = slot_images[image_id];
|
||||||
|
@ -268,6 +272,12 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
} while (has_deleted_images);
|
} while (has_deleted_images);
|
||||||
// Rescale End
|
// Rescale End
|
||||||
|
|
||||||
|
if (is_rescaling != rescaled) {
|
||||||
|
flags[Dirty::RescaleViewports] = true;
|
||||||
|
flags[Dirty::RescaleScissors] = true;
|
||||||
|
is_rescaling = rescaled;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||||
ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index];
|
ImageViewId& color_buffer_id = render_targets.color_buffer_ids[index];
|
||||||
PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id));
|
PrepareImageView(color_buffer_id, true, is_clear && IsFullClear(color_buffer_id));
|
||||||
|
@ -279,9 +289,15 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||||
render_targets.draw_buffers[index] = static_cast<u8>(maxwell3d.regs.rt_control.Map(index));
|
render_targets.draw_buffers[index] = static_cast<u8>(maxwell3d.regs.rt_control.Map(index));
|
||||||
}
|
}
|
||||||
|
u32 up_scale = 1;
|
||||||
|
u32 down_shift = 0;
|
||||||
|
if (is_rescaling) {
|
||||||
|
up_scale = Settings::values.resolution_info.up_scale;
|
||||||
|
down_shift = Settings::values.resolution_info.down_shift;
|
||||||
|
}
|
||||||
render_targets.size = Extent2D{
|
render_targets.size = Extent2D{
|
||||||
maxwell3d.regs.render_area.width,
|
(maxwell3d.regs.render_area.width * up_scale) >> down_shift,
|
||||||
maxwell3d.regs.render_area.height,
|
(maxwell3d.regs.render_area.height * up_scale) >> down_shift,
|
||||||
};
|
};
|
||||||
|
|
||||||
flags[Dirty::DepthBiasGlobal] = true;
|
flags[Dirty::DepthBiasGlobal] = true;
|
||||||
|
@ -538,6 +554,11 @@ void TextureCache<P>::PopAsyncFlushes() {
|
||||||
committed_downloads.pop();
|
committed_downloads.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
bool TextureCache<P>::IsRescaling() {
|
||||||
|
return is_rescaling;
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
bool TextureCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
|
bool TextureCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
|
||||||
bool is_modified = false;
|
bool is_modified = false;
|
||||||
|
|
|
@ -168,6 +168,8 @@ public:
|
||||||
/// Return true when a CPU region is modified from the GPU
|
/// Return true when a CPU region is modified from the GPU
|
||||||
[[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size);
|
[[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsRescaling();
|
||||||
|
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -362,6 +364,7 @@ private:
|
||||||
VAddr virtual_invalid_space{};
|
VAddr virtual_invalid_space{};
|
||||||
|
|
||||||
bool has_deleted_images = false;
|
bool has_deleted_images = false;
|
||||||
|
bool is_rescaling = false;
|
||||||
u64 total_used_memory = 0;
|
u64 total_used_memory = 0;
|
||||||
u64 minimum_memory;
|
u64 minimum_memory;
|
||||||
u64 expected_memory;
|
u64 expected_memory;
|
||||||
|
|
|
@ -849,6 +849,8 @@ void Config::ReadRendererValues() {
|
||||||
ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks);
|
ReadBasicSetting(Settings::values.disable_shader_loop_safety_checks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Settings::UpdateRescalingInfo();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1402,6 +1404,8 @@ void Config::SaveRendererValues() {
|
||||||
WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks);
|
WriteBasicSetting(Settings::values.disable_shader_loop_safety_checks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Settings::UpdateRescalingInfo();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue