Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user