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 29static VkResult 30lvp_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 110struct lvp_image * 111lvp_swapchain_get_image(VkSwapchainKHR swapchain, 112 uint32_t index) 113{ 114 VkImage image = wsi_common_get_image(swapchain, index); 115 return lvp_image_from_handle(image); 116} 117 118static VkResult 119lvp_image_from_swapchain(VkDevice device, 120 const VkImageCreateInfo *pCreateInfo, 121 const VkImageSwapchainCreateInfoKHR *swapchain_info, 122 const VkAllocationCallbacks *pAllocator, 123 VkImage *pImage) 124{ 125 ASSERTED struct lvp_image *swapchain_image = lvp_swapchain_get_image(swapchain_info->swapchain, 0); 126 assert(swapchain_image); 127 128 assert(swapchain_image->vk.image_type == pCreateInfo->imageType); 129 130 VkImageCreateInfo local_create_info; 131 local_create_info = *pCreateInfo; 132 local_create_info.pNext = NULL; 133 /* The following parameters are implictly selected by the wsi code. */ 134 local_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; 135 local_create_info.samples = VK_SAMPLE_COUNT_1_BIT; 136 local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 137 138 assert(!(local_create_info.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)); 139 return lvp_image_create(device, &local_create_info, pAllocator, 140 pImage); 141} 142 143VKAPI_ATTR VkResult VKAPI_CALL 144lvp_CreateImage(VkDevice device, 145 const VkImageCreateInfo *pCreateInfo, 146 const VkAllocationCallbacks *pAllocator, 147 VkImage *pImage) 148{ 149 const VkImageSwapchainCreateInfoKHR *swapchain_info = 150 vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR); 151 if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) 152 return lvp_image_from_swapchain(device, pCreateInfo, swapchain_info, 153 pAllocator, pImage); 154 return lvp_image_create(device, pCreateInfo, pAllocator, 155 pImage); 156} 157 158VKAPI_ATTR void VKAPI_CALL 159lvp_DestroyImage(VkDevice _device, VkImage _image, 160 const VkAllocationCallbacks *pAllocator) 161{ 162 LVP_FROM_HANDLE(lvp_device, device, _device); 163 LVP_FROM_HANDLE(lvp_image, image, _image); 164 165 if (!_image) 166 return; 167 pipe_resource_reference(&image->bo, NULL); 168 vk_image_destroy(&device->vk, pAllocator, &image->vk); 169} 170 171VKAPI_ATTR VkResult VKAPI_CALL 172lvp_CreateImageView(VkDevice _device, 173 const VkImageViewCreateInfo *pCreateInfo, 174 const VkAllocationCallbacks *pAllocator, 175 VkImageView *pView) 176{ 177 LVP_FROM_HANDLE(lvp_device, device, _device); 178 LVP_FROM_HANDLE(lvp_image, image, pCreateInfo->image); 179 struct lvp_image_view *view; 180 181 view = vk_image_view_create(&device->vk, false, pCreateInfo, 182 pAllocator, sizeof(*view)); 183 if (view == NULL) 184 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 185 186 view->pformat = lvp_vk_format_to_pipe_format(view->vk.format); 187 view->image = image; 188 view->surface = NULL; 189 *pView = lvp_image_view_to_handle(view); 190 191 return VK_SUCCESS; 192} 193 194VKAPI_ATTR void VKAPI_CALL 195lvp_DestroyImageView(VkDevice _device, VkImageView _iview, 196 const VkAllocationCallbacks *pAllocator) 197{ 198 LVP_FROM_HANDLE(lvp_device, device, _device); 199 LVP_FROM_HANDLE(lvp_image_view, iview, _iview); 200 201 if (!_iview) 202 return; 203 204 pipe_surface_reference(&iview->surface, NULL); 205 vk_image_view_destroy(&device->vk, pAllocator, &iview->vk); 206} 207 208VKAPI_ATTR void VKAPI_CALL lvp_GetImageSubresourceLayout( 209 VkDevice _device, 210 VkImage _image, 211 const VkImageSubresource* pSubresource, 212 VkSubresourceLayout* pLayout) 213{ 214 LVP_FROM_HANDLE(lvp_device, device, _device); 215 LVP_FROM_HANDLE(lvp_image, image, _image); 216 uint64_t value; 217 218 device->pscreen->resource_get_param(device->pscreen, 219 NULL, 220 image->bo, 221 0, 222 pSubresource->arrayLayer, 223 pSubresource->mipLevel, 224 PIPE_RESOURCE_PARAM_STRIDE, 225 0, &value); 226 227 pLayout->rowPitch = value; 228 229 device->pscreen->resource_get_param(device->pscreen, 230 NULL, 231 image->bo, 232 0, 233 pSubresource->arrayLayer, 234 pSubresource->mipLevel, 235 PIPE_RESOURCE_PARAM_OFFSET, 236 0, &value); 237 238 pLayout->offset = value; 239 240 device->pscreen->resource_get_param(device->pscreen, 241 NULL, 242 image->bo, 243 0, 244 pSubresource->arrayLayer, 245 pSubresource->mipLevel, 246 PIPE_RESOURCE_PARAM_LAYER_STRIDE, 247 0, &value); 248 249 if (image->bo->target == PIPE_TEXTURE_3D) { 250 pLayout->depthPitch = value; 251 pLayout->arrayPitch = 0; 252 } else { 253 pLayout->depthPitch = 0; 254 pLayout->arrayPitch = value; 255 } 256 pLayout->size = image->size; 257 258 switch (pSubresource->aspectMask) { 259 case VK_IMAGE_ASPECT_COLOR_BIT: 260 break; 261 case VK_IMAGE_ASPECT_DEPTH_BIT: 262 break; 263 case VK_IMAGE_ASPECT_STENCIL_BIT: 264 break; 265 default: 266 assert(!"Invalid image aspect"); 267 } 268} 269 270VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateBuffer( 271 VkDevice _device, 272 const VkBufferCreateInfo* pCreateInfo, 273 const VkAllocationCallbacks* pAllocator, 274 VkBuffer* pBuffer) 275{ 276 LVP_FROM_HANDLE(lvp_device, device, _device); 277 struct lvp_buffer *buffer; 278 279 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); 280 281 /* gallium has max 32-bit buffer sizes */ 282 if (pCreateInfo->size > UINT32_MAX) 283 return VK_ERROR_OUT_OF_DEVICE_MEMORY; 284 285 buffer = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*buffer), 8, 286 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 287 if (buffer == NULL) 288 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 289 290 vk_object_base_init(&device->vk, &buffer->base, VK_OBJECT_TYPE_BUFFER); 291 buffer->size = pCreateInfo->size; 292 buffer->usage = pCreateInfo->usage; 293 buffer->offset = 0; 294 295 { 296 struct pipe_resource template; 297 memset(&template, 0, sizeof(struct pipe_resource)); 298 299 if (pCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) 300 template.bind |= PIPE_BIND_CONSTANT_BUFFER; 301 302 template.screen = device->pscreen; 303 template.target = PIPE_BUFFER; 304 template.format = PIPE_FORMAT_R8_UNORM; 305 template.width0 = buffer->size; 306 template.height0 = 1; 307 template.depth0 = 1; 308 template.array_size = 1; 309 if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) 310 template.bind |= PIPE_BIND_SAMPLER_VIEW; 311 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) 312 template.bind |= PIPE_BIND_SHADER_BUFFER; 313 if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) 314 template.bind |= PIPE_BIND_SHADER_IMAGE; 315 template.flags = PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE; 316 buffer->bo = device->pscreen->resource_create_unbacked(device->pscreen, 317 &template, 318 &buffer->total_size); 319 if (!buffer->bo) { 320 vk_free2(&device->vk.alloc, pAllocator, buffer); 321 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY); 322 } 323 } 324 *pBuffer = lvp_buffer_to_handle(buffer); 325 326 return VK_SUCCESS; 327} 328 329VKAPI_ATTR void VKAPI_CALL lvp_DestroyBuffer( 330 VkDevice _device, 331 VkBuffer _buffer, 332 const VkAllocationCallbacks* pAllocator) 333{ 334 LVP_FROM_HANDLE(lvp_device, device, _device); 335 LVP_FROM_HANDLE(lvp_buffer, buffer, _buffer); 336 337 if (!_buffer) 338 return; 339 340 pipe_resource_reference(&buffer->bo, NULL); 341 vk_object_base_finish(&buffer->base); 342 vk_free2(&device->vk.alloc, pAllocator, buffer); 343} 344 345VKAPI_ATTR VkDeviceAddress VKAPI_CALL lvp_GetBufferDeviceAddress( 346 VkDevice device, 347 const VkBufferDeviceAddressInfo* pInfo) 348{ 349 LVP_FROM_HANDLE(lvp_buffer, buffer, pInfo->buffer); 350 351 return (VkDeviceAddress)(uintptr_t)buffer->pmem; 352} 353 354VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetBufferOpaqueCaptureAddress( 355 VkDevice device, 356 const VkBufferDeviceAddressInfo* pInfo) 357{ 358 return 0; 359} 360 361VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetDeviceMemoryOpaqueCaptureAddress( 362 VkDevice device, 363 const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo) 364{ 365 return 0; 366} 367 368VKAPI_ATTR VkResult VKAPI_CALL 369lvp_CreateBufferView(VkDevice _device, 370 const VkBufferViewCreateInfo *pCreateInfo, 371 const VkAllocationCallbacks *pAllocator, 372 VkBufferView *pView) 373{ 374 LVP_FROM_HANDLE(lvp_device, device, _device); 375 LVP_FROM_HANDLE(lvp_buffer, buffer, pCreateInfo->buffer); 376 struct lvp_buffer_view *view; 377 view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8, 378 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 379 if (!view) 380 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 381 382 vk_object_base_init(&device->vk, &view->base, 383 VK_OBJECT_TYPE_BUFFER_VIEW); 384 view->buffer = buffer; 385 view->format = pCreateInfo->format; 386 view->pformat = lvp_vk_format_to_pipe_format(pCreateInfo->format); 387 view->offset = pCreateInfo->offset; 388 view->range = pCreateInfo->range; 389 *pView = lvp_buffer_view_to_handle(view); 390 391 return VK_SUCCESS; 392} 393 394VKAPI_ATTR void VKAPI_CALL 395lvp_DestroyBufferView(VkDevice _device, VkBufferView bufferView, 396 const VkAllocationCallbacks *pAllocator) 397{ 398 LVP_FROM_HANDLE(lvp_device, device, _device); 399 LVP_FROM_HANDLE(lvp_buffer_view, view, bufferView); 400 401 if (!bufferView) 402 return; 403 vk_object_base_finish(&view->base); 404 vk_free2(&device->vk.alloc, pAllocator, view); 405} 406