c29d100f9f556e7e0d3f1ac1cab292bfdb55c55e
[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 #include "genX_state_util.h"
36
37 void
38 genX(fill_buffer_surface_state)(void *state, enum isl_format format,
39 uint32_t offset, uint32_t range, uint32_t stride)
40 {
41 uint32_t num_elements = range / stride;
42
43 struct GENX(RENDER_SURFACE_STATE) surface_state = {
44 .SurfaceType = SURFTYPE_BUFFER,
45 .SurfaceArray = false,
46 .SurfaceFormat = format,
47 .SurfaceVerticalAlignment = VALIGN4,
48 .SurfaceHorizontalAlignment = HALIGN4,
49 .TileMode = LINEAR,
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 },
64 };
65
66 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
67 }
68
69 static const uint8_t anv_halign[] = {
70 [4] = HALIGN4,
71 [8] = HALIGN8,
72 [16] = HALIGN16,
73 };
74
75 static const uint8_t anv_valign[] = {
76 [4] = VALIGN4,
77 [8] = VALIGN8,
78 [16] = VALIGN16,
79 };
80
81 static struct anv_state
82 alloc_surface_state(struct anv_device *device,
83 struct anv_cmd_buffer *cmd_buffer)
84 {
85 if (cmd_buffer) {
86 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
87 } else {
88 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
89 }
90 }
91
92 /**
93 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
94 * and SurfaceVerticalAlignment.
95 */
96 static void
97 get_halign_valign(const struct isl_surf *surf, uint32_t *halign, uint32_t *valign)
98 {
99 #if ANV_GENx10 >= 90
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
104 * VALIGN*.
105 */
106 *halign = 0;
107 *valign = 0;
108 } else {
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.
115 */
116 struct isl_extent3d image_align_el
117 = isl_surf_get_image_alignment_el(surf);
118
119 *halign = anv_halign[image_align_el.width];
120 *valign = anv_valign[image_align_el.height];
121 }
122 #else
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
127 * 4 pixels.
128 */
129 struct isl_extent3d image_align_sa
130 = isl_surf_get_image_alignment_sa(surf);
131
132 *halign = anv_halign[image_align_sa.width];
133 *valign = anv_valign[image_align_sa.height];
134 #endif
135 }
136
137 static uint32_t
138 get_qpitch(const struct isl_surf *surf)
139 {
140 switch (surf->dim) {
141 default:
142 unreachable(!"bad isl_surf_dim");
143 case ISL_SURF_DIM_1D:
144 #if ANV_GENx10 >= 90
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.
148 *
149 * From the Skylake BSpec >> Memory Views >> Common Surface
150 * Formats >> Surface Layout and Tiling >> 1D Surfaces:
151 *
152 * Surface QPitch specifies the distance in pixels between array
153 * slices.
154 */
155 return isl_surf_get_array_pitch_el(surf);
156 #else
157 return isl_surf_get_array_pitch_el_rows(surf);
158 #endif
159 case ISL_SURF_DIM_2D:
160 case ISL_SURF_DIM_3D:
161 return isl_surf_get_array_pitch_el_rows(surf);
162 }
163 }
164
165 void
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)
170 {
171 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
172
173 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
174
175 struct anv_surface *surface =
176 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
177
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,
185 };
186
187 uint32_t halign, valign;
188 get_halign_valign(&surface->isl, &halign, &valign);
189
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),
202
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".
206 */
207 .BaseMipLevel = 0.0,
208
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,
217 .XOffset = 0,
218 .YOffset = 0,
219
220 .MIPCountLOD = 0, /* TEMPLATE */
221 .SurfaceMinLOD = 0, /* TEMPLATE */
222
223 .AuxiliarySurfaceMode = AUX_NONE,
224 .RedClearColor = 0,
225 .GreenClearColor = 0,
226 .BlueClearColor = 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 },
238 };
239
240 switch (surface_state.SurfaceType) {
241 case SURFTYPE_1D:
242 case SURFTYPE_2D:
243 surface_state.MinimumArrayElement = range->baseArrayLayer;
244
245 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
246 *
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].
251 *
252 * In other words, 'Depth' is the number of array layers.
253 */
254 surface_state.Depth = range->layerCount - 1;
255
256 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
257 *
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.
260 */
261 surface_state.RenderTargetViewExtent = surface_state.Depth;
262 break;
263 case SURFTYPE_CUBE:
264 #if ANV_GENx10 >= 90
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;
269 #else
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;
274 #endif
275 break;
276 case SURFTYPE_3D:
277 surface_state.MinimumArrayElement = range->baseArrayLayer;
278
279 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
280 *
281 * If the volume texture is MIP-mapped, this field specifies the
282 * depth of the base MIP level.
283 */
284 surface_state.Depth = image->extent.depth - 1;
285
286 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
287 *
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.
291 */
292 surface_state.RenderTargetViewExtent = iview->extent.depth - 1;
293 break;
294 default:
295 unreachable(!"bad SurfaceType");
296 }
297
298 if (image->needs_nonrt_surface_state) {
299 iview->nonrt_surface_state =
300 alloc_surface_state(device, cmd_buffer);
301
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].
305 */
306 surface_state.SurfaceMinLOD = range->baseMipLevel;
307 surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
308
309 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
310 &surface_state);
311 if (!device->info.has_llc)
312 anv_state_clflush(iview->nonrt_surface_state);
313 }
314
315 if (image->needs_color_rt_surface_state) {
316 iview->color_rt_surface_state =
317 alloc_surface_state(device, cmd_buffer);
318
319 /* For render target surfaces, the hardware interprets field
320 * MIPCount/LOD as LOD. The Broadwell PRM says:
321 *
322 * MIPCountLOD defines the LOD that will be rendered into.
323 * SurfaceMinLOD is ignored.
324 */
325 surface_state.MIPCountLOD = range->baseMipLevel;
326 surface_state.SurfaceMinLOD = 0;
327
328 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
329 &surface_state);
330 if (!device->info.has_llc)
331 anv_state_clflush(iview->color_rt_surface_state);
332 }
333
334 if (image->needs_storage_surface_state) {
335 iview->storage_surface_state =
336 alloc_surface_state(device, cmd_buffer);
337
338 surface_state.SurfaceType =
339 anv_surftype(image, pCreateInfo->viewType, true),
340
341 surface_state.SurfaceFormat =
342 isl_lower_storage_image_format(&device->isl_dev, iview->format);
343
344 surface_state.SurfaceMinLOD = range->baseMipLevel;
345 surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
346
347 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
348 &surface_state);
349 }
350 }
351
352 VkResult genX(CreateSampler)(
353 VkDevice _device,
354 const VkSamplerCreateInfo* pCreateInfo,
355 const VkAllocationCallbacks* pAllocator,
356 VkSampler* pSampler)
357 {
358 ANV_FROM_HANDLE(anv_device, device, _device);
359 struct anv_sampler *sampler;
360 uint32_t mag_filter, min_filter, max_anisotropy;
361
362 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
363
364 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
365 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
366 if (!sampler)
367 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
368
369 if (pCreateInfo->maxAnisotropy > 1) {
370 mag_filter = MAPFILTER_ANISOTROPIC;
371 min_filter = MAPFILTER_ANISOTROPIC;
372 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
373 } else {
374 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
375 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
376 max_anisotropy = RATIO21;
377 }
378
379 struct GENX(SAMPLER_STATE) sampler_state = {
380 .SamplerDisable = false,
381 .TextureBorderColorMode = DX10OGL,
382 .LODPreClampMode = 0,
383 #if ANV_GEN == 8
384 .BaseMipLevel = 0.0,
385 #endif
386 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
387 .MagModeFilter = mag_filter,
388 .MinModeFilter = min_filter,
389 .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16, 15.996),
390 .AnisotropicAlgorithm = EWAApproximation,
391 .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14),
392 .MaxLOD = anv_clamp_f(pCreateInfo->maxLod, 0, 14),
393 .ChromaKeyEnable = 0,
394 .ChromaKeyIndex = 0,
395 .ChromaKeyMode = 0,
396 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
397 .CubeSurfaceControlMode = 0,
398
399 .IndirectStatePointer =
400 device->border_colors.offset +
401 pCreateInfo->borderColor * sizeof(float) * 4,
402
403 .LODClampMagnificationMode = MIPNONE,
404 .MaximumAnisotropy = max_anisotropy,
405 .RAddressMinFilterRoundingEnable = 0,
406 .RAddressMagFilterRoundingEnable = 0,
407 .VAddressMinFilterRoundingEnable = 0,
408 .VAddressMagFilterRoundingEnable = 0,
409 .UAddressMinFilterRoundingEnable = 0,
410 .UAddressMagFilterRoundingEnable = 0,
411 .TrilinearFilterQuality = 0,
412 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
413 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
414 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
415 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
416 };
417
418 GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
419
420 *pSampler = anv_sampler_to_handle(sampler);
421
422 return VK_SUCCESS;
423 }