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