diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index ff174c4a5..22c6c8a0a 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -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 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()); diff --git a/src/xenia/gpu/spirv_shader_translator.h b/src/xenia/gpu/spirv_shader_translator.h index 7c1c14c01..18afaff79 100644 --- a/src/xenia/gpu/spirv_shader_translator.h +++ b/src/xenia/gpu/spirv_shader_translator.h @@ -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,