SPIR-V: Handle conversion of integer vertex input

This commit is contained in:
Dr. Chat 2016-09-07 11:13:53 -05:00
parent 1757411aa8
commit 9457c63a64
3 changed files with 76 additions and 20 deletions

View File

@ -64,10 +64,12 @@ void SpirvShaderTranslator::StartTranslation() {
float_type_ = b.makeFloatType(32); float_type_ = b.makeFloatType(32);
int_type_ = b.makeIntType(32); int_type_ = b.makeIntType(32);
uint_type_ = b.makeUintType(32); uint_type_ = b.makeUintType(32);
vec2_int_type_ = b.makeVectorType(int_type_, 2);
vec2_uint_type_ = b.makeVectorType(uint_type_, 2); vec2_uint_type_ = b.makeVectorType(uint_type_, 2);
vec2_float_type_ = b.makeVectorType(float_type_, 2); vec2_float_type_ = b.makeVectorType(float_type_, 2);
vec3_float_type_ = b.makeVectorType(float_type_, 3); vec3_float_type_ = b.makeVectorType(float_type_, 3);
vec4_float_type_ = b.makeVectorType(float_type_, 4); vec4_float_type_ = b.makeVectorType(float_type_, 4);
vec4_int_type_ = b.makeVectorType(int_type_, 4);
vec4_uint_type_ = b.makeVectorType(uint_type_, 4); vec4_uint_type_ = b.makeVectorType(uint_type_, 4);
vec2_bool_type_ = b.makeVectorType(bool_type_, 2); vec2_bool_type_ = b.makeVectorType(bool_type_, 2);
vec3_bool_type_ = b.makeVectorType(bool_type_, 3); vec3_bool_type_ = b.makeVectorType(bool_type_, 3);
@ -222,6 +224,7 @@ void SpirvShaderTranslator::StartTranslation() {
for (const auto& attrib : binding.attributes) { for (const auto& attrib : binding.attributes) {
Id attrib_type = 0; Id attrib_type = 0;
bool is_signed = attrib.fetch_instr.attributes.is_signed; 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) { switch (attrib.fetch_instr.attributes.data_format) {
case VertexFormat::k_32: case VertexFormat::k_32:
case VertexFormat::k_32_FLOAT: case VertexFormat::k_32_FLOAT:
@ -229,6 +232,10 @@ void SpirvShaderTranslator::StartTranslation() {
break; break;
case VertexFormat::k_16_16: case VertexFormat::k_16_16:
case VertexFormat::k_32_32: 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_16_16_FLOAT:
case VertexFormat::k_32_32_FLOAT: case VertexFormat::k_32_32_FLOAT:
attrib_type = vec2_float_type_; attrib_type = vec2_float_type_;
@ -236,10 +243,16 @@ void SpirvShaderTranslator::StartTranslation() {
case VertexFormat::k_32_32_32_FLOAT: case VertexFormat::k_32_32_32_FLOAT:
attrib_type = vec3_float_type_; attrib_type = vec3_float_type_;
break; break;
case VertexFormat::k_8_8_8_8:
case VertexFormat::k_2_10_10_10: 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_16_16_16_16:
case VertexFormat::k_32_32_32_32: 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_16_16_16_16_FLOAT:
case VertexFormat::k_32_32_32_32_FLOAT: case VertexFormat::k_32_32_32_32_FLOAT:
attrib_type = vec4_float_type_; attrib_type = vec4_float_type_;
@ -970,8 +983,10 @@ spv::Id SpirvShaderTranslator::BitfieldExtract(spv::Id result_type,
spv::Id base_type = b.getTypeId(base); spv::Id base_type = b.getTypeId(base);
// <-- 32 - (offset + count) ------ [bits] -?- // <-- 32 - (offset + count) ------ [bits] -?-
if (32 - (offset + count) > 0) {
base = b.createBinOp(spv::Op::OpShiftLeftLogical, base_type, base, base = b.createBinOp(spv::Op::OpShiftLeftLogical, base_type, base,
b.makeUintConstant(32 - (offset + count))); b.makeUintConstant(32 - (offset + count)));
}
// [bits] -?-?-?--------------------------- // [bits] -?-?-?---------------------------
auto op = is_signed ? spv::Op::OpShiftRightArithmetic auto op = is_signed ? spv::Op::OpShiftRightArithmetic
: spv::Op::OpShiftRightLogical; : spv::Op::OpShiftRightLogical;
@ -1115,9 +1130,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
b.makeUintConstant(11)); b.makeUintConstant(11));
*/ */
// Workaround until NVIDIA fixes their compiler :| // Workaround until NVIDIA fixes their compiler :|
components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 10); components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 11);
components[1] = BitfieldExtract(comp_type, vertex, is_signed, 10, 11); components[1] = BitfieldExtract(comp_type, vertex, is_signed, 11, 11);
components[2] = BitfieldExtract(comp_type, vertex, is_signed, 21, 11); components[2] = BitfieldExtract(comp_type, vertex, is_signed, 22, 10);
op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -1152,9 +1167,9 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
b.makeUintConstant(10)); b.makeUintConstant(10));
*/ */
// Workaround until NVIDIA fixes their compiler :| // Workaround until NVIDIA fixes their compiler :|
components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 11); components[0] = BitfieldExtract(comp_type, vertex, is_signed, 00, 10);
components[1] = BitfieldExtract(comp_type, vertex, is_signed, 11, 11); components[1] = BitfieldExtract(comp_type, vertex, is_signed, 10, 11);
components[2] = BitfieldExtract(comp_type, vertex, is_signed, 22, 10); components[2] = BitfieldExtract(comp_type, vertex, is_signed, 21, 11);
op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -1171,6 +1186,30 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
} break; } 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, vertex = b.createTriOp(spv::Op::OpSelect, b.getTypeId(vertex), cond, vertex,
alt_vertex); alt_vertex);
StoreToResult(vertex, instr.result); StoreToResult(vertex, instr.result);

View File

@ -126,9 +126,9 @@ class SpirvShaderTranslator : public ShaderTranslator {
// Types. // Types.
spv::Id float_type_ = 0, bool_type_ = 0, int_type_ = 0, uint_type_ = 0; 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 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 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, spv::Id image_1d_type_ = 0, image_2d_type_ = 0, image_3d_type_ = 0,
image_cube_type_ = 0; image_cube_type_ = 0;

View File

@ -891,8 +891,13 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState(
bool is_integer = attrib.fetch_instr.attributes.is_integer; bool is_integer = attrib.fetch_instr.attributes.is_integer;
switch (attrib.fetch_instr.attributes.data_format) { switch (attrib.fetch_instr.attributes.data_format) {
case VertexFormat::k_8_8_8_8: case VertexFormat::k_8_8_8_8:
if (is_integer) {
vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R8G8B8A8_SINT : VK_FORMAT_R8G8B8A8_UINT;
} else {
vertex_attrib_descr.format = vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R8G8B8A8_SNORM : VK_FORMAT_R8G8B8A8_UNORM; is_signed ? VK_FORMAT_R8G8B8A8_SNORM : VK_FORMAT_R8G8B8A8_UNORM;
}
break; break;
case VertexFormat::k_2_10_10_10: case VertexFormat::k_2_10_10_10:
vertex_attrib_descr.format = is_signed vertex_attrib_descr.format = is_signed
@ -910,16 +915,28 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState(
is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT; is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT;
break; break;
case VertexFormat::k_16_16: case VertexFormat::k_16_16:
if (is_integer) {
vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R16G16_SINT : VK_FORMAT_R16G16_UINT;
} else {
vertex_attrib_descr.format = vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R16G16_SNORM : VK_FORMAT_R16G16_UNORM; is_signed ? VK_FORMAT_R16G16_SNORM : VK_FORMAT_R16G16_UNORM;
}
break; break;
case VertexFormat::k_16_16_FLOAT: case VertexFormat::k_16_16_FLOAT:
// assert_true(is_signed); // assert_true(is_signed);
vertex_attrib_descr.format = VK_FORMAT_R16G16_SFLOAT; vertex_attrib_descr.format = VK_FORMAT_R16G16_SFLOAT;
break; break;
case VertexFormat::k_16_16_16_16: case VertexFormat::k_16_16_16_16:
vertex_attrib_descr.format = is_signed ? VK_FORMAT_R16G16B16A16_SNORM 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; : VK_FORMAT_R16G16B16A16_UNORM;
}
break; break;
case VertexFormat::k_16_16_16_16_FLOAT: case VertexFormat::k_16_16_16_16_FLOAT:
// assert_true(is_signed); // assert_true(is_signed);
@ -927,19 +944,19 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState(
break; break;
case VertexFormat::k_32: case VertexFormat::k_32:
// FIXME: Is this a NORM format? // FIXME: Is this a NORM format?
assert_always(); assert_true(is_integer);
vertex_attrib_descr.format = vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT; is_signed ? VK_FORMAT_R32_SINT : VK_FORMAT_R32_UINT;
break; break;
case VertexFormat::k_32_32: case VertexFormat::k_32_32:
// FIXME: Is this a NORM format? // FIXME: Is this a NORM format?
assert_always(); assert_true(is_integer);
vertex_attrib_descr.format = vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R32G32_SINT : VK_FORMAT_R32G32_UINT; is_signed ? VK_FORMAT_R32G32_SINT : VK_FORMAT_R32G32_UINT;
break; break;
case VertexFormat::k_32_32_32_32: case VertexFormat::k_32_32_32_32:
// FIXME: Is this a NORM format? // FIXME: Is this a NORM format?
assert_always(); assert_true(is_integer);
vertex_attrib_descr.format = vertex_attrib_descr.format =
is_signed ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32_UINT; is_signed ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32_UINT;
break; break;