Skip to content

Instantly share code, notes, and snippets.

@skrollilehti
Forked from DataBeaver/gl_new.c
Created March 5, 2022 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skrollilehti/a46444dd722e11482fcf3d7a564f5d2e to your computer and use it in GitHub Desktop.
Save skrollilehti/a46444dd722e11482fcf3d7a564f5d2e to your computer and use it in GitHub Desktop.
Graphics API comparison
#include <X11/Xlib.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glext.h>
const char *vertex_src =
"#version 330 core\n"
"layout(location=0) in vec2 position;\n"
"layout(location=1) in vec3 color;\n"
"out vec3 v_color;\n"
"void main()\n"
"{\n"
" v_color = color;\n"
" gl_Position = vec4(position, 0.0, 1.0);\n"
"}\n";
const char *fragment_src =
"#version 330 core\n"
"in vec3 v_color;\n"
"out vec4 frag_color;\n"
"void main()\n"
"{\n"
" frag_color = vec4(v_color, 1.0);\n"
"}\n";
float vertex_data[] =
{
-0.5f, -0.7f, 1.0f, 0.0f, 0.0f,
0.5f, -0.7f, 0.0f, 1.0f, 0.0f,
0.0f, 0.7f, 0.0f, 0.0f, 1.0f
};
int main()
{
Display *display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
glXQueryExtension(display, NULL, NULL);
int fb_attribs[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, 1,
0 };
int n_configs = 0;
GLXFBConfig *fb_configs = glXChooseFBConfig(display, DefaultScreen(display), fb_attribs, &n_configs);
XVisualInfo *vi = glXGetVisualFromFBConfig(display, fb_configs[0]);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, root, vi->visual, AllocNone);
Window window = XCreateWindow(display, root, 0, 0, 1280, 720, 0,
vi->depth, InputOutput, vi->visual, CWColormap, &attr);
GLXWindow glxwnd = glXCreateWindow(display, fb_configs[0], window, 0);
int ctx_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_TYPE,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
0 };
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB");
GLXContext context = glXCreateContextAttribs(display, fb_configs[0], 0, True, ctx_attribs);
XFree(vi);
XFree(fb_configs);
XMapWindow(display, window);
glXMakeContextCurrent(display, glxwnd, glxwnd, context);
unsigned vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_src, NULL);
glCompileShader(vertex_shader);
unsigned fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_src, NULL);
glCompileShader(fragment_shader);
unsigned shprog = glCreateProgram();
glAttachShader(shprog, vertex_shader);
glAttachShader(shprog, fragment_shader);
glLinkProgram(shprog);
unsigned vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
unsigned vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(2*sizeof(float)));
glEnableVertexAttribArray(1);
glUseProgram(shprog);
while(1)
{
int pending = XPending(display);
while(pending--)
{
XEvent event;
XNextEvent(display, &event);
}
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glXSwapBuffers(display, glxwnd);
}
return 0;
}
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/gl.h>
int main()
{
Display *display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
glXQueryExtension(display, NULL, NULL);
int attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0 };
XVisualInfo *vi = glXChooseVisual(display, DefaultScreen(display), attribs);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, root, vi->visual, AllocNone);
Window window = XCreateWindow(display, root, 0, 0, 1280, 720, 0,
vi->depth, InputOutput, vi->visual, CWColormap, &attr);
GLXContext context = glXCreateContext(display, vi, 0, True);
XFree(vi);
XMapWindow(display, window);
glXMakeCurrent(display, window, context);
while(1)
{
int pending = XPending(display);
while(pending--)
{
XEvent event;
XNextEvent(display, &event);
}
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f, -0.7f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.5f, -0.7f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.7f, 0.0f);
glEnd();
glXSwapBuffers(display, window);
}
return 0;
}
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#define VK_USE_PLATFORM_XLIB_KHR
#include <vulkan/vulkan.h>
const uint32_t shader_binary[] =
{
119734787, 66816, 1900544, 35, 0, 131089, 1, 196622, 0, 1, 589839, 0, 19,
1852399981, 0, 13, 15, 17, 11, 458767, 4, 31, 1852399981, 0, 29, 30, 196624,
31, 7, 262149, 1, 1684631414, 0, 196613, 2, 7630441, 262149, 3, 1634692198,
116, 262149, 4, 845374838, 0, 262149, 5, 862152054, 0, 262149, 6, 878929270,
0, 393221, 7, 1348430951, 1700164197, 2019914866, 0, 393222, 7, 0,
1348430951, 1953067887, 7237481, 458758, 7, 1, 1348430951, 1953393007,
1702521171, 0, 458758, 7, 2, 1130327143, 1148217708, 1635021673, 6644590,
327685, 13, 1769172848, 1852795252, 0, 262149, 15, 1869377379, 114, 262149,
17, 1868783478, 7499628, 262149, 18, 1684631414, 10536, 262149, 19,
1852399981, 10536, 262149, 1, 1684631414, 0, 262149, 3, 1634692198, 116,
262149, 5, 862152054, 0, 262149, 6, 878929270, 0, 262149, 29, 1868783478,
7499628, 327685, 30, 1734439526, 1819239263, 29295, 262149, 31, 1852399981,
10536, 196679, 7, 2, 327752, 7, 0, 11, 0, 327752, 7, 1, 11, 1, 262215, 9, 6,
16, 327752, 7, 2, 11, 3, 262215, 13, 30, 0, 262215, 15, 30, 1, 262215, 17,
30, 0, 262215, 29, 30, 0, 262215, 30, 30, 0, 131091, 1, 262165, 2, 32, 1,
196630, 3, 32, 262167, 4, 3, 2, 262167, 5, 3, 3, 262167, 6, 3, 4, 262187, 2,
8, 1, 262172, 9, 3, 8, 327710, 7, 6, 3, 9, 262176, 10, 3, 7, 262203, 10, 11,
3, 262176, 12, 1, 4, 262203, 12, 13, 1, 262176, 14, 1, 5, 262203, 14, 15, 1,
262176, 16, 3, 5, 262203, 16, 17, 3, 196641, 18, 1, 262187, 3, 23, 0,
262187, 3, 24, 1065353216, 262187, 2, 26, 0, 262176, 27, 3, 6, 262203, 14,
29, 1, 262203, 27, 30, 3, 327734, 1, 19, 0, 18, 131320, 20, 262205, 5, 21,
15, 196670, 17, 21, 262205, 4, 22, 13, 393296, 6, 25, 22, 23, 24, 327745,
27, 28, 11, 26, 196670, 28, 25, 65789, 65592, 327734, 1, 31, 0, 18, 131320,
32, 262205, 5, 33, 29, 327760, 6, 34, 33, 24, 196670, 30, 34, 65789, 65592
};
float vertex_data[] =
{
-0.5f, 0.7f, 1.0f, 0.0f, 0.0f,
0.5f, 0.7f, 0.0f, 1.0f, 0.0f,
0.0f, -0.7f, 0.0f, 0.0f, 1.0f
};
int main()
{
Display *display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
Window window = XCreateWindow(display, root, 0, 0, 1280, 720, 0,
CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
const char *extensions[] = { "VK_KHR_surface", "VK_KHR_xlib_surface" };
VkApplicationInfo app_info =
{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.apiVersion = (1<<22)|(2<<12)
};
VkInstanceCreateInfo instance_create_info =
{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &app_info,
.enabledExtensionCount = 2,
.ppEnabledExtensionNames = extensions
};
VkInstance instance;
vkCreateInstance(&instance_create_info, 0, &instance);
VkXlibSurfaceCreateInfoKHR surface_create_info =
{
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
.dpy = display,
.window = window
};
VkSurfaceKHR surface;
vkCreateXlibSurfaceKHR(instance, &surface_create_info, 0, &surface);
unsigned n_phys_devices = 0;
vkEnumeratePhysicalDevices(instance, &n_phys_devices, 0);
VkPhysicalDevice *phys_devices = malloc(n_phys_devices*sizeof(VkPhysicalDevice));
vkEnumeratePhysicalDevices(instance, &n_phys_devices, phys_devices);
VkPhysicalDevice physical_device;
unsigned gfx_queue_index = 0;
for(unsigned i=0; i<n_phys_devices; ++i)
{
physical_device = phys_devices[i];
unsigned n_queue_families = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &n_queue_families, 0);
VkQueueFamilyProperties *queue_family_props = malloc(n_queue_families*sizeof(VkQueueFamilyProperties));
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &n_queue_families, queue_family_props);
for(; gfx_queue_index<n_queue_families; ++gfx_queue_index)
if((queue_family_props[gfx_queue_index].queueFlags&VK_QUEUE_GRAPHICS_BIT))
break;
free(queue_family_props);
if(gfx_queue_index>=n_queue_families)
continue;
VkBool32 supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, gfx_queue_index, surface, &supported);
if(supported)
break;
}
free(phys_devices);
float queue_priority = 1.0f;
VkDeviceQueueCreateInfo queue_create_info =
{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = gfx_queue_index,
.queueCount = 1,
.pQueuePriorities = &queue_priority
};
const char *dev_extensions[] = { "VK_KHR_swapchain" };
VkDeviceCreateInfo device_create_info =
{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queue_create_info,
.enabledExtensionCount = 1,
.ppEnabledExtensionNames = dev_extensions
};
VkDevice device;
vkCreateDevice(physical_device, &device_create_info, 0, &device);
VkQueue graphics_queue;
vkGetDeviceQueue(device, gfx_queue_index, 0, &graphics_queue);
VkSwapchainCreateInfoKHR swapchain_info =
{
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.surface = surface,
.minImageCount = 2,
.imageExtent.width = 1280,
.imageExtent.height = 720,
.imageArrayLayers = 1,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.clipped = VK_TRUE
};
VkSurfaceCapabilitiesKHR surface_caps;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_caps);
swapchain_info.preTransform = surface_caps.currentTransform;
swapchain_info.compositeAlpha = surface_caps.supportedCompositeAlpha&~(surface_caps.supportedCompositeAlpha-1);
uint32_t n_formats = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &n_formats, 0);
VkSurfaceFormatKHR *surface_formats = malloc(n_formats*sizeof(VkSurfaceFormatKHR));
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &n_formats, surface_formats);
for(unsigned i=0; i<n_formats; ++i)
{
const VkSurfaceFormatKHR *format = surface_formats+i;
if(format->format!=VK_FORMAT_R8G8B8_SRGB && format->format!=VK_FORMAT_B8G8R8_SRGB)
{
swapchain_info.imageFormat = format->format;
swapchain_info.imageColorSpace = format->colorSpace;
break;
}
}
free(surface_formats);
uint32_t n_present_modes = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &n_present_modes, 0);
VkPresentModeKHR *present_modes = malloc(n_present_modes*sizeof(VkPresentModeKHR));
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &n_present_modes, present_modes);
swapchain_info.presentMode = present_modes[0];
for(unsigned i=0; i<n_present_modes; ++i)
if(present_modes[i]==VK_PRESENT_MODE_FIFO_KHR)
{
swapchain_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
break;
}
free(present_modes);
VkSwapchainKHR swapchain;
vkCreateSwapchainKHR(device, &swapchain_info, NULL, &swapchain);
VkAttachmentDescription attachment =
{
.format = swapchain_info.imageFormat,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
};
VkAttachmentReference color_ref =
{
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
};
VkSubpassDescription subpass =
{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = 1,
.pColorAttachments = &color_ref
};
VkSubpassDependency dependency =
{
.srcSubpass = 0,
.dstSubpass = VK_SUBPASS_EXTERNAL,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
.dstAccessMask = 0,
};
VkRenderPassCreateInfo render_pass_info =
{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = &attachment,
.subpassCount = 1,
.pSubpasses = &subpass,
.dependencyCount = 1,
.pDependencies = &dependency
};
VkRenderPass render_pass;
vkCreateRenderPass(device, &render_pass_info, NULL, &render_pass);
uint32_t n_swap_images = 0;
vkGetSwapchainImagesKHR(device, swapchain, &n_swap_images, 0);
VkImage *swap_images = malloc(n_swap_images*sizeof(VkImage));
vkGetSwapchainImagesKHR(device, swapchain, &n_swap_images, swap_images);
VkImageView *swap_views = malloc(n_swap_images*sizeof(VkImageView));
VkFramebuffer *framebuffers = malloc(n_swap_images*sizeof(VkFramebuffer));
for(unsigned i=0; i<n_swap_images; ++i)
{
VkImageViewCreateInfo view_info =
{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = swap_images[i],
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = swapchain_info.imageFormat,
.components =
{
.r = VK_COMPONENT_SWIZZLE_R,
.g = VK_COMPONENT_SWIZZLE_G,
.b = VK_COMPONENT_SWIZZLE_B,
.a = VK_COMPONENT_SWIZZLE_A,
},
.subresourceRange =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1
}
};
vkCreateImageView(device, &view_info, NULL, &swap_views[i]);
VkFramebufferCreateInfo framebuffer_info =
{
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.renderPass = render_pass,
.attachmentCount = 1,
.pAttachments = &swap_views[i],
.width = 1280,
.height = 720,
.layers = 1
};
vkCreateFramebuffer(device, &framebuffer_info, NULL, &framebuffers[i]);
}
unsigned frames_in_flight = (n_swap_images>=3 ? 3 : n_swap_images);
VkCommandPool *command_pools = malloc(frames_in_flight*sizeof(VkCommandPool));
VkCommandBuffer *command_buffers = malloc(frames_in_flight*sizeof(VkCommandBuffer));
for(unsigned i=0; i<frames_in_flight; ++i)
{
VkCommandPoolCreateInfo pool_info =
{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = gfx_queue_index
};
vkCreateCommandPool(device, &pool_info, NULL, &command_pools[i]);
VkCommandBufferAllocateInfo alloc_info =
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = command_pools[i],
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1
};
vkAllocateCommandBuffers(device, &alloc_info, &command_buffers[i]);
}
VkSemaphore *semaphores = malloc(frames_in_flight*2*sizeof(VkSemaphore));
for(unsigned i=0; i<frames_in_flight*2; ++i)
{
VkSemaphoreCreateInfo semaphore_info =
{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
};
vkCreateSemaphore(device, &semaphore_info, NULL, &semaphores[i]);
}
VkFence *fences = malloc(frames_in_flight*sizeof(VkFence));
for(unsigned i=0; i<frames_in_flight; ++i)
{
VkFenceCreateInfo fence_info =
{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = VK_FENCE_CREATE_SIGNALED_BIT
};
vkCreateFence(device, &fence_info, NULL, &fences[i]);
}
VkShaderModuleCreateInfo module_info =
{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = sizeof(shader_binary),
.pCode = shader_binary
};
VkShaderModule module;
vkCreateShaderModule(device, &module_info, NULL, &module);
VkPipelineLayoutCreateInfo layout_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
};
VkPipelineLayout layout;
vkCreatePipelineLayout(device, &layout_info, NULL, &layout);
VkPipelineShaderStageCreateInfo stage_infos[2] =
{
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = module,
.pName = "main"
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = module,
.pName = "main"
}
};
VkVertexInputBindingDescription vertex_input_binding =
{
.binding = 0,
.stride = 5*sizeof(float),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
};
VkVertexInputAttributeDescription vertex_attribs[2] =
{
{
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = 0
},
{
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = 2*sizeof(float)
}
};
VkPipelineVertexInputStateCreateInfo vertex_input_state =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &vertex_input_binding,
.vertexAttributeDescriptionCount = 2,
.pVertexAttributeDescriptions = vertex_attribs
};
VkPipelineInputAssemblyStateCreateInfo input_assembly_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = VK_FALSE
};
VkPipelineViewportStateCreateInfo viewport_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1,
.pViewports = NULL,
.scissorCount = 1,
.pScissors = NULL
};
VkPipelineRasterizationStateCreateInfo raster_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_FALSE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
.depthBiasClamp = 0.0f,
.depthBiasSlopeFactor = 0.0f,
.lineWidth = 1.0f
};
VkPipelineMultisampleStateCreateInfo multisample_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.sampleShadingEnable = VK_FALSE,
.minSampleShading = 1.0f,
.pSampleMask = 0,
.alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE
};
VkPipelineDepthStencilStateCreateInfo depth_stencil_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_FALSE,
.depthWriteEnable = VK_FALSE,
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
.depthBoundsTestEnable = VK_FALSE,
.stencilTestEnable = VK_FALSE,
.front =
{
.failOp = VK_STENCIL_OP_KEEP,
.passOp = VK_STENCIL_OP_KEEP,
.depthFailOp = VK_STENCIL_OP_KEEP,
.compareOp = VK_COMPARE_OP_EQUAL,
.compareMask = 0xFFFFFFFFU,
.writeMask = 0xFFFFFFFFU,
.reference = 0
}
};
depth_stencil_info.front = depth_stencil_info.back;
VkPipelineColorBlendAttachmentState blend_attachment =
{
.blendEnable = VK_FALSE,
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = blend_attachment.srcColorBlendFactor,
.dstAlphaBlendFactor = blend_attachment.dstColorBlendFactor,
.alphaBlendOp = blend_attachment.colorBlendOp,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
};
VkPipelineColorBlendStateCreateInfo blend_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = &blend_attachment
};
VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamic_info =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = 2,
.pDynamicStates = dynamic_states
};
VkGraphicsPipelineCreateInfo pipeline_info =
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = 2,
.pStages = stage_infos,
.pVertexInputState = &vertex_input_state,
.pInputAssemblyState = &input_assembly_info,
.pViewportState = &viewport_info,
.pRasterizationState = &raster_info,
.pMultisampleState = &multisample_info,
.pDepthStencilState = &depth_stencil_info,
.pColorBlendState = &blend_info,
.pDynamicState = &dynamic_info,
.layout = layout,
.renderPass = render_pass,
.subpass = 0
};
VkPipeline pipeline;
vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline);
VkBufferCreateInfo buffer_info =
{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = sizeof(vertex_data),
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
VkBuffer vertex_buffer;
vkCreateBuffer(device, &buffer_info, NULL, &vertex_buffer);
VkPhysicalDeviceMemoryProperties mem_props;
vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_props);
VkMemoryRequirements requirements;
vkGetBufferMemoryRequirements(device, vertex_buffer, &requirements);
VkMemoryAllocateInfo alloc_info =
{
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = requirements.size
};
const VkMemoryPropertyFlags mem_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
for(unsigned i=0; i<mem_props.memoryTypeCount; ++i)
if((requirements.memoryTypeBits&(1<<i)) && (mem_props.memoryTypes[i].propertyFlags&mem_flags)==mem_flags)
{
alloc_info.memoryTypeIndex = i;
break;
}
VkDeviceMemory memory;
vkAllocateMemory(device, &alloc_info, NULL, &memory);
vkBindBufferMemory(device, vertex_buffer, memory, 0);
void *mapped_address;
vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, &mapped_address);
memcpy(mapped_address, vertex_data, sizeof(vertex_data));
XMapWindow(display, window);
int first_frame = 1;
unsigned frame_index = 0;
while(1)
{
int pending = XPending(display);
while(pending--)
{
XEvent event;
XNextEvent(display, &event);
}
uint32_t image_index;
vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, semaphores[frame_index*2], 0, &image_index);
vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX);
vkResetCommandPool(device, command_pools[frame_index], 0);
vkResetFences(device, 1, &fences[frame_index]);
VkCommandBuffer cmd_buf = command_buffers[frame_index];
VkCommandBufferBeginInfo buffer_begin_info =
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
};
vkBeginCommandBuffer(cmd_buf, &buffer_begin_info);
if(first_frame)
{
VkBufferMemoryBarrier barrier =
{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = vertex_buffer,
.offset = 0,
.size = VK_WHOLE_SIZE
};
vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0,
1, &barrier, 0, NULL);
first_frame = 0;
}
VkClearValue clear_value = { .color.float32 = { 0.0f, 0.0f, 0.0f, 1.0f } };
VkRenderPassBeginInfo pass_begin_info =
{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = render_pass,
.framebuffer = framebuffers[image_index],
.clearValueCount = 1,
.pClearValues = &clear_value,
.renderArea =
{
.offset.x = 0,
.offset.y = 0,
.extent.width = 1280,
.extent.height = 720,
}
};
vkCmdBeginRenderPass(cmd_buf, &pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDeviceSize vbuf_offset = 0;
vkCmdBindVertexBuffers(cmd_buf, 0, 1, &vertex_buffer, &vbuf_offset);
VkViewport viewport =
{
.width = 1280,
.height = 720,
.minDepth = 0.0f,
.maxDepth = 1.0f
};
vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
VkRect2D scissor =
{
.extent.width = 1280,
.extent.height = 720
};
vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
vkCmdDraw(cmd_buf, 3, 1, 0, 0);
vkCmdEndRenderPass(cmd_buf);
vkEndCommandBuffer(cmd_buf);
VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
VkSubmitInfo submit_info =
{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.pWaitSemaphores = semaphores+frame_index*2,
.pWaitDstStageMask = &wait_stages,
.commandBufferCount = 1,
.pCommandBuffers = &cmd_buf,
.signalSemaphoreCount = 1,
.pSignalSemaphores = semaphores+frame_index*2+1
};
vkQueueSubmit(graphics_queue, 1, &submit_info, fences[frame_index]);
VkPresentInfoKHR present_info =
{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
.pWaitSemaphores = semaphores+frame_index*2+1,
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &image_index
};
vkQueuePresentKHR(graphics_queue, &present_info);
frame_index = (frame_index+1)%frames_in_flight;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment