anv/state: Allow levelCount to be 0
[mesa.git] / src / vulkan / gen8_state.c
1 /*
2 * Copyright © 2015 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "anv_private.h"
31
32 #include "gen8_pack.h"
33 #include "gen9_pack.h"
34
35 static const uint8_t
36 anv_surftype(const struct anv_image *image, VkImageViewType view_type,
37 bool storage)
38 {
39 switch (view_type) {
40 default:
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);
45 return SURFTYPE_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);
53 return SURFTYPE_2D;
54 case VK_IMAGE_VIEW_TYPE_3D:
55 assert(image->type == VK_IMAGE_TYPE_3D);
56 return SURFTYPE_3D;
57 }
58 }
59
60 void
61 genX(fill_buffer_surface_state)(void *state, enum isl_format format,
62 uint32_t offset, uint32_t range, uint32_t stride)
63 {
64 uint32_t num_elements = range / stride;
65
66 struct GENX(RENDER_SURFACE_STATE) surface_state = {
67 .SurfaceType = SURFTYPE_BUFFER,
68 .SurfaceArray = false,
69 .SurfaceFormat = format,
70 .SurfaceVerticalAlignment = VALIGN4,
71 .SurfaceHorizontalAlignment = HALIGN4,
72 .TileMode = LINEAR,
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 },
87 };
88
89 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
90 }
91
92 static const uint8_t anv_halign[] = {
93 [4] = HALIGN4,
94 [8] = HALIGN8,
95 [16] = HALIGN16,
96 };
97
98 static const uint8_t anv_valign[] = {
99 [4] = VALIGN4,
100 [8] = VALIGN8,
101 [16] = VALIGN16,
102 };
103
104 static struct anv_state
105 alloc_surface_state(struct anv_device *device,
106 struct anv_cmd_buffer *cmd_buffer)
107 {
108 if (cmd_buffer) {
109 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
110 } else {
111 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
112 }
113 }
114
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
122 };
123
124 static inline uint32_t
125 vk_to_gen_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component)
126 {
127 if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY)
128 return vk_to_gen_swizzle_map[component];
129 else
130 return vk_to_gen_swizzle_map[swizzle];
131 }
132
133 /**
134 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
135 * and SurfaceVerticalAlignment.
136 */
137 static void
138 get_halign_valign(const struct isl_surf *surf, uint32_t *halign, uint32_t *valign)
139 {
140 #if ANV_GENx10 >= 90
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.
147 */
148 struct isl_extent3d image_align_el
149 = isl_surf_get_image_alignment_el(surf);
150
151 *halign = anv_halign[image_align_el.width];
152 *valign = anv_valign[image_align_el.height];
153 #else
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
158 * 4 pixels.
159 */
160 struct isl_extent3d image_align_sa
161 = isl_surf_get_image_alignment_sa(surf);
162
163 *halign = anv_halign[image_align_sa.width];
164 *valign = anv_valign[image_align_sa.height];
165 #endif
166 }
167
168 void
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)
173 {
174 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
175
176 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
177
178 struct anv_surface *surface =
179 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
180
181 uint32_t depth = 1; /* RENDER_SURFACE_STATE::Depth */
182 uint32_t rt_view_extent = 1; /* RENDER_SURFACE_STATE::RenderTargetViewExtent */
183
184 const struct anv_format *format_info =
185 anv_format_for_vk_format(pCreateInfo->format);
186
187 iview->image = image;
188 iview->bo = image->bo;
189 iview->offset = image->offset + surface->offset;
190 iview->format = format_info;
191
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),
196 };
197
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:
202 *
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].
207 */
208 depth = range->layerCount;
209
210 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
211 *
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.
214 */
215 rt_view_extent = depth;
216 break;
217 case VK_IMAGE_TYPE_3D:
218 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
219 *
220 * If the volume texture is MIP-mapped, this field specifies the
221 * depth of the base MIP level.
222 */
223 depth = image->extent.depth;
224
225 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
226 *
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.
230 */
231 rt_view_extent = iview->extent.depth;
232 break;
233 default:
234 unreachable(!"bad VkImageType");
235 }
236
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,
244 };
245
246 uint32_t halign, valign;
247 get_halign_valign(&surface->isl, &halign, &valign);
248
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),
261
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".
265 */
266 .BaseMipLevel = 0.0,
267
268 .SurfaceQPitch = isl_surf_get_array_pitch_el_rows(&surface->isl) >> 2,
269 .Height = image->extent.height - 1,
270 .Width = image->extent.width - 1,
271 .Depth = depth - 1,
272 .SurfacePitch = surface->isl.row_pitch - 1,
273 .RenderTargetViewExtent = rt_view_extent - 1,
274 .MinimumArrayElement = range->baseArrayLayer,
275 .NumberofMultisamples = MULTISAMPLECOUNT_1,
276 .XOffset = 0,
277 .YOffset = 0,
278
279 .MIPCountLOD = 0, /* TEMPLATE */
280 .SurfaceMinLOD = 0, /* TEMPLATE */
281
282 .AuxiliarySurfaceMode = AUX_NONE,
283 .RedClearColor = 0,
284 .GreenClearColor = 0,
285 .BlueClearColor = 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 },
297 };
298
299 if (image->needs_nonrt_surface_state) {
300 iview->nonrt_surface_state =
301 alloc_surface_state(device, cmd_buffer);
302
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].
306 */
307 surface_state.SurfaceMinLOD = range->baseMipLevel;
308 surface_state.MIPCountLOD = MIN2(range->levelCount, 1) - 1;
309
310 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
311 &surface_state);
312 if (!device->info.has_llc)
313 anv_state_clflush(iview->nonrt_surface_state);
314 }
315
316 if (image->needs_color_rt_surface_state) {
317 iview->color_rt_surface_state =
318 alloc_surface_state(device, cmd_buffer);
319
320 /* For render target surfaces, the hardware interprets field
321 * MIPCount/LOD as LOD. The Broadwell PRM says:
322 *
323 * MIPCountLOD defines the LOD that will be rendered into.
324 * SurfaceMinLOD is ignored.
325 */
326 surface_state.MIPCountLOD = range->baseMipLevel;
327 surface_state.SurfaceMinLOD = 0;
328
329 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
330 &surface_state);
331 if (!device->info.has_llc)
332 anv_state_clflush(iview->color_rt_surface_state);
333 }
334
335 if (image->needs_storage_surface_state) {
336 iview->storage_surface_state =
337 alloc_surface_state(device, cmd_buffer);
338
339 surface_state.SurfaceType =
340 anv_surftype(image, pCreateInfo->viewType, true),
341
342 surface_state.SurfaceFormat =
343 isl_lower_storage_image_format(&device->isl_dev,
344 format_info->surface_format);
345
346 surface_state.SurfaceMinLOD = range->baseMipLevel;
347 surface_state.MIPCountLOD = MIN2(range->levelCount, 1) - 1;
348
349 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
350 &surface_state);
351 }
352 }
353
354 VkResult genX(CreateSampler)(
355 VkDevice _device,
356 const VkSamplerCreateInfo* pCreateInfo,
357 const VkAllocationCallbacks* pAllocator,
358 VkSampler* pSampler)
359 {
360 ANV_FROM_HANDLE(anv_device, device, _device);
361 struct anv_sampler *sampler;
362 uint32_t mag_filter, min_filter, max_anisotropy;
363
364 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
365
366 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
367 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
368 if (!sampler)
369 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
370
371 static const uint32_t vk_to_gen_tex_filter[] = {
372 [VK_FILTER_NEAREST] = MAPFILTER_NEAREST,
373 [VK_FILTER_LINEAR] = MAPFILTER_LINEAR
374 };
375
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
380 };
381
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,
388 };
389
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,
399 };
400
401 if (pCreateInfo->maxAnisotropy > 1) {
402 mag_filter = MAPFILTER_ANISOTROPIC;
403 min_filter = MAPFILTER_ANISOTROPIC;
404 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
405 } else {
406 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
407 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
408 max_anisotropy = RATIO21;
409 }
410
411 struct GENX(SAMPLER_STATE) sampler_state = {
412 .SamplerDisable = false,
413 .TextureBorderColorMode = DX10OGL,
414 .LODPreClampMode = 0,
415 #if ANV_GEN == 8
416 .BaseMipLevel = 0.0,
417 #endif
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,
426 .ChromaKeyIndex = 0,
427 .ChromaKeyMode = 0,
428 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
429 .CubeSurfaceControlMode = 0,
430
431 .IndirectStatePointer =
432 device->border_colors.offset +
433 pCreateInfo->borderColor * sizeof(float) * 4,
434
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],
448 };
449
450 GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
451
452 *pSampler = anv_sampler_to_handle(sampler);
453
454 return VK_SUCCESS;
455 }