[GPU] Get unclipped draw height by running VS on the CPU
This commit is contained in:
@@ -22,7 +22,6 @@
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/gpu/draw_util.h"
|
||||
#include "xenia/gpu/gpu_flags.h"
|
||||
#include "xenia/gpu/register_file.h"
|
||||
#include "xenia/gpu/registers.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
@@ -143,6 +142,19 @@ DEFINE_bool(
|
||||
"-1...1, remap -32...32 to -1...1 to use the full possible range of "
|
||||
"values, at the expense of multiplicative blending correctness.",
|
||||
"GPU");
|
||||
// Enabled by default as the GPU is overall usually the bottleneck when the
|
||||
// pixel shader interlock render backend implementation is used, anything that
|
||||
// may improve GPU performance is favorable.
|
||||
DEFINE_bool(
|
||||
execute_unclipped_draw_vs_on_cpu_for_psi_render_backend, true,
|
||||
"If execute_unclipped_draw_vs_on_cpu is enabled, execute the vertex shader "
|
||||
"for unclipped draws on the CPU even when using the pixel shader interlock "
|
||||
"(rasterizer-ordered view) implementation of the render backend on the "
|
||||
"host, for which no expensive copying between host render targets is "
|
||||
"needed when the ownership of a EDRAM range is changed.\n"
|
||||
"If this is enabled, excessive barriers may be eliminated when switching "
|
||||
"between different render targets in separate EDRAM locations.",
|
||||
"GPU");
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
@@ -367,7 +379,8 @@ void RenderTargetCache::BeginFrame() { ResetAccumulatedRenderTargets(); }
|
||||
|
||||
bool RenderTargetCache::Update(bool is_rasterization_done,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control,
|
||||
uint32_t normalized_color_mask) {
|
||||
uint32_t normalized_color_mask,
|
||||
const Shader& vertex_shader) {
|
||||
const RegisterFile& regs = register_file();
|
||||
bool interlock_barrier_only = GetPath() == Path::kPixelShaderInterlock;
|
||||
|
||||
@@ -556,47 +569,13 @@ bool RenderTargetCache::Update(bool is_rasterization_done,
|
||||
|
||||
// Estimate height used by render targets (for color for writes, for depth /
|
||||
// stencil for both reads and writes) from various sources.
|
||||
uint32_t height_used =
|
||||
GetRenderTargetHeight(pitch_tiles_at_32bpp, msaa_samples);
|
||||
int32_t window_y_offset =
|
||||
regs.Get<reg::PA_SC_WINDOW_OFFSET>().window_y_offset;
|
||||
if (!regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable) {
|
||||
auto pa_cl_vte_cntl = regs.Get<reg::PA_CL_VTE_CNTL>();
|
||||
float viewport_bottom = 0.0f;
|
||||
// First calculate all the integer.0 or integer.5 offsetting exactly at full
|
||||
// precision.
|
||||
if (regs.Get<reg::PA_SU_SC_MODE_CNTL>().vtx_window_offset_enable) {
|
||||
viewport_bottom += float(window_y_offset);
|
||||
}
|
||||
if (cvars::half_pixel_offset &&
|
||||
!regs.Get<reg::PA_SU_VTX_CNTL>().pix_center) {
|
||||
viewport_bottom += 0.5f;
|
||||
}
|
||||
// Then apply the floating-point viewport offset.
|
||||
if (pa_cl_vte_cntl.vport_y_offset_ena) {
|
||||
viewport_bottom += regs[XE_GPU_REG_PA_CL_VPORT_YOFFSET].f32;
|
||||
}
|
||||
viewport_bottom += pa_cl_vte_cntl.vport_y_scale_ena
|
||||
? std::abs(regs[XE_GPU_REG_PA_CL_VPORT_YSCALE].f32)
|
||||
: 1.0f;
|
||||
// Using floor, or, rather, truncation (because maxing with zero anyway)
|
||||
// similar to how viewport scissoring behaves on real AMD, Intel and Nvidia
|
||||
// GPUs on Direct3D 12, also like in draw_util::GetHostViewportInfo.
|
||||
// max(0.0f, viewport_bottom) to drop NaN and < 0 - max picks the first
|
||||
// argument in the !(a < b) case (always for NaN), min as float (height_used
|
||||
// is well below 2^24) to safely drop very large values.
|
||||
height_used =
|
||||
uint32_t(std::min(float(height_used), std::max(0.0f, viewport_bottom)));
|
||||
}
|
||||
int32_t scissor_bottom =
|
||||
int32_t(regs.Get<reg::PA_SC_WINDOW_SCISSOR_BR>().br_y);
|
||||
if (!regs.Get<reg::PA_SC_WINDOW_SCISSOR_TL>().window_offset_disable) {
|
||||
scissor_bottom += window_y_offset;
|
||||
}
|
||||
scissor_bottom =
|
||||
std::min(scissor_bottom, regs.Get<reg::PA_SC_SCREEN_SCISSOR_BR>().br_y);
|
||||
height_used =
|
||||
std::min(height_used, uint32_t(std::max(scissor_bottom, int32_t(0))));
|
||||
uint32_t height_used = std::min(
|
||||
GetRenderTargetHeight(pitch_tiles_at_32bpp, msaa_samples),
|
||||
draw_extent_estimator_.EstimateMaxY(
|
||||
interlock_barrier_only
|
||||
? cvars::execute_unclipped_draw_vs_on_cpu_for_psi_render_backend
|
||||
: true,
|
||||
vertex_shader));
|
||||
|
||||
// Sorted by EDRAM base and then by index in the pipeline - for simplicity,
|
||||
// treat render targets placed closer to the end of the EDRAM as truncating
|
||||
|
||||
Reference in New Issue
Block a user