[SPIR-V] Vertex index writing to r0.x

This commit is contained in:
Triang3l 2020-11-03 23:31:52 +03:00
parent 6030a4cf72
commit 8665fa7517
4 changed files with 252 additions and 77 deletions

View File

@ -10,12 +10,14 @@
#include "xenia/gpu/spirv_shader_translator.h" #include "xenia/gpu/spirv_shader_translator.h"
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "third_party/glslang/SPIRV/GLSL.std.450.h" #include "third_party/glslang/SPIRV/GLSL.std.450.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/math.h"
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -140,6 +142,45 @@ void SpirvShaderTranslator::StartTranslation() {
const_float2_0_1_ = const_float2_0_1_ =
builder_->makeCompositeConstant(type_float2_, id_vector_temp_); builder_->makeCompositeConstant(type_float2_, id_vector_temp_);
// Common uniform buffer - system constants.
struct SystemConstant {
const char* name;
size_t offset;
spv::Id type;
};
const SystemConstant system_constants[] = {
{"vertex_index_endian", offsetof(SystemConstants, vertex_index_endian),
type_uint_},
{"vertex_base_index", offsetof(SystemConstants, vertex_base_index),
type_int_},
};
id_vector_temp_.clear();
id_vector_temp_.reserve(xe::countof(system_constants));
for (size_t i = 0; i < xe::countof(system_constants); ++i) {
id_vector_temp_.push_back(system_constants[i].type);
}
spv::Id type_system_constants =
builder_->makeStructType(id_vector_temp_, "XeSystemConstants");
for (size_t i = 0; i < xe::countof(system_constants); ++i) {
const SystemConstant& system_constant = system_constants[i];
builder_->addMemberName(type_system_constants, static_cast<unsigned int>(i),
system_constant.name);
builder_->addMemberDecoration(
type_system_constants, static_cast<unsigned int>(i),
spv::DecorationOffset, int(system_constant.offset));
}
builder_->addDecoration(type_system_constants, spv::DecorationBlock);
uniform_system_constants_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassUniform, type_system_constants,
"xe_uniform_system_constants");
builder_->addDecoration(uniform_system_constants_,
spv::DecorationDescriptorSet,
kDescriptorSetSystemConstants);
builder_->addDecoration(uniform_system_constants_, spv::DecorationBinding, 0);
if (features_.spirv_version >= spv::Spv_1_4) {
main_interface_.push_back(uniform_system_constants_);
}
// Common uniform buffer - float constants. // Common uniform buffer - float constants.
uint32_t float_constant_count = constant_register_map().float_count; uint32_t float_constant_count = constant_register_map().float_count;
if (float_constant_count) { if (float_constant_count) {
@ -307,15 +348,8 @@ void SpirvShaderTranslator::StartTranslation() {
main_switch_header_ = builder_->getBuildPoint(); main_switch_header_ = builder_->getBuildPoint();
main_switch_merge_ = main_switch_merge_ =
new spv::Block(builder_->getUniqueId(), *function_main_); new spv::Block(builder_->getUniqueId(), *function_main_);
{ SpirvCreateSelectionMerge(main_switch_merge_->getId(),
std::unique_ptr<spv::Instruction> main_switch_selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
main_switch_selection_merge_op->addIdOperand(main_switch_merge_->getId());
main_switch_selection_merge_op->addImmediateOperand(
spv::SelectionControlDontFlattenMask); spv::SelectionControlDontFlattenMask);
builder_->getBuildPoint()->addInstruction(
std::move(main_switch_selection_merge_op));
}
main_switch_op_ = std::make_unique<spv::Instruction>(spv::OpSwitch); main_switch_op_ = std::make_unique<spv::Instruction>(spv::OpSwitch);
main_switch_op_->addIdOperand(main_loop_pc_current); main_switch_op_->addIdOperand(main_loop_pc_current);
main_switch_op_->addIdOperand(main_switch_merge_->getId()); main_switch_op_->addIdOperand(main_switch_merge_->getId());
@ -564,13 +598,7 @@ void SpirvShaderTranslator::ProcessLoopStartInstruction(
spv::OpIEqual, type_bool_, loop_count_new, const_uint_0_); spv::OpIEqual, type_bool_, loop_count_new, const_uint_0_);
spv::Block& skip_block = builder_->makeNewBlock(); spv::Block& skip_block = builder_->makeNewBlock();
spv::Block& body_block = builder_->makeNewBlock(); spv::Block& body_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(body_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(body_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
head_block.addInstruction(std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op = std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional); std::make_unique<spv::Instruction>(spv::OpBranchConditional);
@ -632,13 +660,7 @@ void SpirvShaderTranslator::ProcessLoopEndInstruction(
spv::Block& body_block = *builder_->getBuildPoint(); spv::Block& body_block = *builder_->getBuildPoint();
spv::Block& continue_block = builder_->makeNewBlock(); spv::Block& continue_block = builder_->makeNewBlock();
spv::Block& break_block = builder_->makeNewBlock(); spv::Block& break_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(break_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(break_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
body_block.addInstruction(std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op = std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional); std::make_unique<spv::Instruction>(spv::OpBranchConditional);
@ -841,6 +863,53 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderInMain() {
var_main_point_size_edge_flag_kill_vertex_ = builder_->createVariable( var_main_point_size_edge_flag_kill_vertex_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassFunction, type_float3_, spv::NoPrecision, spv::StorageClassFunction, type_float3_,
"xe_var_point_size_edge_flag_kill_vertex"); "xe_var_point_size_edge_flag_kill_vertex");
// Load the vertex index or the tessellation parameters.
if (register_count()) {
// TODO(Triang3l): Barycentric coordinates and patch index.
if (IsSpirvVertexShader()) {
// TODO(Triang3l): Fetch the vertex index from the shared memory when
// fullDrawIndexUint32 isn't available and the index is 32-bit and needs
// endian swap.
// TODO(Triang3l): Close line loop primitive.
// Load the unswapped index as uint for swapping.
spv::Id vertex_index = builder_->createUnaryOp(
spv::OpBitcast, type_uint_,
builder_->createLoad(input_vertex_index_, spv::NoPrecision));
// Endian-swap the index and convert to int.
id_vector_temp_.clear();
id_vector_temp_.push_back(
builder_->makeIntConstant(kSystemConstantIndexVertexIndexEndian));
spv::Id vertex_index_endian =
builder_->createLoad(builder_->createAccessChain(
spv::StorageClassUniform,
uniform_system_constants_, id_vector_temp_),
spv::NoPrecision);
vertex_index = builder_->createUnaryOp(
spv::OpBitcast, type_int_,
EndianSwap32Uint(vertex_index, vertex_index_endian));
// Add the base to the index.
id_vector_temp_.clear();
id_vector_temp_.push_back(
builder_->makeIntConstant(kSystemConstantIndexVertexBaseIndex));
vertex_index = builder_->createBinOp(
spv::OpIAdd, type_int_, vertex_index,
builder_->createLoad(builder_->createAccessChain(
spv::StorageClassUniform,
uniform_system_constants_, id_vector_temp_),
spv::NoPrecision));
// Write the index to r0.x as float.
id_vector_temp_.clear();
id_vector_temp_.reserve(2);
id_vector_temp_.push_back(const_int_0_);
id_vector_temp_.push_back(const_int_0_);
builder_->createStore(
builder_->createUnaryOp(spv::OpConvertSToF, type_float_,
vertex_index),
builder_->createAccessChain(spv::StorageClassFunction,
var_main_registers_, id_vector_temp_));
}
}
} }
void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {} void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {}
@ -918,13 +987,7 @@ void SpirvShaderTranslator::UpdateExecConditionals(
spv::Function& function = builder_->getBuildPoint()->getParent(); spv::Function& function = builder_->getBuildPoint()->getParent();
cf_exec_conditional_merge_ = cf_exec_conditional_merge_ =
new spv::Block(builder_->getUniqueId(), function); new spv::Block(builder_->getUniqueId(), function);
{ SpirvCreateSelectionMerge(cf_exec_conditional_merge_->getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(cf_exec_conditional_merge_->getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(std::move(selection_merge_op));
}
spv::Block& inner_block = builder_->makeNewBlock(); spv::Block& inner_block = builder_->makeNewBlock();
builder_->createConditionalBranch( builder_->createConditionalBranch(
condition_id, condition ? &inner_block : cf_exec_conditional_merge_, condition_id, condition ? &inner_block : cf_exec_conditional_merge_,
@ -963,13 +1026,7 @@ void SpirvShaderTranslator::UpdateInstructionPredication(bool predicated,
builder_->createLoad(var_main_predicate_, spv::NoPrecision); builder_->createLoad(var_main_predicate_, spv::NoPrecision);
spv::Block& predicated_block = builder_->makeNewBlock(); spv::Block& predicated_block = builder_->makeNewBlock();
cf_instruction_predicate_merge_ = &builder_->makeNewBlock(); cf_instruction_predicate_merge_ = &builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(cf_instruction_predicate_merge_->getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(cf_instruction_predicate_merge_->getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(std::move(selection_merge_op));
}
builder_->createConditionalBranch( builder_->createConditionalBranch(
predicate_id, predicate_id,
condition ? &predicated_block : cf_instruction_predicate_merge_, condition ? &predicated_block : cf_instruction_predicate_merge_,
@ -1426,5 +1483,119 @@ void SpirvShaderTranslator::StoreResult(const InstructionResult& result,
builder_->createStore(value_to_store, target_pointer); builder_->createStore(value_to_store, target_pointer);
} }
spv::Id SpirvShaderTranslator::EndianSwap32Uint(spv::Id value, spv::Id endian) {
spv::Id type = builder_->getTypeId(value);
spv::Id const_uint_8_scalar = builder_->makeUintConstant(8);
spv::Id const_uint_00ff00ff_scalar = builder_->makeUintConstant(0x00FF00FF);
spv::Id const_uint_16_scalar = builder_->makeUintConstant(16);
spv::Id const_uint_8_typed, const_uint_00ff00ff_typed, const_uint_16_typed;
int num_components = builder_->getNumTypeComponents(type);
if (num_components > 1) {
id_vector_temp_.reserve(num_components);
id_vector_temp_.clear();
id_vector_temp_.insert(id_vector_temp_.cend(), num_components,
const_uint_8_scalar);
const_uint_8_typed = builder_->makeCompositeConstant(type, id_vector_temp_);
id_vector_temp_.clear();
id_vector_temp_.insert(id_vector_temp_.cend(), num_components,
const_uint_00ff00ff_scalar);
const_uint_00ff00ff_typed =
builder_->makeCompositeConstant(type, id_vector_temp_);
id_vector_temp_.clear();
id_vector_temp_.insert(id_vector_temp_.cend(), num_components,
const_uint_16_scalar);
const_uint_16_typed =
builder_->makeCompositeConstant(type, id_vector_temp_);
} else {
const_uint_8_typed = const_uint_8_scalar;
const_uint_00ff00ff_typed = const_uint_00ff00ff_scalar;
const_uint_16_typed = const_uint_16_scalar;
}
// 8-in-16 or one half of 8-in-32 (doing 8-in-16 swap).
spv::Id is_8in16 = builder_->createBinOp(
spv::OpIEqual, type_bool_, endian,
builder_->makeUintConstant(
static_cast<unsigned int>(xenos::Endian::k8in16)));
spv::Id is_8in32 = builder_->createBinOp(
spv::OpIEqual, type_bool_, endian,
builder_->makeUintConstant(
static_cast<unsigned int>(xenos::Endian::k8in32)));
spv::Id is_8in16_or_8in32 =
builder_->createBinOp(spv::OpLogicalAnd, type_bool_, is_8in16, is_8in32);
spv::Block& block_pre_8in16 = *builder_->getBuildPoint();
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_->createConditionalBranch(is_8in16_or_8in32, &block_8in16,
&block_8in16_merge);
builder_->setBuildPoint(&block_8in16);
spv::Id swapped_8in16 = builder_->createBinOp(
spv::OpBitwiseOr, type,
builder_->createBinOp(
spv::OpBitwiseAnd, type,
builder_->createBinOp(spv::OpShiftRightLogical, type, value,
const_uint_8_typed),
const_uint_00ff00ff_typed),
builder_->createBinOp(
spv::OpShiftLeftLogical, type,
builder_->createBinOp(spv::OpBitwiseAnd, type, value,
const_uint_00ff00ff_typed),
const_uint_8_typed));
builder_->createBranch(&block_8in16_merge);
builder_->setBuildPoint(&block_8in16_merge);
{
std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(), type,
spv::OpPhi);
phi_op->addIdOperand(swapped_8in16);
phi_op->addIdOperand(block_8in16.getId());
phi_op->addIdOperand(value);
phi_op->addIdOperand(block_pre_8in16.getId());
value = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
}
// 16-in-32 or another half of 8-in-32 (doing 16-in-32 swap).
spv::Id is_16in32 = builder_->createBinOp(
spv::OpIEqual, type_bool_, endian,
builder_->makeUintConstant(
static_cast<unsigned int>(xenos::Endian::k16in32)));
spv::Id is_8in32_or_16in32 =
builder_->createBinOp(spv::OpLogicalAnd, type_bool_, is_8in32, is_16in32);
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_->createConditionalBranch(is_8in32_or_16in32, &block_16in32,
&block_16in32_merge);
builder_->setBuildPoint(&block_16in32);
id_vector_temp_.clear();
id_vector_temp_.reserve(4);
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_);
builder_->createBranch(&block_16in32_merge);
builder_->setBuildPoint(&block_16in32_merge);
{
std::unique_ptr<spv::Instruction> phi_op =
std::make_unique<spv::Instruction>(builder_->getUniqueId(), type,
spv::OpPhi);
phi_op->addIdOperand(swapped_16in32);
phi_op->addIdOperand(block_16in32.getId());
phi_op->addIdOperand(value);
phi_op->addIdOperand(block_pre_16in32.getId());
value = phi_op->getResultId();
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
}
return value;
}
} // namespace gpu } // namespace gpu
} // namespace xe } // namespace xe

View File

@ -17,6 +17,7 @@
#include "third_party/glslang/SPIRV/SpvBuilder.h" #include "third_party/glslang/SPIRV/SpvBuilder.h"
#include "xenia/gpu/shader_translator.h" #include "xenia/gpu/shader_translator.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_provider.h"
namespace xe { namespace xe {
@ -24,6 +25,19 @@ namespace gpu {
class SpirvShaderTranslator : public ShaderTranslator { class SpirvShaderTranslator : public ShaderTranslator {
public: public:
// IF SYSTEM CONSTANTS ARE CHANGED OR ADDED, THE FOLLOWING MUST BE UPDATED:
// - SystemConstantIndex enum.
// - Structure members in BeginTranslation.
struct SystemConstants {
xenos::Endian vertex_index_endian;
int32_t vertex_base_index;
};
// The minimum limit for maxPerStageDescriptorStorageBuffers is 4, and for
// maxStorageBufferRange it's 128 MB. These are the values of those limits on
// Arm Mali as of November 2020. Xenia needs 512 MB shared memory to be bound,
// therefore SSBOs must only be used for shared memory - all other storage
// resources must be images or texel buffers.
enum DescriptorSet : uint32_t { enum DescriptorSet : uint32_t {
// In order of update frequency. // In order of update frequency.
// Very frequently changed, especially for UI draws, and for models drawn in // Very frequently changed, especially for UI draws, and for models drawn in
@ -78,6 +92,17 @@ class SpirvShaderTranslator : public ShaderTranslator {
void ProcessAluInstruction(const ParsedAluInstruction& instr) override; void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
private: private:
// Builder helpers.
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));
}
// TODO(Triang3l): Depth-only pixel shader. // TODO(Triang3l): Depth-only pixel shader.
bool IsSpirvVertexOrTessEvalShader() const { return is_vertex_shader(); } bool IsSpirvVertexOrTessEvalShader() const { return is_vertex_shader(); }
bool IsSpirvVertexShader() const { bool IsSpirvVertexShader() const {
@ -176,6 +201,9 @@ class SpirvShaderTranslator : public ShaderTranslator {
spv::Id ProcessScalarAluOperation(const ParsedAluInstruction& instr, spv::Id ProcessScalarAluOperation(const ParsedAluInstruction& instr,
bool& predicate_written); bool& predicate_written);
// Perform endian swap of a uint scalar or vector.
spv::Id EndianSwap32Uint(spv::Id value, spv::Id endian);
Features features_; Features features_;
std::unique_ptr<spv::Builder> builder_; std::unique_ptr<spv::Builder> builder_;
@ -242,6 +270,11 @@ class SpirvShaderTranslator : public ShaderTranslator {
// components. // components.
spv::Id const_float2_0_1_; spv::Id const_float2_0_1_;
enum SystemConstantIndex : unsigned int {
kSystemConstantIndexVertexIndexEndian,
kSystemConstantIndexVertexBaseIndex,
};
spv::Id uniform_system_constants_;
spv::Id uniform_float_constants_; spv::Id uniform_float_constants_;
spv::Id uniform_bool_loop_constants_; spv::Id uniform_bool_loop_constants_;

View File

@ -580,14 +580,7 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
spv::Block& ma_yx_block = builder_->makeNewBlock(); spv::Block& ma_yx_block = builder_->makeNewBlock();
spv::Block* ma_merge_block = spv::Block* ma_merge_block =
new spv::Block(builder_->getUniqueId(), function); new spv::Block(builder_->getUniqueId(), function);
{ SpirvCreateSelectionMerge(ma_merge_block->getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(ma_merge_block->getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(
std::move(selection_merge_op));
}
builder_->createConditionalBranch(ma_z_condition, &ma_z_block, builder_->createConditionalBranch(ma_z_condition, &ma_z_block,
&ma_yx_block); &ma_yx_block);
@ -627,14 +620,7 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
spv::Block& ma_y_block = builder_->makeNewBlock(); spv::Block& ma_y_block = builder_->makeNewBlock();
spv::Block& ma_x_block = builder_->makeNewBlock(); spv::Block& ma_x_block = builder_->makeNewBlock();
spv::Block& ma_yx_merge_block = builder_->makeNewBlock(); spv::Block& ma_yx_merge_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(ma_yx_merge_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(ma_yx_merge_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(
std::move(selection_merge_op));
}
builder_->createConditionalBranch(ma_y_condition, &ma_y_block, builder_->createConditionalBranch(ma_y_condition, &ma_y_block,
&ma_x_block); &ma_x_block);
@ -849,14 +835,7 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
0b1111))); 0b1111)));
spv::Block& kill_block = builder_->makeNewBlock(); spv::Block& kill_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock(); spv::Block& merge_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(merge_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(merge_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(
std::move(selection_merge_op));
}
builder_->createConditionalBranch(condition, &kill_block, &merge_block); builder_->createConditionalBranch(condition, &kill_block, &merge_block);
builder_->setBuildPoint(&kill_block); builder_->setBuildPoint(&kill_block);
// TODO(Triang3l): Demote to helper invocation to keep derivatives if // TODO(Triang3l): Demote to helper invocation to keep derivatives if
@ -1117,14 +1096,7 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
const_float_0_)); const_float_0_));
spv::Block& multiply_block = builder_->makeNewBlock(); spv::Block& multiply_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock(); spv::Block& merge_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(merge_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(merge_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(
std::move(selection_merge_op));
}
{ {
std::unique_ptr<spv::Instruction> branch_conditional_op = std::unique_ptr<spv::Instruction> branch_conditional_op =
std::make_unique<spv::Instruction>(spv::OpBranchConditional); std::make_unique<spv::Instruction>(spv::OpBranchConditional);
@ -1418,14 +1390,7 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
: const_float_0_); : const_float_0_);
spv::Block& kill_block = builder_->makeNewBlock(); spv::Block& kill_block = builder_->makeNewBlock();
spv::Block& merge_block = builder_->makeNewBlock(); spv::Block& merge_block = builder_->makeNewBlock();
{ SpirvCreateSelectionMerge(merge_block.getId());
std::unique_ptr<spv::Instruction> selection_merge_op =
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
selection_merge_op->addIdOperand(merge_block.getId());
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
builder_->getBuildPoint()->addInstruction(
std::move(selection_merge_op));
}
builder_->createConditionalBranch(condition, &kill_block, &merge_block); builder_->createConditionalBranch(condition, &kill_block, &merge_block);
builder_->setBuildPoint(&kill_block); builder_->setBuildPoint(&kill_block);
// TODO(Triang3l): Demote to helper invocation to keep derivatives if // TODO(Triang3l): Demote to helper invocation to keep derivatives if

View File

@ -287,6 +287,12 @@ bool VulkanProvider::Initialize() {
// Get physical device features and check if the needed ones are supported. // Get physical device features and check if the needed ones are supported.
ifn_.vkGetPhysicalDeviceFeatures(physical_device_current, ifn_.vkGetPhysicalDeviceFeatures(physical_device_current,
&device_features_); &device_features_);
// Passing indices directly from guest memory, where they are big-endian; a
// workaround using fetch from shared memory for 32-bit indices that need
// swapping isn't implemented yet. Not supported only Qualcomm Adreno 4xx.
if (!device_features_.fullDrawIndexUint32) {
continue;
}
// TODO(Triang3l): Make geometry shaders optional by providing compute // TODO(Triang3l): Make geometry shaders optional by providing compute
// shader fallback (though that would require vertex shader stores). // shader fallback (though that would require vertex shader stores).
if (!device_features_.geometryShader) { if (!device_features_.geometryShader) {