[D3D12] Point sprite size fixes, point/line bits in PsParamGen
This commit is contained in:
@@ -663,7 +663,11 @@ void DxbcShaderTranslator::StartPixelShader() {
|
||||
a_.OpIf(true, dxbc::Src::R(param_gen_temp, dxbc::Src::kXXXX));
|
||||
{
|
||||
// XY - floored pixel position (Direct3D VPOS) in the absolute value,
|
||||
// faceness as X sign bit. Using Z as scratch register now.
|
||||
// faceness as X sign bit, whether is a point primitive as Y sign bit.
|
||||
// Using Z as scratch register now.
|
||||
// ZW - [0, 1] UV within a point sprite in the absolute value, whether is
|
||||
// a line primitive as Z sign bit.
|
||||
// Pixel position.
|
||||
// Get XY address of the current host pixel as float (no matter whether
|
||||
// the position is pixel-rate or sample-rate also due to float24 depth
|
||||
// conversion requirements, it will be rounded the same). Rounding down,
|
||||
@@ -688,6 +692,7 @@ void DxbcShaderTranslator::StartPixelShader() {
|
||||
}
|
||||
a_.OpMov(dxbc::Dest::R(param_gen_temp, 0b0011),
|
||||
dxbc::Src::R(param_gen_temp).Abs());
|
||||
// Faceness.
|
||||
// Check if faceness applies to the current primitive type.
|
||||
a_.OpAnd(dxbc::Dest::R(param_gen_temp, 0b0100), LoadFlagsSystemConstant(),
|
||||
dxbc::Src::LU(kSysFlag_PrimitivePolygonal));
|
||||
@@ -704,31 +709,28 @@ void DxbcShaderTranslator::StartPixelShader() {
|
||||
-dxbc::Src::R(param_gen_temp, dxbc::Src::kXXXX));
|
||||
}
|
||||
a_.OpEndIf();
|
||||
// ZW - UV within a point sprite in the absolute value, at centroid if
|
||||
// requested for the interpolator.
|
||||
// TODO(Triang3l): Are centroid point coordinates possible in the hardware
|
||||
// at all? ps_param_gen is not a triangle-IJ-interpolated value
|
||||
// apparently, rather, it replaces the value in the shader input.
|
||||
// TODO(Triang3l): Saturate to avoid negative point coordinates (the sign
|
||||
// bit is used for the primitive type indicator) in case of extrapolation
|
||||
// when the center is not covered with MSAA.
|
||||
dxbc::Dest point_coord_r_zw_dest(dxbc::Dest::R(param_gen_temp, 0b1100));
|
||||
dxbc::Src point_coord_v_xxxy_src(dxbc::Src::V(
|
||||
uint32_t(InOutRegister::kPSInPointParameters), 0b01000000));
|
||||
a_.OpUBFE(dxbc::Dest::R(param_gen_temp, 0b0100), dxbc::Src::LU(1),
|
||||
param_gen_index_src,
|
||||
LoadSystemConstant(
|
||||
SystemConstants::Index::kInterpolatorSamplingPattern,
|
||||
offsetof(SystemConstants, interpolator_sampling_pattern),
|
||||
dxbc::Src::kXXXX));
|
||||
a_.OpIf(bool(xenos::SampleLocation::kCenter),
|
||||
dxbc::Src::R(param_gen_temp, dxbc::Src::kZZZZ));
|
||||
// At center.
|
||||
a_.OpMov(point_coord_r_zw_dest, point_coord_v_xxxy_src);
|
||||
a_.OpElse();
|
||||
// At centroid.
|
||||
a_.OpEvalCentroid(point_coord_r_zw_dest, point_coord_v_xxxy_src);
|
||||
a_.OpEndIf();
|
||||
// Point sprite coordinates.
|
||||
// Saturate to avoid negative point coordinates if the center of the pixel
|
||||
// is not covered, and extrapolation is done.
|
||||
a_.OpMov(dxbc::Dest::R(param_gen_temp, 0b1100),
|
||||
dxbc::Src::V(uint32_t(InOutRegister::kPSInPointParameters),
|
||||
0b0100 << 4),
|
||||
true);
|
||||
// Primitive type.
|
||||
{
|
||||
uint32_t param_gen_primitive_type_temp = PushSystemTemp();
|
||||
a_.OpUBFE(dxbc::Dest::R(param_gen_primitive_type_temp, 0b0011),
|
||||
dxbc::Src::LU(1),
|
||||
dxbc::Src::LU(kSysFlag_PrimitivePoint_Shift,
|
||||
kSysFlag_PrimitiveLine_Shift, 0, 0),
|
||||
LoadFlagsSystemConstant());
|
||||
a_.OpBFI(dxbc::Dest::R(param_gen_temp, 0b0110), dxbc::Src::LU(1),
|
||||
dxbc::Src::LU(31),
|
||||
dxbc::Src::R(param_gen_primitive_type_temp, 0b0100 << 2),
|
||||
dxbc::Src::R(param_gen_temp));
|
||||
// Release param_gen_primitive_type_temp.
|
||||
PopSystemTemp();
|
||||
}
|
||||
// TODO(Triang3l): Point / line primitive type flags to the sign bits.
|
||||
// Write ps_param_gen to the specified GPR.
|
||||
dxbc::Src param_gen_src(dxbc::Src::R(param_gen_temp));
|
||||
@@ -792,7 +794,7 @@ void DxbcShaderTranslator::StartTranslation() {
|
||||
system_temp_position_ = PushSystemTemp(0b1111);
|
||||
system_temp_point_size_edge_flag_kill_vertex_ = PushSystemTemp(0b0100);
|
||||
// Set the point size to a negative value to tell the geometry shader that
|
||||
// it should use the global point size if the vertex shader does not
|
||||
// it should use the default point size if the vertex shader does not
|
||||
// override it.
|
||||
a_.OpMov(
|
||||
dxbc::Dest::R(system_temp_point_size_edge_flag_kill_vertex_, 0b0001),
|
||||
@@ -1578,6 +1580,30 @@ void DxbcShaderTranslator::StoreResult(const InstructionResult& result,
|
||||
float((constant_1_mask >> 2) & 1),
|
||||
float((constant_1_mask >> 3) & 1)));
|
||||
}
|
||||
|
||||
// Make the point size non-negative as negative is used to indicate that the
|
||||
// default size must be used, and also clamp it to the bounds the way the R400
|
||||
// (Adreno 200, to be more precise) hardware clamps it (functionally like a
|
||||
// signed 32-bit integer, -NaN and -Infinity...-0 to the minimum, +NaN to the
|
||||
// maximum).
|
||||
if (result.storage_target ==
|
||||
InstructionStorageTarget::kPointSizeEdgeFlagKillVertex &&
|
||||
(used_write_mask & 0b0001)) {
|
||||
a_.OpIMax(
|
||||
dxbc::Dest::R(system_temp_point_size_edge_flag_kill_vertex_, 0b0001),
|
||||
LoadSystemConstant(SystemConstants::Index::kPointVertexDiameterMin,
|
||||
offsetof(SystemConstants, point_vertex_diameter_min),
|
||||
dxbc::Src::kXXXX),
|
||||
dxbc::Src::R(system_temp_point_size_edge_flag_kill_vertex_,
|
||||
dxbc::Src::kXXXX));
|
||||
a_.OpIMin(
|
||||
dxbc::Dest::R(system_temp_point_size_edge_flag_kill_vertex_, 0b0001),
|
||||
LoadSystemConstant(SystemConstants::Index::kPointVertexDiameterMax,
|
||||
offsetof(SystemConstants, point_vertex_diameter_max),
|
||||
dxbc::Src::kXXXX),
|
||||
dxbc::Src::R(system_temp_point_size_edge_flag_kill_vertex_,
|
||||
dxbc::Src::kXXXX));
|
||||
}
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::UpdateExecConditionalsAndEmitDisassembly(
|
||||
@@ -2007,12 +2033,14 @@ const DxbcShaderTranslator::SystemConstantRdef
|
||||
sizeof(float) * 4 * 6},
|
||||
|
||||
{"xe_ndc_scale", ShaderRdefTypeIndex::kFloat3, sizeof(float) * 3},
|
||||
{"xe_point_size_x", ShaderRdefTypeIndex::kFloat, sizeof(float)},
|
||||
{"xe_point_vertex_diameter_min", ShaderRdefTypeIndex::kFloat,
|
||||
sizeof(float)},
|
||||
|
||||
{"xe_ndc_offset", ShaderRdefTypeIndex::kFloat3, sizeof(float) * 3},
|
||||
{"xe_point_size_y", ShaderRdefTypeIndex::kFloat, sizeof(float)},
|
||||
{"xe_point_vertex_diameter_max", ShaderRdefTypeIndex::kFloat,
|
||||
sizeof(float)},
|
||||
|
||||
{"xe_point_size_min_max", ShaderRdefTypeIndex::kFloat2,
|
||||
{"xe_point_constant_radius", ShaderRdefTypeIndex::kFloat2,
|
||||
sizeof(float) * 2},
|
||||
{"xe_point_screen_to_ndc", ShaderRdefTypeIndex::kFloat2,
|
||||
sizeof(float) * 2},
|
||||
|
||||
Reference in New Issue
Block a user