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

View File

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