vk/image: Add tables for gen SurfaceType
[mesa.git] / src / vulkan / image.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 "private.h"
31
32 static const uint8_t anv_halign[] = {
33 [4] = HALIGN4,
34 [8] = HALIGN8,
35 [16] = HALIGN16,
36 };
37
38 static const uint8_t anv_valign[] = {
39 [4] = VALIGN4,
40 [8] = VALIGN8,
41 [16] = VALIGN16,
42 };
43
44 static const uint8_t anv_surf_type_from_image_type[] = {
45 [VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
46 [VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
47 [VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
48 };
49
50 static const uint8_t anv_surf_type_from_image_view_type[] = {
51 [VK_IMAGE_VIEW_TYPE_1D] = SURFTYPE_1D,
52 [VK_IMAGE_VIEW_TYPE_2D] = SURFTYPE_2D,
53 [VK_IMAGE_VIEW_TYPE_3D] = SURFTYPE_3D,
54 [VK_IMAGE_VIEW_TYPE_CUBE] = SURFTYPE_CUBE,
55 };
56
57 static const struct anv_tile_info {
58 uint32_t width;
59 uint32_t height;
60
61 /**
62 * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
63 *
64 * To simplify calculations, the alignments defined in the table are
65 * sometimes larger than required. For example, Skylake requires that X and
66 * Y tiled buffers be aligned to 4K, but Broadwell permits smaller
67 * alignment. We choose 4K to accomodate both chipsets. The alignment of
68 * a linear buffer depends on its element type and usage. Linear depth
69 * buffers have the largest alignment, 64B, so we choose that for all linear
70 * buffers.
71 */
72 uint32_t surface_alignment;
73 } anv_tile_info_table[] = {
74 [LINEAR] = { 1, 1, 64 },
75 [XMAJOR] = { 512, 8, 4096 },
76 [YMAJOR] = { 128, 32, 4096 },
77 [WMAJOR] = { 128, 32, 4096 },
78 };
79
80 static uint32_t
81 anv_image_choose_tile_mode(const VkImageCreateInfo *vk_info,
82 const struct anv_image_create_info *anv_info)
83 {
84 if (anv_info)
85 return anv_info->tile_mode;
86
87 switch (vk_info->tiling) {
88 case VK_IMAGE_TILING_LINEAR:
89 return LINEAR;
90 case VK_IMAGE_TILING_OPTIMAL:
91 return YMAJOR;
92 default:
93 assert(!"bad VKImageTiling");
94 return LINEAR;
95 }
96 }
97
98 VkResult anv_image_create(
99 VkDevice _device,
100 const VkImageCreateInfo* pCreateInfo,
101 const struct anv_image_create_info * extra,
102 VkImage* pImage)
103 {
104 struct anv_device *device = (struct anv_device *) _device;
105 struct anv_image *image;
106 const struct anv_format *info;
107 int32_t aligned_height;
108 uint32_t stencil_size;
109
110 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
111
112 image = anv_device_alloc(device, sizeof(*image), 8,
113 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
114 if (image == NULL)
115 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
116
117 /* XXX: We don't handle any of these */
118 anv_assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
119 anv_assert(pCreateInfo->mipLevels == 1);
120 anv_assert(pCreateInfo->arraySize == 1);
121 anv_assert(pCreateInfo->samples == 1);
122 anv_assert(pCreateInfo->extent.depth == 1);
123
124 image->bo = NULL;
125 image->offset = 0;
126 image->type = pCreateInfo->imageType;
127 image->format = pCreateInfo->format;
128 image->extent = pCreateInfo->extent;
129 image->swap_chain = NULL;
130 image->tile_mode = anv_image_choose_tile_mode(pCreateInfo, extra);
131
132 assert(image->extent.width > 0);
133 assert(image->extent.height > 0);
134 assert(image->extent.depth > 0);
135
136 const struct anv_tile_info *tile_info =
137 &anv_tile_info_table[image->tile_mode];
138
139 image->alignment = tile_info->surface_alignment;
140
141 /* FINISHME: Stop hardcoding miptree image alignment */
142 image->h_align = 4;
143 image->v_align = 4;
144
145 info = anv_format_for_vk_format(pCreateInfo->format);
146 assert(info->cpp > 0 || info->has_stencil);
147
148 /* First allocate space for the color or depth buffer. info->cpp gives us
149 * the cpp of the color or depth in case of depth/stencil formats. Stencil
150 * only (VK_FORMAT_S8_UINT) has info->cpp == 0 and doesn't allocate
151 * anything here.
152 */
153 if (info->cpp > 0) {
154 image->stride = ALIGN_I32(image->extent.width * info->cpp,
155 tile_info->width);
156 aligned_height = ALIGN_I32(image->extent.height, tile_info->height);
157 image->size = image->stride * aligned_height;
158 } else {
159 image->size = 0;
160 image->stride = 0;
161 }
162
163 /* Formats with a stencil buffer (either combined depth/stencil or
164 * VK_FORMAT_S8_UINT) have info->has_stencil == true. The stencil buffer is
165 * placed after the depth buffer and is a separate buffer from the GPU
166 * point of view, but as far as the API is concerned, depth and stencil are
167 * in the same image.
168 */
169 if (info->has_stencil) {
170 const struct anv_tile_info *w_info = &anv_tile_info_table[WMAJOR];
171 image->stencil_offset = ALIGN_U32(image->size, w_info->surface_alignment);
172 image->stencil_stride = ALIGN_I32(image->extent.width, w_info->width);
173 aligned_height = ALIGN_I32(image->extent.height, w_info->height);
174 stencil_size = image->stencil_stride * aligned_height;
175 image->size = image->stencil_offset + stencil_size;
176 } else {
177 image->stencil_offset = 0;
178 image->stencil_stride = 0;
179 }
180
181 *pImage = (VkImage) image;
182
183 return VK_SUCCESS;
184 }
185
186 VkResult anv_CreateImage(
187 VkDevice device,
188 const VkImageCreateInfo* pCreateInfo,
189 VkImage* pImage)
190 {
191 return anv_image_create(device, pCreateInfo, NULL, pImage);
192 }
193
194 VkResult anv_GetImageSubresourceInfo(
195 VkDevice device,
196 VkImage image,
197 const VkImageSubresource* pSubresource,
198 VkSubresourceInfoType infoType,
199 size_t* pDataSize,
200 void* pData)
201 {
202 stub_return(VK_UNSUPPORTED);
203 }
204
205 void
206 anv_surface_view_destroy(struct anv_device *device,
207 struct anv_object *obj, VkObjectType obj_type)
208 {
209 struct anv_surface_view *view = (struct anv_surface_view *)obj;
210
211 assert(obj_type == VK_OBJECT_TYPE_BUFFER_VIEW ||
212 obj_type == VK_OBJECT_TYPE_IMAGE_VIEW ||
213 obj_type == VK_OBJECT_TYPE_COLOR_ATTACHMENT_VIEW);
214
215 anv_state_pool_free(&device->surface_state_pool, view->surface_state);
216
217 anv_device_free(device, view);
218 }
219
220 void
221 anv_image_view_init(struct anv_surface_view *view,
222 struct anv_device *device,
223 const VkImageViewCreateInfo* pCreateInfo,
224 struct anv_cmd_buffer *cmd_buffer)
225 {
226 struct anv_image *image = (struct anv_image *) pCreateInfo->image;
227 const struct anv_format *info =
228 anv_format_for_vk_format(pCreateInfo->format);
229 uint32_t tile_mode, format;
230
231 /* XXX: We don't handle any of these */
232 anv_assert(pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_2D);
233 anv_assert(pCreateInfo->subresourceRange.baseMipLevel == 0);
234 anv_assert(pCreateInfo->subresourceRange.mipLevels == 1);
235 anv_assert(pCreateInfo->subresourceRange.baseArraySlice == 0);
236 anv_assert(pCreateInfo->subresourceRange.arraySize == 1);
237
238 view->bo = image->bo;
239 switch (pCreateInfo->subresourceRange.aspect) {
240 case VK_IMAGE_ASPECT_STENCIL:
241 /* FIXME: How is stencil texturing formed? */
242 view->offset = image->offset + image->stencil_offset;
243 tile_mode = WMAJOR;
244 format = R8_UINT;
245 break;
246 case VK_IMAGE_ASPECT_DEPTH:
247 case VK_IMAGE_ASPECT_COLOR:
248 view->offset = image->offset;
249 tile_mode = image->tile_mode;
250 format = info->format;
251 break;
252 default:
253 unreachable("");
254 break;
255 }
256
257 /* TODO: Miplevels */
258 view->extent = image->extent;
259
260 static const uint32_t vk_to_gen_swizzle[] = {
261 [VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
262 [VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
263 [VK_CHANNEL_SWIZZLE_R] = SCS_RED,
264 [VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
265 [VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
266 [VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
267 };
268
269 struct GEN8_RENDER_SURFACE_STATE surface_state = {
270 .SurfaceType = SURFTYPE_2D,
271 .SurfaceArray = false,
272 .SurfaceFormat = format,
273 .SurfaceVerticalAlignment = anv_valign[image->v_align],
274 .SurfaceHorizontalAlignment = anv_halign[image->h_align],
275 .TileMode = tile_mode,
276 .VerticalLineStride = 0,
277 .VerticalLineStrideOffset = 0,
278 .SamplerL2BypassModeDisable = true,
279 .RenderCacheReadWriteMode = WriteOnlyCache,
280 .MemoryObjectControlState = GEN8_MOCS,
281 .BaseMipLevel = 0.0,
282 .SurfaceQPitch = 0,
283 .Height = image->extent.height - 1,
284 .Width = image->extent.width - 1,
285 .Depth = image->extent.depth - 1,
286 .SurfacePitch = image->stride - 1,
287 .MinimumArrayElement = 0,
288 .NumberofMultisamples = MULTISAMPLECOUNT_1,
289 .XOffset = 0,
290 .YOffset = 0,
291 .SurfaceMinLOD = 0,
292 .MIPCountLOD = 0,
293 .AuxiliarySurfaceMode = AUX_NONE,
294 .RedClearColor = 0,
295 .GreenClearColor = 0,
296 .BlueClearColor = 0,
297 .AlphaClearColor = 0,
298 .ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
299 .ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
300 .ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
301 .ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
302 .ResourceMinLOD = 0.0,
303 .SurfaceBaseAddress = { NULL, view->offset },
304 };
305
306 if (cmd_buffer)
307 view->surface_state =
308 anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
309 else
310 view->surface_state =
311 anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
312
313 GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
314 }
315
316 VkResult anv_CreateImageView(
317 VkDevice _device,
318 const VkImageViewCreateInfo* pCreateInfo,
319 VkImageView* pView)
320 {
321 struct anv_device *device = (struct anv_device *) _device;
322 struct anv_surface_view *view;
323
324 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
325
326 view = anv_device_alloc(device, sizeof(*view), 8,
327 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
328 if (view == NULL)
329 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
330
331 anv_image_view_init(view, device, pCreateInfo, NULL);
332
333 view->base.destructor = anv_surface_view_destroy;
334
335 *pView = (VkImageView) view;
336
337 return VK_SUCCESS;
338 }
339
340 void
341 anv_color_attachment_view_init(struct anv_surface_view *view,
342 struct anv_device *device,
343 const VkColorAttachmentViewCreateInfo* pCreateInfo,
344 struct anv_cmd_buffer *cmd_buffer)
345 {
346 struct anv_image *image = (struct anv_image *) pCreateInfo->image;
347 const struct anv_format *format =
348 anv_format_for_vk_format(pCreateInfo->format);
349
350 /* XXX: We don't handle any of these */
351 anv_assert(pCreateInfo->mipLevel == 0);
352 anv_assert(pCreateInfo->baseArraySlice == 0);
353 anv_assert(pCreateInfo->arraySize == 1);
354 anv_assert(pCreateInfo->msaaResolveImage == 0);
355
356 view->bo = image->bo;
357 view->offset = image->offset;
358 view->extent = image->extent;
359 view->format = pCreateInfo->format;
360
361 if (cmd_buffer)
362 view->surface_state =
363 anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
364 else
365 view->surface_state =
366 anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
367
368 struct GEN8_RENDER_SURFACE_STATE surface_state = {
369 .SurfaceType = SURFTYPE_2D,
370 .SurfaceArray = false,
371 .SurfaceFormat = format->format,
372 .SurfaceVerticalAlignment = anv_valign[image->v_align],
373 .SurfaceHorizontalAlignment = anv_halign[image->h_align],
374 .TileMode = image->tile_mode,
375 .VerticalLineStride = 0,
376 .VerticalLineStrideOffset = 0,
377 .SamplerL2BypassModeDisable = true,
378 .RenderCacheReadWriteMode = WriteOnlyCache,
379 .MemoryObjectControlState = GEN8_MOCS,
380 .BaseMipLevel = 0.0,
381 .SurfaceQPitch = 0,
382 .Height = image->extent.height - 1,
383 .Width = image->extent.width - 1,
384 .Depth = image->extent.depth - 1,
385 .SurfacePitch = image->stride - 1,
386 .MinimumArrayElement = 0,
387 .NumberofMultisamples = MULTISAMPLECOUNT_1,
388 .XOffset = 0,
389 .YOffset = 0,
390 .SurfaceMinLOD = 0,
391 .MIPCountLOD = 0,
392 .AuxiliarySurfaceMode = AUX_NONE,
393 .RedClearColor = 0,
394 .GreenClearColor = 0,
395 .BlueClearColor = 0,
396 .AlphaClearColor = 0,
397 .ShaderChannelSelectRed = SCS_RED,
398 .ShaderChannelSelectGreen = SCS_GREEN,
399 .ShaderChannelSelectBlue = SCS_BLUE,
400 .ShaderChannelSelectAlpha = SCS_ALPHA,
401 .ResourceMinLOD = 0.0,
402 .SurfaceBaseAddress = { NULL, view->offset },
403 };
404
405 GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
406 }
407
408 VkResult anv_CreateColorAttachmentView(
409 VkDevice _device,
410 const VkColorAttachmentViewCreateInfo* pCreateInfo,
411 VkColorAttachmentView* pView)
412 {
413 struct anv_device *device = (struct anv_device *) _device;
414 struct anv_surface_view *view;
415
416 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO);
417
418 view = anv_device_alloc(device, sizeof(*view), 8,
419 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
420 if (view == NULL)
421 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
422
423 anv_color_attachment_view_init(view, device, pCreateInfo, NULL);
424
425 view->base.destructor = anv_surface_view_destroy;
426
427 *pView = (VkColorAttachmentView) view;
428
429 return VK_SUCCESS;
430 }
431
432 VkResult anv_CreateDepthStencilView(
433 VkDevice _device,
434 const VkDepthStencilViewCreateInfo* pCreateInfo,
435 VkDepthStencilView* pView)
436 {
437 struct anv_device *device = (struct anv_device *) _device;
438 struct anv_depth_stencil_view *view;
439 struct anv_image *image = (struct anv_image *) pCreateInfo->image;
440 const struct anv_format *format =
441 anv_format_for_vk_format(image->format);
442
443 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEPTH_STENCIL_VIEW_CREATE_INFO);
444
445 view = anv_device_alloc(device, sizeof(*view), 8,
446 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
447 if (view == NULL)
448 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
449
450 /* XXX: We don't handle any of these */
451 anv_assert(pCreateInfo->mipLevel == 0);
452 anv_assert(pCreateInfo->baseArraySlice == 0);
453 anv_assert(pCreateInfo->arraySize == 1);
454 anv_assert(pCreateInfo->msaaResolveImage == 0);
455
456 view->bo = image->bo;
457
458 view->depth_stride = image->stride;
459 view->depth_offset = image->offset;
460 view->depth_format = format->format;
461
462 view->stencil_stride = image->stencil_stride;
463 view->stencil_offset = image->offset + image->stencil_offset;
464
465 *pView = (VkDepthStencilView) view;
466
467 return VK_SUCCESS;
468 }