Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / vulkan / gen7_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 "gen7_pack.h"
33 #include "gen75_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 GENX_FUNC(GEN7, GEN75) void
61 genX(fill_buffer_surface_state)(void *state, enum isl_format format,
62 uint32_t offset, uint32_t range,
63 uint32_t stride)
64 {
65 uint32_t num_elements = range / stride;
66
67 struct GENX(RENDER_SURFACE_STATE) surface_state = {
68 .SurfaceType = SURFTYPE_BUFFER,
69 .SurfaceFormat = format,
70 .SurfaceVerticalAlignment = VALIGN_4,
71 .SurfaceHorizontalAlignment = HALIGN_4,
72 .TiledSurface = false,
73 .RenderCacheReadWriteMode = false,
74 .SurfaceObjectControlState = GENX(MOCS),
75 .Height = (num_elements >> 7) & 0x3fff,
76 .Width = num_elements & 0x7f,
77 .Depth = (num_elements >> 21) & 0x3f,
78 .SurfacePitch = stride - 1,
79 # if (ANV_IS_HASWELL)
80 .ShaderChannelSelectR = SCS_RED,
81 .ShaderChannelSelectG = SCS_GREEN,
82 .ShaderChannelSelectB = SCS_BLUE,
83 .ShaderChannelSelectA = SCS_ALPHA,
84 # endif
85 .SurfaceBaseAddress = { NULL, offset },
86 };
87
88 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
89 }
90
91 static const uint32_t vk_to_gen_tex_filter[] = {
92 [VK_FILTER_NEAREST] = MAPFILTER_NEAREST,
93 [VK_FILTER_LINEAR] = MAPFILTER_LINEAR
94 };
95
96 static const uint32_t vk_to_gen_mipmap_mode[] = {
97 [VK_SAMPLER_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
98 [VK_SAMPLER_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
99 [VK_SAMPLER_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
100 };
101
102 static const uint32_t vk_to_gen_tex_address[] = {
103 [VK_SAMPLER_ADDRESS_MODE_REPEAT] = TCM_WRAP,
104 [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT] = TCM_MIRROR,
105 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE] = TCM_CLAMP,
106 [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE] = TCM_MIRROR_ONCE,
107 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER] = TCM_CLAMP_BORDER,
108 };
109
110 static const uint32_t vk_to_gen_compare_op[] = {
111 [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
112 [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
113 [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
114 [VK_COMPARE_OP_LESS_OR_EQUAL] = PREFILTEROPLEQUAL,
115 [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
116 [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
117 [VK_COMPARE_OP_GREATER_OR_EQUAL] = PREFILTEROPGEQUAL,
118 [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
119 };
120
121 static struct anv_state
122 alloc_surface_state(struct anv_device *device,
123 struct anv_cmd_buffer *cmd_buffer)
124 {
125 if (cmd_buffer) {
126 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
127 } else {
128 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
129 }
130 }
131
132 VkResult genX(CreateSampler)(
133 VkDevice _device,
134 const VkSamplerCreateInfo* pCreateInfo,
135 const VkAllocationCallbacks* pAllocator,
136 VkSampler* pSampler)
137 {
138 ANV_FROM_HANDLE(anv_device, device, _device);
139 struct anv_sampler *sampler;
140 uint32_t mag_filter, min_filter, max_anisotropy;
141
142 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
143
144 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
145 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
146 if (!sampler)
147 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
148
149 if (pCreateInfo->maxAnisotropy > 1) {
150 mag_filter = MAPFILTER_ANISOTROPIC;
151 min_filter = MAPFILTER_ANISOTROPIC;
152 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
153 } else {
154 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
155 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
156 max_anisotropy = RATIO21;
157 }
158
159 struct GEN7_SAMPLER_STATE sampler_state = {
160 .SamplerDisable = false,
161 .TextureBorderColorMode = DX10OGL,
162 .BaseMipLevel = 0.0,
163 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
164 .MagModeFilter = mag_filter,
165 .MinModeFilter = min_filter,
166 .TextureLODBias = pCreateInfo->mipLodBias * 256,
167 .AnisotropicAlgorithm = EWAApproximation,
168 .MinLOD = pCreateInfo->minLod,
169 .MaxLOD = pCreateInfo->maxLod,
170 .ChromaKeyEnable = 0,
171 .ChromaKeyIndex = 0,
172 .ChromaKeyMode = 0,
173 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
174 .CubeSurfaceControlMode = 0,
175
176 .BorderColorPointer =
177 device->border_colors.offset +
178 pCreateInfo->borderColor * sizeof(float) * 4,
179
180 .MaximumAnisotropy = max_anisotropy,
181 .RAddressMinFilterRoundingEnable = 0,
182 .RAddressMagFilterRoundingEnable = 0,
183 .VAddressMinFilterRoundingEnable = 0,
184 .VAddressMagFilterRoundingEnable = 0,
185 .UAddressMinFilterRoundingEnable = 0,
186 .UAddressMagFilterRoundingEnable = 0,
187 .TrilinearFilterQuality = 0,
188 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
189 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
190 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
191 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
192 };
193
194 GEN7_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
195
196 *pSampler = anv_sampler_to_handle(sampler);
197
198 return VK_SUCCESS;
199 }
200
201 static const uint8_t anv_halign[] = {
202 [4] = HALIGN_4,
203 [8] = HALIGN_8,
204 };
205
206 static const uint8_t anv_valign[] = {
207 [2] = VALIGN_2,
208 [4] = VALIGN_4,
209 };
210
211 static const uint32_t vk_to_gen_swizzle_map[] = {
212 [VK_COMPONENT_SWIZZLE_ZERO] = SCS_ZERO,
213 [VK_COMPONENT_SWIZZLE_ONE] = SCS_ONE,
214 [VK_COMPONENT_SWIZZLE_R] = SCS_RED,
215 [VK_COMPONENT_SWIZZLE_G] = SCS_GREEN,
216 [VK_COMPONENT_SWIZZLE_B] = SCS_BLUE,
217 [VK_COMPONENT_SWIZZLE_A] = SCS_ALPHA
218 };
219
220 static inline uint32_t
221 vk_to_gen_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component)
222 {
223 if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY)
224 return vk_to_gen_swizzle_map[component];
225 else
226 return vk_to_gen_swizzle_map[swizzle];
227 }
228
229 GENX_FUNC(GEN7, GEN75) void
230 genX(image_view_init)(struct anv_image_view *iview,
231 struct anv_device *device,
232 const VkImageViewCreateInfo* pCreateInfo,
233 struct anv_cmd_buffer *cmd_buffer)
234 {
235 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
236
237 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
238
239 struct anv_surface *surface =
240 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
241
242 const struct anv_format *format =
243 anv_format_for_vk_format(pCreateInfo->format);
244
245 if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
246 anv_finishme("non-2D image views");
247
248 iview->image = image;
249 iview->bo = image->bo;
250 iview->offset = image->offset + surface->offset;
251 iview->format = anv_format_for_vk_format(pCreateInfo->format);
252
253 iview->extent = (VkExtent3D) {
254 .width = anv_minify(image->extent.width, range->baseMipLevel),
255 .height = anv_minify(image->extent.height, range->baseMipLevel),
256 .depth = anv_minify(image->extent.depth, range->baseMipLevel),
257 };
258
259 uint32_t depth = 1;
260 if (range->layerCount > 1) {
261 depth = range->layerCount;
262 } else if (image->extent.depth > 1) {
263 depth = image->extent.depth;
264 }
265
266 const struct isl_extent3d image_align_sa =
267 isl_surf_get_image_alignment_sa(&surface->isl);
268
269 struct GENX(RENDER_SURFACE_STATE) surface_state = {
270 .SurfaceType = anv_surftype(image, pCreateInfo->viewType, false),
271 .SurfaceArray = image->array_size > 1,
272 .SurfaceFormat = format->surface_format,
273 .SurfaceVerticalAlignment = anv_valign[image_align_sa.height],
274 .SurfaceHorizontalAlignment = anv_halign[image_align_sa.width],
275
276 /* From bspec (DevSNB, DevIVB): "Set Tile Walk to TILEWALK_XMAJOR if
277 * Tiled Surface is False."
278 */
279 .TiledSurface = surface->isl.tiling != ISL_TILING_LINEAR,
280 .TileWalk = surface->isl.tiling == ISL_TILING_Y0 ?
281 TILEWALK_YMAJOR : TILEWALK_XMAJOR,
282
283 .VerticalLineStride = 0,
284 .VerticalLineStrideOffset = 0,
285
286 .RenderCacheReadWriteMode = 0, /* TEMPLATE */
287
288 .Height = image->extent.height - 1,
289 .Width = image->extent.width - 1,
290 .Depth = depth - 1,
291 .SurfacePitch = surface->isl.row_pitch - 1,
292 .MinimumArrayElement = range->baseArrayLayer,
293 .NumberofMultisamples = MULTISAMPLECOUNT_1,
294 .XOffset = 0,
295 .YOffset = 0,
296
297 .SurfaceObjectControlState = GENX(MOCS),
298
299 .MIPCountLOD = 0, /* TEMPLATE */
300 .SurfaceMinLOD = 0, /* TEMPLATE */
301
302 .MCSEnable = false,
303 # if (ANV_IS_HASWELL)
304 .ShaderChannelSelectR = vk_to_gen_swizzle(pCreateInfo->components.r,
305 VK_COMPONENT_SWIZZLE_R),
306 .ShaderChannelSelectG = vk_to_gen_swizzle(pCreateInfo->components.g,
307 VK_COMPONENT_SWIZZLE_G),
308 .ShaderChannelSelectB = vk_to_gen_swizzle(pCreateInfo->components.b,
309 VK_COMPONENT_SWIZZLE_B),
310 .ShaderChannelSelectA = vk_to_gen_swizzle(pCreateInfo->components.a,
311 VK_COMPONENT_SWIZZLE_A),
312 # else /* XXX: Seriously? */
313 .RedClearColor = 0,
314 .GreenClearColor = 0,
315 .BlueClearColor = 0,
316 .AlphaClearColor = 0,
317 # endif
318 .ResourceMinLOD = 0.0,
319 .SurfaceBaseAddress = { NULL, iview->offset },
320 };
321
322 if (image->needs_nonrt_surface_state) {
323 iview->nonrt_surface_state = alloc_surface_state(device, cmd_buffer);
324
325 surface_state.RenderCacheReadWriteMode = false;
326
327 /* For non render target surfaces, the hardware interprets field
328 * MIPCount/LOD as MIPCount. The range of levels accessible by the
329 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
330 */
331 surface_state.SurfaceMinLOD = range->baseMipLevel;
332 surface_state.MIPCountLOD = MIN2(range->levelCount, 1) - 1;
333
334 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
335 &surface_state);
336
337 if (!device->info.has_llc)
338 anv_state_clflush(iview->nonrt_surface_state);
339 }
340
341 if (image->needs_color_rt_surface_state) {
342 iview->color_rt_surface_state = alloc_surface_state(device, cmd_buffer);
343
344 surface_state.RenderCacheReadWriteMode = 0; /* Write only */
345
346 /* For render target surfaces, the hardware interprets field MIPCount/LOD as
347 * LOD. The Broadwell PRM says:
348 *
349 * MIPCountLOD defines the LOD that will be rendered into.
350 * SurfaceMinLOD is ignored.
351 */
352 surface_state.MIPCountLOD = range->baseMipLevel;
353 surface_state.SurfaceMinLOD = 0;
354
355 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
356 &surface_state);
357 if (!device->info.has_llc)
358 anv_state_clflush(iview->color_rt_surface_state);
359 }
360
361 if (image->needs_storage_surface_state) {
362 iview->storage_surface_state = alloc_surface_state(device, cmd_buffer);
363
364 surface_state.SurfaceType =
365 anv_surftype(image, pCreateInfo->viewType, true),
366
367 surface_state.SurfaceFormat =
368 isl_lower_storage_image_format(&device->isl_dev,
369 format->surface_format);
370
371 surface_state.SurfaceMinLOD = range->baseMipLevel;
372 surface_state.MIPCountLOD = MIN2(range->levelCount, 1) - 1;
373
374 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
375 &surface_state);
376 }
377 }