Skip to content

Instantly share code, notes, and snippets.

@colbyhall
Created July 3, 2020 23:47
Show Gist options
  • Select an option

  • Save colbyhall/a2c4176b4ae080d75b9142cef1680dfb to your computer and use it in GitHub Desktop.

Select an option

Save colbyhall/a2c4176b4ae080d75b9142cef1680dfb to your computer and use it in GitHub Desktop.
#include "vulkan.h"
#include "string.h"
// #include <glslang/Public/ShaderLang.h>
// #include <glslang/Include/glslang_c_interface.h>
Render_Context* g_render_context = nullptr;
static const char* const instance_layers[] = {
"VK_LAYER_KHRONOS_validation",
// VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
};
static VKAPI_ATTR VkBool32 VKAPI_CALL
vulkan_debug_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
void* user_data
) {
if (severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
log_error("[Vulkan] %s", callback_data->pMessage);
}
return true;
}
VkInstanceCreateInfo make_instance_create_info();
void create_surface(Platform* platform);
void init_vulkan(Platform* platform) {
g_render_context = alloc_struct(platform->permanent_arena, Render_Context);
defer(g_render_context->initialized = true);
// @NOTE(colby): Create the vulkan instance
{
VkInstanceCreateInfo create_info = make_instance_create_info(); // Abstracted into a function because os specific implementation
create_info.ppEnabledLayerNames = instance_layers;
create_info.enabledLayerCount = ARRAY_COUNT(instance_layers);
VkResult result = vkCreateInstance(&create_info, nullptr, &g_render_context->instance);
assert(result == VK_SUCCESS);
}
// @NOTE(colby): Create the debug messenger
/**
* Apparently this extension isn't on this machine
{
const VkDebugUtilsMessengerCreateInfoEXT create_info = {
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
nullptr,
0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
vulkan_debug_callback,
nullptr
};
PFN_vkCreateDebugUtilsMessengerEXT const vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(g_render_context->instance, "vkCreateDebugUtilsMessengerEXT");
VkResult result = vkCreateDebugUtilsMessengerEXT(g_render_context->instance, &create_info, nullptr, &g_render_context->debug_messenger);
assert(result == VK_SUCCESS);
}
*/
create_surface(platform); // Abstracted into a function because os specific implementation
// @NOTE(colby): We now need to pick our actual GPU
{
u32 device_count = 0;
vkEnumeratePhysicalDevices(g_render_context->instance, &device_count, nullptr);
assert(device_count > 0);
Array<VkPhysicalDevice> devices = make_array<VkPhysicalDevice>(device_count);
defer(array_free(&devices));
devices.len = device_count;
vkEnumeratePhysicalDevices(g_render_context->instance, &device_count, devices.data);
VkPhysicalDevice selected_gpu = VK_NULL_HANDLE;
for (VkPhysicalDevice device : devices) {
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties);
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(device, &features);
// @TODO(colby): Maybe do more checking with features we actually will need like KHR Swapchain support?
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && features.geometryShader) {
selected_gpu = device;
break;
}
}
assert(selected_gpu != VK_NULL_HANDLE);
g_render_context->physical_gpu = selected_gpu;
}
u32 queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(g_render_context->physical_gpu, &queue_family_count, nullptr);
assert(queue_family_count > 0);
Array<VkQueueFamilyProperties> queue_families = make_array<VkQueueFamilyProperties>(queue_family_count);
defer(array_free(&queue_families));
queue_families.len = queue_family_count;
vkGetPhysicalDeviceQueueFamilyProperties(g_render_context->physical_gpu, &queue_family_count, queue_families.data);
int graphics_family_index = -1;
int surface_family_index = -1;
for (usize i = 0; i < queue_families.len; ++i) {
const VkQueueFamilyProperties& queue_family = queue_families[i];
if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
graphics_family_index = (int)i;
}
VkBool32 present_support = false;
vkGetPhysicalDeviceSurfaceSupportKHR(g_render_context->physical_gpu, (u32)i, g_render_context->surface, &present_support);
if (present_support) {
surface_family_index = (int)i;
}
}
assert(graphics_family_index != -1 && surface_family_index != -1);
const u32 queue_family_indices[] = {
(u32)graphics_family_index,
(u32)surface_family_index
};
// @NOTE(colby): Setup logical device and queues
{
Array<VkDeviceQueueCreateInfo> queues_create_info = make_array<VkDeviceQueueCreateInfo>(ARRAY_COUNT(queue_family_indices));
defer(array_free(&queues_create_info));
f32 queue_priority = 1.f;
for (int i = 0; i < ARRAY_COUNT(queue_family_indices); ++i) {
VkDeviceQueueCreateInfo create_info = {
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
nullptr,
0,
(u32)queue_family_indices[i],
1,
&queue_priority
};
array_push(&queues_create_info, create_info);
}
VkPhysicalDeviceFeatures logical_device_features = {};
static const char* const logical_device_extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
VkDeviceCreateInfo logical_device_create_info = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
nullptr,
0,
(u32)queues_create_info.len,
queues_create_info.data,
ARRAY_COUNT(instance_layers),
instance_layers,
ARRAY_COUNT(logical_device_extensions),
logical_device_extensions,
&logical_device_features
};
VkResult result = vkCreateDevice(
g_render_context->physical_gpu,
&logical_device_create_info,
nullptr,
&g_render_context->logical_gpu
);
assert(result == VK_SUCCESS);
vkGetDeviceQueue(
g_render_context->logical_gpu,
graphics_family_index,
0,
&g_render_context->graphics_queue
);
vkGetDeviceQueue(
g_render_context->logical_gpu,
surface_family_index,
0,
&g_render_context->presentation_queue
);
}
// @NOTE(colby): Swap chain shit.
// @TODO(colby): Abstract this out since it will need to be recreated with every window change
{
VkSurfaceCapabilitiesKHR surface_capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
g_render_context->physical_gpu,
g_render_context->surface,
&surface_capabilities
);
u32 format_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(
g_render_context->physical_gpu,
g_render_context->surface,
&format_count,
nullptr
);
Array<VkSurfaceFormatKHR> formats = make_array<VkSurfaceFormatKHR>(format_count);
defer(array_free(&formats));
formats.len = format_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(
g_render_context->physical_gpu,
g_render_context->surface,
&format_count,
formats.data
);
VkSurfaceFormatKHR selected_format = {};
b32 found_format = false;
for (VkSurfaceFormatKHR format : formats) {
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
found_format = true;
selected_format = format;
break;
}
}
assert(found_format);
VkPresentModeKHR present_modes[12];
u32 present_mode_count;
vkGetPhysicalDeviceSurfacePresentModesKHR(
g_render_context->physical_gpu,
g_render_context->surface,
&present_mode_count,
present_modes
);
VkPresentModeKHR selected_present_mode = VK_PRESENT_MODE_FIFO_KHR;
VkSwapchainCreateInfoKHR create_info = {
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
nullptr,
0,
g_render_context->surface,
surface_capabilities.minImageCount,
selected_format.format,
selected_format.colorSpace,
surface_capabilities.currentExtent,
1,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_SHARING_MODE_CONCURRENT,
ARRAY_COUNT(queue_family_indices),
queue_family_indices,
surface_capabilities.currentTransform,
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
selected_present_mode,
VK_TRUE,
VK_NULL_HANDLE,
};
VkResult result = vkCreateSwapchainKHR(
g_render_context->logical_gpu,
&create_info,
nullptr,
&g_render_context->swap_chain
);
assert(result == VK_SUCCESS);
g_render_context->swap_chain_extents = surface_capabilities.currentExtent;
u32 image_count = 0;
vkGetSwapchainImagesKHR(
g_render_context->logical_gpu,
g_render_context->swap_chain,
&image_count,
nullptr
);
array_reserve(&g_render_context->swap_chain_images, image_count);
g_render_context->swap_chain_images.len = image_count;
vkGetSwapchainImagesKHR(
g_render_context->logical_gpu,
g_render_context->swap_chain,
&image_count,
g_render_context->swap_chain_images.data
);
array_reserve(&g_render_context->swap_chain_image_views, image_count);
g_render_context->swap_chain_image_views.len = image_count;
for (usize i = 0; i < g_render_context->swap_chain_images.len; ++i) {
static const VkComponentMapping component_mapping = {
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY,
};
static const VkImageSubresourceRange subresource_range = {
VK_IMAGE_ASPECT_COLOR_BIT,
0,
1,
0,
1
};
VkImageViewCreateInfo image_create_info = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
nullptr,
0,
g_render_context->swap_chain_images[i],
VK_IMAGE_VIEW_TYPE_2D,
VK_FORMAT_B8G8R8A8_SRGB,
component_mapping,
subresource_range
};
result = vkCreateImageView(
g_render_context->logical_gpu,
&image_create_info,
nullptr,
&g_render_context->swap_chain_image_views[i]
);
assert(result == VK_SUCCESS);
}
}
// @NOTE(colby): Create render pass
{
VkAttachmentDescription color_attachment = {
0,
VK_FORMAT_B8G8R8A8_SRGB,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
};
VkAttachmentReference color_attachment_ref = {
0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
};
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_attachment_ref;
VkSubpassDependency dependency = {
VK_SUBPASS_EXTERNAL,
0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
0
};
VkRenderPassCreateInfo create_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
1,
&color_attachment,
1,
&subpass,
1,
&dependency,
};
VkResult result = vkCreateRenderPass(
g_render_context->logical_gpu,
&create_info,
nullptr,
&g_render_context->render_pass
);
assert(result == VK_SUCCESS);
}
// @NOTE(colby): Pipeline creation
{
VkShaderModule frag_shader_module;
VkShaderModule vert_shader_module;
// @NOTE(colby): Shader creation
{
String vert;
if (!os_read_file_into_string("assets\\shaders\\triangle.vspv", &vert)) {
assert(false);
}
VkShaderModuleCreateInfo shader_create_info {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
nullptr,
0,
vert.len,
(const u32*)vert.data
};
VkResult result = vkCreateShaderModule(
g_render_context->logical_gpu,
&shader_create_info,
nullptr,
&vert_shader_module
);
assert(result == VK_SUCCESS);
String frag;
if (!os_read_file_into_string("assets\\shaders\\triangle.fspv", &frag)) {
assert(false);
}
shader_create_info.codeSize = frag.len;
shader_create_info.pCode = (const u32*)frag.data;
result = vkCreateShaderModule(
g_render_context->logical_gpu,
&shader_create_info,
nullptr,
&frag_shader_module
);
assert(result == VK_SUCCESS);
}
VkPipelineShaderStageCreateInfo vert_shader_stage_info = {
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr,
0,
VK_SHADER_STAGE_VERTEX_BIT,
vert_shader_module,
"main",
nullptr
};
VkPipelineShaderStageCreateInfo frag_shader_stage_info = {
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr,
0,
VK_SHADER_STAGE_FRAGMENT_BIT,
frag_shader_module,
"main",
nullptr
};
VkPipelineShaderStageCreateInfo shader_stages[] = {
vert_shader_stage_info,
frag_shader_stage_info,
};
// @NOTE(colby): Define vertex attributes
VkPipelineVertexInputStateCreateInfo vertex_input_state = {
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
nullptr,
0,
0,
nullptr,
0,
nullptr,
};
VkPipelineInputAssemblyStateCreateInfo input_assembly_state = {
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
nullptr,
0,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
VK_FALSE,
};
VkViewport viewport = {
0.f,
0.f,
(f32)platform->window_width,
(f32)platform->window_height,
0.f,
1.f,
};
VkRect2D scissor = {
{ 0, 0 },
g_render_context->swap_chain_extents,
};
VkPipelineViewportStateCreateInfo viewport_state = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
nullptr,
0,
1,
&viewport,
1,
&scissor,
};
VkPipelineRasterizationStateCreateInfo rasterizer_state = {
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
nullptr,
0,
VK_FALSE,
VK_FALSE,
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_BACK_BIT,
VK_FRONT_FACE_CLOCKWISE,
VK_FALSE,
0.f,
0.f,
0.f,
1.f, // line width
};
VkPipelineMultisampleStateCreateInfo multisample_state = {
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
nullptr,
0,
VK_SAMPLE_COUNT_1_BIT,
VK_FALSE,
1.f,
nullptr,
VK_FALSE,
VK_FALSE,
};
VkPipelineColorBlendAttachmentState color_blend_attachment = {
VK_FALSE,
VK_BLEND_FACTOR_ONE,
VK_BLEND_FACTOR_ZERO,
VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_ONE,
VK_BLEND_FACTOR_ZERO,
VK_BLEND_OP_ADD,
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
VkPipelineColorBlendStateCreateInfo color_blend_state = {
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
nullptr,
0,
VK_FALSE,
VK_LOGIC_OP_COPY,
1,
&color_blend_attachment,
{ },
};
VkDynamicState dynamic_states[] = {
VK_DYNAMIC_STATE_VIEWPORT,
};
VkPipelineDynamicStateCreateInfo dynamic_state = {
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
nullptr,
0,
ARRAY_COUNT(dynamic_states),
dynamic_states,
};
VkPipelineLayoutCreateInfo pipeline_layout_info = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
0,
0,
nullptr,
0,
nullptr,
};
VkResult result = vkCreatePipelineLayout(
g_render_context->logical_gpu,
&pipeline_layout_info,
nullptr,
&g_render_context->pipeline_layout
);
assert(result == VK_SUCCESS);
VkGraphicsPipelineCreateInfo pipeline_create_info = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
nullptr,
0,
ARRAY_COUNT(shader_stages),
shader_stages,
&vertex_input_state,
&input_assembly_state,
nullptr,
&viewport_state,
&rasterizer_state,
&multisample_state,
nullptr, // @TODO(colby): depth stencil state
&color_blend_state,
nullptr, // @TODO(colby): dynamic state
g_render_context->pipeline_layout,
g_render_context->render_pass,
0,
VK_NULL_HANDLE,
-1,
};
result = vkCreateGraphicsPipelines(
g_render_context->logical_gpu,
VK_NULL_HANDLE, // @Incomplete(colby): Look into pipeline caches
1,
&pipeline_create_info,
nullptr,
&g_render_context->graphics_pipeline
);
assert(result == VK_SUCCESS);
}
// @NOTE(colby): Create swap chain framebuffers
{
g_render_context->swap_chain_framebuffers = make_array<VkFramebuffer>(g_render_context->swap_chain_image_views.len);
g_render_context->swap_chain_framebuffers.len = g_render_context->swap_chain_framebuffers.cap;
for (usize i = 0; i < g_render_context->swap_chain_image_views.len; ++i) {
VkImageView attachments[] = {
g_render_context->swap_chain_image_views[i],
};
VkFramebufferCreateInfo create_info = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr,
0,
g_render_context->render_pass,
ARRAY_COUNT(attachments),
attachments,
platform->window_width,
platform->window_height,
1,
};
VkResult result = vkCreateFramebuffer(
g_render_context->logical_gpu,
&create_info,
nullptr,
&g_render_context->swap_chain_framebuffers[i]
);
assert(result == VK_SUCCESS);
}
}
// @NOTE(colby): create command buffers and do triangle draw
{
// @NOTE(colby): Create a command pool which is used to allocate command buffers
VkCommandPoolCreateInfo pool_create_info = {
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
nullptr,
0,
(u32)graphics_family_index,
};
VkResult result = vkCreateCommandPool(
g_render_context->logical_gpu,
&pool_create_info,
nullptr,
&g_render_context->command_pool
);
assert(result == VK_SUCCESS);
// @@NOTE(colby): Allocate command buffer
g_render_context->command_buffers = make_array<VkCommandBuffer>(g_render_context->swap_chain_images.len);
g_render_context->command_buffers.len = g_render_context->command_buffers.cap;
VkCommandBufferAllocateInfo alloc_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
nullptr,
g_render_context->command_pool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
(u32)g_render_context->command_buffers.len,
};
result = vkAllocateCommandBuffers(
g_render_context->logical_gpu,
&alloc_info,
g_render_context->command_buffers.data
);
assert(result == VK_SUCCESS);
// @NOTE(colby): record draw commands to command buffers
for (usize i = 0; i < g_render_context->command_buffers.len; ++i) {
VkCommandBuffer command_buffer = g_render_context->command_buffers[i];
VkCommandBufferBeginInfo begin_info = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
nullptr,
0,
nullptr,
};
result = vkBeginCommandBuffer(command_buffer, &begin_info);
assert(result == VK_SUCCESS);
VkClearValue clear_color = { 0.f, 0.f, 0.f, 1.f };
// @NOTE(colby): Start render pass
VkRenderPassBeginInfo render_pass_begin_info = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
nullptr,
g_render_context->render_pass,
g_render_context->swap_chain_framebuffers[i],
{
{ 0, 0 },
g_render_context->swap_chain_extents,
},
1,
&clear_color,
};
vkCmdBeginRenderPass(
command_buffer,
&render_pass_begin_info,
VK_SUBPASS_CONTENTS_INLINE
);
vkCmdBindPipeline(
command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
g_render_context->graphics_pipeline
);
vkCmdDraw(command_buffer, 3, 1, 0, 0);
vkCmdEndRenderPass(command_buffer);
result = vkEndCommandBuffer(command_buffer);
assert(result == VK_SUCCESS);
}
}
// @NOTE(colby): Create semaphores
{
VkSemaphoreCreateInfo create_info = {
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
nullptr,
0,
};
VkResult result = vkCreateSemaphore(
g_render_context->logical_gpu,
&create_info,
nullptr,
&g_render_context->image_available_semaphore
);
assert(result == VK_SUCCESS);
result = vkCreateSemaphore(
g_render_context->logical_gpu,
&create_info,
nullptr,
&g_render_context->render_finished_semaphore
);
assert(result == VK_SUCCESS);
}
// glslang_initialize_process();
}
void draw_triangle() {
// @NOTE(colby): Wait untl we have an image we can draw to
u32 image_index;
vkAcquireNextImageKHR(
g_render_context->logical_gpu,
g_render_context->swap_chain,
U64_MAX,
g_render_context->image_available_semaphore,
VK_NULL_HANDLE,
&image_index
);
VkSemaphore wait_semaphores[] = {
g_render_context->image_available_semaphore,
};
VkPipelineStageFlags wait_stages[] = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
};
VkSemaphore signal_semaphores[] = {
g_render_context->render_finished_semaphore,
};
VkSubmitInfo submit_info = {
VK_STRUCTURE_TYPE_SUBMIT_INFO,
nullptr,
ARRAY_COUNT(wait_semaphores),
wait_semaphores,
wait_stages,
1,
&g_render_context->command_buffers[image_index],
ARRAY_COUNT(signal_semaphores),
signal_semaphores,
};
VkResult result = vkQueueSubmit(
g_render_context->graphics_queue,
1,
&submit_info,
VK_NULL_HANDLE
);
assert(result == VK_SUCCESS);
VkPresentInfoKHR present_info = {
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
nullptr,
1,
signal_semaphores,
1,
&g_render_context->swap_chain,
&image_index,
nullptr,
};
vkQueuePresentKHR(g_render_context->presentation_queue, &present_info);
}
#if 0
static const
glslang_resource_s default_glslang_resources = {
/* .MaxLights = */ 32,
/* .MaxClipPlanes = */ 6,
/* .MaxTextureUnits = */ 32,
/* .MaxTextureCoords = */ 32,
/* .MaxVertexAttribs = */ 64,
/* .MaxVertexUniformComponents = */ 4096,
/* .MaxVaryingFloats = */ 64,
/* .MaxVertexTextureImageUnits = */ 32,
/* .MaxCombinedTextureImageUnits = */ 80,
/* .MaxTextureImageUnits = */ 32,
/* .MaxFragmentUniformComponents = */ 4096,
/* .MaxDrawBuffers = */ 32,
/* .MaxVertexUniformVectors = */ 128,
/* .MaxVaryingVectors = */ 8,
/* .MaxFragmentUniformVectors = */ 16,
/* .MaxVertexOutputVectors = */ 16,
/* .MaxFragmentInputVectors = */ 15,
/* .MinProgramTexelOffset = */ -8,
/* .MaxProgramTexelOffset = */ 7,
/* .MaxClipDistances = */ 8,
/* .MaxComputeWorkGroupCountX = */ 65535,
/* .MaxComputeWorkGroupCountY = */ 65535,
/* .MaxComputeWorkGroupCountZ = */ 65535,
/* .MaxComputeWorkGroupSizeX = */ 1024,
/* .MaxComputeWorkGroupSizeY = */ 1024,
/* .MaxComputeWorkGroupSizeZ = */ 64,
/* .MaxComputeUniformComponents = */ 1024,
/* .MaxComputeTextureImageUnits = */ 16,
/* .MaxComputeImageUniforms = */ 8,
/* .MaxComputeAtomicCounters = */ 8,
/* .MaxComputeAtomicCounterBuffers = */ 1,
/* .MaxVaryingComponents = */ 60,
/* .MaxVertexOutputComponents = */ 64,
/* .MaxGeometryInputComponents = */ 64,
/* .MaxGeometryOutputComponents = */ 128,
/* .MaxFragmentInputComponents = */ 128,
/* .MaxImageUnits = */ 8,
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
/* .MaxCombinedShaderOutputResources = */ 8,
/* .MaxImageSamples = */ 0,
/* .MaxVertexImageUniforms = */ 0,
/* .MaxTessControlImageUniforms = */ 0,
/* .MaxTessEvaluationImageUniforms = */ 0,
/* .MaxGeometryImageUniforms = */ 0,
/* .MaxFragmentImageUniforms = */ 8,
/* .MaxCombinedImageUniforms = */ 8,
/* .MaxGeometryTextureImageUnits = */ 16,
/* .MaxGeometryOutputVertices = */ 256,
/* .MaxGeometryTotalOutputComponents = */ 1024,
/* .MaxGeometryUniformComponents = */ 1024,
/* .MaxGeometryVaryingComponents = */ 64,
/* .MaxTessControlInputComponents = */ 128,
/* .MaxTessControlOutputComponents = */ 128,
/* .MaxTessControlTextureImageUnits = */ 16,
/* .MaxTessControlUniformComponents = */ 1024,
/* .MaxTessControlTotalOutputComponents = */ 4096,
/* .MaxTessEvaluationInputComponents = */ 128,
/* .MaxTessEvaluationOutputComponents = */ 128,
/* .MaxTessEvaluationTextureImageUnits = */ 16,
/* .MaxTessEvaluationUniformComponents = */ 1024,
/* .MaxTessPatchComponents = */ 120,
/* .MaxPatchVertices = */ 32,
/* .MaxTessGenLevel = */ 64,
/* .MaxViewports = */ 16,
/* .MaxVertexAtomicCounters = */ 0,
/* .MaxTessControlAtomicCounters = */ 0,
/* .MaxTessEvaluationAtomicCounters = */ 0,
/* .MaxGeometryAtomicCounters = */ 0,
/* .MaxFragmentAtomicCounters = */ 8,
/* .MaxCombinedAtomicCounters = */ 8,
/* .MaxAtomicCounterBindings = */ 1,
/* .MaxVertexAtomicCounterBuffers = */ 0,
/* .MaxTessControlAtomicCounterBuffers = */ 0,
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
/* .MaxGeometryAtomicCounterBuffers = */ 0,
/* .MaxFragmentAtomicCounterBuffers = */ 1,
/* .MaxCombinedAtomicCounterBuffers = */ 1,
/* .MaxAtomicCounterBufferSize = */ 16384,
/* .MaxTransformFeedbackBuffers = */ 4,
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
/* .MaxCullDistances = */ 8,
/* .MaxCombinedClipAndCullDistances = */ 8,
/* .MaxSamples = */ 4,
/* .maxMeshOutputVerticesNV = */ 256,
/* .maxMeshOutputPrimitivesNV = */ 512,
/* .maxMeshWorkGroupSizeX_NV = */ 32,
/* .maxMeshWorkGroupSizeY_NV = */ 1,
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
/* .maxTaskWorkGroupSizeX_NV = */ 32,
/* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ {
/* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1,
/* .doWhileLoops = */ 1,
/* .generalUniformIndexing = */ 1,
/* .generalAttributeMatrixVectorIndexing = */ 1,
/* .generalVaryingIndexing = */ 1,
/* .generalSamplerIndexing = */ 1,
/* .generalVariableIndexing = */ 1,
/* .generalConstantMatrixVectorIndexing = */ 1,
}
};
b32 make_shader(Shader_Type type, String contents, Shader* out_shader) {
glslang_stage_t stage = {};
switch (type) {
case ST_Fragment:
stage = GLSLANG_STAGE_FRAGMENT;
break;
case ST_Vertex:
stage = GLSLANG_STAGE_VERTEX;
break;
default: invalid_code_path;
};
const glslang_input_t input = {
GLSLANG_SOURCE_GLSL,
stage,
GLSLANG_CLIENT_VULKAN,
GLSLANG_TARGET_VULKAN_1_1,
GLSLANG_TARGET_SPV,
GLSLANG_TARGET_SPV_1_3,
(const char*)contents.data,
100,
GLSLANG_NO_PROFILE,
false,
false,
GLSLANG_MSG_DEFAULT_BIT,
&default_glslang_resources,
};
glslang_shader_t* shader = glslang_shader_create(&input);
defer(glslang_shader_delete(shader));
if (!glslang_shader_preprocess(shader, &input)) {
// @TODO(colby): do error handling
return false;
}
if (!glslang_shader_parse(shader, &input)) {
// @TODO(colby): do error handling
return false;
}
glslang_program_t* program = glslang_program_create();
defer(glslang_program_delete(program));
glslang_program_add_shader(program, shader);
if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) {
// @TODO(colby): do error handling
return false;
}
glslang_program_SPIRV_generate(program, stage);
if (const char* message = glslang_program_SPIRV_get_messages(program)) {
// @TODO(colby): do error handling
}
const VkShaderModuleCreateInfo create_info = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
nullptr,
0,
glslang_program_SPIRV_get_size(program) * sizeof(u32),
glslang_program_SPIRV_get_ptr(program),
};
VkShaderModule module;
const VkResult result = vkCreateShaderModule(g_render_context->logical_gpu, &create_info, nullptr, &module);
if (result != VK_SUCCESS) {
// @TODO(colby): do error handling
return false;
}
return true;
}
void free_shader(Shader* shader) {
if (shader->module != VK_NULL_HANDLE) vkDestroyShaderModule(g_render_context->logical_gpu, shader->module, nullptr);
shader->module = VK_NULL_HANDLE;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment