Merge branch 'xenia-project:master' into canary_experimental
This commit is contained in:
commit
37051afcaf
|
@ -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
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
@ -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
Loading…
Reference in New Issue