From ff6d306728629f9dbc12536339d98b66302ad46e Mon Sep 17 00:00:00 2001 From: DrChat Date: Mon, 19 Feb 2018 08:11:31 -0600 Subject: [PATCH] [SPIR-V] Handle 16/16, 16/16/16/16 (float and norm) and 32f --- src/xenia/gpu/spirv_shader_translator.cc | 137 ++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index b1ee2095f..718704047 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -16,6 +16,7 @@ #include #include "xenia/base/logging.h" +#include "xenia/base/math.h" DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation"); DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation"); @@ -242,6 +243,7 @@ void SpirvShaderTranslator::StartTranslation() { // DS 2 binding 0 b.addDecoration(vtx_, spv::Decoration::DecorationDescriptorSet, 2); b.addDecoration(vtx_, spv::Decoration::DecorationBinding, 0); + b.addDecoration(vtx_, spv::Decoration::DecorationNonWritable); // Set up the map from binding -> ssbo index for (const auto& binding : vertex_bindings()) { @@ -1236,15 +1238,137 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( } break; case VertexFormat::k_16_16: { + spv::Id components[1] = {}; + for (uint32_t i = 0; i < 1; i++) { + auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, + b.makeUintConstant(i)); + auto vertex_ptr = b.createAccessChain( + spv::StorageClass::StorageClassUniform, data_ptr, {index}); + auto vertex_data = b.createLoad(vertex_ptr); + + if (instr.attributes.is_integer) { + spv::Id comp[2] = {}; + + bool is_signed = instr.attributes.is_signed; + bool is_integer = instr.attributes.is_integer; + auto comp_type = is_signed ? int_type_ : uint_type_; + + if (is_signed) { + vertex_data = + b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); + } + + comp[0] = BitfieldExtract(comp_type, vertex_data, is_signed, 0, 16); + comp[1] = BitfieldExtract(comp_type, vertex_data, is_signed, 16, 16); + + auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; + for (int i = 0; i < xe::countof(comp); i++) { + comp[i] = b.createUnaryOp(op, float_type_, comp[i]); + } + + components[i] = + b.createCompositeConstruct(vec2_float_type_, {comp[0], comp[1]}); + } else { + spv::GLSLstd450 op; + if (instr.attributes.is_signed) { + op = spv::GLSLstd450::kUnpackSnorm2x16; + } else { + op = spv::GLSLstd450::kUnpackUnorm2x16; + } + + components[i] = CreateGlslStd450InstructionCall( + spv::NoPrecision, vec2_float_type_, op, {vertex_data}); + } + } + + vertex = components[0]; } break; case VertexFormat::k_16_16_16_16: { + spv::Id components[2] = {}; + for (uint32_t i = 0; i < 2; i++) { + auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, + b.makeUintConstant(i)); + auto vertex_ptr = b.createAccessChain( + spv::StorageClass::StorageClassUniform, data_ptr, {index}); + auto vertex_data = b.createLoad(vertex_ptr); + + if (instr.attributes.is_integer) { + spv::Id comp[2] = {}; + + bool is_signed = instr.attributes.is_signed; + bool is_integer = instr.attributes.is_integer; + auto comp_type = is_signed ? int_type_ : uint_type_; + + if (is_signed) { + vertex_data = + b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); + } + + comp[0] = BitfieldExtract(comp_type, vertex_data, is_signed, 0, 16); + comp[1] = BitfieldExtract(comp_type, vertex_data, is_signed, 16, 16); + + auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; + for (int i = 0; i < xe::countof(comp); i++) { + comp[i] = b.createUnaryOp(op, float_type_, comp[i]); + } + + components[i] = + b.createCompositeConstruct(vec2_float_type_, {comp[0], comp[1]}); + } else { + spv::GLSLstd450 op; + if (instr.attributes.is_signed) { + op = spv::GLSLstd450::kUnpackSnorm2x16; + } else { + op = spv::GLSLstd450::kUnpackUnorm2x16; + } + + components[i] = CreateGlslStd450InstructionCall( + spv::NoPrecision, vec2_float_type_, op, {vertex_data}); + } + } + + vertex = b.createConstructor( + spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); } break; case VertexFormat::k_16_16_FLOAT: { + spv::Id components[1] = {}; + for (uint32_t i = 0; i < 1; i++) { + auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, + b.makeUintConstant(i)); + auto vertex_ptr = b.createAccessChain( + spv::StorageClass::StorageClassUniform, data_ptr, {index}); + auto vertex_data = b.createLoad(vertex_ptr); + + assert_true(instr.attributes.is_integer); + assert_true(instr.attributes.is_signed); + components[i] = CreateGlslStd450InstructionCall( + spv::NoPrecision, vec2_float_type_, + spv::GLSLstd450::kUnpackHalf2x16, {vertex_data}); + } + + vertex = components[0]; } break; case VertexFormat::k_16_16_16_16_FLOAT: { + spv::Id components[2] = {}; + for (uint32_t i = 0; i < 2; i++) { + auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, + b.makeUintConstant(i)); + auto vertex_ptr = b.createAccessChain( + spv::StorageClass::StorageClassUniform, data_ptr, {index}); + auto vertex_data = b.createLoad(vertex_ptr); + + assert_true(instr.attributes.is_integer); + assert_true(instr.attributes.is_signed); + components[i] = CreateGlslStd450InstructionCall( + spv::NoPrecision, vec2_float_type_, + spv::GLSLstd450::kUnpackHalf2x16, {vertex_data}); + } + + vertex = b.createConstructor( + spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); } break; case VertexFormat::k_32: { @@ -1263,7 +1387,8 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( components[i] = b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, vertex_data); } else { - components[i] = vertex_data; + components[i] = b.createUnaryOp(spv::Op::OpConvertUToF, float_type_, + vertex_data); } } else { // TODO(DrChat) @@ -1280,6 +1405,11 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( } break; case VertexFormat::k_32_FLOAT: { + auto vertex_ptr = b.createAccessChain( + spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); + auto vertex_data = b.createLoad(vertex_ptr); + + vertex = b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); } break; case VertexFormat::k_32_32_FLOAT: { @@ -1359,6 +1489,11 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( components[2] = BitfieldExtract(comp_type, vertex_data, is_signed, 22, 10); + auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; + for (int i = 0; i < xe::countof(components); i++) { + components[i] = b.createUnaryOp(op, float_type_, components[i]); + } + if (!is_integer) { components[3] = ConvertNormVar(components[3], float_type_, 02, is_signed);