Move the intel vulkan driver to src/intel/vulkan
[mesa.git] / src / intel / 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 "genxml/gen8_pack.h"
33 #include "genxml/gen9_pack.h"
34
35 #include "genX_state_util.h"
36
37 VkResult
38 genX(init_device_state)(struct anv_device *device)
39 {
40 struct anv_batch batch;
41
42 uint32_t cmds[64];
43 batch.start = batch.next = cmds;
44 batch.end = (void *) cmds + sizeof(cmds);
45
46 anv_batch_emit(&batch, GENX(PIPELINE_SELECT),
47 #if ANV_GEN >= 9
48 .MaskBits = 3,
49 #endif
50 .PipelineSelection = _3D);
51
52 anv_batch_emit(&batch, GENX(3DSTATE_VF_STATISTICS),
53 .StatisticsEnable = true);
54 anv_batch_emit(&batch, GENX(3DSTATE_HS), .Enable = false);
55 anv_batch_emit(&batch, GENX(3DSTATE_TE), .TEEnable = false);
56 anv_batch_emit(&batch, GENX(3DSTATE_DS), .FunctionEnable = false);
57 anv_batch_emit(&batch, GENX(3DSTATE_STREAMOUT), .SOFunctionEnable = false);
58 anv_batch_emit(&batch, GENX(3DSTATE_WM_CHROMAKEY),
59 .ChromaKeyKillEnable = false);
60 anv_batch_emit(&batch, GENX(3DSTATE_AA_LINE_PARAMETERS));
61
62 /* See the Vulkan 1.0 spec Table 24.1 "Standard sample locations" and
63 * VkPhysicalDeviceFeatures::standardSampleLocations.
64 */
65 anv_batch_emit(&batch, GENX(3DSTATE_SAMPLE_PATTERN),
66 ._1xSample0XOffset = 0.5,
67 ._1xSample0YOffset = 0.5,
68 ._2xSample0XOffset = 0.25,
69 ._2xSample0YOffset = 0.25,
70 ._2xSample1XOffset = 0.75,
71 ._2xSample1YOffset = 0.75,
72 ._4xSample0XOffset = 0.375,
73 ._4xSample0YOffset = 0.125,
74 ._4xSample1XOffset = 0.875,
75 ._4xSample1YOffset = 0.375,
76 ._4xSample2XOffset = 0.125,
77 ._4xSample2YOffset = 0.625,
78 ._4xSample3XOffset = 0.625,
79 ._4xSample3YOffset = 0.875,
80 ._8xSample0XOffset = 0.5625,
81 ._8xSample0YOffset = 0.3125,
82 ._8xSample1XOffset = 0.4375,
83 ._8xSample1YOffset = 0.6875,
84 ._8xSample2XOffset = 0.8125,
85 ._8xSample2YOffset = 0.5625,
86 ._8xSample3XOffset = 0.3125,
87 ._8xSample3YOffset = 0.1875,
88 ._8xSample4XOffset = 0.1875,
89 ._8xSample4YOffset = 0.8125,
90 ._8xSample5XOffset = 0.0625,
91 ._8xSample5YOffset = 0.4375,
92 ._8xSample6XOffset = 0.6875,
93 ._8xSample6YOffset = 0.9375,
94 ._8xSample7XOffset = 0.9375,
95 ._8xSample7YOffset = 0.0625,
96 #if ANV_GEN >= 9
97 ._16xSample0XOffset = 0.5625,
98 ._16xSample0YOffset = 0.5625,
99 ._16xSample1XOffset = 0.4375,
100 ._16xSample1YOffset = 0.3125,
101 ._16xSample2XOffset = 0.3125,
102 ._16xSample2YOffset = 0.6250,
103 ._16xSample3XOffset = 0.7500,
104 ._16xSample3YOffset = 0.4375,
105 ._16xSample4XOffset = 0.1875,
106 ._16xSample4YOffset = 0.3750,
107 ._16xSample5XOffset = 0.6250,
108 ._16xSample5YOffset = 0.8125,
109 ._16xSample6XOffset = 0.8125,
110 ._16xSample6YOffset = 0.6875,
111 ._16xSample7XOffset = 0.6875,
112 ._16xSample7YOffset = 0.1875,
113 ._16xSample8XOffset = 0.3750,
114 ._16xSample8YOffset = 0.8750,
115 ._16xSample9XOffset = 0.5000,
116 ._16xSample9YOffset = 0.0625,
117 ._16xSample10XOffset = 0.2500,
118 ._16xSample10YOffset = 0.1250,
119 ._16xSample11XOffset = 0.1250,
120 ._16xSample11YOffset = 0.7500,
121 ._16xSample12XOffset = 0.0000,
122 ._16xSample12YOffset = 0.5000,
123 ._16xSample13XOffset = 0.9375,
124 ._16xSample13YOffset = 0.2500,
125 ._16xSample14XOffset = 0.8750,
126 ._16xSample14YOffset = 0.9375,
127 ._16xSample15XOffset = 0.0625,
128 ._16xSample15YOffset = 0.0000,
129 #endif
130 );
131
132 anv_batch_emit(&batch, GENX(MI_BATCH_BUFFER_END));
133
134 assert(batch.next <= batch.end);
135
136 return anv_device_submit_simple_batch(device, &batch);
137 }
138
139 static const uint32_t
140 isl_to_gen_multisample_layout[] = {
141 [ISL_MSAA_LAYOUT_NONE] = MSS,
142 [ISL_MSAA_LAYOUT_INTERLEAVED] = DEPTH_STENCIL,
143 [ISL_MSAA_LAYOUT_ARRAY] = MSS,
144 };
145
146 void
147 genX(fill_buffer_surface_state)(void *state, enum isl_format format,
148 uint32_t offset, uint32_t range, uint32_t stride)
149 {
150 uint32_t num_elements = range / stride;
151
152 struct GENX(RENDER_SURFACE_STATE) surface_state = {
153 .SurfaceType = SURFTYPE_BUFFER,
154 .SurfaceArray = false,
155 .SurfaceFormat = format,
156 .SurfaceVerticalAlignment = VALIGN4,
157 .SurfaceHorizontalAlignment = HALIGN4,
158 .TileMode = LINEAR,
159 .SamplerL2BypassModeDisable = true,
160 .RenderCacheReadWriteMode = WriteOnlyCache,
161 .MemoryObjectControlState = GENX(MOCS),
162 .Height = ((num_elements - 1) >> 7) & 0x3fff,
163 .Width = (num_elements - 1) & 0x7f,
164 .Depth = ((num_elements - 1) >> 21) & 0x3f,
165 .SurfacePitch = stride - 1,
166 .NumberofMultisamples = MULTISAMPLECOUNT_1,
167 .ShaderChannelSelectRed = SCS_RED,
168 .ShaderChannelSelectGreen = SCS_GREEN,
169 .ShaderChannelSelectBlue = SCS_BLUE,
170 .ShaderChannelSelectAlpha = SCS_ALPHA,
171 /* FIXME: We assume that the image must be bound at this time. */
172 .SurfaceBaseAddress = { NULL, offset },
173 };
174
175 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
176 }
177
178 static const uint8_t anv_halign[] = {
179 [4] = HALIGN4,
180 [8] = HALIGN8,
181 [16] = HALIGN16,
182 };
183
184 static const uint8_t anv_valign[] = {
185 [4] = VALIGN4,
186 [8] = VALIGN8,
187 [16] = VALIGN16,
188 };
189
190 /**
191 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
192 * and SurfaceVerticalAlignment.
193 */
194 static void
195 get_halign_valign(const struct isl_surf *surf, uint32_t *halign, uint32_t *valign)
196 {
197 #if ANV_GENx10 >= 90
198 if (isl_tiling_is_std_y(surf->tiling) ||
199 surf->dim_layout == ISL_DIM_LAYOUT_GEN9_1D) {
200 /* The hardware ignores the alignment values. Anyway, the surface's
201 * true alignment is likely outside the enum range of HALIGN* and
202 * VALIGN*.
203 */
204 *halign = 0;
205 *valign = 0;
206 } else {
207 /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
208 * of surface elements (not pixels nor samples). For compressed formats,
209 * a "surface element" is defined as a compression block. For example,
210 * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
211 * format (ETC2 has a block height of 4), then the vertical alignment is
212 * 4 compression blocks or, equivalently, 16 pixels.
213 */
214 struct isl_extent3d image_align_el
215 = isl_surf_get_image_alignment_el(surf);
216
217 *halign = anv_halign[image_align_el.width];
218 *valign = anv_valign[image_align_el.height];
219 }
220 #else
221 /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
222 * units of surface samples. For example, if SurfaceVerticalAlignment
223 * is VALIGN_4 and the surface is singlesampled, then for any surface
224 * format (compressed or not) the vertical alignment is
225 * 4 pixels.
226 */
227 struct isl_extent3d image_align_sa
228 = isl_surf_get_image_alignment_sa(surf);
229
230 *halign = anv_halign[image_align_sa.width];
231 *valign = anv_valign[image_align_sa.height];
232 #endif
233 }
234
235 static uint32_t
236 get_qpitch(const struct isl_surf *surf)
237 {
238 switch (surf->dim) {
239 default:
240 unreachable(!"bad isl_surf_dim");
241 case ISL_SURF_DIM_1D:
242 #if ANV_GENx10 >= 90
243 /* QPitch is usually expressed as rows of surface elements (where
244 * a surface element is an compression block or a single surface
245 * sample). Skylake 1D is an outlier.
246 *
247 * From the Skylake BSpec >> Memory Views >> Common Surface
248 * Formats >> Surface Layout and Tiling >> 1D Surfaces:
249 *
250 * Surface QPitch specifies the distance in pixels between array
251 * slices.
252 */
253 return isl_surf_get_array_pitch_el(surf);
254 #else
255 return isl_surf_get_array_pitch_el_rows(surf);
256 #endif
257 case ISL_SURF_DIM_2D:
258 case ISL_SURF_DIM_3D:
259 #if ANV_GEN >= 9
260 return isl_surf_get_array_pitch_el_rows(surf);
261 #else
262 /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch
263 *
264 * "This field must be set to an integer multiple of the Surface
265 * Vertical Alignment. For compressed textures (BC*, FXT1,
266 * ETC*, and EAC* Surface Formats), this field is in units of
267 * rows in the uncompressed surface, and must be set to an
268 * integer multiple of the vertical alignment parameter "j"
269 * defined in the Common Surface Formats section."
270 */
271 return isl_surf_get_array_pitch_sa_rows(surf);
272 #endif
273 }
274 }
275
276 void
277 genX(fill_image_surface_state)(struct anv_device *device, void *state_map,
278 struct anv_image_view *iview,
279 const VkImageViewCreateInfo *pCreateInfo,
280 VkImageUsageFlagBits usage)
281 {
282 assert(usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
283 VK_IMAGE_USAGE_STORAGE_BIT |
284 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
285 assert(util_is_power_of_two(usage));
286
287 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
288 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
289 bool is_storage = (usage == VK_IMAGE_USAGE_STORAGE_BIT);
290 struct anv_surface *surface =
291 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
292
293 static const uint8_t isl_to_gen_tiling[] = {
294 [ISL_TILING_LINEAR] = LINEAR,
295 [ISL_TILING_X] = XMAJOR,
296 [ISL_TILING_Y0] = YMAJOR,
297 [ISL_TILING_Yf] = YMAJOR,
298 [ISL_TILING_Ys] = YMAJOR,
299 [ISL_TILING_W] = WMAJOR,
300 };
301
302 uint32_t halign, valign;
303 get_halign_valign(&surface->isl, &halign, &valign);
304
305 struct GENX(RENDER_SURFACE_STATE) template = {
306 .SurfaceType = anv_surftype(image, pCreateInfo->viewType, is_storage),
307 .SurfaceArray = image->array_size > 1,
308 .SurfaceFormat = anv_surface_format(device, iview->format, is_storage),
309 .SurfaceVerticalAlignment = valign,
310 .SurfaceHorizontalAlignment = halign,
311 .TileMode = isl_to_gen_tiling[surface->isl.tiling],
312 .VerticalLineStride = 0,
313 .VerticalLineStrideOffset = 0,
314 .SamplerL2BypassModeDisable = true,
315 .RenderCacheReadWriteMode = WriteOnlyCache,
316 .CubeFaceEnablePositiveZ = 1,
317 .CubeFaceEnableNegativeZ = 1,
318 .CubeFaceEnablePositiveY = 1,
319 .CubeFaceEnableNegativeY = 1,
320 .CubeFaceEnablePositiveX = 1,
321 .CubeFaceEnableNegativeX = 1,
322 .MemoryObjectControlState = GENX(MOCS),
323
324 /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
325 * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
326 * both Base Mip Level fields nonzero".
327 */
328 .BaseMipLevel = 0.0,
329
330 .SurfaceQPitch = get_qpitch(&surface->isl) >> 2,
331 .Height = iview->level_0_extent.height - 1,
332 .Width = iview->level_0_extent.width - 1,
333 .Depth = 0, /* TEMPLATE */
334 .SurfacePitch = surface->isl.row_pitch - 1,
335 .RenderTargetViewExtent = 0, /* TEMPLATE */
336 .MinimumArrayElement = 0, /* TEMPLATE */
337 .MultisampledSurfaceStorageFormat =
338 isl_to_gen_multisample_layout[surface->isl.msaa_layout],
339 .NumberofMultisamples = ffs(surface->isl.samples) - 1,
340 .MultisamplePositionPaletteIndex = 0, /* UNUSED */
341 .XOffset = 0,
342 .YOffset = 0,
343
344 .MIPCountLOD = 0, /* TEMPLATE */
345 .SurfaceMinLOD = 0, /* TEMPLATE */
346
347 .AuxiliarySurfaceMode = AUX_NONE,
348 .RedClearColor = 0,
349 .GreenClearColor = 0,
350 .BlueClearColor = 0,
351 .AlphaClearColor = 0,
352 .ShaderChannelSelectRed = vk_to_gen_swizzle[iview->swizzle.r],
353 .ShaderChannelSelectGreen = vk_to_gen_swizzle[iview->swizzle.g],
354 .ShaderChannelSelectBlue = vk_to_gen_swizzle[iview->swizzle.b],
355 .ShaderChannelSelectAlpha = vk_to_gen_swizzle[iview->swizzle.a],
356 .ResourceMinLOD = 0.0,
357 .SurfaceBaseAddress = { NULL, iview->offset },
358 };
359
360 switch (template.SurfaceType) {
361 case SURFTYPE_1D:
362 case SURFTYPE_2D:
363 template.MinimumArrayElement = range->baseArrayLayer;
364
365 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
366 *
367 * For SURFTYPE_1D, 2D, and CUBE: The range of this field is reduced
368 * by one for each increase from zero of Minimum Array Element. For
369 * example, if Minimum Array Element is set to 1024 on a 2D surface,
370 * the range of this field is reduced to [0,1023].
371 *
372 * In other words, 'Depth' is the number of array layers.
373 */
374 template.Depth = range->layerCount - 1;
375
376 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
377 *
378 * For Render Target and Typed Dataport 1D and 2D Surfaces:
379 * This field must be set to the same value as the Depth field.
380 */
381 template.RenderTargetViewExtent = template.Depth;
382 break;
383 case SURFTYPE_CUBE:
384 template.MinimumArrayElement = range->baseArrayLayer;
385 /* Same as SURFTYPE_2D, but divided by 6 */
386 template.Depth = range->layerCount / 6 - 1;
387 template.RenderTargetViewExtent = template.Depth;
388 break;
389 case SURFTYPE_3D:
390 template.MinimumArrayElement = range->baseArrayLayer;
391
392 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
393 *
394 * If the volume texture is MIP-mapped, this field specifies the
395 * depth of the base MIP level.
396 */
397 template.Depth = image->extent.depth - 1;
398
399 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
400 *
401 * For Render Target and Typed Dataport 3D Surfaces: This field
402 * indicates the extent of the accessible 'R' coordinates minus 1 on
403 * the LOD currently being rendered to.
404 */
405 template.RenderTargetViewExtent = iview->extent.depth - 1;
406 break;
407 default:
408 unreachable(!"bad SurfaceType");
409 }
410
411 if (usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
412 /* For render target surfaces, the hardware interprets field
413 * MIPCount/LOD as LOD. The Broadwell PRM says:
414 *
415 * MIPCountLOD defines the LOD that will be rendered into.
416 * SurfaceMinLOD is ignored.
417 */
418 template.MIPCountLOD = range->baseMipLevel;
419 template.SurfaceMinLOD = 0;
420 } else {
421 /* For non render target surfaces, the hardware interprets field
422 * MIPCount/LOD as MIPCount. The range of levels accessible by the
423 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
424 */
425 template.SurfaceMinLOD = range->baseMipLevel;
426 template.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
427 }
428
429 GENX(RENDER_SURFACE_STATE_pack)(NULL, state_map, &template);
430 }
431
432 VkResult genX(CreateSampler)(
433 VkDevice _device,
434 const VkSamplerCreateInfo* pCreateInfo,
435 const VkAllocationCallbacks* pAllocator,
436 VkSampler* pSampler)
437 {
438 ANV_FROM_HANDLE(anv_device, device, _device);
439 struct anv_sampler *sampler;
440
441 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
442
443 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
444 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
445 if (!sampler)
446 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
447
448 uint32_t border_color_offset = device->border_colors.offset +
449 pCreateInfo->borderColor * 64;
450
451 struct GENX(SAMPLER_STATE) sampler_state = {
452 .SamplerDisable = false,
453 .TextureBorderColorMode = DX10OGL,
454 .LODPreClampMode = CLAMP_MODE_OGL,
455 #if ANV_GEN == 8
456 .BaseMipLevel = 0.0,
457 #endif
458 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
459 .MagModeFilter = vk_to_gen_tex_filter(pCreateInfo->magFilter, pCreateInfo->anisotropyEnable),
460 .MinModeFilter = vk_to_gen_tex_filter(pCreateInfo->minFilter, pCreateInfo->anisotropyEnable),
461 .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16, 15.996),
462 .AnisotropicAlgorithm = EWAApproximation,
463 .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14),
464 .MaxLOD = anv_clamp_f(pCreateInfo->maxLod, 0, 14),
465 .ChromaKeyEnable = 0,
466 .ChromaKeyIndex = 0,
467 .ChromaKeyMode = 0,
468 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
469 .CubeSurfaceControlMode = OVERRIDE,
470
471 .IndirectStatePointer = border_color_offset >> 6,
472
473 .LODClampMagnificationMode = MIPNONE,
474 .MaximumAnisotropy = vk_to_gen_max_anisotropy(pCreateInfo->maxAnisotropy),
475 .RAddressMinFilterRoundingEnable = 0,
476 .RAddressMagFilterRoundingEnable = 0,
477 .VAddressMinFilterRoundingEnable = 0,
478 .VAddressMagFilterRoundingEnable = 0,
479 .UAddressMinFilterRoundingEnable = 0,
480 .UAddressMagFilterRoundingEnable = 0,
481 .TrilinearFilterQuality = 0,
482 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
483 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
484 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
485 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
486 };
487
488 GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
489
490 *pSampler = anv_sampler_to_handle(sampler);
491
492 return VK_SUCCESS;
493 }