Merge branch 'xenia-project:master' into canary_experimental

This commit is contained in:
Radosław Gliński 2023-04-26 13:34:57 +02:00 committed by GitHub
commit 37051afcaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1306 additions and 1744 deletions

View File

@ -0,0 +1,105 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2023 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/gpu/spirv_builder.h"
#include <memory>
#include <utility>
#include <vector>
namespace xe {
namespace gpu {
spv::Id SpirvBuilder::createQuadOp(spv::Op op_code, spv::Id type_id,
spv::Id operand1, spv::Id operand2,
spv::Id operand3, spv::Id operand4) {
if (generatingOpCodeForSpecConst) {
std::vector<spv::Id> operands(4);
operands[0] = operand1;
operands[1] = operand2;
operands[2] = operand3;
operands[3] = operand4;
return createSpecConstantOp(op_code, type_id, operands,
std::vector<spv::Id>());
}
std::unique_ptr<spv::Instruction> op =
std::make_unique<spv::Instruction>(getUniqueId(), type_id, op_code);
op->addIdOperand(operand1);
op->addIdOperand(operand2);
op->addIdOperand(operand3);
op->addIdOperand(operand4);
spv::Id result = op->getResultId();
buildPoint->addInstruction(std::move(op));
return result;
}
spv::Id SpirvBuilder::createNoContractionUnaryOp(spv::Op op_code,
spv::Id type_id,
spv::Id operand) {
spv::Id result = createUnaryOp(op_code, type_id, operand);
addDecoration(result, spv::DecorationNoContraction);
return result;
}
spv::Id SpirvBuilder::createNoContractionBinOp(spv::Op op_code, spv::Id type_id,
spv::Id operand1,
spv::Id operand2) {
spv::Id result = createBinOp(op_code, type_id, operand1, operand2);
addDecoration(result, spv::DecorationNoContraction);
return result;
}
spv::Id SpirvBuilder::createUnaryBuiltinCall(spv::Id result_type,
spv::Id builtins, int entry_point,
spv::Id operand) {
std::unique_ptr<spv::Instruction> instruction =
std::make_unique<spv::Instruction>(getUniqueId(), result_type,
spv::OpExtInst);
instruction->addIdOperand(builtins);
instruction->addImmediateOperand(entry_point);
instruction->addIdOperand(operand);
spv::Id result = instruction->getResultId();
getBuildPoint()->addInstruction(std::move(instruction));
return result;
}
spv::Id SpirvBuilder::createBinBuiltinCall(spv::Id result_type,
spv::Id builtins, int entry_point,
spv::Id operand1, spv::Id operand2) {
std::unique_ptr<spv::Instruction> instruction =
std::make_unique<spv::Instruction>(getUniqueId(), result_type,
spv::OpExtInst);
instruction->addIdOperand(builtins);
instruction->addImmediateOperand(entry_point);
instruction->addIdOperand(operand1);
instruction->addIdOperand(operand2);
spv::Id result = instruction->getResultId();
getBuildPoint()->addInstruction(std::move(instruction));
return result;
}
spv::Id SpirvBuilder::createTriBuiltinCall(spv::Id result_type,
spv::Id builtins, int entry_point,
spv::Id operand1, spv::Id operand2,
spv::Id operand3) {
std::unique_ptr<spv::Instruction> instruction =
std::make_unique<spv::Instruction>(getUniqueId(), result_type,
spv::OpExtInst);
instruction->addIdOperand(builtins);
instruction->addImmediateOperand(entry_point);
instruction->addIdOperand(operand1);
instruction->addIdOperand(operand2);
instruction->addIdOperand(operand3);
spv::Id result = instruction->getResultId();
getBuildPoint()->addInstruction(std::move(instruction));
return result;
}
} // namespace gpu
} // namespace xe

View File

@ -0,0 +1,50 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2023 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_SPIRV_BUILDER_H_
#define XENIA_GPU_SPIRV_BUILDER_H_
#include "third_party/glslang/SPIRV/SpvBuilder.h"
namespace xe {
namespace gpu {
// SpvBuilder with extra helpers.
class SpirvBuilder : public spv::Builder {
public:
SpirvBuilder(unsigned int spv_version, unsigned int user_number,
spv::SpvBuildLogger* logger)
: spv::Builder(spv_version, user_number, logger) {}
// Make public rather than protected.
using spv::Builder::createSelectionMerge;
spv::Id createQuadOp(spv::Op op_code, spv::Id type_id, spv::Id operand1,
spv::Id operand2, spv::Id operand3, spv::Id operand4);
spv::Id createNoContractionUnaryOp(spv::Op op_code, spv::Id type_id,
spv::Id operand);
spv::Id createNoContractionBinOp(spv::Op op_code, spv::Id type_id,
spv::Id operand1, spv::Id operand2);
spv::Id createUnaryBuiltinCall(spv::Id result_type, spv::Id builtins,
int entry_point, spv::Id operand);
spv::Id createBinBuiltinCall(spv::Id result_type, spv::Id builtins,
int entry_point, spv::Id operand1,
spv::Id operand2);
spv::Id createTriBuiltinCall(spv::Id result_type, spv::Id builtins,
int entry_point, spv::Id operand1,
spv::Id operand2, spv::Id operand3);
};
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_SPIRV_BUILDER_H_

View File

@ -161,7 +161,7 @@ uint32_t SpirvShaderTranslator::GetModificationRegisterCount() const {
void SpirvShaderTranslator::StartTranslation() { void SpirvShaderTranslator::StartTranslation() {
// TODO(Triang3l): Logger. // TODO(Triang3l): Logger.
builder_ = std::make_unique<spv::Builder>( builder_ = std::make_unique<SpirvBuilder>(
features_.spirv_version, (kSpirvMagicToolId << 16) | 1, nullptr); features_.spirv_version, (kSpirvMagicToolId << 16) | 1, nullptr);
builder_->addCapability(IsSpirvTessEvalShader() ? spv::CapabilityTessellation builder_->addCapability(IsSpirvTessEvalShader() ? spv::CapabilityTessellation
@ -591,7 +591,7 @@ void SpirvShaderTranslator::StartTranslation() {
main_switch_header_ = builder_->getBuildPoint(); main_switch_header_ = builder_->getBuildPoint();
main_switch_merge_ = main_switch_merge_ =
new spv::Block(builder_->getUniqueId(), *function_main_); new spv::Block(builder_->getUniqueId(), *function_main_);
SpirvCreateSelectionMerge(main_switch_merge_->getId(), builder_->createSelectionMerge(main_switch_merge_,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
main_switch_op_ = std::make_unique<spv::Instruction>(spv::OpSwitch); main_switch_op_ = std::make_unique<spv::Instruction>(spv::OpSwitch);
main_switch_op_->addIdOperand(main_loop_pc_current); main_switch_op_->addIdOperand(main_loop_pc_current);
@ -914,7 +914,7 @@ void SpirvShaderTranslator::ProcessLoopStartInstruction(
spv::OpIEqual, type_bool_, loop_count_new, const_uint_0_); spv::OpIEqual, type_bool_, loop_count_new, const_uint_0_);
spv::Block& skip_block = builder_->makeNewBlock(); spv::Block& skip_block = builder_->makeNewBlock();
spv::Block& body_block = builder_->makeNewBlock(); spv::Block& body_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(body_block.getId()); builder_->createSelectionMerge(&body_block, spv::SelectionControlMaskNone);
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op = std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional); std::make_unique<spv::Instruction>(spv::OpBranchConditional);
@ -976,7 +976,7 @@ void SpirvShaderTranslator::ProcessLoopEndInstruction(
spv::Block& body_block = *builder_->getBuildPoint(); spv::Block& body_block = *builder_->getBuildPoint();
spv::Block& continue_block = builder_->makeNewBlock(); spv::Block& continue_block = builder_->makeNewBlock();
spv::Block& break_block = builder_->makeNewBlock(); spv::Block& break_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(break_block.getId()); builder_->createSelectionMerge(&break_block, spv::SelectionControlMaskNone);
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op = std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional); std::make_unique<spv::Instruction>(spv::OpBranchConditional);
@ -1110,7 +1110,6 @@ spv::Id SpirvShaderTranslator::SpirvSmearScalarResultOrConstant(
} }
int num_components = builder_->getNumTypeComponents(vector_type); int num_components = builder_->getNumTypeComponents(vector_type);
id_vector_temp_util_.clear(); id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(size_t(num_components));
for (int i = 0; i < num_components; ++i) { for (int i = 0; i < num_components; ++i) {
id_vector_temp_util_.push_back(scalar); id_vector_temp_util_.push_back(scalar);
} }
@ -1294,7 +1293,7 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderInMain() {
spv::Block& block_load_vertex_index_pre = *builder_->getBuildPoint(); spv::Block& block_load_vertex_index_pre = *builder_->getBuildPoint();
spv::Block& block_load_vertex_index_start = builder_->makeNewBlock(); spv::Block& block_load_vertex_index_start = builder_->makeNewBlock();
spv::Block& block_load_vertex_index_merge = builder_->makeNewBlock(); spv::Block& block_load_vertex_index_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_load_vertex_index_merge.getId(), builder_->createSelectionMerge(&block_load_vertex_index_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch(load_vertex_index, builder_->createConditionalBranch(load_vertex_index,
&block_load_vertex_index_start, &block_load_vertex_index_start,
@ -1390,7 +1389,7 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderInMain() {
spv::Block& block_load_vertex_index_pre = *builder_->getBuildPoint(); spv::Block& block_load_vertex_index_pre = *builder_->getBuildPoint();
spv::Block& block_load_vertex_index_start = builder_->makeNewBlock(); spv::Block& block_load_vertex_index_start = builder_->makeNewBlock();
spv::Block& block_load_vertex_index_merge = builder_->makeNewBlock(); spv::Block& block_load_vertex_index_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_load_vertex_index_merge.getId(), builder_->createSelectionMerge(&block_load_vertex_index_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch(load_vertex_index, builder_->createConditionalBranch(load_vertex_index,
&block_load_vertex_index_start, &block_load_vertex_index_start,
@ -1491,9 +1490,8 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
builder_->makeUintConstant( builder_->makeUintConstant(
static_cast<unsigned int>(kSysFlag_WNotReciprocal))), static_cast<unsigned int>(kSysFlag_WNotReciprocal))),
const_uint_0_); const_uint_0_);
spv::Id guest_position_w_inv = builder_->createBinOp( spv::Id guest_position_w_inv = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_, position_w); spv::OpFDiv, type_float_, const_float_1_, position_w);
builder_->addDecoration(guest_position_w_inv, spv::DecorationNoContraction);
position_w = position_w =
builder_->createTriOp(spv::OpSelect, type_float_, is_w_not_reciprocal, builder_->createTriOp(spv::OpSelect, type_float_, is_w_not_reciprocal,
position_w, guest_position_w_inv); position_w, guest_position_w_inv);
@ -1517,10 +1515,8 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
builder_->makeUintConstant( builder_->makeUintConstant(
static_cast<unsigned int>(kSysFlag_XYDividedByW))), static_cast<unsigned int>(kSysFlag_XYDividedByW))),
const_uint_0_); const_uint_0_);
spv::Id guest_position_xy_mul_w = builder_->createBinOp( spv::Id guest_position_xy_mul_w = builder_->createNoContractionBinOp(
spv::OpVectorTimesScalar, type_float2_, position_xy, position_w); spv::OpVectorTimesScalar, type_float2_, position_xy, position_w);
builder_->addDecoration(guest_position_xy_mul_w,
spv::DecorationNoContraction);
position_xy = builder_->createTriOp( position_xy = builder_->createTriOp(
spv::OpSelect, type_float2_, spv::OpSelect, type_float2_,
builder_->smearScalar(spv::NoPrecision, is_xy_divided_by_w, builder_->smearScalar(spv::NoPrecision, is_xy_divided_by_w,
@ -1538,10 +1534,8 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
builder_->makeUintConstant( builder_->makeUintConstant(
static_cast<unsigned int>(kSysFlag_ZDividedByW))), static_cast<unsigned int>(kSysFlag_ZDividedByW))),
const_uint_0_); const_uint_0_);
spv::Id guest_position_z_mul_w = spv::Id guest_position_z_mul_w = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpFMul, type_float_, position_z, position_w); spv::OpFMul, type_float_, position_z, position_w);
builder_->addDecoration(guest_position_z_mul_w,
spv::DecorationNoContraction);
position_z = position_z =
builder_->createTriOp(spv::OpSelect, type_float_, is_z_divided_by_w, builder_->createTriOp(spv::OpSelect, type_float_, is_z_divided_by_w,
guest_position_z_mul_w, position_z); guest_position_z_mul_w, position_z);
@ -1566,9 +1560,8 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
builder_->createAccessChain(spv::StorageClassUniform, builder_->createAccessChain(spv::StorageClassUniform,
uniform_system_constants_, id_vector_temp_), uniform_system_constants_, id_vector_temp_),
spv::NoPrecision); spv::NoPrecision);
position_xyz = position_xyz = builder_->createNoContractionBinOp(spv::OpFMul, type_float3_,
builder_->createBinOp(spv::OpFMul, type_float3_, position_xyz, ndc_scale); position_xyz, ndc_scale);
builder_->addDecoration(position_xyz, spv::DecorationNoContraction);
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back( id_vector_temp_.push_back(
builder_->makeIntConstant(kSystemConstantNdcOffset)); builder_->makeIntConstant(kSystemConstantNdcOffset));
@ -1576,12 +1569,10 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
builder_->createAccessChain(spv::StorageClassUniform, builder_->createAccessChain(spv::StorageClassUniform,
uniform_system_constants_, id_vector_temp_), uniform_system_constants_, id_vector_temp_),
spv::NoPrecision); spv::NoPrecision);
spv::Id ndc_offset_mul_w = builder_->createBinOp( spv::Id ndc_offset_mul_w = builder_->createNoContractionBinOp(
spv::OpVectorTimesScalar, type_float3_, ndc_offset, position_w); spv::OpVectorTimesScalar, type_float3_, ndc_offset, position_w);
builder_->addDecoration(ndc_offset_mul_w, spv::DecorationNoContraction); position_xyz = builder_->createNoContractionBinOp(
position_xyz = builder_->createBinOp(spv::OpFAdd, type_float3_, position_xyz, spv::OpFAdd, type_float3_, position_xyz, ndc_offset_mul_w);
ndc_offset_mul_w);
builder_->addDecoration(position_xyz, spv::DecorationNoContraction);
// Write the point size. // Write the point size.
if (output_point_size_ != spv::NoResult) { if (output_point_size_ != spv::NoResult) {
@ -1667,36 +1658,29 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back(builder_->makeIntConstant( id_vector_temp_.push_back(builder_->makeIntConstant(
kSystemConstantPointScreenDiameterToNdcRadius)); kSystemConstantPointScreenDiameterToNdcRadius));
spv::Id point_radius = builder_->createBinOp( spv::Id point_radius = builder_->createNoContractionBinOp(
spv::OpFMul, type_float2_, point_guest_diameter, spv::OpFMul, type_float2_, point_guest_diameter,
builder_->createLoad(builder_->createAccessChain( builder_->createLoad(builder_->createAccessChain(
spv::StorageClassUniform, spv::StorageClassUniform,
uniform_system_constants_, id_vector_temp_), uniform_system_constants_, id_vector_temp_),
spv::NoPrecision)); spv::NoPrecision));
builder_->addDecoration(point_radius, spv::DecorationNoContraction);
// Transform the radius from the normalized device coordinates to the clip // Transform the radius from the normalized device coordinates to the clip
// space. // space.
point_radius = builder_->createBinOp(spv::OpVectorTimesScalar, type_float2_, point_radius = builder_->createNoContractionBinOp(
point_radius, position_w); spv::OpVectorTimesScalar, type_float2_, point_radius, position_w);
builder_->addDecoration(point_radius, spv::DecorationNoContraction);
// Apply the direction of expansion for the current host vertex. // Expand the point sprite in the direction for the current host vertex.
spv::Id point_radius_negative =
builder_->createUnaryOp(spv::OpFNegate, type_float2_, point_radius);
builder_->addDecoration(point_radius_negative,
spv::DecorationNoContraction);
// Expand the point sprite.
uint_vector_temp_.clear(); uint_vector_temp_.clear();
uint_vector_temp_.push_back(0); uint_vector_temp_.push_back(0);
uint_vector_temp_.push_back(1); uint_vector_temp_.push_back(1);
spv::Id point_position_xy = builder_->createBinOp( spv::Id point_position_xy = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float2_, spv::OpFAdd, type_float2_,
builder_->createRvalueSwizzle(spv::NoPrecision, type_float2_, builder_->createRvalueSwizzle(spv::NoPrecision, type_float2_,
position_xyz, uint_vector_temp_), position_xyz, uint_vector_temp_),
builder_->createTriOp(spv::OpSelect, type_float2_, builder_->createTriOp(spv::OpSelect, type_float2_,
point_vertex_positive, point_radius, point_vertex_positive, point_radius,
point_radius_negative)); builder_->createNoContractionUnaryOp(
builder_->addDecoration(point_position_xy, spv::DecorationNoContraction); spv::OpFNegate, type_float2_, point_radius)));
// Store the position. // Store the position.
spv::Id position; spv::Id position;
{ {
@ -1993,8 +1977,8 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
builder_->makeNewBlock(); builder_->makeNewBlock();
main_fsi_early_depth_stencil_execute_quad_merge_ = main_fsi_early_depth_stencil_execute_quad_merge_ =
&builder_->makeNewBlock(); &builder_->makeNewBlock();
SpirvCreateSelectionMerge( builder_->createSelectionMerge(
main_fsi_early_depth_stencil_execute_quad_merge_->getId(), main_fsi_early_depth_stencil_execute_quad_merge_,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch( builder_->createConditionalBranch(
quad_needs_execution, &main_fsi_early_depth_stencil_execute_quad, quad_needs_execution, &main_fsi_early_depth_stencil_execute_quad,
@ -2053,19 +2037,15 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
assert_true(input_fragment_coordinates_ != spv::NoResult); assert_true(input_fragment_coordinates_ != spv::NoResult);
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back(const_int_0_); id_vector_temp_.push_back(const_int_0_);
spv::Id param_gen_x = spv::Id param_gen_x = builder_->createUnaryBuiltinCall(
builder_->createLoad(builder_->createAccessChain( type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs,
spv::StorageClassInput, builder_->createUnaryBuiltinCall(
input_fragment_coordinates_, id_vector_temp_), type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor,
spv::NoPrecision); builder_->createLoad(
id_vector_temp_.clear(); builder_->createAccessChain(spv::StorageClassInput,
id_vector_temp_.push_back(param_gen_x); input_fragment_coordinates_,
param_gen_x = builder_->createBuiltinCall( id_vector_temp_),
type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor, id_vector_temp_); spv::NoPrecision)));
id_vector_temp_.clear();
id_vector_temp_.push_back(param_gen_x);
param_gen_x = builder_->createBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, id_vector_temp_);
if (!modification.pixel.param_gen_point) { if (!modification.pixel.param_gen_point) {
assert_true(input_front_facing_ != spv::NoResult); assert_true(input_front_facing_ != spv::NoResult);
param_gen_x = builder_->createTriOp( param_gen_x = builder_->createTriOp(
@ -2092,19 +2072,15 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
// Y - pixel Y .0 in the magnitude, is point in the sign bit. // Y - pixel Y .0 in the magnitude, is point in the sign bit.
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back(builder_->makeIntConstant(1)); id_vector_temp_.push_back(builder_->makeIntConstant(1));
spv::Id param_gen_y = spv::Id param_gen_y = builder_->createUnaryBuiltinCall(
builder_->createLoad(builder_->createAccessChain( type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs,
spv::StorageClassInput, builder_->createUnaryBuiltinCall(
input_fragment_coordinates_, id_vector_temp_), type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor,
spv::NoPrecision); builder_->createLoad(
id_vector_temp_.clear(); builder_->createAccessChain(spv::StorageClassInput,
id_vector_temp_.push_back(param_gen_y); input_fragment_coordinates_,
param_gen_y = builder_->createBuiltinCall( id_vector_temp_),
type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor, id_vector_temp_); spv::NoPrecision)));
id_vector_temp_.clear();
id_vector_temp_.push_back(param_gen_y);
param_gen_y = builder_->createBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, id_vector_temp_);
if (modification.pixel.param_gen_point) { if (modification.pixel.param_gen_point) {
param_gen_y = builder_->createUnaryOp( param_gen_y = builder_->createUnaryOp(
spv::OpBitcast, type_float_, spv::OpBitcast, type_float_,
@ -2120,14 +2096,10 @@ void SpirvShaderTranslator::StartFragmentShaderInMain() {
assert_true(input_point_coordinates_ != spv::NoResult); assert_true(input_point_coordinates_ != spv::NoResult);
// Saturate to avoid negative point coordinates if the center of the pixel // Saturate to avoid negative point coordinates if the center of the pixel
// is not covered, and extrapolation is done. // is not covered, and extrapolation is done.
id_vector_temp_.clear(); spv::Id param_gen_point_coordinates = builder_->createTriBuiltinCall(
id_vector_temp_.push_back( type_float2_, ext_inst_glsl_std_450_, GLSLstd450NClamp,
builder_->createLoad(input_point_coordinates_, spv::NoPrecision)); builder_->createLoad(input_point_coordinates_, spv::NoPrecision),
id_vector_temp_.push_back(const_float2_0_); const_float2_0_, const_float2_1_);
id_vector_temp_.push_back(const_float2_1_);
spv::Id param_gen_point_coordinates =
builder_->createBuiltinCall(type_float2_, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_);
param_gen_z = builder_->createCompositeExtract( param_gen_z = builder_->createCompositeExtract(
param_gen_point_coordinates, type_float_, 0); param_gen_point_coordinates, type_float_, 0);
param_gen_w = builder_->createCompositeExtract( param_gen_w = builder_->createCompositeExtract(
@ -2245,7 +2217,8 @@ void SpirvShaderTranslator::UpdateExecConditionals(
cf_exec_condition_ = condition; cf_exec_condition_ = condition;
cf_exec_conditional_merge_ = new spv::Block( cf_exec_conditional_merge_ = new spv::Block(
builder_->getUniqueId(), builder_->getBuildPoint()->getParent()); builder_->getUniqueId(), builder_->getBuildPoint()->getParent());
SpirvCreateSelectionMerge(cf_exec_conditional_merge_->getId()); builder_->createSelectionMerge(cf_exec_conditional_merge_,
spv::SelectionControlDontFlattenMask);
spv::Block& inner_block = builder_->makeNewBlock(); spv::Block& inner_block = builder_->makeNewBlock();
builder_->createConditionalBranch( builder_->createConditionalBranch(
condition_id, condition ? &inner_block : cf_exec_conditional_merge_, condition_id, condition ? &inner_block : cf_exec_conditional_merge_,
@ -2285,7 +2258,8 @@ void SpirvShaderTranslator::UpdateInstructionPredication(bool predicated,
spv::Block& predicated_block = builder_->makeNewBlock(); spv::Block& predicated_block = builder_->makeNewBlock();
cf_instruction_predicate_merge_ = new spv::Block( cf_instruction_predicate_merge_ = new spv::Block(
builder_->getUniqueId(), builder_->getBuildPoint()->getParent()); builder_->getUniqueId(), builder_->getBuildPoint()->getParent());
SpirvCreateSelectionMerge(cf_instruction_predicate_merge_->getId()); builder_->createSelectionMerge(cf_instruction_predicate_merge_,
spv::SelectionControlMaskNone);
builder_->createConditionalBranch( builder_->createConditionalBranch(
predicate_id, predicate_id,
condition ? &predicated_block : cf_instruction_predicate_merge_, condition ? &predicated_block : cf_instruction_predicate_merge_,
@ -2386,7 +2360,6 @@ spv::Id SpirvShaderTranslator::LoadOperandStorage(
case InstructionStorageSource::kConstantFloat: case InstructionStorageSource::kConstantFloat:
assert_true(uniform_float_constants_ != spv::NoResult); assert_true(uniform_float_constants_ != spv::NoResult);
id_vector_temp_util_.clear(); id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(2);
// The first and the only structure member. // The first and the only structure member.
id_vector_temp_util_.push_back(const_int_0_); id_vector_temp_util_.push_back(const_int_0_);
// Array element. // Array element.
@ -2412,16 +2385,13 @@ spv::Id SpirvShaderTranslator::ApplyOperandModifiers(
} }
if (original_operand.is_absolute_value || force_absolute) { if (original_operand.is_absolute_value || force_absolute) {
EnsureBuildPointAvailable(); EnsureBuildPointAvailable();
id_vector_temp_util_.clear(); operand_value = builder_->createUnaryBuiltinCall(
id_vector_temp_util_.push_back(operand_value); type, ext_inst_glsl_std_450_, GLSLstd450FAbs, operand_value);
operand_value = builder_->createBuiltinCall(
type, ext_inst_glsl_std_450_, GLSLstd450FAbs, id_vector_temp_util_);
} }
if (original_operand.is_negated != invert_negate) { if (original_operand.is_negated != invert_negate) {
EnsureBuildPointAvailable(); EnsureBuildPointAvailable();
operand_value = operand_value = builder_->createNoContractionUnaryOp(spv::OpFNegate, type,
builder_->createUnaryOp(spv::OpFNegate, type, operand_value); operand_value);
builder_->addDecoration(operand_value, spv::DecorationNoContraction);
} }
return operand_value; return operand_value;
} }
@ -2448,7 +2418,6 @@ spv::Id SpirvShaderTranslator::GetUnmodifiedOperandComponents(
static_cast<unsigned int>(SwizzleSource::kX)); static_cast<unsigned int>(SwizzleSource::kX));
} }
uint_vector_temp_util_.clear(); uint_vector_temp_util_.clear();
uint_vector_temp_util_.reserve(component_count);
uint32_t components_remaining = components; uint32_t components_remaining = components;
uint32_t component_index; uint32_t component_index;
while (xe::bit_scan_forward(components_remaining, &component_index)) { while (xe::bit_scan_forward(components_remaining, &component_index)) {
@ -2481,11 +2450,9 @@ spv::Id SpirvShaderTranslator::GetAbsoluteOperand(
return operand_storage; return operand_storage;
} }
EnsureBuildPointAvailable(); EnsureBuildPointAvailable();
id_vector_temp_util_.clear(); return builder_->createUnaryBuiltinCall(builder_->getTypeId(operand_storage),
id_vector_temp_util_.push_back(operand_storage); ext_inst_glsl_std_450_,
return builder_->createBuiltinCall(builder_->getTypeId(operand_storage), GLSLstd450FAbs, operand_storage);
ext_inst_glsl_std_450_, GLSLstd450FAbs,
id_vector_temp_util_);
} }
void SpirvShaderTranslator::StoreResult(const InstructionResult& result, void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
@ -2574,16 +2541,11 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
if (result.is_clamped && non_constant_components) { if (result.is_clamped && non_constant_components) {
// Apply the saturation modifier to the result. // Apply the saturation modifier to the result.
id_vector_temp_util_.clear(); value = builder_->createTriBuiltinCall(
id_vector_temp_util_.reserve(3);
id_vector_temp_util_.push_back(value);
id_vector_temp_util_.push_back(
const_float_vectors_0_[value_num_components - 1]);
id_vector_temp_util_.push_back(
const_float_vectors_1_[value_num_components - 1]);
value = builder_->createBuiltinCall(
type_float_vectors_[value_num_components - 1], ext_inst_glsl_std_450_, type_float_vectors_[value_num_components - 1], ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_util_); GLSLstd450NClamp, value,
const_float_vectors_0_[value_num_components - 1],
const_float_vectors_1_[value_num_components - 1]);
} }
// The value contains either result.GetUsedResultComponents() in a condensed // The value contains either result.GetUsedResultComponents() in a condensed
@ -2660,7 +2622,6 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
value_to_store = value; value_to_store = value;
} else { } else {
uint_vector_temp_util_.clear(); uint_vector_temp_util_.clear();
uint_vector_temp_util_.reserve(target_num_components);
uint_vector_temp_util_.insert( uint_vector_temp_util_.insert(
uint_vector_temp_util_.cend(), result_swizzled_value_components, uint_vector_temp_util_.cend(), result_swizzled_value_components,
result_swizzled_value_components + target_num_components); result_swizzled_value_components + target_num_components);
@ -2686,7 +2647,6 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
if (target_num_components > 1) { if (target_num_components > 1) {
// Constants only - vector target. // Constants only - vector target.
id_vector_temp_util_.clear(); id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(target_num_components);
for (uint32_t i = 0; i < target_num_components; ++i) { for (uint32_t i = 0; i < target_num_components; ++i) {
id_vector_temp_util_.push_back( id_vector_temp_util_.push_back(
(constant_values & (1 << i)) ? const_float_1_ : const_float_0_); (constant_values & (1 << i)) ? const_float_1_ : const_float_0_);
@ -2718,7 +2678,6 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
} else { } else {
// Mixed non-constants and constants - scalar source. // Mixed non-constants and constants - scalar source.
id_vector_temp_util_.clear(); id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(target_num_components);
for (uint32_t i = 0; i < target_num_components; ++i) { for (uint32_t i = 0; i < target_num_components; ++i) {
if (constant_components & (1 << i)) { if (constant_components & (1 << i)) {
id_vector_temp_util_.push_back( id_vector_temp_util_.push_back(
@ -2804,13 +2763,9 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
uniform_system_constants_, uniform_system_constants_,
id_vector_temp_util_), id_vector_temp_util_),
spv::NoPrecision)); spv::NoPrecision));
id_vector_temp_util_.clear(); point_size = builder_->createBinBuiltinCall(
id_vector_temp_util_.reserve(2); type_int_, ext_inst_glsl_std_450_, GLSLstd450SMax,
id_vector_temp_util_.push_back(point_vertex_diameter_min); point_vertex_diameter_min, point_size);
id_vector_temp_util_.push_back(point_size);
point_size =
builder_->createBuiltinCall(type_int_, ext_inst_glsl_std_450_,
GLSLstd450SMax, id_vector_temp_util_);
id_vector_temp_util_.clear(); id_vector_temp_util_.clear();
id_vector_temp_util_.push_back( id_vector_temp_util_.push_back(
builder_->makeIntConstant(kSystemConstantPointVertexDiameterMax)); builder_->makeIntConstant(kSystemConstantPointVertexDiameterMax));
@ -2821,13 +2776,9 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
uniform_system_constants_, uniform_system_constants_,
id_vector_temp_util_), id_vector_temp_util_),
spv::NoPrecision)); spv::NoPrecision));
id_vector_temp_util_.clear(); point_size = builder_->createBinBuiltinCall(
id_vector_temp_util_.reserve(2); type_int_, ext_inst_glsl_std_450_, GLSLstd450SMin,
id_vector_temp_util_.push_back(point_vertex_diameter_max); point_vertex_diameter_max, point_size);
id_vector_temp_util_.push_back(point_size);
point_size =
builder_->createBuiltinCall(type_int_, ext_inst_glsl_std_450_,
GLSLstd450SMin, id_vector_temp_util_);
value_to_store = builder_->createCompositeInsert( value_to_store = builder_->createCompositeInsert(
builder_->createUnaryOp(spv::OpBitcast, type_float_, point_size), builder_->createUnaryOp(spv::OpBitcast, type_float_, point_size),
value_to_store, type_float3_, 0); value_to_store, type_float3_, 0);
@ -2879,7 +2830,8 @@ spv::Id SpirvShaderTranslator::EndianSwap32Uint(spv::Id value, spv::Id endian) {
assert_false(block_pre_8in16.isTerminated()); assert_false(block_pre_8in16.isTerminated());
spv::Block& block_8in16 = builder_->makeNewBlock(); spv::Block& block_8in16 = builder_->makeNewBlock();
spv::Block& block_8in16_merge = builder_->makeNewBlock(); spv::Block& block_8in16_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_8in16_merge.getId()); builder_->createSelectionMerge(&block_8in16_merge,
spv::SelectionControlMaskNone);
builder_->createConditionalBranch(is_8in16_or_8in32, &block_8in16, builder_->createConditionalBranch(is_8in16_or_8in32, &block_8in16,
&block_8in16_merge); &block_8in16_merge);
builder_->setBuildPoint(&block_8in16); builder_->setBuildPoint(&block_8in16);
@ -2919,18 +2871,16 @@ spv::Id SpirvShaderTranslator::EndianSwap32Uint(spv::Id value, spv::Id endian) {
spv::Block& block_pre_16in32 = *builder_->getBuildPoint(); spv::Block& block_pre_16in32 = *builder_->getBuildPoint();
spv::Block& block_16in32 = builder_->makeNewBlock(); spv::Block& block_16in32 = builder_->makeNewBlock();
spv::Block& block_16in32_merge = builder_->makeNewBlock(); spv::Block& block_16in32_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_16in32_merge.getId()); builder_->createSelectionMerge(&block_16in32_merge,
spv::SelectionControlMaskNone);
builder_->createConditionalBranch(is_8in32_or_16in32, &block_16in32, builder_->createConditionalBranch(is_8in32_or_16in32, &block_16in32,
&block_16in32_merge); &block_16in32_merge);
builder_->setBuildPoint(&block_16in32); builder_->setBuildPoint(&block_16in32);
id_vector_temp_.clear(); spv::Id swapped_16in32 = builder_->createQuadOp(
id_vector_temp_.push_back(builder_->createBinOp( spv::OpBitFieldInsert, type,
spv::OpShiftRightLogical, type, value, const_uint_16_typed)); builder_->createBinOp(spv::OpShiftRightLogical, type, value,
id_vector_temp_.push_back(value); const_uint_16_typed),
id_vector_temp_.insert(id_vector_temp_.cend(), 2, value, builder_->makeIntConstant(16), builder_->makeIntConstant(16));
builder_->makeIntConstant(16));
spv::Id swapped_16in32 =
builder_->createOp(spv::OpBitFieldInsert, type, id_vector_temp_);
builder_->createBranch(&block_16in32_merge); builder_->createBranch(&block_16in32_merge);
builder_->setBuildPoint(&block_16in32_merge); builder_->setBuildPoint(&block_16in32_merge);
{ {
@ -2991,7 +2941,7 @@ spv::Id SpirvShaderTranslator::LoadUint32FromSharedMemory(
std::unique_ptr<spv::Instruction> value_phi_op = std::unique_ptr<spv::Instruction> value_phi_op =
std::make_unique<spv::Instruction>(value_phi_result, type_uint_, std::make_unique<spv::Instruction>(value_phi_result, type_uint_,
spv::OpPhi); spv::OpPhi);
SpirvCreateSelectionMerge(switch_merge_block.getId(), builder_->createSelectionMerge(&switch_merge_block,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
{ {
std::unique_ptr<spv::Instruction> switch_op = std::unique_ptr<spv::Instruction> switch_op =
@ -3042,12 +2992,9 @@ spv::Id SpirvShaderTranslator::PWLGammaToLinear(spv::Id gamma,
if (!gamma_pre_saturated) { if (!gamma_pre_saturated) {
// Saturate, flushing NaN to 0. // Saturate, flushing NaN to 0.
id_vector_temp_.clear(); gamma = builder_->createTriBuiltinCall(value_type, ext_inst_glsl_std_450_,
id_vector_temp_.push_back(gamma); GLSLstd450NClamp, gamma,
id_vector_temp_.push_back(const_vector_0); const_vector_0, const_vector_1);
id_vector_temp_.push_back(const_vector_1);
gamma = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_);
} }
spv::Id is_piece_at_least_3 = builder_->createBinOp( spv::Id is_piece_at_least_3 = builder_->createBinOp(
@ -3097,29 +3044,26 @@ spv::Id SpirvShaderTranslator::PWLGammaToLinear(spv::Id gamma,
spv::Op value_times_scalar_opcode = spv::Op value_times_scalar_opcode =
is_vector ? spv::OpVectorTimesScalar : spv::OpFMul; is_vector ? spv::OpVectorTimesScalar : spv::OpFMul;
// linear = gamma * (255.0f * 1024.0f) * scale + offset // linear = gamma * (255.0f * 1024.0f) * scale + offset
spv::Id linear = spv::Id linear = builder_->createNoContractionBinOp(
builder_->createBinOp(value_times_scalar_opcode, value_type, gamma, spv::OpFAdd, value_type,
builder_->makeFloatConstant(255.0f * 1024.0f)); builder_->createNoContractionBinOp(
builder_->addDecoration(linear, spv::DecorationNoContraction); spv::OpFMul, value_type,
linear = builder_->createBinOp(spv::OpFMul, value_type, linear, scale); builder_->createNoContractionBinOp(
builder_->addDecoration(linear, spv::DecorationNoContraction); value_times_scalar_opcode, value_type, gamma,
linear = builder_->createBinOp(spv::OpFAdd, value_type, linear, offset); builder_->makeFloatConstant(255.0f * 1024.0f)),
builder_->addDecoration(linear, spv::DecorationNoContraction); scale),
offset);
// linear += trunc(linear * scale) // linear += trunc(linear * scale)
spv::Id linear_integer_term = linear = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpFMul, value_type, linear, scale); spv::OpFAdd, value_type, linear,
builder_->addDecoration(linear_integer_term, spv::DecorationNoContraction); builder_->createUnaryBuiltinCall(
id_vector_temp_.clear(); value_type, ext_inst_glsl_std_450_, GLSLstd450Trunc,
id_vector_temp_.push_back(linear_integer_term); builder_->createNoContractionBinOp(spv::OpFMul, value_type, linear,
linear_integer_term = builder_->createBuiltinCall( scale)));
value_type, ext_inst_glsl_std_450_, GLSLstd450Trunc, id_vector_temp_);
linear = builder_->createBinOp(spv::OpFAdd, value_type, linear,
linear_integer_term);
builder_->addDecoration(linear, spv::DecorationNoContraction);
// linear *= 1.0f / 1023.0f // linear *= 1.0f / 1023.0f
linear = builder_->createBinOp(value_times_scalar_opcode, value_type, linear, linear = builder_->createNoContractionBinOp(
value_times_scalar_opcode, value_type, linear,
builder_->makeFloatConstant(1.0f / 1023.0f)); builder_->makeFloatConstant(1.0f / 1023.0f));
builder_->addDecoration(linear, spv::DecorationNoContraction);
return linear; return linear;
} }
@ -3139,12 +3083,9 @@ spv::Id SpirvShaderTranslator::LinearToPWLGamma(spv::Id linear,
if (!linear_pre_saturated) { if (!linear_pre_saturated) {
// Saturate, flushing NaN to 0. // Saturate, flushing NaN to 0.
id_vector_temp_.clear(); linear = builder_->createTriBuiltinCall(value_type, ext_inst_glsl_std_450_,
id_vector_temp_.push_back(linear); GLSLstd450NClamp, linear,
id_vector_temp_.push_back(const_vector_0); const_vector_0, const_vector_1);
id_vector_temp_.push_back(const_vector_1);
linear = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_);
} }
spv::Id is_piece_at_least_3 = builder_->createBinOp( spv::Id is_piece_at_least_3 = builder_->createBinOp(
@ -3192,19 +3133,16 @@ spv::Id SpirvShaderTranslator::LinearToPWLGamma(spv::Id linear,
offset_3_or_2, offset_1_or_0); offset_3_or_2, offset_1_or_0);
// gamma = trunc(linear * scale) * (1.0f / 255.0f) + offset // gamma = trunc(linear * scale) * (1.0f / 255.0f) + offset
spv::Id gamma = builder_->createBinOp(spv::OpFMul, value_type, linear, scale); return builder_->createNoContractionBinOp(
builder_->addDecoration(gamma, spv::DecorationNoContraction); spv::OpFAdd, value_type,
id_vector_temp_.clear(); builder_->createNoContractionBinOp(
id_vector_temp_.push_back(gamma); is_vector ? spv::OpVectorTimesScalar : spv::OpFMul, value_type,
gamma = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_, builder_->createUnaryBuiltinCall(
GLSLstd450Trunc, id_vector_temp_); value_type, ext_inst_glsl_std_450_, GLSLstd450Trunc,
gamma = builder_->createBinOp( builder_->createNoContractionBinOp(spv::OpFMul, value_type,
is_vector ? spv::OpVectorTimesScalar : spv::OpFMul, value_type, gamma, linear, scale)),
builder_->makeFloatConstant(1.0f / 255.0f)); builder_->makeFloatConstant(1.0f / 255.0f)),
builder_->addDecoration(gamma, spv::DecorationNoContraction); offset);
gamma = builder_->createBinOp(spv::OpFAdd, value_type, gamma, offset);
builder_->addDecoration(gamma, spv::DecorationNoContraction);
return gamma;
} }
} // namespace gpu } // namespace gpu

View File

@ -17,8 +17,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "third_party/glslang/SPIRV/SpvBuilder.h"
#include "xenia/gpu/shader_translator.h" #include "xenia/gpu/shader_translator.h"
#include "xenia/gpu/spirv_builder.h"
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
#include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_provider.h"
@ -374,30 +374,30 @@ class SpirvShaderTranslator : public ShaderTranslator {
// Converts the color value externally clamped to [0, 31.875] to 7e3 floating // Converts the color value externally clamped to [0, 31.875] to 7e3 floating
// point, with zeros in bits 10:31, rounding to the nearest even. // point, with zeros in bits 10:31, rounding to the nearest even.
static spv::Id PreClampedFloat32To7e3(spv::Builder& builder, static spv::Id PreClampedFloat32To7e3(SpirvBuilder& builder,
spv::Id f32_scalar, spv::Id f32_scalar,
spv::Id ext_inst_glsl_std_450); spv::Id ext_inst_glsl_std_450);
// Same as PreClampedFloat32To7e3, but clamps the input to [0, 31.875]. // Same as PreClampedFloat32To7e3, but clamps the input to [0, 31.875].
static spv::Id UnclampedFloat32To7e3(spv::Builder& builder, static spv::Id UnclampedFloat32To7e3(SpirvBuilder& builder,
spv::Id f32_scalar, spv::Id f32_scalar,
spv::Id ext_inst_glsl_std_450); spv::Id ext_inst_glsl_std_450);
// Converts the 7e3 number in bits [f10_shift, f10_shift + 10) to a 32-bit // Converts the 7e3 number in bits [f10_shift, f10_shift + 10) to a 32-bit
// float. // float.
static spv::Id Float7e3To32(spv::Builder& builder, spv::Id f10_uint_scalar, static spv::Id Float7e3To32(SpirvBuilder& builder, spv::Id f10_uint_scalar,
uint32_t f10_shift, bool result_as_uint, uint32_t f10_shift, bool result_as_uint,
spv::Id ext_inst_glsl_std_450); spv::Id ext_inst_glsl_std_450);
// Converts the depth value externally clamped to the representable [0, 2) // Converts the depth value externally clamped to the representable [0, 2)
// range to 20e4 floating point, with zeros in bits 24:31, rounding to the // range to 20e4 floating point, with zeros in bits 24:31, rounding to the
// nearest even or towards zero. If remap_from_0_to_0_5 is true, it's assumed // nearest even or towards zero. If remap_from_0_to_0_5 is true, it's assumed
// that 0...1 is pre-remapped to 0...0.5 in the input. // that 0...1 is pre-remapped to 0...0.5 in the input.
static spv::Id PreClampedDepthTo20e4(spv::Builder& builder, static spv::Id PreClampedDepthTo20e4(SpirvBuilder& builder,
spv::Id f32_scalar, spv::Id f32_scalar,
bool round_to_nearest_even, bool round_to_nearest_even,
bool remap_from_0_to_0_5, bool remap_from_0_to_0_5,
spv::Id ext_inst_glsl_std_450); spv::Id ext_inst_glsl_std_450);
// Converts the 20e4 number in bits [f24_shift, f24_shift + 10) to a 32-bit // Converts the 20e4 number in bits [f24_shift, f24_shift + 10) to a 32-bit
// float. // float.
static spv::Id Depth20e4To32(spv::Builder& builder, spv::Id f24_uint_scalar, static spv::Id Depth20e4To32(SpirvBuilder& builder, spv::Id f24_uint_scalar,
uint32_t f24_shift, bool remap_to_0_to_0_5, uint32_t f24_shift, bool remap_to_0_to_0_5,
bool result_as_uint, bool result_as_uint,
spv::Id ext_inst_glsl_std_450); spv::Id ext_inst_glsl_std_450);
@ -451,15 +451,6 @@ class SpirvShaderTranslator : public ShaderTranslator {
// Builder helpers. // Builder helpers.
spv::Id SpirvSmearScalarResultOrConstant(spv::Id scalar, spv::Id vector_type); spv::Id SpirvSmearScalarResultOrConstant(spv::Id scalar, spv::Id vector_type);
void SpirvCreateSelectionMerge(
spv::Id merge_block_id, spv::SelectionControlMask selection_control_mask =
spv::SelectionControlMaskNone) {
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(merge_block_id);
selection_merge_op->addImmediateOperand(selection_control_mask);
builder_->getBuildPoint()->addInstruction(std::move(selection_merge_op));
}
Modification GetSpirvShaderModification() const { Modification GetSpirvShaderModification() const {
return Modification(current_translation().modification()); return Modification(current_translation().modification());
@ -571,6 +562,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
// must be called with absolute values of operands - use GetAbsoluteOperand! // must be called with absolute values of operands - use GetAbsoluteOperand!
spv::Id ZeroIfAnyOperandIsZero(spv::Id value, spv::Id operand_0_abs, spv::Id ZeroIfAnyOperandIsZero(spv::Id value, spv::Id operand_0_abs,
spv::Id operand_1_abs); spv::Id operand_1_abs);
// Conditionally discard the current fragment. Changes the build point.
void KillPixel(spv::Id condition);
// Return type is a xe::bit_count(result.GetUsedResultComponents())-component // Return type is a xe::bit_count(result.GetUsedResultComponents())-component
// float vector or a single float, depending on whether it's a reduction // float vector or a single float, depending on whether it's a reduction
// instruction (check getTypeId of the result), or returns spv::NoResult if // instruction (check getTypeId of the result), or returns spv::NoResult if
@ -687,7 +680,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
// and stencil testing with fragment shader interlock. // and stencil testing with fragment shader interlock.
bool is_depth_only_fragment_shader_ = false; bool is_depth_only_fragment_shader_ = false;
std::unique_ptr<spv::Builder> builder_; std::unique_ptr<SpirvBuilder> builder_;
std::vector<spv::Id> id_vector_temp_; std::vector<spv::Id> id_vector_temp_;
// For helper functions like operand loading, so they don't conflict with // For helper functions like operand loading, so they don't conflict with

View File

@ -28,21 +28,44 @@ spv::Id SpirvShaderTranslator::ZeroIfAnyOperandIsZero(spv::Id value,
int num_components = builder_->getNumComponents(value); int num_components = builder_->getNumComponents(value);
assert_true(builder_->getNumComponents(operand_0_abs) == num_components); assert_true(builder_->getNumComponents(operand_0_abs) == num_components);
assert_true(builder_->getNumComponents(operand_1_abs) == num_components); assert_true(builder_->getNumComponents(operand_1_abs) == num_components);
id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(2);
id_vector_temp_util_.push_back(operand_0_abs);
id_vector_temp_util_.push_back(operand_1_abs);
return builder_->createTriOp( return builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp( builder_->createBinOp(
spv::OpFOrdEqual, type_bool_vectors_[num_components - 1], spv::OpFOrdEqual, type_bool_vectors_[num_components - 1],
builder_->createBuiltinCall(type_float_vectors_[num_components - 1], builder_->createBinBuiltinCall(
ext_inst_glsl_std_450_, GLSLstd450NMin, type_float_vectors_[num_components - 1], ext_inst_glsl_std_450_,
id_vector_temp_util_), GLSLstd450NMin, operand_0_abs, operand_1_abs),
const_float_vectors_0_[num_components - 1]), const_float_vectors_0_[num_components - 1]),
const_float_vectors_0_[num_components - 1], value); const_float_vectors_0_[num_components - 1], value);
} }
void SpirvShaderTranslator::KillPixel(spv::Id condition) {
// Same calls as in spv::Builder::If.
spv::Function& function = builder_->getBuildPoint()->getParent();
spv::Block* kill_block = new spv::Block(builder_->getUniqueId(), function);
spv::Block* merge_block = new spv::Block(builder_->getUniqueId(), function);
spv::Block& header_block = *builder_->getBuildPoint();
function.addBlock(kill_block);
builder_->setBuildPoint(kill_block);
// Kill without influencing the control flow in the translated shader.
if (var_main_kill_pixel_ != spv::NoResult) {
builder_->createStore(builder_->makeBoolConstant(true),
var_main_kill_pixel_);
}
if (features_.demote_to_helper_invocation) {
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
}
builder_->createBranch(merge_block);
builder_->setBuildPoint(&header_block);
builder_->createSelectionMerge(merge_block, spv::SelectionControlMaskNone);
builder_->createConditionalBranch(condition, kill_block, merge_block);
function.addBlock(merge_block);
builder_->setBuildPoint(merge_block);
}
void SpirvShaderTranslator::ProcessAluInstruction( void SpirvShaderTranslator::ProcessAluInstruction(
const ParsedAluInstruction& instr) { const ParsedAluInstruction& instr) {
if (instr.IsNop()) { if (instr.IsNop()) {
@ -162,14 +185,12 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
switch (instr.vector_opcode) { switch (instr.vector_opcode) {
case ucode::AluVectorOpcode::kAdd: { case ucode::AluVectorOpcode::kAdd: {
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::OpFAdd, result_type, spv::OpFAdd, result_type,
GetOperandComponents(operand_storage[0], instr.vector_operands[0], GetOperandComponents(operand_storage[0], instr.vector_operands[0],
used_result_components), used_result_components),
GetOperandComponents(operand_storage[1], instr.vector_operands[1], GetOperandComponents(operand_storage[1], instr.vector_operands[1],
used_result_components)); used_result_components));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluVectorOpcode::kMul: case ucode::AluVectorOpcode::kMul:
case ucode::AluVectorOpcode::kMad: { case ucode::AluVectorOpcode::kMad: {
@ -179,9 +200,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
GetOperandComponents(operand_storage[i], instr.vector_operands[i], GetOperandComponents(operand_storage[i], instr.vector_operands[i],
used_result_components); used_result_components);
} }
spv::Id result = builder_->createBinOp( spv::Id result = builder_->createNoContractionBinOp(
spv::OpFMul, result_type, multiplicands[0], multiplicands[1]); spv::OpFMul, result_type, multiplicands[0], multiplicands[1]);
builder_->addDecoration(result, spv::DecorationNoContraction);
uint32_t multiplicands_different = uint32_t multiplicands_different =
used_result_components & used_result_components &
~instr.vector_operands[0].GetIdenticalComponents( ~instr.vector_operands[0].GetIdenticalComponents(
@ -229,15 +249,12 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
different_operands[i] = GetAbsoluteOperand(different_operands[i], different_operands[i] = GetAbsoluteOperand(different_operands[i],
instr.vector_operands[i]); instr.vector_operands[i]);
} }
id_vector_temp_.clear();
id_vector_temp_.push_back(different_operands[0]);
id_vector_temp_.push_back(different_operands[1]);
spv::Id different_abs_min =
builder_->createBuiltinCall(different_type, ext_inst_glsl_std_450_,
GLSLstd450NMin, id_vector_temp_);
spv::Id different_zero = builder_->createBinOp( spv::Id different_zero = builder_->createBinOp(
spv::OpFOrdEqual, type_bool_vectors_[different_count - 1], spv::OpFOrdEqual, type_bool_vectors_[different_count - 1],
different_abs_min, const_float_vectors_0_[different_count - 1]); builder_->createBinBuiltinCall(
different_type, ext_inst_glsl_std_450_, GLSLstd450NMin,
different_operands[0], different_operands[1]),
const_float_vectors_0_[different_count - 1]);
// Replace with +0. // Replace with +0.
different_result = builder_->createTriOp( different_result = builder_->createTriOp(
spv::OpSelect, different_type, different_zero, spv::OpSelect, different_type, different_zero,
@ -276,11 +293,10 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
if (instr.vector_opcode == ucode::AluVectorOpcode::kMad) { if (instr.vector_opcode == ucode::AluVectorOpcode::kMad) {
// Not replacing true `0 + term` with conditional selection of the term // Not replacing true `0 + term` with conditional selection of the term
// because +0 + -0 should result in +0, not -0. // because +0 + -0 should result in +0, not -0.
result = builder_->createBinOp( result = builder_->createNoContractionBinOp(
spv::OpFAdd, result_type, result, spv::OpFAdd, result_type, result,
GetOperandComponents(operand_storage[2], instr.vector_operands[2], GetOperandComponents(operand_storage[2], instr.vector_operands[2],
used_result_components)); used_result_components));
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
return result; return result;
} }
@ -303,24 +319,18 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
} else { } else {
maxa_operand_0_w = operand_0; maxa_operand_0_w = operand_0;
} }
spv::Id maxa_address =
builder_->createBinOp(spv::OpFAdd, type_float_, maxa_operand_0_w,
builder_->makeFloatConstant(0.5f));
builder_->addDecoration(maxa_address, spv::DecorationNoContraction);
id_vector_temp_.clear();
id_vector_temp_.push_back(maxa_address);
maxa_address =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Floor, id_vector_temp_);
id_vector_temp_.clear();
id_vector_temp_.push_back(maxa_address);
id_vector_temp_.push_back(builder_->makeFloatConstant(-256.0f));
id_vector_temp_.push_back(builder_->makeFloatConstant(255.0f));
builder_->createStore( builder_->createStore(
builder_->createUnaryOp( builder_->createUnaryOp(
spv::OpConvertFToS, type_int_, spv::OpConvertFToS, type_int_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->createTriBuiltinCall(
GLSLstd450NClamp, id_vector_temp_)), type_float_, ext_inst_glsl_std_450_, GLSLstd450NClamp,
builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor,
builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, maxa_operand_0_w,
builder_->makeFloatConstant(0.5f))),
builder_->makeFloatConstant(-256.0f),
builder_->makeFloatConstant(255.0f))),
var_main_address_register_); var_main_address_register_);
} }
if (!used_result_components) { if (!used_result_components) {
@ -434,13 +444,11 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
case ucode::AluVectorOpcode::kFrc: case ucode::AluVectorOpcode::kFrc:
case ucode::AluVectorOpcode::kTrunc: case ucode::AluVectorOpcode::kTrunc:
case ucode::AluVectorOpcode::kFloor: case ucode::AluVectorOpcode::kFloor:
id_vector_temp_.clear(); return builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(GetOperandComponents(operand_storage[0],
instr.vector_operands[0],
used_result_components));
return builder_->createBuiltinCall(
result_type, ext_inst_glsl_std_450_, result_type, ext_inst_glsl_std_450_,
GLSLstd450(kOps[size_t(instr.vector_opcode)]), id_vector_temp_); GLSLstd450(kOps[size_t(instr.vector_opcode)]),
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
used_result_components));
case ucode::AluVectorOpcode::kCndEq: case ucode::AluVectorOpcode::kCndEq:
case ucode::AluVectorOpcode::kCndGe: case ucode::AluVectorOpcode::kCndGe:
@ -488,10 +496,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
operand_components[j] = operand_components[j] =
builder_->createCompositeExtract(operands[j], type_float_, i); builder_->createCompositeExtract(operands[j], type_float_, i);
} }
spv::Id product = spv::Id product = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpFMul, type_float_, spv::OpFMul, type_float_, operand_components[0],
operand_components[0], operand_components[1]); operand_components[1]);
builder_->addDecoration(product, spv::DecorationNoContraction);
if (different & (1 << i)) { if (different & (1 << i)) {
// Shader Model 3: +0 or denormal * anything = +-0. // Shader Model 3: +0 or denormal * anything = +-0.
product = ZeroIfAnyOperandIsZero( product = ZeroIfAnyOperandIsZero(
@ -505,16 +512,14 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
result = product; result = product;
continue; continue;
} }
result = result = builder_->createNoContractionBinOp(spv::OpFAdd, type_float_,
builder_->createBinOp(spv::OpFAdd, type_float_, result, product); result, product);
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
if (instr.vector_opcode == ucode::AluVectorOpcode::kDp2Add) { if (instr.vector_opcode == ucode::AluVectorOpcode::kDp2Add) {
result = builder_->createBinOp( result = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, result, spv::OpFAdd, type_float_, result,
GetOperandComponents(operand_storage[2], instr.vector_operands[2], GetOperandComponents(operand_storage[2], instr.vector_operands[2],
0b0001)); 0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
return result; return result;
} }
@ -535,11 +540,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
if (!instr.vector_operands[0].is_absolute_value || if (!instr.vector_operands[0].is_absolute_value ||
instr.vector_operands[0].is_negated) { instr.vector_operands[0].is_negated) {
for (unsigned int i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
id_vector_temp_.clear(); operand_abs[i] = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(operand[i]); type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, operand[i]);
operand_abs[i] =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_);
} }
} else { } else {
for (unsigned int i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
@ -548,40 +550,29 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
} }
spv::Id operand_neg[3] = {}; spv::Id operand_neg[3] = {};
if (used_result_components & 0b0001) { if (used_result_components & 0b0001) {
operand_neg[1] = operand_neg[1] = builder_->createNoContractionUnaryOp(
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[1]); spv::OpFNegate, type_float_, operand[1]);
builder_->addDecoration(operand_neg[1], spv::DecorationNoContraction);
} }
if (used_result_components & 0b0010) { if (used_result_components & 0b0010) {
operand_neg[0] = operand_neg[0] = builder_->createNoContractionUnaryOp(
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[0]); spv::OpFNegate, type_float_, operand[0]);
builder_->addDecoration(operand_neg[0], spv::DecorationNoContraction); operand_neg[2] = builder_->createNoContractionUnaryOp(
operand_neg[2] = spv::OpFNegate, type_float_, operand[2]);
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[2]);
builder_->addDecoration(operand_neg[2], spv::DecorationNoContraction);
} }
spv::Id ma_z_result[4] = {}, ma_yx_result[4] = {};
// Check if the major axis is Z (abs(z) >= abs(x) && abs(z) >= abs(y)). // Check if the major axis is Z (abs(z) >= abs(x) && abs(z) >= abs(y)).
// Selection merge must be the penultimate instruction in the block, check spv::Builder::If ma_z_if(
// the condition before it. builder_->createBinOp(
spv::Id ma_z_condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_, spv::OpLogicalAnd, type_bool_,
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_, builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[0]), operand_abs[2], operand_abs[0]),
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_, builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[1])); operand_abs[2], operand_abs[1])),
spv::Function& function = builder_->getBuildPoint()->getParent(); spv::SelectionControlMaskNone, *builder_);
spv::Block& ma_z_block = builder_->makeNewBlock(); {
spv::Block& ma_yx_block = builder_->makeNewBlock();
spv::Block* ma_merge_block =
new spv::Block(builder_->getUniqueId(), function);
SpirvCreateSelectionMerge(ma_merge_block->getId());
builder_->createConditionalBranch(ma_z_condition, &ma_z_block,
&ma_yx_block);
builder_->setBuildPoint(&ma_z_block);
// The major axis is Z. // The major axis is Z.
spv::Id ma_z_result[4] = {};
// tc = -y // tc = -y
ma_z_result[0] = operand_neg[1]; ma_z_result[0] = operand_neg[1];
// ma/2 = z // ma/2 = z
@ -591,8 +582,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_); spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_);
if (used_result_components & 0b0010) { if (used_result_components & 0b0010) {
// sc = z < 0.0 ? -x : x // sc = z < 0.0 ? -x : x
ma_z_result[1] = builder_->createTriOp( ma_z_result[1] =
spv::OpSelect, type_float_, z_is_neg, operand_neg[0], operand[0]); builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
operand_neg[0], operand[0]);
} }
if (used_result_components & 0b1000) { if (used_result_components & 0b1000) {
// id = z < 0.0 ? 5.0 : 4.0 // id = z < 0.0 ? 5.0 : 4.0
@ -602,26 +594,20 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
builder_->makeFloatConstant(4.0f)); builder_->makeFloatConstant(4.0f));
} }
} }
builder_->createBranch(ma_merge_block); }
spv::Block& ma_z_end_block = *builder_->getBuildPoint();
ma_z_if.makeBeginElse();
{
spv::Id ma_y_result[4] = {}, ma_x_result[4] = {};
builder_->setBuildPoint(&ma_yx_block);
// The major axis is not Z - create an inner conditional to check if the // The major axis is not Z - create an inner conditional to check if the
// major axis is Y (abs(y) >= abs(x)). // major axis is Y (abs(y) >= abs(x)).
// Selection merge must be the penultimate instruction in the block, check spv::Builder::If ma_y_if(
// the condition before it.
spv::Id ma_y_condition =
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_, builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[1], operand_abs[0]); operand_abs[1], operand_abs[0]),
spv::Block& ma_y_block = builder_->makeNewBlock(); spv::SelectionControlMaskNone, *builder_);
spv::Block& ma_x_block = builder_->makeNewBlock(); {
spv::Block& ma_yx_merge_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(ma_yx_merge_block.getId());
builder_->createConditionalBranch(ma_y_condition, &ma_y_block,
&ma_x_block);
builder_->setBuildPoint(&ma_y_block);
// The major axis is Y. // The major axis is Y.
spv::Id ma_y_result[4] = {};
// sc = x // sc = x
ma_y_result[1] = operand[0]; ma_y_result[1] = operand[0];
// ma/2 = y // ma/2 = y
@ -631,8 +617,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_); spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_);
if (used_result_components & 0b0001) { if (used_result_components & 0b0001) {
// tc = y < 0.0 ? -z : z // tc = y < 0.0 ? -z : z
ma_y_result[0] = builder_->createTriOp( ma_y_result[0] =
spv::OpSelect, type_float_, y_is_neg, operand_neg[2], operand[2]); builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
operand_neg[2], operand[2]);
// id = y < 0.0 ? 3.0 : 2.0 // id = y < 0.0 ? 3.0 : 2.0
ma_y_result[3] = ma_y_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg, builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
@ -640,11 +627,11 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
builder_->makeFloatConstant(2.0f)); builder_->makeFloatConstant(2.0f));
} }
} }
builder_->createBranch(&ma_yx_merge_block); }
spv::Block& ma_y_end_block = *builder_->getBuildPoint();
builder_->setBuildPoint(&ma_x_block); ma_y_if.makeBeginElse();
{
// The major axis is X. // The major axis is X.
spv::Id ma_x_result[4] = {};
// tc = -y // tc = -y
ma_x_result[0] = operand_neg[1]; ma_x_result[0] = operand_neg[1];
// ma/2 = x // ma/2 = x
@ -654,8 +641,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_); spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_);
if (used_result_components & 0b0010) { if (used_result_components & 0b0010) {
// sc = x < 0.0 ? z : -z // sc = x < 0.0 ? z : -z
ma_x_result[1] = builder_->createTriOp( ma_x_result[1] =
spv::OpSelect, type_float_, x_is_neg, operand[2], operand_neg[2]); builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
operand[2], operand_neg[2]);
} }
if (used_result_components & 0b1000) { if (used_result_components & 0b1000) {
// id = x < 0.0 ? 1.0 : 0.0 // id = x < 0.0 ? 1.0 : 0.0
@ -664,12 +652,12 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
const_float_1_, const_float_0_); const_float_1_, const_float_0_);
} }
} }
builder_->createBranch(&ma_yx_merge_block); }
spv::Block& ma_x_end_block = *builder_->getBuildPoint();
ma_y_if.makeEndIf();
builder_->setBuildPoint(&ma_yx_merge_block); // The major axis is Y or X - choose the options of the result from Y
// The major axis is Y or X - choose the options of the result from Y and // and X.
// X.
spv::Id ma_yx_result[4] = {};
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
if (!(used_result_components & (1 << i))) { if (!(used_result_components & (1 << i))) {
continue; continue;
@ -678,16 +666,16 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
std::make_unique<spv::Instruction>(builder_->getUniqueId(), std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi); type_float_, spv::OpPhi);
phi_op->addIdOperand(ma_y_result[i]); phi_op->addIdOperand(ma_y_result[i]);
phi_op->addIdOperand(ma_y_block.getId()); phi_op->addIdOperand(ma_y_end_block.getId());
phi_op->addIdOperand(ma_x_result[i]); phi_op->addIdOperand(ma_x_result[i]);
phi_op->addIdOperand(ma_x_block.getId()); phi_op->addIdOperand(ma_x_end_block.getId());
ma_yx_result[i] = phi_op->getResultId(); ma_yx_result[i] = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op)); builder_->getBuildPoint()->addInstruction(std::move(phi_op));
} }
builder_->createBranch(ma_merge_block); }
spv::Block& ma_yx_end_block = *builder_->getBuildPoint();
ma_z_if.makeEndIf();
function.addBlock(ma_merge_block);
builder_->setBuildPoint(ma_merge_block);
// Choose the result options from Z and YX cases. // Choose the result options from Z and YX cases.
id_vector_temp_.clear(); id_vector_temp_.clear();
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
@ -698,9 +686,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
std::make_unique<spv::Instruction>(builder_->getUniqueId(), std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi); type_float_, spv::OpPhi);
phi_op->addIdOperand(ma_z_result[i]); phi_op->addIdOperand(ma_z_result[i]);
phi_op->addIdOperand(ma_z_block.getId()); phi_op->addIdOperand(ma_z_end_block.getId());
phi_op->addIdOperand(ma_yx_result[i]); phi_op->addIdOperand(ma_yx_result[i]);
phi_op->addIdOperand(ma_yx_merge_block.getId()); phi_op->addIdOperand(ma_yx_end_block.getId());
id_vector_temp_.push_back(phi_op->getResultId()); id_vector_temp_.push_back(phi_op->getResultId());
builder_->getBuildPoint()->addInstruction(std::move(phi_op)); builder_->getBuildPoint()->addInstruction(std::move(phi_op));
} }
@ -709,9 +697,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
// Multiply the major axis by 2. // Multiply the major axis by 2.
spv::Id& ma2 = id_vector_temp_[xe::bit_count(used_result_components & spv::Id& ma2 = id_vector_temp_[xe::bit_count(used_result_components &
((1 << 2) - 1))]; ((1 << 2) - 1))];
ma2 = builder_->createBinOp(spv::OpFMul, type_float_, ma2 = builder_->createNoContractionBinOp(
builder_->makeFloatConstant(2.0f), ma2); spv::OpFMul, type_float_, builder_->makeFloatConstant(2.0f), ma2);
builder_->addDecoration(ma2, spv::DecorationNoContraction);
} }
if (used_result_component_count == 1) { if (used_result_component_count == 1) {
// Only one component - not composite. // Only one component - not composite.
@ -746,13 +733,10 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
operand, type_float_, static_cast<unsigned int>(component)); operand, type_float_, static_cast<unsigned int>(component));
while (xe::bit_scan_forward(components_remaining, &component)) { while (xe::bit_scan_forward(components_remaining, &component)) {
components_remaining &= ~(uint32_t(1) << component); components_remaining &= ~(uint32_t(1) << component);
id_vector_temp_.clear(); result = builder_->createBinBuiltinCall(
id_vector_temp_.push_back(result); type_float_, ext_inst_glsl_std_450_, GLSLstd450NMax, result,
id_vector_temp_.push_back(builder_->createCompositeExtract( builder_->createCompositeExtract(
operand, type_float_, static_cast<unsigned int>(component))); operand, type_float_, static_cast<unsigned int>(component)));
result =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450NMax, id_vector_temp_);
} }
return result; return result;
} }
@ -802,45 +786,26 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, operands_x[0], builder_->createBinOp(spv::OpFOrdEqual, type_bool_, operands_x[0],
const_float_0_), const_float_0_),
builder_->createBinOp(op, type_bool_, operands_x[1], const_float_0_)); builder_->createBinOp(op, type_bool_, operands_x[1], const_float_0_));
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, spv::OpFAdd, type_float_,
builder_->createTriOp(spv::OpSelect, type_float_, condition, builder_->createTriOp(spv::OpSelect, type_float_, condition,
builder_->makeFloatConstant(-1.0f), builder_->makeFloatConstant(-1.0f),
operands_x[0]), operands_x[0]),
const_float_1_); const_float_1_);
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluVectorOpcode::kKillEq: case ucode::AluVectorOpcode::kKillEq:
case ucode::AluVectorOpcode::kKillGt: case ucode::AluVectorOpcode::kKillGt:
case ucode::AluVectorOpcode::kKillGe: case ucode::AluVectorOpcode::kKillGe:
case ucode::AluVectorOpcode::kKillNe: { case ucode::AluVectorOpcode::kKillNe: {
// Selection merge must be the penultimate instruction in the block, check KillPixel(builder_->createUnaryOp(
// the condition before it.
spv::Id condition = builder_->createUnaryOp(
spv::OpAny, type_bool_, spv::OpAny, type_bool_,
builder_->createBinOp( builder_->createBinOp(
spv::Op(kOps[size_t(instr.vector_opcode)]), type_bool4_, spv::Op(kOps[size_t(instr.vector_opcode)]), type_bool4_,
GetOperandComponents(operand_storage[0], instr.vector_operands[0], GetOperandComponents(operand_storage[0], instr.vector_operands[0],
0b1111), 0b1111),
GetOperandComponents(operand_storage[1], instr.vector_operands[1], GetOperandComponents(operand_storage[1], instr.vector_operands[1],
0b1111))); 0b1111))));
spv::Block& kill_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(merge_block.getId());
builder_->createConditionalBranch(condition, &kill_block, &merge_block);
builder_->setBuildPoint(&kill_block);
// Kill without influencing the control flow in the translated shader.
if (var_main_kill_pixel_ != spv::NoResult) {
builder_->createStore(builder_->makeBoolConstant(true),
var_main_kill_pixel_);
}
if (features_.demote_to_helper_invocation) {
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
}
builder_->createBranch(&merge_block);
builder_->setBuildPoint(&merge_block);
return const_float_0_; return const_float_0_;
} }
@ -874,9 +839,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
(used_result_components & 0b1000) (used_result_components & 0b1000)
? builder_->createCompositeExtract(operands[1], type_float_, 0) ? builder_->createCompositeExtract(operands[1], type_float_, 0)
: operands[1]; : operands[1];
result_y = builder_->createBinOp(spv::OpFMul, type_float_, result_y = builder_->createNoContractionBinOp(
operands_y[0], operands_y[1]); spv::OpFMul, type_float_, operands_y[0], operands_y[1]);
builder_->addDecoration(result_y, spv::DecorationNoContraction);
if (!(instr.vector_operands[0].GetIdenticalComponents( if (!(instr.vector_operands[0].GetIdenticalComponents(
instr.vector_operands[1]) & instr.vector_operands[1]) &
0b0010)) { 0b0010)) {
@ -999,26 +963,22 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kSubs: { case ucode::AluScalarOpcode::kSubs: {
spv::Id a, b; spv::Id a, b;
GetOperandScalarXY(operand_storage[0], instr.scalar_operands[0], a, b); GetOperandScalarXY(operand_storage[0], instr.scalar_operands[0], a, b);
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_, a, b); spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_, a, b);
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluScalarOpcode::kAddsPrev: case ucode::AluScalarOpcode::kAddsPrev:
case ucode::AluScalarOpcode::kSubsPrev: { case ucode::AluScalarOpcode::kSubsPrev: {
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_, spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001), 0b0001),
builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision)); builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluScalarOpcode::kMuls: { case ucode::AluScalarOpcode::kMuls: {
spv::Id a, b; spv::Id a, b;
GetOperandScalarXY(operand_storage[0], instr.scalar_operands[0], a, b); GetOperandScalarXY(operand_storage[0], instr.scalar_operands[0], a, b);
spv::Id result = builder_->createBinOp(spv::OpFMul, type_float_, a, b); spv::Id result =
builder_->addDecoration(result, spv::DecorationNoContraction); builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, b);
if (a != b) { if (a != b) {
// Shader Model 3: +0 or denormal * anything = +-0. // Shader Model 3: +0 or denormal * anything = +-0.
result = ZeroIfAnyOperandIsZero( result = ZeroIfAnyOperandIsZero(
@ -1032,15 +992,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
instr.scalar_operands[0], 0b0001); instr.scalar_operands[0], 0b0001);
spv::Id ps = spv::Id ps =
builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision); builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision);
spv::Id result = builder_->createBinOp(spv::OpFMul, type_float_, a, ps); spv::Id result =
builder_->addDecoration(result, spv::DecorationNoContraction); builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, ps);
// Shader Model 3: +0 or denormal * anything = +-0. // Shader Model 3: +0 or denormal * anything = +-0.
id_vector_temp_.clear();
id_vector_temp_.push_back(ps);
return ZeroIfAnyOperandIsZero( return ZeroIfAnyOperandIsZero(
result, GetAbsoluteOperand(a, instr.scalar_operands[0]), result, GetAbsoluteOperand(a, instr.scalar_operands[0]),
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->createUnaryBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_)); GLSLstd450FAbs, ps));
} }
case ucode::AluScalarOpcode::kMulsPrev2: { case ucode::AluScalarOpcode::kMulsPrev2: {
// Check if need to select the src0.a * ps case. // Check if need to select the src0.a * ps case.
@ -1054,13 +1012,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
spv::OpFUnordNotEqual, type_bool_, ps, const_float_max_neg); spv::OpFUnordNotEqual, type_bool_, ps, const_float_max_neg);
// isfinite(ps), or |ps| <= FLT_MAX, or -|ps| >= -FLT_MAX, since -FLT_MAX // isfinite(ps), or |ps| <= FLT_MAX, or -|ps| >= -FLT_MAX, since -FLT_MAX
// is already loaded to an SGPR, this is also false if it's NaN. // is already loaded to an SGPR, this is also false if it's NaN.
id_vector_temp_.clear(); spv::Id ps_abs = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(ps); type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, ps);
spv::Id ps_abs = builder_->createBuiltinCall( spv::Id ps_abs_neg = builder_->createNoContractionUnaryOp(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, id_vector_temp_); spv::OpFNegate, type_float_, ps_abs);
spv::Id ps_abs_neg =
builder_->createUnaryOp(spv::OpFNegate, type_float_, ps_abs);
builder_->addDecoration(ps_abs_neg, spv::DecorationNoContraction);
condition = builder_->createBinOp( condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_, condition, spv::OpLogicalAnd, type_bool_, condition,
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_, builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
@ -1070,17 +1025,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
instr.scalar_operands[0], 0b0010); instr.scalar_operands[0], 0b0010);
spv::Id b_abs_neg = b; spv::Id b_abs_neg = b;
if (!instr.scalar_operands[0].is_absolute_value) { if (!instr.scalar_operands[0].is_absolute_value) {
id_vector_temp_.clear(); b_abs_neg = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(b_abs_neg); type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, b_abs_neg);
b_abs_neg =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_);
} }
if (!instr.scalar_operands[0].is_absolute_value || if (!instr.scalar_operands[0].is_absolute_value ||
!instr.scalar_operands[0].is_negated) { !instr.scalar_operands[0].is_negated) {
b_abs_neg = b_abs_neg = builder_->createNoContractionUnaryOp(
builder_->createUnaryOp(spv::OpFNegate, type_float_, b_abs_neg); spv::OpFNegate, type_float_, b_abs_neg);
builder_->addDecoration(b_abs_neg, spv::DecorationNoContraction);
} }
condition = builder_->createBinOp( condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_, condition, spv::OpLogicalAnd, type_bool_, condition,
@ -1092,47 +1043,34 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
spv::OpLogicalAnd, type_bool_, condition, spv::OpLogicalAnd, type_bool_, condition,
builder_->createBinOp(spv::OpFOrdGreaterThan, type_bool_, b, builder_->createBinOp(spv::OpFOrdGreaterThan, type_bool_, b,
const_float_0_)); const_float_0_));
spv::Block& multiply_block = builder_->makeNewBlock(); spv::Block& pre_multiply_if_block = *builder_->getBuildPoint();
spv::Block& merge_block = builder_->makeNewBlock(); spv::Id product;
SpirvCreateSelectionMerge(merge_block.getId()); spv::Builder::If multiply_if(condition, spv::SelectionControlMaskNone,
*builder_);
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional);
branch_conditional_op->addIdOperand(condition);
branch_conditional_op->addIdOperand(multiply_block.getId());
branch_conditional_op->addIdOperand(merge_block.getId());
// More likely to multiply that to return -FLT_MAX.
branch_conditional_op->addImmediateOperand(2);
branch_conditional_op->addImmediateOperand(1);
builder_->getBuildPoint()->addInstruction(
std::move(branch_conditional_op));
}
spv::Block& head_block = *builder_->getBuildPoint();
multiply_block.addPredecessor(&head_block);
merge_block.addPredecessor(&head_block);
// Multiplication case. // Multiplication case.
builder_->setBuildPoint(&multiply_block);
spv::Id a = instr.scalar_operands[0].GetComponent(0) != spv::Id a = instr.scalar_operands[0].GetComponent(0) !=
instr.scalar_operands[0].GetComponent(1) instr.scalar_operands[0].GetComponent(1)
? GetOperandComponents(operand_storage[0], ? GetOperandComponents(operand_storage[0],
instr.scalar_operands[0], 0b0001) instr.scalar_operands[0], 0b0001)
: b; : b;
spv::Id product = builder_->createBinOp(spv::OpFMul, type_float_, a, ps); product =
builder_->addDecoration(product, spv::DecorationNoContraction); builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, ps);
// Shader Model 3: +0 or denormal * anything = +-0. // Shader Model 3: +0 or denormal * anything = +-0.
product = ZeroIfAnyOperandIsZero( product = ZeroIfAnyOperandIsZero(
product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs); product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs);
builder_->createBranch(&merge_block); }
// Merge case - choose between the product and -FLT_MAX. spv::Block& multiply_end_block = *builder_->getBuildPoint();
builder_->setBuildPoint(&merge_block); multiply_if.makeEndIf();
// Merge - choose between the product and -FLT_MAX.
{ {
std::unique_ptr<spv::Instruction> phi_op = std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(), std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi); type_float_, spv::OpPhi);
phi_op->addIdOperand(product); phi_op->addIdOperand(product);
phi_op->addIdOperand(multiply_block.getId()); phi_op->addIdOperand(multiply_end_block.getId());
phi_op->addIdOperand(const_float_max_neg); phi_op->addIdOperand(const_float_max_neg);
phi_op->addIdOperand(head_block.getId()); phi_op->addIdOperand(pre_multiply_if_block.getId());
spv::Id phi_result = phi_op->getResultId(); spv::Id phi_result = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op)); builder_->getBuildPoint()->addInstruction(std::move(phi_op));
return phi_result; return phi_result;
@ -1151,26 +1089,21 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
// maxasf: a0 = (int)clamp(floor(src0.a), -256.0, 255.0) // maxasf: a0 = (int)clamp(floor(src0.a), -256.0, 255.0)
spv::Id maxa_address; spv::Id maxa_address;
if (instr.scalar_opcode == ucode::AluScalarOpcode::kMaxAs) { if (instr.scalar_opcode == ucode::AluScalarOpcode::kMaxAs) {
maxa_address = builder_->createBinOp( maxa_address = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, a, builder_->makeFloatConstant(0.5f)); spv::OpFAdd, type_float_, a, builder_->makeFloatConstant(0.5f));
builder_->addDecoration(maxa_address, spv::DecorationNoContraction);
} else { } else {
maxa_address = a; maxa_address = a;
} }
id_vector_temp_.clear();
id_vector_temp_.push_back(maxa_address);
maxa_address =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Floor, id_vector_temp_);
id_vector_temp_.clear();
id_vector_temp_.push_back(maxa_address);
id_vector_temp_.push_back(builder_->makeFloatConstant(-256.0f));
id_vector_temp_.push_back(builder_->makeFloatConstant(255.0f));
builder_->createStore( builder_->createStore(
builder_->createUnaryOp( builder_->createUnaryOp(
spv::OpConvertFToS, type_int_, spv::OpConvertFToS, type_int_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->createTriBuiltinCall(
GLSLstd450NClamp, id_vector_temp_)), type_float_, ext_inst_glsl_std_450_, GLSLstd450NClamp,
builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor,
maxa_address),
builder_->makeFloatConstant(-256.0f),
builder_->makeFloatConstant(255.0f))),
var_main_address_register_); var_main_address_register_);
} }
if (a == b) { if (a == b) {
@ -1208,18 +1141,16 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kSqrt: case ucode::AluScalarOpcode::kSqrt:
case ucode::AluScalarOpcode::kSin: case ucode::AluScalarOpcode::kSin:
case ucode::AluScalarOpcode::kCos: case ucode::AluScalarOpcode::kCos:
id_vector_temp_.clear(); return builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(GetOperandComponents(
operand_storage[0], instr.scalar_operands[0], 0b0001));
return builder_->createBuiltinCall(
type_float_, ext_inst_glsl_std_450_, type_float_, ext_inst_glsl_std_450_,
GLSLstd450(kOps[size_t(instr.scalar_opcode)]), id_vector_temp_); GLSLstd450(kOps[size_t(instr.scalar_opcode)]),
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
case ucode::AluScalarOpcode::kLogc: { case ucode::AluScalarOpcode::kLogc: {
id_vector_temp_.clear(); spv::Id result = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(GetOperandComponents( type_float_, ext_inst_glsl_std_450_, GLSLstd450Log2,
operand_storage[0], instr.scalar_operands[0], 0b0001)); GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
spv::Id result = builder_->createBuiltinCall( 0b0001));
type_float_, ext_inst_glsl_std_450_, GLSLstd450Log2, id_vector_temp_);
return builder_->createTriOp( return builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result, builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1227,11 +1158,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(-FLT_MAX), result); builder_->makeFloatConstant(-FLT_MAX), result);
} }
case ucode::AluScalarOpcode::kRcpc: { case ucode::AluScalarOpcode::kRcpc: {
spv::Id result = builder_->createBinOp( spv::Id result = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_, spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001)); 0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
result = builder_->createTriOp( result = builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result, builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1244,11 +1174,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(FLT_MAX), result); builder_->makeFloatConstant(FLT_MAX), result);
} }
case ucode::AluScalarOpcode::kRcpf: { case ucode::AluScalarOpcode::kRcpf: {
spv::Id result = builder_->createBinOp( spv::Id result = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_, spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001)); 0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
result = builder_->createTriOp( result = builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result, builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1265,20 +1194,16 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
return builder_->createUnaryOp(spv::OpBitcast, type_float_, result); return builder_->createUnaryOp(spv::OpBitcast, type_float_, result);
} }
case ucode::AluScalarOpcode::kRcp: { case ucode::AluScalarOpcode::kRcp: {
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_, spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001)); 0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluScalarOpcode::kRsqc: { case ucode::AluScalarOpcode::kRsqc: {
id_vector_temp_.clear(); spv::Id result = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(GetOperandComponents( type_float_, ext_inst_glsl_std_450_, GLSLstd450InverseSqrt,
operand_storage[0], instr.scalar_operands[0], 0b0001)); GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
spv::Id result = 0b0001));
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450InverseSqrt, id_vector_temp_);
result = builder_->createTriOp( result = builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result, builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1291,12 +1216,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(FLT_MAX), result); builder_->makeFloatConstant(FLT_MAX), result);
} }
case ucode::AluScalarOpcode::kRsqf: { case ucode::AluScalarOpcode::kRsqf: {
id_vector_temp_.clear(); spv::Id result = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(GetOperandComponents( type_float_, ext_inst_glsl_std_450_, GLSLstd450InverseSqrt,
operand_storage[0], instr.scalar_operands[0], 0b0001)); GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
spv::Id result = 0b0001));
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450InverseSqrt, id_vector_temp_);
result = builder_->createTriOp( result = builder_->createTriOp(
spv::OpSelect, type_float_, spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result, builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1343,12 +1266,11 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
const_float_1_, a)); const_float_1_, a));
} }
case ucode::AluScalarOpcode::kSetpPop: { case ucode::AluScalarOpcode::kSetpPop: {
spv::Id a_minus_1 = builder_->createBinOp( spv::Id a_minus_1 = builder_->createNoContractionBinOp(
spv::OpFSub, type_float_, spv::OpFSub, type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001), 0b0001),
const_float_1_); const_float_1_);
builder_->addDecoration(a_minus_1, spv::DecorationNoContraction);
spv::Id predicate = builder_->createBinOp( spv::Id predicate = builder_->createBinOp(
spv::OpFOrdLessThanEqual, type_bool_, a_minus_1, const_float_0_); spv::OpFOrdLessThanEqual, type_bool_, a_minus_1, const_float_0_);
builder_->createStore(predicate, var_main_predicate_); builder_->createStore(predicate, var_main_predicate_);
@ -1376,30 +1298,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kKillsGe: case ucode::AluScalarOpcode::kKillsGe:
case ucode::AluScalarOpcode::kKillsNe: case ucode::AluScalarOpcode::kKillsNe:
case ucode::AluScalarOpcode::kKillsOne: { case ucode::AluScalarOpcode::kKillsOne: {
// Selection merge must be the penultimate instruction in the block, check KillPixel(builder_->createBinOp(
// the condition before it.
spv::Id condition = builder_->createBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_bool_, spv::Op(kOps[size_t(instr.scalar_opcode)]), type_bool_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001), 0b0001),
instr.scalar_opcode == ucode::AluScalarOpcode::kKillsOne instr.scalar_opcode == ucode::AluScalarOpcode::kKillsOne
? const_float_1_ ? const_float_1_
: const_float_0_); : const_float_0_));
spv::Block& kill_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(merge_block.getId());
builder_->createConditionalBranch(condition, &kill_block, &merge_block);
builder_->setBuildPoint(&kill_block);
// Kill without influencing the control flow in the translated shader.
if (var_main_kill_pixel_ != spv::NoResult) {
builder_->createStore(builder_->makeBoolConstant(true),
var_main_kill_pixel_);
}
if (features_.demote_to_helper_invocation) {
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
}
builder_->createBranch(&merge_block);
builder_->setBuildPoint(&merge_block);
return const_float_0_; return const_float_0_;
} }
@ -1409,9 +1314,8 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
operand_storage[0], instr.scalar_operands[0], 0b0001); operand_storage[0], instr.scalar_operands[0], 0b0001);
spv::Id operand_1 = GetOperandComponents( spv::Id operand_1 = GetOperandComponents(
operand_storage[1], instr.scalar_operands[1], 0b0001); operand_storage[1], instr.scalar_operands[1], 0b0001);
spv::Id result = spv::Id result = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpFMul, type_float_, operand_0, operand_1); spv::OpFMul, type_float_, operand_0, operand_1);
builder_->addDecoration(result, spv::DecorationNoContraction);
if (!(instr.scalar_operands[0].GetIdenticalComponents( if (!(instr.scalar_operands[0].GetIdenticalComponents(
instr.scalar_operands[1]) & instr.scalar_operands[1]) &
0b0001)) { 0b0001)) {
@ -1426,14 +1330,12 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kAddsc1: case ucode::AluScalarOpcode::kAddsc1:
case ucode::AluScalarOpcode::kSubsc0: case ucode::AluScalarOpcode::kSubsc0:
case ucode::AluScalarOpcode::kSubsc1: { case ucode::AluScalarOpcode::kSubsc1: {
spv::Id result = builder_->createBinOp( return builder_->createNoContractionBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_, spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0], GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001), 0b0001),
GetOperandComponents(operand_storage[1], instr.scalar_operands[1], GetOperandComponents(operand_storage[1], instr.scalar_operands[1],
0b0001)); 0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
} }
case ucode::AluScalarOpcode::kRetainPrev: case ucode::AluScalarOpcode::kRetainPrev:

View File

@ -80,16 +80,13 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
spv::Id index = GetOperandComponents( spv::Id index = GetOperandComponents(
LoadOperandStorage(instr.operands[0]), instr.operands[0], 0b0001); LoadOperandStorage(instr.operands[0]), instr.operands[0], 0b0001);
if (instr.attributes.is_index_rounded) { if (instr.attributes.is_index_rounded) {
index = builder_->createBinOp(spv::OpFAdd, type_float_, index, index = builder_->createNoContractionBinOp(
builder_->makeFloatConstant(0.5f)); spv::OpFAdd, type_float_, index, builder_->makeFloatConstant(0.5f));
builder_->addDecoration(index, spv::DecorationNoContraction);
} }
id_vector_temp_.clear();
id_vector_temp_.push_back(index);
index = builder_->createUnaryOp( index = builder_->createUnaryOp(
spv::OpConvertFToS, type_int_, spv::OpConvertFToS, type_int_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->createUnaryBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Floor, id_vector_temp_)); GLSLstd450Floor, index));
if (instr.attributes.stride > 1) { if (instr.attributes.stride > 1) {
index = builder_->createBinOp( index = builder_->createBinOp(
spv::OpIMul, type_int_, index, spv::OpIMul, type_int_, index,
@ -247,11 +244,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
} else { } else {
word = words; word = words;
} }
id_vector_temp_.clear(); word = builder_->createUnaryBuiltinCall(type_float2_,
id_vector_temp_.push_back(word); ext_inst_glsl_std_450_,
word = builder_->createBuiltinCall(type_float2_, ext_inst_glsl_std_450_, GLSLstd450UnpackHalf2x16, word);
GLSLstd450UnpackHalf2x16,
id_vector_temp_);
if (word_needed_components != 0b11) { if (word_needed_components != 0b11) {
// If only one of two components is needed, extract it. // If only one of two components is needed, extract it.
word = builder_->createCompositeExtract( word = builder_->createCompositeExtract(
@ -297,18 +292,16 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
switch (instr.attributes.signed_rf_mode) { switch (instr.attributes.signed_rf_mode) {
case xenos::SignedRepeatingFractionMode::kZeroClampMinusOne: case xenos::SignedRepeatingFractionMode::kZeroClampMinusOne:
result = builder_->createBinOp( result = builder_->createNoContractionBinOp(
spv::OpVectorTimesScalar, result_type, result, spv::OpVectorTimesScalar, result_type, result,
builder_->makeFloatConstant(1.0f / 2147483647.0f)); builder_->makeFloatConstant(1.0f / 2147483647.0f));
builder_->addDecoration(result, spv::DecorationNoContraction);
// No need to clamp to -1 if signed - 1/(2^31-1) is rounded to // No need to clamp to -1 if signed - 1/(2^31-1) is rounded to
// 1/(2^31) as float32. // 1/(2^31) as float32.
break; break;
case xenos::SignedRepeatingFractionMode::kNoZero: { case xenos::SignedRepeatingFractionMode::kNoZero: {
result = builder_->createBinOp( result = builder_->createNoContractionBinOp(
spv::OpVectorTimesScalar, result_type, result, spv::OpVectorTimesScalar, result_type, result,
builder_->makeFloatConstant(1.0f / 2147483647.5f)); builder_->makeFloatConstant(1.0f / 2147483647.5f));
builder_->addDecoration(result, spv::DecorationNoContraction);
spv::Id const_no_zero = spv::Id const_no_zero =
builder_->makeFloatConstant(0.5f / 2147483647.5f); builder_->makeFloatConstant(0.5f / 2147483647.5f);
if (used_format_component_count > 1) { if (used_format_component_count > 1) {
@ -319,18 +312,16 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
const_no_zero = builder_->makeCompositeConstant( const_no_zero = builder_->makeCompositeConstant(
result_type, id_vector_temp_); result_type, id_vector_temp_);
} }
result = builder_->createBinOp(spv::OpFAdd, result_type, result, result = builder_->createNoContractionBinOp(
const_no_zero); spv::OpFAdd, result_type, result, const_no_zero);
builder_->addDecoration(result, spv::DecorationNoContraction);
} break; } break;
default: default:
assert_unhandled_case(instr.attributes.signed_rf_mode); assert_unhandled_case(instr.attributes.signed_rf_mode);
} }
} else { } else {
result = builder_->createBinOp( result = builder_->createNoContractionBinOp(
spv::OpVectorTimesScalar, result_type, result, spv::OpVectorTimesScalar, result_type, result,
builder_->makeFloatConstant(1.0f / 4294967295.0f)); builder_->makeFloatConstant(1.0f / 4294967295.0f));
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
} }
break; break;
@ -449,9 +440,8 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
} else { } else {
packed_scale_mul_op = spv::OpFMul; packed_scale_mul_op = spv::OpFMul;
} }
result = builder_->createBinOp(packed_scale_mul_op, result_type, result, result = builder_->createNoContractionBinOp(
const_packed_scale); packed_scale_mul_op, result_type, result, const_packed_scale);
builder_->addDecoration(result, spv::DecorationNoContraction);
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
switch (instr.attributes.signed_rf_mode) { switch (instr.attributes.signed_rf_mode) {
case xenos::SignedRepeatingFractionMode::kZeroClampMinusOne: { case xenos::SignedRepeatingFractionMode::kZeroClampMinusOne: {
@ -460,18 +450,14 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
spv::Id const_minus_1 = builder_->makeFloatConstant(-1.0f); spv::Id const_minus_1 = builder_->makeFloatConstant(-1.0f);
if (used_format_component_count > 1) { if (used_format_component_count > 1) {
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.insert(id_vector_temp_.cend(), id_vector_temp_.resize(used_format_component_count,
used_format_component_count,
const_minus_1); const_minus_1);
const_minus_1 = const_minus_1 =
builder_->makeCompositeConstant(result_type, id_vector_temp_); builder_->makeCompositeConstant(result_type, id_vector_temp_);
} }
id_vector_temp_.clear(); result = builder_->createBinBuiltinCall(
id_vector_temp_.push_back(result); result_type, ext_inst_glsl_std_450_, GLSLstd450FMax, result,
id_vector_temp_.push_back(const_minus_1); const_minus_1);
result =
builder_->createBuiltinCall(result_type, ext_inst_glsl_std_450_,
GLSLstd450FMax, id_vector_temp_);
} break; } break;
case xenos::SignedRepeatingFractionMode::kNoZero: case xenos::SignedRepeatingFractionMode::kNoZero:
id_vector_temp_.clear(); id_vector_temp_.clear();
@ -479,13 +465,12 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
id_vector_temp_.push_back( id_vector_temp_.push_back(
builder_->makeFloatConstant(0.5f * packed_scales[i])); builder_->makeFloatConstant(0.5f * packed_scales[i]));
} }
result = result = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpFAdd, result_type, result, spv::OpFAdd, result_type, result,
used_format_component_count > 1 used_format_component_count > 1
? builder_->makeCompositeConstant( ? builder_->makeCompositeConstant(result_type,
result_type, id_vector_temp_) id_vector_temp_)
: id_vector_temp_[0]); : id_vector_temp_[0]);
builder_->addDecoration(result, spv::DecorationNoContraction);
break; break;
default: default:
assert_unhandled_case(instr.attributes.signed_rf_mode); assert_unhandled_case(instr.attributes.signed_rf_mode);
@ -497,11 +482,10 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
if (result != spv::NoResult) { if (result != spv::NoResult) {
// Apply the exponent bias. // Apply the exponent bias.
if (instr.attributes.exp_adjust) { if (instr.attributes.exp_adjust) {
result = builder_->createBinOp(spv::OpVectorTimesScalar, result = builder_->createNoContractionBinOp(
builder_->getTypeId(result), result, spv::OpVectorTimesScalar, builder_->getTypeId(result), result,
builder_->makeFloatConstant(std::ldexp( builder_->makeFloatConstant(
1.0f, instr.attributes.exp_adjust))); std::ldexp(1.0f, instr.attributes.exp_adjust)));
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
// If any components not present in the format were requested, pad the // If any components not present in the format were requested, pad the
@ -1102,25 +1086,19 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
if (!instr.attributes.unnormalized_coordinates) { if (!instr.attributes.unnormalized_coordinates) {
spv::Id size_component = size[coordinate_component_index]; spv::Id size_component = size[coordinate_component_index];
assert_true(size_component != spv::NoResult); assert_true(size_component != spv::NoResult);
result_component = builder_->createBinOp( result_component = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, result_component, size_component); spv::OpFMul, type_float_, result_component, size_component);
builder_->addDecoration(result_component,
spv::DecorationNoContraction);
} }
float component_offset = offset_values[coordinate_component_index]; float component_offset = offset_values[coordinate_component_index];
if (component_offset) { if (component_offset) {
result_component = builder_->createBinOp( result_component = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, result_component, spv::OpFAdd, type_float_, result_component,
builder_->makeFloatConstant(component_offset)); builder_->makeFloatConstant(component_offset));
builder_->addDecoration(result_component,
spv::DecorationNoContraction);
} }
// 0.5 has already been subtracted via offsets previously. // 0.5 has already been subtracted via offsets previously.
id_vector_temp_.clear(); result_component = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(result_component); type_float_, ext_inst_glsl_std_450_, GLSLstd450Fract,
result_component = result_component);
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Fract, id_vector_temp_);
result[coordinate_component_index] = result_component; result[coordinate_component_index] = result_component;
} }
} else { } else {
@ -1137,27 +1115,21 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Id size_component = size[i]; spv::Id size_component = size[i];
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
if (component_offset != spv::NoResult) { if (component_offset != spv::NoResult) {
coordinate_ref = builder_->createBinOp( coordinate_ref = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, coordinate_ref, component_offset); spv::OpFAdd, type_float_, coordinate_ref, component_offset);
builder_->addDecoration(coordinate_ref,
spv::DecorationNoContraction);
} }
assert_true(size_component != spv::NoResult); assert_true(size_component != spv::NoResult);
coordinate_ref = builder_->createBinOp( coordinate_ref = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, coordinate_ref, size_component); spv::OpFDiv, type_float_, coordinate_ref, size_component);
builder_->addDecoration(coordinate_ref, spv::DecorationNoContraction);
} else { } else {
if (component_offset != spv::NoResult) { if (component_offset != spv::NoResult) {
assert_true(size_component != spv::NoResult); assert_true(size_component != spv::NoResult);
spv::Id component_offset_normalized = builder_->createBinOp( spv::Id component_offset_normalized =
builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, component_offset, size_component); spv::OpFDiv, type_float_, component_offset, size_component);
builder_->addDecoration(component_offset_normalized, coordinate_ref = builder_->createNoContractionBinOp(
spv::DecorationNoContraction); spv::OpFAdd, type_float_, coordinate_ref,
coordinate_ref =
builder_->createBinOp(spv::OpFAdd, type_float_, coordinate_ref,
component_offset_normalized); component_offset_normalized);
builder_->addDecoration(coordinate_ref,
spv::DecorationNoContraction);
} }
} }
} }
@ -1170,24 +1142,21 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
// Apply the offset, and normalize the Z coordinate for a 3D texture. // Apply the offset, and normalize the Z coordinate for a 3D texture.
if (z_offset != spv::NoResult) { if (z_offset != spv::NoResult) {
z_coordinate_ref = builder_->createBinOp( z_coordinate_ref = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, z_coordinate_ref, z_offset); spv::OpFAdd, type_float_, z_coordinate_ref, z_offset);
builder_->addDecoration(z_coordinate_ref,
spv::DecorationNoContraction);
} }
spv::Block& block_dimension_head = *builder_->getBuildPoint(); spv::Block& block_dimension_head = *builder_->getBuildPoint();
spv::Block& block_dimension_merge = builder_->makeNewBlock(); spv::Block& block_dimension_merge = builder_->makeNewBlock();
spv::Block& block_dimension_3d = builder_->makeNewBlock(); spv::Block& block_dimension_3d = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_dimension_merge.getId(), builder_->createSelectionMerge(&block_dimension_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
assert_true(data_is_3d != spv::NoResult); assert_true(data_is_3d != spv::NoResult);
builder_->createConditionalBranch(data_is_3d, &block_dimension_3d, builder_->createConditionalBranch(data_is_3d, &block_dimension_3d,
&block_dimension_merge); &block_dimension_merge);
builder_->setBuildPoint(&block_dimension_3d); builder_->setBuildPoint(&block_dimension_3d);
assert_true(z_size != spv::NoResult); assert_true(z_size != spv::NoResult);
spv::Id z_3d = builder_->createBinOp(spv::OpFDiv, type_float_, spv::Id z_3d = builder_->createNoContractionBinOp(
z_coordinate_ref, z_size); spv::OpFDiv, type_float_, z_coordinate_ref, z_size);
builder_->addDecoration(z_3d, spv::DecorationNoContraction);
builder_->createBranch(&block_dimension_merge); builder_->createBranch(&block_dimension_merge);
builder_->setBuildPoint(&block_dimension_merge); builder_->setBuildPoint(&block_dimension_merge);
{ {
@ -1209,7 +1178,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Block* block_dimension_3d = spv::Block* block_dimension_3d =
z_offset != spv::NoResult ? &builder_->makeNewBlock() : nullptr; z_offset != spv::NoResult ? &builder_->makeNewBlock() : nullptr;
spv::Block& block_dimension_stacked = builder_->makeNewBlock(); spv::Block& block_dimension_stacked = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_dimension_merge.getId(), builder_->createSelectionMerge(&block_dimension_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
assert_true(data_is_3d != spv::NoResult); assert_true(data_is_3d != spv::NoResult);
builder_->createConditionalBranch( builder_->createConditionalBranch(
@ -1222,13 +1191,10 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->setBuildPoint(block_dimension_3d); builder_->setBuildPoint(block_dimension_3d);
if (z_offset != spv::NoResult) { if (z_offset != spv::NoResult) {
assert_true(z_size != spv::NoResult); assert_true(z_size != spv::NoResult);
spv::Id z_offset_normalized = builder_->createBinOp( spv::Id z_offset_normalized = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, z_offset, z_size); spv::OpFDiv, type_float_, z_offset, z_size);
builder_->addDecoration(z_offset_normalized, z_3d = builder_->createNoContractionBinOp(
spv::DecorationNoContraction); spv::OpFAdd, type_float_, z_3d, z_offset_normalized);
z_3d = builder_->createBinOp(spv::OpFAdd, type_float_, z_3d,
z_offset_normalized);
builder_->addDecoration(z_3d, spv::DecorationNoContraction);
} }
builder_->createBranch(&block_dimension_merge); builder_->createBranch(&block_dimension_merge);
} }
@ -1236,13 +1202,11 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->setBuildPoint(&block_dimension_stacked); builder_->setBuildPoint(&block_dimension_stacked);
spv::Id z_stacked = z_coordinate_ref; spv::Id z_stacked = z_coordinate_ref;
assert_true(z_size != spv::NoResult); assert_true(z_size != spv::NoResult);
z_stacked = builder_->createBinOp(spv::OpFMul, type_float_, z_stacked, z_stacked = builder_->createNoContractionBinOp(
z_size); spv::OpFMul, type_float_, z_stacked, z_size);
builder_->addDecoration(z_stacked, spv::DecorationNoContraction);
if (z_offset != spv::NoResult) { if (z_offset != spv::NoResult) {
z_stacked = builder_->createBinOp(spv::OpFAdd, type_float_, z_stacked = builder_->createNoContractionBinOp(
z_stacked, z_offset); spv::OpFAdd, type_float_, z_stacked, z_offset);
builder_->addDecoration(z_stacked, spv::DecorationNoContraction);
} }
builder_->createBranch(&block_dimension_merge); builder_->createBranch(&block_dimension_merge);
// Select one of the two. // Select one of the two.
@ -1267,32 +1231,26 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Id const_float_2 = builder_->makeFloatConstant(2.0f); spv::Id const_float_2 = builder_->makeFloatConstant(2.0f);
spv::Id const_float_minus_3 = builder_->makeFloatConstant(-3.0f); spv::Id const_float_minus_3 = builder_->makeFloatConstant(-3.0f);
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
spv::Id& coordinate_ref = coordinates[i]; coordinates[i] = builder_->createNoContractionBinOp(
coordinate_ref = builder_->createBinOp(spv::OpFMul, type_float_, spv::OpFAdd, type_float_,
coordinate_ref, const_float_2); builder_->createNoContractionBinOp(spv::OpFMul, type_float_,
builder_->addDecoration(coordinate_ref, spv::DecorationNoContraction); coordinates[i], const_float_2),
coordinate_ref = builder_->createBinOp( const_float_minus_3);
spv::OpFAdd, type_float_, coordinate_ref, const_float_minus_3);
builder_->addDecoration(coordinate_ref, spv::DecorationNoContraction);
} }
// Get the face index (floored, within 0...5 - OpConvertFToU is // Get the face index (floored, within 0...5 - OpConvertFToU is
// undefined for out-of-range values, so clamping from both sides // undefined for out-of-range values, so clamping from both sides
// manually). // manually).
spv::Id face = coordinates[2]; spv::Id face = coordinates[2];
if (offset_values[2]) { if (offset_values[2]) {
face = builder_->createBinOp( face = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, face, spv::OpFAdd, type_float_, face,
builder_->makeFloatConstant(offset_values[2])); builder_->makeFloatConstant(offset_values[2]));
builder_->addDecoration(face, spv::DecorationNoContraction);
} }
id_vector_temp_.clear();
id_vector_temp_.push_back(face);
id_vector_temp_.push_back(const_float_0_);
id_vector_temp_.push_back(builder_->makeFloatConstant(5.0f));
face = builder_->createUnaryOp( face = builder_->createUnaryOp(
spv::OpConvertFToU, type_uint_, spv::OpConvertFToU, type_uint_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->createTriBuiltinCall(
GLSLstd450NClamp, id_vector_temp_)); type_float_, ext_inst_glsl_std_450_, GLSLstd450NClamp, face,
const_float_0_, builder_->makeFloatConstant(5.0f)));
// Split the face index into the axis and the sign. // Split the face index into the axis and the sign.
spv::Id const_uint_1 = builder_->makeUintConstant(1); spv::Id const_uint_1 = builder_->makeUintConstant(1);
spv::Id face_axis = builder_->createBinOp( spv::Id face_axis = builder_->createBinOp(
@ -1307,18 +1265,17 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->makeFloatConstant(-1.0f), builder_->makeFloatConstant(-1.0f),
builder_->makeFloatConstant(1.0f)); builder_->makeFloatConstant(1.0f));
// Remap the axes in a way opposite to the ALU cube instruction. // Remap the axes in a way opposite to the ALU cube instruction.
spv::Id sc_negated = builder_->createUnaryOp( spv::Id sc_negated = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, coordinates[0]); spv::OpFNegate, type_float_, coordinates[0]);
builder_->addDecoration(sc_negated, spv::DecorationNoContraction); spv::Id tc_negated = builder_->createNoContractionUnaryOp(
spv::Id tc_negated = builder_->createUnaryOp(
spv::OpFNegate, type_float_, coordinates[1]); spv::OpFNegate, type_float_, coordinates[1]);
builder_->addDecoration(tc_negated, spv::DecorationNoContraction);
spv::Block& block_ma_head = *builder_->getBuildPoint(); spv::Block& block_ma_head = *builder_->getBuildPoint();
spv::Block& block_ma_x = builder_->makeNewBlock(); spv::Block& block_ma_x = builder_->makeNewBlock();
spv::Block& block_ma_y = builder_->makeNewBlock(); spv::Block& block_ma_y = builder_->makeNewBlock();
spv::Block& block_ma_z = builder_->makeNewBlock(); spv::Block& block_ma_z = builder_->makeNewBlock();
spv::Block& block_ma_merge = builder_->makeNewBlock(); spv::Block& block_ma_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_ma_merge.getId()); builder_->createSelectionMerge(&block_ma_merge,
spv::SelectionControlMaskNone);
{ {
std::unique_ptr<spv::Instruction> ma_switch_op = std::unique_ptr<spv::Instruction> ma_switch_op =
std::make_unique<spv::Instruction>(spv::OpSwitch); std::make_unique<spv::Instruction>(spv::OpSwitch);
@ -1441,7 +1398,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Block& block_dimension_3d_start = builder_->makeNewBlock(); spv::Block& block_dimension_3d_start = builder_->makeNewBlock();
spv::Block& block_dimension_stacked_start = builder_->makeNewBlock(); spv::Block& block_dimension_stacked_start = builder_->makeNewBlock();
spv::Block& block_dimension_merge = builder_->makeNewBlock(); spv::Block& block_dimension_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_dimension_merge.getId(), builder_->createSelectionMerge(&block_dimension_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
assert_true(data_is_3d != spv::NoResult); assert_true(data_is_3d != spv::NoResult);
builder_->createConditionalBranch(data_is_3d, builder_->createConditionalBranch(data_is_3d,
@ -1577,7 +1534,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// specification order: specified LOD + sampler LOD bias + instruction // specification order: specified LOD + sampler LOD bias + instruction
// LOD bias). // LOD bias).
// Fetch constant LOD (bits 12:21 of the word 4). // Fetch constant LOD (bits 12:21 of the word 4).
spv::Id lod = builder_->createBinOp( spv::Id lod = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, spv::OpFMul, type_float_,
builder_->createUnaryOp( builder_->createUnaryOp(
spv::OpConvertSToF, type_float_, spv::OpConvertSToF, type_float_,
@ -1586,21 +1543,18 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->makeUintConstant(12), builder_->makeUintConstant(12),
builder_->makeUintConstant(10))), builder_->makeUintConstant(10))),
builder_->makeFloatConstant(1.0f / 32.0f)); builder_->makeFloatConstant(1.0f / 32.0f));
builder_->addDecoration(lod, spv::DecorationNoContraction);
// Register LOD. // Register LOD.
if (instr.attributes.use_register_lod) { if (instr.attributes.use_register_lod) {
lod = builder_->createBinOp( lod = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, spv::OpFAdd, type_float_,
builder_->createLoad(var_main_tfetch_lod_, spv::NoPrecision), builder_->createLoad(var_main_tfetch_lod_, spv::NoPrecision),
lod); lod);
builder_->addDecoration(lod, spv::DecorationNoContraction);
} }
// Instruction LOD bias. // Instruction LOD bias.
if (instr.attributes.lod_bias) { if (instr.attributes.lod_bias) {
lod = builder_->createBinOp( lod = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, lod, spv::OpFAdd, type_float_, lod,
builder_->makeFloatConstant(instr.attributes.lod_bias)); builder_->makeFloatConstant(instr.attributes.lod_bias));
builder_->addDecoration(lod, spv::DecorationNoContraction);
} }
// Calculate the gradients for sampling the texture if needed. // Calculate the gradients for sampling the texture if needed.
@ -1613,11 +1567,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// in getCompTexLOD, so not doing it here too for now. Apply the // in getCompTexLOD, so not doing it here too for now. Apply the
// gradient exponent biases from the word 4 of the fetch constant in // gradient exponent biases from the word 4 of the fetch constant in
// the future when it's handled in getCompTexLOD somehow. // the future when it's handled in getCompTexLOD somehow.
id_vector_temp_.clear(); spv::Id lod_gradient_scale = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(lod); type_float_, ext_inst_glsl_std_450_, GLSLstd450Exp2, lod);
spv::Id lod_gradient_scale =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Exp2, id_vector_temp_);
switch (instr.dimension) { switch (instr.dimension) {
case xenos::FetchOpDimension::k1D: { case xenos::FetchOpDimension::k1D: {
spv::Id gradient_h_1d, gradient_v_1d; spv::Id gradient_h_1d, gradient_v_1d;
@ -1638,14 +1589,10 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
// Normalize the gradients. // Normalize the gradients.
assert_true(size[0] != spv::NoResult); assert_true(size[0] != spv::NoResult);
gradient_h_1d = builder_->createBinOp( gradient_h_1d = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, gradient_h_1d, size[0]); spv::OpFDiv, type_float_, gradient_h_1d, size[0]);
builder_->addDecoration(gradient_h_1d, gradient_v_1d = builder_->createNoContractionBinOp(
spv::DecorationNoContraction);
gradient_v_1d = builder_->createBinOp(
spv::OpFDiv, type_float_, gradient_v_1d, size[0]); spv::OpFDiv, type_float_, gradient_v_1d, size[0]);
builder_->addDecoration(gradient_v_1d,
spv::DecorationNoContraction);
} }
} else { } else {
builder_->addCapability(spv::CapabilityDerivativeControl); builder_->addCapability(spv::CapabilityDerivativeControl);
@ -1654,14 +1601,10 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
gradient_v_1d = builder_->createUnaryOp( gradient_v_1d = builder_->createUnaryOp(
spv::OpDPdyCoarse, type_float_, coordinates[0]); spv::OpDPdyCoarse, type_float_, coordinates[0]);
} }
gradient_h_1d = builder_->createBinOp( gradient_h_1d = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, gradient_h_1d, lod_gradient_scale); spv::OpFMul, type_float_, gradient_h_1d, lod_gradient_scale);
builder_->addDecoration(gradient_h_1d, gradient_v_1d = builder_->createNoContractionBinOp(
spv::DecorationNoContraction);
gradient_v_1d = builder_->createBinOp(
spv::OpFMul, type_float_, gradient_v_1d, lod_gradient_scale); spv::OpFMul, type_float_, gradient_v_1d, lod_gradient_scale);
builder_->addDecoration(gradient_v_1d,
spv::DecorationNoContraction);
// 1D textures are sampled as 2D arrays - need 2-component // 1D textures are sampled as 2D arrays - need 2-component
// gradients. // gradients.
id_vector_temp_.clear(); id_vector_temp_.clear();
@ -1689,15 +1632,11 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
// Normalize the gradients. // Normalize the gradients.
assert_true(size[0] != spv::NoResult); assert_true(size[0] != spv::NoResult);
register_gradient_x = builder_->createBinOp( register_gradient_x = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, register_gradient_x, size[0]); spv::OpFDiv, type_float_, register_gradient_x, size[0]);
builder_->addDecoration(register_gradient_x,
spv::DecorationNoContraction);
assert_true(size[1] != spv::NoResult); assert_true(size[1] != spv::NoResult);
register_gradient_y = builder_->createBinOp( register_gradient_y = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, register_gradient_y, size[1]); spv::OpFDiv, type_float_, register_gradient_y, size[1]);
builder_->addDecoration(register_gradient_y,
spv::DecorationNoContraction);
} }
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back(register_gradient_x); id_vector_temp_.push_back(register_gradient_x);
@ -1722,16 +1661,12 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->createUnaryOp(spv::OpDPdyCoarse, type_float2_, builder_->createUnaryOp(spv::OpDPdyCoarse, type_float2_,
gradient_coordinate_vector); gradient_coordinate_vector);
} }
gradients_h = gradients_h = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpVectorTimesScalar, type_float2_, spv::OpVectorTimesScalar, type_float2_, gradients_h,
gradients_h, lod_gradient_scale); lod_gradient_scale);
builder_->addDecoration(gradients_h, gradients_v = builder_->createNoContractionBinOp(
spv::DecorationNoContraction); spv::OpVectorTimesScalar, type_float2_, gradients_v,
gradients_v = lod_gradient_scale);
builder_->createBinOp(spv::OpVectorTimesScalar, type_float2_,
gradients_v, lod_gradient_scale);
builder_->addDecoration(gradients_v,
spv::DecorationNoContraction);
} break; } break;
case xenos::FetchOpDimension::k3DOrStacked: { case xenos::FetchOpDimension::k3DOrStacked: {
if (instr.attributes.use_register_gradients) { if (instr.attributes.use_register_gradients) {
@ -1746,13 +1681,12 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
id_vector_temp_.clear(); id_vector_temp_.clear();
for (uint32_t j = 0; j < 3; ++j) { for (uint32_t j = 0; j < 3; ++j) {
assert_true(size[j] != spv::NoResult); assert_true(size[j] != spv::NoResult);
id_vector_temp_.push_back(builder_->createBinOp( id_vector_temp_.push_back(
builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, spv::OpFDiv, type_float_,
builder_->createCompositeExtract(gradient_ref, builder_->createCompositeExtract(gradient_ref,
type_float_, j), type_float_, j),
size[j])); size[j]));
builder_->addDecoration(id_vector_temp_.back(),
spv::DecorationNoContraction);
} }
gradient_ref = builder_->createCompositeConstruct( gradient_ref = builder_->createCompositeConstruct(
type_float3_, id_vector_temp_); type_float3_, id_vector_temp_);
@ -1774,16 +1708,12 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->createUnaryOp(spv::OpDPdyCoarse, type_float3_, builder_->createUnaryOp(spv::OpDPdyCoarse, type_float3_,
gradient_coordinate_vector); gradient_coordinate_vector);
} }
gradients_h = gradients_h = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpVectorTimesScalar, type_float3_, spv::OpVectorTimesScalar, type_float3_, gradients_h,
gradients_h, lod_gradient_scale); lod_gradient_scale);
builder_->addDecoration(gradients_h, gradients_v = builder_->createNoContractionBinOp(
spv::DecorationNoContraction); spv::OpVectorTimesScalar, type_float3_, gradients_v,
gradients_v = lod_gradient_scale);
builder_->createBinOp(spv::OpVectorTimesScalar, type_float3_,
gradients_v, lod_gradient_scale);
builder_->addDecoration(gradients_v,
spv::DecorationNoContraction);
} break; } break;
case xenos::FetchOpDimension::kCube: { case xenos::FetchOpDimension::kCube: {
if (instr.attributes.use_register_gradients) { if (instr.attributes.use_register_gradients) {
@ -1811,16 +1741,12 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
builder_->createUnaryOp(spv::OpDPdyCoarse, type_float3_, builder_->createUnaryOp(spv::OpDPdyCoarse, type_float3_,
gradient_coordinate_vector); gradient_coordinate_vector);
} }
gradients_h = gradients_h = builder_->createNoContractionBinOp(
builder_->createBinOp(spv::OpVectorTimesScalar, type_float3_, spv::OpVectorTimesScalar, type_float3_, gradients_h,
gradients_h, lod_gradient_scale); lod_gradient_scale);
builder_->addDecoration(gradients_h, gradients_v = builder_->createNoContractionBinOp(
spv::DecorationNoContraction); spv::OpVectorTimesScalar, type_float3_, gradients_v,
gradients_v = lod_gradient_scale);
builder_->createBinOp(spv::OpVectorTimesScalar, type_float3_,
gradients_v, lod_gradient_scale);
builder_->addDecoration(gradients_v,
spv::DecorationNoContraction);
} break; } break;
} }
} }
@ -1843,7 +1769,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Block& block_dimension_3d_start = builder_->makeNewBlock(); spv::Block& block_dimension_3d_start = builder_->makeNewBlock();
spv::Block& block_dimension_stacked_start = builder_->makeNewBlock(); spv::Block& block_dimension_stacked_start = builder_->makeNewBlock();
spv::Block& block_dimension_merge = builder_->makeNewBlock(); spv::Block& block_dimension_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_dimension_merge.getId(), builder_->createSelectionMerge(&block_dimension_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
assert_true(data_is_3d != spv::NoResult); assert_true(data_is_3d != spv::NoResult);
builder_->createConditionalBranch(data_is_3d, builder_->createConditionalBranch(data_is_3d,
@ -1899,21 +1825,15 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
(vol_mag_filter_is_fetch_const || vol_min_filter_is_fetch_const || (vol_mag_filter_is_fetch_const || vol_min_filter_is_fetch_const ||
vol_mag_filter_is_linear != vol_min_filter_is_linear)) { vol_mag_filter_is_linear != vol_min_filter_is_linear)) {
// Check if minifying along layers (derivative > 1 along any axis). // Check if minifying along layers (derivative > 1 along any axis).
id_vector_temp_.clear(); spv::Id layer_max_gradient = builder_->createBinBuiltinCall(
for (uint32_t i = 0; i < 2; ++i) { type_float_, ext_inst_glsl_std_450_, GLSLstd450NMax,
id_vector_temp_.push_back(builder_->createCompositeExtract( builder_->createCompositeExtract(gradients_h, type_float_, 2),
i ? gradients_v : gradients_h, type_float_, 2)); builder_->createCompositeExtract(gradients_v, type_float_, 2));
}
spv::Id layer_max_gradient =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450NMax, id_vector_temp_);
if (!instr.attributes.unnormalized_coordinates) { if (!instr.attributes.unnormalized_coordinates) {
// Denormalize the gradient if provided as normalized. // Denormalize the gradient if provided as normalized.
assert_true(size[2] != spv::NoResult); assert_true(size[2] != spv::NoResult);
layer_max_gradient = builder_->createBinOp( layer_max_gradient = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, layer_max_gradient, size[2]); spv::OpFMul, type_float_, layer_max_gradient, size[2]);
builder_->addDecoration(layer_max_gradient,
spv::DecorationNoContraction);
} }
// For NaN, considering that magnification is being done. // For NaN, considering that magnification is being done.
spv::Id is_minifying_z = builder_->createBinOp( spv::Id is_minifying_z = builder_->createBinOp(
@ -1970,20 +1890,16 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// If the filter is linear, subtract 0.5 from the Z coordinate of the // If the filter is linear, subtract 0.5 from the Z coordinate of the
// first layer in filtering because 0.5 is in the middle of it. // first layer in filtering because 0.5 is in the middle of it.
if (vol_filter_is_linear != spv::NoResult) { if (vol_filter_is_linear != spv::NoResult) {
spv::Id layer_coordinate_linear = builder_->createBinOp(
spv::OpFSub, type_float_, layer_coordinate,
builder_->makeFloatConstant(0.5f));
builder_->addDecoration(layer_coordinate_linear,
spv::DecorationNoContraction);
layer_coordinate = builder_->createTriOp( layer_coordinate = builder_->createTriOp(
spv::OpSelect, type_float_, vol_filter_is_linear, spv::OpSelect, type_float_, vol_filter_is_linear,
layer_coordinate_linear, layer_coordinate); builder_->createNoContractionBinOp(
spv::OpFSub, type_float_, layer_coordinate,
builder_->makeFloatConstant(0.5f)),
layer_coordinate);
} else if (vol_mag_filter_is_linear) { } else if (vol_mag_filter_is_linear) {
layer_coordinate = builder_->createBinOp( layer_coordinate = builder_->createNoContractionBinOp(
spv::OpFSub, type_float_, layer_coordinate, spv::OpFSub, type_float_, layer_coordinate,
builder_->makeFloatConstant(0.5f)); builder_->makeFloatConstant(0.5f));
builder_->addDecoration(layer_coordinate,
spv::DecorationNoContraction);
} }
// Sample the first layer, needed regardless of whether filtering is // Sample the first layer, needed regardless of whether filtering is
// needed. // needed.
@ -1991,11 +1907,9 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// floor even for the layer index, but on the Xenos, addressing is // floor even for the layer index, but on the Xenos, addressing is
// similar to that of 3D textures). This is needed for both point and // similar to that of 3D textures). This is needed for both point and
// linear filtering (with linear, 0.5 was subtracted previously). // linear filtering (with linear, 0.5 was subtracted previously).
id_vector_temp_.clear(); spv::Id layer_0_coordinate = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(layer_coordinate); type_float_, ext_inst_glsl_std_450_, GLSLstd450Floor,
spv::Id layer_0_coordinate = layer_coordinate);
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Floor, id_vector_temp_);
id_vector_temp_.clear(); id_vector_temp_.clear();
id_vector_temp_.push_back(coordinates[0]); id_vector_temp_.push_back(coordinates[0]);
id_vector_temp_.push_back(coordinates[1]); id_vector_temp_.push_back(coordinates[1]);
@ -2021,8 +1935,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
? builder_->makeNewBlock() ? builder_->makeNewBlock()
: block_z_head; : block_z_head;
if (vol_filter_is_linear != spv::NoResult) { if (vol_filter_is_linear != spv::NoResult) {
SpirvCreateSelectionMerge(block_z_merge.getId(), builder_->createSelectionMerge(
spv::SelectionControlDontFlattenMask); &block_z_merge, spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch( builder_->createConditionalBranch(
vol_filter_is_linear, &block_z_linear, &block_z_merge); vol_filter_is_linear, &block_z_linear, &block_z_merge);
builder_->setBuildPoint(&block_z_linear); builder_->setBuildPoint(&block_z_linear);
@ -2036,11 +1950,9 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
id_vector_temp_.push_back(layer_1_coordinate); id_vector_temp_.push_back(layer_1_coordinate);
texture_parameters.coords = builder_->createCompositeConstruct( texture_parameters.coords = builder_->createCompositeConstruct(
type_float3_, id_vector_temp_); type_float3_, id_vector_temp_);
id_vector_temp_.clear(); spv::Id layer_lerp_factor = builder_->createUnaryBuiltinCall(
id_vector_temp_.push_back(layer_coordinate); type_float_, ext_inst_glsl_std_450_, GLSLstd450Fract,
spv::Id layer_lerp_factor = layer_coordinate);
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450Fract, id_vector_temp_);
spv::Id sample_result_unsigned_stacked_filtered; spv::Id sample_result_unsigned_stacked_filtered;
spv::Id sample_result_signed_stacked_filtered; spv::Id sample_result_signed_stacked_filtered;
SampleTexture( SampleTexture(
@ -2187,8 +2099,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Block& block_swizzle_constant = builder_->makeNewBlock(); spv::Block& block_swizzle_constant = builder_->makeNewBlock();
spv::Block& block_swizzle_component = builder_->makeNewBlock(); spv::Block& block_swizzle_component = builder_->makeNewBlock();
spv::Block& block_swizzle_merge = builder_->makeNewBlock(); spv::Block& block_swizzle_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_swizzle_merge.getId(), builder_->createSelectionMerge(
spv::SelectionControlDontFlattenMask); &block_swizzle_merge, spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch(swizzle_bit_2, builder_->createConditionalBranch(swizzle_bit_2,
&block_swizzle_constant, &block_swizzle_constant,
&block_swizzle_component); &block_swizzle_component);
@ -2279,8 +2191,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
spv::Block& block_sign_unsigned_biased = builder_->makeNewBlock(); spv::Block& block_sign_unsigned_biased = builder_->makeNewBlock();
spv::Block& block_sign_gamma_start = builder_->makeNewBlock(); spv::Block& block_sign_gamma_start = builder_->makeNewBlock();
spv::Block& block_sign_merge = builder_->makeNewBlock(); spv::Block& block_sign_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_sign_merge.getId(), builder_->createSelectionMerge(
spv::SelectionControlDontFlattenMask); &block_sign_merge, spv::SelectionControlDontFlattenMask);
{ {
std::unique_ptr<spv::Instruction> sign_switch_op = std::unique_ptr<spv::Instruction> sign_switch_op =
std::make_unique<spv::Instruction>(spv::OpSwitch); std::make_unique<spv::Instruction>(spv::OpSwitch);
@ -2323,16 +2235,14 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// Unsigned biased. // Unsigned biased.
builder_->setBuildPoint(&block_sign_unsigned_biased); builder_->setBuildPoint(&block_sign_unsigned_biased);
spv::Id sample_result_component_unsigned_biased = spv::Id sample_result_component_unsigned_biased =
builder_->createBinOp(spv::OpFMul, type_float_, builder_->createNoContractionBinOp(
sample_result_component_unsigned, spv::OpFMul, type_float_, sample_result_component_unsigned,
const_float_2); const_float_2);
builder_->addDecoration(sample_result_component_unsigned_biased, sample_result_component_unsigned_biased =
spv::DecorationNoContraction); builder_->createNoContractionBinOp(
sample_result_component_unsigned_biased = builder_->createBinOp(
spv::OpFAdd, type_float_, spv::OpFAdd, type_float_,
sample_result_component_unsigned_biased, const_float_minus_1); sample_result_component_unsigned_biased,
builder_->addDecoration(sample_result_component_unsigned_biased, const_float_minus_1);
spv::DecorationNoContraction);
builder_->createBranch(&block_sign_merge); builder_->createBranch(&block_sign_merge);
// Gamma. // Gamma.
builder_->setBuildPoint(&block_sign_gamma_start); builder_->setBuildPoint(&block_sign_gamma_start);
@ -2368,14 +2278,13 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// Apply the exponent bias from the bits 13:18 of the fetch constant // Apply the exponent bias from the bits 13:18 of the fetch constant
// word 4. // word 4.
id_vector_temp_.clear(); spv::Id result_exponent_bias = builder_->createBinBuiltinCall(
id_vector_temp_.push_back(builder_->makeFloatConstant(1.0f)); type_float_, ext_inst_glsl_std_450_, GLSLstd450Ldexp,
id_vector_temp_.push_back(builder_->createTriOp( const_float_1_,
spv::OpBitFieldSExtract, type_int_, fetch_constant_word_4_signed, builder_->createTriOp(spv::OpBitFieldSExtract, type_int_,
builder_->makeUintConstant(13), builder_->makeUintConstant(6))); fetch_constant_word_4_signed,
spv::Id result_exponent_bias = builder_->makeUintConstant(13),
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_, builder_->makeUintConstant(6)));
GLSLstd450Ldexp, id_vector_temp_);
{ {
uint32_t result_remaining_components = used_result_nonzero_components; uint32_t result_remaining_components = used_result_nonzero_components;
uint32_t result_component_index; uint32_t result_component_index;
@ -2383,12 +2292,9 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
&result_component_index)) { &result_component_index)) {
result_remaining_components &= result_remaining_components &=
~(UINT32_C(1) << result_component_index); ~(UINT32_C(1) << result_component_index);
spv::Id& result_component_ref = result[result_component_index]; result[result_component_index] = builder_->createNoContractionBinOp(
result_component_ref = builder_->createBinOp( spv::OpFMul, type_float_, result[result_component_index],
spv::OpFMul, type_float_, result_component_ref,
result_exponent_bias); result_exponent_bias);
builder_->addDecoration(result_component_ref,
spv::DecorationNoContraction);
} }
} }
} }
@ -2543,7 +2449,7 @@ void SpirvShaderTranslator::SampleTexture(
spv::Block& block_sign_head = *builder_->getBuildPoint(); spv::Block& block_sign_head = *builder_->getBuildPoint();
spv::Block& block_sign = builder_->makeNewBlock(); spv::Block& block_sign = builder_->makeNewBlock();
spv::Block& block_sign_merge = builder_->makeNewBlock(); spv::Block& block_sign_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_sign_merge.getId(), builder_->createSelectionMerge(&block_sign_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
// Unsigned (i == 0) - if there are any non-signed components. // Unsigned (i == 0) - if there are any non-signed components.
// Signed (i == 1) - if there are any signed components. // Signed (i == 1) - if there are any signed components.
@ -2563,16 +2469,13 @@ void SpirvShaderTranslator::SampleTexture(
if (lerp_factor != spv::NoResult) { if (lerp_factor != spv::NoResult) {
spv::Id lerp_first = i ? lerp_first_signed : lerp_first_unsigned; spv::Id lerp_first = i ? lerp_first_signed : lerp_first_unsigned;
if (lerp_first != spv::NoResult) { if (lerp_first != spv::NoResult) {
spv::Id lerp_difference = builder_->createBinOp( spv::Id lerp_difference = builder_->createNoContractionBinOp(
spv::OpFSub, type_float4_, result, lerp_first); spv::OpVectorTimesScalar, type_float4_,
builder_->addDecoration(lerp_difference, spv::DecorationNoContraction); builder_->createNoContractionBinOp(spv::OpFSub, type_float4_,
lerp_difference = result, lerp_first),
builder_->createBinOp(spv::OpVectorTimesScalar, type_float4_, lerp_factor);
lerp_difference, lerp_factor); result = builder_->createNoContractionBinOp(spv::OpFAdd, type_float4_,
builder_->addDecoration(lerp_difference, spv::DecorationNoContraction); result, lerp_difference);
result = builder_->createBinOp(spv::OpFAdd, type_float4_, result,
lerp_difference);
builder_->addDecoration(result, spv::DecorationNoContraction);
} }
} }
builder_->createBranch(&block_sign_merge); builder_->createBranch(&block_sign_merge);
@ -2601,7 +2504,7 @@ spv::Id SpirvShaderTranslator::QueryTextureLod(
spv::Block& block_sign_signed = builder_->makeNewBlock(); spv::Block& block_sign_signed = builder_->makeNewBlock();
spv::Block& block_sign_unsigned = builder_->makeNewBlock(); spv::Block& block_sign_unsigned = builder_->makeNewBlock();
spv::Block& block_sign_merge = builder_->makeNewBlock(); spv::Block& block_sign_merge = builder_->makeNewBlock();
SpirvCreateSelectionMerge(block_sign_merge.getId(), builder_->createSelectionMerge(&block_sign_merge,
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
builder_->createConditionalBranch(is_all_signed, &block_sign_signed, builder_->createConditionalBranch(is_all_signed, &block_sign_signed,
&block_sign_unsigned); &block_sign_unsigned);

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,6 @@
#include <vector> #include <vector>
#include "third_party/fmt/include/fmt/format.h" #include "third_party/fmt/include/fmt/format.h"
#include "third_party/glslang/SPIRV/SpvBuilder.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
@ -28,6 +27,7 @@
#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/gpu_flags.h"
#include "xenia/gpu/register_file.h" #include "xenia/gpu/register_file.h"
#include "xenia/gpu/registers.h" #include "xenia/gpu/registers.h"
#include "xenia/gpu/spirv_builder.h"
#include "xenia/gpu/spirv_shader_translator.h" #include "xenia/gpu/spirv_shader_translator.h"
#include "xenia/gpu/vulkan/vulkan_command_processor.h" #include "xenia/gpu/vulkan/vulkan_command_processor.h"
#include "xenia/gpu/vulkan/vulkan_shader.h" #include "xenia/gpu/vulkan/vulkan_shader.h"
@ -952,7 +952,7 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
(key.user_clip_plane_cull ? key.user_clip_plane_count : 0) + (key.user_clip_plane_cull ? key.user_clip_plane_count : 0) +
key.has_vertex_kill_and; key.has_vertex_kill_and;
spv::Builder builder(spv::Spv_1_0, SpirvBuilder builder(spv::Spv_1_0,
(SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1, (SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1,
nullptr); nullptr);
spv::Id ext_inst_glsl_std_450 = builder.import("GLSL.std.450"); spv::Id ext_inst_glsl_std_450 = builder.import("GLSL.std.450");
@ -1233,14 +1233,8 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
spv::Block& discard_predecessor = *builder.getBuildPoint(); spv::Block& discard_predecessor = *builder.getBuildPoint();
spv::Block& discard_then_block = builder.makeNewBlock(); spv::Block& discard_then_block = builder.makeNewBlock();
spv::Block& discard_merge_block = builder.makeNewBlock(); spv::Block& discard_merge_block = builder.makeNewBlock();
{ builder.createSelectionMerge(&discard_merge_block,
std::unique_ptr<spv::Instruction> selection_merge_op(
std::make_unique<spv::Instruction>(spv::OpSelectionMerge));
selection_merge_op->addIdOperand(discard_merge_block.getId());
selection_merge_op->addImmediateOperand(
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
discard_predecessor.addInstruction(std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op( std::unique_ptr<spv::Instruction> branch_conditional_op(
std::make_unique<spv::Instruction>(spv::OpBranchConditional)); std::make_unique<spv::Instruction>(spv::OpBranchConditional));
@ -1295,14 +1289,8 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
spv::Block& discard_predecessor = *builder.getBuildPoint(); spv::Block& discard_predecessor = *builder.getBuildPoint();
spv::Block& discard_then_block = builder.makeNewBlock(); spv::Block& discard_then_block = builder.makeNewBlock();
spv::Block& discard_merge_block = builder.makeNewBlock(); spv::Block& discard_merge_block = builder.makeNewBlock();
{ builder.createSelectionMerge(&discard_merge_block,
std::unique_ptr<spv::Instruction> selection_merge_op(
std::make_unique<spv::Instruction>(spv::OpSelectionMerge));
selection_merge_op->addIdOperand(discard_merge_block.getId());
selection_merge_op->addImmediateOperand(
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
discard_predecessor.addInstruction(std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op( std::unique_ptr<spv::Instruction> branch_conditional_op(
std::make_unique<spv::Instruction>(spv::OpBranchConditional)); std::make_unique<spv::Instruction>(spv::OpBranchConditional));
@ -1378,15 +1366,8 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
spv::Block& point_size_zero_predecessor = *builder.getBuildPoint(); spv::Block& point_size_zero_predecessor = *builder.getBuildPoint();
spv::Block& point_size_zero_then_block = builder.makeNewBlock(); spv::Block& point_size_zero_then_block = builder.makeNewBlock();
spv::Block& point_size_zero_merge_block = builder.makeNewBlock(); spv::Block& point_size_zero_merge_block = builder.makeNewBlock();
{ builder.createSelectionMerge(&point_size_zero_merge_block,
std::unique_ptr<spv::Instruction> selection_merge_op(
std::make_unique<spv::Instruction>(spv::OpSelectionMerge));
selection_merge_op->addIdOperand(point_size_zero_merge_block.getId());
selection_merge_op->addImmediateOperand(
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
point_size_zero_predecessor.addInstruction(
std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op( std::unique_ptr<spv::Instruction> branch_conditional_op(
std::make_unique<spv::Instruction>(spv::OpBranchConditional)); std::make_unique<spv::Instruction>(spv::OpBranchConditional));
@ -1412,21 +1393,19 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
id_vector_temp.push_back(builder.makeIntConstant( id_vector_temp.push_back(builder.makeIntConstant(
int32_t(kPointConstantScreenDiameterToNdcRadius))); int32_t(kPointConstantScreenDiameterToNdcRadius)));
id_vector_temp.push_back(const_int_0); id_vector_temp.push_back(const_int_0);
spv::Id point_radius_x = builder.createBinOp( spv::Id point_radius_x = builder.createNoContractionBinOp(
spv::OpFMul, type_float, point_guest_diameter_x, spv::OpFMul, type_float, point_guest_diameter_x,
builder.createLoad(builder.createAccessChain(spv::StorageClassUniform, builder.createLoad(builder.createAccessChain(spv::StorageClassUniform,
uniform_system_constants, uniform_system_constants,
id_vector_temp), id_vector_temp),
spv::NoPrecision)); spv::NoPrecision));
builder.addDecoration(point_radius_x, spv::DecorationNoContraction);
id_vector_temp.back() = const_int_1; id_vector_temp.back() = const_int_1;
spv::Id point_radius_y = builder.createBinOp( spv::Id point_radius_y = builder.createNoContractionBinOp(
spv::OpFMul, type_float, point_guest_diameter_y, spv::OpFMul, type_float, point_guest_diameter_y,
builder.createLoad(builder.createAccessChain(spv::StorageClassUniform, builder.createLoad(builder.createAccessChain(spv::StorageClassUniform,
uniform_system_constants, uniform_system_constants,
id_vector_temp), id_vector_temp),
spv::NoPrecision)); spv::NoPrecision));
builder.addDecoration(point_radius_y, spv::DecorationNoContraction);
id_vector_temp.clear(); id_vector_temp.clear();
// 0 is the input primitive vertex index. // 0 is the input primitive vertex index.
id_vector_temp.push_back(const_int_0); id_vector_temp.push_back(const_int_0);
@ -1437,12 +1416,10 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
spv::NoPrecision); spv::NoPrecision);
spv::Id point_w = spv::Id point_w =
builder.createCompositeExtract(point_position, type_float, 3); builder.createCompositeExtract(point_position, type_float, 3);
point_radius_x = point_radius_x = builder.createNoContractionBinOp(
builder.createBinOp(spv::OpFMul, type_float, point_radius_x, point_w); spv::OpFMul, type_float, point_radius_x, point_w);
builder.addDecoration(point_radius_x, spv::DecorationNoContraction); point_radius_y = builder.createNoContractionBinOp(
point_radius_y = spv::OpFMul, type_float, point_radius_y, point_w);
builder.createBinOp(spv::OpFMul, type_float, point_radius_y, point_w);
builder.addDecoration(point_radius_y, spv::DecorationNoContraction);
// Load the inputs for the guest point. // Load the inputs for the guest point.
// Interpolators. // Interpolators.
@ -1464,12 +1441,10 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
std::array<spv::Id, 2> point_edge_x, point_edge_y; std::array<spv::Id, 2> point_edge_x, point_edge_y;
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
spv::Op point_radius_add_op = i ? spv::OpFAdd : spv::OpFSub; spv::Op point_radius_add_op = i ? spv::OpFAdd : spv::OpFSub;
point_edge_x[i] = builder.createBinOp(point_radius_add_op, type_float, point_edge_x[i] = builder.createNoContractionBinOp(
point_x, point_radius_x); point_radius_add_op, type_float, point_x, point_radius_x);
builder.addDecoration(point_edge_x[i], spv::DecorationNoContraction); point_edge_y[i] = builder.createNoContractionBinOp(
point_edge_y[i] = builder.createBinOp(point_radius_add_op, type_float, point_radius_add_op, type_float, point_y, point_radius_y);
point_y, point_radius_y);
builder.addDecoration(point_edge_y[i], spv::DecorationNoContraction);
}; };
spv::Id point_z = spv::Id point_z =
builder.createCompositeExtract(point_position, type_float, 2); builder.createCompositeExtract(point_position, type_float, 2);
@ -1718,24 +1693,20 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
id_vector_temp), id_vector_temp),
spv::NoPrecision); spv::NoPrecision);
id_vector_temp[0] = vertex_indices[1]; id_vector_temp[0] = vertex_indices[1];
spv::Id vertex_interpolator_v01 = builder.createBinOp( spv::Id vertex_interpolator_v01 = builder.createNoContractionBinOp(
spv::OpFSub, type_float4, spv::OpFSub, type_float4,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_interpolator, id_vector_temp), in_interpolator, id_vector_temp),
spv::NoPrecision), spv::NoPrecision),
vertex_interpolator_v0); vertex_interpolator_v0);
builder.addDecoration(vertex_interpolator_v01,
spv::DecorationNoContraction);
id_vector_temp[0] = vertex_indices[2]; id_vector_temp[0] = vertex_indices[2];
spv::Id vertex_interpolator_v3 = builder.createBinOp( spv::Id vertex_interpolator_v3 = builder.createNoContractionBinOp(
spv::OpFAdd, type_float4, vertex_interpolator_v01, spv::OpFAdd, type_float4, vertex_interpolator_v01,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_interpolator, id_vector_temp), in_interpolator, id_vector_temp),
spv::NoPrecision)); spv::NoPrecision));
builder.addDecoration(vertex_interpolator_v3,
spv::DecorationNoContraction);
builder.createStore(vertex_interpolator_v3, out_interpolators[i]); builder.createStore(vertex_interpolator_v3, out_interpolators[i]);
} }
// Point coordinates. // Point coordinates.
@ -1752,22 +1723,20 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
id_vector_temp), id_vector_temp),
spv::NoPrecision); spv::NoPrecision);
id_vector_temp[0] = vertex_indices[1]; id_vector_temp[0] = vertex_indices[1];
spv::Id vertex_position_v01 = builder.createBinOp( spv::Id vertex_position_v01 = builder.createNoContractionBinOp(
spv::OpFSub, type_float4, spv::OpFSub, type_float4,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_gl_per_vertex, id_vector_temp), in_gl_per_vertex, id_vector_temp),
spv::NoPrecision), spv::NoPrecision),
vertex_position_v0); vertex_position_v0);
builder.addDecoration(vertex_position_v01, spv::DecorationNoContraction);
id_vector_temp[0] = vertex_indices[2]; id_vector_temp[0] = vertex_indices[2];
spv::Id vertex_position_v3 = builder.createBinOp( spv::Id vertex_position_v3 = builder.createNoContractionBinOp(
spv::OpFAdd, type_float4, vertex_position_v01, spv::OpFAdd, type_float4, vertex_position_v01,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_gl_per_vertex, id_vector_temp), in_gl_per_vertex, id_vector_temp),
spv::NoPrecision)); spv::NoPrecision));
builder.addDecoration(vertex_position_v3, spv::DecorationNoContraction);
id_vector_temp.clear(); id_vector_temp.clear();
id_vector_temp.push_back(const_member_out_gl_per_vertex_position); id_vector_temp.push_back(const_member_out_gl_per_vertex_position);
builder.createStore( builder.createStore(
@ -1786,24 +1755,20 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
id_vector_temp), id_vector_temp),
spv::NoPrecision); spv::NoPrecision);
id_vector_temp[0] = vertex_indices[1]; id_vector_temp[0] = vertex_indices[1];
spv::Id vertex_clip_distance_v01 = builder.createBinOp( spv::Id vertex_clip_distance_v01 = builder.createNoContractionBinOp(
spv::OpFSub, type_float, spv::OpFSub, type_float,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_gl_per_vertex, id_vector_temp), in_gl_per_vertex, id_vector_temp),
spv::NoPrecision), spv::NoPrecision),
vertex_clip_distance_v0); vertex_clip_distance_v0);
builder.addDecoration(vertex_clip_distance_v01,
spv::DecorationNoContraction);
id_vector_temp[0] = vertex_indices[2]; id_vector_temp[0] = vertex_indices[2];
spv::Id vertex_clip_distance_v3 = builder.createBinOp( spv::Id vertex_clip_distance_v3 = builder.createNoContractionBinOp(
spv::OpFAdd, type_float, vertex_clip_distance_v01, spv::OpFAdd, type_float, vertex_clip_distance_v01,
builder.createLoad( builder.createLoad(
builder.createAccessChain(spv::StorageClassInput, builder.createAccessChain(spv::StorageClassInput,
in_gl_per_vertex, id_vector_temp), in_gl_per_vertex, id_vector_temp),
spv::NoPrecision)); spv::NoPrecision));
builder.addDecoration(vertex_clip_distance_v3,
spv::DecorationNoContraction);
id_vector_temp.clear(); id_vector_temp.clear();
id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance); id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance);
id_vector_temp.push_back(const_int_i); id_vector_temp.push_back(const_int_i);

File diff suppressed because it is too large Load Diff