summaryrefslogtreecommitdiffstats
path: root/src/intel/isl
diff options
context:
space:
mode:
authorJose Maria Casanova Crespo <[email protected]>2018-01-30 09:59:34 +0100
committerJason Ekstrand <[email protected]>2018-02-28 21:37:40 -0800
commit67d7dd594ecd6f15ba3d126a4bb92d4222c4168d (patch)
tree2ced16dbafdfd4f3a03a9da1013cdef914dcc4dd /src/intel/isl
parent4c232dc721645c147c864f102268a52c9536096d (diff)
isl/i965/fs: SSBO/UBO buffers need size padding if not multiple of 32-bit
The surfaces that backup the GPU buffers have a boundary check that considers that access to partial dwords are considered out-of-bounds. For example, buffers with 1,3 16-bit elements has size 2 or 6 and the last two bytes would always be read as 0 or its writting ignored. The introduction of 16-bit types implies that we need to align the size to 4-bytew multiples so that partial dwords could be read/written. Adding an inconditional +2 size to buffers not being multiple of 2 solves this issue for the general cases of UBO or SSBO. But, when unsized arrays of 16-bit elements are used it is not possible to know if the size was padded or not. To solve this issue the implementation calculates the needed size of the buffer surfaces, as suggested by Jason: surface_size = isl_align(buffer_size, 4) + (isl_align(buffer_size, 4) - buffer_size) So when we calculate backwards the buffer_size in the backend we update the resinfo return value with: buffer_size = (surface_size & ~3) - (surface_size & 3) It is also exposed this buffer requirements when robust buffer access is enabled so these buffer sizes recommend being multiple of 4. v2: (Jason Ekstrand) Move padding logic fron anv to isl_surface_state. Move calculus of original size from spirv to driver backend. v3: (Jason Ekstrand) Rename some variables and use a similar expresion when calculating. padding than when obtaining the original buffer size. Avoid use of unnecesary component call at brw_fs_nir. v4: (Jason Ekstrand) Complete comment with buffer size calculus explanation in brw_fs_nir. Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/intel/isl')
-rw-r--r--src/intel/isl/isl_surface_state.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/intel/isl/isl_surface_state.c b/src/intel/isl/isl_surface_state.c
index bfb27fa4a44..c205b3d2c0b 100644
--- a/src/intel/isl/isl_surface_state.c
+++ b/src/intel/isl/isl_surface_state.c
@@ -673,7 +673,27 @@ void
isl_genX(buffer_fill_state_s)(void *state,
const struct isl_buffer_fill_state_info *restrict info)
{
- uint32_t num_elements = info->size / info->stride;
+ uint64_t buffer_size = info->size;
+
+ /* Uniform and Storage buffers need to have surface size not less that the
+ * aligned 32-bit size of the buffer. To calculate the array lenght on
+ * unsized arrays in StorageBuffer the last 2 bits store the padding size
+ * added to the surface, so we can calculate latter the original buffer
+ * size to know the number of elements.
+ *
+ * surface_size = isl_align(buffer_size, 4) +
+ * (isl_align(buffer_size) - buffer_size)
+ *
+ * buffer_size = (surface_size & ~3) - (surface_size & 3)
+ */
+ if (info->format == ISL_FORMAT_RAW ||
+ info->stride < isl_format_get_layout(info->format)->bpb / 8) {
+ assert(info->stride == 1);
+ uint64_t aligned_size = isl_align(buffer_size, 4);
+ buffer_size = aligned_size + (aligned_size - buffer_size);
+ }
+
+ uint32_t num_elements = buffer_size / info->stride;
if (GEN_GEN >= 7) {
/* From the IVB PRM, SURFACE_STATE::Height,