[Mesa-dev] [PATCH 33/45] anv/pipeline: Use 32-bit surface formats for 16-bit formats
Alejandro Piñeiro
apinheiro at igalia.com
Thu Jul 13 14:35:37 UTC 2017
>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.
So this format expects those 16-bit floats to be passed without any
conversion (applies too using 2/3/4 components, and with int formats)
But from 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 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*).
Signed-off-by: Jose Maria Casanova Crespo <jmcasanova at igalia.com>
Signed-off-by: Alejandro Piñeiro <apinheiro at igalia.com>
---
src/intel/vulkan/genX_pipeline.c | 47 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index 55db533..34baa9b 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -82,6 +82,44 @@ 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_FLOAT:
+ return ISL_FORMAT_R32_FLOAT;
+ case ISL_FORMAT_R16G16_FLOAT:
+ return ISL_FORMAT_R32_FLOAT;
+ case ISL_FORMAT_R16G16B16_FLOAT:
+ return ISL_FORMAT_R32G32_FLOAT;
+ case ISL_FORMAT_R16G16B16A16_FLOAT:
+ return ISL_FORMAT_R32G32_FLOAT;
+
+ case ISL_FORMAT_R16_SINT:
+ return ISL_FORMAT_R32_SINT;
+ case ISL_FORMAT_R16G16_SINT:
+ return ISL_FORMAT_R32_SINT;
+ case ISL_FORMAT_R16G16B16_SINT:
+ return ISL_FORMAT_R32G32_SINT;
+ case ISL_FORMAT_R16G16B16A16_SINT:
+ return ISL_FORMAT_R32G32_SINT;
+
+ case ISL_FORMAT_R16_UINT:
+ return ISL_FORMAT_R32_UINT;
+ case ISL_FORMAT_R16G16_UINT:
+ return ISL_FORMAT_R32_UINT;
+ case ISL_FORMAT_R16G16B16_UINT:
+ return ISL_FORMAT_R32G32_UINT;
+ case ISL_FORMAT_R16G16B16A16_UINT:
+ return ISL_FORMAT_R32G32_UINT;
+
+ default:
+ return format;
+ }
+}
+#endif
+
static void
emit_vertex_input(struct anv_pipeline *pipeline,
const VkPipelineVertexInputStateCreateInfo *info)
@@ -94,6 +132,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 half_inputs_read = vs_prog_data->half_inputs_read;
+ const uint32_t elements_half = half_inputs_read >> VERT_ATTRIB_GENERIC0;
+#endif
const bool needs_svgs_elem = vs_prog_data->uses_vertexid ||
vs_prog_data->uses_instanceid ||
vs_prog_data->uses_basevertex ||
@@ -124,6 +166,11 @@ emit_vertex_input(struct anv_pipeline *pipeline,
VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_TILING_LINEAR);
+#if GEN_GEN >= 8
+ if ((elements_half & (1 << desc->location)) != 0) {
+ format = adjust_16bit_format(format);
+ }
+#endif
assert(desc->binding < MAX_VBS);
if ((elements & (1 << desc->location)) == 0)
--
2.9.3
More information about the mesa-dev
mailing list