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