#include "vk.h"
/* static variables */
+
static VkViewport viewport;
static VkRect2D scissor;
static bool enable_layers = true;
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;
+ 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;
+ /* 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)
{
- int i;
- uint32_t num_layers;
- VkLayerProperties *layers;
- static const char *layer_names[] = {
- "VK_LAYER_KHRONOS_validation",
- };
-
- vkEnumerateInstanceLayerProperties(&num_layers, 0);
- layers = alloca(num_layers * sizeof *layers);
- vkEnumerateInstanceLayerProperties(&num_layers, layers);
-
- if (num_layers) {
- printf("Available validation layers:\n");
- for(i = 0; i < (int)num_layers; i++) {
- printf(" %s\n", layers[i].layerName);
- }
-
- info->ppEnabledLayerNames = layer_names;
- info->enabledLayerCount = sizeof layer_names / sizeof *layer_names;
- } else {
- fprintf(stderr, "Vulkan validation layers not found.\n");
- }
+ int i;
+ uint32_t num_layers;
+ VkLayerProperties *layers;
+ static const char *layer_names[] = {
+ "VK_LAYER_KHRONOS_validation",
+ };
+
+ vkEnumerateInstanceLayerProperties(&num_layers, 0);
+ layers = alloca(num_layers * sizeof *layers);
+ vkEnumerateInstanceLayerProperties(&num_layers, layers);
+
+ if (num_layers) {
+ printf("Available validation layers:\n");
+ for(i = 0; i < (int)num_layers; i++) {
+ printf(" %s\n", layers[i].layerName);
+ }
+
+ info->ppEnabledLayerNames = layer_names;
+ info->enabledLayerCount = sizeof layer_names / sizeof *layer_names;
+ } else {
+ fprintf(stderr, "Vulkan validation layers not found.\n");
+ }
}
static void
static VkInstance
create_instance(bool enable_layers)
{
- VkApplicationInfo app_info;
- VkInstanceCreateInfo inst_info;
- VkInstance inst;
+ VkApplicationInfo app_info;
+ VkInstanceCreateInfo inst_info;
+ VkInstance inst;
/* VkApplicationInfo */
- memset(&app_info, 0, sizeof app_info);
- app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- app_info.pApplicationName = "vktest";
- app_info.apiVersion = VK_API_VERSION_1_1;
+ memset(&app_info, 0, sizeof app_info);
+ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ app_info.pApplicationName = "vktest";
+ app_info.apiVersion = VK_API_VERSION_1_1;
/* VkInstanceCreateInfo */
- memset(&inst_info, 0, sizeof inst_info);
- inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- inst_info.pApplicationInfo = &app_info;
+ memset(&inst_info, 0, sizeof inst_info);
+ inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ inst_info.pApplicationInfo = &app_info;
enable_extensions(&inst_info);
- if (enable_layers) {
- enable_validation_layers(&inst_info);
+ if (enable_layers) {
+ enable_validation_layers(&inst_info);
}
- if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
- return 0;
+ if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
+ return 0;
- return inst;
+ return inst;
}
static VkPhysicalDevice
select_physical_device(VkInstance inst)
{
- VkResult res = VK_SUCCESS;
- uint32_t dev_count = 0;
- VkPhysicalDevice *pdevices;
- VkPhysicalDevice pdevice0;
+ VkResult res = VK_SUCCESS;
+ uint32_t dev_count = 0;
+ VkPhysicalDevice *pdevices;
+ VkPhysicalDevice pdevice0;
- if ((res =
- vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
- return 0;
+ if ((res =
+ vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
+ return 0;
- pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
- if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
- VK_SUCCESS)
- return 0;
+ pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
+ if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
+ VK_SUCCESS)
+ return 0;
- pdevice0 = pdevices[0];
- free(pdevices);
+ pdevice0 = pdevices[0];
+ free(pdevices);
- return pdevice0;
+ return pdevice0;
}
static VkDevice
create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
{
- const char *deviceExtensions[] = { "VK_KHR_swapchain" };
- VkDeviceQueueCreateInfo dev_queue_info;
- VkDeviceCreateInfo dev_info;
- VkDevice dev;
- uint32_t prop_count;
- VkQueueFamilyProperties *fam_props;
- uint32_t i;
- float qprio = 0;
-
- ctx->qfam_idx = -1;
- vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
- if (prop_count < 0) {
- fprintf(stderr, "Invalid queue family properties.\n");
- return 0;
- }
-
- fam_props = malloc(prop_count * sizeof *fam_props);
- vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, fam_props);
-
- for (i = 0; i < prop_count; i++) {
- if (fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
- ctx->qfam_idx = i;
- break;
- }
- }
- free(fam_props);
-
- memset(&dev_queue_info, 0, sizeof dev_queue_info);
- dev_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- dev_queue_info.queueFamilyIndex = ctx->qfam_idx;
- dev_queue_info.queueCount = 1;
- dev_queue_info.pQueuePriorities = &qprio;
-
- memset(&dev_info, 0, sizeof dev_info);
- dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- dev_info.queueCreateInfoCount = 1;
- dev_info.pQueueCreateInfos = &dev_queue_info;
- dev_info.enabledExtensionCount = ARRAY_SIZE(deviceExtensions);
- dev_info.ppEnabledExtensionNames = deviceExtensions;
-
- if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
- return 0;
-
- return dev;
+ const char *deviceExtensions[] = { "VK_KHR_swapchain" };
+ VkDeviceQueueCreateInfo dev_queue_info;
+ VkDeviceCreateInfo dev_info;
+ VkDevice dev;
+ uint32_t prop_count;
+ VkQueueFamilyProperties *fam_props;
+ uint32_t i;
+ float qprio = 0;
+
+ ctx->qfam_idx = -1;
+ vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
+ if (prop_count < 0) {
+ fprintf(stderr, "Invalid queue family properties.\n");
+ return 0;
+ }
+
+ fam_props = malloc(prop_count * sizeof *fam_props);
+ vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, fam_props);
+
+ for (i = 0; i < prop_count; i++) {
+ if (fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ ctx->qfam_idx = i;
+ break;
+ }
+ }
+ free(fam_props);
+
+ memset(&dev_queue_info, 0, sizeof dev_queue_info);
+ dev_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ dev_queue_info.queueFamilyIndex = ctx->qfam_idx;
+ dev_queue_info.queueCount = 1;
+ dev_queue_info.pQueuePriorities = &qprio;
+
+ memset(&dev_info, 0, sizeof dev_info);
+ dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ dev_info.queueCreateInfoCount = 1;
+ dev_info.pQueueCreateInfos = &dev_queue_info;
+ dev_info.enabledExtensionCount = ARRAY_SIZE(deviceExtensions);
+ dev_info.ppEnabledExtensionNames = deviceExtensions;
+
+ if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
+ return 0;
+
+ return dev;
}
static void
fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
{
- VkPhysicalDeviceIDProperties devProp;
- VkPhysicalDeviceProperties2 prop2;
+ VkPhysicalDeviceIDProperties devProp;
+ VkPhysicalDeviceProperties2 prop2;
- memset(&devProp, 0, sizeof devProp);
- devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
+ 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;
+ 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);
+ vkGetPhysicalDeviceProperties2(pdev, &prop2);
+ memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
+ memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
}
static VkCommandPool
create_cmd_pool(struct vk_ctx *ctx)
{
- VkCommandPoolCreateInfo cmd_pool_info;
- VkCommandPool cmd_pool;
- VkDevice dev = ctx->dev;
+ VkCommandPoolCreateInfo cmd_pool_info;
+ VkCommandPool cmd_pool;
+ VkDevice dev = ctx->dev;
- memset(&cmd_pool_info, 0, sizeof cmd_pool_info);
- cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- cmd_pool_info.queueFamilyIndex = ctx->qfam_idx;
- cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ memset(&cmd_pool_info, 0, sizeof cmd_pool_info);
+ cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ cmd_pool_info.queueFamilyIndex = ctx->qfam_idx;
+ cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- if (vkCreateCommandPool(dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
- return 0;
+ if (vkCreateCommandPool(dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
+ return 0;
- return cmd_pool;
+ return cmd_pool;
}
static VkRenderPass
struct vk_image_props *color_img_props,
struct vk_image_props *depth_img_props)
{
- uint32_t num_attachments = 2;
- VkAttachmentDescription att_dsc[2];
- VkAttachmentReference att_rfc[2];
- VkSubpassDescription subpass_dsc[1];
- VkRenderPassCreateInfo rpass_info;
-
- /* VkAttachmentDescription */
- memset(att_dsc, 0, num_attachments * sizeof att_dsc[0]);
-
- att_dsc[0].samples = get_num_samples(color_img_props->num_samples);
- att_dsc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- att_dsc[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- 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) {
- att_dsc[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- 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;
-
- /* VkAttachmentReference */
- memset(att_rfc, 0, num_attachments * sizeof att_rfc[0]);
-
- att_rfc[0].layout = color_img_props->tiling == VK_IMAGE_TILING_OPTIMAL ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL;
- att_rfc[0].attachment = 0;
-
- att_rfc[1].layout = depth_img_props->tiling == VK_IMAGE_TILING_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL;
- att_rfc[1].attachment = 1;
-
- /* VkSubpassDescription */
- memset(&subpass_dsc, 0, sizeof subpass_dsc);
- subpass_dsc[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass_dsc[0].colorAttachmentCount = 1;
- subpass_dsc[0].pColorAttachments = &att_rfc[0];
- subpass_dsc[0].pDepthStencilAttachment = &att_rfc[1];
-
- /* VkRenderPassCreateInfo */
- memset(&rpass_info, 0, sizeof rpass_info);
- rpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- rpass_info.attachmentCount = num_attachments;
- rpass_info.pAttachments = att_dsc;
- rpass_info.subpassCount = 1;
- rpass_info.pSubpasses = subpass_dsc;
-
- VkRenderPass rpass;
- if (vkCreateRenderPass(ctx->dev, &rpass_info, 0, &rpass) != VK_SUCCESS) {
- fprintf(stderr, "Failed to create renderpass.\n");
- rpass = VK_NULL_HANDLE;
- }
-
- return rpass;
+ uint32_t num_attachments = 2;
+ VkAttachmentDescription att_dsc[2];
+ VkAttachmentReference att_rfc[2];
+ VkSubpassDescription subpass_dsc[1];
+ VkRenderPassCreateInfo rpass_info;
+
+ /* VkAttachmentDescription */
+ memset(att_dsc, 0, num_attachments * sizeof att_dsc[0]);
+
+ att_dsc[0].samples = get_num_samples(color_img_props->num_samples);
+ att_dsc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ att_dsc[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ 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) {
+ att_dsc[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ 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;
+
+ /* VkAttachmentReference */
+ memset(att_rfc, 0, num_attachments * sizeof att_rfc[0]);
+
+ att_rfc[0].layout = color_img_props->tiling == VK_IMAGE_TILING_OPTIMAL ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL;
+ att_rfc[0].attachment = 0;
+
+ att_rfc[1].layout = depth_img_props->tiling == VK_IMAGE_TILING_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL;
+ att_rfc[1].attachment = 1;
+
+ /* VkSubpassDescription */
+ memset(&subpass_dsc, 0, sizeof subpass_dsc);
+ subpass_dsc[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass_dsc[0].colorAttachmentCount = 1;
+ subpass_dsc[0].pColorAttachments = &att_rfc[0];
+ subpass_dsc[0].pDepthStencilAttachment = &att_rfc[1];
+
+ /* VkRenderPassCreateInfo */
+ memset(&rpass_info, 0, sizeof rpass_info);
+ rpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rpass_info.attachmentCount = num_attachments;
+ rpass_info.pAttachments = att_dsc;
+ rpass_info.subpassCount = 1;
+ rpass_info.pSubpasses = subpass_dsc;
+
+ VkRenderPass rpass;
+ if (vkCreateRenderPass(ctx->dev, &rpass_info, 0, &rpass) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create renderpass.\n");
+ rpass = VK_NULL_HANDLE;
+ }
+
+ return rpass;
}
static inline VkImageType
get_image_type(uint32_t h, uint32_t d)
{
- if (h == 1)
- return VK_IMAGE_TYPE_1D;
+ if (h == 1)
+ return VK_IMAGE_TYPE_1D;
- if (d > 1)
- return VK_IMAGE_TYPE_3D;
+ if (d > 1)
+ return VK_IMAGE_TYPE_3D;
- return VK_IMAGE_TYPE_2D;
+ return VK_IMAGE_TYPE_2D;
}
static VkImageViewType
get_image_view_type(struct vk_image_props *props)
{
- VkImageType type = get_image_type(props->h, props->depth);
- switch(type) {
- case VK_IMAGE_TYPE_1D:
- return props->num_layers > 1 ?
- VK_IMAGE_VIEW_TYPE_1D_ARRAY :
- VK_IMAGE_VIEW_TYPE_1D;
- case VK_IMAGE_TYPE_2D:
- if (props->num_layers == 1)
- return VK_IMAGE_VIEW_TYPE_2D;
- if (props->num_layers == 6)
- return VK_IMAGE_VIEW_TYPE_CUBE;
- if (props->num_layers % 6 == 0)
- return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
- if (props->num_layers > 1)
- return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
- case VK_IMAGE_TYPE_3D:
- if (props->num_layers == 1)
- return VK_IMAGE_VIEW_TYPE_3D;
- if ((props->num_layers == 1) &&
- (props->num_levels == 1))
- return VK_IMAGE_VIEW_TYPE_2D;
- if ((props->num_levels == 1) &&
- (props->num_layers > 1))
- return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
- default:
- return VK_IMAGE_VIEW_TYPE_2D;
- }
+ VkImageType type = get_image_type(props->h, props->depth);
+ switch(type) {
+ case VK_IMAGE_TYPE_1D:
+ return props->num_layers > 1 ?
+ VK_IMAGE_VIEW_TYPE_1D_ARRAY :
+ VK_IMAGE_VIEW_TYPE_1D;
+ case VK_IMAGE_TYPE_2D:
+ if (props->num_layers == 1)
+ return VK_IMAGE_VIEW_TYPE_2D;
+ if (props->num_layers == 6)
+ return VK_IMAGE_VIEW_TYPE_CUBE;
+ if (props->num_layers % 6 == 0)
+ return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+ if (props->num_layers > 1)
+ return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ case VK_IMAGE_TYPE_3D:
+ if (props->num_layers == 1)
+ return VK_IMAGE_VIEW_TYPE_3D;
+ if ((props->num_layers == 1) &&
+ (props->num_levels == 1))
+ return VK_IMAGE_VIEW_TYPE_2D;
+ if ((props->num_levels == 1) &&
+ (props->num_layers > 1))
+ return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ default:
+ return VK_IMAGE_VIEW_TYPE_2D;
+ }
}
static VkImageAspectFlagBits
get_aspect_from_depth_format(VkFormat depth_format)
{
- switch (depth_format) {
- case VK_FORMAT_D16_UNORM:
- case VK_FORMAT_X8_D24_UNORM_PACK32:
- case VK_FORMAT_D32_SFLOAT:
- return VK_IMAGE_ASPECT_DEPTH_BIT;
- case VK_FORMAT_S8_UINT:
- return VK_IMAGE_ASPECT_STENCIL_BIT;
- case VK_FORMAT_D16_UNORM_S8_UINT:
- case VK_FORMAT_D24_UNORM_S8_UINT:
- case VK_FORMAT_D32_SFLOAT_S8_UINT:
- return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
- default:
- break;
- }
- return 0;
+ switch (depth_format) {
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ case VK_FORMAT_D32_SFLOAT:
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+ case VK_FORMAT_S8_UINT:
+ return VK_IMAGE_ASPECT_STENCIL_BIT;
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ default:
+ break;
+ }
+ return 0;
}
static VkPipelineStageFlags
get_pipeline_stage_flags(const VkImageLayout layout)
{
- switch (layout) {
- case VK_IMAGE_LAYOUT_UNDEFINED:
- return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- case VK_IMAGE_LAYOUT_GENERAL:
- return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- return VK_PIPELINE_STAGE_HOST_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_PIPELINE_STAGE_TRANSFER_BIT;
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
- return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
- VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- default:
+ switch (layout) {
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ case VK_IMAGE_LAYOUT_GENERAL:
+ return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return VK_PIPELINE_STAGE_HOST_BIT;
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ default:
break;
- }
- return 0;
+ }
+ return 0;
+}
+
+static bool
+create_image_view(struct vk_ctx *ctx,
+ VkImage image,
+ VkImageViewType view_type,
+ VkFormat format,
+ VkImageSubresourceRange sr,
+ bool is_swapchain,
+ VkImageView *image_view)
+{
+ VkImageViewCreateInfo info;
+
+ memset(&info, 0, sizeof info);
+ info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ info.image = image;
+ info.viewType = view_type;
+ info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ info.format = format;
+ info.subresourceRange = sr;
+
+ if (is_swapchain) {
+ info.components.r = VK_COMPONENT_SWIZZLE_R;
+ info.components.g = VK_COMPONENT_SWIZZLE_G;
+ info.components.b = VK_COMPONENT_SWIZZLE_B;
+ info.components.a = VK_COMPONENT_SWIZZLE_A;
+ }
+
+ if (vkCreateImageView(ctx->dev, &info, 0, image_view) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create image view.\n");
+ image_view = VK_NULL_HANDLE;
+
+ return false;
+ }
+
+ return true;
}
static void
create_framebuffer(struct vk_ctx *ctx,
- struct vk_image_att *color_att,
- struct vk_image_att *depth_att,
- struct vk_renderer *renderer)
+ struct vk_image_att *color_att,
+ struct vk_image_att *depth_att,
+ struct vk_renderer *renderer)
{
- VkImageSubresourceRange sr;
- VkImageViewCreateInfo color_info;
- VkImageViewCreateInfo depth_info;
- VkFramebufferCreateInfo fb_info;
- VkImageView atts[2];
- VkImageViewType view_type = get_image_view_type(&color_att->props);
-
- if (!color_att->obj.img || !depth_att->obj.img) {
- fprintf(stderr, "Invalid framebuffer attachment image.\n");
- goto fail;
- }
-
- /* create image views */
-
- /* VKImageSubresourceRange */
- memset(&sr, 0, sizeof sr);
- sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- /* If an application wants to use all mip levels
- * or layers in an image after the baseMipLevel
- * or baseArrayLayer, it can set levelCount and
- * layerCount to the special values
- * VK_REMAINING_MIP_LEVELS and
- * VK_REMAINING_ARRAY_LAYERS without knowing the
- * exact number of mip levels or layers.
- */
- sr.baseMipLevel = 0;
- sr.levelCount = color_att->props.num_levels;
- sr.baseArrayLayer = 0;
- sr.layerCount = color_att->props.num_layers;
-
- /* color view */
- memset(&color_info, 0, sizeof color_info);
- color_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- color_info.image = color_att->obj.img;
- color_info.viewType = view_type;
- color_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- color_info.format = color_att->props.format;
- color_info.subresourceRange = sr;
-
- 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 view */
- memset(&sr, 0, sizeof sr);
- sr.aspectMask = get_aspect_from_depth_format(depth_att->props.format);
- sr.baseMipLevel = 0;
- sr.levelCount = depth_att->props.num_levels ? depth_att->props.num_levels : 1;
- sr.baseArrayLayer = 0;
- sr.layerCount = depth_att->props.num_layers ? depth_att->props.num_layers : 1;
-
- memset(&depth_info, 0, sizeof depth_info);
- depth_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- depth_info.image = depth_att->obj.img;
- depth_info.viewType = depth_att->props.num_layers > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
- depth_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- depth_info.format = depth_att->props.format;
- depth_info.subresourceRange = sr;
-
- 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;
- }
+ VkImageSubresourceRange sr;
+ VkFramebufferCreateInfo fb_info;
+ VkImageView atts[2];
+ VkImageViewType view_type = get_image_view_type(&color_att->props);
+
+ if (!color_att->obj.img || !depth_att->obj.img) {
+ fprintf(stderr, "Invalid framebuffer attachment image.\n");
+ goto fail;
+ }
+
+ /* create image views */
+
+ /* VKImageSubresourceRange */
+ memset(&sr, 0, sizeof sr);
+ sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ /* If an application wants to use all mip levels
+ * or layers in an image after the baseMipLevel
+ * or baseArrayLayer, it can set levelCount and
+ * layerCount to the special values
+ * VK_REMAINING_MIP_LEVELS and
+ * VK_REMAINING_ARRAY_LAYERS without knowing the
+ * exact number of mip levels or layers.
+ */
+ sr.baseMipLevel = 0;
+ sr.levelCount = color_att->props.num_levels;
+ sr.baseArrayLayer = 0;
+ sr.layerCount = color_att->props.num_layers;
+
+ /* color view */
+ if (!create_image_view(ctx, color_att->obj.img, view_type, color_att->props.format, sr, false, &color_att->obj.img_view)) {
+ fprintf(stderr, "Failed to create color image view for framebuffer.\n");
+ vk_destroy_image(ctx, &color_att->obj);
+ goto fail;
+ }
+
+ /* depth view */
+ memset(&sr, 0, sizeof sr);
+ sr.aspectMask = get_aspect_from_depth_format(depth_att->props.format);
+ sr.baseMipLevel = 0;
+ sr.levelCount = depth_att->props.num_levels ? depth_att->props.num_levels : 1;
+ sr.baseArrayLayer = 0;
+ sr.layerCount = depth_att->props.num_layers ? depth_att->props.num_layers : 1;
+
+ if (!create_image_view(ctx, depth_att->obj.img,
+ depth_att->props.num_layers > 1 ?
+ VK_IMAGE_VIEW_TYPE_2D_ARRAY :
+ VK_IMAGE_VIEW_TYPE_2D,
+ depth_att->props.format,
+ sr,
+ false,
+ &depth_att->obj.img_view)) {
+ 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;
+ 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;
- fb_info.width = color_att->props.w;
- fb_info.height = color_att->props.h;
- fb_info.layers = color_att->props.num_layers ? color_att->props.num_layers : 1;
- fb_info.attachmentCount = 2;
- fb_info.pAttachments = atts;
+ memset(&fb_info, 0, sizeof fb_info);
+ fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fb_info.renderPass = renderer->renderpass;
+ fb_info.width = color_att->props.w;
+ fb_info.height = color_att->props.h;
+ fb_info.layers = color_att->props.num_layers ? color_att->props.num_layers : 1;
+ fb_info.attachmentCount = 2;
+ fb_info.pAttachments = atts;
- if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, &renderer->fb) != VK_SUCCESS)
- goto fail;
+ if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, &renderer->fb) != VK_SUCCESS)
+ goto fail;
- return;
+ return;
fail:
- fprintf(stderr, "Failed to create framebuffer.\n");
- renderer->fb = VK_NULL_HANDLE;
+ fprintf(stderr, "Failed to create framebuffer.\n");
+ renderer->fb = VK_NULL_HANDLE;
}
static VkShaderModule
create_shader_module(struct vk_ctx *ctx,
- const char *src,
- unsigned int size)
+ const char *src,
+ unsigned int size)
{
- VkShaderModuleCreateInfo sm_info;
- VkShaderModule sm;
-
- /* VkShaderModuleCreateInfo */
- memset(&sm_info, 0, sizeof sm_info);
- sm_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- sm_info.codeSize = size;
- sm_info.pCode = (void*)src;
-
- if (vkCreateShaderModule(ctx->dev, &sm_info, 0, &sm) != VK_SUCCESS) {
- fprintf(stderr, "Failed to create shader module.\n");
- sm = VK_NULL_HANDLE;
- }
+ VkShaderModuleCreateInfo sm_info;
+ VkShaderModule sm;
+
+ /* VkShaderModuleCreateInfo */
+ memset(&sm_info, 0, sizeof sm_info);
+ sm_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ sm_info.codeSize = size;
+ sm_info.pCode = (void*)src;
+
+ if (vkCreateShaderModule(ctx->dev, &sm_info, 0, &sm) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create shader module.\n");
+ sm = VK_NULL_HANDLE;
+ }
- return sm;
+ return sm;
}
static void
bool enable_stencil,
struct vk_renderer *renderer)
{
- VkVertexInputBindingDescription vert_bind_dsc[1];
- VkVertexInputAttributeDescription vert_att_dsc[1];
-
- VkPipelineColorBlendAttachmentState cb_att_state[1];
- VkPipelineVertexInputStateCreateInfo vert_input_info;
- VkPipelineInputAssemblyStateCreateInfo asm_info;
- VkPipelineViewportStateCreateInfo viewport_info;
- VkPipelineRasterizationStateCreateInfo rs_info;
- VkPipelineMultisampleStateCreateInfo ms_info;
- VkPipelineDepthStencilStateCreateInfo ds_info;
- VkPipelineColorBlendStateCreateInfo cb_info;
- VkPipelineShaderStageCreateInfo sdr_stages[2];
- VkPipelineLayoutCreateInfo layout_info;
- VkGraphicsPipelineCreateInfo pipeline_info;
- VkFormat format;
- VkFormatProperties fmt_props;
- VkPushConstantRange pc_range[1];
-
- VkStencilOpState front;
- VkStencilOpState back;
- int i;
- VkPipelineLayout pipeline_layout;
- uint32_t stride;
-
- /* format of vertex attributes:
- * we have 2D vectors so we need a RG format:
- * R for x, G for y
- * the stride (distance between 2 consecutive elements)
- * must be 8 because we use 32 bit floats and
- * 32bits = 8bytes */
- format = VK_FORMAT_R32G32_SFLOAT;
- vkGetPhysicalDeviceFormatProperties(ctx->pdev, format, &fmt_props);
- assert(fmt_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
- stride = 8;
-
- /* VkVertexInputAttributeDescription */
- memset(&vert_att_dsc, 0, sizeof vert_att_dsc);
- vert_att_dsc[0].location = 0;
- vert_att_dsc[0].binding = 0;
- vert_att_dsc[0].format = format; /* see comment */
- vert_att_dsc[0].offset = 0;
-
- /* VkVertexInputBindingDescription */
- memset(&vert_bind_dsc, 0, sizeof vert_bind_dsc);
- vert_bind_dsc[0].binding = 0;
- vert_bind_dsc[0].stride = stride;
- vert_bind_dsc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+ VkVertexInputBindingDescription vert_bind_dsc[1];
+ VkVertexInputAttributeDescription vert_att_dsc[1];
+
+ VkPipelineColorBlendAttachmentState cb_att_state[1];
+ VkPipelineVertexInputStateCreateInfo vert_input_info;
+ VkPipelineInputAssemblyStateCreateInfo asm_info;
+ VkPipelineViewportStateCreateInfo viewport_info;
+ VkPipelineRasterizationStateCreateInfo rs_info;
+ VkPipelineMultisampleStateCreateInfo ms_info;
+ VkPipelineDepthStencilStateCreateInfo ds_info;
+ VkPipelineColorBlendStateCreateInfo cb_info;
+ VkPipelineShaderStageCreateInfo sdr_stages[2];
+ VkPipelineLayoutCreateInfo layout_info;
+ VkGraphicsPipelineCreateInfo pipeline_info;
+ VkFormat format;
+ VkFormatProperties fmt_props;
+ VkPushConstantRange pc_range[1];
+
+ VkStencilOpState front;
+ VkStencilOpState back;
+ int i;
+ VkPipelineLayout pipeline_layout;
+ uint32_t stride;
+
+ /* format of vertex attributes:
+ * we have 2D vectors so we need a RG format:
+ * R for x, G for y
+ * the stride (distance between 2 consecutive elements)
+ * must be 8 because we use 32 bit floats and
+ * 32bits = 8bytes */
+ format = VK_FORMAT_R32G32_SFLOAT;
+ vkGetPhysicalDeviceFormatProperties(ctx->pdev, format, &fmt_props);
+ assert(fmt_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
+ stride = 8;
+
+ /* VkVertexInputAttributeDescription */
+ memset(&vert_att_dsc, 0, sizeof vert_att_dsc);
+ vert_att_dsc[0].location = 0;
+ vert_att_dsc[0].binding = 0;
+ vert_att_dsc[0].format = format; /* see comment */
+ vert_att_dsc[0].offset = 0;
+
+ /* VkVertexInputBindingDescription */
+ memset(&vert_bind_dsc, 0, sizeof vert_bind_dsc);
+ vert_bind_dsc[0].binding = 0;
+ 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 = use_vbo ? 1 : 0;
- vert_input_info.pVertexBindingDescriptions = vert_bind_dsc;
- 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 ?
+ 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 = use_vbo ? 1 : 0;
+ vert_input_info.pVertexBindingDescriptions = vert_bind_dsc;
+ 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;
- asm_info.primitiveRestartEnable = false;
-
- /* VkViewport */
- viewport.x = viewport.y = 0;
- viewport.width = width;
- viewport.height = height;
- viewport.minDepth = 0;
- viewport.maxDepth = 1;
-
- /* VkRect2D scissor */
- scissor.offset.x = scissor.offset.y = 0;
- scissor.extent.width = width;
- scissor.extent.height = height;
-
- /* VkPipelineViewportStateCreateInfo */
- memset(&viewport_info, 0, sizeof viewport_info);
- viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewport_info.viewportCount = 1;
- viewport_info.pViewports = &viewport;
- viewport_info.scissorCount = 1;
- viewport_info.pScissors = &scissor;
-
- /* VkPipelineRasterizationStateCreateInfo */
- memset(&rs_info, 0, sizeof rs_info);
- rs_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rs_info.polygonMode = VK_POLYGON_MODE_FILL;
- rs_info.cullMode = VK_CULL_MODE_NONE;
- rs_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
- rs_info.lineWidth = 1.0;
-
- /* VkPipelineMultisampleStateCreateInfo */
- memset(&ms_info, 0, sizeof ms_info);
- ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- ms_info.rasterizationSamples = num_samples;
-
- /* VkStencilOpState */
- /* The default values for ES are taken by Topi Pohjolainen's code */
- /* defaults in OpenGL ES 3.1 */
- memset(&front, 0, sizeof front);
- front.compareMask = ~0;
- front.writeMask = ~0;
- front.reference = 0;
-
- memset(&back, 0, sizeof back);
- back.compareMask = ~0;
- back.writeMask = ~0;
- back.reference = 0;
-
- /* VkPipelineDepthStencilStateCreateInfo */
- memset(&ds_info, 0, sizeof ds_info);
- ds_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- ds_info.front = front;
- ds_info.back = back;
- /* defaults in OpenGL ES 3.1 */
- ds_info.minDepthBounds = 0;
- ds_info.maxDepthBounds = 1;
- /* z buffer, stencil buffer */
- if (enable_depth) {
- ds_info.depthTestEnable = VK_TRUE;
- ds_info.depthWriteEnable = VK_TRUE;
- ds_info.depthCompareOp = VK_COMPARE_OP_LESS;
- }
- if (enable_stencil) {
- ds_info.stencilTestEnable = VK_TRUE;
- ds_info.depthTestEnable = VK_FALSE;
- ds_info.depthWriteEnable = VK_TRUE;
- }
-
- /* we only care about the passOp here */
- ds_info.back.compareOp = VK_COMPARE_OP_ALWAYS;
- ds_info.back.failOp = VK_STENCIL_OP_REPLACE;
- ds_info.back.depthFailOp = VK_STENCIL_OP_REPLACE;
- ds_info.back.passOp = VK_STENCIL_OP_REPLACE;
- ds_info.back.compareMask = 0xffffffff;
- ds_info.back.writeMask = 0xffffffff;
- ds_info.back.reference = 1;
- ds_info.front = ds_info.back;
-
- /* VkPipelineColorBlendAttachmentState */
- memset(&cb_att_state[0], 0, sizeof cb_att_state[0]);
- cb_att_state[0].colorWriteMask = (VK_COLOR_COMPONENT_R_BIT |
+ asm_info.primitiveRestartEnable = false;
+
+ /* VkViewport */
+ viewport.x = viewport.y = 0;
+ viewport.width = width;
+ viewport.height = height;
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+
+ /* VkRect2D scissor */
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = width;
+ scissor.extent.height = height;
+
+ /* VkPipelineViewportStateCreateInfo */
+ memset(&viewport_info, 0, sizeof viewport_info);
+ viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ viewport_info.viewportCount = 1;
+ viewport_info.pViewports = &viewport;
+ viewport_info.scissorCount = 1;
+ viewport_info.pScissors = &scissor;
+
+ /* VkPipelineRasterizationStateCreateInfo */
+ memset(&rs_info, 0, sizeof rs_info);
+ rs_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs_info.polygonMode = VK_POLYGON_MODE_FILL;
+ rs_info.cullMode = VK_CULL_MODE_NONE;
+ rs_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rs_info.lineWidth = 1.0;
+
+ /* VkPipelineMultisampleStateCreateInfo */
+ memset(&ms_info, 0, sizeof ms_info);
+ ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms_info.rasterizationSamples = num_samples;
+
+ /* VkStencilOpState */
+ /* The default values for ES are taken by Topi Pohjolainen's code */
+ /* defaults in OpenGL ES 3.1 */
+ memset(&front, 0, sizeof front);
+ front.compareMask = ~0;
+ front.writeMask = ~0;
+ front.reference = 0;
+
+ memset(&back, 0, sizeof back);
+ back.compareMask = ~0;
+ back.writeMask = ~0;
+ back.reference = 0;
+
+ /* VkPipelineDepthStencilStateCreateInfo */
+ memset(&ds_info, 0, sizeof ds_info);
+ ds_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds_info.front = front;
+ ds_info.back = back;
+ /* defaults in OpenGL ES 3.1 */
+ ds_info.minDepthBounds = 0;
+ ds_info.maxDepthBounds = 1;
+ /* z buffer, stencil buffer */
+ if (enable_depth) {
+ ds_info.depthTestEnable = VK_TRUE;
+ ds_info.depthWriteEnable = VK_TRUE;
+ ds_info.depthCompareOp = VK_COMPARE_OP_LESS;
+ }
+ if (enable_stencil) {
+ ds_info.stencilTestEnable = VK_TRUE;
+ ds_info.depthTestEnable = VK_FALSE;
+ ds_info.depthWriteEnable = VK_TRUE;
+ }
+
+ /* we only care about the passOp here */
+ ds_info.back.compareOp = VK_COMPARE_OP_ALWAYS;
+ ds_info.back.failOp = VK_STENCIL_OP_REPLACE;
+ ds_info.back.depthFailOp = VK_STENCIL_OP_REPLACE;
+ ds_info.back.passOp = VK_STENCIL_OP_REPLACE;
+ ds_info.back.compareMask = 0xffffffff;
+ ds_info.back.writeMask = 0xffffffff;
+ ds_info.back.reference = 1;
+ ds_info.front = ds_info.back;
+
+ /* 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);
- /* VkPipelineColorBlendStateCreateInfo */
- memset(&cb_info, 0, sizeof cb_info);
- cb_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- cb_info.attachmentCount = 1;
- cb_info.pAttachments = cb_att_state;
- /* default in ES 3.1 */
- for (i = 0; i < 4; i++) {
- cb_info.blendConstants[i] = 0.0f;
- }
-
- /* VkPipelineShaderStageCreateInfo */
- memset(sdr_stages, 0, 2 * sizeof sdr_stages[0]);
-
- sdr_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- sdr_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
- sdr_stages[0].module = renderer->vs;
- sdr_stages[0].pName = "main";
-
- sdr_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- sdr_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
- sdr_stages[1].module = renderer->fs;
- sdr_stages[1].pName = "main";
-
- /* VkPushConstantRange */
- memset(pc_range, 0, sizeof pc_range[0]);
- pc_range[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- pc_range[0].size = sizeof (struct vk_dims); /* w, h */
-
- /* VkPipelineLayoutCreateInfo */
- memset(&layout_info, 0, sizeof layout_info);
- layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- layout_info.pushConstantRangeCount = 1;
- layout_info.pPushConstantRanges = pc_range;
-
- if (vkCreatePipelineLayout(ctx->dev, &layout_info, 0, &pipeline_layout) != VK_SUCCESS) {
- fprintf(stderr, "Failed to create pipeline layout\n");
- renderer->pipeline = VK_NULL_HANDLE;
- return;
- }
-
- renderer->pipeline_layout = pipeline_layout;
-
- /* VkGraphicsPipelineCreateInfo */
- memset(&pipeline_info, 0, sizeof pipeline_info);
- pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipeline_info.layout = pipeline_layout;
- pipeline_info.renderPass = renderer->renderpass;
- pipeline_info.pVertexInputState = &vert_input_info;
- pipeline_info.pInputAssemblyState = &asm_info;
- pipeline_info.pViewportState = &viewport_info;
- pipeline_info.pRasterizationState = &rs_info;
- pipeline_info.pMultisampleState = &ms_info;
- pipeline_info.pDepthStencilState = &ds_info;
- pipeline_info.pColorBlendState = &cb_info;
- pipeline_info.stageCount = 2;
- pipeline_info.pStages = sdr_stages;
-
- if (vkCreateGraphicsPipelines(ctx->dev, 0, 1,
+ /* VkPipelineColorBlendStateCreateInfo */
+ memset(&cb_info, 0, sizeof cb_info);
+ cb_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ cb_info.attachmentCount = 1;
+ cb_info.pAttachments = cb_att_state;
+ /* default in ES 3.1 */
+ for (i = 0; i < 4; i++) {
+ cb_info.blendConstants[i] = 0.0f;
+ }
+
+ /* VkPipelineShaderStageCreateInfo */
+ memset(sdr_stages, 0, 2 * sizeof sdr_stages[0]);
+
+ sdr_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ sdr_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+ sdr_stages[0].module = renderer->vs;
+ sdr_stages[0].pName = "main";
+
+ sdr_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ sdr_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ sdr_stages[1].module = renderer->fs;
+ sdr_stages[1].pName = "main";
+
+ /* VkPushConstantRange */
+ memset(pc_range, 0, sizeof pc_range[0]);
+ pc_range[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ pc_range[0].size = sizeof (struct vk_dims); /* w, h */
+
+ /* VkPipelineLayoutCreateInfo */
+ memset(&layout_info, 0, sizeof layout_info);
+ layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ layout_info.pushConstantRangeCount = 1;
+ layout_info.pPushConstantRanges = pc_range;
+
+ if (vkCreatePipelineLayout(ctx->dev, &layout_info, 0, &pipeline_layout) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create pipeline layout\n");
+ renderer->pipeline = VK_NULL_HANDLE;
+ return;
+ }
+
+ renderer->pipeline_layout = pipeline_layout;
+
+ /* VkGraphicsPipelineCreateInfo */
+ memset(&pipeline_info, 0, sizeof pipeline_info);
+ pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ pipeline_info.layout = pipeline_layout;
+ pipeline_info.renderPass = renderer->renderpass;
+ pipeline_info.pVertexInputState = &vert_input_info;
+ pipeline_info.pInputAssemblyState = &asm_info;
+ pipeline_info.pViewportState = &viewport_info;
+ pipeline_info.pRasterizationState = &rs_info;
+ pipeline_info.pMultisampleState = &ms_info;
+ pipeline_info.pDepthStencilState = &ds_info;
+ pipeline_info.pColorBlendState = &cb_info;
+ pipeline_info.stageCount = 2;
+ pipeline_info.pStages = sdr_stages;
+
+ 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;
- }
+ fprintf(stderr, "Failed to create graphics pipeline.\n");
+ renderer->pipeline = VK_NULL_HANDLE;
+ }
}
static VkCommandBuffer
create_cmd_buf(VkDevice dev, VkCommandPool cmd_pool)
{
- VkCommandBuffer cmd_buf;
- VkCommandBufferAllocateInfo alloc_info;
+ VkCommandBuffer cmd_buf;
+ VkCommandBufferAllocateInfo alloc_info;
- memset(&alloc_info, 0, sizeof alloc_info);
- alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- alloc_info.commandBufferCount = 1;
- alloc_info.commandPool = cmd_pool;
+ memset(&alloc_info, 0, sizeof alloc_info);
+ alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ alloc_info.commandBufferCount = 1;
+ alloc_info.commandPool = cmd_pool;
- if (vkAllocateCommandBuffers(dev, &alloc_info, &cmd_buf) != VK_SUCCESS)
- return 0;
+ if (vkAllocateCommandBuffers(dev, &alloc_info, &cmd_buf) != VK_SUCCESS)
+ return 0;
- return cmd_buf;
+ return cmd_buf;
}
static uint32_t
get_memory_type_idx(VkPhysicalDevice pdev,
- const VkMemoryRequirements *mem_reqs,
- VkMemoryPropertyFlagBits prop_flags)
+ const VkMemoryRequirements *mem_reqs,
+ VkMemoryPropertyFlagBits prop_flags)
{
- VkPhysicalDeviceMemoryProperties pdev_mem_props;
- uint32_t i;
+ VkPhysicalDeviceMemoryProperties pdev_mem_props;
+ uint32_t i;
- vkGetPhysicalDeviceMemoryProperties(pdev, &pdev_mem_props);
+ vkGetPhysicalDeviceMemoryProperties(pdev, &pdev_mem_props);
- for (i = 0; i < pdev_mem_props.memoryTypeCount; i++) {
- const VkMemoryType *type = &pdev_mem_props.memoryTypes[i];
+ for (i = 0; i < pdev_mem_props.memoryTypeCount; i++) {
+ const VkMemoryType *type = &pdev_mem_props.memoryTypes[i];
- if ((mem_reqs->memoryTypeBits & (1 << i)) &&
- (type->propertyFlags & prop_flags) == prop_flags) {
- return i;
- break;
- }
- }
- return UINT32_MAX;
+ if ((mem_reqs->memoryTypeBits & (1 << i)) &&
+ (type->propertyFlags & prop_flags) == prop_flags) {
+ return i;
+ break;
+ }
+ }
+ return UINT32_MAX;
}
static VkDeviceMemory
VkBuffer buffer,
VkMemoryPropertyFlagBits prop_flags)
{
- VkExportMemoryAllocateInfo exp_mem_info;
- VkMemoryAllocateInfo mem_alloc_info;
- VkDeviceMemory mem;
- VkMemoryDedicatedAllocateInfoKHR ded_info;
+ VkExportMemoryAllocateInfo exp_mem_info;
+ VkMemoryAllocateInfo mem_alloc_info;
+ VkDeviceMemory mem;
+ VkMemoryDedicatedAllocateInfoKHR ded_info;
if (is_external) {
memset(&exp_mem_info, 0, sizeof exp_mem_info);
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;
- mem_alloc_info.pNext = &exp_mem_info;
- mem_alloc_info.allocationSize = mem_reqs->size;
- mem_alloc_info.memoryTypeIndex =
- get_memory_type_idx(ctx->pdev, mem_reqs, prop_flags);
+ memset(&mem_alloc_info, 0, sizeof mem_alloc_info);
+ mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ mem_alloc_info.pNext = &exp_mem_info;
+ mem_alloc_info.allocationSize = mem_reqs->size;
+ mem_alloc_info.memoryTypeIndex =
+ get_memory_type_idx(ctx->pdev, mem_reqs, prop_flags);
- if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
- fprintf(stderr, "No suitable memory type index found.\n");
- return 0;
- }
+ if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
+ fprintf(stderr, "No suitable memory type index found.\n");
+ return 0;
+ }
- if (image || buffer) {
- memset(&ded_info, 0, sizeof ded_info);
- ded_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
- ded_info.image = image;
- ded_info.buffer = buffer;
+ if (image || buffer) {
+ memset(&ded_info, 0, sizeof ded_info);
+ ded_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
+ ded_info.image = image;
+ ded_info.buffer = buffer;
- exp_mem_info.pNext = &ded_info;
- }
+ exp_mem_info.pNext = &ded_info;
+ }
- if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
- VK_SUCCESS)
- return 0;
+ if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
+ VK_SUCCESS)
+ return 0;
- return mem;
+ return mem;
}
static bool
alloc_image_memory(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
{
- VkMemoryDedicatedRequirements ded_reqs;
- VkImageMemoryRequirementsInfo2 req_info2;
- VkMemoryRequirements2 mem_reqs2;
+ VkMemoryDedicatedRequirements ded_reqs;
+ VkImageMemoryRequirementsInfo2 req_info2;
+ VkMemoryRequirements2 mem_reqs2;
- memset(&ded_reqs, 0, sizeof ded_reqs);
- ded_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
+ memset(&ded_reqs, 0, sizeof ded_reqs);
+ ded_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
- /* VkImageMemoryRequirementsInfo2 */
- memset(&req_info2, 0, sizeof req_info2);
- req_info2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
- req_info2.image = img_obj->img;
+ /* VkImageMemoryRequirementsInfo2 */
+ memset(&req_info2, 0, sizeof req_info2);
+ req_info2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
+ req_info2.image = img_obj->img;
- /* VkMemoryRequirements2 */
- memset(&mem_reqs2, 0, sizeof mem_reqs2);
- mem_reqs2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
- mem_reqs2.pNext = &ded_reqs;
+ /* VkMemoryRequirements2 */
+ memset(&mem_reqs2, 0, sizeof mem_reqs2);
+ mem_reqs2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
+ mem_reqs2.pNext = &ded_reqs;
- vkGetImageMemoryRequirements2(ctx->dev, &req_info2, &mem_reqs2);
- img_obj->mobj.mem = alloc_memory(ctx,
+ vkGetImageMemoryRequirements2(ctx->dev, &req_info2, &mem_reqs2);
+ img_obj->mobj.mem = alloc_memory(ctx,
true, /* is_external = FIXME */
&mem_reqs2.memoryRequirements,
ded_reqs.requiresDedicatedAllocation ?
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;
- if (img_obj->mobj.mem == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to allocate image memory.\n");
- return false;
- }
+ img_obj->mobj.mem_sz = mem_reqs2.memoryRequirements.size;
+ img_obj->mobj.dedicated = ded_reqs.requiresDedicatedAllocation;
+ if (img_obj->mobj.mem == VK_NULL_HANDLE) {
+ fprintf(stderr, "Failed to allocate image memory.\n");
+ return false;
+ }
- if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) !=
+ if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) !=
VK_SUCCESS) {
- fprintf(stderr, "Failed to bind image memory.\n");
- return false;
- }
+ fprintf(stderr, "Failed to bind image memory.\n");
+ return false;
+ }
- return true;
+ return true;
}
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 = &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;
-
- 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) {
- fprintf(stderr,
- "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;
+ 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 = &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;
+
+ 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) {
+ fprintf(stderr,
+ "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;
+}
+
+/* static swapchain / surf related functions */
+
+static bool
+sc_validate_surface(struct vk_ctx *ctx,
+ VkSurfaceKHR surf)
+{
+ VkBool32 supported;
+ if (!surf) {
+ fprintf(stderr, "No surface!\n");
+ return false;
+ }
+
+ if(vkGetPhysicalDeviceSurfaceSupportKHR(ctx->pdev, ctx->qfam_idx, surf, &supported) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to validate surface.\n");
+ return false;
+ }
+
+ if (!supported) {
+ fprintf(stderr, "Invalid surface! Check if the surface with queue family index: %d supports presentation.\n", (int)ctx->qfam_idx);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+sc_select_format(struct vk_ctx *ctx,
+ VkSurfaceKHR surf,
+ VkSwapchainCreateInfoKHR *s_info)
+{
+ VkSurfaceFormatKHR *formats;
+ uint32_t num_formats;
+
+ if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev, surf, &num_formats, 0) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to get the number of surface formats.\n");
+ return false;
+ }
+
+ if (!num_formats) {
+ fprintf(stderr, "No surface formats found.\n");
+ return false;
+ }
+
+ formats = malloc(num_formats * sizeof *formats);
+
+ if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev, surf, &num_formats, formats) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to get the supported surface formats.\n");
+ return false;
+ }
+
+ if ((num_formats == 1) && (formats[0].format == VK_FORMAT_UNDEFINED)) {
+ s_info->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
+ s_info->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ } else {
+ s_info->imageFormat = formats[0].format;
+ s_info->imageColorSpace = formats[0].colorSpace;
+ }
+ free(formats);
+
+ return true;
}
+static bool
+sc_select_supported_present_modes(struct vk_ctx *ctx,
+ VkSurfaceKHR surf,
+ bool has_vsync,
+ VkSwapchainCreateInfoKHR *s_info)
+{
+ VkPresentModeKHR *present_modes;
+ uint32_t num_present_modes;
+ int i;
+
+ /* find supported present modes */
+ if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf, &num_present_modes, 0) != VK_SUCCESS || !num_present_modes) {
+ fprintf(stderr, "Failed to get the number of the supported presentation modes.\n");
+ return false;
+ }
+
+ present_modes = malloc(num_present_modes * sizeof *present_modes);
+ if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf, &num_present_modes, present_modes) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to get the number of supported presentation modes.\n");
+ return false;
+ }
+ if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf, &num_present_modes,
+ present_modes) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to get the supported presentation modes.\n");
+ return false;
+ }
+
+ s_info->presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ if (!has_vsync) {
+ for (i = 0; i < num_present_modes; i++) {
+ if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
+ s_info->presentMode = present_modes[i];
+ goto success;
+ }
+ if (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
+ s_info->presentMode = present_modes[i];
+ goto success;
+ }
+ }
+ }
+
+success:
+ free(present_modes);
+ return true;
+}
+
+/* end of static functions */
+
/* exposed Vulkan functions */
bool
vk_init_ctx(struct vk_ctx *ctx)
{
- if ((ctx->inst = create_instance(enable_layers)) == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to create Vulkan instance.\n");
- goto fail;
- }
+ if ((ctx->inst = create_instance(enable_layers)) == VK_NULL_HANDLE) {
+ fprintf(stderr, "Failed to create Vulkan instance.\n");
+ goto fail;
+ }
- if ((ctx->pdev = select_physical_device(ctx->inst)) == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to find suitable physical device.\n");
- goto fail;
- }
+ if ((ctx->pdev = select_physical_device(ctx->inst)) == VK_NULL_HANDLE) {
+ fprintf(stderr, "Failed to find suitable physical device.\n");
+ goto fail;
+ }
- if ((ctx->dev = create_device(ctx, ctx->pdev)) == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to create Vulkan device.\n");
- goto fail;
- }
+ if ((ctx->dev = create_device(ctx, ctx->pdev)) == VK_NULL_HANDLE) {
+ fprintf(stderr, "Failed to create Vulkan device.\n");
+ goto fail;
+ }
- fill_uuid(ctx->pdev, ctx->deviceUUID, ctx->driverUUID);
- return true;
+ fill_uuid(ctx->pdev, ctx->deviceUUID, ctx->driverUUID);
+ return true;
fail:
- vk_cleanup_ctx(ctx);
- return false;
+ vk_cleanup_ctx(ctx);
+ return false;
}
bool
vk_init_ctx_for_rendering(struct vk_ctx *ctx)
{
- if (!vk_init_ctx(ctx)) {
- fprintf(stderr, "Failed to initialize Vulkan.\n");
- return false;
- }
+ if (!vk_init_ctx(ctx)) {
+ fprintf(stderr, "Failed to initialize Vulkan.\n");
+ return false;
+ }
- if ((ctx->cmd_pool = create_cmd_pool(ctx)) == VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to create command pool.\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)) ==
+ if ((ctx->cmd_buf = create_cmd_buf(ctx->dev, ctx->cmd_pool)) ==
VK_NULL_HANDLE) {
- fprintf(stderr, "Failed to create command buffer.\n");
- goto fail;
- }
+ fprintf(stderr, "Failed to create command buffer.\n");
+ goto fail;
+ }
- vkGetDeviceQueue(ctx->dev, ctx->qfam_idx, 0, &ctx->queue);
- if (!ctx->queue) {
- fprintf(stderr, "Failed to get command queue.\n");
- goto fail;
- }
+ vkGetDeviceQueue(ctx->dev, ctx->qfam_idx, 0, &ctx->queue);
+ if (!ctx->queue) {
+ fprintf(stderr, "Failed to get command queue.\n");
+ goto fail;
+ }
- return true;
+ return true;
fail:
- vk_cleanup_ctx(ctx);
- return false;
+ vk_cleanup_ctx(ctx);
+ return false;
}
void
}
if (ctx->cmd_buf != VK_NULL_HANDLE) {
- vkResetCommandBuffer(ctx->cmd_buf,
+ 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;
- }
+ vkFreeCommandBuffers(ctx->dev, ctx->cmd_pool, 1, &ctx->cmd_buf);
+ ctx->cmd_buf = VK_NULL_HANDLE;
+ }
- if (ctx->cmd_pool != VK_NULL_HANDLE) {
- vkResetCommandPool(ctx->dev, ctx->cmd_pool,
+ 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->dev != VK_NULL_HANDLE) {
- vkDestroyDevice(ctx->dev, 0);
- ctx->dev = VK_NULL_HANDLE;
- }
-
- if (ctx->inst != VK_NULL_HANDLE) {
- vkDestroyInstance(ctx->inst, 0);
- ctx->inst = VK_NULL_HANDLE;
- }
+ vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, 0);
+ ctx->cmd_pool = VK_NULL_HANDLE;
+ }
+
+ if (ctx->dev != VK_NULL_HANDLE) {
+ vkDestroyDevice(ctx->dev, 0);
+ ctx->dev = VK_NULL_HANDLE;
+ }
+
+ if (ctx->inst != VK_NULL_HANDLE) {
+ vkDestroyInstance(ctx->inst, 0);
+ ctx->inst = VK_NULL_HANDLE;
+ }
}
bool
vk_create_image(struct vk_ctx *ctx,
- struct vk_image_props *props,
- struct vk_image_obj *img)
+ struct vk_image_props *props,
+ struct vk_image_obj *img)
{
- VkImageCreateInfo img_info;
-
- memset(&img_info, 0, sizeof img_info);
- img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- img_info.pNext = 0; /* do something if external */
- 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 ?
+ VkImageCreateInfo img_info;
+
+ memset(&img_info, 0, sizeof img_info);
+ img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ img_info.pNext = 0; /* do something if external */
+ 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.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.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
- goto fail;
+ if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
+ goto fail;
- if(!alloc_image_memory(ctx, img))
- goto fail;
+ if(!alloc_image_memory(ctx, img))
+ goto fail;
- return true;
+ 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;
+ 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;
}
void
vk_destroy_image(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
{
- if (img_obj->img != VK_NULL_HANDLE) {
- vkDestroyImage(ctx->dev, img_obj->img, 0);
- img_obj->img = VK_NULL_HANDLE;
- }
-
- if (img_obj->mobj.mem != VK_NULL_HANDLE) {
- vkFreeMemory(ctx->dev, img_obj->mobj.mem, 0);
- img_obj->mobj.mem = VK_NULL_HANDLE;
- }
+ if (img_obj->img != VK_NULL_HANDLE) {
+ vkDestroyImage(ctx->dev, img_obj->img, 0);
+ img_obj->img = VK_NULL_HANDLE;
+ }
+
+ if (img_obj->mobj.mem != VK_NULL_HANDLE) {
+ vkFreeMemory(ctx->dev, img_obj->mobj.mem, 0);
+ img_obj->mobj.mem = VK_NULL_HANDLE;
+ }
}
bool
vk_create_ext_image(struct vk_ctx *ctx,
- struct vk_image_props *props, struct vk_image_obj *img)
+ 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;
+ 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;
+ 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
bool need_export,
struct vk_image_props *props)
{
- props->w = w;
- props->h = h;
- props->depth = d;
+ props->w = w;
+ props->h = h;
+ props->depth = d;
- props->num_samples = num_samples;
- props->num_levels = num_levels;
- props->num_layers = num_layers;
+ props->num_samples = num_samples;
+ props->num_levels = num_levels;
+ props->num_layers = num_layers;
- props->format = format;
- props->tiling = tiling;
+ props->format = format;
+ props->tiling = tiling;
- props->in_layout = in_layout;
- props->end_layout = end_layout;
+ props->in_layout = in_layout;
+ props->end_layout = end_layout;
props->need_export = need_export;
- if (!are_props_supported(ctx, props))
- return false;
+ if (!are_props_supported(ctx, props))
+ return false;
- return true;
+ return true;
}
bool
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;
+ memset(&renderer->vertex_info, 0, sizeof renderer->vertex_info);
+ if (vert_info)
+ renderer->vertex_info = *vert_info;
+
+ if (!color_att || depth_att) {
+ fprintf(stderr, "Empty attachment.\n");
+ goto fail;
+ }
- renderer->renderpass = create_renderpass(ctx, &color_att->props,
+ renderer->renderpass = create_renderpass(ctx, &color_att->props,
&depth_att->props);
- if (renderer->renderpass == VK_NULL_HANDLE)
- goto fail;
+ if (renderer->renderpass == VK_NULL_HANDLE)
+ goto fail;
- create_framebuffer(ctx, color_att, depth_att, renderer);
- if (renderer->fb == VK_NULL_HANDLE)
- goto fail;
+ create_framebuffer(ctx, color_att, depth_att, renderer);
+ if (renderer->fb == VK_NULL_HANDLE)
+ goto fail;
- renderer->vs = create_shader_module(ctx, vs_src, vs_size);
- if (renderer->vs == VK_NULL_HANDLE)
- goto fail;
+ renderer->vs = create_shader_module(ctx, vs_src, vs_size);
+ if (renderer->vs == VK_NULL_HANDLE)
+ goto fail;
- renderer->fs = create_shader_module(ctx, fs_src, fs_size);
- if (renderer->fs == VK_NULL_HANDLE)
- goto fail;
+ renderer->fs = create_shader_module(ctx, fs_src, fs_size);
+ if (renderer->fs == VK_NULL_HANDLE)
+ goto fail;
- create_pipeline(ctx, color_att->props.w, color_att->props.h,
+ create_pipeline(ctx, color_att->props.w, color_att->props.h,
color_att->props.num_samples, enable_depth,
enable_stencil, renderer);
- if (renderer->pipeline == VK_NULL_HANDLE)
- goto fail;
+ if (renderer->pipeline == VK_NULL_HANDLE)
+ goto fail;
- return true;
+ return true;
fail:
- fprintf(stderr, "Failed to create graphics pipeline.\n");
- vk_destroy_renderer(ctx, renderer);
- return false;
+ fprintf(stderr, "Failed to create graphics pipeline.\n");
+ vk_destroy_renderer(ctx, renderer);
+ return false;
}
void
struct vk_renderer *renderer)
{
if (renderer->renderpass != VK_NULL_HANDLE) {
- vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
- renderer->renderpass = 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) {
- vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
- renderer->fs = VK_NULL_HANDLE;
- }
-
- if (renderer->fb != VK_NULL_HANDLE) {
- vkDestroyFramebuffer(ctx->dev, renderer->fb, 0);
- renderer->fb = 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;
- }
+ vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
+ renderer->renderpass = 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) {
+ vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
+ renderer->fs = VK_NULL_HANDLE;
+ }
+
+ if (renderer->fb != VK_NULL_HANDLE) {
+ vkDestroyFramebuffer(ctx->dev, renderer->fb, 0);
+ renderer->fb = 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
VkBufferUsageFlagBits usage,
struct vk_buf *bo)
{
- VkExternalMemoryBufferCreateInfo ext_bo_info;
+ 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;
+ 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;
- }
+ if (!vk_create_buffer(ctx, true, sz, usage, &ext_bo_info, bo)) {
+ fprintf(stderr, "Failed to allocate external buffer.\n");
+ return false;
+ }
- return true;
+ return true;
}
bool
vk_create_buffer(struct vk_ctx *ctx,
bool is_external,
- uint32_t sz,
- VkBufferUsageFlagBits usage,
- void *pnext,
- struct vk_buf *bo)
+ uint32_t sz,
+ VkBufferUsageFlagBits usage,
+ void *pnext,
+ struct vk_buf *bo)
{
- VkBufferCreateInfo buf_info;
- VkMemoryRequirements mem_reqs;
-
- bo->mobj.mem = VK_NULL_HANDLE;
- bo->buf = VK_NULL_HANDLE;
-
- /* VkBufferCreateInfo */
- memset(&buf_info, 0, sizeof buf_info);
- buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buf_info.size = sz;
- buf_info.usage = usage;
- buf_info.pNext = pnext;
- buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
-
- if (vkCreateBuffer(ctx->dev, &buf_info, 0, &bo->buf) != VK_SUCCESS)
- goto fail;
-
- /* allocate buffer */
- vkGetBufferMemoryRequirements(ctx->dev, bo->buf, &mem_reqs);
- /* VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the
- * host cache management commands vkFlushMappedMemoryRanges and
- * 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, is_external, &mem_reqs, VK_NULL_HANDLE,
+ VkBufferCreateInfo buf_info;
+ VkMemoryRequirements mem_reqs;
+
+ bo->mobj.mem = VK_NULL_HANDLE;
+ bo->buf = VK_NULL_HANDLE;
+
+ /* VkBufferCreateInfo */
+ memset(&buf_info, 0, sizeof buf_info);
+ buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buf_info.size = sz;
+ buf_info.usage = usage;
+ buf_info.pNext = pnext;
+ buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ if (vkCreateBuffer(ctx->dev, &buf_info, 0, &bo->buf) != VK_SUCCESS)
+ goto fail;
+
+ /* allocate buffer */
+ vkGetBufferMemoryRequirements(ctx->dev, bo->buf, &mem_reqs);
+ /* VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the
+ * host cache management commands vkFlushMappedMemoryRanges and
+ * 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, 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;
+ if (bo->mobj.mem == VK_NULL_HANDLE)
+ goto fail;
- bo->mobj.mem_sz = sz;
+ bo->mobj.mem_sz = sz;
- if (vkBindBufferMemory(ctx->dev, bo->buf, bo->mobj.mem, 0) != VK_SUCCESS) {
- fprintf(stderr, "Failed to bind buffer memory.\n");
- goto fail;
- }
+ if (vkBindBufferMemory(ctx->dev, bo->buf, bo->mobj.mem, 0) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to bind buffer memory.\n");
+ goto fail;
+ }
- return true;
+ return true;
fail:
- fprintf(stderr, "Failed to allocate buffer.\n");
- vk_destroy_buffer(ctx, bo);
- return false;
+ fprintf(stderr, "Failed to allocate buffer.\n");
+ vk_destroy_buffer(ctx, bo);
+ return false;
}
bool
vk_update_buffer_data(struct vk_ctx *ctx,
- void *data,
- uint32_t data_sz,
- struct vk_buf *bo)
+ void *data,
+ uint32_t data_sz,
+ struct vk_buf *bo)
{
- void *map;
+ void *map;
- if (vkMapMemory(ctx->dev, bo->mobj.mem, 0, data_sz, 0, &map) != VK_SUCCESS) {
- fprintf(stderr, "Failed to map buffer memory.\n");
- goto fail;
- }
+ if (vkMapMemory(ctx->dev, bo->mobj.mem, 0, data_sz, 0, &map) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to map buffer memory.\n");
+ goto fail;
+ }
- memcpy(map, data, data_sz);
+ memcpy(map, data, data_sz);
- vkUnmapMemory(ctx->dev, bo->mobj.mem);
- return true;
+ vkUnmapMemory(ctx->dev, bo->mobj.mem);
+ return true;
fail:
- fprintf(stderr, "Failed to update buffer data. Destroying the buffer.\n");
- vk_destroy_buffer(ctx, bo);
+ fprintf(stderr, "Failed to update buffer data. Destroying the buffer.\n");
+ vk_destroy_buffer(ctx, bo);
- return false;
+ return false;
}
void
vk_destroy_buffer(struct vk_ctx *ctx,
- struct vk_buf *bo)
+ struct vk_buf *bo)
{
- if (bo->buf != VK_NULL_HANDLE)
- vkDestroyBuffer(ctx->dev, bo->buf, 0);
+ if (bo->buf != VK_NULL_HANDLE)
+ vkDestroyBuffer(ctx->dev, bo->buf, 0);
- if (bo->mobj.mem != VK_NULL_HANDLE)
- vkFreeMemory(ctx->dev, bo->mobj.mem, 0);
+ if (bo->mobj.mem != VK_NULL_HANDLE)
+ vkFreeMemory(ctx->dev, bo->mobj.mem, 0);
- bo->mobj.mem_sz = 0;
- bo->buf = VK_NULL_HANDLE;
- bo->mobj.mem = VK_NULL_HANDLE;
+ bo->mobj.mem_sz = 0;
+ bo->buf = VK_NULL_HANDLE;
+ bo->mobj.mem = VK_NULL_HANDLE;
}
void
vk_draw(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,
- struct vk_image_att *attachments,
- uint32_t n_attachments,
- float x, float y,
- float w, float h)
+ struct vk_buf *vbo,
+ struct vk_renderer *renderer,
+ float *vk_fb_color,
+ uint32_t vk_fb_color_count,
+ struct vk_semaphores *semaphores,
+ 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;
- VkDeviceSize offsets[] = {0};
- VkPipelineStageFlagBits stage_flags;
- struct vk_dims img_size;
-
- 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_SIMULTANEOUS_USE_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;
-
- /* semaphores */
- if (semaphores) {
- assert(semaphores->frame_ready);
- assert(semaphores->frame_done);
-
- submit_info.pWaitDstStageMask = &stage_flags;
- submit_info.waitSemaphoreCount = 1;
- submit_info.pWaitSemaphores = &semaphores->frame_done;
-
- submit_info.signalSemaphoreCount = 1;
- submit_info.pSignalSemaphores = &semaphores->frame_ready;
- }
-
- vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin_info);
- 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);
-
- img_size.w = (float)w;
- img_size.h = (float)h;
- vkCmdPushConstants(ctx->cmd_buf,
- renderer->pipeline_layout,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- 0, sizeof (struct vk_dims),
- &img_size);
-
- if (vbo) {
- vkCmdBindVertexBuffers(ctx->cmd_buf, 0, 1, &vbo->buf, offsets);
- }
- vkCmdBindPipeline(ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->pipeline);
-
- int num_vertices = vbo ? renderer->vertex_info.num_verts : 4;
- vkCmdDraw(ctx->cmd_buf, num_vertices, 1, 0, 0);
- vkCmdEndRenderPass(ctx->cmd_buf);
+ VkCommandBufferBeginInfo cmd_begin_info;
+ VkRenderPassBeginInfo rp_begin_info;
+ VkRect2D rp_area;
+ VkClearValue clear_values[2];
+ VkSubmitInfo submit_info;
+ VkDeviceSize offsets[] = {0};
+ VkPipelineStageFlagBits stage_flags;
+ struct vk_dims img_size;
+
+ 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_SIMULTANEOUS_USE_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;
+
+ /* semaphores */
+ if (semaphores) {
+ assert(semaphores->frame_ready);
+ assert(semaphores->frame_done);
+
+ submit_info.pWaitDstStageMask = &stage_flags;
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = &semaphores->frame_done;
+
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &semaphores->frame_ready;
+ }
+
+ vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin_info);
+ 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);
+
+ img_size.w = (float)w;
+ img_size.h = (float)h;
+ vkCmdPushConstants(ctx->cmd_buf,
+ renderer->pipeline_layout,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ 0, sizeof (struct vk_dims),
+ &img_size);
+
+ if (vbo) {
+ vkCmdBindVertexBuffers(ctx->cmd_buf, 0, 1, &vbo->buf, offsets);
+ }
+ vkCmdBindPipeline(ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->pipeline);
+
+ 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);
+ 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
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;
+ 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];
-
- /* Insert barrier to mark ownership transfer. */
- barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
-
- bool is_depth =
- get_aspect_from_depth_format(att->props.format) != VK_NULL_HANDLE;
-
- 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 ?
- VK_IMAGE_ASPECT_DEPTH_BIT :
- 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 && !has_wait && !has_signal)
- vkQueueWaitIdle(ctx->queue);
+ 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];
+
+ /* Insert barrier to mark ownership transfer. */
+ barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+
+ bool is_depth =
+ get_aspect_from_depth_format(att->props.format) != VK_NULL_HANDLE;
+
+ 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 ?
+ VK_IMAGE_ASPECT_DEPTH_BIT :
+ 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 && !has_wait && !has_signal)
+ vkQueueWaitIdle(ctx->queue);
}
bool
vk_create_swapchain(struct vk_ctx *ctx,
int width, int height,
- int num_qfam,
+ bool has_vsync,
+ VkSurfaceKHR surf,
+ struct vk_swapchain *old_swapchain,
struct vk_swapchain *swapchain)
{
+ VkSurfaceCapabilitiesKHR surf_cap;
VkSwapchainCreateInfoKHR s_info;
VkExtent2D extent;
+ VkImageSubresourceRange sr;
+ VkImage *s_images;
+ int i;
- extent.width = width;
- extent.height = height;
+ if (!sc_validate_surface(ctx, surf)) {
+ fprintf(stderr, "Failed to validate surface!\n");
+ return false;
+ }
- memset(&s_info, 0, sizeof s_info);
+ /* get pdevice capabilities
+ * will need that to determine the swapchain number of images
+ */
+ if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(ctx->pdev, surf, &surf_cap) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to query surface capabilities.\n");
+ return false;
+ }
+
+ /* allocate and init an empty struct vk_swapchain */
+ swapchain = malloc(sizeof *swapchain);
+ memset(swapchain, 0, sizeof *swapchain);
+
+ swapchain->surface = surf;
+ memset(&s_info, 0, sizeof s_info);
s_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
s_info.flags = 0;
- s_info.surface = swapchain->surface;
- s_info.minImageCount = 2;
- s_info.imageFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
- s_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+ /* surface format */
+ if (!sc_select_format(ctx, surf, &s_info)) {
+ fprintf(stderr, "Failed to determine the surface format.\n");
+ return false;
+ }
+ s_info.surface = surf;
+
+ /* number of images */
+ s_info.minImageCount = surf_cap.minImageCount;
+ /* swapchain images dims */
+ {
+ extent.width = width;
+ extent.height = height;
+ }
+ if (!sc_select_supported_present_modes(ctx, surf, has_vsync, &s_info)) {
+ s_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ }
s_info.imageExtent = extent;
s_info.imageArrayLayers = 1;
- s_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_SAMPLED_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
- s_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- s_info.queueFamilyIndexCount = num_qfam; /* how many queue families */
-
- s_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ /* enable color attachment bit and transfer src and transfer dst bits
+ * too if they are supported */
+ {
+ s_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
+ s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
+ s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ }
+ s_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ s_info.queueFamilyIndexCount = ctx->qfam_idx;
+
+ /* we might want to use this function when we recreate the swapchain too */
+ s_info.preTransform = surf_cap.supportedTransforms &
+ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ?
+ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR :
+ surf_cap.currentTransform;
+
+ /* we could also write a sc_select_supported_composite_alpha
+ * later but VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR is universally
+ * supported */
s_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- s_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
s_info.clipped = VK_TRUE;
- s_info.oldSwapchain = VK_NULL_HANDLE;
+ s_info.oldSwapchain = old_swapchain ? old_swapchain->swapchain : 0;
if (vkCreateSwapchainKHR(ctx->dev, &s_info, 0,
&swapchain->swapchain) != VK_SUCCESS) {
return false;
}
+ /* if an existing swapchain is recreated we need to destroy
+ * the old swapchain and clean up the images */
+ if (old_swapchain) {
+ for (i = 0; i < old_swapchain->num_images; i++) {
+ vkDestroyImageView(ctx->dev, old_swapchain->images[i].image_view, 0);
+ }
+ vk_destroy_swapchain(ctx, old_swapchain);
+ }
+
+ /* get the number of swapchain images and the swapchain images
+ * and store the new swapchain images
+ */
+ vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain, &swapchain->num_images, 0);
+ printf("number of swapchain images: %d\n", swapchain->num_images);
+
+ /* create images */
+ s_images = malloc(swapchain->num_images * sizeof(VkImage));
+ vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain, &swapchain->num_images, s_images);
+
+ swapchain->image_fmt = s_info.imageFormat;
+ swapchain->images = malloc(swapchain->num_images * sizeof(struct vk_swap_image_obj));
+
+ memset(&sr, 0, sizeof sr);
+ sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ sr.levelCount = 1;
+ sr.layerCount = 1;
+
+ for (i = 0; i < swapchain->num_images; i++) {
+ swapchain->images[i].image = s_images[i];
+ if (!(create_image_view(ctx,
+ swapchain->images[i].image,
+ VK_IMAGE_VIEW_TYPE_2D,
+ swapchain->image_fmt,
+ sr,
+ true,
+ &swapchain->images[i].image_view))) {
+ fprintf(stderr, "Fail to create an image view from the swapchain image: i=%d\n", i);
+ break;
+ }
+ if (i < swapchain->num_images - 1) {
+ int j;
+ for (j = 0; j < i; j++) {
+ vkDestroyImageView(ctx->dev, swapchain->images[i].image_view, 0);
+ }
+ return false;
+ }
+ }
+
+ free(s_images);
return true;
}
{
vkDestroySwapchainKHR(ctx->dev, swapchain->swapchain, 0);
vkDestroySurfaceKHR(ctx->inst, swapchain->surface, 0);
+
+ free(swapchain);
+ swapchain = 0;
}
void
struct vk_buf *dst_bo,
float w, float h)
{
- VkCommandBufferBeginInfo cmd_begin_info;
- VkSubmitInfo submit_info;
- VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(src_img->props.format);
-
- /* 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;
-
- 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;
-
- 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,
+ VkCommandBufferBeginInfo cmd_begin_info;
+ VkSubmitInfo submit_info;
+ VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(src_img->props.format);
+
+ /* 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;
+
+ 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;
+
+ 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);
- /* copy image to buf */
- VkBufferImageCopy copy_region = {
- .bufferOffset = 0,
- .bufferRowLength = w,
- .bufferImageHeight = h,
- .imageSubresource = {
- .aspectMask = aspect_mask ? aspect_mask
+ /* copy image to buf */
+ VkBufferImageCopy copy_region = {
+ .bufferOffset = 0,
+ .bufferRowLength = w,
+ .bufferImageHeight = h,
+ .imageSubresource = {
+ .aspectMask = aspect_mask ? aspect_mask
: VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .imageOffset = { 0, 0, 0 },
- .imageExtent = { w, h, 1 }
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .imageOffset = { 0, 0, 0 },
+ .imageExtent = { w, h, 1 }
};
- vkCmdCopyImageToBuffer(ctx->cmd_buf,
+ vkCmdCopyImageToBuffer(ctx->cmd_buf,
src_img->obj.img,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_bo->buf, 1, ©_region);
- vk_transition_image_layout(src_img,
+ 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);
- VkBufferMemoryBarrier write_finish_buffer_memory_barrier = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
- .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
- .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
- .dstQueueFamilyIndex = ctx->qfam_idx,
- .buffer = dst_bo->buf,
- .offset = 0,
- .size = VK_WHOLE_SIZE
- };
-
- vkCmdPipelineBarrier(ctx->cmd_buf,
+ VkBufferMemoryBarrier write_finish_buffer_memory_barrier = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
+ .dstQueueFamilyIndex = ctx->qfam_idx,
+ .buffer = dst_bo->buf,
+ .offset = 0,
+ .size = VK_WHOLE_SIZE
+ };
+
+ 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);
}
- vkEndCommandBuffer(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");
- }
- vkQueueWaitIdle(ctx->queue);
+ if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to submit queue.\n");
+ }
+ vkQueueWaitIdle(ctx->queue);
}
// FIXME: external
bool
vk_create_semaphores(struct vk_ctx *ctx,
- struct vk_semaphores *semaphores)
+ bool is_external,
+ struct vk_semaphores *semaphores)
{
- VkSemaphoreCreateInfo sema_info;
- VkExportSemaphoreCreateInfo exp_sema_info;
-
- /* VkExportSemaphoreCreateInfo */
- memset(&exp_sema_info, 0, sizeof exp_sema_info);
- exp_sema_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
- exp_sema_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
-
- /* VkSemaphoreCreateInfo */
- memset(&sema_info, 0, sizeof sema_info);
- sema_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- sema_info.pNext = &exp_sema_info;
-
- if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_ready) != VK_SUCCESS) {
- fprintf(stderr, "Failed to create semaphore frame_ready.\n");
- return false;
- }
-
- if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_done) != VK_SUCCESS) {
- fprintf(stderr, "Failed to create semaphore frame_done.\n");
- return false;
- }
-
- return true;
+ VkSemaphoreCreateInfo sema_info;
+ VkExportSemaphoreCreateInfo exp_sema_info;
+
+ if (is_external) {
+ /* VkExportSemaphoreCreateInfo */
+ memset(&exp_sema_info, 0, sizeof exp_sema_info);
+ exp_sema_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
+ exp_sema_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+ }
+
+ /* VkSemaphoreCreateInfo */
+ memset(&sema_info, 0, sizeof sema_info);
+ sema_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ sema_info.pNext = is_external ? &exp_sema_info : 0;
+
+ if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_ready) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create semaphore frame_ready.\n");
+ return false;
+ }
+
+ if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_done) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create semaphore frame_done.\n");
+ return false;
+ }
+
+ return true;
}
void
vk_destroy_semaphores(struct vk_ctx *ctx,
- struct vk_semaphores *semaphores)
+ struct vk_semaphores *semaphores)
{
- if (semaphores->frame_ready)
- vkDestroySemaphore(ctx->dev, semaphores->frame_ready, 0);
- if (semaphores->frame_done)
- vkDestroySemaphore(ctx->dev, semaphores->frame_done, 0);
+ if (semaphores->frame_ready)
+ vkDestroySemaphore(ctx->dev, semaphores->frame_ready, 0);
+ if (semaphores->frame_done)
+ vkDestroySemaphore(ctx->dev, semaphores->frame_done, 0);
}
void
vk_transition_image_layout(struct vk_image_att *img_att,
- VkCommandBuffer cmd_buf,
- VkImageLayout old_layout,
- VkImageLayout new_layout,
- uint32_t src_queue_fam_idx,
- uint32_t dst_queue_fam_idx)
+ VkCommandBuffer cmd_buf,
+ VkImageLayout old_layout,
+ VkImageLayout new_layout,
+ uint32_t src_queue_fam_idx,
+ uint32_t dst_queue_fam_idx)
{
- VkImageMemoryBarrier barrier;
- struct vk_image_props props = img_att->props;
- VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(props.format);
-
- memset(&barrier, 0, sizeof barrier);
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.srcAccessMask = get_access_mask(old_layout);
- barrier.dstAccessMask = get_access_mask(new_layout);
- barrier.oldLayout = old_layout;
- barrier.newLayout = new_layout;
- 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 :
+ VkImageMemoryBarrier barrier;
+ struct vk_image_props props = img_att->props;
+ VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(props.format);
+
+ memset(&barrier, 0, sizeof barrier);
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.srcAccessMask = get_access_mask(old_layout);
+ barrier.dstAccessMask = get_access_mask(new_layout);
+ barrier.oldLayout = old_layout;
+ barrier.newLayout = new_layout;
+ 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.levelCount = 1;
- barrier.subresourceRange.layerCount = 1;
+ barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(cmd_buf,
+ 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);