vulkan: only send out buffers when ready

Keep track of the buffer that is rendering and when it finishes,
move it to the ready queue.
This commit is contained in:
Wim Taymans 2019-08-19 18:16:32 +02:00
parent 38169ec5db
commit 4f31ca5383
3 changed files with 136 additions and 110 deletions

View file

@ -287,20 +287,28 @@ static int make_buffer(struct impl *this)
spa_vulkan_process(&this->state, b->id); spa_vulkan_process(&this->state, b->id);
b->outbuf->datas[0].chunk->offset = 0; if (this->state.ready_buffer_id != SPA_ID_INVALID) {
b->outbuf->datas[0].chunk->size = n_bytes; struct buffer *b = &port->buffers[this->state.ready_buffer_id];
b->outbuf->datas[0].chunk->stride = port->stride;
if (b->h) { this->state.ready_buffer_id = SPA_ID_INVALID;
b->h->seq = this->frame_count;
b->h->pts = this->start_time + this->elapsed_time; spa_log_trace(this->log, NAME " %p: ready buffer %d", this, b->id);
b->h->dts_offset = 0;
b->outbuf->datas[0].chunk->offset = 0;
b->outbuf->datas[0].chunk->size = n_bytes;
b->outbuf->datas[0].chunk->stride = port->stride;
if (b->h) {
b->h->seq = this->frame_count;
b->h->pts = this->start_time + this->elapsed_time;
b->h->dts_offset = 0;
}
SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT);
spa_list_append(&port->ready, &b->link);
res = SPA_STATUS_HAVE_BUFFER;
} }
SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT);
spa_list_append(&port->ready, &b->link);
res = SPA_STATUS_HAVE_BUFFER;
next: next:
this->frame_count++; this->frame_count++;
this->elapsed_time = FRAMES_TO_TIME(port, this->frame_count); this->elapsed_time = FRAMES_TO_TIME(port, this->frame_count);
@ -926,6 +934,8 @@ impl_init(const struct spa_handle_factory *factory,
spa_list_init(&port->empty); spa_list_init(&port->empty);
spa_list_init(&port->ready); spa_list_init(&port->ready);
this->state.log = this->log;
spa_log_info(this->log, NAME " %p: initialized", this); spa_log_info(this->log, NAME " %p: initialized", this);
return 0; return 0;

View file

@ -13,6 +13,8 @@
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <spa/utils/result.h>
#include <spa/support/log.h>
#include <spa/debug/mem.h> #include <spa/debug/mem.h>
#include "vulkan-utils.h" #include "vulkan-utils.h"
@ -72,18 +74,17 @@ static int vkresult_to_errno(VkResult result)
} }
} }
// Used for validating return values of Vulkan API calls.
#define VK_CHECK_RESULT(f) \ #define VK_CHECK_RESULT(f) \
{ \ { \
VkResult res = (f); \ VkResult result = (f); \
if (res != VK_SUCCESS) \ int res = -vkresult_to_errno(result); \
{ \ if (result != VK_SUCCESS) { \
printf("Fatal : VkResult is %d in %s at line %d\n", res, __FILE__, __LINE__); \ spa_log_debug(s->log, "error: %d (%s)", result, spa_strerror(res)); \
return -vkresult_to_errno(res); \ return res; \
} \ } \
} }
static int createInstance(struct vulkan_state *d) static int createInstance(struct vulkan_state *s)
{ {
const VkApplicationInfo applicationInfo = { const VkApplicationInfo applicationInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@ -103,20 +104,20 @@ static int createInstance(struct vulkan_state *d)
.ppEnabledExtensionNames = extensions, .ppEnabledExtensionNames = extensions,
}; };
VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &d->instance)); VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &s->instance));
return 0; return 0;
} }
static uint32_t getComputeQueueFamilyIndex(struct vulkan_state *d) static uint32_t getComputeQueueFamilyIndex(struct vulkan_state *s)
{ {
uint32_t i, queueFamilyCount; uint32_t i, queueFamilyCount;
VkQueueFamilyProperties *queueFamilies; VkQueueFamilyProperties *queueFamilies;
vkGetPhysicalDeviceQueueFamilyProperties(d->physicalDevice, &queueFamilyCount, NULL); vkGetPhysicalDeviceQueueFamilyProperties(s->physicalDevice, &queueFamilyCount, NULL);
queueFamilies = alloca(queueFamilyCount * sizeof(VkQueueFamilyProperties)); queueFamilies = alloca(queueFamilyCount * sizeof(VkQueueFamilyProperties));
vkGetPhysicalDeviceQueueFamilyProperties(d->physicalDevice, &queueFamilyCount, queueFamilies); vkGetPhysicalDeviceQueueFamilyProperties(s->physicalDevice, &queueFamilyCount, queueFamilies);
for (i = 0; i < queueFamilyCount; i++) { for (i = 0; i < queueFamilyCount; i++) {
VkQueueFamilyProperties props = queueFamilies[i]; VkQueueFamilyProperties props = queueFamilies[i];
@ -130,30 +131,30 @@ static uint32_t getComputeQueueFamilyIndex(struct vulkan_state *d)
return i; return i;
} }
static int findPhysicalDevice(struct vulkan_state *d) static int findPhysicalDevice(struct vulkan_state *s)
{ {
uint32_t deviceCount; uint32_t deviceCount;
VkPhysicalDevice *devices; VkPhysicalDevice *devices;
vkEnumeratePhysicalDevices(d->instance, &deviceCount, NULL); vkEnumeratePhysicalDevices(s->instance, &deviceCount, NULL);
if (deviceCount == 0) if (deviceCount == 0)
return -ENODEV; return -ENODEV;
devices = alloca(deviceCount * sizeof(VkPhysicalDevice)); devices = alloca(deviceCount * sizeof(VkPhysicalDevice));
vkEnumeratePhysicalDevices(d->instance, &deviceCount, devices); vkEnumeratePhysicalDevices(s->instance, &deviceCount, devices);
d->physicalDevice = devices[0]; s->physicalDevice = devices[0];
d->queueFamilyIndex = getComputeQueueFamilyIndex(d); s->queueFamilyIndex = getComputeQueueFamilyIndex(s);
return 0; return 0;
} }
static int createDevice(struct vulkan_state *d) static int createDevice(struct vulkan_state *s)
{ {
VkDeviceQueueCreateInfo queueCreateInfo = { VkDeviceQueueCreateInfo queueCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = d->queueFamilyIndex, .queueFamilyIndex = s->queueFamilyIndex,
.queueCount = 1, .queueCount = 1,
.pQueuePriorities = (const float[]) { 1.0f } .pQueuePriorities = (const float[]) { 1.0f }
}; };
@ -169,26 +170,26 @@ static int createDevice(struct vulkan_state *d)
.ppEnabledExtensionNames = extensions, .ppEnabledExtensionNames = extensions,
}; };
VK_CHECK_RESULT(vkCreateDevice(d->physicalDevice, &deviceCreateInfo, NULL, &d->device)); VK_CHECK_RESULT(vkCreateDevice(s->physicalDevice, &deviceCreateInfo, NULL, &s->device));
vkGetDeviceQueue(d->device, d->queueFamilyIndex, 0, &d->queue); vkGetDeviceQueue(s->device, s->queueFamilyIndex, 0, &s->queue);
VkFenceCreateInfo fenceCreateInfo = { VkFenceCreateInfo fenceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = 0, .flags = 0,
}; };
VK_CHECK_RESULT(vkCreateFence(d->device, &fenceCreateInfo, NULL, &d->fence)); VK_CHECK_RESULT(vkCreateFence(s->device, &fenceCreateInfo, NULL, &s->fence));
return 0; return 0;
} }
static uint32_t findMemoryType(struct vulkan_state *d, static uint32_t findMemoryType(struct vulkan_state *s,
uint32_t memoryTypeBits, VkMemoryPropertyFlags properties) uint32_t memoryTypeBits, VkMemoryPropertyFlags properties)
{ {
uint32_t i; uint32_t i;
VkPhysicalDeviceMemoryProperties memoryProperties; VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(d->physicalDevice, &memoryProperties); vkGetPhysicalDeviceMemoryProperties(s->physicalDevice, &memoryProperties);
for (i = 0; i < memoryProperties.memoryTypeCount; i++) { for (i = 0; i < memoryProperties.memoryTypeCount; i++) {
if ((memoryTypeBits & (1 << i)) && if ((memoryTypeBits & (1 << i)) &&
@ -198,7 +199,7 @@ static uint32_t findMemoryType(struct vulkan_state *d,
return -1; return -1;
} }
static int createDescriptors(struct vulkan_state *d) static int createDescriptors(struct vulkan_state *s)
{ {
VkDescriptorPoolSize descriptorPoolSize = { VkDescriptorPoolSize descriptorPoolSize = {
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
@ -211,9 +212,9 @@ static int createDescriptors(struct vulkan_state *d)
.pPoolSizes = &descriptorPoolSize, .pPoolSizes = &descriptorPoolSize,
}; };
VK_CHECK_RESULT(vkCreateDescriptorPool(d->device, VK_CHECK_RESULT(vkCreateDescriptorPool(s->device,
&descriptorPoolCreateInfo, NULL, &descriptorPoolCreateInfo, NULL,
&d->descriptorPool)); &s->descriptorPool));
VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = { VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
.binding = 0, .binding = 0,
@ -226,87 +227,90 @@ static int createDescriptors(struct vulkan_state *d)
.bindingCount = 1, .bindingCount = 1,
.pBindings = &descriptorSetLayoutBinding .pBindings = &descriptorSetLayoutBinding
}; };
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(d->device, VK_CHECK_RESULT(vkCreateDescriptorSetLayout(s->device,
&descriptorSetLayoutCreateInfo, NULL, &descriptorSetLayoutCreateInfo, NULL,
&d->descriptorSetLayout)); &s->descriptorSetLayout));
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = d->descriptorPool, .descriptorPool = s->descriptorPool,
.descriptorSetCount = 1, .descriptorSetCount = 1,
.pSetLayouts = &d->descriptorSetLayout .pSetLayouts = &s->descriptorSetLayout
}; };
VK_CHECK_RESULT(vkAllocateDescriptorSets(d->device, VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device,
&descriptorSetAllocateInfo, &descriptorSetAllocateInfo,
&d->descriptorSet)); &s->descriptorSet));
return 0; return 0;
} }
static int createBuffer(struct vulkan_state *d, uint32_t id) static int createBuffer(struct vulkan_state *s, uint32_t id)
{ {
VkBufferCreateInfo bufferCreateInfo = { VkBufferCreateInfo bufferCreateInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = d->bufferSize, .size = s->bufferSize,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
}; };
VkMemoryRequirements memoryRequirements; VkMemoryRequirements memoryRequirements;
VK_CHECK_RESULT(vkCreateBuffer(d->device, VK_CHECK_RESULT(vkCreateBuffer(s->device,
&bufferCreateInfo, NULL, &d->buffers[id].buffer)); &bufferCreateInfo, NULL, &s->buffers[id].buffer));
vkGetBufferMemoryRequirements(d->device, vkGetBufferMemoryRequirements(s->device,
d->buffers[id].buffer, &memoryRequirements); s->buffers[id].buffer, &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = { VkMemoryAllocateInfo allocateInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memoryRequirements.size .allocationSize = memoryRequirements.size
}; };
allocateInfo.memoryTypeIndex = findMemoryType(d, allocateInfo.memoryTypeIndex = findMemoryType(s,
memoryRequirements.memoryTypeBits, memoryRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VK_CHECK_RESULT(vkAllocateMemory(d->device, VK_CHECK_RESULT(vkAllocateMemory(s->device,
&allocateInfo, NULL, &d->buffers[id].memory)); &allocateInfo, NULL, &s->buffers[id].memory));
VK_CHECK_RESULT(vkBindBufferMemory(d->device, VK_CHECK_RESULT(vkBindBufferMemory(s->device,
d->buffers[id].buffer, d->buffers[id].memory, 0)); s->buffers[id].buffer, s->buffers[id].memory, 0));
return 0; return 0;
} }
static int updateDescriptors(struct vulkan_state *d, uint32_t buffer_id) static int updateDescriptors(struct vulkan_state *s, uint32_t buffer_id)
{ {
if (s->current_buffer_id == buffer_id)
return 0;
VkDescriptorBufferInfo descriptorBufferInfo = { VkDescriptorBufferInfo descriptorBufferInfo = {
.buffer = d->buffers[buffer_id].buffer, .buffer = s->buffers[buffer_id].buffer,
.offset = 0, .offset = 0,
.range = d->bufferSize, .range = s->bufferSize,
}; };
VkWriteDescriptorSet writeDescriptorSet = { VkWriteDescriptorSet writeDescriptorSet = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = d->descriptorSet, .dstSet = s->descriptorSet,
.dstBinding = 0, .dstBinding = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &descriptorBufferInfo, .pBufferInfo = &descriptorBufferInfo,
}; };
vkUpdateDescriptorSets(d->device, 1, &writeDescriptorSet, 0, NULL); vkUpdateDescriptorSets(s->device, 1, &writeDescriptorSet, 0, NULL);
s->current_buffer_id = buffer_id;
d->buffer_id = buffer_id;
return 0; return 0;
} }
static VkShaderModule createShaderModule(struct vulkan_state *d, const char* shaderFile) static VkShaderModule createShaderModule(struct vulkan_state *s, const char* shaderFile)
{ {
VkShaderModule shaderModule = VK_NULL_HANDLE; VkShaderModule shaderModule = VK_NULL_HANDLE;
VkResult result;
void *data; void *data;
int fd; int fd;
struct stat stat; struct stat stat;
if ((fd = open(shaderFile, 0, O_RDONLY)) == -1) { if ((fd = open(shaderFile, 0, O_RDONLY)) == -1) {
fprintf(stderr, "can't open %s: %m\n", shaderFile); spa_log_error(s->log, "can't open %s: %m", shaderFile);
return NULL; return NULL;
} }
fstat(fd, &stat); fstat(fd, &stat);
@ -318,15 +322,20 @@ static VkShaderModule createShaderModule(struct vulkan_state *d, const char* sha
.codeSize = stat.st_size, .codeSize = stat.st_size,
.pCode = data, .pCode = data,
}; };
vkCreateShaderModule(d->device, &shaderModuleCreateInfo, 0, &shaderModule); result = vkCreateShaderModule(s->device,
&shaderModuleCreateInfo, 0, &shaderModule);
munmap(data, stat.st_size); munmap(data, stat.st_size);
close(fd); close(fd);
if (result != VK_SUCCESS) {
spa_log_error(s->log, "can't create shader %s: %m", shaderFile);
return NULL;
}
return shaderModule; return shaderModule;
} }
static int createComputePipeline(struct vulkan_state *d, const char *shader_file) static int createComputePipeline(struct vulkan_state *s, const char *shader_file)
{ {
const VkPushConstantRange range = { const VkPushConstantRange range = {
.stageFlags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, .stageFlags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
@ -337,86 +346,89 @@ static int createComputePipeline(struct vulkan_state *d, const char *shader_file
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1, .setLayoutCount = 1,
.pSetLayouts = &d->descriptorSetLayout, .pSetLayouts = &s->descriptorSetLayout,
.pushConstantRangeCount = 1, .pushConstantRangeCount = 1,
.pPushConstantRanges = &range, .pPushConstantRanges = &range,
}; };
VK_CHECK_RESULT(vkCreatePipelineLayout(d->device, VK_CHECK_RESULT(vkCreatePipelineLayout(s->device,
&pipelineLayoutCreateInfo, NULL, &pipelineLayoutCreateInfo, NULL,
&d->pipelineLayout)); &s->pipelineLayout));
s->computeShaderModule = createShaderModule(s, shader_file);
if (s->computeShaderModule == NULL)
return -ENOENT;
d->computeShaderModule = createShaderModule(d, shader_file);
VkPipelineShaderStageCreateInfo shaderStageCreateInfo = { VkPipelineShaderStageCreateInfo shaderStageCreateInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_COMPUTE_BIT, .stage = VK_SHADER_STAGE_COMPUTE_BIT,
.module = d->computeShaderModule, .module = s->computeShaderModule,
.pName = "main", .pName = "main",
}; };
VkComputePipelineCreateInfo pipelineCreateInfo = { VkComputePipelineCreateInfo pipelineCreateInfo = {
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.stage = shaderStageCreateInfo, .stage = shaderStageCreateInfo,
.layout = d->pipelineLayout, .layout = s->pipelineLayout,
}; };
VK_CHECK_RESULT(vkCreateComputePipelines(d->device, VK_NULL_HANDLE, VK_CHECK_RESULT(vkCreateComputePipelines(s->device, VK_NULL_HANDLE,
1, &pipelineCreateInfo, NULL, 1, &pipelineCreateInfo, NULL,
&d->pipeline)); &s->pipeline));
return 0; return 0;
} }
static int createCommandBuffer(struct vulkan_state *d) static int createCommandBuffer(struct vulkan_state *s)
{ {
VkCommandPoolCreateInfo commandPoolCreateInfo = { VkCommandPoolCreateInfo commandPoolCreateInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = d->queueFamilyIndex, .queueFamilyIndex = s->queueFamilyIndex,
}; };
VK_CHECK_RESULT(vkCreateCommandPool(d->device, VK_CHECK_RESULT(vkCreateCommandPool(s->device,
&commandPoolCreateInfo, NULL, &commandPoolCreateInfo, NULL,
&d->commandPool)); &s->commandPool));
VkCommandBufferAllocateInfo commandBufferAllocateInfo = { VkCommandBufferAllocateInfo commandBufferAllocateInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = d->commandPool, .commandPool = s->commandPool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1, .commandBufferCount = 1,
}; };
VK_CHECK_RESULT(vkAllocateCommandBuffers(d->device, VK_CHECK_RESULT(vkAllocateCommandBuffers(s->device,
&commandBufferAllocateInfo, &commandBufferAllocateInfo,
&d->commandBuffer)); &s->commandBuffer));
return 0; return 0;
} }
static int runCommandBuffer(struct vulkan_state *d) static int runCommandBuffer(struct vulkan_state *s)
{ {
VkCommandBufferBeginInfo beginInfo = { 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(d->commandBuffer, &beginInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(s->commandBuffer, &beginInfo));
vkCmdBindPipeline(d->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, d->pipeline); vkCmdBindPipeline(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, s->pipeline);
vkCmdPushConstants (d->commandBuffer, vkCmdPushConstants (s->commandBuffer,
d->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(struct push_constants), (const void *) &d->constants); 0, sizeof(struct push_constants), (const void *) &s->constants);
vkCmdBindDescriptorSets(d->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, vkCmdBindDescriptorSets(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
d->pipelineLayout, 0, 1, &d->descriptorSet, 0, NULL); s->pipelineLayout, 0, 1, &s->descriptorSet, 0, NULL);
vkCmdDispatch(d->commandBuffer, vkCmdDispatch(s->commandBuffer,
(uint32_t)ceil(d->constants.width / (float)WORKGROUP_SIZE), (uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE),
(uint32_t)ceil(d->constants.height / (float)WORKGROUP_SIZE), 1); (uint32_t)ceil(s->constants.height / (float)WORKGROUP_SIZE), 1);
VK_CHECK_RESULT(vkEndCommandBuffer(d->commandBuffer)); VK_CHECK_RESULT(vkEndCommandBuffer(s->commandBuffer));
VK_CHECK_RESULT(vkResetFences(d->device, 1, &d->fence)); VK_CHECK_RESULT(vkResetFences(s->device, 1, &s->fence));
VkSubmitInfo submitInfo = { VkSubmitInfo submitInfo = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1, .commandBufferCount = 1,
.pCommandBuffers = &d->commandBuffer, .pCommandBuffers = &s->commandBuffer,
}; };
VK_CHECK_RESULT(vkQueueSubmit(d->queue, 1, &submitInfo, d->fence)); VK_CHECK_RESULT(vkQueueSubmit(s->queue, 1, &submitInfo, s->fence));
d->busy = true; s->busy_buffer_id = s->current_buffer_id;
return 0; return 0;
} }
@ -500,7 +512,9 @@ int spa_vulkan_unprepare(struct vulkan_state *s)
int spa_vulkan_start(struct vulkan_state *s) int spa_vulkan_start(struct vulkan_state *s)
{ {
s->busy = false; s->current_buffer_id = SPA_ID_INVALID;
s->busy_buffer_id = SPA_ID_INVALID;
s->ready_buffer_id = SPA_ID_INVALID;
return 0; return 0;
} }
@ -514,24 +528,23 @@ int spa_vulkan_ready(struct vulkan_state *s)
{ {
VkResult result; VkResult result;
if (!s->busy) if (s->busy_buffer_id == SPA_ID_INVALID)
return 0; return 0;
result = vkGetFenceStatus(s->device, s->fence); result = vkGetFenceStatus(s->device, s->fence);
if (result != VK_SUCCESS) if (result == VK_NOT_READY)
return -vkresult_to_errno(result); return -EBUSY;
VK_CHECK_RESULT(result);
s->busy = false; s->ready_buffer_id = s->busy_buffer_id;
s->busy_buffer_id = SPA_ID_INVALID;
return 0; return 0;
} }
int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id) int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id)
{ {
if (buffer_id != s->buffer_id) { updateDescriptors(s, buffer_id);
updateDescriptors(s, buffer_id);
s->buffer_id = buffer_id;
}
runCommandBuffer(s); runCommandBuffer(s);
return 0; return 0;

View file

@ -23,6 +23,8 @@ struct vulkan_buffer {
}; };
struct vulkan_state { struct vulkan_state {
struct spa_log *log;
struct push_constants constants; struct push_constants constants;
VkInstance instance; VkInstance instance;
@ -41,17 +43,18 @@ struct vulkan_state {
uint32_t queueFamilyIndex; uint32_t queueFamilyIndex;
VkFence fence; VkFence fence;
unsigned int prepared:1; unsigned int prepared:1;
unsigned int busy:1; uint32_t busy_buffer_id;
uint32_t ready_buffer_id;
VkDescriptorPool descriptorPool; VkDescriptorPool descriptorPool;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout descriptorSetLayout;
uint32_t current_buffer_id;
uint32_t bufferSize;
struct vulkan_buffer buffers[MAX_BUFFERS]; struct vulkan_buffer buffers[MAX_BUFFERS];
uint32_t n_buffers; uint32_t n_buffers;
uint32_t bufferSize;
uint32_t buffer_id;
}; };
int spa_vulkan_prepare(struct vulkan_state *s); int spa_vulkan_prepare(struct vulkan_state *s);