From f5f2007322b5468aa3025e7e259b4c50c7a7a0bd Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 14 May 2015 09:46:42 +0800 Subject: [PATCH] ilo: add ilo_state_surface We want to replace ilo_view_surface with ilo_state_surface. --- src/gallium/drivers/ilo/Makefile.sources | 2 + .../drivers/ilo/core/ilo_state_surface.c | 1179 +++++++++++++++++ .../drivers/ilo/core/ilo_state_surface.h | 116 ++ 3 files changed, 1297 insertions(+) create mode 100644 src/gallium/drivers/ilo/core/ilo_state_surface.c create mode 100644 src/gallium/drivers/ilo/core/ilo_state_surface.h diff --git a/src/gallium/drivers/ilo/Makefile.sources b/src/gallium/drivers/ilo/Makefile.sources index 943e29113ae..587850eafdb 100644 --- a/src/gallium/drivers/ilo/Makefile.sources +++ b/src/gallium/drivers/ilo/Makefile.sources @@ -23,6 +23,8 @@ C_SOURCES := \ core/ilo_state_3d.h \ core/ilo_state_3d_bottom.c \ core/ilo_state_3d_top.c \ + core/ilo_state_surface.c \ + core/ilo_state_surface.h \ core/ilo_state_zs.c \ core/ilo_state_zs.h \ core/intel_winsys.h \ diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.c b/src/gallium/drivers/ilo/core/ilo_state_surface.c new file mode 100644 index 00000000000..be7225b7bc4 --- /dev/null +++ b/src/gallium/drivers/ilo/core/ilo_state_surface.c @@ -0,0 +1,1179 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2012-2015 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "ilo_debug.h" +#include "ilo_buffer.h" +#include "ilo_image.h" +#include "ilo_state_surface.h" + +static bool +surface_set_gen6_null_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev) +{ + uint32_t dw0, dw3; + + ILO_DEV_ASSERT(dev, 6, 6); + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 71: + * + * "All of the remaining fields in surface state are ignored for null + * surfaces, with the following exceptions: + * + * - [DevSNB+]: Width, Height, Depth, and LOD fields must match the + * depth buffer's corresponding state for all render target + * surfaces, including null. + * - Surface Format must be R8G8B8A8_UNORM." + * + * From the Sandy Bridge PRM, volume 4 part 1, page 82: + * + * "If Surface Type is SURFTYPE_NULL, this field (Tiled Surface) must + * be true" + * + * Note that we ignore the first exception for all surface types. + */ + dw0 = GEN6_SURFTYPE_NULL << GEN6_SURFACE_DW0_TYPE__SHIFT | + GEN6_FORMAT_R8G8B8A8_UNORM << GEN6_SURFACE_DW0_FORMAT__SHIFT; + dw3 = GEN6_TILING_X << GEN6_SURFACE_DW3_TILING__SHIFT; + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6); + surf->surface[0] = dw0; + surf->surface[1] = 0; + surf->surface[2] = 0; + surf->surface[3] = dw3; + surf->surface[4] = 0; + surf->surface[5] = 0; + + return true; +} + +static bool +surface_set_gen7_null_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev) +{ + uint32_t dw0; + + ILO_DEV_ASSERT(dev, 7, 8); + + dw0 = GEN6_SURFTYPE_NULL << GEN7_SURFACE_DW0_TYPE__SHIFT | + GEN6_FORMAT_R8G8B8A8_UNORM << GEN7_SURFACE_DW0_FORMAT__SHIFT; + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + dw0 |= GEN6_TILING_X << GEN8_SURFACE_DW0_TILING__SHIFT; + else + dw0 |= GEN6_TILING_X << GEN7_SURFACE_DW0_TILING__SHIFT; + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13); + surf->surface[0] = dw0; + memset(&surf->surface[1], 0, sizeof(uint32_t) * + ((ilo_dev_gen(dev) >= ILO_GEN(8)) ? 13 : 8) - 1); + + return true; +} + +static bool +surface_validate_gen6_buffer(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->buf->bo_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; + } + + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 68: + * + * "The Base Address for linear render target surfaces and surfaces + * accessed with the typed surface read/write data port messages must + * be element-size aligned, for non-YUV surface formats, or a multiple + * of 2 element-sizes for YUV surface formats. Other linear surfaces + * have no alignment requirements (byte alignment is sufficient)." + * + * "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); + + if (info->offset % info->struct_size) { + ilo_warn("bad buffer offset\n"); + return false; + } + } + + if (info->format == GEN6_FORMAT_RAW) { + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 97: + * + * ""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." + * + * We do not have a specific access mode for untyped messages. + */ + assert(info->access == ILO_STATE_SURFACE_ACCESS_DP_UNTYPED); + + /* + * Nothing is said about Untyped* messages, but I guess they require the + * base address to be DWord aligned. + */ + if (info->offset % 4) { + ilo_warn("bad RAW buffer offset\n"); + return false; + } + + 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; + } + + /* + * 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 true; +} + +static bool +surface_get_gen6_buffer_struct_count(const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info, + uint32_t *count) +{ + uint32_t max_struct, c; + + 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) + c++; + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 77: + * + * "For buffer surfaces, the number of entries in the buffer ranges + * from 1 to 2^27." + * + * From the Ivy Bridge PRM, volume 4 part 1, page 68: + * + * "For typed buffer and structured buffer surfaces, the number of + * entries in the buffer ranges from 1 to 2^27. For raw buffer + * surfaces, the number of entries in the buffer is the number of + * bytes which can range from 1 to 2^30." + * + * From the Ivy Bridge PRM, volume 4 part 1, page 69: + * + * For SURFTYPE_BUFFER: The low two bits of this field (Width) must be + * 11 if the Surface Format is RAW (the size of the buffer must be a + * multiple of 4 bytes)." + */ + max_struct = 1 << 27; + if (info->format == GEN6_FORMAT_RAW && info->struct_size == 1) { + if (ilo_dev_gen(dev) >= ILO_GEN(7)) + max_struct = 1 << 30; + + c &= ~3; + } + + if (!c || c > max_struct) { + ilo_warn("too many or zero buffer structs\n"); + return false; + } + + *count = c - 1; + + return true; +} + +static bool +surface_set_gen6_buffer_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info) +{ + uint32_t dw0, dw1, dw2, dw3; + uint32_t struct_count; + int width, height, depth; + + ILO_DEV_ASSERT(dev, 6, 6); + + if (!surface_validate_gen6_buffer(dev, info) || + !surface_get_gen6_buffer_struct_count(dev, info, &struct_count)) + return false; + + /* bits [6:0] */ + width = (struct_count & 0x0000007f); + /* bits [19:7] */ + height = (struct_count & 0x000fff80) >> 7; + /* bits [26:20] */ + depth = (struct_count & 0x07f00000) >> 20; + + dw0 = GEN6_SURFTYPE_BUFFER << GEN6_SURFACE_DW0_TYPE__SHIFT | + info->format << GEN6_SURFACE_DW0_FORMAT__SHIFT; + dw1 = info->offset; + dw2 = height << GEN6_SURFACE_DW2_HEIGHT__SHIFT | + width << GEN6_SURFACE_DW2_WIDTH__SHIFT; + dw3 = depth << GEN6_SURFACE_DW3_DEPTH__SHIFT | + (info->struct_size - 1) << GEN6_SURFACE_DW3_PITCH__SHIFT; + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6); + surf->surface[0] = dw0; + surf->surface[1] = dw1; + surf->surface[2] = dw2; + surf->surface[3] = dw3; + surf->surface[4] = 0; + surf->surface[5] = 0; + + surf->type = GEN6_SURFTYPE_BUFFER; + surf->min_lod = 0; + surf->mip_count = 0; + + return true; +} + +static bool +surface_set_gen7_buffer_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info) +{ + uint32_t dw0, dw1, dw2, dw3, dw7; + enum gen_surface_type type; + uint32_t struct_count; + int width, height, depth; + + ILO_DEV_ASSERT(dev, 7, 8); + + if (!surface_validate_gen6_buffer(dev, info) || + !surface_get_gen6_buffer_struct_count(dev, info, &struct_count)) + return false; + + type = (info->format == GEN6_FORMAT_RAW && info->struct_size > 1) ? + GEN7_SURFTYPE_STRBUF : GEN6_SURFTYPE_BUFFER; + + /* bits [6:0] */ + width = (struct_count & 0x0000007f); + /* bits [20:7] */ + height = (struct_count & 0x001fff80) >> 7; + /* bits [30:21] */ + depth = (struct_count & 0x7fe00000) >> 21; + + dw0 = type << GEN7_SURFACE_DW0_TYPE__SHIFT | + info->format << GEN7_SURFACE_DW0_FORMAT__SHIFT; + dw1 = (ilo_dev_gen(dev) >= ILO_GEN(8)) ? 0 : info->offset; + dw2 = GEN_SHIFT32(height, GEN7_SURFACE_DW2_HEIGHT) | + GEN_SHIFT32(width, GEN7_SURFACE_DW2_WIDTH); + dw3 = GEN_SHIFT32(depth, GEN7_SURFACE_DW3_DEPTH) | + GEN_SHIFT32(info->struct_size - 1, GEN7_SURFACE_DW3_PITCH); + + dw7 = 0; + if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) { + dw7 |= GEN_SHIFT32(GEN75_SCS_RED, GEN75_SURFACE_DW7_SCS_R) | + GEN_SHIFT32(GEN75_SCS_GREEN, GEN75_SURFACE_DW7_SCS_G) | + GEN_SHIFT32(GEN75_SCS_BLUE, GEN75_SURFACE_DW7_SCS_B) | + GEN_SHIFT32(GEN75_SCS_ALPHA, GEN75_SURFACE_DW7_SCS_A); + } + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13); + surf->surface[0] = dw0; + surf->surface[1] = dw1; + surf->surface[2] = dw2; + surf->surface[3] = dw3; + surf->surface[4] = 0; + surf->surface[5] = 0; + surf->surface[6] = 0; + surf->surface[7] = dw7; + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + surf->surface[8] = info->offset; + surf->surface[9] = 0; + surf->surface[10] = 0; + surf->surface[11] = 0; + surf->surface[12] = 0; + } + + surf->type = type; + surf->min_lod = 0; + surf->mip_count = 0; + + return true; +} + +static enum gen_surface_type +get_gen6_surface_type(const struct ilo_dev *dev, const struct ilo_image *img) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + switch (img->target) { + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_1D_ARRAY: + return GEN6_SURFTYPE_1D; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_CUBE_ARRAY: + return GEN6_SURFTYPE_2D; + case PIPE_TEXTURE_3D: + return GEN6_SURFTYPE_3D; + default: + assert(!"unknown texture target"); + return GEN6_SURFTYPE_NULL; + } +} + +static bool +surface_validate_gen6_image(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + switch (info->access) { + case ILO_STATE_SURFACE_ACCESS_SAMPLER: + case ILO_STATE_SURFACE_ACCESS_DP_RENDER: + break; + case ILO_STATE_SURFACE_ACCESS_DP_TYPED: + assert(ilo_dev_gen(dev) >= ILO_GEN(7)); + break; + default: + assert(!"unsupported surface access"); + break; + } + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 78: + * + * "For surface types other than SURFTYPE_BUFFER, the Width specified + * by this field must be less than or equal to the surface pitch + * (specified in bytes via the Surface Pitch field)." + */ + assert(info->img->bo_stride && info->img->bo_stride <= 512 * 1024 && + info->img->width0 <= info->img->bo_stride); + + if (info->is_cube_map) { + assert(get_gen6_surface_type(dev, info->img) == GEN6_SURFTYPE_2D); + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 78: + * + * "For cube maps, Width must be set equal to the Height." + */ + assert(info->img->width0 == info->img->height0); + } + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 72: + * + * "Tile Walk TILEWALK_YMAJOR is UNDEFINED for render target formats + * that have 128 bits-per-element (BPE)." + * + * "If Number of Multisamples is set to a value other than + * MULTISAMPLECOUNT_1, this field cannot be set to the following + * formats: + * + * - any format with greater than 64 bits per element + * - any compressed texture format (BC*) + * - any YCRCB* format" + * + * From the Ivy Bridge PRM, volume 4 part 1, page 63: + * + * If Number of Multisamples is set to a value other than + * MULTISAMPLECOUNT_1, this field cannot be set to the following + * formats: any format with greater than 64 bits per element, if + * Number of Multisamples is MULTISAMPLECOUNT_8, any compressed + * texture format (BC*), and any YCRCB* format. + * + * TODO + */ + + if (ilo_dev_gen(dev) < ILO_GEN(8) && info->img->tiling == GEN8_TILING_W) { + ilo_warn("tiling W is not supported\n"); + return false; + } + + return true; +} + +static void +get_gen6_max_extent(const struct ilo_dev *dev, + const struct ilo_image *img, + uint16_t *max_w, uint16_t *max_h) +{ + const uint16_t max_size = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 16384 : 8192; + + ILO_DEV_ASSERT(dev, 6, 8); + + switch (get_gen6_surface_type(dev, img)) { + case GEN6_SURFTYPE_1D: + *max_w = max_size; + *max_h = 1; + break; + case GEN6_SURFTYPE_2D: + *max_w = max_size; + *max_h = max_size; + break; + case GEN6_SURFTYPE_3D: + *max_w = 2048; + *max_h = 2048; + break; + default: + assert(!"invalid surface type"); + *max_w = 1; + *max_h = 1; + break; + } +} + +static bool +surface_get_gen6_image_extent(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info, + uint16_t *width, uint16_t *height) +{ + uint16_t w, h, max_w, max_h; + + ILO_DEV_ASSERT(dev, 6, 8); + + w = info->img->width0; + h = info->img->height0; + + get_gen6_max_extent(dev, info->img, &max_w, &max_h); + assert(w && h && w <= max_w && h <= max_h); + + *width = w - 1; + *height = h - 1; + + return true; +} + +static bool +surface_get_gen6_image_slices(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info, + uint16_t *depth, uint16_t *min_array_elem, + uint16_t *rt_view_extent) +{ + uint16_t max_slice, d; + + ILO_DEV_ASSERT(dev, 6, 8); + + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 63: + * + * "If this field (Surface Array) is enabled, the Surface Type must be + * SURFTYPE_1D, SURFTYPE_2D, or SURFTYPE_CUBE. If this field is + * disabled and Surface Type is SURFTYPE_1D, SURFTYPE_2D, or + * SURFTYPE_CUBE, the Depth field must be set to zero." + * + * From the Ivy Bridge PRM, volume 4 part 1, page 69: + * + * "This field (Depth) specifies the total number of levels for a + * volume texture or the number of array elements allowed to be + * accessed starting at the Minimum Array Element for arrayed + * surfaces. If the volume texture is MIP-mapped, this field + * specifies the depth of the base MIP level." + * + * "For SURFTYPE_CUBE:For Sampling Engine Surfaces, the range of this + * field is [0,340], indicating the number of cube array elements + * (equal to the number of underlying 2D array elements divided by 6). + * For other surfaces, this field must be zero." + * + * "Errata: For SURFTYPE_CUBE sampling engine surfaces, the range of + * this field is limited to [0,85]. + * + * Errata: If Surface Array is enabled, and Depth is between 1024 and + * 2047, an incorrect array slice may be accessed if the requested + * array index in the message is greater than or equal to 4096." + * + * The errata are for Gen7-specific, and they limit the number of useable + * layers to (86 * 6), about 512. + */ + + switch (get_gen6_surface_type(dev, info->img)) { + case GEN6_SURFTYPE_1D: + case GEN6_SURFTYPE_2D: + max_slice = (ilo_dev_gen(dev) >= ILO_GEN(7.5)) ? 2048 : 512; + + assert(info->img->array_size <= max_slice); + max_slice = info->img->array_size; + + d = info->slice_count; + if (info->is_cube_map) { + if (info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER) { + if (!d || d % 6) { + ilo_warn("invalid cube slice count\n"); + return false; + } + + if (ilo_dev_gen(dev) == ILO_GEN(7) && d > 86 * 6) { + ilo_warn("cube slice count exceeds Gen7 limit\n"); + return false; + } + } else { + /* + * Minumum Array Element and Depth must be 0; Render Target View + * Extent is ignored. + */ + if (info->slice_base || d != 6) { + ilo_warn("no cube RT array support in data port\n"); + return false; + } + } + + d /= 6; + } + + if (!info->is_array && d > 1) { + ilo_warn("non-array surface with non-zero depth\n"); + return false; + } + break; + case GEN6_SURFTYPE_3D: + max_slice = 2048; + + assert(info->img->depth0 <= max_slice); + max_slice = u_minify(info->img->depth0, info->level_base); + + d = info->img->depth0; + + if (info->is_array) { + ilo_warn("3D surfaces cannot be arrays\n"); + return false; + } + break; + default: + assert(!"invalid surface type"); + return false; + break; + } + + if (!info->slice_count || + info->slice_base + info->slice_count > max_slice) { + ilo_warn("invalid slice range\n"); + return false; + } + + assert(d); + *depth = d - 1; + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 84: + * + * "For Sampling Engine and Render Target 1D and 2D Surfaces: + * This field (Minimum Array Element) indicates the minimum array + * element that can be accessed as part of this surface. This field + * is added to the delivered array index before it is used to address + * the surface. + * + * For Render Target 3D Surfaces: + * This field indicates the minimum `R' coordinate on the LOD + * currently being rendered to. This field is added to the delivered + * array index before it is used to address the surface. + * + * For Sampling Engine Cube Surfaces on [DevSNB+] only: + * This field indicates the minimum array element in the underlying 2D + * surface array that can be accessed as part of this surface (the + * cube array index is multipled by 6 to compute this value, although + * this field is not restricted to only multiples of 6). This field is + * added to the delivered array index before it is used to address the + * surface. + * + * For Other Surfaces: + * This field must be set to zero." + * + * On Gen7+, typed sufaces are treated like sampling engine 1D and 2D + * surfaces. + */ + *min_array_elem = info->slice_base; + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 84: + * + * "For Render Target 3D Surfaces: + * This field (Render Target View Extent) indicates the extent of the + * accessible `R' coordinates minus 1 on the LOD currently being + * rendered to. + * + * For Render Target 1D and 2D Surfaces: + * This field must be set to the same value as the Depth field. + * + * For Other Surfaces: + * This field is ignored." + */ + *rt_view_extent = info->slice_count - 1; + + return true; +} + +static bool +surface_get_gen6_image_levels(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info, + uint8_t *min_lod, uint8_t *mip_count) +{ + uint8_t max_level = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 15 : 14; + + ILO_DEV_ASSERT(dev, 6, 8); + + assert(info->img->level_count <= max_level); + max_level = info->img->level_count; + + if (!info->level_count || + info->level_base + info->level_count > max_level) { + ilo_warn("invalid level range\n"); + return false; + } + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 79: + * + * "For Sampling Engine Surfaces: + * This field (MIP Count / LOD) indicates the number of MIP levels + * allowed to be accessed starting at Surface Min LOD, which must be + * less than or equal to the number of MIP levels actually stored in + * memory for this surface. + * + * Force the mip map access to be between the mipmap specified by the + * integer bits of the Min LOD and the ceiling of the value specified + * here. + * + * For Render Target Surfaces: + * This field defines the MIP level that is currently being rendered + * into. This is the absolute MIP level on the surface and is not + * relative to the Surface Min LOD field, which is ignored for render + * target surfaces. + * + * For Other Surfaces: + * This field is reserved : MBZ" + * + * From the Sandy Bridge PRM, volume 4 part 1, page 83: + * + * "For Sampling Engine Surfaces: + * + * This field (Surface Min LOD) indicates the most detailed LOD that + * can be accessed as part of this surface. This field is added to + * the delivered LOD (sample_l, ld, or resinfo message types) before + * it is used to address the surface. + * + * For Other Surfaces: + * This field is ignored." + * + * On Gen7+, typed sufaces are treated like sampling engine surfaces. + */ + if (info->access == ILO_STATE_SURFACE_ACCESS_DP_RENDER) { + assert(info->level_count == 1); + + *min_lod = 0; + *mip_count = info->level_base; + } else { + *min_lod = info->level_base; + *mip_count = info->level_count - 1; + } + + return true; +} + +static bool +surface_get_gen6_image_sample_count(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info, + enum gen_sample_count *sample_count) +{ + int min_gen; + + ILO_DEV_ASSERT(dev, 6, 8); + + switch (info->img->sample_count) { + case 1: + *sample_count = GEN6_NUMSAMPLES_1; + min_gen = ILO_GEN(6); + break; + case 2: + *sample_count = GEN8_NUMSAMPLES_2; + min_gen = ILO_GEN(8); + break; + case 4: + *sample_count = GEN6_NUMSAMPLES_4; + min_gen = ILO_GEN(6); + break; + case 8: + *sample_count = GEN7_NUMSAMPLES_8; + min_gen = ILO_GEN(7); + break; + case 16: + *sample_count = GEN8_NUMSAMPLES_16; + min_gen = ILO_GEN(8); + break; + default: + assert(!"invalid sample count"); + *sample_count = GEN6_NUMSAMPLES_1; + break; + } + + assert(ilo_dev_gen(dev) >= min_gen); + + return true; +} + +static bool +surface_get_gen6_image_alignments(const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info, + uint32_t *alignments) +{ + uint32_t a = 0; + bool err = false; + + ILO_DEV_ASSERT(dev, 6, 8); + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + switch (info->img->align_i) { + case 4: + a |= GEN8_SURFACE_DW0_HALIGN_4; + break; + case 8: + a |= GEN8_SURFACE_DW0_HALIGN_8; + break; + case 16: + a |= GEN8_SURFACE_DW0_HALIGN_16; + break; + default: + err = true; + break; + } + + switch (info->img->align_j) { + case 4: + a |= GEN7_SURFACE_DW0_VALIGN_4; + break; + case 8: + a |= GEN8_SURFACE_DW0_VALIGN_8; + break; + case 16: + a |= GEN8_SURFACE_DW0_VALIGN_16; + break; + default: + err = true; + break; + } + } else if (ilo_dev_gen(dev) >= ILO_GEN(7)) { + switch (info->img->align_i) { + case 4: + a |= GEN7_SURFACE_DW0_HALIGN_4; + break; + case 8: + a |= GEN7_SURFACE_DW0_HALIGN_8; + break; + default: + err = true; + break; + } + + switch (info->img->align_j) { + case 2: + a |= GEN7_SURFACE_DW0_VALIGN_2; + break; + case 4: + a |= GEN7_SURFACE_DW0_VALIGN_4; + break; + default: + err = true; + break; + } + } else { + if (info->img->align_i != 4) + err = true; + + switch (info->img->align_j) { + case 2: + a |= GEN6_SURFACE_DW5_VALIGN_2; + break; + case 4: + a |= GEN6_SURFACE_DW5_VALIGN_4; + break; + default: + err = true; + break; + } + } + + if (err) + assert(!"invalid HALIGN or VALIGN"); + + *alignments = a; + + return true; +} + +static bool +surface_set_gen6_image_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info) +{ + uint16_t width, height, depth, array_base, view_extent; + uint8_t min_lod, mip_count; + enum gen_sample_count sample_count; + uint32_t alignments; + enum gen_surface_type type; + uint32_t dw0, dw2, dw3, dw4, dw5; + + ILO_DEV_ASSERT(dev, 6, 6); + + if (!surface_validate_gen6_image(dev, info) || + !surface_get_gen6_image_extent(dev, info, &width, &height) || + !surface_get_gen6_image_slices(dev, info, &depth, &array_base, + &view_extent) || + !surface_get_gen6_image_levels(dev, info, &min_lod, &mip_count) || + !surface_get_gen6_image_sample_count(dev, info, &sample_count) || + !surface_get_gen6_image_alignments(dev, info, &alignments)) + return false; + + /* no ARYSPC_LOD0 */ + assert(info->img->walk != ILO_IMAGE_WALK_LOD); + /* no UMS/CMS */ + if (info->img->sample_count > 1) + assert(info->img->interleaved_samples); + + type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE : + get_gen6_surface_type(dev, info->img); + + dw0 = type << GEN6_SURFACE_DW0_TYPE__SHIFT | + info->format << GEN6_SURFACE_DW0_FORMAT__SHIFT | + GEN6_SURFACE_DW0_MIPLAYOUT_BELOW; + + /* + * From the Sandy Bridge PRM, volume 4 part 1, page 74: + * + * "CUBE_AVERAGE may only be selected if all of the Cube Face Enable + * fields are equal to one." + * + * From the Sandy Bridge PRM, volume 4 part 1, page 75-76: + * + * "For SURFTYPE_CUBE Surfaces accessed via the Sampling Engine: + * Bits 5:0 of this field (Cube Face Enables) enable the individual + * faces of a cube map. Enabling a face indicates that the face is + * present in the cube map, while disabling it indicates that that + * face is represented by the texture map's border color. Refer to + * Memory Data Formats for the correlation between faces and the cube + * map memory layout. Note that storage for disabled faces must be + * provided. + * + * For other surfaces: + * This field is reserved : MBZ" + * + * "When TEXCOORDMODE_CLAMP is used when accessing a cube map, this + * field must be programmed to 111111b (all faces enabled)." + */ + if (info->is_cube_map && + info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER) { + dw0 |= GEN6_SURFACE_DW0_CUBE_MAP_CORNER_MODE_AVERAGE | + GEN6_SURFACE_DW0_CUBE_FACE_ENABLES__MASK; + } + + dw2 = height << GEN6_SURFACE_DW2_HEIGHT__SHIFT | + width << GEN6_SURFACE_DW2_WIDTH__SHIFT | + mip_count << GEN6_SURFACE_DW2_MIP_COUNT_LOD__SHIFT; + + dw3 = depth << GEN6_SURFACE_DW3_DEPTH__SHIFT | + (info->img->bo_stride - 1) << GEN6_SURFACE_DW3_PITCH__SHIFT | + info->img->tiling << GEN6_SURFACE_DW3_TILING__SHIFT; + + dw4 = min_lod << GEN6_SURFACE_DW4_MIN_LOD__SHIFT | + array_base << GEN6_SURFACE_DW4_MIN_ARRAY_ELEMENT__SHIFT | + view_extent << GEN6_SURFACE_DW4_RT_VIEW_EXTENT__SHIFT | + sample_count << GEN6_SURFACE_DW4_MULTISAMPLECOUNT__SHIFT; + + dw5 = alignments; + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6); + surf->surface[0] = dw0; + surf->surface[1] = 0; + surf->surface[2] = dw2; + surf->surface[3] = dw3; + surf->surface[4] = dw4; + surf->surface[5] = dw5; + + surf->type = type; + surf->min_lod = min_lod; + surf->mip_count = mip_count; + + return true; +} + +static bool +surface_set_gen7_image_SURFACE_STATE(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info) +{ + uint16_t width, height, depth, array_base, view_extent; + uint8_t min_lod, mip_count; + uint32_t alignments; + enum gen_sample_count sample_count; + enum gen_surface_type type; + uint32_t dw0, dw1, dw2, dw3, dw4, dw5, dw7; + + ILO_DEV_ASSERT(dev, 7, 8); + + if (!surface_validate_gen6_image(dev, info) || + !surface_get_gen6_image_extent(dev, info, &width, &height) || + !surface_get_gen6_image_slices(dev, info, &depth, &array_base, + &view_extent) || + !surface_get_gen6_image_levels(dev, info, &min_lod, &mip_count) || + !surface_get_gen6_image_sample_count(dev, info, &sample_count) || + !surface_get_gen6_image_alignments(dev, info, &alignments)) + return false; + + type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE : + get_gen6_surface_type(dev, info->img); + + dw0 = type << GEN7_SURFACE_DW0_TYPE__SHIFT | + info->format << GEN7_SURFACE_DW0_FORMAT__SHIFT | + alignments; + + if (info->is_array) + dw0 |= GEN7_SURFACE_DW0_IS_ARRAY; + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + dw0 |= info->img->tiling << GEN8_SURFACE_DW0_TILING__SHIFT; + } else { + dw0 |= info->img->tiling << GEN7_SURFACE_DW0_TILING__SHIFT; + + if (info->img->walk == ILO_IMAGE_WALK_LOD) + dw0 |= GEN7_SURFACE_DW0_ARYSPC_LOD0; + else + dw0 |= GEN7_SURFACE_DW0_ARYSPC_FULL; + } + + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 67: + * + * "For SURFTYPE_CUBE Surfaces accessed via the Sampling Engine: Bits + * 5:0 of this field (Cube Face Enables) enable the individual faces + * of a cube map. Enabling a face indicates that the face is present + * in the cube map, while disabling it indicates that that face is + * represented by the texture map's border color. Refer to Memory Data + * Formats for the correlation between faces and the cube map memory + * layout. Note that storage for disabled faces must be provided. For + * other surfaces this field is reserved and MBZ." + * + * "When TEXCOORDMODE_CLAMP is used when accessing a cube map, this + * field must be programmed to 111111b (all faces enabled). This field + * is ignored unless the Surface Type is SURFTYPE_CUBE." + */ + if (info->is_cube_map && + info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER) + dw0 |= GEN7_SURFACE_DW0_CUBE_FACE_ENABLES__MASK; + + dw1 = 0; + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + assert(info->img->walk_layer_height % 4 == 0); + dw1 |= info->img->walk_layer_height / 4 << + GEN8_SURFACE_DW1_QPITCH__SHIFT; + } + + dw2 = height << GEN7_SURFACE_DW2_HEIGHT__SHIFT | + width << GEN7_SURFACE_DW2_WIDTH__SHIFT; + + dw3 = depth << GEN7_SURFACE_DW3_DEPTH__SHIFT | + (info->img->bo_stride - 1) << GEN7_SURFACE_DW3_PITCH__SHIFT; + + if (ilo_dev_gen(dev) == ILO_GEN(7.5)) + dw3 |= 0 << GEN75_SURFACE_DW3_INTEGER_SURFACE_FORMAT__SHIFT; + + dw4 = array_base << GEN7_SURFACE_DW4_MIN_ARRAY_ELEMENT__SHIFT | + view_extent << GEN7_SURFACE_DW4_RT_VIEW_EXTENT__SHIFT | + sample_count << GEN7_SURFACE_DW4_MULTISAMPLECOUNT__SHIFT; + + /* + * MSFMT_MSS means the samples are not interleaved and MSFMT_DEPTH_STENCIL + * means the samples are interleaved. The layouts are the same when the + * number of samples is 1. + */ + if (info->img->interleaved_samples && info->img->sample_count > 1) { + assert(info->access != ILO_STATE_SURFACE_ACCESS_DP_RENDER); + dw4 |= GEN7_SURFACE_DW4_MSFMT_DEPTH_STENCIL; + } else { + dw4 |= GEN7_SURFACE_DW4_MSFMT_MSS; + } + + dw5 = min_lod << GEN7_SURFACE_DW5_MIN_LOD__SHIFT | + mip_count << GEN7_SURFACE_DW5_MIP_COUNT_LOD__SHIFT; + + dw7 = 0; + if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) { + dw7 |= GEN_SHIFT32(GEN75_SCS_RED, GEN75_SURFACE_DW7_SCS_R) | + GEN_SHIFT32(GEN75_SCS_GREEN, GEN75_SURFACE_DW7_SCS_G) | + GEN_SHIFT32(GEN75_SCS_BLUE, GEN75_SURFACE_DW7_SCS_B) | + GEN_SHIFT32(GEN75_SCS_ALPHA, GEN75_SURFACE_DW7_SCS_A); + } + + STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13); + surf->surface[0] = dw0; + surf->surface[1] = dw1; + surf->surface[2] = dw2; + surf->surface[3] = dw3; + surf->surface[4] = dw4; + surf->surface[5] = dw5; + surf->surface[6] = 0; + surf->surface[7] = dw7; + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + surf->surface[8] = 0; + surf->surface[9] = 0; + surf->surface[10] = 0; + surf->surface[11] = 0; + surf->surface[12] = 0; + } + + surf->type = type; + surf->min_lod = min_lod; + surf->mip_count = mip_count; + + return true; +} + +bool +ilo_state_surface_init_for_null(struct ilo_state_surface *surf, + const struct ilo_dev *dev) +{ + bool ret = true; + + assert(ilo_is_zeroed(surf, sizeof(*surf))); + + if (ilo_dev_gen(dev) >= ILO_GEN(7)) + ret &= surface_set_gen7_null_SURFACE_STATE(surf, dev); + else + ret &= surface_set_gen6_null_SURFACE_STATE(surf, dev); + + surf->type = GEN6_SURFTYPE_NULL; + surf->readonly = true; + + assert(ret); + + return ret; +} + +bool +ilo_state_surface_init_for_buffer(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info) +{ + bool ret = true; + + assert(ilo_is_zeroed(surf, sizeof(*surf))); + + if (ilo_dev_gen(dev) >= ILO_GEN(7)) + ret &= surface_set_gen7_buffer_SURFACE_STATE(surf, dev, info); + else + ret &= surface_set_gen6_buffer_SURFACE_STATE(surf, dev, info); + + surf->readonly = info->readonly; + + assert(ret); + + return ret; +} + +bool +ilo_state_surface_init_for_image(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info) +{ + bool ret = true; + + assert(ilo_is_zeroed(surf, sizeof(*surf))); + + if (ilo_dev_gen(dev) >= ILO_GEN(7)) + ret &= surface_set_gen7_image_SURFACE_STATE(surf, dev, info); + else + ret &= surface_set_gen6_image_SURFACE_STATE(surf, dev, info); + + surf->is_integer = info->is_integer; + surf->readonly = info->readonly; + surf->scanout = info->img->scanout; + + assert(ret); + + return ret; +} + +bool +ilo_state_surface_set_scs(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + enum gen_surface_scs rgba[4]) +{ + const uint32_t scs = GEN_SHIFT32(rgba[0], GEN75_SURFACE_DW7_SCS_R) | + GEN_SHIFT32(rgba[1], GEN75_SURFACE_DW7_SCS_G) | + GEN_SHIFT32(rgba[2], GEN75_SURFACE_DW7_SCS_B) | + GEN_SHIFT32(rgba[3], GEN75_SURFACE_DW7_SCS_A); + + ILO_DEV_ASSERT(dev, 6, 8); + + assert(ilo_dev_gen(dev) >= ILO_GEN(7.5)); + + surf->surface[7] = (surf->surface[7] & ~GEN75_SURFACE_DW7_SCS__MASK) | scs; + + return true; +} diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.h b/src/gallium/drivers/ilo/core/ilo_state_surface.h new file mode 100644 index 00000000000..deb0b549ebd --- /dev/null +++ b/src/gallium/drivers/ilo/core/ilo_state_surface.h @@ -0,0 +1,116 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef ILO_STATE_SURFACE_H +#define ILO_STATE_SURFACE_H + +#include "genhw/genhw.h" +#include "intel_winsys.h" + +#include "ilo_core.h" +#include "ilo_dev.h" + +struct ilo_buffer; +struct ilo_image; + +enum ilo_state_surface_access { + ILO_STATE_SURFACE_ACCESS_SAMPLER, /* sampling engine surfaces */ + ILO_STATE_SURFACE_ACCESS_DP_RENDER, /* render target surfaces */ + ILO_STATE_SURFACE_ACCESS_DP_TYPED, /* typed surfaces */ + ILO_STATE_SURFACE_ACCESS_DP_UNTYPED, /* untyped surfaces */ + ILO_STATE_SURFACE_ACCESS_DP_DATA, + ILO_STATE_SURFACE_ACCESS_DP_SVB, +}; + +struct ilo_state_surface_buffer_info { + const struct ilo_buffer *buf; + + enum ilo_state_surface_access access; + + enum gen_surface_format format; + uint8_t format_size; + + bool readonly; + uint16_t struct_size; + + uint32_t offset; + uint32_t size; +}; + +struct ilo_state_surface_image_info { + const struct ilo_image *img; + + enum ilo_state_surface_access access; + + enum gen_surface_format format; + bool is_integer; + + bool readonly; + bool is_cube_map; + bool is_array; + + uint8_t level_base; + uint8_t level_count; + uint16_t slice_base; + uint16_t slice_count; +}; + +struct ilo_state_surface { + uint32_t surface[13]; + + enum gen_surface_type type; + uint8_t min_lod; + uint8_t mip_count; + bool is_integer; + + bool readonly; + bool scanout; + + /* managed by users */ + struct intel_bo *bo; +}; + +bool +ilo_state_surface_init_for_null(struct ilo_state_surface *surf, + const struct ilo_dev *dev); + +bool +ilo_state_surface_init_for_buffer(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_buffer_info *info); + +bool +ilo_state_surface_init_for_image(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + const struct ilo_state_surface_image_info *info); + +bool +ilo_state_surface_set_scs(struct ilo_state_surface *surf, + const struct ilo_dev *dev, + enum gen_surface_scs rgba[4]); + +#endif /* ILO_STATE_SURFACE_H */ -- 2.30.2