diff --git a/spa/plugins/vulkan/shaders/main.comp b/spa/plugins/vulkan/shaders/main.comp index d85f7fba8..368b7cf41 100644 --- a/spa/plugins/vulkan/shaders/main.comp +++ b/spa/plugins/vulkan/shaders/main.comp @@ -4,14 +4,7 @@ #define WORKGROUP_SIZE 32 layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1 ) in; -struct Pixel{ - vec4 value; -}; - -layout(std140, binding = 0) buffer buf -{ - Pixel imageData[]; -}; +layout(rgba32f, binding = 0) uniform image2D resultImage; layout( push_constant ) uniform Constants { float time; @@ -42,8 +35,7 @@ void main() mainImage(outColor, coord); - imageData[PushConstant.width * gl_GlobalInvocationID.y + - gl_GlobalInvocationID.x].value = outColor; + imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), outColor); } //#include "plasma-globe.comp" diff --git a/spa/plugins/vulkan/vulkan-compute-filter.c b/spa/plugins/vulkan/vulkan-compute-filter.c index 9ffccaf6d..fbe9e769e 100644 --- a/spa/plugins/vulkan/vulkan-compute-filter.c +++ b/spa/plugins/vulkan/vulkan-compute-filter.c @@ -91,12 +91,7 @@ struct impl { struct spa_hook_list hooks; struct spa_callbacks callbacks; - bool async; - struct spa_source timer_source; - struct itimerspec timerspec; - bool started; - uint64_t frame_count; struct vulkan_state state; struct port port[2]; @@ -177,7 +172,7 @@ static inline void reuse_buffer(struct impl *this, struct port *port, uint32_t i struct buffer *b = &port->buffers[id]; if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) { - spa_log_info(this->log, NAME " %p: reuse buffer %d", this, id); + spa_log_debug(this->log, NAME " %p: reuse buffer %d", this, id); SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT); spa_list_append(&port->empty, &b->link); @@ -196,7 +191,6 @@ static int impl_node_send_command(void *object, const struct spa_command *comman if (this->started) return 0; - this->frame_count = 0; this->started = true; spa_vulkan_start(&this->state); break; @@ -608,21 +602,31 @@ static int impl_node_process(void *object) } if (spa_list_is_empty(&outport->empty)) { - spa_log_error(this->log, NAME " %p: out of buffers", this); + spa_log_debug(this->log, NAME " %p: out of buffers", this); return -EPIPE; } b = &inport->buffers[inio->buffer_id]; - this->state.streams[0].pending_buffer_id = b->id; + this->state.streams[inport->stream_id].pending_buffer_id = b->id; + inio->status = SPA_STATUS_NEED_DATA; b = spa_list_first(&outport->empty, struct buffer, link); spa_list_remove(&b->link); - this->state.streams[1].pending_buffer_id = b->id; + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); + this->state.streams[outport->stream_id].pending_buffer_id = b->id; + + this->state.constants.time += 0.025; + this->state.constants.frame++; + + spa_log_debug(this->log, "filter into %d", b->id); spa_vulkan_process(&this->state); + b->outbuf->datas[0].chunk->offset = 0; + b->outbuf->datas[0].chunk->size = b->outbuf->datas[0].maxsize; + b->outbuf->datas[0].chunk->stride = this->position->video.stride; + outio->buffer_id = b->id; outio->status = SPA_STATUS_HAVE_DATA; - inio->status = SPA_STATUS_NEED_DATA; return SPA_STATUS_NEED_DATA | SPA_STATUS_HAVE_DATA; } @@ -694,6 +698,7 @@ impl_init(const struct spa_handle_factory *factory, this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); this->state.log = this->log; + this->state.shaderName = "spa/plugins/vulkan/shaders/filter.spv"; spa_hook_list_init(&this->hooks); @@ -715,7 +720,7 @@ impl_init(const struct spa_handle_factory *factory, this->info.n_params = 2; port = &this->port[0]; - port->stream_id = 0; + port->stream_id = 1; port->direction = SPA_DIRECTION_INPUT; port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PARAMS | @@ -729,13 +734,13 @@ impl_init(const struct spa_handle_factory *factory, port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); port->info.params = port->params; port->info.n_params = 5; - spa_vulkan_init_stream(&this->state, &this->state.streams[0], + spa_vulkan_init_stream(&this->state, &this->state.streams[port->stream_id], SPA_DIRECTION_INPUT, NULL); spa_list_init(&port->empty); spa_list_init(&port->ready); port = &this->port[1]; - port->stream_id = 1; + port->stream_id = 0; port->direction = SPA_DIRECTION_OUTPUT; port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PARAMS | @@ -751,7 +756,7 @@ impl_init(const struct spa_handle_factory *factory, port->info.n_params = 5; spa_list_init(&port->empty); spa_list_init(&port->ready); - spa_vulkan_init_stream(&this->state, &this->state.streams[1], + spa_vulkan_init_stream(&this->state, &this->state.streams[port->stream_id], SPA_DIRECTION_OUTPUT, NULL); this->state.n_streams = 2; diff --git a/spa/plugins/vulkan/vulkan-compute-source.c b/spa/plugins/vulkan/vulkan-compute-source.c index 5682da45f..3f26c9b24 100644 --- a/spa/plugins/vulkan/vulkan-compute-source.c +++ b/spa/plugins/vulkan/vulkan-compute-source.c @@ -959,6 +959,7 @@ impl_init(const struct spa_handle_factory *factory, this->state.log = this->log; spa_vulkan_init_stream(&this->state, &this->state.streams[0], SPA_DIRECTION_OUTPUT, NULL); + this->state.shaderName = "spa/plugins/vulkan/shaders/main.spv"; this->state.n_streams = 1; return 0; diff --git a/spa/plugins/vulkan/vulkan-utils.c b/spa/plugins/vulkan/vulkan-utils.c index 8f06c4c46..424cc2bac 100644 --- a/spa/plugins/vulkan/vulkan-utils.c +++ b/spa/plugins/vulkan/vulkan-utils.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -91,10 +92,10 @@ static int vkresult_to_errno(VkResult result) #define VK_CHECK_RESULT(f) \ { \ VkResult _result = (f); \ - int _res = -vkresult_to_errno(_result); \ + int _r = -vkresult_to_errno(_result); \ if (_result != VK_SUCCESS) { \ - spa_log_error(s->log, "error: %d (%s)", _result, spa_strerror(_res)); \ - return _res; \ + spa_log_error(s->log, "error: %d (%d %s)", _result, _r, spa_strerror(_r)); \ + return _r; \ } \ } #define CHECK(f) \ @@ -117,24 +118,32 @@ static int createInstance(struct vulkan_state *s) static const char * const extensions[] = { VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME }; - static const char * const layers[] = { + static const char * const checkLayers[] = { +#ifdef ENABLE_VALIDATION "VK_LAYER_KHRONOS_validation", +#endif + NULL }; - uint32_t i, layerCount; + uint32_t i, j, layerCount, n_layers = 0; + const char *layers[1]; vkEnumerateInstanceLayerProperties(&layerCount, NULL); VkLayerProperties availableLayers[layerCount]; vkEnumerateInstanceLayerProperties(&layerCount, availableLayers); - for (i = 0; i < layerCount; i++) - spa_log_info(s->log, "%s", availableLayers[i].layerName); + for (i = 0; i < layerCount; i++) { + for (j = 0; j < SPA_N_ELEMENTS(checkLayers); j++) { + if (spa_streq(availableLayers[i].layerName, checkLayers[j])) + layers[n_layers++] = checkLayers[j]; + } + } const VkInstanceCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &applicationInfo, .enabledExtensionCount = 1, .ppEnabledExtensionNames = extensions, - .enabledLayerCount = 1, + .enabledLayerCount = n_layers, .ppEnabledLayerNames = layers, }; @@ -239,7 +248,7 @@ static int createDescriptors(struct vulkan_state *s) uint32_t i; VkDescriptorPoolSize descriptorPoolSize = { - .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = s->n_streams, }; const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { @@ -257,7 +266,7 @@ static int createDescriptors(struct vulkan_state *s) for (i = 0; i < s->n_streams; i++) { descriptorSetLayoutBinding[i] = (VkDescriptorSetLayoutBinding) { .binding = i, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT }; @@ -281,13 +290,16 @@ static int createDescriptors(struct vulkan_state *s) VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device, &descriptorSetAllocateInfo, &s->descriptorSet)); + + + return 0; } static int updateDescriptors(struct vulkan_state *s) { uint32_t i; - VkDescriptorBufferInfo descriptorBufferInfo[s->n_streams]; + VkDescriptorImageInfo descriptorImageInfo[s->n_streams]; VkWriteDescriptorSet writeDescriptorSet[s->n_streams]; for (i = 0; i < s->n_streams; i++) { @@ -301,18 +313,17 @@ static int updateDescriptors(struct vulkan_state *s) p->busy_buffer_id = p->current_buffer_id; p->pending_buffer_id = SPA_ID_INVALID; - descriptorBufferInfo[i] = (VkDescriptorBufferInfo) { - .buffer = p->buffers[p->current_buffer_id].buffer, - .offset = 0, - .range = p->bufferSize, + descriptorImageInfo[i] = (VkDescriptorImageInfo) { + .imageView = p->buffers[p->current_buffer_id].view, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, }; writeDescriptorSet[i] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = s->descriptorSet, .dstBinding = i, .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .pBufferInfo = &descriptorBufferInfo[i], + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .pImageInfo = &descriptorImageInfo[i], }; } vkUpdateDescriptorSets(s->device, s->n_streams, @@ -465,7 +476,8 @@ static void clear_buffers(struct vulkan_state *s, struct vulkan_stream *p) if (p->buffers[i].fd != -1) close(p->buffers[i].fd); vkFreeMemory(s->device, p->buffers[i].memory, NULL); - vkDestroyBuffer(s->device, p->buffers[i].buffer, NULL); + vkDestroyImage(s->device, p->buffers[i].image, NULL); + vkDestroyImageView(s->device, p->buffers[i].view, NULL); } p->n_buffers = 0; } @@ -487,30 +499,37 @@ int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *p, uint clear_buffers(s, p); - p->bufferSize = s->constants.width * s->constants.height * sizeof(struct pixel); - for (i = 0; i < n_buffers; i++) { - VkExternalMemoryBufferCreateInfo extInfo; - VkBufferCreateInfo bufferCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = p->bufferSize, - .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VkExternalMemoryImageCreateInfo extInfo; + VkImageCreateInfo imageCreateInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .extent.width = s->constants.width, + .extent.height = s->constants.height, + .extent.depth = 1, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; if (!(flags & SPA_NODE_BUFFERS_FLAG_ALLOC)) { - extInfo = (VkExternalMemoryBufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + extInfo = (VkExternalMemoryImageCreateInfo) { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; - bufferCreateInfo.pNext = &extInfo; + imageCreateInfo.pNext = &extInfo; } - VK_CHECK_RESULT(vkCreateBuffer(s->device, - &bufferCreateInfo, NULL, &p->buffers[i].buffer)); + VK_CHECK_RESULT(vkCreateImage(s->device, + &imageCreateInfo, NULL, &p->buffers[i].image)); VkMemoryRequirements memoryRequirements; - vkGetBufferMemoryRequirements(s->device, - p->buffers[i].buffer, &memoryRequirements); + vkGetImageMemoryRequirements(s->device, + p->buffers[i].image, &memoryRequirements); VkMemoryAllocateInfo allocateInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, @@ -534,12 +553,14 @@ int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *p, uint VK_CHECK_RESULT(vkGetMemoryFdKHR(s->device, &getFdInfo, &fd)); + spa_log_info(s->log, "export DMABUF %zd", memoryRequirements.size); + // buffers[i]->datas[0].type = SPA_DATA_DmaBuf; buffers[i]->datas[0].type = SPA_DATA_MemFd; 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].maxsize = p->bufferSize; + buffers[i]->datas[0].maxsize = memoryRequirements.size; p->buffers[i].fd = fd; } else { VkImportMemoryFdInfoKHR importInfo = { @@ -549,12 +570,30 @@ int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *p, uint }; allocateInfo.pNext = &importInfo; p->buffers[i].fd = -1; + spa_log_info(s->log, "import DMABUF"); 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)); + VK_CHECK_RESULT(vkBindImageMemory(s->device, + p->buffers[i].image, p->buffers[i].memory, 0)); + + VkImageViewCreateInfo viewInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = p->buffers[i].image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .components.r = VK_COMPONENT_SWIZZLE_R, + .components.g = VK_COMPONENT_SWIZZLE_G, + .components.b = VK_COMPONENT_SWIZZLE_B, + .components.a = VK_COMPONENT_SWIZZLE_A, + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }; + + VK_CHECK_RESULT(vkCreateImageView(s->device, + &viewInfo, NULL, &p->buffers[i].view)); } p->n_buffers = n_buffers; @@ -579,7 +618,7 @@ int spa_vulkan_prepare(struct vulkan_state *s) CHECK(findPhysicalDevice(s)); CHECK(createDevice(s)); CHECK(createDescriptors(s)); - CHECK(createComputePipeline(s, "spa/plugins/vulkan/shaders/main.spv")); + CHECK(createComputePipeline(s, s->shaderName)); CHECK(createCommandBuffer(s)); s->prepared = true; } @@ -651,6 +690,7 @@ int spa_vulkan_process(struct vulkan_state *s) { CHECK(updateDescriptors(s)); CHECK(runCommandBuffer(s)); + VK_CHECK_RESULT(vkDeviceWaitIdle(s->device)); return 0; } diff --git a/spa/plugins/vulkan/vulkan-utils.h b/spa/plugins/vulkan/vulkan-utils.h index 4b9a888c7..03cdec8b7 100644 --- a/spa/plugins/vulkan/vulkan-utils.h +++ b/spa/plugins/vulkan/vulkan-utils.h @@ -20,7 +20,8 @@ struct push_constants { struct vulkan_buffer { int fd; - VkBuffer buffer; + VkImage image; + VkImageView view; VkDeviceMemory memory; }; @@ -32,7 +33,6 @@ struct vulkan_stream { uint32_t busy_buffer_id; uint32_t ready_buffer_id; - uint32_t bufferSize; struct vulkan_buffer buffers[MAX_BUFFERS]; uint32_t n_buffers; }; @@ -49,6 +49,7 @@ struct vulkan_state { VkPipeline pipeline; VkPipelineLayout pipelineLayout; + const char *shaderName; VkShaderModule computeShaderModule; VkCommandPool commandPool;