[GPU] Offset and clamp tessellation patch index (#2008, thanks @deaklajos)
This commit is contained in:
parent
fea430f1f9
commit
38aca269e1
|
@ -273,6 +273,36 @@ void DxbcShaderTranslator::ConvertPWLGamma(
|
|||
accumulator_src);
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::RemapAndConvertVertexIndices(
|
||||
uint32_t dest_temp, uint32_t dest_temp_components, const dxbc::Src& src) {
|
||||
dxbc::Dest dest(dxbc::Dest::R(dest_temp, dest_temp_components));
|
||||
dxbc::Src dest_src(dxbc::Src::R(dest_temp));
|
||||
|
||||
// Add the base vertex index.
|
||||
a_.OpIAdd(dest, src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexOffset,
|
||||
offsetof(SystemConstants, vertex_index_offset),
|
||||
dxbc::Src::kXXXX));
|
||||
|
||||
// Mask since the GPU only uses the lower 24 bits of the vertex index (tested
|
||||
// on an Adreno 200 phone). `((index & 0xFFFFFF) + offset) & 0xFFFFFF` is the
|
||||
// same as `(index + offset) & 0xFFFFFF`.
|
||||
a_.OpAnd(dest, dest_src, dxbc::Src::LU(xenos::kVertexIndexMask));
|
||||
|
||||
// Clamp after offsetting.
|
||||
a_.OpUMax(dest, dest_src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexMinMax,
|
||||
offsetof(SystemConstants, vertex_index_min),
|
||||
dxbc::Src::kXXXX));
|
||||
a_.OpUMin(dest, dest_src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexMinMax,
|
||||
offsetof(SystemConstants, vertex_index_max),
|
||||
dxbc::Src::kXXXX));
|
||||
|
||||
// Convert to float.
|
||||
a_.OpUToF(dest, dest_src);
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
|
||||
if (register_count() < 1) {
|
||||
return;
|
||||
|
@ -348,29 +378,9 @@ void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
|
|||
}
|
||||
}
|
||||
|
||||
// Add the base vertex index.
|
||||
a_.OpIAdd(index_dest, index_src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexOffset,
|
||||
offsetof(SystemConstants, vertex_index_offset),
|
||||
dxbc::Src::kXXXX));
|
||||
|
||||
// Mask since the GPU only uses the lower 24 bits of the vertex index (tested
|
||||
// on an Adreno 200 phone). `((index & 0xFFFFFF) + offset) & 0xFFFFFF` is the
|
||||
// same as `(index + offset) & 0xFFFFFF`.
|
||||
a_.OpAnd(index_dest, index_src, dxbc::Src::LU(xenos::kVertexIndexMask));
|
||||
|
||||
// Clamp the vertex index after offsetting.
|
||||
a_.OpUMax(index_dest, index_src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexMinMax,
|
||||
offsetof(SystemConstants, vertex_index_min),
|
||||
dxbc::Src::kXXXX));
|
||||
a_.OpUMin(index_dest, index_src,
|
||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexMinMax,
|
||||
offsetof(SystemConstants, vertex_index_max),
|
||||
dxbc::Src::kXXXX));
|
||||
|
||||
// Convert to float.
|
||||
a_.OpUToF(index_dest, index_src);
|
||||
// Remap the index to the needed range and convert it to floating-point.
|
||||
RemapAndConvertVertexIndices(index_dest.index_1d_.index_,
|
||||
index_dest.write_mask_, index_src);
|
||||
|
||||
if (uses_register_dynamic_addressing) {
|
||||
// Store to indexed GPR 0 in x0[0].
|
||||
|
@ -435,12 +445,12 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() {
|
|||
: dxbc::Dest::R(0, 0b0111),
|
||||
dxbc::Src::VDomain(0b000110));
|
||||
if (register_count() >= 2) {
|
||||
// Copy the primitive index to r1.x as a float.
|
||||
// Remap and write the primitive index to r1.x as floating-point.
|
||||
uint32_t primitive_id_temp =
|
||||
uses_register_dynamic_addressing ? PushSystemTemp() : 1;
|
||||
in_primitive_id_used_ = true;
|
||||
a_.OpUToF(dxbc::Dest::R(primitive_id_temp, 0b0001),
|
||||
dxbc::Src::VPrim());
|
||||
RemapAndConvertVertexIndices(primitive_id_temp, 0b0001,
|
||||
dxbc::Src::VPrim());
|
||||
if (uses_register_dynamic_addressing) {
|
||||
a_.OpMov(dxbc::Dest::X(0, 1, 0b0001),
|
||||
dxbc::Src::R(primitive_id_temp, dxbc::Src::kXXXX));
|
||||
|
@ -518,11 +528,13 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() {
|
|||
a_.OpMov(uses_register_dynamic_addressing ? dxbc::Dest::X(0, 0, 0b0110)
|
||||
: dxbc::Dest::R(0, 0b0110),
|
||||
dxbc::Src::VDomain(0b010000));
|
||||
// Copy the primitive index to r0.x as a float.
|
||||
// Remap and write the primitive index to r0.x as floating-point.
|
||||
// 4D5307F1 ground quad patches use the primitive index offset.
|
||||
uint32_t primitive_id_temp =
|
||||
uses_register_dynamic_addressing ? PushSystemTemp() : 0;
|
||||
in_primitive_id_used_ = true;
|
||||
a_.OpUToF(dxbc::Dest::R(primitive_id_temp, 0b0001), dxbc::Src::VPrim());
|
||||
RemapAndConvertVertexIndices(primitive_id_temp, 0b0001,
|
||||
dxbc::Src::VPrim());
|
||||
if (uses_register_dynamic_addressing) {
|
||||
a_.OpMov(dxbc::Dest::X(0, 0, 0b0001),
|
||||
dxbc::Src::R(primitive_id_temp, dxbc::Src::kXXXX));
|
||||
|
|
|
@ -756,6 +756,13 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
|||
uint32_t factor_component);
|
||||
|
||||
// Writing the prologue.
|
||||
// Applies the offset to vertex or tessellation patch indices in the source
|
||||
// components, restricts them to the minimum and the maximum index values, and
|
||||
// converts them to floating-point. The destination may be the same as the
|
||||
// source.
|
||||
void RemapAndConvertVertexIndices(uint32_t dest_temp,
|
||||
uint32_t dest_temp_components,
|
||||
const dxbc::Src& src);
|
||||
void StartVertexShader_LoadVertexIndex();
|
||||
void StartVertexOrDomainShader();
|
||||
void StartDomainShader();
|
||||
|
|
Loading…
Reference in New Issue