1 /*
2 * Copyright © 2019 Red Hat.
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 "lvp_private.h"
25 #include "util/format/u_format.h"
26 #include "util/u_inlines.h"
27 #include "pipe/p_state.h"
28
29 static VkResult
lvp_image_create(VkDevice _device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * alloc,VkImage * pImage)30 lvp_image_create(VkDevice _device,
31 const VkImageCreateInfo *pCreateInfo,
32 const VkAllocationCallbacks* alloc,
33 VkImage *pImage)
34 {
35 LVP_FROM_HANDLE(lvp_device, device, _device);
36 struct lvp_image *image;
37
38 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
39
40 image = vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image));
41 if (image == NULL)
42 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
43
44 image->alignment = 16;
45 {
46 struct pipe_resource template;
47
48 memset(&template, 0, sizeof(template));
49
50 template.screen = device->pscreen;
51 switch (pCreateInfo->imageType) {
52 case VK_IMAGE_TYPE_1D:
53 template.target = pCreateInfo->arrayLayers > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D;
54 break;
55 default:
56 case VK_IMAGE_TYPE_2D:
57 template.target = pCreateInfo->arrayLayers > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D;
58 break;
59 case VK_IMAGE_TYPE_3D:
60 template.target = PIPE_TEXTURE_3D;
61 break;
62 }
63
64 template.format = lvp_vk_format_to_pipe_format(pCreateInfo->format);
65
66 bool is_ds = util_format_is_depth_or_stencil(template.format);
67
68 if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
69 template.bind |= PIPE_BIND_RENDER_TARGET;
70 /* sampler view is needed for resolve blits */
71 if (pCreateInfo->samples > 1)
72 template.bind |= PIPE_BIND_SAMPLER_VIEW;
73 }
74
75 if (pCreateInfo->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
76 if (!is_ds)
77 template.bind |= PIPE_BIND_RENDER_TARGET;
78 else
79 template.bind |= PIPE_BIND_DEPTH_STENCIL;
80 }
81
82 if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
83 template.bind |= PIPE_BIND_DEPTH_STENCIL;
84
85 if (pCreateInfo->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
86 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
87 template.bind |= PIPE_BIND_SAMPLER_VIEW;
88
89 if (pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT)
90 template.bind |= PIPE_BIND_SHADER_IMAGE;
91
92 template.width0 = pCreateInfo->extent.width;
93 template.height0 = pCreateInfo->extent.height;
94 template.depth0 = pCreateInfo->extent.depth;
95 template.array_size = pCreateInfo->arrayLayers;
96 template.last_level = pCreateInfo->mipLevels - 1;
97 template.nr_samples = pCreateInfo->samples;
98 template.nr_storage_samples = pCreateInfo->samples;
99 image->bo = device->pscreen->resource_create_unbacked(device->pscreen,
100 &template,
101 &image->size);
102 if (!image->bo)
103 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
104 }
105 *pImage = lvp_image_to_handle(image);
106
107 return VK_SUCCESS;
108 }
109
110 struct lvp_image *
lvp_swapchain_get_image(VkSwapchainKHR swapchain,uint32_t index)111 lvp_swapchain_get_image(VkSwapchainKHR swapchain,
112 uint32_t index)
113 {
114 uint32_t n_images = index + 1;
115 VkImage *images = malloc(sizeof(*images) * n_images);
116 VkResult result = wsi_common_get_images(swapchain, &n_images, images);
117
118 if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
119 free(images);
120 return NULL;
121 }
122
123 LVP_FROM_HANDLE(lvp_image, image, images[index]);
124 free(images);
125
126 return image;
127 }
128
129 static VkResult
lvp_image_from_swapchain(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkImageSwapchainCreateInfoKHR * swapchain_info,const VkAllocationCallbacks * pAllocator,VkImage * pImage)130 lvp_image_from_swapchain(VkDevice device,
131 const VkImageCreateInfo *pCreateInfo,
132 const VkImageSwapchainCreateInfoKHR *swapchain_info,
133 const VkAllocationCallbacks *pAllocator,
134 VkImage *pImage)
135 {
136 ASSERTED struct lvp_image *swapchain_image = lvp_swapchain_get_image(swapchain_info->swapchain, 0);
137 assert(swapchain_image);
138
139 assert(swapchain_image->vk.image_type == pCreateInfo->imageType);
140
141 VkImageCreateInfo local_create_info;
142 local_create_info = *pCreateInfo;
143 local_create_info.pNext = NULL;
144 /* The following parameters are implictly selected by the wsi code. */
145 local_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
146 local_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
147 local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
148
149 assert(!(local_create_info.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
150 return lvp_image_create(device, &local_create_info, pAllocator,
151 pImage);
152 }
153
154 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)155 lvp_CreateImage(VkDevice device,
156 const VkImageCreateInfo *pCreateInfo,
157 const VkAllocationCallbacks *pAllocator,
158 VkImage *pImage)
159 {
160 const VkImageSwapchainCreateInfoKHR *swapchain_info =
161 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
162 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
163 return lvp_image_from_swapchain(device, pCreateInfo, swapchain_info,
164 pAllocator, pImage);
165 return lvp_image_create(device, pCreateInfo, pAllocator,
166 pImage);
167 }
168
169 VKAPI_ATTR void VKAPI_CALL
lvp_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)170 lvp_DestroyImage(VkDevice _device, VkImage _image,
171 const VkAllocationCallbacks *pAllocator)
172 {
173 LVP_FROM_HANDLE(lvp_device, device, _device);
174 LVP_FROM_HANDLE(lvp_image, image, _image);
175
176 if (!_image)
177 return;
178 pipe_resource_reference(&image->bo, NULL);
179 vk_image_destroy(&device->vk, pAllocator, &image->vk);
180 }
181
182 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)183 lvp_CreateImageView(VkDevice _device,
184 const VkImageViewCreateInfo *pCreateInfo,
185 const VkAllocationCallbacks *pAllocator,
186 VkImageView *pView)
187 {
188 LVP_FROM_HANDLE(lvp_device, device, _device);
189 LVP_FROM_HANDLE(lvp_image, image, pCreateInfo->image);
190 struct lvp_image_view *view;
191
192 view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8,
193 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
194 if (view == NULL)
195 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
196
197 vk_object_base_init(&device->vk, &view->base,
198 VK_OBJECT_TYPE_IMAGE_VIEW);
199 view->view_type = pCreateInfo->viewType;
200 view->format = pCreateInfo->format;
201 view->pformat = lvp_vk_format_to_pipe_format(pCreateInfo->format);
202 view->components = pCreateInfo->components;
203 view->subresourceRange = pCreateInfo->subresourceRange;
204 view->image = image;
205 view->surface = NULL;
206 *pView = lvp_image_view_to_handle(view);
207
208 return VK_SUCCESS;
209 }
210
211 VKAPI_ATTR void VKAPI_CALL
lvp_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)212 lvp_DestroyImageView(VkDevice _device, VkImageView _iview,
213 const VkAllocationCallbacks *pAllocator)
214 {
215 LVP_FROM_HANDLE(lvp_device, device, _device);
216 LVP_FROM_HANDLE(lvp_image_view, iview, _iview);
217
218 if (!_iview)
219 return;
220
221 pipe_surface_reference(&iview->surface, NULL);
222 vk_object_base_finish(&iview->base);
223 vk_free2(&device->vk.alloc, pAllocator, iview);
224 }
225
lvp_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * pSubresource,VkSubresourceLayout * pLayout)226 VKAPI_ATTR void VKAPI_CALL lvp_GetImageSubresourceLayout(
227 VkDevice _device,
228 VkImage _image,
229 const VkImageSubresource* pSubresource,
230 VkSubresourceLayout* pLayout)
231 {
232 LVP_FROM_HANDLE(lvp_device, device, _device);
233 LVP_FROM_HANDLE(lvp_image, image, _image);
234 uint64_t value;
235
236 device->pscreen->resource_get_param(device->pscreen,
237 NULL,
238 image->bo,
239 0,
240 pSubresource->arrayLayer,
241 pSubresource->mipLevel,
242 PIPE_RESOURCE_PARAM_STRIDE,
243 0, &value);
244
245 pLayout->rowPitch = value;
246
247 device->pscreen->resource_get_param(device->pscreen,
248 NULL,
249 image->bo,
250 0,
251 pSubresource->arrayLayer,
252 pSubresource->mipLevel,
253 PIPE_RESOURCE_PARAM_OFFSET,
254 0, &value);
255
256 pLayout->offset = value;
257
258 device->pscreen->resource_get_param(device->pscreen,
259 NULL,
260 image->bo,
261 0,
262 pSubresource->arrayLayer,
263 pSubresource->mipLevel,
264 PIPE_RESOURCE_PARAM_LAYER_STRIDE,
265 0, &value);
266
267 if (image->bo->target == PIPE_TEXTURE_3D) {
268 pLayout->depthPitch = value;
269 pLayout->arrayPitch = 0;
270 } else {
271 pLayout->depthPitch = 0;
272 pLayout->arrayPitch = value;
273 }
274 pLayout->size = image->size;
275
276 switch (pSubresource->aspectMask) {
277 case VK_IMAGE_ASPECT_COLOR_BIT:
278 break;
279 case VK_IMAGE_ASPECT_DEPTH_BIT:
280 break;
281 case VK_IMAGE_ASPECT_STENCIL_BIT:
282 break;
283 default:
284 assert(!"Invalid image aspect");
285 }
286 }
287
lvp_CreateBuffer(VkDevice _device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)288 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateBuffer(
289 VkDevice _device,
290 const VkBufferCreateInfo* pCreateInfo,
291 const VkAllocationCallbacks* pAllocator,
292 VkBuffer* pBuffer)
293 {
294 LVP_FROM_HANDLE(lvp_device, device, _device);
295 struct lvp_buffer *buffer;
296
297 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
298
299 /* gallium has max 32-bit buffer sizes */
300 if (pCreateInfo->size > UINT32_MAX)
301 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
302
303 buffer = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*buffer), 8,
304 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
305 if (buffer == NULL)
306 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
307
308 vk_object_base_init(&device->vk, &buffer->base, VK_OBJECT_TYPE_BUFFER);
309 buffer->size = pCreateInfo->size;
310 buffer->usage = pCreateInfo->usage;
311 buffer->offset = 0;
312
313 {
314 struct pipe_resource template;
315 memset(&template, 0, sizeof(struct pipe_resource));
316
317 if (pCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
318 template.bind |= PIPE_BIND_CONSTANT_BUFFER;
319
320 template.screen = device->pscreen;
321 template.target = PIPE_BUFFER;
322 template.format = PIPE_FORMAT_R8_UNORM;
323 template.width0 = buffer->size;
324 template.height0 = 1;
325 template.depth0 = 1;
326 template.array_size = 1;
327 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
328 template.bind |= PIPE_BIND_SAMPLER_VIEW;
329 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
330 template.bind |= PIPE_BIND_SHADER_BUFFER;
331 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
332 template.bind |= PIPE_BIND_SHADER_IMAGE;
333 template.flags = PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE;
334 buffer->bo = device->pscreen->resource_create_unbacked(device->pscreen,
335 &template,
336 &buffer->total_size);
337 if (!buffer->bo) {
338 vk_free2(&device->vk.alloc, pAllocator, buffer);
339 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
340 }
341 }
342 *pBuffer = lvp_buffer_to_handle(buffer);
343
344 return VK_SUCCESS;
345 }
346
lvp_DestroyBuffer(VkDevice _device,VkBuffer _buffer,const VkAllocationCallbacks * pAllocator)347 VKAPI_ATTR void VKAPI_CALL lvp_DestroyBuffer(
348 VkDevice _device,
349 VkBuffer _buffer,
350 const VkAllocationCallbacks* pAllocator)
351 {
352 LVP_FROM_HANDLE(lvp_device, device, _device);
353 LVP_FROM_HANDLE(lvp_buffer, buffer, _buffer);
354
355 if (!_buffer)
356 return;
357
358 pipe_resource_reference(&buffer->bo, NULL);
359 vk_object_base_finish(&buffer->base);
360 vk_free2(&device->vk.alloc, pAllocator, buffer);
361 }
362
lvp_GetBufferDeviceAddress(VkDevice device,const VkBufferDeviceAddressInfoKHR * pInfo)363 VKAPI_ATTR VkDeviceAddress VKAPI_CALL lvp_GetBufferDeviceAddress(
364 VkDevice device,
365 const VkBufferDeviceAddressInfoKHR* pInfo)
366 {
367 LVP_FROM_HANDLE(lvp_buffer, buffer, pInfo->buffer);
368
369 return (VkDeviceAddress)(uintptr_t)buffer->pmem;
370 }
371
lvp_GetBufferOpaqueCaptureAddress(VkDevice device,const VkBufferDeviceAddressInfoKHR * pInfo)372 VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetBufferOpaqueCaptureAddress(
373 VkDevice device,
374 const VkBufferDeviceAddressInfoKHR* pInfo)
375 {
376 return 0;
377 }
378
lvp_GetDeviceMemoryOpaqueCaptureAddress(VkDevice device,const VkDeviceMemoryOpaqueCaptureAddressInfoKHR * pInfo)379 VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetDeviceMemoryOpaqueCaptureAddress(
380 VkDevice device,
381 const VkDeviceMemoryOpaqueCaptureAddressInfoKHR* pInfo)
382 {
383 return 0;
384 }
385
386 VKAPI_ATTR VkResult VKAPI_CALL
lvp_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)387 lvp_CreateBufferView(VkDevice _device,
388 const VkBufferViewCreateInfo *pCreateInfo,
389 const VkAllocationCallbacks *pAllocator,
390 VkBufferView *pView)
391 {
392 LVP_FROM_HANDLE(lvp_device, device, _device);
393 LVP_FROM_HANDLE(lvp_buffer, buffer, pCreateInfo->buffer);
394 struct lvp_buffer_view *view;
395 view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8,
396 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
397 if (!view)
398 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
399
400 vk_object_base_init(&device->vk, &view->base,
401 VK_OBJECT_TYPE_BUFFER_VIEW);
402 view->buffer = buffer;
403 view->format = pCreateInfo->format;
404 view->pformat = lvp_vk_format_to_pipe_format(pCreateInfo->format);
405 view->offset = pCreateInfo->offset;
406 view->range = pCreateInfo->range;
407 *pView = lvp_buffer_view_to_handle(view);
408
409 return VK_SUCCESS;
410 }
411
412 VKAPI_ATTR void VKAPI_CALL
lvp_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)413 lvp_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
414 const VkAllocationCallbacks *pAllocator)
415 {
416 LVP_FROM_HANDLE(lvp_device, device, _device);
417 LVP_FROM_HANDLE(lvp_buffer_view, view, bufferView);
418
419 if (!bufferView)
420 return;
421 vk_object_base_finish(&view->base);
422 vk_free2(&device->vk.alloc, pAllocator, view);
423 }
424