Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created April 17, 2021 20:48
Show Gist options
  • Save untodesu/5d1bf5f18e390da4a485ec09fe3bf8a3 to your computer and use it in GitHub Desktop.
Save untodesu/5d1bf5f18e390da4a485ec09fe3bf8a3 to your computer and use it in GitHub Desktop.
fckn vulkan
#include <glad/vulkan.h>
#include <GLFW/glfw3.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "tri_v.h"
#include "tri_f.h"
// Note #1:
// All the Vulkan-related code should be
// eventually moved from this to a more suitable
// place where it can be also abstracted so the
// OpenGL (both 4.6 and 3.2) compatibility can be
// achieved. For now since I'm learning about how
// Vulkan works, shit's about to live here for a while.
// Note #2:
// There will be a bunch of my own comments about
// how Vulkan differs from OpenGL from the perspective
// of a huge modern OpenGL nerd that wants to learn Vulkan.
// So the first difference is function loading process:
// we need to call the loader three (holy shit!) times.
// So the process of initialization is:
// 1. Load a basic set of functions: LoadVulkan(null, GetInstanceProcAddress, null)
// 2. Create a new Vulkan instance
// 3. Load some more functions: LoadVulkan(null, GetInstanceProcAddress, instance)
// 4. Choose a GPU (physical device) to use
// 5. Load the remaining functions: LoadVulkan(gpu, GetInstanceProcAddress, instance)
// 6. Create a new logical device
// This seems like a bad idea
typedef _Bool boolean;
enum { false, true };
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
struct r_queuefamily_s {
boolean valid;
uint32_t index;
};
struct r_vkstate_s {
VkInstance instance;
VkPhysicalDevice gpu;
VkPhysicalDeviceFeatures gpu_features;
VkPhysicalDeviceProperties gpu_properties;
struct r_queuefamily_s gpu_graphics_qf;
struct r_queuefamily_s gpu_present_qf;
VkDevice device;
VkQueue graphics;
VkQueue present;
VkSurfaceKHR surface;
VkSurfaceCapabilitiesKHR surface_caps;
VkSurfaceFormatKHR swapchain_format;
VkPresentModeKHR swapchain_present_mode;
VkExtent2D swapchain_extent;
VkSwapchainKHR swapchain;
uint32_t num_swapchain_images;
VkImage *swapchain_images;
VkImageView *swapchain_image_views;
VkFramebuffer *swapchain_framebuffers;
VkCommandBuffer *command_buffers;
};
static struct r_vkstate_s r_state;
static boolean R_CreateInstance(void)
{
uint32_t num_instance_extensions;
const char **instance_extensions = glfwGetRequiredInstanceExtensions(&num_instance_extensions);
VkApplicationInfo app_info = { 0 };
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = "Test App";
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 0);
app_info.pEngineName = "Wynn";
app_info.engineVersion = VK_MAKE_VERSION(0, 0, 0);
app_info.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo instance_info = { 0 };
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_info.pApplicationInfo = &app_info;
instance_info.ppEnabledExtensionNames = instance_extensions;
instance_info.enabledExtensionCount = num_instance_extensions;
instance_info.enabledLayerCount = 0;
return vkCreateInstance(&instance_info, NULL, &r_state.instance) == VK_SUCCESS;
}
static boolean R_ChooseGPU(void)
{
r_state.gpu = VK_NULL_HANDLE;
uint32_t num_gpus;
vkEnumeratePhysicalDevices(r_state.instance, &num_gpus, NULL);
unsigned int *gpu_ratings = malloc(sizeof(unsigned int) * num_gpus);
VkPhysicalDevice *gpus = malloc(sizeof(VkPhysicalDevice) * num_gpus);
vkEnumeratePhysicalDevices(r_state.instance, &num_gpus, gpus);
uint32_t max_index = 0;
unsigned int max_rating = 0;
for(uint32_t i = 0; i < num_gpus; i++) {
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(gpus[i], &features);
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(gpus[i], &properties);
gpu_ratings[i] = 0;
if(properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
gpu_ratings[i] += 1000;
gpu_ratings[i] += properties.limits.maxImageDimension2D;
if(gpu_ratings[i] > max_rating) {
max_rating = gpu_ratings[i];
max_index = i;
}
}
if(max_rating > 0) {
uint32_t num_queue_families;
vkGetPhysicalDeviceQueueFamilyProperties(gpus[max_index], &num_queue_families, NULL);
VkQueueFamilyProperties *queue_families = malloc(sizeof(VkQueueFamilyProperties) * num_queue_families);
vkGetPhysicalDeviceQueueFamilyProperties(gpus[max_index], &num_queue_families, queue_families);
for(uint32_t i = 0; i < num_queue_families; i++) {
if(!r_state.gpu_graphics_qf.valid && queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
r_state.gpu_graphics_qf.valid = true;
r_state.gpu_graphics_qf.index = i;
}
if(!r_state.gpu_present_qf.valid && glfwGetPhysicalDevicePresentationSupport(r_state.instance, gpus[max_index], i)) {
r_state.gpu_present_qf.valid = true;
r_state.gpu_present_qf.index = i;
}
}
free(queue_families);
// todo: R_QueuesComplete
if(r_state.gpu_graphics_qf.valid && r_state.gpu_present_qf.valid) {
r_state.gpu = gpus[max_index];
vkGetPhysicalDeviceFeatures(r_state.gpu, &r_state.gpu_features);
vkGetPhysicalDeviceProperties(r_state.gpu, &r_state.gpu_properties);
printf("R_ChooseGPU: choosing %s\n", r_state.gpu_properties.deviceName);
printf("R_ChooseGPU: gpu rating: %u\n", max_rating);
}
}
free(gpus);
free(gpu_ratings);
return r_state.gpu != VK_NULL_HANDLE;
}
static boolean R_CreateDevice(void)
{
const float queue_priority = 1.0f;
VkDeviceQueueCreateInfo queue_infos[] = {
{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = r_state.gpu_graphics_qf.index,
.queueCount = 1,
.pQueuePriorities = &queue_priority,
},
{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = r_state.gpu_present_qf.index,
.queueCount = 1,
.pQueuePriorities = &queue_priority,
},
};
const char *device_extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
VkDeviceCreateInfo device_info = { 0 };
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_info.pQueueCreateInfos = queue_infos;
device_info.queueCreateInfoCount = ARRAY_SIZE(queue_infos);
device_info.pEnabledFeatures = &r_state.gpu_features;
device_info.ppEnabledExtensionNames = device_extensions;
device_info.enabledExtensionCount = ARRAY_SIZE(device_extensions);
device_info.enabledLayerCount = 0;
return vkCreateDevice(r_state.gpu, &device_info, NULL, &r_state.device) == VK_SUCCESS;
}
static boolean R_CreateSwapchain(GLFWwindow *window)
{
uint32_t num_formats;
vkGetPhysicalDeviceSurfaceFormatsKHR(r_state.gpu, r_state.surface, &num_formats, NULL);
if(!num_formats) {
printf("R_CreateSwapchain: surface has no formats");
return false;
}
VkSurfaceFormatKHR *formats = malloc(sizeof(VkSurfaceFormatKHR) * num_formats);
vkGetPhysicalDeviceSurfaceFormatsKHR(r_state.gpu, r_state.surface, &num_formats, formats);
boolean has_best_format = false;
for(uint32_t i = 0; i < num_formats; i++) {
if(formats[i].format == VK_FORMAT_B8G8R8A8_SRGB && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
r_state.swapchain_format = formats[i];
has_best_format = true;
}
}
if(!has_best_format) {
printf("R_CreateSwapchain: can't find the best surface format, defaulting to 0\n");
r_state.swapchain_format = formats[0];
}
free(formats);
uint32_t num_present_modes;
vkGetPhysicalDeviceSurfacePresentModesKHR(r_state.gpu, r_state.surface, &num_present_modes, NULL);
if(!num_present_modes) {
printf("R_CreateSwapchain: surface has no present modes\n");
return false;
}
VkPresentModeKHR *present_modes = malloc(sizeof(VkPresentModeKHR) * num_present_modes);
vkGetPhysicalDeviceSurfacePresentModesKHR(r_state.gpu, r_state.surface, &num_present_modes, present_modes);
boolean has_best_present_mode = false;
for(uint32_t i = 0; i < num_present_modes; i++) {
if(present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
r_state.swapchain_present_mode = present_modes[i];
has_best_present_mode = true;
}
}
if(!has_best_present_mode) {
printf("R_CreateSwapchain: can't find the best surface present mode, defaulting to VK_PRESENT_MODE_FIFO_KHR\n");
r_state.swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR;
}
free(present_modes);
if(r_state.surface_caps.currentExtent.width != UINT32_MAX) {
printf("R_CreateSwapchain: using current surface extent\n");
r_state.swapchain_extent = r_state.surface_caps.currentExtent;
}
else {
int width, height;
glfwGetFramebufferSize(window, &width, &height);
r_state.swapchain_extent.width = width;
r_state.swapchain_extent.height = height;
// clamp the width
if(r_state.swapchain_extent.width > r_state.surface_caps.maxImageExtent.width)
r_state.swapchain_extent.width = r_state.surface_caps.maxImageExtent.width;
if(r_state.swapchain_extent.width < r_state.surface_caps.minImageExtent.width)
r_state.swapchain_extent.width = r_state.surface_caps.minImageExtent.width;
// clamp the height
if(r_state.swapchain_extent.height > r_state.surface_caps.maxImageExtent.height)
r_state.swapchain_extent.height = r_state.surface_caps.maxImageExtent.height;
if(r_state.swapchain_extent.height < r_state.surface_caps.minImageExtent.height)
r_state.swapchain_extent.height = r_state.surface_caps.minImageExtent.height;
}
uint32_t num_images = r_state.surface_caps.minImageCount + 1;
if(num_images > r_state.surface_caps.maxImageCount)
num_images = r_state.surface_caps.maxImageCount;
VkSwapchainCreateInfoKHR swapchain_info = { 0 };
swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchain_info.surface = r_state.surface;
swapchain_info.minImageCount = num_images;
swapchain_info.imageFormat = r_state.swapchain_format.format;
swapchain_info.imageColorSpace = r_state.swapchain_format.colorSpace;
swapchain_info.imageExtent = r_state.swapchain_extent;
swapchain_info.imageArrayLayers = 1;
swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchain_info.preTransform = r_state.surface_caps.currentTransform;
swapchain_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchain_info.presentMode = r_state.swapchain_present_mode;
swapchain_info.clipped = VK_TRUE;
swapchain_info.oldSwapchain = VK_NULL_HANDLE;
uint32_t indices[] = {
r_state.gpu_graphics_qf.index,
r_state.gpu_present_qf.index
};
if(r_state.gpu_graphics_qf.index != r_state.gpu_present_qf.index) {
swapchain_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swapchain_info.queueFamilyIndexCount = ARRAY_SIZE(indices);
swapchain_info.pQueueFamilyIndices = indices;
}
else {
swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchain_info.queueFamilyIndexCount = 0;
}
return vkCreateSwapchainKHR(r_state.device, &swapchain_info, NULL, &r_state.swapchain) == VK_SUCCESS;
}
static boolean R_GetSwapchainImages(void)
{
vkGetSwapchainImagesKHR(r_state.device, r_state.swapchain, &r_state.num_swapchain_images, NULL);
r_state.swapchain_images = malloc(sizeof(VkImage) * r_state.num_swapchain_images);
vkGetSwapchainImagesKHR(r_state.device, r_state.swapchain, &r_state.num_swapchain_images, r_state.swapchain_images);
r_state.swapchain_image_views = malloc(sizeof(VkImageView) * r_state.num_swapchain_images);
for(uint32_t i = 0; i < r_state.num_swapchain_images; i++) {
VkImageViewCreateInfo view_info = { 0 };
view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_info.image = r_state.swapchain_images[i];
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.format = r_state.swapchain_format.format;
view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
view_info.subresourceRange.baseMipLevel = 0;
view_info.subresourceRange.levelCount = 1;
view_info.subresourceRange.baseArrayLayer = 0;
view_info.subresourceRange.layerCount = 1;
if(vkCreateImageView(r_state.device, &view_info, NULL, &r_state.swapchain_image_views[i]) != VK_SUCCESS)
return false;
}
return true;
}
static boolean R_Init(GLFWwindow *window)
{
if(!gladLoadVulkanUserPtr(NULL, glfwGetInstanceProcAddress, NULL)) {
printf("R_Init: failed to load Vulkan functions (1)\n");
return false;
}
if(!R_CreateInstance()) {
printf("R_Init: failed to create a Vulkan instance\n");
return false;
}
if(!gladLoadVulkanUserPtr(NULL, glfwGetInstanceProcAddress, r_state.instance)) {
printf("R_Init: failed to load Vulkan functions (2)\n");
return false;
}
if(!R_ChooseGPU()) {
printf("R_Init: failed to choose a suitable GPU\n");
return false;
}
if(!gladLoadVulkanUserPtr(r_state.gpu, glfwGetInstanceProcAddress, r_state.instance)) {
printf("R_Init: failed to load Vulkan functions (3)\n");
return false;
}
if(!R_CreateDevice()) {
printf("R_Init: failed to create a Vulkan device\n");
return false;
}
vkGetDeviceQueue(r_state.device, r_state.gpu_graphics_qf.index, 0, &r_state.graphics);
vkGetDeviceQueue(r_state.device, r_state.gpu_present_qf.index, 0, &r_state.present);
if(glfwCreateWindowSurface(r_state.instance, window, NULL, &r_state.surface) != VK_SUCCESS) {
printf("R_Init: failed to create a window surface\n");
return false;
}
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(r_state.gpu, r_state.surface, &r_state.surface_caps);
if(!R_CreateSwapchain(window)) {
printf("R_Init: failed to create a swapchain\n");
return false;
}
if(!R_GetSwapchainImages()) {
printf("R_Init: failed to get swapchain images\n");
return false;
}
return true;
}
static void R_Shutdown(void)
{
for(uint32_t i = 0; i < r_state.num_swapchain_images; i++)
vkDestroyImageView(r_state.device, r_state.swapchain_image_views[i], NULL);
free(r_state.swapchain_image_views);
free(r_state.swapchain_images);
vkDestroySwapchainKHR(r_state.device, r_state.swapchain, NULL);
vkDestroySurfaceKHR(r_state.instance, r_state.surface, NULL);
vkDestroyDevice(r_state.device, NULL);
vkDestroyInstance(r_state.instance, NULL);
}
static boolean R_CreateShaderModule(const void *data, size_t size, VkShaderModule *out)
{
VkShaderModuleCreateInfo module_info = { 0 };
module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
module_info.codeSize = size;
module_info.pCode = data;
return vkCreateShaderModule(r_state.device, &module_info, NULL, out) == VK_SUCCESS;
}
static boolean R_CreateRenderPass(VkRenderPass *out)
{
VkAttachmentDescription color = { 0 };
color.format = r_state.swapchain_format.format;
color.samples = VK_SAMPLE_COUNT_1_BIT;
color.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
color.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference color_ref = { 0 };
color_ref.attachment = 0;
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDependency dependency = { 0 };
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
VkSubpassDescription subpass = { 0 };
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
VkRenderPassCreateInfo pass_info = { 0 };
pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
pass_info.attachmentCount = 1;
pass_info.pAttachments = &color;
pass_info.subpassCount = 1;
pass_info.pSubpasses = &subpass;
pass_info.dependencyCount = 1;
pass_info.pDependencies = &dependency;
return vkCreateRenderPass(r_state.device, &pass_info, NULL, out) == VK_SUCCESS;
}
static void GLFW_ErrorCallback(int code, const char *message)
{
printf("glfw error %d: %s\n", code, message);
}
int main(void)
{
glfwSetErrorCallback(GLFW_ErrorCallback);
if(!glfwInit())
return 1;
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow *window = glfwCreateWindow(800, 600, "", NULL, NULL);
if(!window) {
glfwTerminate();
return 1;
}
if(!R_Init(window)) {
glfwTerminate();
return 1;
}
VkShaderModule vert;
if(!R_CreateShaderModule(tri_vspv, tri_vspv_len, &vert)) {
R_Shutdown();
glfwTerminate();
return 2;
}
VkShaderModule frag;
if(!R_CreateShaderModule(tri_fspv, tri_fspv_len, &frag)) {
R_Shutdown();
glfwTerminate();
return 2;
}
VkPipelineShaderStageCreateInfo stages[] = {
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vert,
.pName = "main",
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = frag,
.pName = "main",
}
};
VkRenderPass pass;
if(!R_CreateRenderPass(&pass)) {
R_Shutdown();
glfwTerminate();
return 3;
}
VkPipelineVertexInputStateCreateInfo vertex_info = { 0 };
vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_info.vertexBindingDescriptionCount = 0;
vertex_info.vertexAttributeDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo input_info = { 0 };
input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_info.primitiveRestartEnable = VK_FALSE;
VkViewport viewport = {
.x = 0.0f,
.y = 0.0f,
.width = r_state.swapchain_extent.width,
.height = r_state.swapchain_extent.height,
.minDepth = 0.0f,
.maxDepth = 1.0f
};
VkRect2D scissor = {
.offset = { 0, 0 },
.extent = r_state.swapchain_extent
};
VkPipelineViewportStateCreateInfo viewport_info = { 0 };
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 rasterizer_info = { 0 };
rasterizer_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer_info.depthClampEnable = VK_FALSE;
rasterizer_info.rasterizerDiscardEnable = VK_FALSE;
rasterizer_info.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer_info.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer_info.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer_info.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo msaa_info = { 0 };
msaa_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
msaa_info.sampleShadingEnable = VK_FALSE;
msaa_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState blend_attachment = { 0 };
blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
blend_attachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo color_blend = { 0 };
color_blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blend.logicOpEnable = VK_FALSE;
color_blend.logicOp = VK_LOGIC_OP_COPY;
color_blend.attachmentCount = 1;
color_blend.pAttachments = &blend_attachment;
color_blend.blendConstants[0] = 0.0f;
color_blend.blendConstants[1] = 0.0f;
color_blend.blendConstants[2] = 0.0f;
color_blend.blendConstants[3] = 0.0f;
VkPipelineLayout pipeline_layout;
VkPipelineLayoutCreateInfo layout_info = { 0 };
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
vkCreatePipelineLayout(r_state.device, &layout_info, NULL, &pipeline_layout);
VkGraphicsPipelineCreateInfo pipeline_info = { 0 };
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.stageCount = 2;
pipeline_info.pStages = stages;
pipeline_info.pVertexInputState = &vertex_info;
pipeline_info.pInputAssemblyState = &input_info;
pipeline_info.pViewportState = &viewport_info;
pipeline_info.pRasterizationState = &rasterizer_info;
pipeline_info.pMultisampleState = &msaa_info;
pipeline_info.pColorBlendState = &color_blend;
pipeline_info.layout = pipeline_layout;
pipeline_info.renderPass = pass;
pipeline_info.subpass = 0;
VkPipeline pipeline;
if(vkCreateGraphicsPipelines(r_state.device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline) != VK_SUCCESS) {
printf("failed to create pipeline\n");
R_Shutdown();
glfwTerminate();
return 4;
}
r_state.swapchain_framebuffers = malloc(sizeof(VkFramebuffer) * r_state.num_swapchain_images);
for(uint32_t i = 0; i < r_state.num_swapchain_images; i++) {
VkFramebufferCreateInfo framebuffer_info = { 0 };
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebuffer_info.renderPass = pass;
framebuffer_info.attachmentCount = 1;
framebuffer_info.pAttachments = &r_state.swapchain_image_views[i];
framebuffer_info.width = r_state.swapchain_extent.width;
framebuffer_info.height = r_state.swapchain_extent.height;
framebuffer_info.layers = 1;
if(vkCreateFramebuffer(r_state.device, &framebuffer_info, NULL, &r_state.swapchain_framebuffers[i]) != VK_SUCCESS) {
printf("failed to create framebuffer\n");
R_Shutdown();
glfwTerminate();
return 1;
}
}
VkCommandPool pool;
VkCommandPoolCreateInfo pool_info = { 0 };
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.queueFamilyIndex = r_state.gpu_graphics_qf.index;
pool_info.flags = 0;
if(vkCreateCommandPool(r_state.device, &pool_info, NULL, &pool) != VK_SUCCESS) {
printf("failed to create command pool\n");
R_Shutdown();
glfwTerminate();
return 1;
}
r_state.command_buffers = malloc(sizeof(VkCommandBuffer) * r_state.num_swapchain_images);
VkCommandBufferAllocateInfo cb_info = { 0 };
cb_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cb_info.commandPool = pool;
cb_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cb_info.commandBufferCount = r_state.num_swapchain_images;
if(vkAllocateCommandBuffers(r_state.device, &cb_info, r_state.command_buffers) != VK_SUCCESS) {
printf("failed to allocate command buffers\n");
R_Shutdown();
glfwTerminate();
return 1;
}
VkSemaphore ia_se;
VkSemaphore rf_se;
VkSemaphoreCreateInfo se_info = { 0 };
se_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if(vkCreateSemaphore(r_state.device, &se_info, NULL, &ia_se) != VK_SUCCESS) {
printf("failed to create semaphore\n");
R_Shutdown();
glfwTerminate();
return 1;
}
if(vkCreateSemaphore(r_state.device, &se_info, NULL, &rf_se) != VK_SUCCESS) {
printf("failed to create semaphore\n");
R_Shutdown();
glfwTerminate();
return 1;
}
while(!glfwWindowShouldClose(window)) {
for(uint32_t i = 0; i < r_state.num_swapchain_images; i++) {
VkCommandBufferBeginInfo begin_info = { 0 };
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
if(vkBeginCommandBuffer(r_state.command_buffers[i], &begin_info) != VK_SUCCESS) {
printf("failed to begin command buffer\n");
R_Shutdown();
glfwTerminate();
return 1;
}
VkClearValue clear = { 0.0f, 0.0f, 0.0f, 1.0f };
VkRenderPassBeginInfo pass_info = { 0 };
pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
pass_info.renderPass = pass;
pass_info.framebuffer = r_state.swapchain_framebuffers[i];
pass_info.renderArea.offset.x = 0;
pass_info.renderArea.offset.y = 0;
pass_info.renderArea.extent = r_state.swapchain_extent;
pass_info.clearValueCount = 1;
pass_info.pClearValues = &clear;
vkCmdBeginRenderPass(r_state.command_buffers[i], &pass_info, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(r_state.command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdDraw(r_state.command_buffers[i], 3, 1, 0, 0);
vkCmdEndRenderPass(r_state.command_buffers[i]);
if(vkEndCommandBuffer(r_state.command_buffers[i]) != VK_SUCCESS) {
printf("failed to end command buffer\n");
R_Shutdown();
glfwTerminate();
return 1;
}
}
uint32_t index;
vkAcquireNextImageKHR(r_state.device, r_state.swapchain, UINT64_MAX, ia_se, VK_NULL_HANDLE, &index);
VkPipelineStageFlags ws[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSubmitInfo si = { 0 };
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
si.waitSemaphoreCount = 1;
si.pWaitSemaphores = &ia_se;
si.pWaitDstStageMask = ws;
si.commandBufferCount = 1;
si.pCommandBuffers = &r_state.command_buffers[index];
si.signalSemaphoreCount = 1;
si.pSignalSemaphores = &rf_se;
if(vkQueueSubmit(r_state.graphics, 1, &si, VK_NULL_HANDLE) != VK_SUCCESS) {
printf("failed to submit\n");
R_Shutdown();
glfwTerminate();
return 1;
}
VkPresentInfoKHR present_info = { 0 };
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = &rf_se;
present_info.swapchainCount = 1;
present_info.pSwapchains = &r_state.swapchain;
present_info.pImageIndices = &index;
vkQueuePresentKHR(r_state.graphics, &present_info);
glfwPollEvents();
}
vkDestroySemaphore(r_state.device, rf_se, NULL);
vkDestroySemaphore(r_state.device, ia_se, NULL);
vkDestroyCommandPool(r_state.device, pool, NULL);
for(uint32_t i = 0; i , r_state.num_swapchain_images; i++)
vkDestroyFramebuffer(r_state.device, r_state.swapchain_framebuffers[i], NULL);
free(r_state.swapchain_framebuffers);
vkDestroyPipeline(r_state.device, pipeline, NULL);
vkDestroyPipelineLayout(r_state.device, pipeline_layout, NULL);
vkDestroyShaderModule(r_state.device, vert, NULL);
vkDestroyShaderModule(r_state.device, frag, NULL);
R_Shutdown();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
#version 450
layout(location = 0) in vec3 col;
layout(location = 0) out vec4 fc;
void main(void)
{
fc = vec4(col, 1.0);
}
#version 450
vec2 positions[3] = vec2[](
vec2(-0.5, -0.5),
vec2( 0.0, 0.5),
vec2( 0.5, -0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
layout(location = 0) out vec3 col;
void main(void)
{
col = colors[gl_VertexIndex];
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
}
unsigned char tri_fspv[] = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00,
0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70,
0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00,
0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00,
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x63, 0x00, 0x00,
0x05, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x00,
0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
0x38, 0x00, 0x01, 0x00
};
unsigned int tri_fspv_len = 556;
unsigned char tri_vspv[] = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00,
0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00,
0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f,
0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47,
0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00,
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00,
0x05, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f,
0x72, 0x73, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x63, 0x6f, 0x6c, 0x00, 0x05, 0x00, 0x06, 0x00, 0x21, 0x00, 0x00, 0x00,
0x67, 0x6c, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00,
0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x29, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74,
0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00,
0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43,
0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00,
0x06, 0x00, 0x07, 0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x67, 0x6c, 0x5f, 0x43, 0x75, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61,
0x6e, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
0x48, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x48, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x2c, 0x00, 0x05, 0x00,
0x07, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x05, 0x00,
0x07, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
0x2c, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00,
0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x17, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x21, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x25, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00,
0x2d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x2d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x32, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x50, 0x00, 0x07, 0x00, 0x26, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x34, 0x00, 0x00, 0x00,
0x35, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x35, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
};
unsigned int tri_vspv_len = 1496;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment