
// VULKAN CONFIG

static const VkFormat 
VK_IMAGE_FORMATS[] = {
	VK_FORMAT_R16G16B16A16_UNORM,
	VK_FORMAT_R8G8B8A8_UNORM,
};

static VkApplicationInfo 
g_App_Info = {
	.sType = STYPE(APPLICATION_INFO),
	.pApplicationName = "Video Game",
	.applicationVersion = VK_MAKE_API_VERSION(0, 0, 0, 1),
	.pEngineName = "None (yet)",
	.engineVersion = VK_MAKE_API_VERSION(0, 0, 0, 1),
	.apiVersion = VK_API_VERSION_1_3,
};

static const char *
instance_layers[] = 
{
#ifdef BUILD_DEBUG
	"VK_LAYER_KHRONOS_validation"
#endif
};


static const char *
g_Instance_Extensions[] = 
{
	VK_KHR_SURFACE_EXTENSION_NAME,

#ifdef __linux__
	VK_KHR_XCB_SURFACE_EXTENSION_NAME,
#endif

#ifdef _WIN32
	VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
#endif

#ifdef BUILD_DEBUG
	VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
#endif
};

static VkInstanceCreateInfo 
g_Instance_Info = 
{
	.sType = STYPE(INSTANCE_CREATE_INFO),
	.pApplicationInfo = &g_App_Info,
	.enabledLayerCount = sizeof(instance_layers) / sizeof(char *),
	.ppEnabledLayerNames = instance_layers,
	.enabledExtensionCount = sizeof(g_Instance_Extensions) / sizeof(char *),
	.ppEnabledExtensionNames = g_Instance_Extensions,
};

const char *
g_Device_Extensions[] = 
{
	VK_KHR_SWAPCHAIN_EXTENSION_NAME,
	VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME,
};

#ifdef BUILD_DEBUG
static VkDebugUtilsMessengerCreateInfoEXT 
g_Debug_Message_Info = 
{
	.sType = STYPE(DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT),
	.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
										 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
	.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
								 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
								 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
	.pfnUserCallback = (PFN_vkDebugUtilsMessengerCallbackEXT)vDebugCallback,
};
#endif

static VkPhysicalDeviceVulkan13Features 
g_Vk_13_Features = 
{ 
	.sType = STYPE(PHYSICAL_DEVICE_VULKAN_1_3_FEATURES),
	.synchronization2 = VK_TRUE,
	.dynamicRendering = VK_TRUE
};

static VkPhysicalDeviceVulkan12Features 
g_Vk_12_Features = 
{
	.sType = STYPE(PHYSICAL_DEVICE_VULKAN_1_2_FEATURES),
	.pNext = &g_Vk_13_Features,
	.descriptorIndexing = VK_TRUE,
	.bufferDeviceAddress = VK_TRUE,
	.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE,
	.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
	.descriptorBindingStorageImageUpdateAfterBind = VK_TRUE,
	.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE,
	.descriptorBindingPartiallyBound = VK_TRUE,
	.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
	.shaderUniformBufferArrayNonUniformIndexing = VK_TRUE,
	.runtimeDescriptorArray = VK_TRUE,
};

static VkPhysicalDeviceVulkan11Features 
g_Vk_11_Features = 
{
	.sType = STYPE(PHYSICAL_DEVICE_VULKAN_1_1_FEATURES),
	.pNext = &g_Vk_12_Features
};

static const VkPhysicalDeviceFeatures2 
g_Vk_Features_2 = 
{
	.sType = STYPE(PHYSICAL_DEVICE_FEATURES_2),
	.pNext = &g_Vk_11_Features,
	.features = {
		.shaderUniformBufferArrayDynamicIndexing = VK_TRUE,
		.shaderSampledImageArrayDynamicIndexing = VK_TRUE,
		.shaderStorageBufferArrayDynamicIndexing = VK_TRUE,
		.shaderStorageImageArrayDynamicIndexing = VK_TRUE,
		.samplerAnisotropy											 = VK_TRUE,
	},
};

static VkDeviceCreateInfo 
g_Device_Info = 
{
	.sType = STYPE(DEVICE_CREATE_INFO),
	.pNext = &g_Vk_Features_2,
	.ppEnabledExtensionNames = g_Device_Extensions,
	.enabledExtensionCount = Len(g_Device_Extensions),
	.pEnabledFeatures = NULL,
};

static VmaAllocatorCreateInfo 
g_VMA_Create_Info = 
{
	.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT,
	.vulkanApiVersion = VK_API_VERSION_1_3,
};

static VkCommandPoolCreateInfo 
g_Pool_Create_Info = 
{
	.sType = STYPE(COMMAND_POOL_CREATE_INFO),
	.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
};

static VkFenceCreateInfo 
g_Fence_Create_Info = 
{
	.sType = STYPE(FENCE_CREATE_INFO),
	.flags = VK_FENCE_CREATE_SIGNALED_BIT,
};

static VkSemaphoreCreateInfo 
g_Semaphore_Create_Info = 
{
	.sType = STYPE(SEMAPHORE_CREATE_INFO),
};

static VkCommandBufferAllocateInfo 
g_Command_Buffer_Info = 
{
	.sType = STYPE(COMMAND_BUFFER_ALLOCATE_INFO),
	.commandBufferCount = 1,
	.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
};

static VkSwapchainCreateInfoKHR 
g_Swap_Info = 
{
	.sType = STYPE(SWAPCHAIN_CREATE_INFO_KHR),
	.imageArrayLayers = 1,
	.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
	.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
	.clipped = VK_TRUE,
	.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
};

static VkImageViewCreateInfo 
g_Swap_View_Info = 
{
	.sType = STYPE(IMAGE_VIEW_CREATE_INFO),
	.viewType = VK_IMAGE_VIEW_TYPE_2D,
	.components = {
		.r = VK_COMPONENT_SWIZZLE_IDENTITY,
		.g = VK_COMPONENT_SWIZZLE_IDENTITY,
		.b = VK_COMPONENT_SWIZZLE_IDENTITY,
		.a = VK_COMPONENT_SWIZZLE_IDENTITY,
	},
	.subresourceRange = {
		.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
		.baseMipLevel = 0,
		.levelCount = 1,
		.baseArrayLayer = 0,
		.layerCount = 1,
	},
};

static VkImageCreateInfo 
g_Draw_Image_Info =
{
	.sType = STYPE(IMAGE_CREATE_INFO),
	.imageType = VK_IMAGE_TYPE_2D,
	.mipLevels = 1,
	.arrayLayers = 1,
	.samples = VK_SAMPLE_COUNT_1_BIT,
	.tiling = VK_IMAGE_TILING_OPTIMAL,
	.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
};

static VkImageViewCreateInfo 
g_Draw_View_Info = 
{
	.sType = STYPE(IMAGE_VIEW_CREATE_INFO),
	.viewType = VK_IMAGE_VIEW_TYPE_2D,
	.subresourceRange = {
		.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
		.baseMipLevel = 0,
		.levelCount = 1,
		.baseArrayLayer = 0,
		.layerCount = 1,
	},
};

static VkImageCreateInfo 
g_Depth_Image_Info = 
{
	.sType = STYPE(IMAGE_CREATE_INFO),
	.imageType = VK_IMAGE_TYPE_2D,
	.mipLevels = 1,
	.arrayLayers = 1,
	.samples = VK_SAMPLE_COUNT_1_BIT,
	.tiling = VK_IMAGE_TILING_OPTIMAL,
	.format = VK_FORMAT_D32_SFLOAT,
	.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
};

static VkImageViewCreateInfo 
g_Depth_View_Info = 
{
	.sType = STYPE(IMAGE_VIEW_CREATE_INFO),
	.viewType = VK_IMAGE_VIEW_TYPE_2D,
	.format = VK_FORMAT_D32_SFLOAT,
	.subresourceRange = {
		.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
		.baseMipLevel = 0,
		.levelCount = 1,
		.baseArrayLayer = 0,
		.layerCount = 1,
	},
};

//
// PIPELINES & DESCRIPTORS
//

static VkDescriptorPoolSize 
g_Desc_Pool_Sizes[] =
{
	{ .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = 4096 },
	{ .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 4096},
	{ .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 4096},
	{ .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 4096},
	{ .type = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 4096 },
};

static VkDescriptorPoolCreateInfo 
g_Desc_Pool_Info = 
{
	.sType = STYPE(DESCRIPTOR_POOL_CREATE_INFO),
	.poolSizeCount = Len(g_Desc_Pool_Sizes),
	.pPoolSizes = g_Desc_Pool_Sizes,
	.maxSets = 12, // Not sure if this is correct
	.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
};

static VkDescriptorBindingFlags 
g_Shared_Binding_Flags[] = 
{	
	VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
	VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
	VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
	VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
};

static VkDescriptorSetLayoutBindingFlagsCreateInfo 
g_Shared_Desc_Flag_Info = 
{
	.sType = STYPE(DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO),
	.bindingCount = Len(g_Shared_Binding_Flags),
	.pBindingFlags = g_Shared_Binding_Flags,
};

static VkDescriptorSetLayoutBinding 
g_Shared_Desc_Bindings[] =
{
	{ .binding = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_ALL },
	{ .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_ALL },
	{ .binding = 2, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_ALL },
	{ .binding = 3, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_ALL },
};

static VkDescriptorSetLayoutCreateInfo 
g_Shared_Desc_Layout_Info = 
{
	.sType = STYPE(DESCRIPTOR_SET_LAYOUT_CREATE_INFO),
	.pNext = &g_Shared_Desc_Flag_Info,
	.bindingCount = Len(g_Shared_Desc_Bindings),
	.pBindings = g_Shared_Desc_Bindings,
	.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
};

static VkDescriptorType 
g_Desc_Type_Map[vDT_MAX] = 
{
	[vDT_SAMPLED_IMAGE] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
	[vDT_MATERIAL] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
	[vDT_MESH] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
};

static VkDescriptorBindingFlags 
g_Bindless_Binding_Flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;

static VkDescriptorSetLayoutBindingFlagsCreateInfo 
g_Bindless_Desc_Flag_Info = 
{
	.sType = STYPE(DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO),
	.bindingCount = 1,
	.pBindingFlags = &g_Bindless_Binding_Flags,
};

static VkDescriptorSetLayoutBinding 
g_Bindless_Desc_Binding = 
{
	.binding = 0,
	.descriptorCount = 1024,
	.stageFlags = VK_SHADER_STAGE_ALL,
};

static VkDescriptorSetLayoutCreateInfo 
g_Bindless_Desc_Info = 
{
	.sType = STYPE(DESCRIPTOR_SET_LAYOUT_CREATE_INFO),
	.pNext = &g_Bindless_Desc_Flag_Info,
	.bindingCount = 1,
	.pBindings = &g_Bindless_Desc_Binding,
	.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
};

static VkDescriptorSetAllocateInfo 
g_Descriptor_Alloc_Info = 
{
	.sType = STYPE(DESCRIPTOR_SET_ALLOCATE_INFO),
	.descriptorSetCount = vDT_MAX,
};

static VkPushConstantRange 
g_Push_Const_Range = 
{
	.offset = 0,
	.size = sizeof(rPushConst),
	.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT,
};

static VkPipelineLayoutCreateInfo 
g_Pipeline_Layout_Info = 
{
	.sType = STYPE(PIPELINE_LAYOUT_CREATE_INFO),
	.setLayoutCount = vDT_MAX, 
	.pushConstantRangeCount = 1,
	.pPushConstantRanges = &g_Push_Const_Range,
};

//
//	PIPELINES
//

#define PIPELINE_DYNAMIC_STATE { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }
 

static VkDynamicState 
g_Pipeline_Dynamic_State[] = PIPELINE_DYNAMIC_STATE;

#define PIPELINE_DEFAULT_DYN_STATE_INFO { \
	.sType = STYPE(PIPELINE_DYNAMIC_STATE_CREATE_INFO), \
	.pDynamicStates = g_Pipeline_Dynamic_State, \
	.dynamicStateCount = Len(g_Pipeline_Dynamic_State), \
}

static VkPipelineDynamicStateCreateInfo 
g_Pipeline_Default_Dynamic_Info = PIPELINE_DEFAULT_DYN_STATE_INFO;

#define PIPELINE_DEFAULT_ASSEMBLY_INFO { \
	.sType = STYPE(PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO), \
	.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, \
	.primitiveRestartEnable = VK_FALSE, \
}

static VkPipelineInputAssemblyStateCreateInfo 
g_Pipeline_Default_Assembly_Info = PIPELINE_DEFAULT_ASSEMBLY_INFO;

#define PIPELINE_DEFAULT_RASTERIZATION_INFO { \
	.sType = STYPE(PIPELINE_RASTERIZATION_STATE_CREATE_INFO), \
	.polygonMode = VK_POLYGON_MODE_FILL, \
	.lineWidth = 1.0, \
	.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, \
}

static VkPipelineRasterizationStateCreateInfo 
g_Pipeline_Default_Rasterization_Info = PIPELINE_DEFAULT_RASTERIZATION_INFO;

#define PIPELINE_DEFAULT_MULTISAMPLE_INFO { \
	.sType = STYPE(PIPELINE_MULTISAMPLE_STATE_CREATE_INFO), \
	.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, \
	.minSampleShading = 1.0, \
	.alphaToCoverageEnable = VK_FALSE, \
	.alphaToOneEnable = VK_FALSE, \
}

static VkPipelineMultisampleStateCreateInfo 
g_Pipeline_Default_Multisample_Info = PIPELINE_DEFAULT_MULTISAMPLE_INFO;

#define PIPELINE_DEFAULT_DEPTH_INFO { \
	.sType = STYPE(PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO), \
	.depthTestEnable = VK_TRUE, \
	.depthWriteEnable = VK_TRUE, \
	.depthCompareOp = VK_COMPARE_OP_GREATER_OR_EQUAL, \
	.depthBoundsTestEnable = VK_FALSE, \
	.stencilTestEnable = VK_FALSE, \
	.minDepthBounds = 0.0, \
	.maxDepthBounds = 1.0, \
}

static VkPipelineDepthStencilStateCreateInfo 
g_Pipeline_Default_Depth_Info = PIPELINE_DEFAULT_DEPTH_INFO;

#define PIPELINE_DEFAULT_RENDERING_INFO { \
	.sType = STYPE(PIPELINE_RENDERING_CREATE_INFO), \
	.colorAttachmentCount = 1, \
}

static VkPipelineRenderingCreateInfo 
g_Pipeline_Default_Rendering_Info = PIPELINE_DEFAULT_RENDERING_INFO;

#define PIPELINE_DEFAULT_BLEND_ATTACH_STATE { \
	.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, \
	.blendEnable = VK_FALSE, \
}

static VkPipelineColorBlendAttachmentState 
g_Pipeline_Default_Blend_State = PIPELINE_DEFAULT_BLEND_ATTACH_STATE;

#define PIPELINE_DEFAULT_BLEND_INFO { \
	.sType = STYPE(PIPELINE_COLOR_BLEND_STATE_CREATE_INFO), \
	.logicOpEnable = VK_FALSE, \
	.logicOp = VK_LOGIC_OP_COPY, \
	.attachmentCount = 1, \
	.pAttachments = &g_Pipeline_Default_Blend_State, \
}

static VkPipelineColorBlendStateCreateInfo 
g_Pipeline_Default_Blend_Info = PIPELINE_DEFAULT_BLEND_INFO;

#define PIPELINE_DEFAULT_VERTEX_INFO { \
	.sType = STYPE(PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO), \
}

static VkPipelineVertexInputStateCreateInfo 
g_Pipeline_Default_Vertex_Info = PIPELINE_DEFAULT_VERTEX_INFO;

#define PIPELINE_DEFAULT_VIEWPORT_INFO { \
	.sType = STYPE(PIPELINE_VIEWPORT_STATE_CREATE_INFO), \
	.viewportCount = 1, \
	.scissorCount = 1, \
}

const static VkPipelineViewportStateCreateInfo 
g_Pipeline_Default_Viewport_Info = PIPELINE_DEFAULT_VIEWPORT_INFO;


#define INIT_PIPELINE_DEFAULTS(pipeline)  																																\
VkPipelineDynamicStateCreateInfo g_##pipeline##_Default_Dynamic_Info = PIPELINE_DEFAULT_DYN_STATE_INFO; 				\
VkPipelineInputAssemblyStateCreateInfo g_##pipeline##_Default_Assembly_Info = PIPELINE_DEFAULT_ASSEMBLY_INFO; 	\
VkPipelineRasterizationStateCreateInfo g_##pipeline##_Default_Rasterization_Info = PIPELINE_DEFAULT_RASTERIZATION_INFO; \
VkPipelineMultisampleStateCreateInfo g_##pipeline##_Default_Multisample_Info = PIPELINE_DEFAULT_MULTISAMPLE_INFO; \
VkPipelineDepthStencilStateCreateInfo g_##pipeline##_Default_Depth_Info = PIPELINE_DEFAULT_DEPTH_INFO; \
VkPipelineRenderingCreateInfo g_##pipeline##_Default_Rendering_Info = PIPELINE_DEFAULT_RENDERING_INFO; \
VkPipelineColorBlendStateCreateInfo g_##pipeline##_Default_Blend_Info = PIPELINE_DEFAULT_BLEND_INFO; \
VkPipelineVertexInputStateCreateInfo g_##pipeline##_Default_Vertex_Info = PIPELINE_DEFAULT_VERTEX_INFO; \
VkPipelineViewportStateCreateInfo g_##pipeline##_Default_Viewport_Info = PIPELINE_DEFAULT_VIEWPORT_INFO; \
VkGraphicsPipelineCreateInfo g_##pipeline##_Create_Info = { \
	.sType = STYPE(GRAPHICS_PIPELINE_CREATE_INFO),				\
	.pNext = &g_##pipeline##_Default_Rendering_Info, 									\
	.pVertexInputState = &g_##pipeline##_Default_Vertex_Info,					\
	.pInputAssemblyState = &g_##pipeline##_Default_Assembly_Info,			\
	.pViewportState = &g_##pipeline##_Default_Viewport_Info, 					\
	.pRasterizationState = &g_##pipeline##_Default_Rasterization_Info,\
	.pMultisampleState = &g_##pipeline##_Default_Multisample_Info, 		\
	.pColorBlendState = &g_##pipeline##_Default_Blend_Info, 					\
	.pDepthStencilState = &g_##pipeline##_Default_Depth_Info,					\
	.pDynamicState = &g_##pipeline##_Default_Dynamic_Info,						\
};

INIT_PIPELINE_DEFAULTS(CUBE);

// GUI Pipeline
INIT_PIPELINE_DEFAULTS(GUI);

VkVertexInputBindingDescription 
gui_input_bind_desc = {
	.binding = 0,
	.stride = sizeof(rUIVertex),
	.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE,
};

VkVertexInputAttributeDescription 
gui_input_descriptions[] = {
	{ .binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = 0 },
	{ .binding = 0, .location = 1, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(rUIVertex, p1) },
	{ .binding = 0, .location = 2, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(rUIVertex, col) },
	{ .binding = 0, .location = 3, .format = VK_FORMAT_R32_UINT, .offset = offsetof(rUIVertex, tex_idx) },
};

VkPipelineVertexInputStateCreateInfo 
gui_vertex_input_info = 
{
	.sType = STYPE(PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO),
	.vertexBindingDescriptionCount = 1,
	.pVertexBindingDescriptions = &gui_input_bind_desc,
	.vertexAttributeDescriptionCount = Len(gui_input_descriptions),
	.pVertexAttributeDescriptions = gui_input_descriptions,
};

VkPipelineInputAssemblyStateCreateInfo 
gui_assembly_info = 
{
	.sType = STYPE(PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO),
	.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
	.primitiveRestartEnable = VK_FALSE,
};

// PBR Pipeline
INIT_PIPELINE_DEFAULTS(PBR);

VkVertexInputBindingDescription 
pbr_input_bind_desc = 
{
	.binding = 0,
	.stride = sizeof(rPBRVertex),
	.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
};

VkPipelineVertexInputStateCreateInfo 
pbr_vertex_input_info = 
{
	.sType = STYPE(PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO),
	.vertexBindingDescriptionCount = 1,
	.pVertexBindingDescriptions = &pbr_input_bind_desc,
};

VkPipelineInputAssemblyStateCreateInfo 
pbr_assembly_info = 
{
	.sType = STYPE(PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO),
	.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
	.primitiveRestartEnable = VK_FALSE,
};

static void 
vCustomizePipelines()
{
	// GUI
	g_GUI_Create_Info.pVertexInputState = &gui_vertex_input_info;
	g_GUI_Create_Info.pInputAssemblyState = &gui_assembly_info;

	// PBR
	g_PBR_Create_Info.pVertexInputState = &pbr_vertex_input_info;
	g_PBR_Create_Info.pInputAssemblyState = &pbr_assembly_info;
}
