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