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"
36 anv_surftype(const struct anv_image
*image
, VkImageViewType view_type
,
41 unreachable("bad VkImageViewType");
42 case VK_IMAGE_VIEW_TYPE_1D
:
43 case VK_IMAGE_VIEW_TYPE_1D_ARRAY
:
44 assert(image
->type
== VK_IMAGE_TYPE_1D
);
46 case VK_IMAGE_VIEW_TYPE_CUBE
:
47 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
:
48 assert(image
->type
== VK_IMAGE_TYPE_2D
);
49 return storage
? SURFTYPE_2D
: SURFTYPE_CUBE
;
50 case VK_IMAGE_VIEW_TYPE_2D
:
51 case VK_IMAGE_VIEW_TYPE_2D_ARRAY
:
52 assert(image
->type
== VK_IMAGE_TYPE_2D
);
54 case VK_IMAGE_VIEW_TYPE_3D
:
55 assert(image
->type
== VK_IMAGE_TYPE_3D
);
61 genX(fill_buffer_surface_state
)(void *state
, enum isl_format format
,
62 uint32_t offset
, uint32_t range
, uint32_t stride
)
64 uint32_t num_elements
= range
/ stride
;
66 struct GENX(RENDER_SURFACE_STATE
) surface_state
= {
67 .SurfaceType
= SURFTYPE_BUFFER
,
68 .SurfaceArray
= false,
69 .SurfaceFormat
= format
,
70 .SurfaceVerticalAlignment
= VALIGN4
,
71 .SurfaceHorizontalAlignment
= HALIGN4
,
73 .SamplerL2BypassModeDisable
= true,
74 .RenderCacheReadWriteMode
= WriteOnlyCache
,
75 .MemoryObjectControlState
= GENX(MOCS
),
76 .Height
= ((num_elements
- 1) >> 7) & 0x3fff,
77 .Width
= (num_elements
- 1) & 0x7f,
78 .Depth
= ((num_elements
- 1) >> 21) & 0x3f,
79 .SurfacePitch
= stride
- 1,
80 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
81 .ShaderChannelSelectRed
= SCS_RED
,
82 .ShaderChannelSelectGreen
= SCS_GREEN
,
83 .ShaderChannelSelectBlue
= SCS_BLUE
,
84 .ShaderChannelSelectAlpha
= SCS_ALPHA
,
85 /* FIXME: We assume that the image must be bound at this time. */
86 .SurfaceBaseAddress
= { NULL
, offset
},
89 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, state
, &surface_state
);
92 static const uint8_t anv_halign
[] = {
98 static const uint8_t anv_valign
[] = {
104 static struct anv_state
105 alloc_surface_state(struct anv_device
*device
,
106 struct anv_cmd_buffer
*cmd_buffer
)
109 return anv_cmd_buffer_alloc_surface_state(cmd_buffer
);
111 return anv_state_pool_alloc(&device
->surface_state_pool
, 64, 64);
115 static const uint32_t vk_to_gen_swizzle_map
[] = {
116 [VK_COMPONENT_SWIZZLE_ZERO
] = SCS_ZERO
,
117 [VK_COMPONENT_SWIZZLE_ONE
] = SCS_ONE
,
118 [VK_COMPONENT_SWIZZLE_R
] = SCS_RED
,
119 [VK_COMPONENT_SWIZZLE_G
] = SCS_GREEN
,
120 [VK_COMPONENT_SWIZZLE_B
] = SCS_BLUE
,
121 [VK_COMPONENT_SWIZZLE_A
] = SCS_ALPHA
124 static inline uint32_t
125 vk_to_gen_swizzle(VkComponentSwizzle swizzle
, VkComponentSwizzle component
)
127 if (swizzle
== VK_COMPONENT_SWIZZLE_IDENTITY
)
128 return vk_to_gen_swizzle_map
[component
];
130 return vk_to_gen_swizzle_map
[swizzle
];
134 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
135 * and SurfaceVerticalAlignment.
138 get_halign_valign(const struct isl_surf
*surf
, uint32_t *halign
, uint32_t *valign
)
141 /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
142 * of surface elements (not pixels nor samples). For compressed formats,
143 * a "surface element" is defined as a compression block. For example,
144 * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
145 * format (ETC2 has a block height of 4), then the vertical alignment is
146 * 4 compression blocks or, equivalently, 16 pixels.
148 struct isl_extent3d image_align_el
149 = isl_surf_get_image_alignment_el(surf
);
151 *halign
= anv_halign
[image_align_el
.width
];
152 *valign
= anv_valign
[image_align_el
.height
];
154 /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
155 * units of surface samples. For example, if SurfaceVerticalAlignment
156 * is VALIGN_4 and the surface is singlesampled, then for any surface
157 * format (compressed or not) the vertical alignment is
160 struct isl_extent3d image_align_sa
161 = isl_surf_get_image_alignment_sa(surf
);
163 *halign
= anv_halign
[image_align_sa
.width
];
164 *valign
= anv_valign
[image_align_sa
.height
];
169 genX(image_view_init
)(struct anv_image_view
*iview
,
170 struct anv_device
*device
,
171 const VkImageViewCreateInfo
* pCreateInfo
,
172 struct anv_cmd_buffer
*cmd_buffer
)
174 ANV_FROM_HANDLE(anv_image
, image
, pCreateInfo
->image
);
176 const VkImageSubresourceRange
*range
= &pCreateInfo
->subresourceRange
;
178 struct anv_surface
*surface
=
179 anv_image_get_surface_for_aspect_mask(image
, range
->aspectMask
);
181 uint32_t depth
= 1; /* RENDER_SURFACE_STATE::Depth */
182 uint32_t rt_view_extent
= 1; /* RENDER_SURFACE_STATE::RenderTargetViewExtent */
184 const struct anv_format
*format_info
=
185 anv_format_for_vk_format(pCreateInfo
->format
);
187 iview
->image
= image
;
188 iview
->bo
= image
->bo
;
189 iview
->offset
= image
->offset
+ surface
->offset
;
190 iview
->format
= format_info
;
192 iview
->extent
= (VkExtent3D
) {
193 .width
= anv_minify(image
->extent
.width
, range
->baseMipLevel
),
194 .height
= anv_minify(image
->extent
.height
, range
->baseMipLevel
),
195 .depth
= anv_minify(image
->extent
.depth
, range
->baseMipLevel
),
198 switch (image
->type
) {
199 case VK_IMAGE_TYPE_1D
:
200 case VK_IMAGE_TYPE_2D
:
201 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
203 * For SURFTYPE_1D, 2D, and CUBE: The range of this field is reduced
204 * by one for each increase from zero of Minimum Array Element. For
205 * example, if Minimum Array Element is set to 1024 on a 2D surface,
206 * the range of this field is reduced to [0,1023].
208 depth
= range
->layerCount
;
210 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
212 * For Render Target and Typed Dataport 1D and 2D Surfaces:
213 * This field must be set to the same value as the Depth field.
215 rt_view_extent
= depth
;
217 case VK_IMAGE_TYPE_3D
:
218 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
220 * If the volume texture is MIP-mapped, this field specifies the
221 * depth of the base MIP level.
223 depth
= image
->extent
.depth
;
225 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
227 * For Render Target and Typed Dataport 3D Surfaces: This field
228 * indicates the extent of the accessible 'R' coordinates minus 1 on
229 * the LOD currently being rendered to.
231 rt_view_extent
= iview
->extent
.depth
;
234 unreachable(!"bad VkImageType");
237 static const uint8_t isl_to_gen_tiling
[] = {
238 [ISL_TILING_LINEAR
] = LINEAR
,
239 [ISL_TILING_X
] = XMAJOR
,
240 [ISL_TILING_Y0
] = YMAJOR
,
241 [ISL_TILING_Yf
] = YMAJOR
,
242 [ISL_TILING_Ys
] = YMAJOR
,
243 [ISL_TILING_W
] = WMAJOR
,
246 uint32_t halign
, valign
;
247 get_halign_valign(&surface
->isl
, &halign
, &valign
);
249 struct GENX(RENDER_SURFACE_STATE
) surface_state
= {
250 .SurfaceType
= anv_surftype(image
, pCreateInfo
->viewType
, false),
251 .SurfaceArray
= image
->array_size
> 1,
252 .SurfaceFormat
= format_info
->surface_format
,
253 .SurfaceVerticalAlignment
= valign
,
254 .SurfaceHorizontalAlignment
= halign
,
255 .TileMode
= isl_to_gen_tiling
[surface
->isl
.tiling
],
256 .VerticalLineStride
= 0,
257 .VerticalLineStrideOffset
= 0,
258 .SamplerL2BypassModeDisable
= true,
259 .RenderCacheReadWriteMode
= WriteOnlyCache
,
260 .MemoryObjectControlState
= GENX(MOCS
),
262 /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
263 * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
264 * both Base Mip Level fields nonzero".
268 .SurfaceQPitch
= isl_surf_get_array_pitch_el_rows(&surface
->isl
) >> 2,
269 .Height
= image
->extent
.height
- 1,
270 .Width
= image
->extent
.width
- 1,
272 .SurfacePitch
= surface
->isl
.row_pitch
- 1,
273 .RenderTargetViewExtent
= rt_view_extent
- 1,
274 .MinimumArrayElement
= range
->baseArrayLayer
,
275 .NumberofMultisamples
= MULTISAMPLECOUNT_1
,
279 .MIPCountLOD
= 0, /* TEMPLATE */
280 .SurfaceMinLOD
= 0, /* TEMPLATE */
282 .AuxiliarySurfaceMode
= AUX_NONE
,
284 .GreenClearColor
= 0,
286 .AlphaClearColor
= 0,
287 .ShaderChannelSelectRed
= vk_to_gen_swizzle(pCreateInfo
->components
.r
,
288 VK_COMPONENT_SWIZZLE_R
),
289 .ShaderChannelSelectGreen
= vk_to_gen_swizzle(pCreateInfo
->components
.g
,
290 VK_COMPONENT_SWIZZLE_G
),
291 .ShaderChannelSelectBlue
= vk_to_gen_swizzle(pCreateInfo
->components
.b
,
292 VK_COMPONENT_SWIZZLE_B
),
293 .ShaderChannelSelectAlpha
= vk_to_gen_swizzle(pCreateInfo
->components
.a
,
294 VK_COMPONENT_SWIZZLE_A
),
295 .ResourceMinLOD
= 0.0,
296 .SurfaceBaseAddress
= { NULL
, iview
->offset
},
299 if (image
->needs_nonrt_surface_state
) {
300 iview
->nonrt_surface_state
=
301 alloc_surface_state(device
, cmd_buffer
);
303 /* For non render target surfaces, the hardware interprets field
304 * MIPCount/LOD as MIPCount. The range of levels accessible by the
305 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
307 surface_state
.SurfaceMinLOD
= range
->baseMipLevel
;
308 surface_state
.MIPCountLOD
= MIN2(range
->levelCount
, 1) - 1;
310 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->nonrt_surface_state
.map
,
312 if (!device
->info
.has_llc
)
313 anv_state_clflush(iview
->nonrt_surface_state
);
316 if (image
->needs_color_rt_surface_state
) {
317 iview
->color_rt_surface_state
=
318 alloc_surface_state(device
, cmd_buffer
);
320 /* For render target surfaces, the hardware interprets field
321 * MIPCount/LOD as LOD. The Broadwell PRM says:
323 * MIPCountLOD defines the LOD that will be rendered into.
324 * SurfaceMinLOD is ignored.
326 surface_state
.MIPCountLOD
= range
->baseMipLevel
;
327 surface_state
.SurfaceMinLOD
= 0;
329 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->color_rt_surface_state
.map
,
331 if (!device
->info
.has_llc
)
332 anv_state_clflush(iview
->color_rt_surface_state
);
335 if (image
->needs_storage_surface_state
) {
336 iview
->storage_surface_state
=
337 alloc_surface_state(device
, cmd_buffer
);
339 surface_state
.SurfaceType
=
340 anv_surftype(image
, pCreateInfo
->viewType
, true),
342 surface_state
.SurfaceFormat
=
343 isl_lower_storage_image_format(&device
->isl_dev
,
344 format_info
->surface_format
);
346 surface_state
.SurfaceMinLOD
= range
->baseMipLevel
;
347 surface_state
.MIPCountLOD
= MIN2(range
->levelCount
, 1) - 1;
349 GENX(RENDER_SURFACE_STATE_pack
)(NULL
, iview
->storage_surface_state
.map
,
354 VkResult
genX(CreateSampler
)(
356 const VkSamplerCreateInfo
* pCreateInfo
,
357 const VkAllocationCallbacks
* pAllocator
,
360 ANV_FROM_HANDLE(anv_device
, device
, _device
);
361 struct anv_sampler
*sampler
;
362 uint32_t mag_filter
, min_filter
, max_anisotropy
;
364 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
);
366 sampler
= anv_alloc2(&device
->alloc
, pAllocator
, sizeof(*sampler
), 8,
367 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
369 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
371 static const uint32_t vk_to_gen_tex_filter
[] = {
372 [VK_FILTER_NEAREST
] = MAPFILTER_NEAREST
,
373 [VK_FILTER_LINEAR
] = MAPFILTER_LINEAR
376 static const uint32_t vk_to_gen_mipmap_mode
[] = {
377 [VK_SAMPLER_MIPMAP_MODE_BASE
] = MIPFILTER_NONE
,
378 [VK_SAMPLER_MIPMAP_MODE_NEAREST
] = MIPFILTER_NEAREST
,
379 [VK_SAMPLER_MIPMAP_MODE_LINEAR
] = MIPFILTER_LINEAR
382 static const uint32_t vk_to_gen_tex_address
[] = {
383 [VK_SAMPLER_ADDRESS_MODE_REPEAT
] = TCM_WRAP
,
384 [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT
] = TCM_MIRROR
,
385 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
] = TCM_CLAMP
,
386 [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE
] = TCM_MIRROR_ONCE
,
387 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
] = TCM_CLAMP_BORDER
,
390 static const uint32_t vk_to_gen_compare_op
[] = {
391 [VK_COMPARE_OP_NEVER
] = PREFILTEROPNEVER
,
392 [VK_COMPARE_OP_LESS
] = PREFILTEROPLESS
,
393 [VK_COMPARE_OP_EQUAL
] = PREFILTEROPEQUAL
,
394 [VK_COMPARE_OP_LESS_OR_EQUAL
] = PREFILTEROPLEQUAL
,
395 [VK_COMPARE_OP_GREATER
] = PREFILTEROPGREATER
,
396 [VK_COMPARE_OP_NOT_EQUAL
] = PREFILTEROPNOTEQUAL
,
397 [VK_COMPARE_OP_GREATER_OR_EQUAL
] = PREFILTEROPGEQUAL
,
398 [VK_COMPARE_OP_ALWAYS
] = PREFILTEROPALWAYS
,
401 if (pCreateInfo
->maxAnisotropy
> 1) {
402 mag_filter
= MAPFILTER_ANISOTROPIC
;
403 min_filter
= MAPFILTER_ANISOTROPIC
;
404 max_anisotropy
= (pCreateInfo
->maxAnisotropy
- 2) / 2;
406 mag_filter
= vk_to_gen_tex_filter
[pCreateInfo
->magFilter
];
407 min_filter
= vk_to_gen_tex_filter
[pCreateInfo
->minFilter
];
408 max_anisotropy
= RATIO21
;
411 struct GENX(SAMPLER_STATE
) sampler_state
= {
412 .SamplerDisable
= false,
413 .TextureBorderColorMode
= DX10OGL
,
414 .LODPreClampMode
= 0,
418 .MipModeFilter
= vk_to_gen_mipmap_mode
[pCreateInfo
->mipmapMode
],
419 .MagModeFilter
= mag_filter
,
420 .MinModeFilter
= min_filter
,
421 .TextureLODBias
= anv_clamp_f(pCreateInfo
->mipLodBias
, -16, 15.996),
422 .AnisotropicAlgorithm
= EWAApproximation
,
423 .MinLOD
= anv_clamp_f(pCreateInfo
->minLod
, 0, 14),
424 .MaxLOD
= anv_clamp_f(pCreateInfo
->maxLod
, 0, 14),
425 .ChromaKeyEnable
= 0,
428 .ShadowFunction
= vk_to_gen_compare_op
[pCreateInfo
->compareOp
],
429 .CubeSurfaceControlMode
= 0,
431 .IndirectStatePointer
=
432 device
->border_colors
.offset
+
433 pCreateInfo
->borderColor
* sizeof(float) * 4,
435 .LODClampMagnificationMode
= MIPNONE
,
436 .MaximumAnisotropy
= max_anisotropy
,
437 .RAddressMinFilterRoundingEnable
= 0,
438 .RAddressMagFilterRoundingEnable
= 0,
439 .VAddressMinFilterRoundingEnable
= 0,
440 .VAddressMagFilterRoundingEnable
= 0,
441 .UAddressMinFilterRoundingEnable
= 0,
442 .UAddressMagFilterRoundingEnable
= 0,
443 .TrilinearFilterQuality
= 0,
444 .NonnormalizedCoordinateEnable
= pCreateInfo
->unnormalizedCoordinates
,
445 .TCXAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeU
],
446 .TCYAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeV
],
447 .TCZAddressControlMode
= vk_to_gen_tex_address
[pCreateInfo
->addressModeW
],
450 GENX(SAMPLER_STATE_pack
)(NULL
, sampler
->state
, &sampler_state
);
452 *pSampler
= anv_sampler_to_handle(sampler
);