Home | History | Annotate | Line # | Download | only in lavapipe
      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
     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 *
    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
    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
    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
    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
    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
    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 
    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 
    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 
    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 
    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 
    372 VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetBufferOpaqueCaptureAddress(
    373     VkDevice                                    device,
    374     const VkBufferDeviceAddressInfoKHR*         pInfo)
    375 {
    376    return 0;
    377 }
    378 
    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
    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
    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