/* static functions */
static VkSampleCountFlagBits
-get_num_samples(uint32_t num_samples);
+get_num_samples(uint32_t num_samples)
+{
+ switch(num_samples) {
+ case 64:
+ return VK_SAMPLE_COUNT_64_BIT;
+ case 32:
+ return VK_SAMPLE_COUNT_32_BIT;
+ case 16:
+ return VK_SAMPLE_COUNT_16_BIT;
+ case 8:
+ return VK_SAMPLE_COUNT_8_BIT;
+ case 4:
+ return VK_SAMPLE_COUNT_4_BIT;
+ case 2:
+ return VK_SAMPLE_COUNT_2_BIT;
+ case 1:
+ break;
+ default:
+ fprintf(stderr, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
+ break;
+ }
+ return VK_SAMPLE_COUNT_1_BIT;
+}
+
+static VkAccessFlagBits
+get_access_mask(const VkImageLayout layout)
+{
+ /* dstAccessMask of barriers must be supported from the pipeline
+ * stage, see also access scopes and this table:
+ * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#synchronization-access-types-supported
+ */
+ switch (layout) {
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ return 0;
+ case VK_IMAGE_LAYOUT_GENERAL:
+ return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return VK_ACCESS_HOST_WRITE_BIT;
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ return VK_ACCESS_TRANSFER_READ_BIT;
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ return VK_ACCESS_TRANSFER_WRITE_BIT;
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ return 0;
+ default:
+ return 0;
+ };
+
+ return 0;
+}
static void
enable_validation_layers(VkInstanceCreateInfo *info)
}
}
-static void
-fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
-{
- VkPhysicalDeviceIDProperties devProp;
- VkPhysicalDeviceProperties2 prop2;
-
- memset(&devProp, 0, sizeof devProp);
- devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
-
- memset(&prop2, 0, sizeof prop2);
- prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- prop2.pNext = &devProp;
-
- vkGetPhysicalDeviceProperties2(pdev, &prop2);
- memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
- memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
-}
-
static VkInstance
create_instance(bool enable_layers)
{
enable_validation_layers(&inst_info);
if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
return inst;
}
if ((res =
vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
pdevice0 = pdevices[0];
free(pdevices);
static VkDevice
create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
{
+ /* FIXME: swapchain */
const char *deviceExtensions[] = { "VK_KHR_external_memory_fd",
"VK_KHR_external_semaphore_fd" };
VkDeviceQueueCreateInfo dev_queue_info;
vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
if (prop_count < 0) {
fprintf(stderr, "Invalid queue family properties.\n");
- return VK_NULL_HANDLE;
+ return 0;
}
fam_props = malloc(prop_count * sizeof *fam_props);
dev_info.ppEnabledExtensionNames = deviceExtensions;
if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
return dev;
}
-static VkPipelineCache
-create_pipeline_cache(VkDevice dev)
+static void
+fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
{
- VkPipelineCacheCreateInfo pcache_info;
- VkPipelineCache pcache;
+ VkPhysicalDeviceIDProperties devProp;
+ VkPhysicalDeviceProperties2 prop2;
- memset(&pcache_info, 0, sizeof pcache_info);
- pcache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ memset(&devProp, 0, sizeof devProp);
+ devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
- if (vkCreatePipelineCache(dev, &pcache_info, 0, &pcache) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ memset(&prop2, 0, sizeof prop2);
+ prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ prop2.pNext = &devProp;
- return pcache;
+ vkGetPhysicalDeviceProperties2(pdev, &prop2);
+ memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
+ memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
}
static VkCommandPool
cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
if (vkCreateCommandPool(dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
return cmd_pool;
}
static VkRenderPass
create_renderpass(struct vk_ctx *ctx,
- struct vk_image_props *color_img_props,
- struct vk_image_props *depth_img_props)
+ struct vk_image_props *color_img_props,
+ struct vk_image_props *depth_img_props)
{
uint32_t num_attachments = 2;
VkAttachmentDescription att_dsc[2];
att_dsc[0].initialLayout = color_img_props->in_layout;
att_dsc[0].finalLayout = color_img_props->end_layout;
att_dsc[0].format = color_img_props->format;
+ att_dsc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ att_dsc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
att_dsc[1].samples = get_num_samples(depth_img_props->num_samples);
+
/* We might want to reuse a depth buffer */
- if (depth_img_props->in_layout != VK_IMAGE_LAYOUT_UNDEFINED)
+ if (depth_img_props->in_layout != VK_IMAGE_LAYOUT_UNDEFINED) {
att_dsc[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- else
+ att_dsc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ }
+ else {
att_dsc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ att_dsc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ }
+
att_dsc[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ att_dsc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
att_dsc[1].initialLayout = depth_img_props->in_layout;
att_dsc[1].finalLayout = depth_img_props->end_layout;
att_dsc[1].format = depth_img_props->format;
default:
break;
}
- return VK_NULL_HANDLE;
+ return 0;
}
static VkPipelineStageFlags
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
default:
- return 0;
+ break;
}
return 0;
}
color_info.format = color_att->props.format;
color_info.subresourceRange = sr;
- if (vkCreateImageView(ctx->dev, &color_info, 0, &atts[0]) != VK_SUCCESS) {
+ if (vkCreateImageView(ctx->dev, &color_info, 0, &color_att->obj.img_view) != VK_SUCCESS) {
fprintf(stderr, "Failed to create color image view for framebuffer.\n");
vk_destroy_image(ctx, &color_att->obj);
goto fail;
depth_info.format = depth_att->props.format;
depth_info.subresourceRange = sr;
- if (vkCreateImageView(ctx->dev, &depth_info, 0, &atts[1]) != VK_SUCCESS) {
+ if (vkCreateImageView(ctx->dev, &depth_info, 0, &depth_att->obj.img_view) != VK_SUCCESS) {
+
fprintf(stderr, "Failed to create depth image view for framebuffer.\n");
vk_destroy_image(ctx, &depth_att->obj);
goto fail;
}
+ atts[0] = color_att->obj.img_view;
+ atts[1] = depth_att->obj.img_view;
+
memset(&fb_info, 0, sizeof fb_info);
fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fb_info.renderPass = renderer->renderpass;
static void
create_pipeline(struct vk_ctx *ctx,
- uint32_t width,
- uint32_t height,
- uint32_t num_samples,
- bool enable_depth,
- bool enable_stencil,
- struct vk_renderer *renderer)
+ uint32_t width,
+ uint32_t height,
+ uint32_t num_samples,
+ bool enable_depth,
+ bool enable_stencil,
+ struct vk_renderer *renderer)
{
VkVertexInputBindingDescription vert_bind_dsc[1];
VkVertexInputAttributeDescription vert_att_dsc[1];
vert_bind_dsc[0].stride = stride;
vert_bind_dsc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+ /* If using vbo, we have setup vertex_info in the renderer. */
+ bool use_vbo = renderer->vertex_info.num_verts > 0;
+
/* VkPipelineVertexInputStateCreateInfo */
memset(&vert_input_info, 0, sizeof vert_input_info);
vert_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vert_input_info.vertexBindingDescriptionCount = 1;
+ vert_input_info.vertexBindingDescriptionCount = use_vbo ? 1 : 0;
vert_input_info.pVertexBindingDescriptions = vert_bind_dsc;
- vert_input_info.vertexAttributeDescriptionCount = 1;
+ vert_input_info.vertexAttributeDescriptionCount = use_vbo ? 1 : 0;
vert_input_info.pVertexAttributeDescriptions = vert_att_dsc;
/* VkPipelineInputAssemblyStateCreateInfo */
memset(&asm_info, 0, sizeof asm_info);
asm_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
asm_info.topology = renderer->vertex_info.topology ?
- renderer->vertex_info.topology : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ renderer->vertex_info.topology
+ : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
asm_info.primitiveRestartEnable = false;
/* VkViewport */
/* VkPipelineColorBlendAttachmentState */
memset(&cb_att_state[0], 0, sizeof cb_att_state[0]);
cb_att_state[0].colorWriteMask = (VK_COLOR_COMPONENT_R_BIT |
- VK_COLOR_COMPONENT_G_BIT |
- VK_COLOR_COMPONENT_B_BIT |
- VK_COLOR_COMPONENT_A_BIT);
+ VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT |
+ VK_COLOR_COMPONENT_A_BIT);
/* VkPipelineColorBlendStateCreateInfo */
memset(&cb_info, 0, sizeof cb_info);
pipeline_info.stageCount = 2;
pipeline_info.pStages = sdr_stages;
- if (vkCreateGraphicsPipelines(ctx->dev, ctx->cache, 1,
- &pipeline_info, 0, &renderer->pipeline) !=
- VK_SUCCESS) {
+ if (vkCreateGraphicsPipelines(ctx->dev, 0, 1,
+ &pipeline_info, 0,
+ &renderer->pipeline) != VK_SUCCESS) {
fprintf(stderr, "Failed to create graphics pipeline.\n");
renderer->pipeline = VK_NULL_HANDLE;
}
}
-static VkAccessFlagBits
-get_access_mask(const VkImageLayout layout)
-{
- switch (layout) {
- case VK_IMAGE_LAYOUT_UNDEFINED:
- return 0;
- case VK_IMAGE_LAYOUT_GENERAL:
- return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
- VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT |
- VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_HOST_WRITE_BIT |
- VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
- VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- return VK_ACCESS_HOST_WRITE_BIT;
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
- return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- return VK_ACCESS_TRANSFER_READ_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_ACCESS_TRANSFER_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return 0;
- default:
- return 0;
- };
-
- return 0;
-}
-
static VkCommandBuffer
create_cmd_buf(VkDevice dev, VkCommandPool cmd_pool)
{
alloc_info.commandPool = cmd_pool;
if (vkAllocateCommandBuffers(dev, &alloc_info, &cmd_buf) != VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
return cmd_buf;
}
return UINT32_MAX;
}
-static VkSampleCountFlagBits
-get_num_samples(uint32_t num_samples)
-{
- switch(num_samples) {
- case 64:
- return VK_SAMPLE_COUNT_64_BIT;
- case 32:
- return VK_SAMPLE_COUNT_32_BIT;
- case 16:
- return VK_SAMPLE_COUNT_16_BIT;
- case 8:
- return VK_SAMPLE_COUNT_8_BIT;
- case 4:
- return VK_SAMPLE_COUNT_4_BIT;
- case 2:
- return VK_SAMPLE_COUNT_2_BIT;
- case 1:
- break;
- default:
- fprintf(stderr, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
- break;
- }
- return VK_SAMPLE_COUNT_1_BIT;
-}
-
static VkDeviceMemory
alloc_memory(struct vk_ctx *ctx,
- const VkMemoryRequirements *mem_reqs,
- VkImage image,
- VkBuffer buffer,
- VkMemoryPropertyFlagBits prop_flags)
+ bool is_external,
+ const VkMemoryRequirements *mem_reqs,
+ VkImage image,
+ VkBuffer buffer,
+ VkMemoryPropertyFlagBits prop_flags)
{
VkExportMemoryAllocateInfo exp_mem_info;
VkMemoryAllocateInfo mem_alloc_info;
VkDeviceMemory mem;
VkMemoryDedicatedAllocateInfoKHR ded_info;
- memset(&exp_mem_info, 0, sizeof exp_mem_info);
- exp_mem_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
- exp_mem_info.handleTypes =
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+ if (is_external) {
+ memset(&exp_mem_info, 0, sizeof exp_mem_info);
+ exp_mem_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
+ exp_mem_info.handleTypes =
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+ }
memset(&mem_alloc_info, 0, sizeof mem_alloc_info);
mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
fprintf(stderr, "No suitable memory type index found.\n");
- return VK_NULL_HANDLE;
+ return 0;
}
if (image || buffer) {
if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
VK_SUCCESS)
- return VK_NULL_HANDLE;
+ return 0;
return mem;
}
vkGetImageMemoryRequirements2(ctx->dev, &req_info2, &mem_reqs2);
img_obj->mobj.mem = alloc_memory(ctx,
- &mem_reqs2.memoryRequirements,
- ded_reqs.requiresDedicatedAllocation? img_obj->img : VK_NULL_HANDLE,
- VK_NULL_HANDLE,
- mem_reqs2.memoryRequirements.memoryTypeBits &
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ true, /* is_external = FIXME */
+ &mem_reqs2.memoryRequirements,
+ ded_reqs.requiresDedicatedAllocation ?
+ img_obj->img : VK_NULL_HANDLE,
+ VK_NULL_HANDLE,
+ mem_reqs2.memoryRequirements.memoryTypeBits &
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
img_obj->mobj.mem_sz = mem_reqs2.memoryRequirements.size;
img_obj->mobj.dedicated = ded_reqs.requiresDedicatedAllocation;
return false;
}
- if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) != VK_SUCCESS) {
+ if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) !=
+ VK_SUCCESS) {
fprintf(stderr, "Failed to bind image memory.\n");
return false;
}
static bool
are_props_supported(struct vk_ctx *ctx, struct vk_image_props *props)
{
+ VkPhysicalDeviceExternalImageFormatInfo ext_img_fmt_info;
+ VkExternalImageFormatProperties ext_img_fmt_props;
+
+ int i;
VkPhysicalDeviceImageFormatInfo2 img_fmt_info;
VkImageFormatProperties2 img_fmt_props;
+ VkImageUsageFlagBits all_flags[] = {
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ VK_IMAGE_USAGE_SAMPLED_BIT,
+ VK_IMAGE_USAGE_STORAGE_BIT,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
+ /* Shouldn't be used together with COLOR, DEPTH_STENCIL
+ * attachment bits:
+ * VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
+ * Provided by VK_EXT_fragment_density_map
+ * VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
+ * Provided by VK_NV_shading_rate_image
+ * VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
+ * Provided by VK_KHR_fragment_shading_rate
+ * VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
+ */
+ };
+ VkImageUsageFlagBits flags = 0;
+
+ VkExternalMemoryFeatureFlagBits export_feature_flags =
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
+ VkExternalMemoryHandleTypeFlagBits handle_type =
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ memset(&ext_img_fmt_info, 0, sizeof ext_img_fmt_info);
+ ext_img_fmt_info.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
+ ext_img_fmt_info.handleType = handle_type;
+
+ memset(&ext_img_fmt_props, 0, sizeof ext_img_fmt_props);
+ ext_img_fmt_props.sType =
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
+
+ memset(&img_fmt_props, 0, sizeof img_fmt_props);
+ img_fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
+ img_fmt_props.pNext = &ext_img_fmt_props;
memset(&img_fmt_info, 0, sizeof img_fmt_info);
img_fmt_info.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
- img_fmt_info.pNext = 0;
+ img_fmt_info.pNext = &ext_img_fmt_info;
img_fmt_info.format = props->format;
img_fmt_info.type = get_image_type(props->h, props->depth);
img_fmt_info.tiling = props->tiling;
- img_fmt_info.usage = props->usage ? props->usage : VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
- memset(&img_fmt_props, 0, sizeof img_fmt_props);
- img_fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
+ for (i = 0; i < ARRAY_SIZE(all_flags); i++) {
+ img_fmt_info.usage = all_flags[i];
+ if (vkGetPhysicalDeviceImageFormatProperties2(ctx->pdev,
+ &img_fmt_info,
+ &img_fmt_props) == VK_SUCCESS) {
+ flags |= all_flags[i];
+ }
+ }
+
+ /* usage can't be null */
+ if (flags) {
+ img_fmt_info.usage = flags;
+ }
+ else {
+ fprintf(stderr, "Unsupported Vulkan format properties: usage.\n");
+ return false;
+ }
if (vkGetPhysicalDeviceImageFormatProperties2
(ctx->pdev, &img_fmt_info, &img_fmt_props) != VK_SUCCESS) {
"Unsupported Vulkan format properties.\n");
return false;
}
+ props->usage = flags;
+
+ if (props->need_export &&
+ !(ext_img_fmt_props.externalMemoryProperties.externalMemoryFeatures
+ & export_feature_flags)) {
+ fprintf(stderr, "Unsupported Vulkan external memory features.\n");
+ return false;
+ }
return true;
}
+/* exposed Vulkan functions */
+
bool
vk_init_ctx(struct vk_ctx *ctx)
{
return false;
}
- if ((ctx->cache = create_pipeline_cache(ctx->dev)) == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to create pipeline cache.\n");
- goto fail;
- }
-
if ((ctx->cmd_pool = create_cmd_pool(ctx)) == VK_NULL_HANDLE) {
fprintf(stderr, "Failed to create command pool.\n");
goto fail;
}
if ((ctx->cmd_buf = create_cmd_buf(ctx->dev, ctx->cmd_pool)) ==
- VK_NULL_HANDLE) {
+ VK_NULL_HANDLE) {
fprintf(stderr, "Failed to create command buffer.\n");
goto fail;
}
void
vk_cleanup_ctx(struct vk_ctx *ctx)
{
- if (ctx->cmd_buf != VK_NULL_HANDLE)
+ if (ctx->cmd_buf != VK_NULL_HANDLE) {
+ vkResetCommandBuffer(ctx->cmd_buf,
+ VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
vkFreeCommandBuffers(ctx->dev, ctx->cmd_pool, 1, &ctx->cmd_buf);
+ ctx->cmd_buf = VK_NULL_HANDLE;
+ }
- if (ctx->cmd_pool != VK_NULL_HANDLE)
+ if (ctx->cmd_pool != VK_NULL_HANDLE) {
+ vkResetCommandPool(ctx->dev, ctx->cmd_pool,
+ VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, 0);
+ ctx->cmd_pool = VK_NULL_HANDLE;
+ }
- if (ctx->cache != VK_NULL_HANDLE)
- vkDestroyPipelineCache(ctx->dev, ctx->cache, 0);
-
- if (ctx->dev != VK_NULL_HANDLE)
+ if (ctx->dev != VK_NULL_HANDLE) {
vkDestroyDevice(ctx->dev, 0);
+ ctx->dev = VK_NULL_HANDLE;
+ }
- if (ctx->inst != VK_NULL_HANDLE)
+ if (ctx->inst != VK_NULL_HANDLE) {
vkDestroyInstance(ctx->inst, 0);
+ ctx->inst = VK_NULL_HANDLE;
+ }
}
bool
img_info.extent.height = props->h;
img_info.extent.depth = props->depth;
img_info.mipLevels = props->num_levels ? props->num_levels : 1;
- img_info.arrayLayers = props->num_layers ? props->num_layers : VK_SAMPLE_COUNT_1_BIT;
+ img_info.arrayLayers = props->num_layers ?
+ props->num_layers : VK_SAMPLE_COUNT_1_BIT;
img_info.samples = get_num_samples(props->num_samples);
img_info.tiling = props->tiling;
- img_info.usage = props->usage ? props->usage : VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ img_info.usage = props->usage ?
+ props->usage : VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
}
bool
+vk_create_ext_image(struct vk_ctx *ctx,
+ struct vk_image_props *props, struct vk_image_obj *img)
+{
+ VkExternalMemoryImageCreateInfo ext_img_info;
+ VkImageCreateInfo img_info;
+
+ memset(&ext_img_info, 0, sizeof ext_img_info);
+ ext_img_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
+ ext_img_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ memset(&img_info, 0, sizeof img_info);
+ img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ img_info.pNext = &ext_img_info;
+ img_info.imageType = get_image_type(props->h, props->depth);
+ img_info.format = props->format;
+ img_info.extent.width = props->w;
+ img_info.extent.height = props->h;
+ img_info.extent.depth = props->depth;
+ img_info.mipLevels = props->num_levels ? props->num_levels : 1;
+ img_info.arrayLayers = props->num_layers ? props->num_layers : VK_SAMPLE_COUNT_1_BIT;
+ img_info.samples = get_num_samples(props->num_samples);
+ img_info.tiling = props->tiling;
+ img_info.usage = props->usage;
+ img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ /* issue 17 of EXT_external_objects
+ * Required in OpenGL implementations that support
+ * ARB_texture_view, OES_texture_view, EXT_texture_view,
+ * or OpenGL 4.3 and above.
+ */
+ img_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+ if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
+ goto fail;
+
+ if(!alloc_image_memory(ctx, img))
+ goto fail;
+
+ return true;
+
+fail:
+ fprintf(stderr, "Failed to create external image.\n");
+ vk_destroy_image(ctx, img);
+ img->img = VK_NULL_HANDLE;
+ img->mobj.mem = VK_NULL_HANDLE;
+ return false;
+}
+
+bool
vk_fill_ext_image_props(struct vk_ctx *ctx,
- uint32_t w,
- uint32_t h,
- uint32_t d,
- uint32_t num_samples,
- uint32_t num_levels,
- uint32_t num_layers,
- VkFormat format,
- VkImageTiling tiling,
- VkImageUsageFlagBits usage,
- VkImageLayout in_layout,
- VkImageLayout end_layout,
- struct vk_image_props *props)
+ uint32_t w,
+ uint32_t h,
+ uint32_t d,
+ uint32_t num_samples,
+ uint32_t num_levels,
+ uint32_t num_layers,
+ VkFormat format,
+ VkImageTiling tiling,
+ VkImageLayout in_layout,
+ VkImageLayout end_layout,
+ bool need_export,
+ struct vk_image_props *props)
{
props->w = w;
props->h = h;
props->num_layers = num_layers;
props->format = format;
- props->usage = usage;
props->tiling = tiling;
props->in_layout = in_layout;
props->end_layout = end_layout;
+ props->need_export = need_export;
if (!are_props_supported(ctx, props))
return false;
bool
vk_create_renderer(struct vk_ctx *ctx,
- const char *vs_src,
- unsigned int vs_size,
- const char *fs_src,
- unsigned int fs_size,
- bool enable_depth,
- bool enable_stencil,
- struct vk_image_att *color_att,
- struct vk_image_att *depth_att,
- struct vk_vertex_info *vert_info,
- struct vk_renderer *renderer)
+ const char *vs_src,
+ unsigned int vs_size,
+ const char *fs_src,
+ unsigned int fs_size,
+ bool enable_depth,
+ bool enable_stencil,
+ struct vk_image_att *color_att,
+ struct vk_image_att *depth_att,
+ struct vk_vertex_info *vert_info,
+ struct vk_renderer *renderer)
{
memset(&renderer->vertex_info, 0, sizeof renderer->vertex_info);
if (vert_info)
renderer->vertex_info = *vert_info;
- renderer->renderpass = create_renderpass(ctx, &color_att->props, &depth_att->props);
+ renderer->renderpass = create_renderpass(ctx, &color_att->props,
+ &depth_att->props);
if (renderer->renderpass == VK_NULL_HANDLE)
goto fail;
goto fail;
create_pipeline(ctx, color_att->props.w, color_att->props.h,
- color_att->props.num_samples, enable_depth, enable_stencil, renderer);
+ color_att->props.num_samples, enable_depth,
+ enable_stencil, renderer);
if (renderer->pipeline == VK_NULL_HANDLE)
goto fail;
void
vk_destroy_renderer(struct vk_ctx *ctx,
- struct vk_renderer *renderer)
+ struct vk_renderer *renderer)
{
- if (renderer->renderpass != VK_NULL_HANDLE)
+ if (renderer->renderpass != VK_NULL_HANDLE) {
vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
+ renderer->renderpass = VK_NULL_HANDLE;
+ }
- if (renderer->vs != VK_NULL_HANDLE)
+ if (renderer->vs != VK_NULL_HANDLE) {
vkDestroyShaderModule(ctx->dev, renderer->vs, 0);
+ renderer->vs = VK_NULL_HANDLE;
+ }
- if (renderer->fs != VK_NULL_HANDLE)
+ if (renderer->fs != VK_NULL_HANDLE) {
vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
+ renderer->fs = VK_NULL_HANDLE;
+ }
- if (renderer->pipeline != VK_NULL_HANDLE)
- vkDestroyPipeline(ctx->dev, renderer->pipeline, 0);
-
- if (renderer->fb != VK_NULL_HANDLE)
+ if (renderer->fb != VK_NULL_HANDLE) {
vkDestroyFramebuffer(ctx->dev, renderer->fb, 0);
+ renderer->fb = VK_NULL_HANDLE;
+ }
- if (renderer->pipeline_layout != VK_NULL_HANDLE)
+ if (renderer->pipeline != VK_NULL_HANDLE) {
+ vkDestroyPipeline(ctx->dev, renderer->pipeline, 0);
+ renderer->pipeline = VK_NULL_HANDLE;
+ }
+
+ if (renderer->pipeline_layout != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(ctx->dev, renderer->pipeline_layout, 0);
+ renderer->pipeline_layout = VK_NULL_HANDLE;
+ }
+}
+
+bool
+vk_create_ext_buffer(struct vk_ctx *ctx,
+ uint32_t sz,
+ VkBufferUsageFlagBits usage,
+ struct vk_buf *bo)
+{
+ VkExternalMemoryBufferCreateInfo ext_bo_info;
+
+ memset(&ext_bo_info, 0, sizeof ext_bo_info);
+ ext_bo_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
+ ext_bo_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ if (!vk_create_buffer(ctx, true, sz, usage, &ext_bo_info, bo)) {
+ fprintf(stderr, "Failed to allocate external buffer.\n");
+ return false;
+ }
+
+ return true;
}
bool
vk_create_buffer(struct vk_ctx *ctx,
+ bool is_external,
uint32_t sz,
VkBufferUsageFlagBits usage,
void *pnext,
* vkInvalidateMappedMemoryRanges are not needed to flush host
* writes to the device or make device writes visible to the
* host, respectively. */
- bo->mobj.mem = alloc_memory(ctx, &mem_reqs, VK_NULL_HANDLE, VK_NULL_HANDLE,
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+ bo->mobj.mem = alloc_memory(ctx, is_external, &mem_reqs, VK_NULL_HANDLE,
+ VK_NULL_HANDLE,
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (bo->mobj.mem == VK_NULL_HANDLE)
goto fail;
int num_vertices = vbo ? renderer->vertex_info.num_verts : 4;
vkCmdDraw(ctx->cmd_buf, num_vertices, 1, 0, 0);
+ vkCmdEndRenderPass(ctx->cmd_buf);
+ if (attachments) {
+ VkImageMemoryBarrier *barriers =
+ calloc(n_attachments, sizeof(VkImageMemoryBarrier));
+ VkImageMemoryBarrier *barrier = barriers;
+ for (uint32_t n = 0; n < n_attachments; n++, barrier++) {
+ struct vk_image_att *att = &attachments[n];
+ VkImageAspectFlagBits depth_stencil_flags =
+ get_aspect_from_depth_format(att->props.format);
+ bool is_depth = (depth_stencil_flags != 0);
+
+ /* Insert barrier to mark ownership transfer. */
+ barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier->oldLayout = is_depth ?
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
+ barrier->dstAccessMask = get_access_mask(barrier->newLayout);
+ barrier->srcQueueFamilyIndex = ctx->qfam_idx;
+ barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
+ barrier->image = att->obj.img;
+ barrier->subresourceRange.aspectMask = is_depth ?
+ depth_stencil_flags :
+ VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier->subresourceRange.baseMipLevel = 0;
+ barrier->subresourceRange.levelCount = 1;
+ barrier->subresourceRange.baseArrayLayer = 0;
+ barrier->subresourceRange.layerCount = 1;
+ }
+
+ vkCmdPipelineBarrier(ctx->cmd_buf,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ 0,
+ 0, NULL,
+ 0, NULL,
+ n_attachments, barriers);
+ free(barriers);
+ }
+
+ vkEndCommandBuffer(ctx->cmd_buf);
+
+ if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to submit queue.\n");
+ }
+
+ if (!semaphores)
+ vkQueueWaitIdle(ctx->queue);
+}
+
+void
+vk_clear_color(struct vk_ctx *ctx,
+ struct vk_buf *vbo,
+ struct vk_renderer *renderer,
+ float *vk_fb_color,
+ uint32_t vk_fb_color_count,
+ struct vk_semaphores *semaphores,
+ bool has_wait, bool has_signal,
+ struct vk_image_att *attachments,
+ uint32_t n_attachments,
+ float x, float y,
+ float w, float h)
+{
+ VkCommandBufferBeginInfo cmd_begin_info;
+ VkRenderPassBeginInfo rp_begin_info;
+ VkRect2D rp_area;
+ VkClearValue clear_values[2];
+ VkSubmitInfo submit_info;
+ VkPipelineStageFlagBits stage_flags;
+ VkImageSubresourceRange img_range;
+
+ assert(vk_fb_color_count == 4);
+
+ /* VkCommandBufferBeginInfo */
+ memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
+ cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+ /* VkRect2D render area */
+ memset(&rp_area, 0, sizeof rp_area);
+ rp_area.extent.width = (uint32_t)w;
+ rp_area.extent.height = (uint32_t)h;
+ rp_area.offset.x = x;
+ rp_area.offset.y = y;
+
+ /* VkClearValue */
+ memset(&clear_values[0], 0, sizeof clear_values[0]);
+ clear_values[0].color.float32[0] = vk_fb_color[0]; /* red */
+ clear_values[0].color.float32[1] = vk_fb_color[1]; /* green */
+ clear_values[0].color.float32[2] = vk_fb_color[2]; /* blue */
+ clear_values[0].color.float32[3] = vk_fb_color[3]; /* alpha */
+
+ memset(&clear_values[1], 0, sizeof clear_values[1]);
+ clear_values[1].depthStencil.depth = 1.0;
+ clear_values[1].depthStencil.stencil = 0;
+
+ /* VkRenderPassBeginInfo */
+ memset(&rp_begin_info, 0, sizeof rp_begin_info);
+ rp_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rp_begin_info.renderPass = renderer->renderpass;
+ rp_begin_info.framebuffer = renderer->fb;
+ rp_begin_info.renderArea = rp_area;
+ rp_begin_info.clearValueCount = 2;
+ rp_begin_info.pClearValues = clear_values;
+
+ /* VkSubmitInfo */
+ stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
+
+ memset(&submit_info, 0, sizeof submit_info);
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &ctx->cmd_buf;
+
+ /* FIXME */
+ if (has_wait) {
+ submit_info.pWaitDstStageMask = &stage_flags;
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = &semaphores->frame_done;
+ }
+
+ if (has_signal) {
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &semaphores->frame_ready;
+ }
+
+ img_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ img_range.baseMipLevel = 0;
+ img_range.levelCount = 1;
+ img_range.baseArrayLayer = 0;
+ img_range.layerCount = 1;
+
+ vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin_info);
+ vk_transition_image_layout(&attachments[0],
+ ctx->cmd_buf,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_QUEUE_FAMILY_EXTERNAL,
+ ctx->qfam_idx);
+ vkCmdClearColorImage(ctx->cmd_buf,
+ attachments[0].obj.img,
+ VK_IMAGE_LAYOUT_GENERAL,
+ &clear_values[0].color,
+ 1,
+ &img_range);
+
+ vkCmdBeginRenderPass(ctx->cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
+
+ viewport.x = x;
+ viewport.y = y;
+ viewport.width = w;
+ viewport.height = h;
+
+ scissor.offset.x = x;
+ scissor.offset.y = y;
+ scissor.extent.width = w;
+ scissor.extent.height = h;
+
+ vkCmdSetViewport(ctx->cmd_buf, 0, 1, &viewport);
+ vkCmdSetScissor(ctx->cmd_buf, 0, 1, &scissor);
+
+ vkCmdBindPipeline(ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->pipeline);
+
+ vkCmdEndRenderPass(ctx->cmd_buf);
if (attachments) {
VkImageMemoryBarrier *barriers =
calloc(n_attachments, sizeof(VkImageMemoryBarrier));
VkImageMemoryBarrier *barrier = barriers;
+
for (uint32_t n = 0; n < n_attachments; n++, barrier++) {
struct vk_image_att *att = &attachments[n];
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
+ barrier->dstAccessMask = get_access_mask(barrier->newLayout);
barrier->srcQueueFamilyIndex = ctx->qfam_idx;
barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
barrier->image = att->obj.img;
}
vkCmdPipelineBarrier(ctx->cmd_buf,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0,
0, NULL,
free(barriers);
}
- vkCmdEndRenderPass(ctx->cmd_buf);
vkEndCommandBuffer(ctx->cmd_buf);
if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
fprintf(stderr, "Failed to submit queue.\n");
}
- if (!semaphores)
+ if (!semaphores && !has_wait && !has_signal)
vkQueueWaitIdle(ctx->queue);
}
void
vk_copy_image_to_buffer(struct vk_ctx *ctx,
- struct vk_image_att *src_img,
- struct vk_buf *dst_bo,
- float w, float h)
+ struct vk_image_att *src_img,
+ struct vk_buf *dst_bo,
+ float w, float h)
{
VkCommandBufferBeginInfo cmd_begin_info;
VkSubmitInfo submit_info;
vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin_info);
if (src_img->props.end_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && dst_bo) {
vk_transition_image_layout(src_img,
- ctx->cmd_buf,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_QUEUE_FAMILY_EXTERNAL,
- ctx->qfam_idx);
+ ctx->cmd_buf,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_QUEUE_FAMILY_EXTERNAL,
+ ctx->qfam_idx);
/* copy image to buf */
VkBufferImageCopy copy_region = {
.bufferRowLength = w,
.bufferImageHeight = h,
.imageSubresource = {
- .aspectMask = aspect_mask ? aspect_mask : VK_IMAGE_ASPECT_COLOR_BIT,
+ .aspectMask = aspect_mask ? aspect_mask
+ : VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
};
vkCmdCopyImageToBuffer(ctx->cmd_buf,
- src_img->obj.img,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- dst_bo->buf, 1, ©_region);
+ src_img->obj.img,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ dst_bo->buf, 1, ©_region);
vk_transition_image_layout(src_img,
- ctx->cmd_buf,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_QUEUE_FAMILY_EXTERNAL,
- ctx->qfam_idx);
+ ctx->cmd_buf,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_QUEUE_FAMILY_EXTERNAL,
+ ctx->qfam_idx);
VkBufferMemoryBarrier write_finish_buffer_memory_barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
};
vkCmdPipelineBarrier(ctx->cmd_buf,
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_HOST_BIT,
- (VkDependencyFlags) 0, 0, NULL,
- 1, &write_finish_buffer_memory_barrier,
- 0, NULL);
- }
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_HOST_BIT,
+ (VkDependencyFlags) 0, 0, NULL,
+ 1, &write_finish_buffer_memory_barrier,
+ 0, NULL);
+ }
vkEndCommandBuffer(ctx->cmd_buf);
if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
vkQueueWaitIdle(ctx->queue);
}
+// FIXME: external
bool
vk_create_semaphores(struct vk_ctx *ctx,
struct vk_semaphores *semaphores)
barrier.srcQueueFamilyIndex = src_queue_fam_idx;
barrier.dstQueueFamilyIndex = dst_queue_fam_idx;
barrier.image = img_att->obj.img;
- barrier.subresourceRange.aspectMask = aspect_mask ? aspect_mask : VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.aspectMask = aspect_mask ? aspect_mask :
+ VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(cmd_buf,
- get_pipeline_stage_flags(old_layout),
- get_pipeline_stage_flags(new_layout),
- 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &barrier);
+ get_pipeline_stage_flags(old_layout),
+ get_pipeline_stage_flags(new_layout),
+ 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &barrier);
}