Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2024-05-31 22:43:59 +02:00
38 changed files with 3073 additions and 1908 deletions

View File

@@ -9,8 +9,6 @@
#include "xenia/gpu/draw_util.h"
#include <cstring>
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
@@ -93,22 +91,21 @@ void GetPreferredFacePolygonOffset(const RegisterFile& regs,
// ones that are rendered (except for shadow volumes).
if (pa_su_sc_mode_cntl.poly_offset_front_enable &&
!pa_su_sc_mode_cntl.cull_front) {
scale = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32;
offset = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32;
scale = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE);
offset = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET);
scale = roundToNearestOrderOfMagnitude(scale);
}
if (pa_su_sc_mode_cntl.poly_offset_back_enable &&
!pa_su_sc_mode_cntl.cull_back && !scale && !offset) {
scale = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE].f32;
offset = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET].f32;
scale = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE);
offset = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET);
}
} else {
// Non-triangle primitives use the front offset, but it's toggled via
// poly_offset_para_enable.
if (pa_su_sc_mode_cntl.poly_offset_para_enable) {
scale = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32;
offset = regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32;
scale = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE);
offset = regs.Get<float>(XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET);
}
}
scale_out = scale;
@@ -143,7 +140,7 @@ bool IsPixelShaderNeededWithRasterization(const Shader& shader,
}
// Check if a color target is actually written.
uint32_t rb_color_mask = regs[XE_GPU_REG_RB_COLOR_MASK].u32;
uint32_t rb_color_mask = regs[XE_GPU_REG_RB_COLOR_MASK];
uint32_t rts_remaining = shader.writes_color_targets();
uint32_t rt_index;
while (xe::bit_scan_forward(rts_remaining, &rt_index)) {
@@ -306,7 +303,6 @@ void GetHostViewportInfo(GetViewportInfoArgs* XE_RESTRICT args,
// Obtain the original viewport values in a normalized way.
float scale_xy[] = {
pa_cl_vte_cntl.vport_x_scale_ena ? args->PA_CL_VPORT_XSCALE : 1.0f,
pa_cl_vte_cntl.vport_y_scale_ena ? args->PA_CL_VPORT_YSCALE : 1.0f,
};
@@ -392,16 +388,11 @@ void GetHostViewportInfo(GetViewportInfoArgs* XE_RESTRICT args,
float offset_axis = offset_base_xy[i] + offset_add_xy[i];
float scale_axis = scale_xy[i];
float scale_axis_abs = std::abs(scale_xy[i]);
float axis_0 = offset_axis - scale_axis_abs;
float axis_1 = offset_axis + scale_axis_abs;
float axis_max_unscaled_float = float(xy_max_unscaled[i]);
// max(0.0f, xy) drops NaN and < 0 - max picks the first argument in the
// !(a < b) case (always for NaN), min as float (axis_max_unscaled_float
// is well below 2^24) to safely drop very large values.
uint32_t axis_0_int =
uint32_t(std::min(axis_max_unscaled_float, std::max(0.0f, axis_0)));
uint32_t axis_1_int =
uint32_t(std::min(axis_max_unscaled_float, std::max(0.0f, axis_1)));
uint32_t axis_0_int = uint32_t(xe::clamp_float(
offset_axis - scale_axis_abs, 0.0f, axis_max_unscaled_float));
uint32_t axis_1_int = uint32_t(xe::clamp_float(
offset_axis + scale_axis_abs, 0.0f, axis_max_unscaled_float));
uint32_t axis_extent_int = axis_1_int - axis_0_int;
viewport_info_out.xy_offset[i] = axis_0_int * axis_resolution_scale;
viewport_info_out.xy_extent[i] = axis_extent_int * axis_resolution_scale;
@@ -507,8 +498,8 @@ void GetHostViewportInfo(GetViewportInfoArgs* XE_RESTRICT args,
// extension. But cases when this really matters are yet to be found -
// trying to fix this will result in more correct depth values, but
// incorrect clipping.
z_min = xe::saturate_unsigned(host_clip_offset_z);
z_max = xe::saturate_unsigned(host_clip_offset_z + host_clip_scale_z);
z_min = xe::saturate(host_clip_offset_z);
z_max = xe::saturate(host_clip_offset_z + host_clip_scale_z);
// Direct3D 12 doesn't allow reverse depth range - on some drivers it
// works, on some drivers it doesn't, actually, but it was never
// explicitly allowed by the specification.
@@ -730,7 +721,7 @@ uint32_t GetNormalizedColorMask(const RegisterFile& regs,
return 0;
}
uint32_t normalized_color_mask = 0;
uint32_t rb_color_mask = regs[XE_GPU_REG_RB_COLOR_MASK].u32;
uint32_t rb_color_mask = regs[XE_GPU_REG_RB_COLOR_MASK];
for (uint32_t i = 0; i < xenos::kMaxColorRenderTargets; ++i) {
// Exclude the render targets not statically written to by the pixel shader.
// If the shader doesn't write to a render target, it shouldn't be written
@@ -776,10 +767,16 @@ void AddMemExportRanges(const RegisterFile& regs, const Shader& shader,
? regs.Get<reg::SQ_VS_CONST>().base
: regs.Get<reg::SQ_PS_CONST>().base;
for (uint32_t constant_index : shader.memexport_stream_constants()) {
const auto& stream = regs.Get<xenos::xe_gpu_memexport_stream_t>(
XE_GPU_REG_SHADER_CONSTANT_000_X +
(float_constants_base + constant_index) * 4);
if (!stream.index_count) {
xenos::xe_gpu_memexport_stream_t stream =
regs.GetMemExportStream(float_constants_base + constant_index);
// Safety checks for stream constants potentially not set up if the export
// isn't done on the control flow path taken by the shader (not checking the
// Y component because the index is more likely to be constructed
// arbitrarily).
// The hardware validates the upper bits of eA according to the
// IPR2015-00325 sequencer specification.
if (stream.const_0x1 != 0x1 || stream.const_0x4b0 != 0x4B0 ||
stream.const_0x96 != 0x96 || !stream.index_count) {
continue;
}
const FormatInfo& format_info =
@@ -821,7 +818,7 @@ void AddMemExportRanges(const RegisterFile& regs, const Shader& shader,
}
// Add a new range if haven't expanded an existing one.
if (!range_reused) {
ranges_out.emplace_back(stream.base_address, stream_size_bytes);
ranges_out.emplace_back(uint32_t(stream.base_address), stream_size_bytes);
}
}
}
@@ -943,8 +940,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
// Get the extent of pixels covered by the resolve rectangle, according to the
// top-left rasterization rule.
// D3D9 HACK: Vertices to use are always in vf0, and are written by the CPU.
auto fetch = regs.Get<xenos::xe_gpu_vertex_fetch_t>(
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
xenos::xe_gpu_vertex_fetch_t fetch = regs.GetVertexFetch(0);
if (fetch.type != xenos::FetchConstantType::kVertex || fetch.size != 3 * 2) {
XELOGE("Unsupported resolve vertex buffer format");
assert_always();
@@ -997,10 +993,10 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
GetScissor(regs, scissor, false);
int32_t scissor_right = int32_t(scissor.offset[0] + scissor.extent[0]);
int32_t scissor_bottom = int32_t(scissor.offset[1] + scissor.extent[1]);
x0 = xe::clamp(x0, int32_t(scissor.offset[0]), scissor_right);
y0 = xe::clamp(y0, int32_t(scissor.offset[1]), scissor_bottom);
x1 = xe::clamp(x1, int32_t(scissor.offset[0]), scissor_right);
y1 = xe::clamp(y1, int32_t(scissor.offset[1]), scissor_bottom);
x0 = std::clamp(x0, int32_t(scissor.offset[0]), scissor_right);
y0 = std::clamp(y0, int32_t(scissor.offset[1]), scissor_bottom);
x1 = std::clamp(x1, int32_t(scissor.offset[0]), scissor_right);
y1 = std::clamp(y1, int32_t(scissor.offset[1]), scissor_bottom);
assert_true(x0 <= x1 && y0 <= y1);
@@ -1114,7 +1110,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
}
// Calculate the destination memory extent.
uint32_t rb_copy_dest_base = regs[XE_GPU_REG_RB_COPY_DEST_BASE].u32;
uint32_t rb_copy_dest_base = regs[XE_GPU_REG_RB_COPY_DEST_BASE];
uint32_t copy_dest_base_adjusted = rb_copy_dest_base;
uint32_t copy_dest_extent_start, copy_dest_extent_end;
auto rb_copy_dest_pitch = regs.Get<reg::RB_COPY_DEST_PITCH>();
@@ -1284,9 +1280,10 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
info_out.copy_dest_info.copy_dest_swap = false;
}
info_out.rb_depth_clear = regs[XE_GPU_REG_RB_DEPTH_CLEAR].u32;
info_out.rb_color_clear = regs[XE_GPU_REG_RB_COLOR_CLEAR].u32;
info_out.rb_color_clear_lo = regs[XE_GPU_REG_RB_COLOR_CLEAR_LO].u32;
info_out.rb_depth_clear = regs[XE_GPU_REG_RB_DEPTH_CLEAR];
info_out.rb_color_clear = regs[XE_GPU_REG_RB_COLOR_CLEAR];
info_out.rb_color_clear_lo = regs[XE_GPU_REG_RB_COLOR_CLEAR_LO];
#if 0
XELOGD(
"Resolve: {},{} <= x,y < {},{}, {} -> {} at 0x{:08X} (potentially "
@@ -1377,4 +1374,4 @@ ResolveCopyShaderIndex ResolveInfo::GetCopyShader(
} // namespace draw_util
} // namespace gpu
} // namespace xe
} // namespace xe