mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	vulkan: support multiple streams of buffers
This commit is contained in:
		
							parent
							
								
									332e8b7029
								
							
						
					
					
						commit
						e6f01563ab
					
				
					 4 changed files with 214 additions and 137 deletions
				
			
		| 
						 | 
					@ -47,8 +47,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NAME "vulkan-compute-filter"
 | 
					#define NAME "vulkan-compute-filter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_PORTS 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct buffer {
 | 
					struct buffer {
 | 
				
			||||||
	uint32_t id;
 | 
						uint32_t id;
 | 
				
			||||||
#define BUFFER_FLAG_OUT (1<<0)
 | 
					#define BUFFER_FLAG_OUT (1<<0)
 | 
				
			||||||
| 
						 | 
					@ -75,6 +73,7 @@ struct port {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_list empty;
 | 
						struct spa_list empty;
 | 
				
			||||||
	struct spa_list ready;
 | 
						struct spa_list ready;
 | 
				
			||||||
 | 
						uint32_t stream_id;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
| 
						 | 
					@ -103,7 +102,7 @@ struct impl {
 | 
				
			||||||
	struct port port[2];
 | 
						struct port port[2];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_PORT(this,d,p)  ((p) < MAX_PORTS)
 | 
					#define CHECK_PORT(this,d,p)  ((p) < 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int impl_node_enum_params(void *object, int seq,
 | 
					static int impl_node_enum_params(void *object, int seq,
 | 
				
			||||||
				 uint32_t id, uint32_t start, uint32_t num,
 | 
									 uint32_t id, uint32_t start, uint32_t num,
 | 
				
			||||||
| 
						 | 
					@ -416,7 +415,7 @@ static int clear_buffers(struct impl *this, struct port *port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (port->n_buffers > 0) {
 | 
						if (port->n_buffers > 0) {
 | 
				
			||||||
		spa_log_debug(this->log, NAME " %p: clear buffers", this);
 | 
							spa_log_debug(this->log, NAME " %p: clear buffers", this);
 | 
				
			||||||
		spa_vulkan_use_buffers(&this->state, 0, 0, NULL);
 | 
							spa_vulkan_use_buffers(&this->state, &this->state.streams[port->stream_id], 0, 0, NULL);
 | 
				
			||||||
		port->n_buffers = 0;
 | 
							port->n_buffers = 0;
 | 
				
			||||||
		spa_list_init(&port->empty);
 | 
							spa_list_init(&port->empty);
 | 
				
			||||||
		spa_list_init(&port->ready);
 | 
							spa_list_init(&port->ready);
 | 
				
			||||||
| 
						 | 
					@ -528,7 +527,7 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spa_list_append(&port->empty, &b->link);
 | 
							spa_list_append(&port->empty, &b->link);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spa_vulkan_use_buffers(&this->state, flags, n_buffers, buffers);
 | 
						spa_vulkan_use_buffers(&this->state, &this->state.streams[port->stream_id], flags, n_buffers, buffers);
 | 
				
			||||||
	port->n_buffers = n_buffers;
 | 
						port->n_buffers = n_buffers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -693,24 +692,8 @@ impl_init(const struct spa_handle_factory *factory,
 | 
				
			||||||
	this->info.params = this->params;
 | 
						this->info.params = this->params;
 | 
				
			||||||
	this->info.n_params = 2;
 | 
						this->info.n_params = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port = &this->port[SPA_DIRECTION_OUTPUT];
 | 
						port = &this->port[0];
 | 
				
			||||||
	port->direction = SPA_DIRECTION_OUTPUT;
 | 
						port->stream_id = 0;
 | 
				
			||||||
	port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
 | 
					 | 
				
			||||||
			SPA_PORT_CHANGE_MASK_PARAMS |
 | 
					 | 
				
			||||||
			SPA_PORT_CHANGE_MASK_PROPS;
 | 
					 | 
				
			||||||
	port->info = SPA_PORT_INFO_INIT();
 | 
					 | 
				
			||||||
	port->info.flags = SPA_PORT_FLAG_NO_REF | SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
 | 
					 | 
				
			||||||
	port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
 | 
					 | 
				
			||||||
	port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
 | 
					 | 
				
			||||||
	port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
 | 
					 | 
				
			||||||
	port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
 | 
					 | 
				
			||||||
	port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
 | 
					 | 
				
			||||||
	port->info.params = port->params;
 | 
					 | 
				
			||||||
	port->info.n_params = 5;
 | 
					 | 
				
			||||||
	spa_list_init(&port->empty);
 | 
					 | 
				
			||||||
	spa_list_init(&port->ready);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	port = &this->port[SPA_DIRECTION_INPUT];
 | 
					 | 
				
			||||||
	port->direction = SPA_DIRECTION_INPUT;
 | 
						port->direction = SPA_DIRECTION_INPUT;
 | 
				
			||||||
	port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
 | 
						port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
 | 
				
			||||||
			SPA_PORT_CHANGE_MASK_PARAMS |
 | 
								SPA_PORT_CHANGE_MASK_PARAMS |
 | 
				
			||||||
| 
						 | 
					@ -727,7 +710,30 @@ 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						port = &this->port[1];
 | 
				
			||||||
 | 
						port->stream_id = 1;
 | 
				
			||||||
 | 
						port->direction = SPA_DIRECTION_OUTPUT;
 | 
				
			||||||
 | 
						port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
 | 
				
			||||||
 | 
								SPA_PORT_CHANGE_MASK_PARAMS |
 | 
				
			||||||
 | 
								SPA_PORT_CHANGE_MASK_PROPS;
 | 
				
			||||||
 | 
						port->info = SPA_PORT_INFO_INIT();
 | 
				
			||||||
 | 
						port->info.flags = SPA_PORT_FLAG_NO_REF | SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
 | 
				
			||||||
 | 
						port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
 | 
				
			||||||
 | 
						port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
 | 
				
			||||||
 | 
						port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
 | 
				
			||||||
 | 
						port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
 | 
				
			||||||
 | 
						port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
 | 
				
			||||||
 | 
						port->info.params = port->params;
 | 
				
			||||||
 | 
						port->info.n_params = 5;
 | 
				
			||||||
 | 
						spa_list_init(&port->empty);
 | 
				
			||||||
 | 
						spa_list_init(&port->ready);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->state.log = this->log;
 | 
						this->state.log = this->log;
 | 
				
			||||||
 | 
						spa_vulkan_init_stream(&this->state, &this->state.streams[0],
 | 
				
			||||||
 | 
								SPA_DIRECTION_INPUT, NULL);
 | 
				
			||||||
 | 
						spa_vulkan_init_stream(&this->state, &this->state.streams[1],
 | 
				
			||||||
 | 
								SPA_DIRECTION_OUTPUT, NULL);
 | 
				
			||||||
 | 
						this->state.n_streams = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,8 +61,6 @@ static void reset_props(struct props *props)
 | 
				
			||||||
	props->live = DEFAULT_LIVE;
 | 
						props->live = DEFAULT_LIVE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_PORTS 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct buffer {
 | 
					struct buffer {
 | 
				
			||||||
	uint32_t id;
 | 
						uint32_t id;
 | 
				
			||||||
#define BUFFER_FLAG_OUT (1<<0)
 | 
					#define BUFFER_FLAG_OUT (1<<0)
 | 
				
			||||||
| 
						 | 
					@ -122,7 +120,7 @@ struct impl {
 | 
				
			||||||
	struct port port;
 | 
						struct port port;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_PORT(this,d,p)  ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
 | 
					#define CHECK_PORT(this,d,p)  ((d) == SPA_DIRECTION_OUTPUT && (p) < 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int impl_node_enum_params(void *object, int seq,
 | 
					static int impl_node_enum_params(void *object, int seq,
 | 
				
			||||||
				 uint32_t id, uint32_t start, uint32_t num,
 | 
									 uint32_t id, uint32_t start, uint32_t num,
 | 
				
			||||||
| 
						 | 
					@ -308,12 +306,13 @@ static int make_buffer(struct impl *this)
 | 
				
			||||||
	this->state.constants.time = this->elapsed_time / (float) SPA_NSEC_PER_SEC;
 | 
						this->state.constants.time = this->elapsed_time / (float) SPA_NSEC_PER_SEC;
 | 
				
			||||||
	this->state.constants.frame = this->frame_count;
 | 
						this->state.constants.frame = this->frame_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_vulkan_process(&this->state, b->id);
 | 
						this->state.streams[0].pending_buffer_id = b->id;
 | 
				
			||||||
 | 
						spa_vulkan_process(&this->state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->state.ready_buffer_id != SPA_ID_INVALID) {
 | 
						if (this->state.streams[0].ready_buffer_id != SPA_ID_INVALID) {
 | 
				
			||||||
		struct buffer *b = &port->buffers[this->state.ready_buffer_id];
 | 
							struct buffer *b = &port->buffers[this->state.streams[0].ready_buffer_id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this->state.ready_buffer_id = SPA_ID_INVALID;
 | 
							this->state.streams[0].ready_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spa_log_trace(this->log, NAME " %p: ready buffer %d", this, b->id);
 | 
							spa_log_trace(this->log, NAME " %p: ready buffer %d", this, b->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -636,7 +635,7 @@ static int clear_buffers(struct impl *this, struct port *port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (port->n_buffers > 0) {
 | 
						if (port->n_buffers > 0) {
 | 
				
			||||||
		spa_log_debug(this->log, NAME " %p: clear buffers", this);
 | 
							spa_log_debug(this->log, NAME " %p: clear buffers", this);
 | 
				
			||||||
		spa_vulkan_use_buffers(&this->state, 0, 0, NULL);
 | 
							spa_vulkan_use_buffers(&this->state, &this->state.streams[0], 0, 0, NULL);
 | 
				
			||||||
		port->n_buffers = 0;
 | 
							port->n_buffers = 0;
 | 
				
			||||||
		spa_list_init(&port->empty);
 | 
							spa_list_init(&port->empty);
 | 
				
			||||||
		spa_list_init(&port->ready);
 | 
							spa_list_init(&port->ready);
 | 
				
			||||||
| 
						 | 
					@ -749,7 +748,7 @@ impl_node_port_use_buffers(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spa_list_append(&port->empty, &b->link);
 | 
							spa_list_append(&port->empty, &b->link);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spa_vulkan_use_buffers(&this->state, flags, n_buffers, buffers);
 | 
						spa_vulkan_use_buffers(&this->state, &this->state.streams[0], flags, n_buffers, buffers);
 | 
				
			||||||
	port->n_buffers = n_buffers;
 | 
						port->n_buffers = n_buffers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -958,6 +957,9 @@ impl_init(const struct spa_handle_factory *factory,
 | 
				
			||||||
	spa_list_init(&port->ready);
 | 
						spa_list_init(&port->ready);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->state.log = this->log;
 | 
						this->state.log = this->log;
 | 
				
			||||||
 | 
						spa_vulkan_init_stream(&this->state, &this->state.streams[0],
 | 
				
			||||||
 | 
								SPA_DIRECTION_OUTPUT, NULL);
 | 
				
			||||||
 | 
						this->state.n_streams = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,31 +217,36 @@ static uint32_t findMemoryType(struct vulkan_state *s,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int createDescriptors(struct vulkan_state *s)
 | 
					static int createDescriptors(struct vulkan_state *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const VkDescriptorPoolSize descriptorPoolSize = {
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkDescriptorPoolSize descriptorPoolSize = {
 | 
				
			||||||
		.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
							.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
				
			||||||
		.descriptorCount = 1
 | 
							.descriptorCount = s->n_streams,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	static const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
 | 
						const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
 | 
				
			||||||
		.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
 | 
							.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
 | 
				
			||||||
		.maxSets = 1,
 | 
							.maxSets = 1,
 | 
				
			||||||
		.poolSizeCount = 1,
 | 
							.poolSizeCount = 1,
 | 
				
			||||||
		.pPoolSizes = &descriptorPoolSize,
 | 
							.pPoolSizes = &descriptorPoolSize,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						VkDescriptorSetLayoutBinding descriptorSetLayoutBinding[s->n_streams];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        VK_CHECK_RESULT(vkCreateDescriptorPool(s->device,
 | 
					        VK_CHECK_RESULT(vkCreateDescriptorPool(s->device,
 | 
				
			||||||
				&descriptorPoolCreateInfo, NULL,
 | 
									&descriptorPoolCreateInfo, NULL,
 | 
				
			||||||
				&s->descriptorPool));
 | 
									&s->descriptorPool));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
 | 
						for (i = 0; i < s->n_streams; i++) {
 | 
				
			||||||
		.binding = 0,
 | 
							descriptorSetLayoutBinding[i] = (VkDescriptorSetLayoutBinding) {
 | 
				
			||||||
 | 
								.binding = i,
 | 
				
			||||||
			.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
								.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
				
			||||||
			.descriptorCount = 1,
 | 
								.descriptorCount = 1,
 | 
				
			||||||
			.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
 | 
								.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	static const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
 | 
						};
 | 
				
			||||||
 | 
						const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
 | 
				
			||||||
		.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
 | 
							.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
 | 
				
			||||||
		.bindingCount = 1,
 | 
							.bindingCount = s->n_streams,
 | 
				
			||||||
		.pBindings = &descriptorSetLayoutBinding
 | 
							.pBindings = descriptorSetLayoutBinding
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	VK_CHECK_RESULT(vkCreateDescriptorSetLayout(s->device,
 | 
						VK_CHECK_RESULT(vkCreateDescriptorSetLayout(s->device,
 | 
				
			||||||
				&descriptorSetLayoutCreateInfo, NULL,
 | 
									&descriptorSetLayoutCreateInfo, NULL,
 | 
				
			||||||
| 
						 | 
					@ -256,63 +261,42 @@ static int createDescriptors(struct vulkan_state *s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device,
 | 
						VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device,
 | 
				
			||||||
				&descriptorSetAllocateInfo,
 | 
									&descriptorSetAllocateInfo,
 | 
				
			||||||
				&s->descriptorSet));
 | 
									s->descriptorSet));
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int createBuffer(struct vulkan_state *s, uint32_t id)
 | 
					static int updateDescriptors(struct vulkan_state *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const VkBufferCreateInfo bufferCreateInfo = {
 | 
						uint32_t i;
 | 
				
			||||||
		.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
 | 
						VkDescriptorBufferInfo descriptorBufferInfo[s->n_streams];
 | 
				
			||||||
		.size = s->bufferSize,
 | 
						VkWriteDescriptorSet writeDescriptorSet[s->n_streams];
 | 
				
			||||||
		.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
 | 
					 | 
				
			||||||
		.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	VkMemoryRequirements memoryRequirements;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VK_CHECK_RESULT(vkCreateBuffer(s->device,
 | 
						for (i = 0; i < s->n_streams; i++) {
 | 
				
			||||||
				&bufferCreateInfo, NULL, &s->buffers[id].buffer));
 | 
							struct vulkan_stream *p = &s->streams[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vkGetBufferMemoryRequirements(s->device,
 | 
							if (p->current_buffer_id == p->pending_buffer_id ||
 | 
				
			||||||
			s->buffers[id].buffer, &memoryRequirements);
 | 
							    p->pending_buffer_id == SPA_ID_INVALID)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const VkMemoryAllocateInfo allocateInfo = {
 | 
							p->current_buffer_id = p->pending_buffer_id;
 | 
				
			||||||
		.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
 | 
							p->busy_buffer_id = p->current_buffer_id;
 | 
				
			||||||
		.allocationSize = memoryRequirements.size,
 | 
							p->pending_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
		.memoryTypeIndex = findMemoryType(s,
 | 
					 | 
				
			||||||
						  memoryRequirements.memoryTypeBits,
 | 
					 | 
				
			||||||
						  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
 | 
					 | 
				
			||||||
						  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VK_CHECK_RESULT(vkAllocateMemory(s->device,
 | 
							descriptorBufferInfo[i] = (VkDescriptorBufferInfo) {
 | 
				
			||||||
				&allocateInfo, NULL, &s->buffers[id].memory));
 | 
								.buffer = p->buffers[p->current_buffer_id].buffer,
 | 
				
			||||||
	VK_CHECK_RESULT(vkBindBufferMemory(s->device,
 | 
					 | 
				
			||||||
				s->buffers[id].buffer, s->buffers[id].memory, 0));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int updateDescriptors(struct vulkan_state *s, uint32_t buffer_id)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (s->current_buffer_id == buffer_id)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const VkDescriptorBufferInfo descriptorBufferInfo = {
 | 
					 | 
				
			||||||
		.buffer = s->buffers[buffer_id].buffer,
 | 
					 | 
				
			||||||
			.offset = 0,
 | 
								.offset = 0,
 | 
				
			||||||
		.range = s->bufferSize,
 | 
								.range = p->bufferSize,
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	const VkWriteDescriptorSet writeDescriptorSet = {
 | 
							writeDescriptorSet[i] = (VkWriteDescriptorSet) {
 | 
				
			||||||
			.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
 | 
								.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
 | 
				
			||||||
		.dstSet = s->descriptorSet,
 | 
								.dstSet = s->descriptorSet[i],
 | 
				
			||||||
		.dstBinding = 0,
 | 
								.dstBinding = i,
 | 
				
			||||||
			.descriptorCount = 1,
 | 
								.descriptorCount = 1,
 | 
				
			||||||
			.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
								.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
				
			||||||
		.pBufferInfo = &descriptorBufferInfo,
 | 
								.pBufferInfo = &descriptorBufferInfo[i],
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	vkUpdateDescriptorSets(s->device, 1, &writeDescriptorSet, 0, NULL);
 | 
						}
 | 
				
			||||||
	s->current_buffer_id = buffer_id;
 | 
						vkUpdateDescriptorSets(s->device, s->n_streams, writeDescriptorSet, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -432,7 +416,7 @@ static int runCommandBuffer(struct vulkan_state *s)
 | 
				
			||||||
			s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT,
 | 
								s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT,
 | 
				
			||||||
			0, sizeof(struct push_constants), (const void *) &s->constants);
 | 
								0, sizeof(struct push_constants), (const void *) &s->constants);
 | 
				
			||||||
	vkCmdBindDescriptorSets(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
 | 
						vkCmdBindDescriptorSets(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
 | 
				
			||||||
			s->pipelineLayout, 0, 1, &s->descriptorSet, 0, NULL);
 | 
								s->pipelineLayout, 0, s->n_streams, s->descriptorSet, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vkCmdDispatch(s->commandBuffer,
 | 
						vkCmdDispatch(s->commandBuffer,
 | 
				
			||||||
			(uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE),
 | 
								(uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE),
 | 
				
			||||||
| 
						 | 
					@ -448,55 +432,114 @@ static int runCommandBuffer(struct vulkan_state *s)
 | 
				
			||||||
		.pCommandBuffers = &s->commandBuffer,
 | 
							.pCommandBuffers = &s->commandBuffer,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
        VK_CHECK_RESULT(vkQueueSubmit(s->queue, 1, &submitInfo, s->fence));
 | 
					        VK_CHECK_RESULT(vkQueueSubmit(s->queue, 1, &submitInfo, s->fence));
 | 
				
			||||||
	s->busy_buffer_id = s->current_buffer_id;
 | 
						s->started = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void clear_buffers(struct vulkan_state *s)
 | 
					static void clear_buffers(struct vulkan_state *s, struct vulkan_stream *p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < s->n_buffers; i++) {
 | 
						for (i = 0; i < p->n_buffers; i++) {
 | 
				
			||||||
		close(s->buffers[i].buf->datas[0].fd);
 | 
							if (p->buffers[i].fd != -1)
 | 
				
			||||||
		vkFreeMemory(s->device, s->buffers[i].memory, NULL);
 | 
								close(p->buffers[i].fd);
 | 
				
			||||||
		vkDestroyBuffer(s->device, s->buffers[i].buffer, NULL);
 | 
							vkFreeMemory(s->device, p->buffers[i].memory, NULL);
 | 
				
			||||||
 | 
							vkDestroyBuffer(s->device, p->buffers[i].buffer, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s->n_buffers = 0;
 | 
						p->n_buffers = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_vulkan_use_buffers(struct vulkan_state *s, uint32_t flags,
 | 
					static void clear_streams(struct vulkan_state *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						for (i = 0; i < s->n_streams; i++) {
 | 
				
			||||||
 | 
							struct vulkan_stream *p = &s->streams[i];
 | 
				
			||||||
 | 
							clear_buffers(s, p);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *p, uint32_t flags,
 | 
				
			||||||
		uint32_t n_buffers, struct spa_buffer **buffers)
 | 
							uint32_t n_buffers, struct spa_buffer **buffers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	VULKAN_INSTANCE_FUNCTION(vkGetMemoryFdKHR);
 | 
						VULKAN_INSTANCE_FUNCTION(vkGetMemoryFdKHR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clear_buffers(s);
 | 
						clear_buffers(s, p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->bufferSize = s->constants.width * s->constants.height * sizeof(struct pixel);
 | 
						p->bufferSize = s->constants.width * s->constants.height * sizeof(struct pixel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < n_buffers; i++) {
 | 
						for (i = 0; i < n_buffers; i++) {
 | 
				
			||||||
		createBuffer(s, i);
 | 
							const VkBufferCreateInfo bufferCreateInfo = {
 | 
				
			||||||
 | 
								.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
 | 
				
			||||||
 | 
								.size = p->bufferSize,
 | 
				
			||||||
 | 
								.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
 | 
				
			||||||
 | 
								.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkCreateBuffer(s->device,
 | 
				
			||||||
 | 
										&bufferCreateInfo, NULL, &p->buffers[i].buffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkMemoryRequirements memoryRequirements;
 | 
				
			||||||
 | 
							vkGetBufferMemoryRequirements(s->device,
 | 
				
			||||||
 | 
									p->buffers[i].buffer, &memoryRequirements);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkMemoryAllocateInfo allocateInfo = {
 | 
				
			||||||
 | 
								.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
 | 
				
			||||||
 | 
								.allocationSize = memoryRequirements.size,
 | 
				
			||||||
 | 
								.memoryTypeIndex = findMemoryType(s,
 | 
				
			||||||
 | 
											  memoryRequirements.memoryTypeBits,
 | 
				
			||||||
 | 
											  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
 | 
				
			||||||
 | 
											  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (flags & SPA_NODE_BUFFERS_FLAG_ALLOC) {
 | 
				
			||||||
 | 
								VK_CHECK_RESULT(vkAllocateMemory(s->device,
 | 
				
			||||||
 | 
										&allocateInfo, NULL, &p->buffers[i].memory));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const VkMemoryGetFdInfoKHR getFdInfo = {
 | 
								const VkMemoryGetFdInfoKHR getFdInfo = {
 | 
				
			||||||
				.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
 | 
									.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
 | 
				
			||||||
			.memory = s->buffers[i].memory,
 | 
									.memory = p->buffers[i].memory,
 | 
				
			||||||
				.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
 | 
									.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			int fd;
 | 
								int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		s->buffers[i].buf = buffers[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		        VK_CHECK_RESULT(vkGetMemoryFdKHR(s->device, &getFdInfo, &fd));
 | 
							        VK_CHECK_RESULT(vkGetMemoryFdKHR(s->device, &getFdInfo, &fd));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		buffers[i]->datas[0].type = SPA_DATA_DmaBuf;
 | 
					//			buffers[i]->datas[0].type = SPA_DATA_DmaBuf;
 | 
				
			||||||
		buffers[i]->datas[0].flags = SPA_DATA_FLAG_READABLE;
 | 
								buffers[i]->datas[0].type = SPA_DATA_MemFd;
 | 
				
			||||||
			buffers[i]->datas[0].fd = fd;
 | 
								buffers[i]->datas[0].fd = fd;
 | 
				
			||||||
 | 
								buffers[i]->datas[0].flags = SPA_DATA_FLAG_READABLE;
 | 
				
			||||||
			buffers[i]->datas[0].mapoffset = 0;
 | 
								buffers[i]->datas[0].mapoffset = 0;
 | 
				
			||||||
		buffers[i]->datas[0].maxsize = s->bufferSize;
 | 
								buffers[i]->datas[0].maxsize = p->bufferSize;
 | 
				
			||||||
	}
 | 
								p->buffers[i].fd = fd;
 | 
				
			||||||
	s->n_buffers = n_buffers;
 | 
							} else {
 | 
				
			||||||
 | 
								VkImportMemoryFdInfoKHR importInfo = {
 | 
				
			||||||
 | 
									.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
 | 
				
			||||||
 | 
									.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
 | 
				
			||||||
 | 
									.fd = fcntl(buffers[i]->datas[0].fd, F_DUPFD_CLOEXEC, 0),
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								allocateInfo.pNext = &importInfo;
 | 
				
			||||||
 | 
								p->buffers[i].fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								VK_CHECK_RESULT(vkAllocateMemory(s->device,
 | 
				
			||||||
 | 
										&allocateInfo, NULL, &p->buffers[i].memory));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkBindBufferMemory(s->device,
 | 
				
			||||||
 | 
										p->buffers[i].buffer, p->buffers[i].memory, 0));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p->n_buffers = n_buffers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spa_vulkan_init_stream(struct vulkan_state *s, struct vulkan_stream *stream,
 | 
				
			||||||
 | 
							enum spa_direction direction, struct spa_dict *props)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						spa_zero(*stream);
 | 
				
			||||||
 | 
						stream->direction = direction;
 | 
				
			||||||
 | 
						stream->current_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
						stream->busy_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
						stream->ready_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -532,23 +575,31 @@ 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->current_buffer_id = SPA_ID_INVALID;
 | 
						uint32_t i;
 | 
				
			||||||
	s->busy_buffer_id = SPA_ID_INVALID;
 | 
					
 | 
				
			||||||
	s->ready_buffer_id = SPA_ID_INVALID;
 | 
						for (i = 0; i < s->n_streams; i++) {
 | 
				
			||||||
 | 
							struct vulkan_stream *p = &s->streams[i];
 | 
				
			||||||
 | 
							p->current_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
							p->busy_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
							p->ready_buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_vulkan_stop(struct vulkan_state *s)
 | 
					int spa_vulkan_stop(struct vulkan_state *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
        VK_CHECK_RESULT(vkDeviceWaitIdle(s->device));
 | 
					        VK_CHECK_RESULT(vkDeviceWaitIdle(s->device));
 | 
				
			||||||
 | 
						clear_streams(s);
 | 
				
			||||||
 | 
						s->started = false;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_vulkan_ready(struct vulkan_state *s)
 | 
					int spa_vulkan_ready(struct vulkan_state *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						uint32_t i;
 | 
				
			||||||
	VkResult result;
 | 
						VkResult result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (s->busy_buffer_id == SPA_ID_INVALID)
 | 
						if (!s->started)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result = vkGetFenceStatus(s->device, s->fence);
 | 
						result = vkGetFenceStatus(s->device, s->fence);
 | 
				
			||||||
| 
						 | 
					@ -556,15 +607,19 @@ int spa_vulkan_ready(struct vulkan_state *s)
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
	VK_CHECK_RESULT(result);
 | 
						VK_CHECK_RESULT(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->ready_buffer_id = s->busy_buffer_id;
 | 
						s->started = false;
 | 
				
			||||||
	s->busy_buffer_id = SPA_ID_INVALID;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < s->n_streams; i++) {
 | 
				
			||||||
 | 
							struct vulkan_stream *p = &s->streams[i];
 | 
				
			||||||
 | 
							p->ready_buffer_id = p->busy_buffer_id;
 | 
				
			||||||
 | 
							p->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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	updateDescriptors(s, buffer_id);
 | 
						updateDescriptors(s);
 | 
				
			||||||
	runCommandBuffer(s);
 | 
						runCommandBuffer(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
#include <vulkan/vulkan.h>
 | 
					#include <vulkan/vulkan.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <spa/buffer/buffer.h>
 | 
					#include <spa/buffer/buffer.h>
 | 
				
			||||||
 | 
					#include <spa/node/node.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_STREAMS 2
 | 
				
			||||||
#define MAX_BUFFERS 16
 | 
					#define MAX_BUFFERS 16
 | 
				
			||||||
#define WORKGROUP_SIZE 32
 | 
					#define WORKGROUP_SIZE 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,11 +19,24 @@ struct push_constants {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vulkan_buffer {
 | 
					struct vulkan_buffer {
 | 
				
			||||||
	struct spa_buffer *buf;
 | 
						int fd;
 | 
				
			||||||
	VkBuffer buffer;
 | 
						VkBuffer buffer;
 | 
				
			||||||
	VkDeviceMemory memory;
 | 
						VkDeviceMemory memory;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct vulkan_stream {
 | 
				
			||||||
 | 
						enum spa_direction direction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t pending_buffer_id;
 | 
				
			||||||
 | 
						uint32_t current_buffer_id;
 | 
				
			||||||
 | 
						uint32_t busy_buffer_id;
 | 
				
			||||||
 | 
						uint32_t ready_buffer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t bufferSize;
 | 
				
			||||||
 | 
						struct vulkan_buffer buffers[MAX_BUFFERS];
 | 
				
			||||||
 | 
						uint32_t n_buffers;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vulkan_state {
 | 
					struct vulkan_state {
 | 
				
			||||||
	struct spa_log *log;
 | 
						struct spa_log *log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,27 +58,26 @@ struct vulkan_state {
 | 
				
			||||||
	uint32_t queueFamilyIndex;
 | 
						uint32_t queueFamilyIndex;
 | 
				
			||||||
	VkFence fence;
 | 
						VkFence fence;
 | 
				
			||||||
	unsigned int prepared:1;
 | 
						unsigned int prepared:1;
 | 
				
			||||||
	uint32_t busy_buffer_id;
 | 
						unsigned int started:1;
 | 
				
			||||||
	uint32_t ready_buffer_id;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VkDescriptorPool descriptorPool;
 | 
						VkDescriptorPool descriptorPool;
 | 
				
			||||||
	VkDescriptorSet descriptorSet;
 | 
					 | 
				
			||||||
	VkDescriptorSetLayout descriptorSetLayout;
 | 
						VkDescriptorSetLayout descriptorSetLayout;
 | 
				
			||||||
	uint32_t current_buffer_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint32_t bufferSize;
 | 
					 | 
				
			||||||
	struct vulkan_buffer buffers[MAX_BUFFERS];
 | 
					 | 
				
			||||||
	uint32_t n_buffers;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t n_streams;
 | 
				
			||||||
 | 
						VkDescriptorSet descriptorSet[MAX_STREAMS];
 | 
				
			||||||
 | 
						struct vulkan_stream streams[MAX_STREAMS];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spa_vulkan_init_stream(struct vulkan_state *s, struct vulkan_stream *stream, enum spa_direction,
 | 
				
			||||||
 | 
							struct spa_dict *props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_vulkan_prepare(struct vulkan_state *s);
 | 
					int spa_vulkan_prepare(struct vulkan_state *s);
 | 
				
			||||||
int spa_vulkan_use_buffers(struct vulkan_state *s, uint32_t flags,
 | 
					int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *stream, uint32_t flags,
 | 
				
			||||||
		uint32_t n_buffers, struct spa_buffer **buffers);
 | 
							uint32_t n_buffers, struct spa_buffer **buffers);
 | 
				
			||||||
int spa_vulkan_unprepare(struct vulkan_state *s);
 | 
					int spa_vulkan_unprepare(struct vulkan_state *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_vulkan_start(struct vulkan_state *s);
 | 
					int spa_vulkan_start(struct vulkan_state *s);
 | 
				
			||||||
int spa_vulkan_stop(struct vulkan_state *s);
 | 
					int spa_vulkan_stop(struct vulkan_state *s);
 | 
				
			||||||
int spa_vulkan_ready(struct vulkan_state *s);
 | 
					int spa_vulkan_ready(struct vulkan_state *s);
 | 
				
			||||||
int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id);
 | 
					int spa_vulkan_process(struct vulkan_state *s);
 | 
				
			||||||
int spa_vulkan_cleanup(struct vulkan_state *s);
 | 
					int spa_vulkan_cleanup(struct vulkan_state *s);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue