From: Alejandro Piñeiro <apinhe...@igalia.com> As we are using 32-bit surface formats with 16-bit elements we can be on a situation where a vertex element can poke over the buffer by 2 bytes. To avoid that we add a padding when flushing the state.
This is similar to what the i965 drivers prior to Haswell do, as they use 4-component formats to fake 3-component formats, and add a padding there too. See commit: 7c8dfa78b98a12c1c5f74d11433c8554d4c90657 v2: (Jason Ekstrand) Increase by 2 the size returned by GetBufferMemoryRequirements when robust buffer access is enabled in a vertex buffer. Renamed half_inputs_read to inputs_read_16bit. Signed-off-by: Jose Maria Casanova Crespo <jmcasan...@igalia.com> Signed-off-by: Alejandro Piñeiro <apinhe...@igalia.com> --- src/intel/vulkan/anv_device.c | 10 ++++++++++ src/intel/vulkan/genX_cmd_buffer.c | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 69a1f5a5f6..2e5b914480 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1847,6 +1847,16 @@ void anv_GetBufferMemoryRequirements( } pMemoryRequirements->size = buffer->size; + + /* Vertex buffers with 16-bit values need a 2 bytes padding in some cases + * because they are read as 32-bit components. By adding 2 bytes to memory + * requirements size when robust buffer accesss is enabled the paddings we + * read would be outside of the VkBuffer but would not be outside "the + * memory range(s) bound to the buffer". + */ + if (device->robust_buffer_access && (buffer->usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)) + pMemoryRequirements->size += 2; + pMemoryRequirements->alignment = 16; pMemoryRequirements->memoryTypeBits = memory_types; } diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index ab5590d7ce..c019ab5259 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -1868,6 +1868,11 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) { struct anv_pipeline *pipeline = cmd_buffer->state.pipeline; uint32_t *p; +#if GEN_GEN >= 8 + const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline); + const uint64_t inputs_read_16bit = vs_prog_data->inputs_read_16bit; + const uint32_t elements_16bit = inputs_read_16bit >> VERT_ATTRIB_GENERIC0; +#endif uint32_t vb_emit = cmd_buffer->state.vb_dirty & pipeline->vb_used; @@ -1880,6 +1885,17 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) if (vb_emit) { const uint32_t num_buffers = __builtin_popcount(vb_emit); const uint32_t num_dwords = 1 + num_buffers * 4; + /* ISL 16-bit formats do a 16-bit to 32-bit float conversion, so we need + * to use ISL 32-bit formats to avoid such conversion in order to support + * properly 16-bit formats. This means that the vertex element may poke + * over the end of the buffer by 2 bytes. + */ + const unsigned padding = +#if GEN_GEN >= 8 + (elements_16bit > 0) * 2; +#else + 0; +#endif p = anv_batch_emitn(&cmd_buffer->batch, num_dwords, GENX(3DSTATE_VERTEX_BUFFERS)); @@ -1909,9 +1925,9 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) .BufferStartingAddress = { buffer->bo, buffer->offset + offset }, #if GEN_GEN >= 8 - .BufferSize = buffer->size - offset + .BufferSize = buffer->size - offset + padding, #else - .EndAddress = { buffer->bo, buffer->offset + buffer->size - 1}, + .EndAddress = { buffer->bo, buffer->offset + buffer->size + padding - 1}, #endif }; -- 2.14.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev