2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 #include "anv_private.h"
32 #include "gen8_pack.h"
33 #include "gen9_pack.h"
35 #include "genX_state_util.h"
38 genX(fill_buffer_surface_state
)(void *state
, enum isl_format format
,
39 uint32_t offset
, uint32_t range
, uint32_t stride
)
41 uint32_t num_elements
= range
/ stride
;
43 struct GENX(RENDER_SURFACE_STATE
) surface_state
= {
44 .SurfaceType
= SURFTYPE_BUFFER
,
45 .SurfaceArray
= false,
46 .SurfaceFormat
= format
,
47 .SurfaceVerticalAlignment
= VALIGN4
,
48 .SurfaceHorizontalAlignment
= HALIGN4
,
50 .SamplerL2BypassModeDisable
= true,
51 .RenderCacheReadWriteMode
= WriteOnlyCache
,
52 .MemoryObjectControlState
= GENX(MOCS
),
53 .Height
= ((num_elements
- 1) >> 7) & 0x3fff,
54 .Width
= (num_elements
- 1) & 0x7f,
55 .Depth
= ((num_elements
- 1) >> 21) & 0x3f,
56 .SurfacePitch
= stride
- 1,
57 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
58 .ShaderChannelSelectRed
= SCS_RED
,
59 .ShaderChannelSelectGreen
= SCS_GREEN
,
60 .ShaderChannelSelectBlue
= SCS_BLUE
,
61 .ShaderChannelSelectAlpha
= SCS_ALPHA
,
62 /* FIXME: We assume that the image must be bound at this time. */
63 .SurfaceBaseAddress
= { NULL
, offset
},
66 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, state
, &surface_state
);
69 static const uint8_t anv_halign
[] = {
75 static const uint8_t anv_valign
[] = {
81 static struct anv_state
82 alloc_surface_state(struct anv_device
*device
,
83 struct anv_cmd_buffer
*cmd_buffer
)
86 return anv_cmd_buffer_alloc_surface_state(cmd_buffer
);
88 return anv_state_pool_alloc(&device
->surface_state_pool
, 64, 64);
93 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
94 * and SurfaceVerticalAlignment.
97 get_halign_valign(const struct isl_surf
*surf
, uint32_t *halign
, uint32_t *valign
)
100 if (isl_tiling_is_std_y(surf
->tiling
) ||
101 surf
->dim_layout
== ISL_DIM_LAYOUT_GEN9_1D
) {
102 /* The hardware ignores the alignment values. Anyway, the surface's
103 * true alignment is likely outside the enum range of HALIGN* and
109 /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
110 * of surface elements (not pixels nor samples). For compressed formats,
111 * a "surface element" is defined as a compression block. For example,
112 * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
113 * format (ETC2 has a block height of 4), then the vertical alignment is
114 * 4 compression blocks or, equivalently, 16 pixels.
116 struct isl_extent3d image_align_el
117 = isl_surf_get_image_alignment_el(surf
);
119 *halign
= anv_halign
[image_align_el
.width
];
120 *valign
= anv_valign
[image_align_el
.height
];
123 /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
124 * units of surface samples. For example, if SurfaceVerticalAlignment
125 * is VALIGN_4 and the surface is singlesampled, then for any surface
126 * format (compressed or not) the vertical alignment is
129 struct isl_extent3d image_align_sa
130 = isl_surf_get_image_alignment_sa(surf
);
132 *halign
= anv_halign
[image_align_sa
.width
];
133 *valign
= anv_valign
[image_align_sa
.height
];
138 get_qpitch(const struct isl_surf
*surf
)
142 unreachable(!"bad isl_surf_dim");
143 case ISL_SURF_DIM_1D
:
145 /* QPitch is usually expressed as rows of surface elements (where
146 * a surface element is an compression block or a single surface
147 * sample). Skylake 1D is an outlier.
149 * From the Skylake BSpec >> Memory Views >> Common Surface
150 * Formats >> Surface Layout and Tiling >> 1D Surfaces:
152 * Surface QPitch specifies the distance in pixels between array
155 return isl_surf_get_array_pitch_el(surf
);
157 return isl_surf_get_array_pitch_el_rows(surf
);
159 case ISL_SURF_DIM_2D
:
160 case ISL_SURF_DIM_3D
:
161 return isl_surf_get_array_pitch_el_rows(surf
);
166 genX(image_view_init
)(struct anv_image_view
*iview
,
167 struct anv_device
*device
,
168 const VkImageViewCreateInfo
* pCreateInfo
,
169 struct anv_cmd_buffer
*cmd_buffer
)
171 ANV_FROM_HANDLE(anv_image
, image
, pCreateInfo
->image
);
173 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
175 struct anv_surface
*surface
=
176 anv_image_get_surface_for_aspect_mask(image
, range
->aspectMask
);
178 static const uint8_t isl_to_gen_tiling
[] = {
179 [ISL_TILING_LINEAR
] = LINEAR
,
180 [ISL_TILING_X
] = XMAJOR
,
181 [ISL_TILING_Y0
] = YMAJOR
,
182 [ISL_TILING_Yf
] = YMAJOR
,
183 [ISL_TILING_Ys
] = YMAJOR
,
184 [ISL_TILING_W
] = WMAJOR
,
187 uint32_t halign
, valign
;
188 get_halign_valign(&surface
->isl
, &halign
, &valign
);
190 struct GENX(RENDER_SURFACE_STATE
) surface_state
= {
191 .SurfaceType
= anv_surftype(image
, pCreateInfo
->viewType
, false),
192 .SurfaceArray
= image
->array_size
> 1,
193 .SurfaceFormat
= iview
->format
,
194 .SurfaceVerticalAlignment
= valign
,
195 .SurfaceHorizontalAlignment
= halign
,
196 .TileMode
= isl_to_gen_tiling
[surface
->isl
.tiling
],
197 .VerticalLineStride
= 0,
198 .VerticalLineStrideOffset
= 0,
199 .SamplerL2BypassModeDisable
= true,
200 .RenderCacheReadWriteMode
= WriteOnlyCache
,
201 .MemoryObjectControlState
= GENX(MOCS
),
203 /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
204 * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
205 * both Base Mip Level fields nonzero".
209 .SurfaceQPitch
= get_qpitch(&surface
->isl
) >> 2,
210 .Height
= image
->extent
.height
- 1,
211 .Width
= image
->extent
.width
- 1,
212 .Depth
= 0, /* TEMPLATE */
213 .SurfacePitch
= surface
->isl
.row_pitch
- 1,
214 .RenderTargetViewExtent
= 0, /* TEMPLATE */
215 .MinimumArrayElement
= 0, /* TEMPLATE */
216 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
220 .MIPCountLOD
= 0, /* TEMPLATE */
221 .SurfaceMinLOD
= 0, /* TEMPLATE */
223 .AuxiliarySurfaceMode
= AUX_NONE
,
225 .GreenClearColor
= 0,
227 .AlphaClearColor
= 0,
228 .ShaderChannelSelectRed
= vk_to_gen_swizzle(pCreateInfo
->components
.r
,
229 VK_COMPONENT_SWIZZLE_R
),
230 .ShaderChannelSelectGreen
= vk_to_gen_swizzle(pCreateInfo
->components
.g
,
231 VK_COMPONENT_SWIZZLE_G
),
232 .ShaderChannelSelectBlue
= vk_to_gen_swizzle(pCreateInfo
->components
.b
,
233 VK_COMPONENT_SWIZZLE_B
),
234 .ShaderChannelSelectAlpha
= vk_to_gen_swizzle(pCreateInfo
->components
.a
,
235 VK_COMPONENT_SWIZZLE_A
),
236 .ResourceMinLOD
= 0.0,
237 .SurfaceBaseAddress
= { NULL
, iview
->offset
},
240 switch (surface_state
.SurfaceType
) {
243 surface_state
.MinimumArrayElement
= range
->baseArrayLayer
;
245 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
247 * For SURFTYPE_1D, 2D, and CUBE: The range of this field is reduced
248 * by one for each increase from zero of Minimum Array Element. For
249 * example, if Minimum Array Element is set to 1024 on a 2D surface,
250 * the range of this field is reduced to [0,1023].
252 * In other words, 'Depth' is the number of array layers.
254 surface_state
.Depth
= range
->layerCount
- 1;
256 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
258 * For Render Target and Typed Dataport 1D and 2D Surfaces:
259 * This field must be set to the same value as the Depth field.
261 surface_state
.RenderTargetViewExtent
= surface_state
.Depth
;
265 /* Like SURFTYPE_2D, but divided by 6. */
266 surface_state
.MinimumArrayElement
= range
->baseArrayLayer
/ 6;
267 surface_state
.Depth
= range
->layerCount
/ 6 - 1;
268 surface_state
.RenderTargetViewExtent
= surface_state
.Depth
;
270 /* Same as SURFTYPE_2D */
271 surface_state
.MinimumArrayElement
= range
->baseArrayLayer
;
272 surface_state
.Depth
= range
->layerCount
- 1;
273 surface_state
.RenderTargetViewExtent
= surface_state
.Depth
;
277 surface_state
.MinimumArrayElement
= range
->baseArrayLayer
;
279 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
281 * If the volume texture is MIP-mapped, this field specifies the
282 * depth of the base MIP level.
284 surface_state
.Depth
= image
->extent
.depth
- 1;
286 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
288 * For Render Target and Typed Dataport 3D Surfaces: This field
289 * indicates the extent of the accessible 'R' coordinates minus 1 on
290 * the LOD currently being rendered to.
292 surface_state
.RenderTargetViewExtent
= iview
->extent
.depth
- 1;
295 unreachable(!"bad SurfaceType");
298 if (image
->needs_nonrt_surface_state
) {
299 iview
->nonrt_surface_state
=
300 alloc_surface_state(device
, cmd_buffer
);
302 /* For non render target surfaces, the hardware interprets field
303 * MIPCount/LOD as MIPCount. The range of levels accessible by the
304 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
306 surface_state
.SurfaceMinLOD
= range
->baseMipLevel
;
307 surface_state
.MIPCountLOD
= MAX2(range
->levelCount
, 1) - 1;
309 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->nonrt_surface_state
.map
,
311 if (!device
->info
.has_llc
)
312 anv_state_clflush(iview
->nonrt_surface_state
);
314 iview
->nonrt_surface_state
.alloc_size
= 0;
317 if (image
->needs_color_rt_surface_state
) {
318 iview
->color_rt_surface_state
=
319 alloc_surface_state(device
, cmd_buffer
);
321 /* For render target surfaces, the hardware interprets field
322 * MIPCount/LOD as LOD. The Broadwell PRM says:
324 * MIPCountLOD defines the LOD that will be rendered into.
325 * SurfaceMinLOD is ignored.
327 surface_state
.MIPCountLOD
= range
->baseMipLevel
;
328 surface_state
.SurfaceMinLOD
= 0;
330 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->color_rt_surface_state
.map
,
332 if (!device
->info
.has_llc
)
333 anv_state_clflush(iview
->color_rt_surface_state
);
335 iview
->color_rt_surface_state
.alloc_size
= 0;
338 if (image
->needs_storage_surface_state
) {
339 iview
->storage_surface_state
=
340 alloc_surface_state(device
, cmd_buffer
);
342 surface_state
.SurfaceType
=
343 anv_surftype(image
, pCreateInfo
->viewType
, true),
345 surface_state
.SurfaceFormat
=
346 isl_lower_storage_image_format(&device
->isl_dev
, iview
->format
);
348 surface_state
.SurfaceMinLOD
= range
->baseMipLevel
;
349 surface_state
.MIPCountLOD
= MAX2(range
->levelCount
, 1) - 1;
351 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->storage_surface_state
.map
,
354 iview
->storage_surface_state
.alloc_size
= 0;
358 VkResult
genX(CreateSampler
)(
360 const VkSamplerCreateInfo
* pCreateInfo
,
361 const VkAllocationCallbacks
* pAllocator
,
364 ANV_FROM_HANDLE(anv_device
, device
, _device
);
365 struct anv_sampler
*sampler
;
366 uint32_t mag_filter
, min_filter
, max_anisotropy
;
368 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
);
370 sampler
= anv_alloc2(&device
->alloc
, pAllocator
, sizeof(*sampler
), 8,
371 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
373 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
375 if (pCreateInfo
->maxAnisotropy
> 1) {
376 mag_filter
= MAPFILTER_ANISOTROPIC
;
377 min_filter
= MAPFILTER_ANISOTROPIC
;
378 max_anisotropy
= (pCreateInfo
->maxAnisotropy
- 2) / 2;
380 mag_filter
= vk_to_gen_tex_filter
[pCreateInfo
->magFilter
];
381 min_filter
= vk_to_gen_tex_filter
[pCreateInfo
->minFilter
];
382 max_anisotropy
= RATIO21
;
385 struct GENX(SAMPLER_STATE
) sampler_state
= {
386 .SamplerDisable
= false,
387 .TextureBorderColorMode
= DX10OGL
,
388 .LODPreClampMode
= 0,
392 .MipModeFilter
= vk_to_gen_mipmap_mode
[pCreateInfo
->mipmapMode
],
393 .MagModeFilter
= mag_filter
,
394 .MinModeFilter
= min_filter
,
395 .TextureLODBias
= anv_clamp_f(pCreateInfo
->mipLodBias
, -16, 15.996),
396 .AnisotropicAlgorithm
= EWAApproximation
,
397 .MinLOD
= anv_clamp_f(pCreateInfo
->minLod
, 0, 14),
398 .MaxLOD
= anv_clamp_f(pCreateInfo
->maxLod
, 0, 14),
399 .ChromaKeyEnable
= 0,
402 .ShadowFunction
= vk_to_gen_compare_op
[pCreateInfo
->compareOp
],
403 .CubeSurfaceControlMode
= 0,
405 .IndirectStatePointer
=
406 device
->border_colors
.offset
+
407 pCreateInfo
->borderColor
* sizeof(float) * 4,
409 .LODClampMagnificationMode
= MIPNONE
,
410 .MaximumAnisotropy
= max_anisotropy
,
411 .RAddressMinFilterRoundingEnable
= 0,
412 .RAddressMagFilterRoundingEnable
= 0,
413 .VAddressMinFilterRoundingEnable
= 0,
414 .VAddressMagFilterRoundingEnable
= 0,
415 .UAddressMinFilterRoundingEnable
= 0,
416 .UAddressMagFilterRoundingEnable
= 0,
417 .TrilinearFilterQuality
= 0,
418 .NonnormalizedCoordinateEnable
= pCreateInfo
->unnormalizedCoordinates
,
419 .TCXAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeU
],
420 .TCYAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeV
],
421 .TCZAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeW
],
424 GENX(SAMPLER_STATE_pack
)(NULL
, sampler
->state
, &sampler_state
);
426 *pSampler
= anv_sampler_to_handle(sampler
);