From 07acf9cb167d4e1f7aebd6837d22e3523ad63109 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 24 Jun 2015 12:57:57 +0800 Subject: [PATCH] ilo: improve SURFTYPE_BUFFER validations Reorganize the validations to make them more systematic. --- .../drivers/ilo/core/ilo_state_surface.c | 219 +++++++++++------- .../drivers/ilo/core/ilo_state_surface.h | 1 + 2 files changed, 139 insertions(+), 81 deletions(-) diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.c b/src/gallium/drivers/ilo/core/ilo_state_surface.c index d3581749e56..2caba6df46e 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_surface.c +++ b/src/gallium/drivers/ilo/core/ilo_state_surface.c @@ -94,31 +94,13 @@ surface_set_gen7_null_SURFACE_STATE(struct ilo_state_surface *surf, return true; } -static bool -surface_validate_gen6_buffer(const struct ilo_dev *dev, - const struct ilo_state_surface_buffer_info *info) +static uint32_t +surface_get_gen6_buffer_offset_alignment(const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info) { - ILO_DEV_ASSERT(dev, 6, 8); - - /* SVB writes are Gen6-only */ - if (ilo_dev_gen(dev) >= ILO_GEN(7)) - assert(info->access != ILO_STATE_SURFACE_ACCESS_DP_SVB); - - if (info->offset + info->size > info->vma->vm_size) { - ilo_warn("invalid buffer range\n"); - return false; - } + uint32_t alignment; - /* - * From the Sandy Bridge PRM, volume 4 part 1, page 81: - * - * "For surfaces of type SURFTYPE_BUFFER: [0,2047] -> [1B, 2048B] - * For surfaces of type SURFTYPE_STRBUF: [0,2047] -> [1B, 2048B]" - */ - if (!info->struct_size || info->struct_size > 2048) { - ilo_warn("invalid buffer struct size\n"); - return false; - } + ILO_DEV_ASSERT(dev, 6, 8); /* * From the Ivy Bridge PRM, volume 4 part 1, page 68: @@ -132,77 +114,153 @@ surface_validate_gen6_buffer(const struct ilo_dev *dev, * "Certain message types used to access surfaces have more stringent * alignment requirements. Please refer to the specific message * documentation for additional restrictions." - * - * From the Ivy Bridge PRM, volume 4 part 1, page 233, 235, and 237: - * - * "the surface base address must be OWord aligned" - * - * for OWord Block Read/Write, Unaligned OWord Block Read, and OWord Dual - * Block Read/Write. - * - * From the Ivy Bridge PRM, volume 4 part 1, page 246 and 249: - * - * "The surface base address must be DWord aligned" - * - * for DWord Scattered Read/Write and Byte Scattered Read/Write. - * - * We have to rely on users to correctly set info->struct_size here. DWord - * Scattered Read/Write has conflicting pitch and alignment, but we do not - * use them yet so we are fine. - * - * It is unclear if sampling engine surfaces require aligned offsets. */ - if (info->access != ILO_STATE_SURFACE_ACCESS_DP_SVB) { - assert(info->struct_size % info->format_size == 0); + switch (info->access) { + case ILO_STATE_SURFACE_ACCESS_SAMPLER: + /* no alignment requirements */ + alignment = 1; + break; + case ILO_STATE_SURFACE_ACCESS_DP_RENDER: + case ILO_STATE_SURFACE_ACCESS_DP_TYPED: + /* element-size aligned */ + alignment = info->format_size; - if (info->offset % info->struct_size || - info->vma->vm_alignment % info->struct_size) { - ilo_warn("bad buffer offset\n"); - return false; - } - } + assert(info->struct_size % alignment == 0); + break; + case ILO_STATE_SURFACE_ACCESS_DP_UNTYPED: + /* + * Nothing is said about Untyped* messages, but I think they require the + * base address to be DWord aligned. + */ + alignment = 4; - if (info->format == GEN6_FORMAT_RAW) { /* - * From the Sandy Bridge PRM, volume 4 part 1, page 97: + * From the Ivy Bridge PRM, volume 4 part 1, page 70: + * + * "For linear surfaces with Surface Type of SURFTYPE_STRBUF, the + * pitch must be a multiple of 4 bytes." + */ + if (info->struct_size > 1) + assert(info->struct_size % alignment == 0); + break; + case ILO_STATE_SURFACE_ACCESS_DP_DATA: + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 233, 235, and 237: * - * ""RAW" is supported only with buffers and structured buffers - * accessed via the untyped surface read/write and untyped atomic - * operation messages, which do not have a column in the table." + * "the surface base address must be OWord aligned" * - * We do not have a specific access mode for untyped messages. + * for OWord Block Read/Write, Unaligned OWord Block Read, and OWord + * Dual Block Read/Write. + * + * From the Ivy Bridge PRM, volume 4 part 1, page 246 and 249: + * + * "The surface base address must be DWord aligned" + * + * for DWord Scattered Read/Write and Byte Scattered Read/Write. */ - assert(info->access == ILO_STATE_SURFACE_ACCESS_DP_UNTYPED); + alignment = (info->format_size > 4) ? 16 : 4; /* - * Nothing is said about Untyped* messages, but I guess they require the - * base address to be DWord aligned. + * From the Ivy Bridge PRM, volume 4 part 1, page 233, 235, 237, and + * 246: + * + * "the surface pitch is ignored, the surface is treated as a + * 1-dimensional surface. An element size (pitch) of 16 bytes is + * used to determine the size of the buffer for out-of-bounds + * checking if using the surface state model." + * + * for OWord Block Read/Write, Unaligned OWord Block Read, OWord + * Dual Block Read/Write, and DWord Scattered Read/Write. + * + * From the Ivy Bridge PRM, volume 4 part 1, page 248: + * + * "The surface pitch is ignored, the surface is treated as a + * 1-dimensional surface. An element size (pitch) of 4 bytes is + * used to determine the size of the buffer for out-of-bounds + * checking if using the surface state model." + * + * for Byte Scattered Read/Write. + * + * It is programmable on Gen7.5+. */ - if (info->offset % 4 || info->vma->vm_alignment % 4) { - ilo_warn("bad RAW buffer offset\n"); - return false; + if (ilo_dev_gen(dev) < ILO_GEN(7.5)) { + const int fixed = (info->format_size > 1) ? 16 : 4; + assert(info->struct_size == fixed); } + break; + case ILO_STATE_SURFACE_ACCESS_DP_SVB: + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 259: + * + * "Both the surface base address and surface pitch must be DWord + * aligned." + */ + alignment = 4; - if (info->struct_size > 1) { - /* no STRBUF on Gen6 */ - if (ilo_dev_gen(dev) == ILO_GEN(6)) { - ilo_warn("no STRBUF support\n"); - return false; - } + assert(info->struct_size % alignment == 0); + break; + default: + assert(!"unknown access"); + alignment = 1; + break; + } - /* - * From the Ivy Bridge PRM, volume 4 part 1, page 70: - * - * "For linear surfaces with Surface Type of SURFTYPE_STRBUF, the - * pitch must be a multiple of 4 bytes." - */ - if (info->struct_size % 4) { - ilo_warn("bad STRBUF pitch\n"); - return false; - } - } + return alignment; +} + +static bool +surface_validate_gen6_buffer(const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info) +{ + uint32_t alignment; + + ILO_DEV_ASSERT(dev, 6, 8); + + if (info->offset + info->size > info->vma->vm_size) { + ilo_warn("invalid buffer range\n"); + return false; + } + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 81: + * + * "For surfaces of type SURFTYPE_BUFFER: [0,2047] -> [1B, 2048B] + * For surfaces of type SURFTYPE_STRBUF: [0,2047] -> [1B, 2048B]" + */ + if (!info->struct_size || info->struct_size > 2048) { + ilo_warn("invalid buffer struct size\n"); + return false; + } + + alignment = surface_get_gen6_buffer_offset_alignment(dev, info); + if (info->offset % alignment || info->vma->vm_alignment % alignment) { + ilo_warn("bad buffer offset\n"); + return false; } + /* no STRBUF on Gen6 */ + if (info->format == GEN6_FORMAT_RAW && info->struct_size > 1) + assert(ilo_dev_gen(dev) >= ILO_GEN(7)); + + /* SVB writes are Gen6 only */ + if (info->access == ILO_STATE_SURFACE_ACCESS_DP_SVB) + assert(ilo_dev_gen(dev) == ILO_GEN(6)); + + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 83: + * + * "NOTE: "RAW" is supported only with buffers and structured buffers + * accessed via the untyped surface read/write and untyped atomic + * operation messages, which do not have a column in the table." + * + * From the Ivy Bridge PRM, volume 4 part 1, page 252: + * + * "For untyped messages, the Surface Format must be RAW and the + * Surface Type must be SURFTYPE_BUFFER or SURFTYPE_STRBUF." + */ + assert((info->access == ILO_STATE_SURFACE_ACCESS_DP_UNTYPED) == + (info->format == GEN6_FORMAT_RAW)); + return true; } @@ -216,8 +274,7 @@ surface_get_gen6_buffer_struct_count(const struct ilo_dev *dev, ILO_DEV_ASSERT(dev, 6, 8); c = info->size / info->struct_size; - if (info->access == ILO_STATE_SURFACE_ACCESS_DP_SVB && - info->format_size < info->size - info->struct_size * c) + if (info->format_size < info->size - info->struct_size * c) c++; /* diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.h b/src/gallium/drivers/ilo/core/ilo_state_surface.h index 0cda08eb031..835df69882e 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_surface.h +++ b/src/gallium/drivers/ilo/core/ilo_state_surface.h @@ -52,6 +52,7 @@ struct ilo_state_surface_buffer_info { enum ilo_state_surface_access access; + /* format_size may be less than, equal to, or greater than struct_size */ enum gen_surface_format format; uint8_t format_size; -- 2.30.2