SPIR-V: Use gl_VertexIndex rather than gl_VertexID

Rewrite bits of LoadFromOperand/StoreToResult
This commit is contained in:
Dr. Chat 2016-07-29 11:28:19 -05:00
parent 72d83591e5
commit a547c79b51
2 changed files with 87 additions and 48 deletions

View File

@ -278,22 +278,23 @@ void SpirvShaderTranslator::StartTranslation() {
b.addDecoration(pos_, spv::Decoration::DecorationBuiltIn, b.addDecoration(pos_, spv::Decoration::DecorationBuiltIn,
spv::BuiltIn::BuiltInPosition); spv::BuiltIn::BuiltInPosition);
vertex_id_ = b.createVariable(spv::StorageClass::StorageClassInput, vertex_idx_ = b.createVariable(spv::StorageClass::StorageClassInput,
int_type_, "gl_VertexId"); int_type_, "gl_VertexIndex");
b.addDecoration(vertex_id_, spv::Decoration::DecorationBuiltIn, b.addDecoration(vertex_idx_, spv::Decoration::DecorationBuiltIn,
spv::BuiltIn::BuiltInVertexId); spv::BuiltIn::BuiltInVertexIndex);
interface_ids_.push_back(interpolators_); interface_ids_.push_back(interpolators_);
interface_ids_.push_back(pos_); interface_ids_.push_back(pos_);
interface_ids_.push_back(vertex_id_); interface_ids_.push_back(vertex_idx_);
auto vertex_id = b.createLoad(vertex_id_); auto vertex_idx = b.createLoad(vertex_idx_);
vertex_id = b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, vertex_id); vertex_idx =
b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, vertex_idx);
auto r0_ptr = b.createAccessChain(spv::StorageClass::StorageClassFunction, auto r0_ptr = b.createAccessChain(spv::StorageClass::StorageClassFunction,
registers_ptr_, registers_ptr_,
std::vector<Id>({b.makeUintConstant(0)})); std::vector<Id>({b.makeUintConstant(0)}));
auto r0 = b.createLoad(r0_ptr); auto r0 = b.createLoad(r0_ptr);
r0 = b.createCompositeInsert(vertex_id, r0, vec4_float_type_, r0 = b.createCompositeInsert(vertex_idx, r0, vec4_float_type_,
std::vector<uint32_t>({0})); std::vector<uint32_t>({0}));
b.createStore(r0, r0_ptr); b.createStore(r0, r0_ptr);
} else { } else {
@ -857,7 +858,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
const ParsedVertexFetchInstruction& instr) { const ParsedVertexFetchInstruction& instr) {
auto& b = *builder_; auto& b = *builder_;
assert_true(is_vertex_shader()); assert_true(is_vertex_shader());
assert_not_zero(vertex_id_); assert_not_zero(vertex_idx_);
// Close the open predicated block if this instr isn't predicated or the // Close the open predicated block if this instr isn't predicated or the
// conditions do not match. // conditions do not match.
@ -889,10 +890,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
// Operand 0 is the index // Operand 0 is the index
// Operand 1 is the binding // Operand 1 is the binding
// TODO: Indexed fetch // TODO: Indexed fetch
auto vertex_id = LoadFromOperand(instr.operands[0]); auto vertex_idx = LoadFromOperand(instr.operands[0]);
vertex_id = b.createCompositeExtract(vertex_id, float_type_, 0); vertex_idx = b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, vertex_idx);
vertex_id = b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, vertex_id); auto shader_vertex_idx = b.createLoad(vertex_idx_);
auto shader_vertex_id = b.createLoad(vertex_id_);
// Skip loading if it's an indexed fetch. // Skip loading if it's an indexed fetch.
auto vertex_ptr = vertex_binding_map_[instr.operands[1].storage_index] auto vertex_ptr = vertex_binding_map_[instr.operands[1].storage_index]
@ -1716,6 +1716,7 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
} }
assert_not_zero(dest); assert_not_zero(dest);
assert_true(b.getTypeId(dest) == vec4_float_type_);
if (dest) { if (dest) {
b.createStore(dest, pv_); b.createStore(dest, pv_);
StoreToResult(dest, instr.result); StoreToResult(dest, instr.result);
@ -1741,9 +1742,13 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
auto src = LoadFromOperand(instr.operands[i]); auto src = LoadFromOperand(instr.operands[i]);
// Pull components out of the vector operands and use them as sources. // Pull components out of the vector operands and use them as sources.
if (instr.operands[i].component_count > 1) {
for (int j = 0; j < instr.operands[i].component_count; j++) { for (int j = 0; j < instr.operands[i].component_count; j++) {
sources[x++] = b.createCompositeExtract(src, float_type_, j); sources[x++] = b.createCompositeExtract(src, float_type_, j);
} }
} else {
sources[x++] = src;
}
} }
// Close the open predicated block if this instr isn't predicated or the // Close the open predicated block if this instr isn't predicated or the
@ -2006,15 +2011,17 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_,
spv::GLSLstd450::kInverseSqrt, spv::GLSLstd450::kInverseSqrt,
{sources[0]}); {sources[0]});
auto c = b.createUnaryOp(spv::Op::OpIsInf, bool_type_, dest); auto c1 = b.createUnaryOp(spv::Op::OpIsInf, bool_type_, dest);
auto c2 = b.createUnaryOp(spv::Op::OpIsNan, bool_type_, dest);
auto c = b.createBinOp(spv::Op::OpLogicalOr, bool_type_, c1, c2);
dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, dest = b.createTriOp(spv::Op::OpSelect, float_type_, c,
b.makeFloatConstant(0.f), dest); b.makeFloatConstant(0.f), dest);
} break; } break;
case AluScalarOpcode::kRsq: { case AluScalarOpcode::kRsq: {
// dest = src0 != 0.0 ? inversesqrt(src0) : 0.0; // dest = src0 > 0.0 ? inversesqrt(src0) : 0.0;
auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], auto c = b.createBinOp(spv::Op::OpFOrdLessThanEqual, bool_type_,
b.makeFloatConstant(0.f)); sources[0], b.makeFloatConstant(0.f));
auto d = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, auto d = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_,
spv::GLSLstd450::kInverseSqrt, spv::GLSLstd450::kInverseSqrt,
{sources[0]}); {sources[0]});
@ -2179,6 +2186,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
} }
assert_not_zero(dest); assert_not_zero(dest);
assert_true(b.getTypeId(dest) == float_type_);
if (dest) { if (dest) {
b.createStore(dest, ps_); b.createStore(dest, ps_);
StoreToResult(dest, instr.result); StoreToResult(dest, instr.result);
@ -2272,6 +2280,35 @@ Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
auto storage_value = b.createLoad(storage_pointer); auto storage_value = b.createLoad(storage_pointer);
assert_true(b.getTypeId(storage_value) == vec4_float_type_); assert_true(b.getTypeId(storage_value) == vec4_float_type_);
if (op.component_count == 1) {
// Don't bother handling constant 0/1 fetches, as they're invalid in scalar
// opcodes.
uint32_t index = 0;
switch (op.components[0]) {
case SwizzleSource::kX:
index = 0;
break;
case SwizzleSource::kY:
index = 1;
break;
case SwizzleSource::kZ:
index = 2;
break;
case SwizzleSource::kW:
index = 3;
break;
case SwizzleSource::k0:
assert_always();
break;
case SwizzleSource::k1:
assert_always();
break;
}
storage_value = b.createCompositeExtract(storage_value, float_type_, index);
storage_type = float_type_;
}
if (op.is_absolute_value) { if (op.is_absolute_value) {
storage_value = CreateGlslStd450InstructionCall( storage_value = CreateGlslStd450InstructionCall(
spv::NoPrecision, storage_type, GLSLstd450::kFAbs, {storage_value}); spv::NoPrecision, storage_type, GLSLstd450::kFAbs, {storage_value});
@ -2282,7 +2319,7 @@ Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
} }
// swizzle // swizzle
if (!op.is_standard_swizzle()) { if (op.component_count > 1 && !op.is_standard_swizzle()) {
std::vector<uint32_t> operands; std::vector<uint32_t> operands;
operands.push_back(storage_value); operands.push_back(storage_value);
operands.push_back(b.makeCompositeConstant( operands.push_back(b.makeCompositeConstant(
@ -2427,42 +2464,25 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
b.createAccessChain(storage_class, storage_pointer, storage_offsets); b.createAccessChain(storage_class, storage_pointer, storage_offsets);
} }
bool source_is_scalar = b.isScalar(source_value_id);
bool storage_is_scalar = b.isScalarType(b.getDerefTypeId(storage_pointer));
spv::Id source_type = b.getTypeId(source_value_id);
// Only load from storage if we need it later. // Only load from storage if we need it later.
Id storage_value = 0; Id storage_value = 0;
if (!result.has_all_writes()) { if ((source_is_scalar && !storage_is_scalar) || !result.has_all_writes()) {
storage_value = b.createLoad(storage_pointer); storage_value = b.createLoad(storage_pointer);
} }
// Clamp the input value. // Clamp the input value.
if (result.is_clamped) { if (result.is_clamped) {
source_value_id = CreateGlslStd450InstructionCall( source_value_id = CreateGlslStd450InstructionCall(
spv::NoPrecision, b.getTypeId(source_value_id), spv::NoPrecision, source_type, spv::GLSLstd450::kFClamp,
spv::GLSLstd450::kFClamp,
{source_value_id, b.makeFloatConstant(0.0), b.makeFloatConstant(1.0)}); {source_value_id, b.makeFloatConstant(0.0), b.makeFloatConstant(1.0)});
} }
// Convert to the appropriate type, if needed.
if (b.getTypeId(source_value_id) != storage_type) {
std::vector<Id> constituents;
auto n_el = b.getNumComponents(source_value_id);
auto n_dst = b.getNumTypeComponents(storage_type);
if (n_el != 1) {
std::vector<uint32_t> channels;
for (int i = 0; i < n_dst; i++) {
channels.push_back(i % n_el);
}
source_value_id = b.createRvalueSwizzle(spv::NoPrecision, storage_type,
source_value_id, channels);
} else {
source_value_id =
b.smearScalar(spv::NoPrecision, source_value_id, storage_type);
}
}
// swizzle // swizzle
if (!result.is_standard_swizzle()) { if (!result.is_standard_swizzle() && !source_is_scalar) {
std::vector<uint32_t> operands; std::vector<uint32_t> operands;
operands.push_back(source_value_id); operands.push_back(source_value_id);
operands.push_back(b.makeCompositeConstant( operands.push_back(b.makeCompositeConstant(
@ -2471,6 +2491,7 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
// Components start from left and are duplicated rightwards // Components start from left and are duplicated rightwards
// e.g. count = 1, xxxx / count = 2, xyyy ... // e.g. count = 1, xxxx / count = 2, xyyy ...
uint32_t source_components = b.getNumComponents(source_value_id);
for (int i = 0; i < b.getNumTypeComponents(storage_type); i++) { for (int i = 0; i < b.getNumTypeComponents(storage_type); i++) {
if (!result.write_mask[i]) { if (!result.write_mask[i]) {
// Undefined / don't care. // Undefined / don't care.
@ -2493,10 +2514,10 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
operands.push_back(3); operands.push_back(3);
break; break;
case SwizzleSource::k0: case SwizzleSource::k0:
operands.push_back(4); operands.push_back(source_components + 0);
break; break;
case SwizzleSource::k1: case SwizzleSource::k1:
operands.push_back(5); operands.push_back(source_components + 1);
break; break;
} }
} }
@ -2506,7 +2527,7 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
} }
// write mask // write mask
if (!result.has_all_writes()) { if (!result.has_all_writes() && !source_is_scalar) {
std::vector<uint32_t> operands; std::vector<uint32_t> operands;
operands.push_back(source_value_id); operands.push_back(source_value_id);
operands.push_back(storage_value); operands.push_back(storage_value);
@ -2518,6 +2539,24 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
source_value_id = source_value_id =
b.createOp(spv::Op::OpVectorShuffle, storage_type, operands); b.createOp(spv::Op::OpVectorShuffle, storage_type, operands);
} else if (source_is_scalar && !storage_is_scalar) {
assert_true(result.num_writes() >= 1);
if (result.has_all_writes()) {
source_value_id =
b.smearScalar(spv::NoPrecision, source_value_id, storage_type);
} else {
// Find first enabled component
uint32_t index = 0;
for (uint32_t i = 0; i < 4; i++) {
if (result.write_mask[i]) {
index = i;
break;
}
}
source_value_id = b.createCompositeInsert(source_value_id, storage_value,
storage_type, index);
}
} }
// Perform store into the pointer. // Perform store into the pointer.

View File

@ -135,7 +135,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
spv::Id pos_ = 0; spv::Id pos_ = 0;
spv::Id push_consts_ = 0; spv::Id push_consts_ = 0;
spv::Id interpolators_ = 0; spv::Id interpolators_ = 0;
spv::Id vertex_id_ = 0; spv::Id vertex_idx_ = 0;
spv::Id frag_outputs_ = 0, frag_depth_ = 0; spv::Id frag_outputs_ = 0, frag_depth_ = 0;
spv::Id samplers_ = 0; spv::Id samplers_ = 0;
spv::Id tex_[4] = {0}; // Images {1D, 2D, 3D, Cube} spv::Id tex_[4] = {0}; // Images {1D, 2D, 3D, Cube}