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

View File

@ -17,8 +17,8 @@
#include <utility>
#include <vector>
#include "third_party/glslang/SPIRV/SpvBuilder.h"
#include "xenia/gpu/shader_translator.h"
#include "xenia/gpu/spirv_builder.h"
#include "xenia/gpu/xenos.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
// 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 ext_inst_glsl_std_450);
// 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 ext_inst_glsl_std_450);
// Converts the 7e3 number in bits [f10_shift, f10_shift + 10) to a 32-bit
// 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,
spv::Id ext_inst_glsl_std_450);
// 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
// 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.
static spv::Id PreClampedDepthTo20e4(spv::Builder& builder,
static spv::Id PreClampedDepthTo20e4(SpirvBuilder& builder,
spv::Id f32_scalar,
bool round_to_nearest_even,
bool remap_from_0_to_0_5,
spv::Id ext_inst_glsl_std_450);
// Converts the 20e4 number in bits [f24_shift, f24_shift + 10) to a 32-bit
// 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,
bool result_as_uint,
spv::Id ext_inst_glsl_std_450);
@ -451,15 +451,6 @@ class SpirvShaderTranslator : public ShaderTranslator {
// Builder helpers.
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 {
return Modification(current_translation().modification());
@ -571,6 +562,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
// must be called with absolute values of operands - use GetAbsoluteOperand!
spv::Id ZeroIfAnyOperandIsZero(spv::Id value, spv::Id operand_0_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
// float vector or a single float, depending on whether it's a reduction
// 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.
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_;
// 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);
assert_true(builder_->getNumComponents(operand_0_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(
spv::OpSelect, type_float_,
builder_->createBinOp(
spv::OpFOrdEqual, type_bool_vectors_[num_components - 1],
builder_->createBuiltinCall(type_float_vectors_[num_components - 1],
ext_inst_glsl_std_450_, GLSLstd450NMin,
id_vector_temp_util_),
builder_->createBinBuiltinCall(
type_float_vectors_[num_components - 1], ext_inst_glsl_std_450_,
GLSLstd450NMin, operand_0_abs, operand_1_abs),
const_float_vectors_0_[num_components - 1]),
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(
const ParsedAluInstruction& instr) {
if (instr.IsNop()) {
@ -162,14 +185,12 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
switch (instr.vector_opcode) {
case ucode::AluVectorOpcode::kAdd: {
spv::Id result = builder_->createBinOp(
return builder_->createNoContractionBinOp(
spv::OpFAdd, result_type,
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
used_result_components),
GetOperandComponents(operand_storage[1], instr.vector_operands[1],
used_result_components));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluVectorOpcode::kMul:
case ucode::AluVectorOpcode::kMad: {
@ -179,9 +200,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
GetOperandComponents(operand_storage[i], instr.vector_operands[i],
used_result_components);
}
spv::Id result = builder_->createBinOp(
spv::Id result = builder_->createNoContractionBinOp(
spv::OpFMul, result_type, multiplicands[0], multiplicands[1]);
builder_->addDecoration(result, spv::DecorationNoContraction);
uint32_t multiplicands_different =
used_result_components &
~instr.vector_operands[0].GetIdenticalComponents(
@ -229,15 +249,12 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
different_operands[i] = GetAbsoluteOperand(different_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::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.
different_result = builder_->createTriOp(
spv::OpSelect, different_type, different_zero,
@ -276,11 +293,10 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
if (instr.vector_opcode == ucode::AluVectorOpcode::kMad) {
// Not replacing true `0 + term` with conditional selection of the term
// because +0 + -0 should result in +0, not -0.
result = builder_->createBinOp(
result = builder_->createNoContractionBinOp(
spv::OpFAdd, result_type, result,
GetOperandComponents(operand_storage[2], instr.vector_operands[2],
used_result_components));
builder_->addDecoration(result, spv::DecorationNoContraction);
}
return result;
}
@ -303,24 +319,18 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
} else {
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_->createUnaryOp(
spv::OpConvertFToS, type_int_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_)),
builder_->createTriBuiltinCall(
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_);
}
if (!used_result_components) {
@ -434,13 +444,11 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
case ucode::AluVectorOpcode::kFrc:
case ucode::AluVectorOpcode::kTrunc:
case ucode::AluVectorOpcode::kFloor:
id_vector_temp_.clear();
id_vector_temp_.push_back(GetOperandComponents(operand_storage[0],
instr.vector_operands[0],
used_result_components));
return builder_->createBuiltinCall(
return builder_->createUnaryBuiltinCall(
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::kCndGe:
@ -488,10 +496,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
operand_components[j] =
builder_->createCompositeExtract(operands[j], type_float_, i);
}
spv::Id product =
builder_->createBinOp(spv::OpFMul, type_float_,
operand_components[0], operand_components[1]);
builder_->addDecoration(product, spv::DecorationNoContraction);
spv::Id product = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, operand_components[0],
operand_components[1]);
if (different & (1 << i)) {
// Shader Model 3: +0 or denormal * anything = +-0.
product = ZeroIfAnyOperandIsZero(
@ -505,16 +512,14 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
result = product;
continue;
}
result =
builder_->createBinOp(spv::OpFAdd, type_float_, result, product);
builder_->addDecoration(result, spv::DecorationNoContraction);
result = builder_->createNoContractionBinOp(spv::OpFAdd, type_float_,
result, product);
}
if (instr.vector_opcode == ucode::AluVectorOpcode::kDp2Add) {
result = builder_->createBinOp(
result = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, result,
GetOperandComponents(operand_storage[2], instr.vector_operands[2],
0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
}
return result;
}
@ -535,11 +540,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
if (!instr.vector_operands[0].is_absolute_value ||
instr.vector_operands[0].is_negated) {
for (unsigned int i = 0; i < 3; ++i) {
id_vector_temp_.clear();
id_vector_temp_.push_back(operand[i]);
operand_abs[i] =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_);
operand_abs[i] = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, operand[i]);
}
} else {
for (unsigned int i = 0; i < 3; ++i) {
@ -548,146 +550,132 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
}
spv::Id operand_neg[3] = {};
if (used_result_components & 0b0001) {
operand_neg[1] =
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[1]);
builder_->addDecoration(operand_neg[1], spv::DecorationNoContraction);
operand_neg[1] = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, operand[1]);
}
if (used_result_components & 0b0010) {
operand_neg[0] =
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[0]);
builder_->addDecoration(operand_neg[0], spv::DecorationNoContraction);
operand_neg[2] =
builder_->createUnaryOp(spv::OpFNegate, type_float_, operand[2]);
builder_->addDecoration(operand_neg[2], spv::DecorationNoContraction);
operand_neg[0] = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, operand[0]);
operand_neg[2] = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, operand[2]);
}
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)).
// Selection merge must be the penultimate instruction in the block, check
// the condition before it.
spv::Id ma_z_condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_,
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[0]),
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[1]));
spv::Function& function = builder_->getBuildPoint()->getParent();
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.
spv::Id ma_z_result[4] = {};
// tc = -y
ma_z_result[0] = operand_neg[1];
// ma/2 = z
ma_z_result[2] = operand[2];
if (used_result_components & 0b1010) {
spv::Id z_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_);
if (used_result_components & 0b0010) {
// sc = z < 0.0 ? -x : x
ma_z_result[1] = builder_->createTriOp(
spv::OpSelect, type_float_, z_is_neg, operand_neg[0], operand[0]);
}
if (used_result_components & 0b1000) {
// id = z < 0.0 ? 5.0 : 4.0
ma_z_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
builder_->makeFloatConstant(5.0f),
builder_->makeFloatConstant(4.0f));
spv::Builder::If ma_z_if(
builder_->createBinOp(
spv::OpLogicalAnd, type_bool_,
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[0]),
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[2], operand_abs[1])),
spv::SelectionControlMaskNone, *builder_);
{
// The major axis is Z.
// tc = -y
ma_z_result[0] = operand_neg[1];
// ma/2 = z
ma_z_result[2] = operand[2];
if (used_result_components & 0b1010) {
spv::Id z_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_);
if (used_result_components & 0b0010) {
// sc = z < 0.0 ? -x : x
ma_z_result[1] =
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
operand_neg[0], operand[0]);
}
if (used_result_components & 0b1000) {
// id = z < 0.0 ? 5.0 : 4.0
ma_z_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
builder_->makeFloatConstant(5.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
// major axis is Y (abs(y) >= abs(x)).
// Selection merge must be the penultimate instruction in the block, check
// the condition before it.
spv::Id ma_y_condition =
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[1], operand_abs[0]);
spv::Block& ma_y_block = builder_->makeNewBlock();
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);
// The major axis is not Z - create an inner conditional to check if the
// major axis is Y (abs(y) >= abs(x)).
spv::Builder::If ma_y_if(
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
operand_abs[1], operand_abs[0]),
spv::SelectionControlMaskNone, *builder_);
{
// The major axis is Y.
// sc = x
ma_y_result[1] = operand[0];
// ma/2 = y
ma_y_result[2] = operand[1];
if (used_result_components & 0b1001) {
spv::Id y_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_);
if (used_result_components & 0b0001) {
// tc = y < 0.0 ? -z : z
ma_y_result[0] =
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
operand_neg[2], operand[2]);
// id = y < 0.0 ? 3.0 : 2.0
ma_y_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
builder_->makeFloatConstant(3.0f),
builder_->makeFloatConstant(2.0f));
}
}
}
spv::Block& ma_y_end_block = *builder_->getBuildPoint();
ma_y_if.makeBeginElse();
{
// The major axis is X.
// tc = -y
ma_x_result[0] = operand_neg[1];
// ma/2 = x
ma_x_result[2] = operand[0];
if (used_result_components & 0b1010) {
spv::Id x_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_);
if (used_result_components & 0b0010) {
// sc = x < 0.0 ? z : -z
ma_x_result[1] =
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
operand[2], operand_neg[2]);
}
if (used_result_components & 0b1000) {
// id = x < 0.0 ? 1.0 : 0.0
ma_x_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
const_float_1_, const_float_0_);
}
}
}
spv::Block& ma_x_end_block = *builder_->getBuildPoint();
ma_y_if.makeEndIf();
builder_->setBuildPoint(&ma_y_block);
// The major axis is Y.
spv::Id ma_y_result[4] = {};
// sc = x
ma_y_result[1] = operand[0];
// ma/2 = y
ma_y_result[2] = operand[1];
if (used_result_components & 0b1001) {
spv::Id y_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_);
if (used_result_components & 0b0001) {
// tc = y < 0.0 ? -z : z
ma_y_result[0] = builder_->createTriOp(
spv::OpSelect, type_float_, y_is_neg, operand_neg[2], operand[2]);
// id = y < 0.0 ? 3.0 : 2.0
ma_y_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
builder_->makeFloatConstant(3.0f),
builder_->makeFloatConstant(2.0f));
// The major axis is Y or X - choose the options of the result from Y
// and X.
for (uint32_t i = 0; i < 4; ++i) {
if (!(used_result_components & (1 << i))) {
continue;
}
std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi);
phi_op->addIdOperand(ma_y_result[i]);
phi_op->addIdOperand(ma_y_end_block.getId());
phi_op->addIdOperand(ma_x_result[i]);
phi_op->addIdOperand(ma_x_end_block.getId());
ma_yx_result[i] = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
}
}
builder_->createBranch(&ma_yx_merge_block);
spv::Block& ma_yx_end_block = *builder_->getBuildPoint();
ma_z_if.makeEndIf();
builder_->setBuildPoint(&ma_x_block);
// The major axis is X.
spv::Id ma_x_result[4] = {};
// tc = -y
ma_x_result[0] = operand_neg[1];
// ma/2 = x
ma_x_result[2] = operand[0];
if (used_result_components & 0b1010) {
spv::Id x_is_neg = builder_->createBinOp(
spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_);
if (used_result_components & 0b0010) {
// sc = x < 0.0 ? z : -z
ma_x_result[1] = builder_->createTriOp(
spv::OpSelect, type_float_, x_is_neg, operand[2], operand_neg[2]);
}
if (used_result_components & 0b1000) {
// id = x < 0.0 ? 1.0 : 0.0
ma_x_result[3] =
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
const_float_1_, const_float_0_);
}
}
builder_->createBranch(&ma_yx_merge_block);
builder_->setBuildPoint(&ma_yx_merge_block);
// The major axis is Y or X - choose the options of the result from Y and
// X.
spv::Id ma_yx_result[4] = {};
for (uint32_t i = 0; i < 4; ++i) {
if (!(used_result_components & (1 << i))) {
continue;
}
std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi);
phi_op->addIdOperand(ma_y_result[i]);
phi_op->addIdOperand(ma_y_block.getId());
phi_op->addIdOperand(ma_x_result[i]);
phi_op->addIdOperand(ma_x_block.getId());
ma_yx_result[i] = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
}
builder_->createBranch(ma_merge_block);
function.addBlock(ma_merge_block);
builder_->setBuildPoint(ma_merge_block);
// Choose the result options from Z and YX cases.
id_vector_temp_.clear();
for (uint32_t i = 0; i < 4; ++i) {
@ -698,9 +686,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi);
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_merge_block.getId());
phi_op->addIdOperand(ma_yx_end_block.getId());
id_vector_temp_.push_back(phi_op->getResultId());
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
}
@ -709,9 +697,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
// Multiply the major axis by 2.
spv::Id& ma2 = id_vector_temp_[xe::bit_count(used_result_components &
((1 << 2) - 1))];
ma2 = builder_->createBinOp(spv::OpFMul, type_float_,
builder_->makeFloatConstant(2.0f), ma2);
builder_->addDecoration(ma2, spv::DecorationNoContraction);
ma2 = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, builder_->makeFloatConstant(2.0f), ma2);
}
if (used_result_component_count == 1) {
// Only one component - not composite.
@ -746,13 +733,10 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
operand, type_float_, static_cast<unsigned int>(component));
while (xe::bit_scan_forward(components_remaining, &component)) {
components_remaining &= ~(uint32_t(1) << component);
id_vector_temp_.clear();
id_vector_temp_.push_back(result);
id_vector_temp_.push_back(builder_->createCompositeExtract(
operand, type_float_, static_cast<unsigned int>(component)));
result =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450NMax, id_vector_temp_);
result = builder_->createBinBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450NMax, result,
builder_->createCompositeExtract(
operand, type_float_, static_cast<unsigned int>(component)));
}
return result;
}
@ -802,45 +786,26 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, operands_x[0],
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_,
builder_->createTriOp(spv::OpSelect, type_float_, condition,
builder_->makeFloatConstant(-1.0f),
operands_x[0]),
const_float_1_);
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluVectorOpcode::kKillEq:
case ucode::AluVectorOpcode::kKillGt:
case ucode::AluVectorOpcode::kKillGe:
case ucode::AluVectorOpcode::kKillNe: {
// Selection merge must be the penultimate instruction in the block, check
// the condition before it.
spv::Id condition = builder_->createUnaryOp(
KillPixel(builder_->createUnaryOp(
spv::OpAny, type_bool_,
builder_->createBinOp(
spv::Op(kOps[size_t(instr.vector_opcode)]), type_bool4_,
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
0b1111),
GetOperandComponents(operand_storage[1], instr.vector_operands[1],
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);
0b1111))));
return const_float_0_;
}
@ -874,9 +839,8 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
(used_result_components & 0b1000)
? builder_->createCompositeExtract(operands[1], type_float_, 0)
: operands[1];
result_y = builder_->createBinOp(spv::OpFMul, type_float_,
operands_y[0], operands_y[1]);
builder_->addDecoration(result_y, spv::DecorationNoContraction);
result_y = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, operands_y[0], operands_y[1]);
if (!(instr.vector_operands[0].GetIdenticalComponents(
instr.vector_operands[1]) &
0b0010)) {
@ -999,26 +963,22 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kSubs: {
spv::Id 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);
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluScalarOpcode::kAddsPrev:
case ucode::AluScalarOpcode::kSubsPrev: {
spv::Id result = builder_->createBinOp(
return builder_->createNoContractionBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001),
builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluScalarOpcode::kMuls: {
spv::Id a, b;
GetOperandScalarXY(operand_storage[0], instr.scalar_operands[0], a, b);
spv::Id result = builder_->createBinOp(spv::OpFMul, type_float_, a, b);
builder_->addDecoration(result, spv::DecorationNoContraction);
spv::Id result =
builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, b);
if (a != b) {
// Shader Model 3: +0 or denormal * anything = +-0.
result = ZeroIfAnyOperandIsZero(
@ -1032,15 +992,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
instr.scalar_operands[0], 0b0001);
spv::Id ps =
builder_->createLoad(var_main_previous_scalar_, spv::NoPrecision);
spv::Id result = builder_->createBinOp(spv::OpFMul, type_float_, a, ps);
builder_->addDecoration(result, spv::DecorationNoContraction);
spv::Id result =
builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, ps);
// Shader Model 3: +0 or denormal * anything = +-0.
id_vector_temp_.clear();
id_vector_temp_.push_back(ps);
return ZeroIfAnyOperandIsZero(
result, GetAbsoluteOperand(a, instr.scalar_operands[0]),
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_));
builder_->createUnaryBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, ps));
}
case ucode::AluScalarOpcode::kMulsPrev2: {
// 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);
// 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.
id_vector_temp_.clear();
id_vector_temp_.push_back(ps);
spv::Id ps_abs = builder_->createBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, id_vector_temp_);
spv::Id ps_abs_neg =
builder_->createUnaryOp(spv::OpFNegate, type_float_, ps_abs);
builder_->addDecoration(ps_abs_neg, spv::DecorationNoContraction);
spv::Id ps_abs = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, ps);
spv::Id ps_abs_neg = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, ps_abs);
condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_, condition,
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
@ -1070,17 +1025,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
instr.scalar_operands[0], 0b0010);
spv::Id b_abs_neg = b;
if (!instr.scalar_operands[0].is_absolute_value) {
id_vector_temp_.clear();
id_vector_temp_.push_back(b_abs_neg);
b_abs_neg =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450FAbs, id_vector_temp_);
b_abs_neg = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450FAbs, b_abs_neg);
}
if (!instr.scalar_operands[0].is_absolute_value ||
!instr.scalar_operands[0].is_negated) {
b_abs_neg =
builder_->createUnaryOp(spv::OpFNegate, type_float_, b_abs_neg);
builder_->addDecoration(b_abs_neg, spv::DecorationNoContraction);
b_abs_neg = builder_->createNoContractionUnaryOp(
spv::OpFNegate, type_float_, b_abs_neg);
}
condition = builder_->createBinOp(
spv::OpLogicalAnd, type_bool_, condition,
@ -1092,47 +1043,34 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
spv::OpLogicalAnd, type_bool_, condition,
builder_->createBinOp(spv::OpFOrdGreaterThan, type_bool_, b,
const_float_0_));
spv::Block& multiply_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock();
SpirvCreateSelectionMerge(merge_block.getId());
spv::Block& pre_multiply_if_block = *builder_->getBuildPoint();
spv::Id product;
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));
// Multiplication case.
spv::Id a = instr.scalar_operands[0].GetComponent(0) !=
instr.scalar_operands[0].GetComponent(1)
? GetOperandComponents(operand_storage[0],
instr.scalar_operands[0], 0b0001)
: b;
product =
builder_->createNoContractionBinOp(spv::OpFMul, type_float_, a, ps);
// Shader Model 3: +0 or denormal * anything = +-0.
product = ZeroIfAnyOperandIsZero(
product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs);
}
spv::Block& head_block = *builder_->getBuildPoint();
multiply_block.addPredecessor(&head_block);
merge_block.addPredecessor(&head_block);
// Multiplication case.
builder_->setBuildPoint(&multiply_block);
spv::Id a = instr.scalar_operands[0].GetComponent(0) !=
instr.scalar_operands[0].GetComponent(1)
? GetOperandComponents(operand_storage[0],
instr.scalar_operands[0], 0b0001)
: b;
spv::Id product = builder_->createBinOp(spv::OpFMul, type_float_, a, ps);
builder_->addDecoration(product, spv::DecorationNoContraction);
// Shader Model 3: +0 or denormal * anything = +-0.
product = ZeroIfAnyOperandIsZero(
product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs);
builder_->createBranch(&merge_block);
// Merge case - choose between the product and -FLT_MAX.
builder_->setBuildPoint(&merge_block);
spv::Block& multiply_end_block = *builder_->getBuildPoint();
multiply_if.makeEndIf();
// Merge - choose between the product and -FLT_MAX.
{
std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
type_float_, spv::OpPhi);
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(head_block.getId());
phi_op->addIdOperand(pre_multiply_if_block.getId());
spv::Id phi_result = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
return phi_result;
@ -1151,26 +1089,21 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
// maxasf: a0 = (int)clamp(floor(src0.a), -256.0, 255.0)
spv::Id maxa_address;
if (instr.scalar_opcode == ucode::AluScalarOpcode::kMaxAs) {
maxa_address = builder_->createBinOp(
maxa_address = builder_->createNoContractionBinOp(
spv::OpFAdd, type_float_, a, builder_->makeFloatConstant(0.5f));
builder_->addDecoration(maxa_address, spv::DecorationNoContraction);
} else {
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_->createUnaryOp(
spv::OpConvertFToS, type_int_,
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_)),
builder_->createTriBuiltinCall(
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_);
}
if (a == b) {
@ -1208,18 +1141,16 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kSqrt:
case ucode::AluScalarOpcode::kSin:
case ucode::AluScalarOpcode::kCos:
id_vector_temp_.clear();
id_vector_temp_.push_back(GetOperandComponents(
operand_storage[0], instr.scalar_operands[0], 0b0001));
return builder_->createBuiltinCall(
return builder_->createUnaryBuiltinCall(
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: {
id_vector_temp_.clear();
id_vector_temp_.push_back(GetOperandComponents(
operand_storage[0], instr.scalar_operands[0], 0b0001));
spv::Id result = builder_->createBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450Log2, id_vector_temp_);
spv::Id result = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450Log2,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
return builder_->createTriOp(
spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1227,11 +1158,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(-FLT_MAX), result);
}
case ucode::AluScalarOpcode::kRcpc: {
spv::Id result = builder_->createBinOp(
spv::Id result = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
result = builder_->createTriOp(
spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1244,11 +1174,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(FLT_MAX), result);
}
case ucode::AluScalarOpcode::kRcpf: {
spv::Id result = builder_->createBinOp(
spv::Id result = builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
result = builder_->createTriOp(
spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1265,20 +1194,16 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
return builder_->createUnaryOp(spv::OpBitcast, type_float_, result);
}
case ucode::AluScalarOpcode::kRcp: {
spv::Id result = builder_->createBinOp(
return builder_->createNoContractionBinOp(
spv::OpFDiv, type_float_, const_float_1_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluScalarOpcode::kRsqc: {
id_vector_temp_.clear();
id_vector_temp_.push_back(GetOperandComponents(
operand_storage[0], instr.scalar_operands[0], 0b0001));
spv::Id result =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450InverseSqrt, id_vector_temp_);
spv::Id result = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450InverseSqrt,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
result = builder_->createTriOp(
spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1291,12 +1216,10 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
builder_->makeFloatConstant(FLT_MAX), result);
}
case ucode::AluScalarOpcode::kRsqf: {
id_vector_temp_.clear();
id_vector_temp_.push_back(GetOperandComponents(
operand_storage[0], instr.scalar_operands[0], 0b0001));
spv::Id result =
builder_->createBuiltinCall(type_float_, ext_inst_glsl_std_450_,
GLSLstd450InverseSqrt, id_vector_temp_);
spv::Id result = builder_->createUnaryBuiltinCall(
type_float_, ext_inst_glsl_std_450_, GLSLstd450InverseSqrt,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001));
result = builder_->createTriOp(
spv::OpSelect, type_float_,
builder_->createBinOp(spv::OpFOrdEqual, type_bool_, result,
@ -1343,12 +1266,11 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
const_float_1_, a));
}
case ucode::AluScalarOpcode::kSetpPop: {
spv::Id a_minus_1 = builder_->createBinOp(
spv::Id a_minus_1 = builder_->createNoContractionBinOp(
spv::OpFSub, type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001),
const_float_1_);
builder_->addDecoration(a_minus_1, spv::DecorationNoContraction);
spv::Id predicate = builder_->createBinOp(
spv::OpFOrdLessThanEqual, type_bool_, a_minus_1, const_float_0_);
builder_->createStore(predicate, var_main_predicate_);
@ -1376,30 +1298,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kKillsGe:
case ucode::AluScalarOpcode::kKillsNe:
case ucode::AluScalarOpcode::kKillsOne: {
// Selection merge must be the penultimate instruction in the block, check
// the condition before it.
spv::Id condition = builder_->createBinOp(
KillPixel(builder_->createBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_bool_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001),
instr.scalar_opcode == ucode::AluScalarOpcode::kKillsOne
? const_float_1_
: 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);
: const_float_0_));
return const_float_0_;
}
@ -1409,9 +1314,8 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
operand_storage[0], instr.scalar_operands[0], 0b0001);
spv::Id operand_1 = GetOperandComponents(
operand_storage[1], instr.scalar_operands[1], 0b0001);
spv::Id result =
builder_->createBinOp(spv::OpFMul, type_float_, operand_0, operand_1);
builder_->addDecoration(result, spv::DecorationNoContraction);
spv::Id result = builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, operand_0, operand_1);
if (!(instr.scalar_operands[0].GetIdenticalComponents(
instr.scalar_operands[1]) &
0b0001)) {
@ -1426,14 +1330,12 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
case ucode::AluScalarOpcode::kAddsc1:
case ucode::AluScalarOpcode::kSubsc0:
case ucode::AluScalarOpcode::kSubsc1: {
spv::Id result = builder_->createBinOp(
return builder_->createNoContractionBinOp(
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_float_,
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
0b0001),
GetOperandComponents(operand_storage[1], instr.scalar_operands[1],
0b0001));
builder_->addDecoration(result, spv::DecorationNoContraction);
return result;
}
case ucode::AluScalarOpcode::kRetainPrev:

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff