[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);
|
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() {
|
void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
|
||||||
if (register_count() < 1) {
|
if (register_count() < 1) {
|
||||||
return;
|
return;
|
||||||
|
@ -348,29 +378,9 @@ void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the base vertex index.
|
// Remap the index to the needed range and convert it to floating-point.
|
||||||
a_.OpIAdd(index_dest, index_src,
|
RemapAndConvertVertexIndices(index_dest.index_1d_.index_,
|
||||||
LoadSystemConstant(SystemConstants::Index::kVertexIndexOffset,
|
index_dest.write_mask_, index_src);
|
||||||
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);
|
|
||||||
|
|
||||||
if (uses_register_dynamic_addressing) {
|
if (uses_register_dynamic_addressing) {
|
||||||
// Store to indexed GPR 0 in x0[0].
|
// Store to indexed GPR 0 in x0[0].
|
||||||
|
@ -435,12 +445,12 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() {
|
||||||
: dxbc::Dest::R(0, 0b0111),
|
: dxbc::Dest::R(0, 0b0111),
|
||||||
dxbc::Src::VDomain(0b000110));
|
dxbc::Src::VDomain(0b000110));
|
||||||
if (register_count() >= 2) {
|
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 =
|
uint32_t primitive_id_temp =
|
||||||
uses_register_dynamic_addressing ? PushSystemTemp() : 1;
|
uses_register_dynamic_addressing ? PushSystemTemp() : 1;
|
||||||
in_primitive_id_used_ = true;
|
in_primitive_id_used_ = true;
|
||||||
a_.OpUToF(dxbc::Dest::R(primitive_id_temp, 0b0001),
|
RemapAndConvertVertexIndices(primitive_id_temp, 0b0001,
|
||||||
dxbc::Src::VPrim());
|
dxbc::Src::VPrim());
|
||||||
if (uses_register_dynamic_addressing) {
|
if (uses_register_dynamic_addressing) {
|
||||||
a_.OpMov(dxbc::Dest::X(0, 1, 0b0001),
|
a_.OpMov(dxbc::Dest::X(0, 1, 0b0001),
|
||||||
dxbc::Src::R(primitive_id_temp, dxbc::Src::kXXXX));
|
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)
|
a_.OpMov(uses_register_dynamic_addressing ? dxbc::Dest::X(0, 0, 0b0110)
|
||||||
: dxbc::Dest::R(0, 0b0110),
|
: dxbc::Dest::R(0, 0b0110),
|
||||||
dxbc::Src::VDomain(0b010000));
|
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 =
|
uint32_t primitive_id_temp =
|
||||||
uses_register_dynamic_addressing ? PushSystemTemp() : 0;
|
uses_register_dynamic_addressing ? PushSystemTemp() : 0;
|
||||||
in_primitive_id_used_ = true;
|
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) {
|
if (uses_register_dynamic_addressing) {
|
||||||
a_.OpMov(dxbc::Dest::X(0, 0, 0b0001),
|
a_.OpMov(dxbc::Dest::X(0, 0, 0b0001),
|
||||||
dxbc::Src::R(primitive_id_temp, dxbc::Src::kXXXX));
|
dxbc::Src::R(primitive_id_temp, dxbc::Src::kXXXX));
|
||||||
|
|
|
@ -756,6 +756,13 @@ class DxbcShaderTranslator : public ShaderTranslator {
|
||||||
uint32_t factor_component);
|
uint32_t factor_component);
|
||||||
|
|
||||||
// Writing the prologue.
|
// 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 StartVertexShader_LoadVertexIndex();
|
||||||
void StartVertexOrDomainShader();
|
void StartVertexOrDomainShader();
|
||||||
void StartDomainShader();
|
void StartDomainShader();
|
||||||
|
|
Loading…
Reference in New Issue