From 9457c63a645df723b422f73a704cb6adf8b779c1 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Wed, 7 Sep 2016 11:13:53 -0500 Subject: [PATCH] SPIR-V: Handle conversion of integer vertex input --- src/xenia/gpu/spirv_shader_translator.cc | 57 ++++++++++++++++++++---- src/xenia/gpu/spirv_shader_translator.h | 4 +- src/xenia/gpu/vulkan/pipeline_cache.cc | 35 +++++++++++---- 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index f3905f8f6..3c5ae404a 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -64,10 +64,12 @@ void SpirvShaderTranslator::StartTranslation() { float_type_ = b.makeFloatType(32); int_type_ = b.makeIntType(32); uint_type_ = b.makeUintType(32); + vec2_int_type_ = b.makeVectorType(int_type_, 2); vec2_uint_type_ = b.makeVectorType(uint_type_, 2); vec2_float_type_ = b.makeVectorType(float_type_, 2); vec3_float_type_ = b.makeVectorType(float_type_, 3); vec4_float_type_ = b.makeVectorType(float_type_, 4); + vec4_int_type_ = b.makeVectorType(int_type_, 4); vec4_uint_type_ = b.makeVectorType(uint_type_, 4); vec2_bool_type_ = b.makeVectorType(bool_type_, 2); vec3_bool_type_ = b.makeVectorType(bool_type_, 3); @@ -222,6 +224,7 @@ void SpirvShaderTranslator::StartTranslation() { for (const auto& attrib : binding.attributes) { Id attrib_type = 0; bool is_signed = attrib.fetch_instr.attributes.is_signed; + bool is_integer = attrib.fetch_instr.attributes.is_integer; switch (attrib.fetch_instr.attributes.data_format) { case VertexFormat::k_32: case VertexFormat::k_32_FLOAT: @@ -229,6 +232,10 @@ void SpirvShaderTranslator::StartTranslation() { break; case VertexFormat::k_16_16: case VertexFormat::k_32_32: + if (is_integer) { + attrib_type = is_signed ? vec2_int_type_ : vec2_uint_type_; + break; + } case VertexFormat::k_16_16_FLOAT: case VertexFormat::k_32_32_FLOAT: attrib_type = vec2_float_type_; @@ -236,10 +243,16 @@ void SpirvShaderTranslator::StartTranslation() { case VertexFormat::k_32_32_32_FLOAT: attrib_type = vec3_float_type_; break; - case VertexFormat::k_8_8_8_8: case VertexFormat::k_2_10_10_10: + attrib_type = vec4_float_type_; + break; + case VertexFormat::k_8_8_8_8: case VertexFormat::k_16_16_16_16: case VertexFormat::k_32_32_32_32: + if (is_integer) { + attrib_type = is_signed ? vec4_int_type_ : vec4_uint_type_; + break; + } case VertexFormat::k_16_16_16_16_FLOAT: case VertexFormat::k_32_32_32_32_FLOAT: attrib_type = vec4_float_type_; @@ -970,8 +983,10 @@ spv::Id SpirvShaderTranslator::BitfieldExtract(spv::Id result_type, spv::Id base_type = b.getTypeId(base); // <-- 32 - (offset + count) ------ [bits] -?- - base = b.createBinOp(spv::Op::OpShiftLeftLogical, base_type, base, - b.makeUintConstant(32 - (offset + count))); + if (32 - (offset + count) > 0) { + base = b.createBinOp(spv::Op::OpShiftLeftLogical, base_type, base, + b.makeUintConstant(32 - (offset + count))); + } // [bits] -?-?-?--------------------------- auto op = is_signed ? spv::Op::OpShiftRightArithmetic : spv::Op::OpShiftRightLogical; @@ -1115,9 +1130,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( b.makeUintConstant(11)); */ // Workaround until NVIDIA fixes their compiler :| - components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 10); - components[1] = BitfieldExtract(comp_type, vertex, is_signed, 10, 11); - components[2] = BitfieldExtract(comp_type, vertex, is_signed, 21, 11); + components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 11); + components[1] = BitfieldExtract(comp_type, vertex, is_signed, 11, 11); + components[2] = BitfieldExtract(comp_type, vertex, is_signed, 22, 10); op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; for (int i = 0; i < 3; i++) { @@ -1152,9 +1167,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( b.makeUintConstant(10)); */ // Workaround until NVIDIA fixes their compiler :| - components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 11); - components[1] = BitfieldExtract(comp_type, vertex, is_signed, 11, 11); - components[2] = BitfieldExtract(comp_type, vertex, is_signed, 22, 10); + components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 10); + components[1] = BitfieldExtract(comp_type, vertex, is_signed, 10, 11); + components[2] = BitfieldExtract(comp_type, vertex, is_signed, 21, 11); op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; for (int i = 0; i < 3; i++) { @@ -1171,6 +1186,30 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction( } break; } + // Convert any integers to floats. + auto scalar_type = b.getScalarTypeId(b.getTypeId(vertex)); + if (scalar_type == int_type_ || scalar_type == uint_type_) { + auto op = scalar_type == int_type_ ? spv::Op::OpConvertSToF + : spv::Op::OpConvertUToF; + spv::Id vtx_type; + switch (vertex_components) { + case 1: + vtx_type = float_type_; + break; + case 2: + vtx_type = vec2_float_type_; + break; + case 3: + vtx_type = vec3_float_type_; + break; + case 4: + vtx_type = vec4_float_type_; + break; + } + + vertex = b.createUnaryOp(op, vtx_type, vertex); + } + vertex = b.createTriOp(spv::Op::OpSelect, b.getTypeId(vertex), cond, vertex, alt_vertex); StoreToResult(vertex, instr.result); diff --git a/src/xenia/gpu/spirv_shader_translator.h b/src/xenia/gpu/spirv_shader_translator.h index 24b0d9823..a6f6fe67c 100644 --- a/src/xenia/gpu/spirv_shader_translator.h +++ b/src/xenia/gpu/spirv_shader_translator.h @@ -126,9 +126,9 @@ class SpirvShaderTranslator : public ShaderTranslator { // Types. spv::Id float_type_ = 0, bool_type_ = 0, int_type_ = 0, uint_type_ = 0; - spv::Id vec2_uint_type_ = 0; + spv::Id vec2_int_type_ = 0, vec2_uint_type_ = 0; spv::Id vec2_float_type_ = 0, vec3_float_type_ = 0, vec4_float_type_ = 0; - spv::Id vec4_uint_type_ = 0; + spv::Id vec4_int_type_ = 0, vec4_uint_type_ = 0; spv::Id vec2_bool_type_ = 0, vec3_bool_type_ = 0, vec4_bool_type_ = 0; spv::Id image_1d_type_ = 0, image_2d_type_ = 0, image_3d_type_ = 0, image_cube_type_ = 0; diff --git a/src/xenia/gpu/vulkan/pipeline_cache.cc b/src/xenia/gpu/vulkan/pipeline_cache.cc index 89b10909d..c07f07e4a 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/pipeline_cache.cc @@ -891,8 +891,13 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState( bool is_integer = attrib.fetch_instr.attributes.is_integer; switch (attrib.fetch_instr.attributes.data_format) { case VertexFormat::k_8_8_8_8: - vertex_attrib_descr.format = - is_signed ? VK_FORMAT_R8G8B8A8_SNORM : VK_FORMAT_R8G8B8A8_UNORM; + if (is_integer) { + vertex_attrib_descr.format = + is_signed ? VK_FORMAT_R8G8B8A8_SINT : VK_FORMAT_R8G8B8A8_UINT; + } else { + vertex_attrib_descr.format = + is_signed ? VK_FORMAT_R8G8B8A8_SNORM : VK_FORMAT_R8G8B8A8_UNORM; + } break; case VertexFormat::k_2_10_10_10: vertex_attrib_descr.format = is_signed @@ -910,16 +915,28 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState( is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT; break; case VertexFormat::k_16_16: - vertex_attrib_descr.format = - is_signed ? VK_FORMAT_R16G16_SNORM : VK_FORMAT_R16G16_UNORM; + if (is_integer) { + vertex_attrib_descr.format = + is_signed ? VK_FORMAT_R16G16_SINT : VK_FORMAT_R16G16_UINT; + } else { + vertex_attrib_descr.format = + is_signed ? VK_FORMAT_R16G16_SNORM : VK_FORMAT_R16G16_UNORM; + } break; case VertexFormat::k_16_16_FLOAT: // assert_true(is_signed); vertex_attrib_descr.format = VK_FORMAT_R16G16_SFLOAT; break; case VertexFormat::k_16_16_16_16: - vertex_attrib_descr.format = is_signed ? VK_FORMAT_R16G16B16A16_SNORM - : VK_FORMAT_R16G16B16A16_UNORM; + if (is_integer) { + vertex_attrib_descr.format = is_signed + ? VK_FORMAT_R16G16B16A16_SINT + : VK_FORMAT_R16G16B16A16_UINT; + } else { + vertex_attrib_descr.format = is_signed + ? VK_FORMAT_R16G16B16A16_SNORM + : VK_FORMAT_R16G16B16A16_UNORM; + } break; case VertexFormat::k_16_16_16_16_FLOAT: // assert_true(is_signed); @@ -927,19 +944,19 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState( break; case VertexFormat::k_32: // FIXME: Is this a NORM format? - assert_always(); + assert_true(is_integer); vertex_attrib_descr.format = is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT; break; case VertexFormat::k_32_32: // FIXME: Is this a NORM format? - assert_always(); + assert_true(is_integer); vertex_attrib_descr.format = is_signed ? VK_FORMAT_R32G32_SINT : VK_FORMAT_R32G32_UINT; break; case VertexFormat::k_32_32_32_32: // FIXME: Is this a NORM format? - assert_always(); + assert_true(is_integer); vertex_attrib_descr.format = is_signed ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32_UINT; break;