void intel_buf_view_init(const struct intel_dev *dev, const VkBufferViewCreateInfo *info, struct intel_buf_view *view, bool raw) { struct intel_buf *buf = intel_buf(info->buffer); /* TODO: Is transfer destination the only shader write operation? */ const bool will_write = (buf->usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)); VkFormat format; VkDeviceSize stride; uint32_t *cmd; int i; view->obj.destroy = buf_view_destroy; view->buf = buf; /* * The compiler expects uniform buffers to have pitch of * 4 for fragment shaders, but 16 for other stages. The format * must be VK_FORMAT_R32G32B32A32_SFLOAT. */ if (raw) { format = VK_FORMAT_R32G32B32A32_SFLOAT; stride = 16; } else { format = info->format; stride = icd_format_get_size(format); } cmd = view->cmd; for (i = 0; i < 2; i++) { if (intel_gpu_gen(dev->gpu) >= INTEL_GEN(7)) { surface_state_buf_gen7(dev->gpu, info->offset, info->range, stride, format, will_write, will_write, cmd); view->cmd_len = 8; } else { surface_state_buf_gen6(dev->gpu, info->offset, info->range, stride, format, will_write, will_write, cmd); view->cmd_len = 6; } /* switch to view->fs_cmd */ if (raw) { cmd = view->fs_cmd; stride = 4; } else { memcpy(view->fs_cmd, view->cmd, sizeof(uint32_t) * view->cmd_len); break; } } }
static void layout_init_size_and_format(struct intel_layout *layout, struct intel_layout_params *params) { const VkImageCreateInfo *info = params->info; VkFormat format = info->format; bool require_separate_stencil = false; layout->width0 = info->extent.width; layout->height0 = info->extent.height; /* * From the Sandy Bridge PRM, volume 2 part 1, page 317: * * "This field (Separate Stencil Buffer Enable) must be set to the same * value (enabled or disabled) as Hierarchical Depth Buffer Enable." * * GEN7+ requires separate stencil buffers. */ if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { if (intel_gpu_gen(params->gpu) >= INTEL_GEN(7)) require_separate_stencil = true; else require_separate_stencil = (layout->aux == INTEL_LAYOUT_AUX_HIZ); } switch (format) { case VK_FORMAT_D24_UNORM_S8_UINT: if (require_separate_stencil) { format = VK_FORMAT_X8_D24_UNORM_PACK32; layout->separate_stencil = true; } break; case VK_FORMAT_D32_SFLOAT_S8_UINT: if (require_separate_stencil) { format = VK_FORMAT_D32_SFLOAT; layout->separate_stencil = true; } break; default: break; } layout->format = format; layout->block_width = icd_format_get_block_width(format); layout->block_height = layout->block_width; layout->block_size = icd_format_get_size(format); params->compressed = icd_format_is_compressed(format); }
static void surface_state_buf_gen7(const struct intel_gpu *gpu, unsigned offset, unsigned size, unsigned struct_size, VkFormat elem_format, bool is_rt, bool render_cache_rw, uint32_t dw[8]) { const bool typed = !icd_format_is_undef(elem_format); const bool structured = (!typed && struct_size > 1); const int elem_size = (typed) ? icd_format_get_size(elem_format) : 1; int width, height, depth, pitch; int surface_type, surface_format, num_entries; INTEL_GPU_ASSERT(gpu, 7, 7.5); surface_type = (structured) ? GEN7_SURFTYPE_STRBUF : GEN6_SURFTYPE_BUFFER; surface_format = (typed) ? intel_format_translate_color(gpu, elem_format) : GEN6_FORMAT_RAW; /* * It's possible that the buffer view being used is smaller than * the format element size (required to be 16 for non-fragment shaders) * Make certain that size is at least struct_size to keep HW happy. */ if (size < struct_size) { size = struct_size; } num_entries = size / struct_size; /* see if there is enough space to fit another element */ if (size % struct_size >= elem_size && !structured) num_entries++; /* * From the Ivy Bridge PRM, volume 4 part 1, page 67: * * "For SURFTYPE_BUFFER render targets, this field (Surface Base * Address) specifies the base address of first element of the * surface. The surface is interpreted as a simple array of that * single element type. The address must be naturally-aligned to the * element size (e.g., a buffer containing R32G32B32A32_FLOAT elements * must be 16-byte aligned) * * For SURFTYPE_BUFFER non-rendertarget surfaces, this field specifies * the base address of the first element of the surface, computed in * software by adding the surface base address to the byte offset of * the element in the buffer." */ if (is_rt) assert(offset % elem_size == 0); /* * 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." */ assert(num_entries >= 1 && num_entries <= 1 << ((typed || structured) ? 27 : 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)." * * From the Ivy Bridge PRM, volume 4 part 1, page 70: * * "For surfaces of type SURFTYPE_BUFFER and SURFTYPE_STRBUF, this * field (Surface Pitch) indicates the size of the structure." * * "For linear surfaces with Surface Type of SURFTYPE_STRBUF, the pitch * must be a multiple of 4 bytes." */ if (structured) assert(struct_size % 4 == 0); else if (!typed) assert(num_entries % 4 == 0); pitch = struct_size; pitch--; num_entries--; /* bits [6:0] */ width = (num_entries & 0x0000007f); /* bits [20:7] */ height = (num_entries & 0x001fff80) >> 7; /* bits [30:21] */ depth = (num_entries & 0x7fe00000) >> 21; /* limit to [26:21] */ if (typed || structured) depth &= 0x3f; dw[0] = surface_type << GEN7_SURFACE_DW0_TYPE__SHIFT | surface_format << GEN7_SURFACE_DW0_FORMAT__SHIFT; if (render_cache_rw) dw[0] |= GEN7_SURFACE_DW0_RENDER_CACHE_RW; dw[1] = offset; dw[2] = height << GEN7_SURFACE_DW2_HEIGHT__SHIFT | width << GEN7_SURFACE_DW2_WIDTH__SHIFT; dw[3] = depth << GEN7_SURFACE_DW3_DEPTH__SHIFT | pitch; dw[4] = 0; dw[5] = GEN7_MOCS_L3_WB << GEN7_SURFACE_DW5_MOCS__SHIFT; dw[6] = 0; dw[7] = 0; if (intel_gpu_gen(gpu) >= INTEL_GEN(7.5)) { dw[7] |= GEN75_SCS_RED << GEN75_SURFACE_DW7_SCS_R__SHIFT | GEN75_SCS_GREEN << GEN75_SURFACE_DW7_SCS_G__SHIFT | GEN75_SCS_BLUE << GEN75_SURFACE_DW7_SCS_B__SHIFT | GEN75_SCS_ALPHA << GEN75_SURFACE_DW7_SCS_A__SHIFT; } }
static void surface_state_tex_gen6(const struct intel_gpu *gpu, const struct intel_img *img, VkImageViewType type, VkFormat format, unsigned first_level, unsigned num_levels, unsigned first_layer, unsigned num_layers, bool is_rt, uint32_t dw[6]) { int surface_type, surface_format; int width, height, depth, pitch, lod; INTEL_GPU_ASSERT(gpu, 6, 6); surface_type = view_type_to_surface_type(type); assert(surface_type != GEN6_SURFTYPE_BUFFER); surface_format = intel_format_translate_color(gpu, format); assert(surface_format >= 0); width = img->layout.width0; height = img->layout.height0; depth = (type == VK_IMAGE_VIEW_TYPE_3D) ? img->depth : num_layers; pitch = img->layout.bo_stride; if (surface_type == GEN6_SURFTYPE_CUBE) { /* * From the Sandy Bridge PRM, volume 4 part 1, page 81: * * "For SURFTYPE_CUBE: [DevSNB+]: for Sampling Engine Surfaces, the * range of this field (Depth) is [0,84], 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." * * When is_rt is true, we treat the texture as a 2D one to avoid the * restriction. */ if (is_rt) { surface_type = GEN6_SURFTYPE_2D; } else { assert(num_layers % 6 == 0); depth = num_layers / 6; } } /* sanity check the size */ assert(width >= 1 && height >= 1 && depth >= 1 && pitch >= 1); switch (surface_type) { case GEN6_SURFTYPE_1D: assert(width <= 8192 && height == 1 && depth <= 512); assert(first_layer < 512 && num_layers <= 512); break; case GEN6_SURFTYPE_2D: assert(width <= 8192 && height <= 8192 && depth <= 512); assert(first_layer < 512 && num_layers <= 512); break; case GEN6_SURFTYPE_3D: assert(width <= 2048 && height <= 2048 && depth <= 2048); assert(first_layer < 2048 && num_layers <= 512); if (!is_rt) assert(first_layer == 0); break; case GEN6_SURFTYPE_CUBE: assert(width <= 8192 && height <= 8192 && depth <= 85); assert(width == height); assert(first_layer < 512 && num_layers <= 512); if (is_rt) assert(first_layer == 0); break; default: assert(!"unexpected surface type"); break; } /* non-full array spacing is supported only on GEN7+ */ assert(img->layout.walk != INTEL_LAYOUT_WALK_LOD); /* non-interleaved samples are supported only on GEN7+ */ if (img->sample_count > 1) assert(img->layout.interleaved_samples); if (is_rt) { assert(num_levels == 1); lod = first_level; } else { lod = num_levels - 1; } /* * From the Sandy Bridge PRM, volume 4 part 1, page 76: * * "Linear render target surface base addresses 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.)" * * From the Sandy Bridge PRM, volume 4 part 1, page 81: * * "For linear render target surfaces, the pitch must be a multiple * of the element size for non-YUV surface formats. Pitch must be a * multiple of 2 * element size for YUV surface formats." * * From the Sandy Bridge PRM, volume 4 part 1, page 86: * * "For linear surfaces, this field (X Offset) must be zero" */ if (img->layout.tiling == GEN6_TILING_NONE) { if (is_rt) { const int elem_size U_ASSERT_ONLY = icd_format_get_size(format); assert(pitch % elem_size == 0); } } dw[0] = surface_type << GEN6_SURFACE_DW0_TYPE__SHIFT | surface_format << GEN6_SURFACE_DW0_FORMAT__SHIFT | GEN6_SURFACE_DW0_MIPLAYOUT_BELOW; if (surface_type == GEN6_SURFTYPE_CUBE && !is_rt) { dw[0] |= 1 << 9 | GEN6_SURFACE_DW0_CUBE_FACE_ENABLES__MASK; } if (is_rt) dw[0] |= GEN6_SURFACE_DW0_RENDER_CACHE_RW; dw[1] = 0; dw[2] = (height - 1) << GEN6_SURFACE_DW2_HEIGHT__SHIFT | (width - 1) << GEN6_SURFACE_DW2_WIDTH__SHIFT | lod << GEN6_SURFACE_DW2_MIP_COUNT_LOD__SHIFT; assert(img->layout.tiling != GEN8_TILING_W); dw[3] = (depth - 1) << GEN6_SURFACE_DW3_DEPTH__SHIFT | (pitch - 1) << GEN6_SURFACE_DW3_PITCH__SHIFT | img->layout.tiling; dw[4] = first_level << GEN6_SURFACE_DW4_MIN_LOD__SHIFT | first_layer << 17 | (num_layers - 1) << 8 | ((img->sample_count > 1) ? GEN6_SURFACE_DW4_MULTISAMPLECOUNT_4 : GEN6_SURFACE_DW4_MULTISAMPLECOUNT_1); dw[5] = 0; assert(img->layout.align_j == 2 || img->layout.align_j == 4); if (img->layout.align_j == 4) dw[5] |= GEN6_SURFACE_DW5_VALIGN_4; }
static void surface_state_buf_gen6(const struct intel_gpu *gpu, unsigned offset, unsigned size, unsigned struct_size, VkFormat elem_format, bool is_rt, bool render_cache_rw, uint32_t dw[6]) { const bool typed = !icd_format_is_undef(elem_format); const int elem_size = icd_format_get_size(elem_format); int width, height, depth, pitch; int surface_format, num_entries; INTEL_GPU_ASSERT(gpu, 6, 6); /* * For SURFTYPE_BUFFER, a SURFACE_STATE specifies an element of a * structure in a buffer. */ surface_format = (typed) ? intel_format_translate_color(gpu, elem_format) : GEN6_FORMAT_RAW; num_entries = size / struct_size; /* see if there is enough space to fit another element */ if (size % struct_size >= elem_size) num_entries++; /* * From the Sandy Bridge PRM, volume 4 part 1, page 76: * * "For SURFTYPE_BUFFER render targets, this field (Surface Base * Address) specifies the base address of first element of the * surface. The surface is interpreted as a simple array of that * single element type. The address must be naturally-aligned to the * element size (e.g., a buffer containing R32G32B32A32_FLOAT elements * must be 16-byte aligned). * * For SURFTYPE_BUFFER non-rendertarget surfaces, this field specifies * the base address of the first element of the surface, computed in * software by adding the surface base address to the byte offset of * the element in the buffer." */ if (is_rt) assert(offset % elem_size == 0); /* * 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." */ assert(num_entries >= 1 && num_entries <= 1 << 27); /* * From the Sandy Bridge PRM, volume 4 part 1, page 81: * * "For surfaces of type SURFTYPE_BUFFER, this field (Surface Pitch) * indicates the size of the structure." */ pitch = struct_size; pitch--; num_entries--; /* bits [6:0] */ width = (num_entries & 0x0000007f); /* bits [19:7] */ height = (num_entries & 0x000fff80) >> 7; /* bits [26:20] */ depth = (num_entries & 0x07f00000) >> 20; dw[0] = GEN6_SURFTYPE_BUFFER << GEN6_SURFACE_DW0_TYPE__SHIFT | surface_format << GEN6_SURFACE_DW0_FORMAT__SHIFT; if (render_cache_rw) dw[0] |= GEN6_SURFACE_DW0_RENDER_CACHE_RW; dw[1] = offset; dw[2] = height << GEN6_SURFACE_DW2_HEIGHT__SHIFT | width << GEN6_SURFACE_DW2_WIDTH__SHIFT; dw[3] = depth << GEN6_SURFACE_DW3_DEPTH__SHIFT | pitch << GEN6_SURFACE_DW3_PITCH__SHIFT; dw[4] = 0; dw[5] = 0; }
static void surface_state_tex_gen7(const struct intel_gpu *gpu, const struct intel_img *img, VkImageViewType type, VkFormat format, unsigned first_level, unsigned num_levels, unsigned first_layer, unsigned num_layers, VkComponentMapping swizzles, bool is_rt, uint32_t dw[8]) { int surface_type, surface_format; int width, height, depth, pitch, lod; INTEL_GPU_ASSERT(gpu, 7, 7.5); surface_type = view_type_to_surface_type(type); assert(surface_type != GEN6_SURFTYPE_BUFFER); surface_format = intel_format_translate_color(gpu, format); assert(surface_format >= 0); width = img->layout.width0; height = img->layout.height0; depth = (type == VK_IMAGE_VIEW_TYPE_3D) ? img->depth : num_layers; pitch = img->layout.bo_stride; if (surface_type == GEN6_SURFTYPE_CUBE) { /* * From the Ivy Bridge PRM, volume 4 part 1, page 70: * * "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." * * When is_rt is true, we treat the texture as a 2D one to avoid the * restriction. */ if (is_rt) { surface_type = GEN6_SURFTYPE_2D; } else { assert(num_layers % 6 == 0); depth = num_layers / 6; } } /* sanity check the size */ assert(width >= 1 && height >= 1 && depth >= 1 && pitch >= 1); assert(first_layer < 2048 && num_layers <= 2048); switch (surface_type) { case GEN6_SURFTYPE_1D: assert(width <= 16384 && height == 1 && depth <= 2048); break; case GEN6_SURFTYPE_2D: assert(width <= 16384 && height <= 16384 && depth <= 2048); break; case GEN6_SURFTYPE_3D: assert(width <= 2048 && height <= 2048 && depth <= 2048); if (!is_rt) assert(first_layer == 0); break; case GEN6_SURFTYPE_CUBE: assert(width <= 16384 && height <= 16384 && depth <= 86); assert(width == height); if (is_rt) assert(first_layer == 0); break; default: assert(!"unexpected surface type"); break; } if (is_rt) { assert(num_levels == 1); lod = first_level; } else { lod = num_levels - 1; } /* * 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)." * * From the Ivy Bridge PRM, volume 4 part 1, page 70: * * "For linear render target surfaces and surfaces accessed with the * typed data port messages, the pitch must be a multiple of the * element size for non-YUV surface formats. Pitch must be a multiple * of 2 * element size for YUV surface formats. For linear surfaces * with Surface Type of SURFTYPE_STRBUF, the pitch must be a multiple * of 4 bytes.For other linear surfaces, the pitch can be any multiple * of bytes." * * From the Ivy Bridge PRM, volume 4 part 1, page 74: * * "For linear surfaces, this field (X Offset) must be zero." */ if (img->layout.tiling == GEN6_TILING_NONE) { if (is_rt) { const int elem_size U_ASSERT_ONLY = icd_format_get_size(format); assert(pitch % elem_size == 0); } } assert(img->layout.tiling != GEN8_TILING_W); dw[0] = surface_type << GEN7_SURFACE_DW0_TYPE__SHIFT | surface_format << GEN7_SURFACE_DW0_FORMAT__SHIFT | img->layout.tiling << 13; /* * 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." * * For non-3D sampler surfaces, resinfo (the sampler message) always * returns zero for the number of layers when this field is not set. */ if (surface_type != GEN6_SURFTYPE_3D) { if (num_layers > 1) dw[0] |= GEN7_SURFACE_DW0_IS_ARRAY; else assert(depth == 1); } assert(img->layout.align_i == 4 || img->layout.align_i == 8); assert(img->layout.align_j == 2 || img->layout.align_j == 4); if (img->layout.align_j == 4) dw[0] |= GEN7_SURFACE_DW0_VALIGN_4; if (img->layout.align_i == 8) dw[0] |= GEN7_SURFACE_DW0_HALIGN_8; if (img->layout.walk == INTEL_LAYOUT_WALK_LOD) dw[0] |= GEN7_SURFACE_DW0_ARYSPC_LOD0; else dw[0] |= GEN7_SURFACE_DW0_ARYSPC_FULL; if (is_rt) dw[0] |= GEN7_SURFACE_DW0_RENDER_CACHE_RW; if (surface_type == GEN6_SURFTYPE_CUBE && !is_rt) dw[0] |= GEN7_SURFACE_DW0_CUBE_FACE_ENABLES__MASK; dw[1] = 0; dw[2] = (height - 1) << GEN7_SURFACE_DW2_HEIGHT__SHIFT | (width - 1) << GEN7_SURFACE_DW2_WIDTH__SHIFT; dw[3] = (depth - 1) << GEN7_SURFACE_DW3_DEPTH__SHIFT | (pitch - 1); dw[4] = first_layer << 18 | (num_layers - 1) << 7; /* * 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 (img->layout.interleaved_samples && img->sample_count > 1) { assert(!is_rt); dw[4] |= GEN7_SURFACE_DW4_MSFMT_DEPTH_STENCIL; } else { dw[4] |= GEN7_SURFACE_DW4_MSFMT_MSS; } if (img->sample_count > 4) dw[4] |= GEN7_SURFACE_DW4_MULTISAMPLECOUNT_8; else if (img->sample_count > 2) dw[4] |= GEN7_SURFACE_DW4_MULTISAMPLECOUNT_4; else dw[4] |= GEN7_SURFACE_DW4_MULTISAMPLECOUNT_1; dw[5] = GEN7_MOCS_L3_WB << GEN7_SURFACE_DW5_MOCS__SHIFT | (first_level) << GEN7_SURFACE_DW5_MIN_LOD__SHIFT | lod; dw[6] = 0; dw[7] = 0; if (intel_gpu_gen(gpu) >= INTEL_GEN(7.5)) { dw[7] |= channel_swizzle_to_scs((swizzles.r == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_R : swizzles.r) << GEN75_SURFACE_DW7_SCS_R__SHIFT | channel_swizzle_to_scs((swizzles.g == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_G : swizzles.g) << GEN75_SURFACE_DW7_SCS_G__SHIFT | channel_swizzle_to_scs((swizzles.b == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_B : swizzles.b) << GEN75_SURFACE_DW7_SCS_B__SHIFT | channel_swizzle_to_scs((swizzles.a == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_A : swizzles.a) << GEN75_SURFACE_DW7_SCS_A__SHIFT; } else { assert(((swizzles.r == VK_COMPONENT_SWIZZLE_R) || (swizzles.r == VK_COMPONENT_SWIZZLE_IDENTITY)) && ((swizzles.g == VK_COMPONENT_SWIZZLE_G) || (swizzles.g == VK_COMPONENT_SWIZZLE_IDENTITY)) && ((swizzles.b == VK_COMPONENT_SWIZZLE_B) || (swizzles.b == VK_COMPONENT_SWIZZLE_IDENTITY)) && ((swizzles.a == VK_COMPONENT_SWIZZLE_A) || (swizzles.a == VK_COMPONENT_SWIZZLE_IDENTITY))); } }