[SPIR-V] Make interpolators an array to fix Adreno linkage

This commit is contained in:
Triang3l 2022-07-09 17:52:26 +03:00
parent b3edc56576
commit b41bb35a20
2 changed files with 42 additions and 33 deletions

View File

@ -75,9 +75,6 @@ SpirvShaderTranslator::Features::Features(
} }
} }
const std::string SpirvShaderTranslator::kInterpolatorNamePrefix =
"xe_interpolator_";
SpirvShaderTranslator::SpirvShaderTranslator(const Features& features) SpirvShaderTranslator::SpirvShaderTranslator(const Features& features)
: features_(features) {} : features_(features) {}
@ -164,6 +161,8 @@ void SpirvShaderTranslator::StartTranslation() {
type_float2_ = builder_->makeVectorType(type_float_, 2); type_float2_ = builder_->makeVectorType(type_float_, 2);
type_float3_ = builder_->makeVectorType(type_float_, 3); type_float3_ = builder_->makeVectorType(type_float_, 3);
type_float4_ = builder_->makeVectorType(type_float_, 4); type_float4_ = builder_->makeVectorType(type_float_, 4);
type_interpolators_ = builder_->makeArrayType(
type_float4_, builder_->makeUintConstant(xenos::kMaxInterpolators), 0);
const_int_0_ = builder_->makeIntConstant(0); const_int_0_ = builder_->makeIntConstant(0);
id_vector_temp_.clear(); id_vector_temp_.clear();
@ -1069,17 +1068,15 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
main_interface_.push_back(input_vertex_index_); main_interface_.push_back(input_vertex_index_);
} }
// Create the Xenia-specific outputs. // Create the interpolator output.
// TODO(Triang3l): Change to an interpolator array. input_output_interpolators_ =
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) { builder_->createVariable(spv::NoPrecision, spv::StorageClassOutput,
spv::Id interpolator = builder_->createVariable( type_interpolators_, "xe_out_interpolators");
spv::NoPrecision, spv::StorageClassOutput, type_float4_, builder_->addDecoration(input_output_interpolators_, spv::DecorationLocation,
(kInterpolatorNamePrefix + std::to_string(i)).c_str()); 0);
input_output_interpolators_[i] = interpolator; builder_->addDecoration(input_output_interpolators_,
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i)); spv::DecorationInvariant);
builder_->addDecoration(interpolator, spv::DecorationInvariant); main_interface_.push_back(input_output_interpolators_);
main_interface_.push_back(interpolator);
}
// Create the gl_PerVertex output for used system outputs. // Create the gl_PerVertex output for used system outputs.
std::vector<spv::Id> struct_per_vertex_members; std::vector<spv::Id> struct_per_vertex_members;
@ -1108,7 +1105,12 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderInMain() {
// Zero the interpolators. // Zero the interpolators.
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) { for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) {
builder_->createStore(const_float4_0_, input_output_interpolators_[i]); id_vector_temp_.clear();
id_vector_temp_.push_back(builder_->makeIntConstant(int(i)));
builder_->createStore(const_float4_0_,
builder_->createAccessChain(
spv::StorageClassOutput,
input_output_interpolators_, id_vector_temp_));
} }
// Load the vertex index or the tessellation parameters. // Load the vertex index or the tessellation parameters.
@ -1282,17 +1284,13 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
} }
void SpirvShaderTranslator::StartFragmentShaderBeforeMain() { void SpirvShaderTranslator::StartFragmentShaderBeforeMain() {
// Interpolator inputs. // Interpolator input.
uint32_t interpolator_count = input_output_interpolators_ =
std::min(xenos::kMaxInterpolators, register_count()); builder_->createVariable(spv::NoPrecision, spv::StorageClassInput,
for (uint32_t i = 0; i < interpolator_count; ++i) { type_interpolators_, "xe_in_interpolators");
spv::Id interpolator = builder_->createVariable( builder_->addDecoration(input_output_interpolators_, spv::DecorationLocation,
spv::NoPrecision, spv::StorageClassInput, type_float4_, 0);
(kInterpolatorNamePrefix + std::to_string(i)).c_str()); main_interface_.push_back(input_output_interpolators_);
input_output_interpolators_[i] = interpolator;
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i));
main_interface_.push_back(interpolator);
}
bool param_gen_needed = GetPsParamGenInterpolator() != UINT32_MAX; bool param_gen_needed = GetPsParamGenInterpolator() != UINT32_MAX;
@ -1360,7 +1358,10 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
// Register array element. // Register array element.
id_vector_temp_.push_back(builder_->makeIntConstant(int(i))); id_vector_temp_.push_back(builder_->makeIntConstant(int(i)));
builder_->createStore( builder_->createStore(
builder_->createLoad(input_output_interpolators_[i], spv::NoPrecision), builder_->createLoad(builder_->createAccessChain(
spv::StorageClassInput,
input_output_interpolators_, id_vector_temp_),
spv::NoPrecision),
builder_->createAccessChain(spv::StorageClassFunction, builder_->createAccessChain(spv::StorageClassFunction,
var_main_registers_, id_vector_temp_)); var_main_registers_, id_vector_temp_));
} }
@ -1837,7 +1838,12 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
} break; } break;
case InstructionStorageTarget::kInterpolator: case InstructionStorageTarget::kInterpolator:
assert_true(is_vertex_shader()); assert_true(is_vertex_shader());
target_pointer = input_output_interpolators_[result.storage_index]; id_vector_temp_util_.clear();
id_vector_temp_util_.push_back(
builder_->makeIntConstant(int(result.storage_index)));
target_pointer = builder_->createAccessChain(spv::StorageClassOutput,
input_output_interpolators_,
id_vector_temp_util_);
break; break;
case InstructionStorageTarget::kPosition: case InstructionStorageTarget::kPosition:
assert_true(is_vertex_shader()); assert_true(is_vertex_shader());

View File

@ -529,6 +529,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
spv::Id type_float_vectors_[4]; spv::Id type_float_vectors_[4];
}; };
spv::Id type_interpolators_;
spv::Id const_int_0_; spv::Id const_int_0_;
spv::Id const_int4_0_; spv::Id const_int4_0_;
spv::Id const_uint_0_; spv::Id const_uint_0_;
@ -589,11 +591,12 @@ class SpirvShaderTranslator : public ShaderTranslator {
// PS, only when needed - bool. // PS, only when needed - bool.
spv::Id input_front_facing_; spv::Id input_front_facing_;
// In vertex or tessellation evaluation shaders - outputs, always // VS output or PS input, only when needed - type_interpolators_.
// xenos::kMaxInterpolators. // The Qualcomm Adreno driver has strict requirements for stage linkage - if
// In pixel shaders - inputs, min(xenos::kMaxInterpolators, register_count()). // this is an array in one stage, it must be an array in the other (in case of
spv::Id input_output_interpolators_[xenos::kMaxInterpolators]; // Xenia, including geometry shaders); it must not be an array in one and just
static const std::string kInterpolatorNamePrefix; // elements in consecutive locations in another.
spv::Id input_output_interpolators_;
enum OutputPerVertexMember : unsigned int { enum OutputPerVertexMember : unsigned int {
kOutputPerVertexMemberPosition, kOutputPerVertexMemberPosition,