anv/image: Refactor anv_image_make_surface()
[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 void
36 genX(fill_buffer_surface_state)(void *state, const struct anv_format *format,
37 uint32_t offset, uint32_t range, uint32_t stride)
38 {
39 uint32_t num_elements = range / stride;
40
41 struct GENX(RENDER_SURFACE_STATE) surface_state = {
42 .SurfaceType = SURFTYPE_BUFFER,
43 .SurfaceArray = false,
44 .SurfaceFormat = format->surface_format,
45 .SurfaceVerticalAlignment = VALIGN4,
46 .SurfaceHorizontalAlignment = HALIGN4,
47 .TileMode = LINEAR,
48 .SamplerL2BypassModeDisable = true,
49 .RenderCacheReadWriteMode = WriteOnlyCache,
50 .MemoryObjectControlState = GENX(MOCS),
51 .Height = ((num_elements - 1) >> 7) & 0x3fff,
52 .Width = (num_elements - 1) & 0x7f,
53 .Depth = ((num_elements - 1) >> 21) & 0x3f,
54 .SurfacePitch = stride - 1,
55 .NumberofMultisamples = MULTISAMPLECOUNT_1,
56 .ShaderChannelSelectRed = SCS_RED,
57 .ShaderChannelSelectGreen = SCS_GREEN,
58 .ShaderChannelSelectBlue = SCS_BLUE,
59 .ShaderChannelSelectAlpha = SCS_ALPHA,
60 /* FIXME: We assume that the image must be bound at this time. */
61 .SurfaceBaseAddress = { NULL, offset },
62 };
63
64 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
65 }
66
67 static const uint8_t anv_halign[] = {
68 [4] = HALIGN4,
69 [8] = HALIGN8,
70 [16] = HALIGN16,
71 };
72
73 static const uint8_t anv_valign[] = {
74 [4] = VALIGN4,
75 [8] = VALIGN8,
76 [16] = VALIGN16,
77 };
78
79 static struct anv_state
80 alloc_surface_state(struct anv_device *device,
81 struct anv_cmd_buffer *cmd_buffer)
82 {
83 if (cmd_buffer) {
84 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
85 } else {
86 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
87 }
88 }
89
90 static const uint32_t vk_to_gen_swizzle_map[] = {
91 [VK_COMPONENT_SWIZZLE_ZERO] = SCS_ZERO,
92 [VK_COMPONENT_SWIZZLE_ONE] = SCS_ONE,
93 [VK_COMPONENT_SWIZZLE_R] = SCS_RED,
94 [VK_COMPONENT_SWIZZLE_G] = SCS_GREEN,
95 [VK_COMPONENT_SWIZZLE_B] = SCS_BLUE,
96 [VK_COMPONENT_SWIZZLE_A] = SCS_ALPHA
97 };
98
99 static inline uint32_t
100 vk_to_gen_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component)
101 {
102 if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY)
103 return vk_to_gen_swizzle_map[component];
104 else
105 return vk_to_gen_swizzle_map[swizzle];
106 }
107
108 /**
109 * Get the values to pack into RENDER_SUFFACE_STATE.SurfaceHorizontalAlignment
110 * and SurfaceVerticalAlignment.
111 */
112 static void
113 get_halign_valign(const struct isl_surf *surf, uint32_t *halign, uint32_t *valign)
114 {
115 #if ANV_GENx10 >= 90
116 /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
117 * of surface elements (not pixels nor samples). For compressed formats,
118 * a "surface element" is defined as a compression block. For example,
119 * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
120 * format (ETC2 has a block height of 4), then the vertical alignment is
121 * 4 compression blocks or, equivalently, 16 pixels.
122 */
123 struct isl_extent3d lod_align_el = isl_surf_get_lod_alignment_el(surf);
124 *halign = anv_halign[lod_align_el.width];
125 *valign = anv_valign[lod_align_el.height];
126 #else
127 /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
128 * units of surface samples. For example, if SurfaceVerticalAlignment
129 * is VALIGN_4 and the surface is singlesampled, then for any surface
130 * format (compressed or not) the vertical alignment is
131 * 4 pixels.
132 */
133 struct isl_extent3d lod_align_sa = isl_surf_get_lod_alignment_sa(surf);
134 *halign = anv_halign[lod_align_sa.width];
135 *valign = anv_valign[lod_align_sa.height];
136 #endif
137 }
138
139 void
140 genX(image_view_init)(struct anv_image_view *iview,
141 struct anv_device *device,
142 const VkImageViewCreateInfo* pCreateInfo,
143 struct anv_cmd_buffer *cmd_buffer)
144 {
145 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
146
147 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
148
149 struct anv_surface *surface =
150 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
151
152 uint32_t depth = 1; /* RENDER_SURFACE_STATE::Depth */
153 uint32_t rt_view_extent = 1; /* RENDER_SURFACE_STATE::RenderTargetViewExtent */
154
155 const struct anv_format *format_info =
156 anv_format_for_vk_format(pCreateInfo->format);
157
158 iview->image = image;
159 iview->bo = image->bo;
160 iview->offset = image->offset + surface->offset;
161 iview->format = format_info;
162
163 iview->extent = (VkExtent3D) {
164 .width = anv_minify(image->extent.width, range->baseMipLevel),
165 .height = anv_minify(image->extent.height, range->baseMipLevel),
166 .depth = anv_minify(image->extent.depth, range->baseMipLevel),
167 };
168
169 switch (image->type) {
170 case VK_IMAGE_TYPE_1D:
171 case VK_IMAGE_TYPE_2D:
172 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
173 *
174 * For SURFTYPE_1D, 2D, and CUBE: The range of this field is reduced
175 * by one for each increase from zero of Minimum Array Element. For
176 * example, if Minimum Array Element is set to 1024 on a 2D surface,
177 * the range of this field is reduced to [0,1023].
178 */
179 depth = range->layerCount;
180
181 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
182 *
183 * For Render Target and Typed Dataport 1D and 2D Surfaces:
184 * This field must be set to the same value as the Depth field.
185 */
186 rt_view_extent = depth;
187 break;
188 case VK_IMAGE_TYPE_3D:
189 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
190 *
191 * If the volume texture is MIP-mapped, this field specifies the
192 * depth of the base MIP level.
193 */
194 depth = image->extent.depth;
195
196 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
197 *
198 * For Render Target and Typed Dataport 3D Surfaces: This field
199 * indicates the extent of the accessible 'R' coordinates minus 1 on
200 * the LOD currently being rendered to.
201 */
202 rt_view_extent = iview->extent.depth;
203 break;
204 default:
205 unreachable(!"bad VkImageType");
206 }
207
208 static const uint8_t isl_to_gen_tiling[] = {
209 [ISL_TILING_LINEAR] = LINEAR,
210 [ISL_TILING_X] = XMAJOR,
211 [ISL_TILING_Y0] = YMAJOR,
212 [ISL_TILING_Yf] = YMAJOR,
213 [ISL_TILING_Ys] = YMAJOR,
214 [ISL_TILING_W] = WMAJOR,
215 };
216
217 uint32_t halign, valign;
218 get_halign_valign(&surface->isl, &halign, &valign);
219
220 struct GENX(RENDER_SURFACE_STATE) surface_state = {
221 .SurfaceType = image->surface_type,
222 .SurfaceArray = image->array_size > 1,
223 .SurfaceFormat = format_info->surface_format,
224 .SurfaceVerticalAlignment = valign,
225 .SurfaceHorizontalAlignment = halign,
226 .TileMode = isl_to_gen_tiling[surface->isl.tiling],
227 .VerticalLineStride = 0,
228 .VerticalLineStrideOffset = 0,
229 .SamplerL2BypassModeDisable = true,
230 .RenderCacheReadWriteMode = WriteOnlyCache,
231 .MemoryObjectControlState = GENX(MOCS),
232
233 /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
234 * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
235 * both Base Mip Level fields nonzero".
236 */
237 .BaseMipLevel = 0.0,
238
239 .SurfaceQPitch = isl_surf_get_array_pitch_el_rows(&surface->isl) >> 2,
240 .Height = image->extent.height - 1,
241 .Width = image->extent.width - 1,
242 .Depth = depth - 1,
243 .SurfacePitch = surface->isl.row_pitch - 1,
244 .RenderTargetViewExtent = rt_view_extent - 1,
245 .MinimumArrayElement = range->baseArrayLayer,
246 .NumberofMultisamples = MULTISAMPLECOUNT_1,
247 .XOffset = 0,
248 .YOffset = 0,
249
250 .MIPCountLOD = 0, /* TEMPLATE */
251 .SurfaceMinLOD = 0, /* TEMPLATE */
252
253 .AuxiliarySurfaceMode = AUX_NONE,
254 .RedClearColor = 0,
255 .GreenClearColor = 0,
256 .BlueClearColor = 0,
257 .AlphaClearColor = 0,
258 .ShaderChannelSelectRed = vk_to_gen_swizzle(pCreateInfo->components.r,
259 VK_COMPONENT_SWIZZLE_R),
260 .ShaderChannelSelectGreen = vk_to_gen_swizzle(pCreateInfo->components.g,
261 VK_COMPONENT_SWIZZLE_G),
262 .ShaderChannelSelectBlue = vk_to_gen_swizzle(pCreateInfo->components.b,
263 VK_COMPONENT_SWIZZLE_B),
264 .ShaderChannelSelectAlpha = vk_to_gen_swizzle(pCreateInfo->components.a,
265 VK_COMPONENT_SWIZZLE_A),
266 .ResourceMinLOD = 0.0,
267 .SurfaceBaseAddress = { NULL, iview->offset },
268 };
269
270 if (image->needs_nonrt_surface_state) {
271 iview->nonrt_surface_state =
272 alloc_surface_state(device, cmd_buffer);
273
274 /* For non render target surfaces, the hardware interprets field
275 * MIPCount/LOD as MIPCount. The range of levels accessible by the
276 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
277 */
278 surface_state.SurfaceMinLOD = range->baseMipLevel;
279 surface_state.MIPCountLOD = range->levelCount - 1;
280
281 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
282 &surface_state);
283 if (!device->info.has_llc)
284 anv_state_clflush(iview->nonrt_surface_state);
285 }
286
287 if (image->needs_color_rt_surface_state) {
288 iview->color_rt_surface_state =
289 alloc_surface_state(device, cmd_buffer);
290
291 /* For render target surfaces, the hardware interprets field
292 * MIPCount/LOD as LOD. The Broadwell PRM says:
293 *
294 * MIPCountLOD defines the LOD that will be rendered into.
295 * SurfaceMinLOD is ignored.
296 */
297 surface_state.MIPCountLOD = range->baseMipLevel;
298 surface_state.SurfaceMinLOD = 0;
299
300 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
301 &surface_state);
302 if (!device->info.has_llc)
303 anv_state_clflush(iview->color_rt_surface_state);
304 }
305 }
306
307 VkResult genX(CreateSampler)(
308 VkDevice _device,
309 const VkSamplerCreateInfo* pCreateInfo,
310 const VkAllocationCallbacks* pAllocator,
311 VkSampler* pSampler)
312 {
313 ANV_FROM_HANDLE(anv_device, device, _device);
314 struct anv_sampler *sampler;
315 uint32_t mag_filter, min_filter, max_anisotropy;
316
317 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
318
319 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
320 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
321 if (!sampler)
322 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
323
324 static const uint32_t vk_to_gen_tex_filter[] = {
325 [VK_FILTER_NEAREST] = MAPFILTER_NEAREST,
326 [VK_FILTER_LINEAR] = MAPFILTER_LINEAR
327 };
328
329 static const uint32_t vk_to_gen_mipmap_mode[] = {
330 [VK_SAMPLER_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
331 [VK_SAMPLER_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
332 [VK_SAMPLER_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
333 };
334
335 static const uint32_t vk_to_gen_tex_address[] = {
336 [VK_SAMPLER_ADDRESS_MODE_REPEAT] = TCM_WRAP,
337 [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT] = TCM_MIRROR,
338 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE] = TCM_CLAMP,
339 [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE] = TCM_MIRROR_ONCE,
340 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER] = TCM_CLAMP_BORDER,
341 };
342
343 static const uint32_t vk_to_gen_compare_op[] = {
344 [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
345 [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
346 [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
347 [VK_COMPARE_OP_LESS_OR_EQUAL] = PREFILTEROPLEQUAL,
348 [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
349 [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
350 [VK_COMPARE_OP_GREATER_OR_EQUAL] = PREFILTEROPGEQUAL,
351 [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
352 };
353
354 if (pCreateInfo->maxAnisotropy > 1) {
355 mag_filter = MAPFILTER_ANISOTROPIC;
356 min_filter = MAPFILTER_ANISOTROPIC;
357 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
358 } else {
359 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
360 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
361 max_anisotropy = RATIO21;
362 }
363
364 struct GENX(SAMPLER_STATE) sampler_state = {
365 .SamplerDisable = false,
366 .TextureBorderColorMode = DX10OGL,
367 .LODPreClampMode = 0,
368 #if ANV_GEN == 8
369 .BaseMipLevel = 0.0,
370 #endif
371 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
372 .MagModeFilter = mag_filter,
373 .MinModeFilter = min_filter,
374 .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16, 15.996),
375 .AnisotropicAlgorithm = EWAApproximation,
376 .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14),
377 .MaxLOD = anv_clamp_f(pCreateInfo->maxLod, 0, 14),
378 .ChromaKeyEnable = 0,
379 .ChromaKeyIndex = 0,
380 .ChromaKeyMode = 0,
381 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
382 .CubeSurfaceControlMode = 0,
383
384 .IndirectStatePointer =
385 device->border_colors.offset +
386 pCreateInfo->borderColor * sizeof(float) * 4,
387
388 .LODClampMagnificationMode = MIPNONE,
389 .MaximumAnisotropy = max_anisotropy,
390 .RAddressMinFilterRoundingEnable = 0,
391 .RAddressMagFilterRoundingEnable = 0,
392 .VAddressMinFilterRoundingEnable = 0,
393 .VAddressMagFilterRoundingEnable = 0,
394 .UAddressMinFilterRoundingEnable = 0,
395 .UAddressMagFilterRoundingEnable = 0,
396 .TrilinearFilterQuality = 0,
397 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
398 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
399 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
400 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
401 };
402
403 GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
404
405 *pSampler = anv_sampler_to_handle(sampler);
406
407 return VK_SUCCESS;
408 }