mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
vulkan: Synchronize in and out buffers
This commit is contained in:
parent
412b0c7b49
commit
b8c91f7e54
5 changed files with 212 additions and 31 deletions
|
|
@ -247,39 +247,23 @@ static int createCommandBuffer(struct vulkan_compute_state *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** runCommandBuffer
|
||||||
|
* The return value of this functions means the following:
|
||||||
|
* ret < 0: Error
|
||||||
|
* ret = 0: queueSubmit was succsessful, but manual synchronization is required
|
||||||
|
* ret = 1: queueSubmit was succsessful and buffers can be released without synchronization
|
||||||
|
*/
|
||||||
static int runCommandBuffer(struct vulkan_compute_state *s)
|
static int runCommandBuffer(struct vulkan_compute_state *s)
|
||||||
{
|
{
|
||||||
|
VULKAN_INSTANCE_FUNCTION(vkQueueSubmit2KHR);
|
||||||
|
VULKAN_INSTANCE_FUNCTION(vkGetSemaphoreFdKHR);
|
||||||
|
|
||||||
static const VkCommandBufferBeginInfo beginInfo = {
|
static const VkCommandBufferBeginInfo beginInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
};
|
};
|
||||||
VK_CHECK_RESULT(vkBeginCommandBuffer(s->commandBuffer, &beginInfo));
|
VK_CHECK_RESULT(vkBeginCommandBuffer(s->commandBuffer, &beginInfo));
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier[s->n_streams];
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < s->n_streams; i++) {
|
|
||||||
struct vulkan_stream *p = &s->streams[i];
|
|
||||||
|
|
||||||
barrier[i]= (VkImageMemoryBarrier) {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
||||||
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.subresourceRange.levelCount = 1,
|
|
||||||
.subresourceRange.layerCount = 1,
|
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcAccessMask = 0,
|
|
||||||
.dstAccessMask = 0,
|
|
||||||
.image = p->buffers[p->current_buffer_id].image,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(s->commandBuffer,
|
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
|
||||||
0, 0, NULL, 0, NULL,
|
|
||||||
s->n_streams, barrier);
|
|
||||||
|
|
||||||
vkCmdBindPipeline(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, s->pipeline);
|
vkCmdBindPipeline(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, s->pipeline);
|
||||||
vkCmdPushConstants (s->commandBuffer,
|
vkCmdPushConstants (s->commandBuffer,
|
||||||
s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT,
|
s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT,
|
||||||
|
|
@ -291,19 +275,135 @@ static int runCommandBuffer(struct vulkan_compute_state *s)
|
||||||
(uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE),
|
(uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE),
|
||||||
(uint32_t)ceil(s->constants.height / (float)WORKGROUP_SIZE), 1);
|
(uint32_t)ceil(s->constants.height / (float)WORKGROUP_SIZE), 1);
|
||||||
|
|
||||||
|
VkImageMemoryBarrier acquire_barrier[s->n_streams];
|
||||||
|
VkImageMemoryBarrier release_barrier[s->n_streams];
|
||||||
|
VkSemaphoreSubmitInfo semaphore_wait_info[s->n_streams];
|
||||||
|
uint32_t semaphore_wait_info_len = 0;
|
||||||
|
VkSemaphoreSubmitInfo semaphore_signal_info[1];
|
||||||
|
uint32_t semaphore_signal_info_len = 0;
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < s->n_streams; i++) {
|
||||||
|
struct vulkan_stream *p = &s->streams[i];
|
||||||
|
struct vulkan_buffer *current_buffer = &p->buffers[p->current_buffer_id];
|
||||||
|
|
||||||
|
VkAccessFlags access_flags;
|
||||||
|
if (p->direction == SPA_DIRECTION_INPUT) {
|
||||||
|
access_flags = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
} else {
|
||||||
|
access_flags = VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
acquire_barrier[i]= (VkImageMemoryBarrier) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
|
||||||
|
.dstQueueFamilyIndex = s->base.queueFamilyIndex,
|
||||||
|
.image = current_buffer->image,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcAccessMask = 0,
|
||||||
|
.dstAccessMask = access_flags,
|
||||||
|
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.subresourceRange.levelCount = 1,
|
||||||
|
.subresourceRange.layerCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
release_barrier[i]= (VkImageMemoryBarrier) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcQueueFamilyIndex = s->base.queueFamilyIndex,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
|
||||||
|
.image = current_buffer->image,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcAccessMask = access_flags,
|
||||||
|
.dstAccessMask = 0,
|
||||||
|
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.subresourceRange.levelCount = 1,
|
||||||
|
.subresourceRange.layerCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vulkan_sync_foreign_dmabuf(&s->base, current_buffer) < 0) {
|
||||||
|
spa_log_warn(s->log, "Failed to wait for foreign buffer DMA-BUF fence");
|
||||||
|
} else {
|
||||||
|
if (current_buffer->foreign_semaphore != VK_NULL_HANDLE) {
|
||||||
|
semaphore_wait_info[semaphore_wait_info_len++] = (VkSemaphoreSubmitInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
|
||||||
|
.semaphore = current_buffer->foreign_semaphore,
|
||||||
|
.stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(s->commandBuffer,
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
|
0, 0, NULL, 0, NULL,
|
||||||
|
s->n_streams, acquire_barrier);
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(s->commandBuffer,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||||
|
0, 0, NULL, 0, NULL,
|
||||||
|
s->n_streams, release_barrier);
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkEndCommandBuffer(s->commandBuffer));
|
VK_CHECK_RESULT(vkEndCommandBuffer(s->commandBuffer));
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkResetFences(s->base.device, 1, &s->fence));
|
VK_CHECK_RESULT(vkResetFences(s->base.device, 1, &s->fence));
|
||||||
|
|
||||||
const VkSubmitInfo submitInfo = {
|
if (s->pipelineSemaphore == VK_NULL_HANDLE) {
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
VkExportSemaphoreCreateInfo export_info = {
|
||||||
.commandBufferCount = 1,
|
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
|
||||||
.pCommandBuffers = &s->commandBuffer,
|
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||||
};
|
};
|
||||||
VK_CHECK_RESULT(vkQueueSubmit(s->base.queue, 1, &submitInfo, s->fence));
|
VkSemaphoreCreateInfo semaphore_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
|
.pNext = &export_info,
|
||||||
|
};
|
||||||
|
VK_CHECK_RESULT(vkCreateSemaphore(s->base.device, &semaphore_info, NULL, &s->pipelineSemaphore));
|
||||||
|
}
|
||||||
|
|
||||||
|
semaphore_signal_info[semaphore_signal_info_len++] = (VkSemaphoreSubmitInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
|
||||||
|
.semaphore = s->pipelineSemaphore,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkCommandBufferSubmitInfoKHR commandBufferInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
|
||||||
|
.commandBuffer = s->commandBuffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
const VkSubmitInfo2KHR submitInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR,
|
||||||
|
.commandBufferInfoCount = 1,
|
||||||
|
.pCommandBufferInfos = &commandBufferInfo,
|
||||||
|
.waitSemaphoreInfoCount = semaphore_wait_info_len,
|
||||||
|
.pWaitSemaphoreInfos = semaphore_wait_info,
|
||||||
|
.signalSemaphoreInfoCount = semaphore_signal_info_len,
|
||||||
|
.pSignalSemaphoreInfos = semaphore_signal_info,
|
||||||
|
};
|
||||||
|
VK_CHECK_RESULT(vkQueueSubmit2KHR(s->base.queue, 1, &submitInfo, s->fence));
|
||||||
s->started = true;
|
s->started = true;
|
||||||
|
|
||||||
return 0;
|
VkSemaphoreGetFdInfoKHR get_fence_fd_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
|
||||||
|
.semaphore = s->pipelineSemaphore,
|
||||||
|
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||||
|
};
|
||||||
|
int sync_file_fd = -1;
|
||||||
|
VK_CHECK_RESULT(vkGetSemaphoreFdKHR(s->base.device, &get_fence_fd_info, &sync_file_fd));
|
||||||
|
|
||||||
|
int ret = 1;
|
||||||
|
for (uint32_t i = 0; i < s->n_streams; i++) {
|
||||||
|
struct vulkan_stream *p = &s->streams[i];
|
||||||
|
|
||||||
|
if (!vulkan_sync_export_dmabuf(&s->base, &p->buffers[p->current_buffer_id], sync_file_fd)) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(sync_file_fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_buffers(struct vulkan_compute_state *s, struct vulkan_stream *p)
|
static void clear_buffers(struct vulkan_compute_state *s, struct vulkan_stream *p)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ struct vulkan_compute_state {
|
||||||
VkCommandBuffer commandBuffer;
|
VkCommandBuffer commandBuffer;
|
||||||
|
|
||||||
VkFence fence;
|
VkFence fence;
|
||||||
|
VkSemaphore pipelineSemaphore;
|
||||||
unsigned int initialized:1;
|
unsigned int initialized:1;
|
||||||
unsigned int prepared:1;
|
unsigned int prepared:1;
|
||||||
unsigned int started:1;
|
unsigned int started:1;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ struct vulkan_buffer {
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
|
VkSemaphore foreign_semaphore;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vulkan_stream {
|
struct vulkan_stream {
|
||||||
|
|
@ -67,5 +68,7 @@ struct vulkan_base {
|
||||||
uint32_t formatInfoCount;
|
uint32_t formatInfoCount;
|
||||||
struct vulkan_format_info *formatInfos;
|
struct vulkan_format_info *formatInfos;
|
||||||
|
|
||||||
|
bool implicit_sync_interop;
|
||||||
|
|
||||||
unsigned int initialized:1;
|
unsigned int initialized:1;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <poll.h>
|
||||||
#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
|
#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
#include <spa/debug/mem.h>
|
#include <spa/debug/mem.h>
|
||||||
|
|
||||||
#include "vulkan-utils.h"
|
#include "vulkan-utils.h"
|
||||||
|
#include "dmabuf.h"
|
||||||
|
|
||||||
//#define ENABLE_VALIDATION
|
//#define ENABLE_VALIDATION
|
||||||
|
|
||||||
|
|
@ -201,10 +203,16 @@ static int createDevice(struct vulkan_base *s, struct vulkan_base_info *info)
|
||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = (const float[]) { 1.0f }
|
.pQueuePriorities = (const float[]) { 1.0f }
|
||||||
};
|
};
|
||||||
|
const VkPhysicalDeviceSynchronization2FeaturesKHR sync2_features = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR,
|
||||||
|
.synchronization2 = VK_TRUE,
|
||||||
|
};
|
||||||
static const char * const extensions[] = {
|
static const char * const extensions[] = {
|
||||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||||
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
|
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
|
||||||
|
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
|
||||||
|
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
|
||||||
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME
|
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME
|
||||||
};
|
};
|
||||||
const VkDeviceCreateInfo deviceCreateInfo = {
|
const VkDeviceCreateInfo deviceCreateInfo = {
|
||||||
|
|
@ -213,6 +221,7 @@ static int createDevice(struct vulkan_base *s, struct vulkan_base_info *info)
|
||||||
.pQueueCreateInfos = &queueCreateInfo,
|
.pQueueCreateInfos = &queueCreateInfo,
|
||||||
.enabledExtensionCount = SPA_N_ELEMENTS(extensions),
|
.enabledExtensionCount = SPA_N_ELEMENTS(extensions),
|
||||||
.ppEnabledExtensionNames = extensions,
|
.ppEnabledExtensionNames = extensions,
|
||||||
|
.pNext = &sync2_features,
|
||||||
};
|
};
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateDevice(s->physicalDevice, &deviceCreateInfo, NULL, &s->device));
|
VK_CHECK_RESULT(vkCreateDevice(s->physicalDevice, &deviceCreateInfo, NULL, &s->device));
|
||||||
|
|
@ -329,6 +338,60 @@ static void destroyFormatInfo(struct vulkan_base *s)
|
||||||
s->formatInfoCount = 0;
|
s->formatInfoCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vulkan_sync_foreign_dmabuf(struct vulkan_base *s, struct vulkan_buffer *vk_buf)
|
||||||
|
{
|
||||||
|
VULKAN_INSTANCE_FUNCTION(vkImportSemaphoreFdKHR);
|
||||||
|
|
||||||
|
if (!s->implicit_sync_interop) {
|
||||||
|
struct pollfd pollfd = {
|
||||||
|
.fd = vk_buf->fd,
|
||||||
|
.events = POLLIN,
|
||||||
|
};
|
||||||
|
int timeout_ms = 1000;
|
||||||
|
int ret = poll(&pollfd, 1, timeout_ms);
|
||||||
|
if (ret < 0) {
|
||||||
|
spa_log_error(s->log, "Failed to wait for DMA-BUF fence");
|
||||||
|
return -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
spa_log_error(s->log, "Timed out waiting for DMA-BUF fence");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync_file_fd = dmabuf_export_sync_file(s->log, vk_buf->fd, DMA_BUF_SYNC_READ);
|
||||||
|
if (sync_file_fd < 0) {
|
||||||
|
spa_log_error(s->log, "Failed to extract for DMA-BUF fence");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk_buf->foreign_semaphore == VK_NULL_HANDLE) {
|
||||||
|
VkSemaphoreCreateInfo semaphore_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
|
};
|
||||||
|
VK_CHECK_RESULT_WITH_CLEANUP(vkCreateSemaphore(s->device, &semaphore_info, NULL, &vk_buf->foreign_semaphore), close(sync_file_fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImportSemaphoreFdInfoKHR import_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
|
||||||
|
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||||
|
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR,
|
||||||
|
.semaphore = vk_buf->foreign_semaphore,
|
||||||
|
.fd = sync_file_fd,
|
||||||
|
};
|
||||||
|
VK_CHECK_RESULT_WITH_CLEANUP(vkImportSemaphoreFdKHR(s->device, &import_info), close(sync_file_fd));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vulkan_sync_export_dmabuf(struct vulkan_base *s, struct vulkan_buffer *vk_buf, int sync_file_fd)
|
||||||
|
{
|
||||||
|
if (!s->implicit_sync_interop)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return dmabuf_import_sync_file(s->log, vk_buf->fd, DMA_BUF_SYNC_WRITE, sync_file_fd);
|
||||||
|
}
|
||||||
|
|
||||||
int vulkan_commandPool_create(struct vulkan_base *s, VkCommandPool *commandPool)
|
int vulkan_commandPool_create(struct vulkan_base *s, VkCommandPool *commandPool)
|
||||||
{
|
{
|
||||||
const VkCommandPoolCreateInfo commandPoolCreateInfo = {
|
const VkCommandPoolCreateInfo commandPoolCreateInfo = {
|
||||||
|
|
@ -720,6 +783,7 @@ int vulkan_base_init(struct vulkan_base *s, struct vulkan_base_info *info)
|
||||||
CHECK(findPhysicalDevice(s));
|
CHECK(findPhysicalDevice(s));
|
||||||
CHECK(createDevice(s, info));
|
CHECK(createDevice(s, info));
|
||||||
CHECK(queryFormatInfo(s, info));
|
CHECK(queryFormatInfo(s, info));
|
||||||
|
s->implicit_sync_interop = dmabuf_check_sync_file_import_export(s->log);
|
||||||
s->initialized = true;
|
s->initialized = true;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,16 @@
|
||||||
return _r; \
|
return _r; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
#define VK_CHECK_RESULT_WITH_CLEANUP(f, c) \
|
||||||
|
{ \
|
||||||
|
VkResult _result = (f); \
|
||||||
|
int _r = -vkresult_to_errno(_result); \
|
||||||
|
if (_result != VK_SUCCESS) { \
|
||||||
|
spa_log_error(s->log, "error: %d (%d %s)", _result, _r, spa_strerror(_r)); \
|
||||||
|
(c); \
|
||||||
|
return _r; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
#define VK_CHECK_RESULT_LOOP(f) \
|
#define VK_CHECK_RESULT_LOOP(f) \
|
||||||
{ \
|
{ \
|
||||||
VkResult _result = (f); \
|
VkResult _result = (f); \
|
||||||
|
|
@ -52,6 +62,9 @@ struct external_dmabuf_info {
|
||||||
struct spa_buffer *spa_buf;
|
struct spa_buffer *spa_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int vulkan_sync_foreign_dmabuf(struct vulkan_base *s, struct vulkan_buffer *vk_buf);
|
||||||
|
bool vulkan_sync_export_dmabuf(struct vulkan_base *s, struct vulkan_buffer *vk_buf, int sync_file_fd);
|
||||||
|
|
||||||
int vulkan_fixate_modifier(struct vulkan_base *s, struct dmabuf_fixation_info *info, uint64_t *modifier);
|
int vulkan_fixate_modifier(struct vulkan_base *s, struct dmabuf_fixation_info *info, uint64_t *modifier);
|
||||||
int vulkan_create_dmabuf(struct vulkan_base *s, struct external_dmabuf_info *info, struct vulkan_buffer *vk_buf);
|
int vulkan_create_dmabuf(struct vulkan_base *s, struct external_dmabuf_info *info, struct vulkan_buffer *vk_buf);
|
||||||
int vulkan_import_dmabuf(struct vulkan_base *s, struct external_dmabuf_info *info, struct vulkan_buffer *vk_buf);
|
int vulkan_import_dmabuf(struct vulkan_base *s, struct external_dmabuf_info *info, struct vulkan_buffer *vk_buf);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue