From: Alejandro Piñeiro <apinhe...@igalia.com>

From Vulkan 1.0.50 spec, Section 3.30.1. Format Definition:
    VK_FORMAT_R16G16_SFLOAT

    A two-component, 32-bit signed floating-point format that has a
    16-bit R component in bytes 0..1, and a 16-bit G component in
    bytes 2..3.

As vertex data and other inputs has been always expected to be up-converted
from 16-bit to 32-bits. But when we use the 16-bit input in the shader
without any conversion we use 32-bit uint format. (applies also to use of
2/3/4 components)

At skl PRM, vol 07, section FormatConversion, page 445 there is
a table that points that *16*FLOAT formats are converted to FLOAT,
that in that context, is a 32-bit float. This is similar to the
*64*FLOAT formats, that converts 64-bit floats to 32-bit floats.

Unfortunately, while with 64-bit floats we have the alternative to use
*64*PASSTHRU formats, it is not the case with 16-bits.

This issue happens too with 16-bit int surface formats.

As a workaround, if we are using a 16-bit location at the shader, we
use 32-bit uint formats to avoid the conversion, and will fix getting the
proper content later. Note that as we are using 32-bit formats, we
can use formats with less components (example: use *R32* for *R16G16*).

v2: Always use UINT surface format variants. (Topi Pohjolainen)
    Renamed half_inputs_read to inputs_read_16bit (Jason Ekstrand)
    Reword commit log (Jason Ekstrand)
v3: Rebase minor changes (Chema Casanova)

Signed-off-by: Jose Maria Casanova Crespo <jmcasan...@igalia.com>
Signed-off-by: Alejandro Piñeiro <apinhe...@igalia.com>
---
 src/intel/vulkan/genX_pipeline.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index 89cbe293b8..9a60c286cc 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -83,6 +83,31 @@ vertex_element_comp_control(enum isl_format format, unsigned 
comp)
    }
 }
 
+#if GEN_GEN >= 8
+static enum isl_format
+adjust_16bit_format(enum isl_format format)
+{
+   switch(format) {
+   case ISL_FORMAT_R16_UINT:
+   case ISL_FORMAT_R16_SINT:
+   case ISL_FORMAT_R16_FLOAT:
+   case ISL_FORMAT_R16G16_UINT:
+   case ISL_FORMAT_R16G16_SINT:
+   case ISL_FORMAT_R16G16_FLOAT:
+      return ISL_FORMAT_R32_UINT;
+   case ISL_FORMAT_R16G16B16_UINT:
+   case ISL_FORMAT_R16G16B16_SINT:
+   case ISL_FORMAT_R16G16B16_FLOAT:
+   case ISL_FORMAT_R16G16B16A16_UINT:
+   case ISL_FORMAT_R16G16B16A16_SINT:
+   case ISL_FORMAT_R16G16B16A16_FLOAT:
+      return ISL_FORMAT_R32G32_UINT;
+   default:
+      return format;
+   }
+}
+#endif
+
 static void
 emit_vertex_input(struct anv_pipeline *pipeline,
                   const VkPipelineVertexInputStateCreateInfo *info)
@@ -95,6 +120,10 @@ emit_vertex_input(struct anv_pipeline *pipeline,
    assert((inputs_read & ((1 << VERT_ATTRIB_GENERIC0) - 1)) == 0);
    const uint32_t elements = inputs_read >> VERT_ATTRIB_GENERIC0;
    const uint32_t elements_double = double_inputs_read >> VERT_ATTRIB_GENERIC0;
+#if GEN_GEN >= 8
+   const uint64_t inputs_read_16bit = vs_prog_data->inputs_read_16bit;
+   const uint32_t elements_16bit = inputs_read_16bit >> VERT_ATTRIB_GENERIC0;
+#endif
    const bool needs_svgs_elem = vs_prog_data->uses_vertexid ||
                                 vs_prog_data->uses_instanceid ||
                                 vs_prog_data->uses_basevertex ||
@@ -125,6 +154,11 @@ emit_vertex_input(struct anv_pipeline *pipeline,
                                                   VK_IMAGE_ASPECT_COLOR_BIT,
                                                   VK_IMAGE_TILING_LINEAR);
 
+#if GEN_GEN >= 8
+      if ((elements_16bit & (1 << desc->location)) != 0) {
+         format = adjust_16bit_format(format);
+      }
+#endif
       assert(desc->binding < MAX_VBS);
 
       if ((elements & (1 << desc->location)) == 0)
-- 
2.14.3

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to