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 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 129static VkResult 130lvp_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 154VKAPI_ATTR VkResult VKAPI_CALL 155lvp_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 169VKAPI_ATTR void VKAPI_CALL 170lvp_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 182VKAPI_ATTR VkResult VKAPI_CALL 183lvp_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 211VKAPI_ATTR void VKAPI_CALL 212lvp_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 226VKAPI_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 288VKAPI_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 347VKAPI_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 363VKAPI_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 372VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetBufferOpaqueCaptureAddress( 373 VkDevice device, 374 const VkBufferDeviceAddressInfoKHR* pInfo) 375{ 376 return 0; 377} 378 379VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetDeviceMemoryOpaqueCaptureAddress( 380 VkDevice device, 381 const VkDeviceMemoryOpaqueCaptureAddressInfoKHR* pInfo) 382{ 383 return 0; 384} 385 386VKAPI_ATTR VkResult VKAPI_CALL 387lvp_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 412VKAPI_ATTR void VKAPI_CALL 413lvp_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