pPresentModes);
}
-static VkResult
-radv_wsi_image_create(VkDevice device_h,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- struct wsi_image *wsi_image)
-{
- VkResult result = VK_SUCCESS;
- struct radeon_surf *surface;
- VkImage image_h;
- struct radv_image *image;
- int fd;
- RADV_FROM_HANDLE(radv_device, device, device_h);
-
- result = radv_image_create(device_h,
- &(struct radv_image_create_info) {
- .vk_info =
- &(VkImageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = pCreateInfo->imageFormat,
- .extent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1
- },
- .mipLevels = 1,
- .arrayLayers = 1,
- .samples = 1,
- /* FIXME: Need a way to use X tiling to allow scanout */
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
- .flags = 0,
- },
- .scanout = true},
- NULL,
- &image_h);
- if (result != VK_SUCCESS)
- return result;
-
- image = radv_image_from_handle(image_h);
-
- VkDeviceMemory memory_h;
-
- const VkMemoryDedicatedAllocateInfoKHR ded_alloc = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
- .pNext = NULL,
- .buffer = VK_NULL_HANDLE,
- .image = image_h
- };
-
- /* Find the first VRAM memory type, or GART for PRIME images. */
- int memory_type_index = -1;
- for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) {
- bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- if (is_local) {
- memory_type_index = i;
- break;
- }
- }
-
- /* fallback */
- if (memory_type_index == -1)
- memory_type_index = 0;
-
- result = radv_alloc_memory(device_h,
- &(VkMemoryAllocateInfo) {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = &ded_alloc,
- .allocationSize = image->size,
- .memoryTypeIndex = memory_type_index,
- },
- NULL /* XXX: pAllocator */,
- RADV_MEM_IMPLICIT_SYNC,
- &memory_h);
- if (result != VK_SUCCESS)
- goto fail_create_image;
-
- radv_BindImageMemory(device_h, image_h, memory_h, 0);
-
- RADV_FROM_HANDLE(radv_device_memory, memory, memory_h);
- if (!radv_get_memory_fd(device, memory, &fd))
- goto fail_alloc_memory;
- wsi_image->fd = fd;
-
- surface = &image->surface;
-
- wsi_image->image = image_h;
- wsi_image->memory = memory_h;
- wsi_image->size = image->size;
- wsi_image->offset = image->offset;
- if (device->physical_device->rad_info.chip_class >= GFX9)
- wsi_image->row_pitch =
- surface->u.gfx9.surf_pitch * surface->bpe;
- else
- wsi_image->row_pitch =
- surface->u.legacy.level[0].nblk_x * surface->bpe;
-
- return VK_SUCCESS;
- fail_alloc_memory:
- radv_FreeMemory(device_h, memory_h, pAllocator);
-
-fail_create_image:
- radv_DestroyImage(device_h, image_h, pAllocator);
-
- return result;
-}
-
-static void
-radv_wsi_image_free(VkDevice device,
- const VkAllocationCallbacks* pAllocator,
- struct wsi_image *wsi_image)
-{
- radv_DestroyImage(device, wsi_image->image, pAllocator);
-
- radv_FreeMemory(device, wsi_image->memory, pAllocator);
-}
-
-static const struct wsi_image_fns radv_wsi_image_fns = {
- .create_wsi_image = radv_wsi_image_create,
- .free_wsi_image = radv_wsi_image_free,
-};
-
VkResult radv_CreateSwapchainKHR(
VkDevice _device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
&device->physical_device->wsi_device,
device->physical_device->local_fd,
pCreateInfo,
- alloc, &radv_wsi_image_fns,
+ alloc,
&swapchain);
if (result != VK_SUCCESS)
return result;
pPresentModes);
}
-
-static VkResult
-anv_wsi_image_create(VkDevice device_h,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- struct wsi_image *wsi_image)
-{
- struct anv_device *device = anv_device_from_handle(device_h);
- VkImage image_h;
- struct anv_image *image;
-
- VkResult result;
- result = anv_image_create(anv_device_to_handle(device),
- &(struct anv_image_create_info) {
- .isl_tiling_flags = ISL_TILING_X_BIT,
- .stride = 0,
- .vk_info =
- &(VkImageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = pCreateInfo->imageFormat,
- .extent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1
- },
- .mipLevels = 1,
- .arrayLayers = 1,
- .samples = 1,
- /* FIXME: Need a way to use X tiling to allow scanout */
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = (pCreateInfo->imageUsage |
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
- .flags = 0,
- }},
- NULL,
- &image_h);
- if (result != VK_SUCCESS)
- return result;
-
- image = anv_image_from_handle(image_h);
- assert(vk_format_is_color(image->vk_format));
-
- VkDeviceMemory memory_h;
- struct anv_device_memory *memory;
- result = anv_AllocateMemory(anv_device_to_handle(device),
- &(VkMemoryAllocateInfo) {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .allocationSize = image->size,
- .memoryTypeIndex = 0,
- },
- NULL /* XXX: pAllocator */,
- &memory_h);
- if (result != VK_SUCCESS)
- goto fail_create_image;
-
- memory = anv_device_memory_from_handle(memory_h);
-
- /* We need to set the WRITE flag on window system buffers so that GEM will
- * know we're writing to them and synchronize uses on other rings (eg if
- * the display server uses the blitter ring).
- */
- memory->bo->flags &= ~EXEC_OBJECT_ASYNC;
- memory->bo->flags |= EXEC_OBJECT_WRITE;
-
- anv_BindImageMemory(device_h, image_h, memory_h, 0);
- assert(image->planes[0].offset == 0);
-
- struct anv_surface *surface = &image->planes[0].surface;
- assert(surface->isl.tiling == ISL_TILING_X);
-
- int ret = anv_gem_set_tiling(device, memory->bo->gem_handle,
- surface->isl.row_pitch, I915_TILING_X);
- if (ret) {
- /* FINISHME: Choose a better error. */
- result = vk_errorf(device->instance, device,
- VK_ERROR_OUT_OF_DEVICE_MEMORY,
- "set_tiling failed: %m");
- goto fail_alloc_memory;
- }
-
- int fd = anv_gem_handle_to_fd(device, memory->bo->gem_handle);
- if (fd == -1) {
- /* FINISHME: Choose a better error. */
- result = vk_errorf(device->instance, device,
- VK_ERROR_OUT_OF_DEVICE_MEMORY,
- "handle_to_fd failed: %m");
- goto fail_alloc_memory;
- }
-
- wsi_image->image = image_h;
- wsi_image->memory = memory_h;
- wsi_image->fd = fd;
- wsi_image->size = image->size;
- wsi_image->offset = 0;
- wsi_image->row_pitch = surface->isl.row_pitch;
- return VK_SUCCESS;
-fail_alloc_memory:
- anv_FreeMemory(device_h, memory_h, pAllocator);
-
-fail_create_image:
- anv_DestroyImage(device_h, image_h, pAllocator);
- return result;
-}
-
-static void
-anv_wsi_image_free(VkDevice device,
- const VkAllocationCallbacks* pAllocator,
- struct wsi_image *wsi_image)
-{
- anv_DestroyImage(device, wsi_image->image, pAllocator);
-
- anv_FreeMemory(device, wsi_image->memory, pAllocator);
-}
-
-static const struct wsi_image_fns anv_wsi_image_fns = {
- .create_wsi_image = anv_wsi_image_create,
- .free_wsi_image = anv_wsi_image_free,
-};
-
VkResult anv_CreateSwapchainKHR(
VkDevice _device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
&device->instance->physicalDevice.wsi_device,
device->instance->physicalDevice.local_fd,
pCreateInfo,
- alloc, &anv_wsi_image_fns,
+ alloc,
&swapchain);
if (result != VK_SUCCESS)
return result;
WSI_GET_CB(FreeCommandBuffers);
WSI_GET_CB(GetBufferMemoryRequirements);
WSI_GET_CB(GetImageMemoryRequirements);
+ WSI_GET_CB(GetImageSubresourceLayout);
WSI_GET_CB(GetMemoryFdKHR);
WSI_GET_CB(QueueSubmit);
#undef WSI_GET_CB
return (v + a - 1) & ~(a - 1);
}
+VkResult
+wsi_create_native_image(const struct wsi_swapchain *chain,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ struct wsi_image *image)
+{
+ const struct wsi_device *wsi = chain->wsi;
+ VkResult result;
+
+ memset(image, 0, sizeof(*image));
+
+ const struct wsi_image_create_info image_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+ .pNext = NULL,
+ .scanout = true,
+ };
+ const VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .pNext = &image_wsi_info,
+ .flags = 0,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = pCreateInfo->imageFormat,
+ .extent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = pCreateInfo->imageUsage,
+ .sharingMode = pCreateInfo->imageSharingMode,
+ .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
+ .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
+ result = wsi->CreateImage(chain->device, &image_info,
+ &chain->alloc, &image->image);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ VkMemoryRequirements reqs;
+ wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+
+ VkSubresourceLayout image_layout;
+ const VkImageSubresource image_subresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .arrayLayer = 0,
+ };
+ wsi->GetImageSubresourceLayout(chain->device, image->image,
+ &image_subresource, &image_layout);
+
+ const struct wsi_memory_allocate_info memory_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
+ .pNext = NULL,
+ .implicit_sync = true,
+ };
+ const VkExportMemoryAllocateInfoKHR memory_export_info = {
+ .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
+ .pNext = &memory_wsi_info,
+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
+ .pNext = &memory_export_info,
+ .image = image->image,
+ .buffer = VK_NULL_HANDLE,
+ };
+ const VkMemoryAllocateInfo memory_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_dedicated_info,
+ .allocationSize = reqs.size,
+ .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ reqs.memoryTypeBits),
+ };
+ result = wsi->AllocateMemory(chain->device, &memory_info,
+ &chain->alloc, &image->memory);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ result = wsi->BindImageMemory(chain->device, image->image,
+ image->memory, 0);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const VkMemoryGetFdInfoKHR memory_get_fd_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+ .pNext = NULL,
+ .memory = image->memory,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ int fd;
+ result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ image->size = reqs.size;
+ image->row_pitch = image_layout.rowPitch;
+ image->offset = 0;
+ image->fd = fd;
+
+ return VK_SUCCESS;
+
+fail:
+ wsi_destroy_image(chain, image);
+
+ return result;
+}
+
#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
VkResult
return VK_SUCCESS;
fail:
- wsi_destroy_prime_image(chain, image);
+ wsi_destroy_image(chain, image);
return result;
}
void
-wsi_destroy_prime_image(const struct wsi_swapchain *chain,
- struct wsi_image *image)
+wsi_destroy_image(const struct wsi_swapchain *chain,
+ struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
bool implicit_sync;
};
-struct wsi_image {
- VkImage image;
- VkDeviceMemory memory;
-
- struct {
- VkBuffer buffer;
- VkDeviceMemory memory;
- VkCommandBuffer *blit_cmd_buffers;
- } prime;
-
- uint32_t size;
- uint32_t offset;
- uint32_t row_pitch;
- int fd;
-};
-
struct wsi_device;
-struct wsi_image_fns {
- VkResult (*create_wsi_image)(VkDevice device_h,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- struct wsi_image *image_p);
- void (*free_wsi_image)(VkDevice device,
- const VkAllocationCallbacks *pAllocator,
- struct wsi_image *image);
-};
struct wsi_swapchain {
const struct wsi_device *wsi;
VkDevice device;
VkAllocationCallbacks alloc;
- const struct wsi_image_fns *image_fns;
VkFence fences[3];
VkPresentModeKHR present_mode;
uint32_t image_count;
int local_fd,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- const struct wsi_image_fns *image_fns,
struct wsi_swapchain **swapchain);
};
WSI_CB(FreeCommandBuffers);
WSI_CB(GetBufferMemoryRequirements);
WSI_CB(GetImageMemoryRequirements);
+ WSI_CB(GetImageSubresourceLayout);
WSI_CB(GetMemoryFdKHR);
WSI_CB(QueueSubmit);
#undef WSI_CB
#include "wsi_common.h"
+struct wsi_image {
+ VkImage image;
+ VkDeviceMemory memory;
+
+ struct {
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ VkCommandBuffer *blit_cmd_buffers;
+ } prime;
+
+ uint32_t size;
+ uint32_t offset;
+ uint32_t row_pitch;
+ int fd;
+};
+
VkResult
wsi_swapchain_init(const struct wsi_device *wsi,
struct wsi_swapchain *chain,
void wsi_swapchain_finish(struct wsi_swapchain *chain);
+VkResult
+wsi_create_native_image(const struct wsi_swapchain *chain,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ struct wsi_image *image);
+
VkResult
wsi_create_prime_image(const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
struct wsi_image *image);
void
-wsi_destroy_prime_image(const struct wsi_swapchain *chain,
- struct wsi_image *image);
+wsi_destroy_image(const struct wsi_swapchain *chain,
+ struct wsi_image *image);
VkResult
wsi_prime_image_blit_to_linear(const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator)
{
- VkDevice vk_device = chain->base.device;
VkResult result;
- result = chain->base.image_fns->create_wsi_image(vk_device,
- pCreateInfo,
- pAllocator,
- &image->base);
+ result = wsi_create_native_image(&chain->base, pCreateInfo, &image->base);
if (result != VK_SUCCESS)
return result;
return VK_SUCCESS;
fail_image:
- chain->base.image_fns->free_wsi_image(vk_device, pAllocator, &image->base);
+ wsi_destroy_image(&chain->base, &image->base);
return result;
}
for (uint32_t i = 0; i < chain->base.image_count; i++) {
if (chain->images[i].buffer) {
wl_buffer_destroy(chain->images[i].buffer);
- chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
- &chain->images[i].base);
+ wsi_destroy_image(&chain->base, &chain->images[i].base);
}
}
int local_fd,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- const struct wsi_image_fns *image_fns,
struct wsi_swapchain **swapchain_out)
{
VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
chain->base.get_images = wsi_wl_swapchain_get_images;
chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image;
chain->base.queue_present = wsi_wl_swapchain_queue_present;
- chain->base.image_fns = image_fns;
chain->base.present_mode = pCreateInfo->presentMode;
chain->base.image_count = num_images;
chain->extent = pCreateInfo->imageExtent;
if (chain->use_prime_blit) {
result = wsi_create_prime_image(&chain->base, pCreateInfo, &image->base);
} else {
- result = chain->base.image_fns->create_wsi_image(device_h,
- pCreateInfo,
- pAllocator,
- &image->base);
+ result = wsi_create_native_image(&chain->base, pCreateInfo, &image->base);
}
if (result != VK_SUCCESS)
return result;
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
- if (chain->use_prime_blit) {
- wsi_destroy_prime_image(&chain->base, &image->base);
- } else {
- chain->base.image_fns->free_wsi_image(device_h, pAllocator, &image->base);
- }
+ wsi_destroy_image(&chain->base, &image->base);
return result;
}
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
- if (chain->use_prime_blit) {
- wsi_destroy_prime_image(&chain->base, &image->base);
- } else {
- chain->base.image_fns->free_wsi_image(chain->base.device,
- pAllocator, &image->base);
- }
+ wsi_destroy_image(&chain->base, &image->base);
}
static VkResult
int local_fd,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- const struct wsi_image_fns *image_fns,
struct wsi_swapchain **swapchain_out)
{
struct x11_swapchain *chain;
chain->base.get_images = x11_get_images;
chain->base.acquire_next_image = x11_acquire_next_image;
chain->base.queue_present = x11_queue_present;
- chain->base.image_fns = image_fns;
chain->base.present_mode = pCreateInfo->presentMode;
chain->base.image_count = num_images;
chain->conn = conn;