2352 lines
109 KiB
C
Executable File
2352 lines
109 KiB
C
Executable File
/// _ _
|
|
/// __ ___ _| | | ____ _ _ __
|
|
/// \ \/ / | | | | |/ / _` | '_ \
|
|
/// > <| |_| | | < (_| | | | |
|
|
/// /_/\_\\__,_|_|_|\_\__,_|_| |_|
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xulkan - Tiny and elegant Vulkan wrapper library so I don't have to write 40k lines of code for a triangle...
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
|
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
/// DO NOT USE THIS CRAP...
|
|
|
|
#define VK_USE_PLATFORM_XCB_KHR
|
|
|
|
#include <vulkan/vulkan.h>
|
|
|
|
typedef struct {
|
|
boolean active;
|
|
boolean reconfigure_active;
|
|
boolean validation_layers;
|
|
boolean hide_cursor_full;
|
|
boolean hide_cursor;
|
|
natural time;
|
|
|
|
natural cursor; /// TODO: PROPER INPUT
|
|
integer cursor_x;
|
|
integer cursor_y;
|
|
|
|
boolean signal [signal_count];
|
|
|
|
real pixel_width;
|
|
real pixel_height;
|
|
natural frame;
|
|
natural width;
|
|
natural height;
|
|
natural sprite_count;
|
|
natural * * sprite_data;
|
|
natural * sprite_width;
|
|
natural * sprite_height;
|
|
real * sprite_u;
|
|
real * sprite_v;
|
|
natural font_count;
|
|
natural * * font_index;
|
|
natural * * font_width;
|
|
natural * * font_height;
|
|
character * font_begin;
|
|
character * font_end;
|
|
|
|
xcb_connection_t * connection;
|
|
xcb_screen_t * screen;
|
|
xcb_window_t window;
|
|
|
|
natural global_time;
|
|
natural gameplay_time;
|
|
natural animation_time;
|
|
natural framerate;
|
|
natural gameplay_framerate;
|
|
natural animation_framerate;
|
|
natural_64 frame_time_in_ns;
|
|
|
|
VkInstance instance;
|
|
VkSurfaceKHR surface;
|
|
VkPhysicalDevice physical_device;
|
|
VkQueue queue;
|
|
natural queue_index;
|
|
VkDevice boolean_device;
|
|
natural image_count;
|
|
VkExtent2D extent;
|
|
VkFormat format;
|
|
VkPresentModeKHR present_mode;
|
|
VkSurfaceTransformFlagBitsKHR transform;
|
|
VkCompositeAlphaFlagBitsKHR composite_alpha;
|
|
VkSwapchainKHR swapchain;
|
|
VkImage * images;
|
|
VkImageView * image_views;
|
|
VkSemaphore * semaphore_set_1;
|
|
VkSemaphore * semaphore_set_2;
|
|
VkFence * fence_set_1;
|
|
VkDescriptorSetLayout descriptor_set_layout;
|
|
VkDescriptorSetLayout * descriptor_set_layouts;
|
|
VkDescriptorPool descriptor_pool;
|
|
VkDescriptorSet * descriptor_sets;
|
|
VkRenderPass render_pass;
|
|
VkShaderModule vertex_shader;
|
|
VkShaderModule fragment_shader;
|
|
VkPipelineLayout pipeline_layout;
|
|
VkPipeline pipeline;
|
|
VkFramebuffer * framebuffers;
|
|
VkCommandPool command_pool;
|
|
VkCommandBuffer * command_buffers;
|
|
VkCommandBuffer transfer_buffer;
|
|
VkBuffer vertex_buffer;
|
|
VkDeviceMemory vertex_memory;
|
|
real * vertex_data;
|
|
VkDeviceSize vertex_size;
|
|
natural vertex_count;
|
|
natural vertex_limit;
|
|
VkBuffer index_buffer;
|
|
VkDeviceMemory index_memory;
|
|
natural * index_data;
|
|
VkDeviceSize index_size;
|
|
natural index_count;
|
|
natural index_limit;
|
|
VkSampler sampler;
|
|
VkImage layout_image;
|
|
VkDeviceMemory layout_memory;
|
|
VkImageView layout_image_view;
|
|
natural * layout_data;
|
|
natural layout_size;
|
|
natural layout_width;
|
|
natural layout_height;
|
|
} vulkan_structure;
|
|
|
|
static character * vulkan_continue_execution [] = {
|
|
"/s Commands successfully completed.\n",
|
|
"/w Fence or query hasn't yet completed.\n",
|
|
"/w Wait operation hasn't completed in the specified time.\n",
|
|
"/w Event is signaled.\n",
|
|
"/w Event isn't signaled.\n",
|
|
"/w Return array was too small for the result.\n"
|
|
};
|
|
|
|
static character * vulkan_break_execution [] = {
|
|
"/f Host memory allocation has failed.\n",
|
|
"/f Device memory allocation has failed.\n",
|
|
"/f Initialization of an object couldn't be completed.\n",
|
|
"/f Logical or physical device has been lost.\n",
|
|
"/f Mapping of a memory object has failed.\n",
|
|
"/f Requested layer isn't present or couln't be loaded.\n",
|
|
"/f Requested extension isn't supported.\n",
|
|
"/f Requested feature isn't supported.\n",
|
|
"/f Requested version of Vulkan isn't suported.\n",
|
|
"/f Too many objects of the type have alrady been created.\n",
|
|
"/f Requested format isn't supported.\n",
|
|
"/f Pool allocation has failed due to framentation.\n",
|
|
"/f Unknown error has occurred.\n",
|
|
"/f Undefined error has occured.\n"
|
|
};
|
|
|
|
static procedure vulkan_result (VkResult result) {
|
|
if (result == 0) {
|
|
return;
|
|
} else if (result > 0) {
|
|
print (vulkan_continue_execution [result]);
|
|
} else {
|
|
print (vulkan_break_execution [- result - 1]);
|
|
//~exit (log_failure);
|
|
}
|
|
}
|
|
|
|
static vulkan_structure * vulkan_initialize (caliber quad_memory, caliber layout_side, natural gameplay_framerate, natural animation_framerate) {
|
|
vulkan_structure * vulkan = allocate (sizeof (* vulkan));
|
|
|
|
vulkan->vertex_limit = quad_memory * 32;
|
|
vulkan->index_limit = quad_memory * 6;
|
|
vulkan->gameplay_framerate = gameplay_framerate;
|
|
vulkan->animation_framerate = animation_framerate;
|
|
vulkan->layout_width = layout_side;
|
|
vulkan->layout_height = layout_side;
|
|
|
|
return (vulkan);
|
|
}
|
|
|
|
static vulkan_structure * vulkan_deinitialize (vulkan_structure * vulkan) {
|
|
print ("/c Destroying and deallocating all the bullshit used so far...\n");
|
|
|
|
vulkan_result (vkQueueWaitIdle (vulkan->queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan->boolean_device));
|
|
|
|
vulkan->sprite_width = deallocate (vulkan->sprite_width);
|
|
vulkan->sprite_height = deallocate (vulkan->sprite_height);
|
|
vulkan->sprite_u = deallocate (vulkan->sprite_u);
|
|
vulkan->sprite_v = deallocate (vulkan->sprite_v);
|
|
|
|
if (vulkan->font_count > 0) {
|
|
for (natural index = 0; index < vulkan->font_count; ++index) {
|
|
vulkan->font_index [index] = deallocate (vulkan->font_index [index]);
|
|
vulkan->font_width [index] = deallocate (vulkan->font_width [index]);
|
|
vulkan->font_height [index] = deallocate (vulkan->font_height [index]);
|
|
}
|
|
|
|
vulkan->font_index = deallocate (vulkan->font_index);
|
|
vulkan->font_width = deallocate (vulkan->font_width);
|
|
vulkan->font_height = deallocate (vulkan->font_height);
|
|
vulkan->font_begin = deallocate (vulkan->font_begin);
|
|
vulkan->font_end = deallocate (vulkan->font_end);
|
|
}
|
|
|
|
vkFreeDescriptorSets (vulkan->boolean_device, vulkan->descriptor_pool, vulkan->image_count, vulkan->descriptor_sets);
|
|
|
|
vulkan->descriptor_set_layouts = deallocate (vulkan->descriptor_set_layouts);
|
|
vulkan->descriptor_sets = deallocate (vulkan->descriptor_sets);
|
|
|
|
vkDestroyDescriptorPool (vulkan->boolean_device, vulkan->descriptor_pool, null);
|
|
vkDestroySampler (vulkan->boolean_device, vulkan->sampler, null);
|
|
vkDestroyImageView (vulkan->boolean_device, vulkan->layout_image_view, null);
|
|
vkDestroyImage (vulkan->boolean_device, vulkan->layout_image, null);
|
|
vkFreeMemory (vulkan->boolean_device, vulkan->layout_memory, null);
|
|
|
|
vulkan->layout_data = deallocate (vulkan->layout_data);
|
|
|
|
vulkan->index_data = deallocate (vulkan->index_data);
|
|
vulkan->vertex_data = deallocate (vulkan->vertex_data);
|
|
/*
|
|
vkFreeCommandBuffers (vulkan->boolean_device, vulkan->command_pool, vulkan->image_count, vulkan->command_buffers);
|
|
*/
|
|
vulkan->command_buffers = deallocate (vulkan->command_buffers);
|
|
|
|
vkDestroyCommandPool (vulkan->boolean_device, vulkan->command_pool, null);
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
vkDestroyFramebuffer (vulkan->boolean_device, vulkan->framebuffers [index], null);
|
|
}
|
|
|
|
vulkan->framebuffers = deallocate (vulkan->framebuffers);
|
|
|
|
vkDestroyPipeline (vulkan->boolean_device, vulkan->pipeline, null);
|
|
vkDestroyPipelineLayout (vulkan->boolean_device, vulkan->pipeline_layout, null);
|
|
vkDestroyShaderModule (vulkan->boolean_device, vulkan->fragment_shader, null);
|
|
vkDestroyShaderModule (vulkan->boolean_device, vulkan->vertex_shader, null);
|
|
vkDestroyDescriptorSetLayout (vulkan->boolean_device, vulkan->descriptor_set_layout, null);
|
|
vkDestroyRenderPass (vulkan->boolean_device, vulkan->render_pass, null);
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
vkDestroySemaphore (vulkan->boolean_device, vulkan->semaphore_set_1 [index], null);
|
|
vkDestroySemaphore (vulkan->boolean_device, vulkan->semaphore_set_2 [index], null);
|
|
vkDestroyFence (vulkan->boolean_device, vulkan->fence_set_1 [index], null);
|
|
}
|
|
|
|
vulkan->semaphore_set_1 = deallocate (vulkan->semaphore_set_1);
|
|
vulkan->semaphore_set_2 = deallocate (vulkan->semaphore_set_2);
|
|
vulkan->fence_set_1 = deallocate (vulkan->fence_set_1);
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
vkDestroyImageView (vulkan->boolean_device, vulkan->image_views [index], null);
|
|
}
|
|
|
|
vulkan->image_views = deallocate (vulkan->image_views);
|
|
|
|
vkDestroySwapchainKHR (vulkan->boolean_device, vulkan->swapchain, null);
|
|
|
|
vulkan->images = deallocate (vulkan->images);
|
|
|
|
vkDestroySurfaceKHR (vulkan->instance, vulkan->surface, null);
|
|
|
|
vkDestroyDevice (vulkan->boolean_device, null);
|
|
vkDestroyInstance (vulkan->instance, null);
|
|
|
|
xcb_destroy_window (vulkan->connection, vulkan->window);
|
|
xcb_disconnect (vulkan->connection);
|
|
|
|
print ("/c Destroyed and deallocated all resources.\n");
|
|
|
|
return (deallocate (vulkan));
|
|
}
|
|
|
|
static natural vulkan_choose_memory_property (vulkan_structure * vulkan, natural wanted) {
|
|
natural index = 0;
|
|
natural usable = 0;
|
|
|
|
VkPhysicalDeviceMemoryProperties memory_properties = { 0 };
|
|
|
|
vkGetPhysicalDeviceMemoryProperties (vulkan->physical_device, & memory_properties);
|
|
|
|
for (index = 0; index < memory_properties.memoryTypeCount; ++index) {
|
|
if ((memory_properties.memoryTypes [index].propertyFlags & wanted) == wanted) {
|
|
usable &= (1 << index);
|
|
}
|
|
}
|
|
|
|
if (usable != wanted) {
|
|
print ("/w Can't set this memory property bit: usable = %i, wanted = %i.\n", usable, wanted);
|
|
}
|
|
|
|
return (usable);
|
|
}
|
|
|
|
static procedure vulkan_create_buffer (vulkan_structure * vulkan, VkBuffer * buffer, VkDeviceMemory * memory, VkDeviceSize size, VkMemoryPropertyFlags usage) {
|
|
natural wanted_memory_index = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
|
|
VkBufferCreateInfo buffer_information = { 0 };
|
|
VkMemoryRequirements memory_requirements = { 0 };
|
|
VkMemoryAllocateInfo memory_allocation_information = { 0 };
|
|
|
|
buffer_information.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
buffer_information.size = size;
|
|
buffer_information.usage = usage;
|
|
buffer_information.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
vulkan_result (vkCreateBuffer (vulkan->boolean_device, & buffer_information, null, buffer));
|
|
|
|
vkGetBufferMemoryRequirements (vulkan->boolean_device, * buffer, & memory_requirements);
|
|
|
|
memory_allocation_information.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
memory_allocation_information.allocationSize = memory_requirements.size;
|
|
memory_allocation_information.memoryTypeIndex = vulkan_choose_memory_property (vulkan, wanted_memory_index);
|
|
|
|
vulkan_result (vkAllocateMemory (vulkan->boolean_device, & memory_allocation_information, null, memory));
|
|
|
|
vulkan_result (vkBindBufferMemory (vulkan->boolean_device, * buffer, * memory, 0));
|
|
}
|
|
|
|
static procedure vulkan_begin_command_buffer (vulkan_structure * vulkan) {
|
|
VkCommandBufferAllocateInfo command_buffer_allocation_information = { 0 };
|
|
VkCommandBufferBeginInfo command_buffer_begin_information = { 0 };
|
|
|
|
command_buffer_allocation_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
command_buffer_allocation_information.commandPool = vulkan->command_pool;
|
|
command_buffer_allocation_information.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
command_buffer_allocation_information.commandBufferCount = 1;
|
|
|
|
command_buffer_begin_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
command_buffer_begin_information.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
|
|
vulkan_result (vkAllocateCommandBuffers (vulkan->boolean_device, & command_buffer_allocation_information, & vulkan->transfer_buffer));
|
|
|
|
vulkan_result (vkBeginCommandBuffer (vulkan->transfer_buffer, & command_buffer_begin_information));
|
|
}
|
|
|
|
static procedure vulkan_end_command_buffer (vulkan_structure * vulkan) {
|
|
VkSubmitInfo submit_information = { 0 };
|
|
|
|
vkEndCommandBuffer (vulkan->transfer_buffer);
|
|
|
|
submit_information.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
submit_information.commandBufferCount = 1;
|
|
submit_information.pCommandBuffers = & vulkan->transfer_buffer;
|
|
|
|
vkQueueSubmit (vulkan->queue, 1, & submit_information, VK_NULL_HANDLE);
|
|
|
|
vkQueueWaitIdle (vulkan->queue);
|
|
|
|
vkFreeCommandBuffers (vulkan->boolean_device, vulkan->command_pool, 1, & vulkan->transfer_buffer);
|
|
|
|
vulkan->transfer_buffer = VK_NULL_HANDLE;
|
|
}
|
|
|
|
static procedure vulkan_create_window (vulkan_structure * vulkan, character * application) {
|
|
natural window_flags [2] = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->connection = xcb_connect (null, null);
|
|
|
|
print ("Connected to /3X11 server/-.\n");
|
|
|
|
vulkan->screen = xcb_setup_roots_iterator (xcb_get_setup (vulkan->connection)).data;
|
|
|
|
vulkan->window = xcb_generate_id (vulkan->connection);
|
|
|
|
window_flags [0] = vulkan->screen->black_pixel;
|
|
window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
|
|
XCB_EVENT_MASK_EXPOSURE |
|
|
/*XCB_EVENT_MASK_STRUCTURE_NOTIFY |*/
|
|
XCB_EVENT_MASK_RESIZE_REDIRECT |
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
/*XCB_EVENT_MASK_POINTER_MOTION |*/
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS;
|
|
|
|
xcb_create_window (vulkan->connection, vulkan->screen->root_depth, vulkan->window, vulkan->screen->root, 0, 0,
|
|
(natural_16) vulkan->width, (natural_16) vulkan->height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
vulkan->screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, window_flags);
|
|
|
|
print ("/c Created /3XCB window/-.\n");
|
|
|
|
xcb_map_window (vulkan->connection, vulkan->window);
|
|
|
|
xcb_change_property (vulkan->connection, XCB_PROP_MODE_REPLACE, vulkan->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
string_length (application), application);
|
|
|
|
xcb_flush (vulkan->connection);
|
|
|
|
print ("Mapped /3XCB window/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_instance (vulkan_structure * vulkan, character * application) {
|
|
natural current = 0;
|
|
natural general = 0;
|
|
|
|
VkApplicationInfo application_information = { 0 };
|
|
VkInstanceCreateInfo instance_information = { 0 };
|
|
|
|
natural instance_layer_count = 0;
|
|
natural * instance_layer_index = null;
|
|
VkLayerProperties * instance_layer_array = null;
|
|
natural instance_extension_count = 0;
|
|
natural * instance_extension_index = null;
|
|
VkExtensionProperties * instance_extension_array = null;
|
|
|
|
natural default_instance_layer_count = (natural) (vulkan->validation_layers == true);
|
|
natural default_instance_extension_count = 2;
|
|
|
|
character * default_instance_layer_array [VK_MAX_EXTENSION_NAME_SIZE] = {
|
|
"VK_LAYER_KHRONOS_validation"
|
|
//~"VK_LAYER_LUNARG_parameter_validation",
|
|
//~"VK_LAYER_LUNARG_core_validation",
|
|
//~"VK_LAYER_LUNARG_standard_validation"
|
|
};
|
|
|
|
character * default_instance_extension_array [VK_MAX_EXTENSION_NAME_SIZE] = {
|
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
|
VK_KHR_XCB_SURFACE_EXTENSION_NAME
|
|
};
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkEnumerateInstanceLayerProperties (& instance_layer_count, null));
|
|
|
|
print ("Instance layer count: /2%i/-\n", instance_layer_count);
|
|
|
|
instance_layer_index = allocate (instance_layer_count * sizeof (* instance_layer_index));
|
|
instance_layer_array = allocate (instance_layer_count * sizeof (* instance_layer_array));
|
|
|
|
vulkan_result (vkEnumerateInstanceLayerProperties (& instance_layer_count, instance_layer_array));
|
|
|
|
for (current = 0; current < instance_layer_count; ++current) {
|
|
for (general = 0; general < default_instance_layer_count; ++general) {
|
|
if (string_compare (instance_layer_array [current].layerName, (character *) default_instance_layer_array [general])) {
|
|
instance_layer_index [current] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (current = 0; current < instance_layer_count; ++current) {
|
|
print ("\t[%t] %s\n", instance_layer_index [current], instance_layer_array [current].layerName);
|
|
}
|
|
|
|
instance_layer_index = deallocate (instance_layer_index);
|
|
instance_layer_array = deallocate (instance_layer_array);
|
|
|
|
print ("Enumerated /2instance layer properties/-.\n");
|
|
|
|
vulkan_result (vkEnumerateInstanceExtensionProperties (null, & instance_extension_count, null));
|
|
|
|
print ("Instance extension count: /2%i/-\n", instance_extension_count);
|
|
|
|
instance_extension_index = allocate (instance_extension_count * sizeof (* instance_extension_index));
|
|
instance_extension_array = allocate (instance_extension_count * sizeof (* instance_extension_array));
|
|
|
|
vulkan_result (vkEnumerateInstanceExtensionProperties (null, & instance_extension_count, instance_extension_array));
|
|
|
|
for (current = 0; current < instance_extension_count; ++current) {
|
|
for (general = 0; general < default_instance_extension_count; ++general) {
|
|
if (string_compare (instance_extension_array [current].extensionName, (character *) default_instance_extension_array [general])) {
|
|
instance_extension_index [current] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (current = 0; current < instance_extension_count; ++current) {
|
|
print ("\t[%t] %s\n", instance_extension_index [current], instance_extension_array [current].extensionName);
|
|
}
|
|
|
|
instance_extension_index = deallocate (instance_extension_index);
|
|
instance_extension_array = deallocate (instance_extension_array);
|
|
|
|
print ("Enumerated /2instance extension properties/-.\n");
|
|
|
|
application_information.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
|
application_information.pApplicationName = application;
|
|
application_information.applicationVersion = VK_MAKE_VERSION (1, 0, 0);
|
|
application_information.pEngineName = "xulkan";
|
|
application_information.engineVersion = VK_MAKE_VERSION (1, 0, 0);
|
|
application_information.apiVersion = VK_API_VERSION_1_0;
|
|
|
|
instance_information.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
instance_information.pApplicationInfo = & application_information;
|
|
instance_information.enabledLayerCount = default_instance_layer_count;
|
|
instance_information.ppEnabledLayerNames = default_instance_layer_array;
|
|
instance_information.enabledExtensionCount = default_instance_extension_count;
|
|
instance_information.ppEnabledExtensionNames = default_instance_extension_array;
|
|
|
|
vulkan_result (vkCreateInstance (& instance_information, null, & vulkan->instance));
|
|
|
|
print ("/c Created /2Vulkan instance/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_surface (vulkan_structure * vulkan) {
|
|
VkXcbSurfaceCreateInfoKHR surface_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
surface_information.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
|
surface_information.connection = vulkan->connection;
|
|
surface_information.window = vulkan->window;
|
|
|
|
vulkan_result (vkCreateXcbSurfaceKHR (vulkan->instance, & surface_information, null, & vulkan->surface));
|
|
|
|
print ("/c Created /2Vulkan-XCB surface/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_device (vulkan_structure * vulkan) {
|
|
VkDeviceQueueCreateInfo queues = { 0 };
|
|
VkDeviceCreateInfo device_information = { 0 };
|
|
VkPhysicalDeviceMemoryProperties memory_properties = { 0 };
|
|
|
|
natural queue_count = 0;
|
|
natural physical_device_count = 0;
|
|
VkPhysicalDevice * physical_device_array = null;
|
|
VkBool32 * support = null;
|
|
|
|
real queue_priorities [1] = { 1 };
|
|
|
|
natural default_device_extension_count = 1;
|
|
|
|
character * default_device_extension_array [VK_MAX_EXTENSION_NAME_SIZE] = {
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
|
};
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkEnumeratePhysicalDevices (vulkan->instance, & physical_device_count, null));
|
|
|
|
print ("Device count: /2%i/-\n", physical_device_count);
|
|
|
|
physical_device_array = allocate (physical_device_count * sizeof (VkPhysicalDevice));
|
|
|
|
vulkan_result (vkEnumeratePhysicalDevices (vulkan->instance, & physical_device_count, physical_device_array));
|
|
|
|
print ("Enumerated available physical devices.\n");
|
|
|
|
for (natural index = 0; index < physical_device_count; ++index) {
|
|
natural general = 0;
|
|
natural current = 0;
|
|
|
|
natural device_extension_count = 0;
|
|
natural * device_extension_index = null;
|
|
VkExtensionProperties * device_extension_array = null;
|
|
|
|
VkPhysicalDeviceProperties physical_device_properties = { 0 };
|
|
VkPhysicalDeviceFeatures physical_device_features = { 0 };
|
|
|
|
VkQueueFamilyProperties * queue_properties = null;
|
|
|
|
vkGetPhysicalDeviceProperties (physical_device_array [index], & physical_device_properties);
|
|
vkGetPhysicalDeviceFeatures (physical_device_array [index], & physical_device_features);
|
|
|
|
#define get_fucking_version(i) \
|
|
VK_VERSION_MAJOR(i), \
|
|
VK_VERSION_MINOR(i), \
|
|
VK_VERSION_PATCH(i)
|
|
print ("Physical device: /2%s/-\n", physical_device_properties.deviceName);
|
|
print ("Device ID: /2%i/-\n", physical_device_properties.deviceID);
|
|
print ("API version: /2%i.%i.%i/-\n", get_fucking_version (physical_device_properties.apiVersion));
|
|
print ("Driver version: /2%i.%i.%i/-\n", get_fucking_version (physical_device_properties.driverVersion));
|
|
#undef get_fucking_version
|
|
|
|
switch (physical_device_properties.deviceType) {
|
|
case (VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU): print ("Device type: /2Integrated GPU/-\n"); break;
|
|
case (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU): print ("Device type: /2Discrete GPU/-\n"); break;
|
|
case (VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU): print ("Device type: /2Virtual GPU/-\n"); break;
|
|
case (VK_PHYSICAL_DEVICE_TYPE_CPU): print ("Device type: /2CPU/-\n"); break;
|
|
default: print ("Device type: /2Other/-\n"); break;
|
|
}
|
|
|
|
switch (physical_device_properties.vendorID) {
|
|
case (VK_VENDOR_ID_VIV): print ("Vendor: /2VIV/-\n"); break;
|
|
case (VK_VENDOR_ID_VSI): print ("Vendor: /2VSI/-\n"); break;
|
|
case (VK_VENDOR_ID_KAZAN): print ("Vendor: /2Kazan/-\n"); break;
|
|
case (VK_VENDOR_ID_CODEPLAY): print ("Vendor: /2Codeplay/-\n"); break;
|
|
case (VK_VENDOR_ID_MESA): print ("Vendor: /2MESA/-\n"); break;
|
|
case (VK_VENDOR_ID_POCL): print ("Vendor: /2POCL/-\n"); break;
|
|
default: print ("Vendor: /2Other/-\n"); break;
|
|
}
|
|
|
|
vulkan_result (vkEnumerateDeviceExtensionProperties (physical_device_array [index], null, & device_extension_count, null));
|
|
|
|
print ("Device extensions available: %i\n", device_extension_count);
|
|
|
|
device_extension_index = allocate (device_extension_count * sizeof (* device_extension_index));
|
|
device_extension_array = allocate (device_extension_count * sizeof (* device_extension_array));
|
|
|
|
vulkan_result (vkEnumerateDeviceExtensionProperties (physical_device_array [index], null, & device_extension_count,
|
|
device_extension_array));
|
|
|
|
for (current = 0; current < device_extension_count; ++current) {
|
|
for (general = 0; general < default_device_extension_count; ++general) {
|
|
if (string_compare (device_extension_array [current].extensionName, (character *) default_device_extension_array [general])) {
|
|
device_extension_index [current] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (current = 0; current < device_extension_count; ++current) {
|
|
print ("\t[%t] %s\n", device_extension_index [current], device_extension_array [current].extensionName);
|
|
}
|
|
|
|
device_extension_index = deallocate (device_extension_index);
|
|
device_extension_array = deallocate (device_extension_array);
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties (physical_device_array [index], & queue_count, null);
|
|
|
|
queue_properties = allocate (queue_count * sizeof (VkQueueFamilyProperties));
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties (physical_device_array [index], & queue_count, queue_properties);
|
|
|
|
vulkan->queue_index = 0;
|
|
|
|
if ((physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
|
|
|| (physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)) {
|
|
vulkan->physical_device = physical_device_array [index];
|
|
}
|
|
|
|
queue_properties = deallocate (queue_properties);
|
|
|
|
print ("Enumerated device layer properties.\n");
|
|
|
|
print ("Enumerated device extension properties.\n");
|
|
}
|
|
|
|
vulkan->physical_device = physical_device_array [1]; /// THIS SHIT SUCKS.
|
|
|
|
VkPhysicalDeviceProperties selected_physical_device_properties = { 0 };
|
|
|
|
vkGetPhysicalDeviceProperties (vulkan->physical_device, & selected_physical_device_properties);
|
|
|
|
print ("/c Selecting physical device '/2%s/-'.\n", selected_physical_device_properties.deviceName);
|
|
|
|
physical_device_array = deallocate (physical_device_array);
|
|
|
|
queues.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
queues.queueFamilyIndex = vulkan->queue_index;
|
|
queues.queueCount = 1;
|
|
queues.pQueuePriorities = queue_priorities;
|
|
|
|
device_information.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
device_information.queueCreateInfoCount = 1;
|
|
device_information.pQueueCreateInfos = & queues;
|
|
device_information.enabledExtensionCount = default_device_extension_count;
|
|
device_information.ppEnabledExtensionNames = default_device_extension_array;
|
|
device_information.pEnabledFeatures = null;
|
|
|
|
vulkan_result (vkCreateDevice (vulkan->physical_device, & device_information, null, & vulkan->boolean_device));
|
|
|
|
print ("/c Created Vulkan boolean device.\n");
|
|
|
|
vkGetDeviceQueue (vulkan->boolean_device, vulkan->queue_index, 0, & vulkan->queue);
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties (vulkan->physical_device, & queue_count, null);
|
|
|
|
support = allocate (queue_count * sizeof (VkBool32));
|
|
|
|
for (natural index = 0; index < queue_count; ++index) {
|
|
vulkan_result (vkGetPhysicalDeviceSurfaceSupportKHR (vulkan->physical_device, index, vulkan->surface, & support [index]));
|
|
}
|
|
|
|
for (natural index = 0; (index != queue_count) && (! (vulkan->queue_index = support [index] ? (index++) : 0)); );
|
|
|
|
support = deallocate (support);
|
|
|
|
vkGetPhysicalDeviceMemoryProperties (vulkan->physical_device, & memory_properties);
|
|
|
|
print ("Found /2Vulkan physical device/- memory properties.\n");
|
|
|
|
for (natural index = 0; index < memory_properties.memoryTypeCount; ++index) {
|
|
print ("> %i\n", memory_properties.memoryTypes [index].propertyFlags);
|
|
}
|
|
|
|
print ("Found /2Vulkan surface support/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_choose_extent (vulkan_structure * vulkan) {
|
|
VkSurfaceCapabilitiesKHR capabilities = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkGetPhysicalDeviceSurfaceCapabilitiesKHR (vulkan->physical_device, vulkan->surface, & capabilities));
|
|
|
|
vulkan->image_count = capabilities.minImageCount + 1;
|
|
|
|
vulkan->extent.width = vulkan->width;
|
|
vulkan->extent.height = vulkan->height;
|
|
|
|
vulkan->extent.width = (vulkan->extent.width < capabilities.minImageExtent.width) ? capabilities.minImageExtent.width : vulkan->extent.width;
|
|
vulkan->extent.height = (vulkan->extent.height < capabilities.minImageExtent.height) ? capabilities.minImageExtent.height : vulkan->extent.height;
|
|
|
|
vulkan->extent.width = (vulkan->extent.width > capabilities.maxImageExtent.width) ? capabilities.maxImageExtent.width : vulkan->extent.width;
|
|
vulkan->extent.height = (vulkan->extent.height > capabilities.maxImageExtent.height) ? capabilities.maxImageExtent.height : vulkan->extent.height;
|
|
|
|
vulkan->transform = capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
|
vulkan->composite_alpha = capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
|
|
print ("Found /2Vulkan-XCB surface capabilities/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_choose_format (vulkan_structure * vulkan) {
|
|
natural format_count = 0;
|
|
VkSurfaceFormatKHR * format_array = null;
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkGetPhysicalDeviceSurfaceFormatsKHR (vulkan->physical_device, vulkan->surface, & format_count, null));
|
|
|
|
format_array = allocate (format_count * sizeof (VkSurfaceFormatKHR));
|
|
|
|
vulkan_result (vkGetPhysicalDeviceSurfaceFormatsKHR (vulkan->physical_device, vulkan->surface, & format_count, format_array));
|
|
|
|
print ("Available surface format count: /2%i/-\n", format_count);
|
|
|
|
vulkan->format = VK_FORMAT_B8G8R8A8_UNORM;
|
|
|
|
format_array = deallocate (format_array);
|
|
|
|
print ("Choosing default /2Vulkan surface formats/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_choose_present_mode (vulkan_structure * vulkan) {
|
|
natural present_mode_count = 0;
|
|
VkPresentModeKHR * present_mode_array = null;
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkGetPhysicalDeviceSurfacePresentModesKHR (vulkan->physical_device, vulkan->surface, & present_mode_count, null));
|
|
|
|
present_mode_array = allocate (present_mode_count * sizeof (VkPresentModeKHR));
|
|
|
|
vulkan_result (vkGetPhysicalDeviceSurfacePresentModesKHR (vulkan->physical_device, vulkan->surface, & present_mode_count,
|
|
present_mode_array));
|
|
|
|
vulkan->present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
|
|
|
present_mode_array = deallocate (present_mode_array);
|
|
|
|
print ("Choosing FIFO /2Vulkan surface present mode/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_swapchain (vulkan_structure * vulkan) {
|
|
VkSwapchainCreateInfoKHR swapchain_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
swapchain_information.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
swapchain_information.surface = vulkan->surface;
|
|
swapchain_information.minImageCount = vulkan->image_count;
|
|
swapchain_information.imageFormat = vulkan->format;
|
|
swapchain_information.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
|
swapchain_information.imageExtent = vulkan->extent;
|
|
swapchain_information.imageArrayLayers = 1;
|
|
swapchain_information.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
swapchain_information.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
swapchain_information.queueFamilyIndexCount = 0;
|
|
swapchain_information.pQueueFamilyIndices = null;
|
|
swapchain_information.preTransform = vulkan->transform;
|
|
swapchain_information.compositeAlpha = vulkan->composite_alpha;
|
|
swapchain_information.presentMode = vulkan->present_mode;
|
|
swapchain_information.clipped = VK_TRUE;
|
|
swapchain_information.oldSwapchain = VK_NULL_HANDLE;
|
|
|
|
vulkan_result (vkCreateSwapchainKHR (vulkan->boolean_device, & swapchain_information, null, & vulkan->swapchain));
|
|
|
|
print ("/c Created /2Vulkan swapchain/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_images (vulkan_structure * vulkan) {
|
|
natural temporary = vulkan->image_count;
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_result (vkGetSwapchainImagesKHR (vulkan->boolean_device, vulkan->swapchain, & temporary, null));
|
|
|
|
vulkan->images = allocate (vulkan->image_count * sizeof (VkImage));
|
|
|
|
vulkan_result (vkGetSwapchainImagesKHR (vulkan->boolean_device, vulkan->swapchain, & temporary, vulkan->images));
|
|
|
|
print ("/c Created /2Vulkan swapchain images/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_image_views (vulkan_structure * vulkan) {
|
|
VkComponentMapping component_mapping = { 0 };
|
|
VkImageSubresourceRange image_subresource_range = { 0 };
|
|
VkImageViewCreateInfo image_view_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->image_views = allocate (vulkan->image_count * sizeof (VkImageView));
|
|
|
|
component_mapping.r = VK_COMPONENT_SWIZZLE_R;
|
|
component_mapping.g = VK_COMPONENT_SWIZZLE_G;
|
|
component_mapping.b = VK_COMPONENT_SWIZZLE_B;
|
|
component_mapping.a = VK_COMPONENT_SWIZZLE_A;
|
|
|
|
image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
image_subresource_range.baseMipLevel = 0;
|
|
image_subresource_range.levelCount = 1;
|
|
image_subresource_range.baseArrayLayer = 0;
|
|
image_subresource_range.layerCount = 1;
|
|
|
|
image_view_information.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
image_view_information.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
image_view_information.format = vulkan->format;
|
|
image_view_information.components = component_mapping;
|
|
image_view_information.subresourceRange = image_subresource_range;
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
image_view_information.image = vulkan->images [index];
|
|
|
|
vulkan_result (vkCreateImageView (vulkan->boolean_device, & image_view_information, null, & vulkan->image_views [index]));
|
|
}
|
|
|
|
print ("/c Created /2Vulkan swapchain image views/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_semaphores (vulkan_structure * vulkan) {
|
|
VkSemaphoreCreateInfo semaphore_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->semaphore_set_1 = allocate (vulkan->image_count * sizeof (VkSemaphore));
|
|
vulkan->semaphore_set_2 = allocate (vulkan->image_count * sizeof (VkSemaphore));
|
|
|
|
semaphore_information.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
vulkan_result (vkCreateSemaphore (vulkan->boolean_device, & semaphore_information, null, & vulkan->semaphore_set_1 [index]));
|
|
vulkan_result (vkCreateSemaphore (vulkan->boolean_device, & semaphore_information, null, & vulkan->semaphore_set_2 [index]));
|
|
}
|
|
|
|
print ("/c Created /2Vulkan synchronization semaphores/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_fences (vulkan_structure * vulkan) {
|
|
natural index = 0;
|
|
|
|
VkFenceCreateInfo fence_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->fence_set_1 = allocate (vulkan->image_count * sizeof (VkFence));
|
|
|
|
fence_information.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
|
fence_information.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
|
|
|
for (index = 0; index < vulkan->image_count; ++index) {
|
|
vulkan_result (vkCreateFence (vulkan->boolean_device, & fence_information, null, & vulkan->fence_set_1 [index]));
|
|
}
|
|
|
|
print ("/c Created /2Vulkan synchronization fences/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_render_pass (vulkan_structure * vulkan) {
|
|
VkAttachmentDescription attachment_description = { 0 };
|
|
VkAttachmentReference attachment_reference = { 0 };
|
|
VkSubpassDescription subpass_description = { 0 };
|
|
VkSubpassDependency subpass_dependencies [2] = { { 0 } };
|
|
VkRenderPassCreateInfo render_pass_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
attachment_description.flags = 0;
|
|
attachment_description.format = vulkan->format;
|
|
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
attachment_description.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
|
|
attachment_reference.attachment = 0;
|
|
attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
subpass_description.flags = 0;
|
|
subpass_description.pipelineBindPointeger = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
subpass_description.inputAttachmentCount = 0;
|
|
subpass_description.pInputAttachments = null;
|
|
subpass_description.colorAttachmentCount = 1;
|
|
subpass_description.pColorAttachments = & attachment_reference;
|
|
subpass_description.pResolveAttachments = null;
|
|
subpass_description.pDepthStencilAttachment = null;
|
|
subpass_description.preserveAttachmentCount = 0;
|
|
subpass_description.pPreserveAttachments = null;
|
|
|
|
subpass_dependencies [0].srcSubpass = VK_SUBPASS_EXTERNAL;
|
|
subpass_dependencies [0].dstSubpass = 0;
|
|
subpass_dependencies [0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
subpass_dependencies [0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
subpass_dependencies [0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
|
subpass_dependencies [0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
subpass_dependencies [0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
subpass_dependencies [1].srcSubpass = 0;
|
|
subpass_dependencies [1].dstSubpass = VK_SUBPASS_EXTERNAL;
|
|
subpass_dependencies [1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
subpass_dependencies [1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
subpass_dependencies [1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
subpass_dependencies [1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
|
subpass_dependencies [1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
|
|
render_pass_information.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
render_pass_information.attachmentCount = 1;
|
|
render_pass_information.pAttachments = & attachment_description;
|
|
render_pass_information.subpassCount = 1;
|
|
render_pass_information.pSubpasses = & subpass_description;
|
|
render_pass_information.dependencyCount = 2;
|
|
render_pass_information.pDependencies = subpass_dependencies;
|
|
|
|
vulkan_result (vkCreateRenderPass (vulkan->boolean_device, & render_pass_information, null, & vulkan->render_pass));
|
|
|
|
print ("/c Created /2Vulkan render pass/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_descriptor_set_layout (vulkan_structure * vulkan) {
|
|
VkDescriptorSetLayoutBinding descriptor_set_layout_bindings [2] = { { 0 } };
|
|
VkDescriptorSetLayoutCreateInfo descriptor_set_layout_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
descriptor_set_layout_bindings [0].binding = 0;
|
|
descriptor_set_layout_bindings [0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
descriptor_set_layout_bindings [0].descriptorCount = 1;
|
|
descriptor_set_layout_bindings [0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
descriptor_set_layout_bindings [0].pImmutableSamplers = null;
|
|
descriptor_set_layout_bindings [1].binding = 1;
|
|
descriptor_set_layout_bindings [1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
descriptor_set_layout_bindings [1].descriptorCount = 1;
|
|
descriptor_set_layout_bindings [1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
descriptor_set_layout_bindings [1].pImmutableSamplers = null;
|
|
|
|
descriptor_set_layout_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
descriptor_set_layout_information.bindingCount = 2;
|
|
descriptor_set_layout_information.pBindings = descriptor_set_layout_bindings;
|
|
|
|
vulkan_result (vkCreateDescriptorSetLayout (vulkan->boolean_device, & descriptor_set_layout_information, null,
|
|
& vulkan->descriptor_set_layout));
|
|
|
|
print ("/c Created /2 Vulkan descriptor layout/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_vertex_shader (vulkan_structure * vulkan) {
|
|
natural vertex_shader_code [] = {
|
|
0x07230203, 0x00010000, 0x000d000b, 0x00000028, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
|
|
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
|
|
0x000b000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000d, 0x00000012, 0x00000021,
|
|
0x00000022, 0x00000024, 0x00000026, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47,
|
|
0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576,
|
|
0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669,
|
|
0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x0000000b, 0x505f6c67, 0x65567265,
|
|
0x78657472, 0x00000000, 0x00060006, 0x0000000b, 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69,
|
|
0x00070006, 0x0000000b, 0x00000001, 0x505f6c67, 0x746e696f, 0x657a6953, 0x00000000, 0x00070006,
|
|
0x0000000b, 0x00000002, 0x435f6c67, 0x4470696c, 0x61747369, 0x0065636e, 0x00070006, 0x0000000b,
|
|
0x00000003, 0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e, 0x00030005, 0x0000000d, 0x00000000,
|
|
0x00030005, 0x00000012, 0x00797869, 0x00030005, 0x00000021, 0x0076756f, 0x00030005, 0x00000022,
|
|
0x00767569, 0x00030005, 0x00000024, 0x0000636f, 0x00030005, 0x00000026, 0x00006369, 0x00050048,
|
|
0x0000000b, 0x00000000, 0x0000000b, 0x00000000, 0x00050048, 0x0000000b, 0x00000001, 0x0000000b,
|
|
0x00000001, 0x00050048, 0x0000000b, 0x00000002, 0x0000000b, 0x00000003, 0x00050048, 0x0000000b,
|
|
0x00000003, 0x0000000b, 0x00000004, 0x00030047, 0x0000000b, 0x00000002, 0x00040047, 0x00000012,
|
|
0x0000001e, 0x00000000, 0x00040047, 0x00000021, 0x0000001e, 0x00000000, 0x00040047, 0x00000022,
|
|
0x0000001e, 0x00000001, 0x00040047, 0x00000024, 0x0000001e, 0x00000001, 0x00040047, 0x00000026,
|
|
0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016,
|
|
0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040015, 0x00000008,
|
|
0x00000020, 0x00000000, 0x0004002b, 0x00000008, 0x00000009, 0x00000001, 0x0004001c, 0x0000000a,
|
|
0x00000006, 0x00000009, 0x0006001e, 0x0000000b, 0x00000007, 0x00000006, 0x0000000a, 0x0000000a,
|
|
0x00040020, 0x0000000c, 0x00000003, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000003,
|
|
0x00040015, 0x0000000e, 0x00000020, 0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000,
|
|
0x00040017, 0x00000010, 0x00000006, 0x00000002, 0x00040020, 0x00000011, 0x00000001, 0x00000010,
|
|
0x0004003b, 0x00000011, 0x00000012, 0x00000001, 0x0004002b, 0x00000008, 0x00000013, 0x00000000,
|
|
0x00040020, 0x00000014, 0x00000001, 0x00000006, 0x0004002b, 0x00000006, 0x00000017, 0x3f800000,
|
|
0x0004002b, 0x00000006, 0x0000001c, 0x00000000, 0x00040020, 0x0000001e, 0x00000003, 0x00000007,
|
|
0x00040020, 0x00000020, 0x00000003, 0x00000010, 0x0004003b, 0x00000020, 0x00000021, 0x00000003,
|
|
0x0004003b, 0x00000011, 0x00000022, 0x00000001, 0x0004003b, 0x0000001e, 0x00000024, 0x00000003,
|
|
0x00040020, 0x00000025, 0x00000001, 0x00000007, 0x0004003b, 0x00000025, 0x00000026, 0x00000001,
|
|
0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x00050041,
|
|
0x00000014, 0x00000015, 0x00000012, 0x00000013, 0x0004003d, 0x00000006, 0x00000016, 0x00000015,
|
|
0x00050083, 0x00000006, 0x00000018, 0x00000016, 0x00000017, 0x00050041, 0x00000014, 0x00000019,
|
|
0x00000012, 0x00000009, 0x0004003d, 0x00000006, 0x0000001a, 0x00000019, 0x00050083, 0x00000006,
|
|
0x0000001b, 0x0000001a, 0x00000017, 0x00070050, 0x00000007, 0x0000001d, 0x00000018, 0x0000001b,
|
|
0x0000001c, 0x00000017, 0x00050041, 0x0000001e, 0x0000001f, 0x0000000d, 0x0000000f, 0x0003003e,
|
|
0x0000001f, 0x0000001d, 0x0004003d, 0x00000010, 0x00000023, 0x00000022, 0x0003003e, 0x00000021,
|
|
0x00000023, 0x0004003d, 0x00000007, 0x00000027, 0x00000026, 0x0003003e, 0x00000024, 0x00000027,
|
|
0x000100fd, 0x00010038
|
|
};
|
|
|
|
VkShaderModuleCreateInfo vertex_shader_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vertex_shader_information.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
vertex_shader_information.codeSize = sizeof (vertex_shader_code);
|
|
vertex_shader_information.pCode = vertex_shader_code;
|
|
|
|
vulkan_result (vkCreateShaderModule (vulkan->boolean_device, & vertex_shader_information, null, & vulkan->vertex_shader));
|
|
|
|
print ("/c Created /2Vulkan vertex shader module/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_fragment_shader (vulkan_structure * vulkan) {
|
|
natural fragment_shader_code [] = {
|
|
0x07230203, 0x00010000, 0x000d000b, 0x00000018, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
|
|
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
|
|
0x0008000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x00000011, 0x00000015,
|
|
0x00030010, 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47,
|
|
0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576,
|
|
0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669,
|
|
0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00040005, 0x00000009, 0x69727073, 0x00006574,
|
|
0x00060005, 0x0000000d, 0x74786574, 0x5f657275, 0x706d6173, 0x0072656c, 0x00030005, 0x00000011,
|
|
0x00007675, 0x00030005, 0x00000015, 0x0000636f, 0x00040047, 0x00000009, 0x0000001e, 0x00000000,
|
|
0x00040047, 0x0000000d, 0x00000022, 0x00000000, 0x00040047, 0x0000000d, 0x00000021, 0x00000001,
|
|
0x00040047, 0x00000011, 0x0000001e, 0x00000000, 0x00040047, 0x00000015, 0x0000001e, 0x00000001,
|
|
0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020,
|
|
0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003, 0x00000007,
|
|
0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00090019, 0x0000000a, 0x00000006, 0x00000001,
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b, 0x0000000b, 0x0000000a,
|
|
0x00040020, 0x0000000c, 0x00000000, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000000,
|
|
0x00040017, 0x0000000f, 0x00000006, 0x00000002, 0x00040020, 0x00000010, 0x00000001, 0x0000000f,
|
|
0x0004003b, 0x00000010, 0x00000011, 0x00000001, 0x00040020, 0x00000014, 0x00000001, 0x00000007,
|
|
0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00050036, 0x00000002, 0x00000004, 0x00000000,
|
|
0x00000003, 0x000200f8, 0x00000005, 0x0004003d, 0x0000000b, 0x0000000e, 0x0000000d, 0x0004003d,
|
|
0x0000000f, 0x00000012, 0x00000011, 0x00050057, 0x00000007, 0x00000013, 0x0000000e, 0x00000012,
|
|
0x0004003d, 0x00000007, 0x00000016, 0x00000015, 0x00050085, 0x00000007, 0x00000017, 0x00000013,
|
|
0x00000016, 0x0003003e, 0x00000009, 0x00000017, 0x000100fd, 0x00010038
|
|
};
|
|
|
|
VkShaderModuleCreateInfo fragment_shader_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
fragment_shader_information.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
fragment_shader_information.codeSize = sizeof (fragment_shader_code);
|
|
fragment_shader_information.pCode = fragment_shader_code;
|
|
|
|
vulkan_result (vkCreateShaderModule (vulkan->boolean_device, & fragment_shader_information, null, & vulkan->fragment_shader));
|
|
|
|
print ("/c Created /2Vulkan fragment shader module/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_pipeline_layout (vulkan_structure * vulkan) {
|
|
VkPipelineLayoutCreateInfo pipeline_layout_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
pipeline_layout_information.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
pipeline_layout_information.setLayoutCount = 1;
|
|
pipeline_layout_information.pSetLayouts = & vulkan->descriptor_set_layout;
|
|
|
|
vulkan_result (vkCreatePipelineLayout (vulkan->boolean_device, & pipeline_layout_information, VK_NULL_HANDLE, & vulkan->pipeline_layout));
|
|
|
|
print ("/c Created /2Vulkan graphics pipeline layout/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_pipeline (vulkan_structure * vulkan) {
|
|
VkPipelineShaderStageCreateInfo pipeline_shader_stage_information [2] = { { 0 } };
|
|
VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_information = { 0 };
|
|
VkVertexInputBindingDescription vertex_input_binding_description [1] = { { 0 } };
|
|
VkVertexInputAttributeDescription vertex_input_attribute_description [4] = { { 0 } };
|
|
VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_information = { 0 };
|
|
VkViewport viewport = { 0 };
|
|
VkOffset2D scissor_offset = { 0 };
|
|
VkExtent2D scissor_extent = { 0 };
|
|
VkRect2D scissor = { 0 };
|
|
VkPipelineViewportStateCreateInfo pipeline_viewport_state_information = { 0 };
|
|
VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_information = { 0 };
|
|
VkPipelineMultisampleStateCreateInfo pipeline_multisample_state_information = { 0 };
|
|
VkPipelineColorBlendAttachmentState pipeline_colour_blend_attachment_state = { 0 };
|
|
VkPipelineColorBlendStateCreateInfo pipeline_colour_blend_state_information = { 0 };
|
|
VkGraphicsPipelineCreateInfo pipeline_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
pipeline_shader_stage_information [0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
pipeline_shader_stage_information [0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
pipeline_shader_stage_information [0].module = vulkan->vertex_shader;
|
|
pipeline_shader_stage_information [0].pName = "main";
|
|
pipeline_shader_stage_information [0].pSpecializationInfo = null;
|
|
pipeline_shader_stage_information [1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
pipeline_shader_stage_information [1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
pipeline_shader_stage_information [1].module = vulkan->fragment_shader;
|
|
pipeline_shader_stage_information [1].pName = "main";
|
|
pipeline_shader_stage_information [1].pSpecializationInfo = null;
|
|
|
|
pipeline_input_assembly_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
pipeline_input_assembly_state_information.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
pipeline_input_assembly_state_information.primitiveRestartEnable = VK_FALSE;
|
|
|
|
vertex_input_binding_description [0].binding = 0;
|
|
vertex_input_binding_description [0].stride = 32;
|
|
vertex_input_binding_description [0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
vertex_input_attribute_description [0].binding = vertex_input_binding_description [0].binding;
|
|
vertex_input_attribute_description [0].location = 0;
|
|
vertex_input_attribute_description [0].format = VK_FORMAT_R32G32_SFLOAT;
|
|
vertex_input_attribute_description [0].offset = 0;
|
|
vertex_input_attribute_description [1].binding = vertex_input_binding_description [0].binding;
|
|
vertex_input_attribute_description [1].location = 1;
|
|
vertex_input_attribute_description [1].format = VK_FORMAT_R32G32_SFLOAT;
|
|
vertex_input_attribute_description [1].offset = 8;
|
|
vertex_input_attribute_description [2].binding = vertex_input_binding_description [0].binding;
|
|
vertex_input_attribute_description [2].location = 2;
|
|
vertex_input_attribute_description [2].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
|
vertex_input_attribute_description [2].offset = 16;
|
|
|
|
pipeline_vertex_input_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
pipeline_vertex_input_state_information.vertexBindingDescriptionCount = 1;
|
|
pipeline_vertex_input_state_information.pVertexBindingDescriptions = vertex_input_binding_description;
|
|
pipeline_vertex_input_state_information.vertexAttributeDescriptionCount = 3;
|
|
pipeline_vertex_input_state_information.pVertexAttributeDescriptions = vertex_input_attribute_description;
|
|
|
|
viewport.x = 0;
|
|
viewport.y = 0;
|
|
viewport.width = vulkan->width;
|
|
viewport.height = vulkan->height;
|
|
viewport.minDepth = 0;
|
|
viewport.maxDepth = 1;
|
|
|
|
scissor_offset.x = 0;
|
|
scissor_offset.y = 0;
|
|
|
|
scissor_extent.width = vulkan->width;
|
|
scissor_extent.height = vulkan->height;
|
|
|
|
scissor.offset = scissor_offset;
|
|
scissor.extent = scissor_extent;
|
|
|
|
pipeline_viewport_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
pipeline_viewport_state_information.viewportCount = 1;
|
|
pipeline_viewport_state_information.pViewports = & viewport;
|
|
pipeline_viewport_state_information.scissorCount = 1;
|
|
pipeline_viewport_state_information.pScissors = & scissor;
|
|
|
|
pipeline_rasterization_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
pipeline_rasterization_state_information.depthClampEnable = VK_FALSE;
|
|
pipeline_rasterization_state_information.rasterizerDiscardEnable = VK_FALSE;
|
|
pipeline_rasterization_state_information.polygonMode = VK_POLYGON_MODE_FILL;
|
|
pipeline_rasterization_state_information.cullMode = VK_CULL_MODE_BACK_BIT;
|
|
pipeline_rasterization_state_information.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
|
pipeline_rasterization_state_information.depthBiasEnable = VK_FALSE;
|
|
pipeline_rasterization_state_information.depthBiasConstantFactor = 0;
|
|
pipeline_rasterization_state_information.depthBiasClamp = 0;
|
|
pipeline_rasterization_state_information.depthBiasSlopeFactor = 0;
|
|
pipeline_rasterization_state_information.lineWidth = 1;
|
|
|
|
pipeline_multisample_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
pipeline_multisample_state_information.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
pipeline_multisample_state_information.sampleShadingEnable = VK_FALSE;
|
|
pipeline_multisample_state_information.minSampleShading = 1;
|
|
pipeline_multisample_state_information.pSampleMask = null;
|
|
pipeline_multisample_state_information.alphaToCoverageEnable = VK_FALSE;
|
|
pipeline_multisample_state_information.alphaToOneEnable = VK_FALSE;
|
|
|
|
pipeline_colour_blend_attachment_state.blendEnable = VK_TRUE;
|
|
pipeline_colour_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
|
pipeline_colour_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
pipeline_colour_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD;
|
|
pipeline_colour_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
|
pipeline_colour_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
|
pipeline_colour_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD;
|
|
pipeline_colour_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT
|
|
| VK_COLOR_COMPONENT_G_BIT
|
|
| VK_COLOR_COMPONENT_B_BIT
|
|
| VK_COLOR_COMPONENT_A_BIT;
|
|
|
|
pipeline_colour_blend_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
|
pipeline_colour_blend_state_information.logicOpEnable = VK_FALSE;
|
|
pipeline_colour_blend_state_information.logicOp = VK_LOGIC_OP_COPY;
|
|
pipeline_colour_blend_state_information.attachmentCount = 1;
|
|
pipeline_colour_blend_state_information.pAttachments = & pipeline_colour_blend_attachment_state;
|
|
|
|
pipeline_information.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
pipeline_information.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
|
|
pipeline_information.stageCount = 2;
|
|
pipeline_information.pStages = pipeline_shader_stage_information;
|
|
pipeline_information.pVertexInputState = & pipeline_vertex_input_state_information;
|
|
pipeline_information.pInputAssemblyState = & pipeline_input_assembly_state_information;
|
|
pipeline_information.pTessellationState = null;
|
|
pipeline_information.pViewportState = & pipeline_viewport_state_information;
|
|
pipeline_information.pRasterizationState = & pipeline_rasterization_state_information;
|
|
pipeline_information.pMultisampleState = & pipeline_multisample_state_information;
|
|
pipeline_information.pDepthStencilState = null;
|
|
pipeline_information.pColorBlendState = & pipeline_colour_blend_state_information;
|
|
pipeline_information.pDynamicState = null;
|
|
pipeline_information.layout = vulkan->pipeline_layout;
|
|
pipeline_information.renderPass = vulkan->render_pass;
|
|
pipeline_information.subpass = 0;
|
|
pipeline_information.basePipelineHandle = VK_NULL_HANDLE;
|
|
pipeline_information.basePipelineIndex = -1;
|
|
|
|
vulkan_result (vkCreateGraphicsPipelines (vulkan->boolean_device, VK_NULL_HANDLE, 1, & pipeline_information, null, & vulkan->pipeline));
|
|
|
|
print ("/c Created /2Vulkan graphics pipeline/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_framebuffers (vulkan_structure * vulkan) {
|
|
VkFramebufferCreateInfo framebuffer_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->framebuffers = allocate (vulkan->image_count * sizeof (VkFramebuffer));
|
|
|
|
framebuffer_information.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
framebuffer_information.renderPass = vulkan->render_pass;
|
|
framebuffer_information.attachmentCount = 1;
|
|
framebuffer_information.width = vulkan->extent.width;
|
|
framebuffer_information.height = vulkan->extent.height;
|
|
framebuffer_information.layers = 1;
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
framebuffer_information.pAttachments = & vulkan->image_views [index];
|
|
|
|
vulkan_result (vkCreateFramebuffer (vulkan->boolean_device, & framebuffer_information, null, & vulkan->framebuffers [index]));
|
|
}
|
|
|
|
print ("/c Created /2Vulkan framebuffers/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_command_pool (vulkan_structure * vulkan) {
|
|
VkCommandPoolCreateInfo command_pool_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
command_pool_information.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
command_pool_information.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
|
command_pool_information.queueFamilyIndex = vulkan->queue_index;
|
|
|
|
vulkan_result (vkCreateCommandPool (vulkan->boolean_device, & command_pool_information, null, & vulkan->command_pool));
|
|
|
|
print ("/c Created /2Vulkan command pool/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_command_buffers (vulkan_structure * vulkan) {
|
|
VkCommandBufferAllocateInfo command_buffer_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->command_buffers = allocate (vulkan->image_count * sizeof (VkCommandBuffer));
|
|
|
|
command_buffer_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
command_buffer_information.commandPool = vulkan->command_pool;
|
|
command_buffer_information.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
command_buffer_information.commandBufferCount = vulkan->image_count;
|
|
|
|
vulkan_result (vkAllocateCommandBuffers (vulkan->boolean_device, & command_buffer_information, vulkan->command_buffers));
|
|
|
|
print ("/c Allocated /2Vulkan command buffers/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_vertex_buffer (vulkan_structure * vulkan) {
|
|
VkBuffer transfer_buffer = VK_NULL_HANDLE;
|
|
VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
|
|
procedure * transfer_procedure = null;
|
|
|
|
VkBufferCopy copy_information = { 0 };
|
|
/*
|
|
vulkan->time = tick_tock ();
|
|
*/
|
|
vulkan->vertex_size = vulkan->vertex_count * sizeof (* vulkan->vertex_data);
|
|
|
|
vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->vertex_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
|
|
|
vulkan_result (vkMapMemory (vulkan->boolean_device, transfer_memory, 0, vulkan->vertex_size, 0, & transfer_v0));
|
|
|
|
memory_copy (transfer_v0, vulkan->vertex_data, vulkan->vertex_size);
|
|
|
|
vulkan_create_buffer (vulkan, & vulkan->vertex_buffer, & vulkan->vertex_memory, vulkan->vertex_size,
|
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
|
|
|
vulkan_begin_command_buffer (vulkan);
|
|
|
|
copy_information.srcOffset = 0;
|
|
copy_information.dstOffset = 0;
|
|
copy_information.size = vulkan->vertex_size;
|
|
|
|
vkCmdCopyBuffer (vulkan->transfer_buffer, transfer_buffer, vulkan->vertex_buffer, 1, & copy_information);
|
|
|
|
vulkan_end_command_buffer (vulkan);
|
|
|
|
vkDestroyBuffer (vulkan->boolean_device, transfer_buffer, null);
|
|
vkFreeMemory (vulkan->boolean_device, transfer_memory, null);
|
|
|
|
/*print ("/c Created /2Vulkan vertex buffer/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
|
|
}
|
|
|
|
static procedure vulkan_create_index_buffer (vulkan_structure * vulkan) {
|
|
VkBuffer transfer_buffer = VK_NULL_HANDLE;
|
|
VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
|
|
procedure * transfer_procedure = null;
|
|
|
|
VkBufferCopy copy_information = { 0 };
|
|
/*
|
|
vulkan->time = tick_tock ();
|
|
*/
|
|
vulkan->index_size = vulkan->index_count * sizeof (* vulkan->index_data);
|
|
|
|
vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->index_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
|
|
|
vulkan_result (vkMapMemory (vulkan->boolean_device, transfer_memory, 0, vulkan->index_size, 0, & transfer_v0));
|
|
|
|
memory_copy (transfer_v0, vulkan->index_data, vulkan->index_size);
|
|
|
|
vulkan_create_buffer (vulkan, & vulkan->index_buffer, & vulkan->index_memory, vulkan->index_size,
|
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
|
|
|
vulkan_begin_command_buffer (vulkan);
|
|
|
|
copy_information.srcOffset = 0;
|
|
copy_information.dstOffset = 0;
|
|
copy_information.size = vulkan->index_size;
|
|
|
|
vkCmdCopyBuffer (vulkan->transfer_buffer, transfer_buffer, vulkan->index_buffer, 1, & copy_information);
|
|
|
|
vulkan_end_command_buffer (vulkan);
|
|
|
|
vkDestroyBuffer (vulkan->boolean_device, transfer_buffer, null);
|
|
vkFreeMemory (vulkan->boolean_device, transfer_memory, null);
|
|
/*
|
|
print ("/c Created /2Vulkan index buffer/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
|
|
}
|
|
|
|
static procedure vulkan_create_image_buffer (vulkan_structure * vulkan) {
|
|
VkBuffer transfer_buffer = VK_NULL_HANDLE;
|
|
VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
|
|
procedure * transfer_procedure = null;
|
|
|
|
VkExtent3D image_extent = { 0 };
|
|
VkImageCreateInfo image_information = { 0 };
|
|
VkMemoryRequirements memory_requirements = { 0 };
|
|
VkMemoryAllocateInfo memory_allocation_information = { 0 };
|
|
VkImageSubresourceLayers region_subresource_layers = { 0 };
|
|
VkOffset3D region_offset = { 0 };
|
|
VkExtent3D region_extent = { 0 };
|
|
VkBufferImageCopy region_copying_information = { 0 };
|
|
VkComponentMapping component_mapping = { 0 };
|
|
VkImageSubresourceRange image_subresource_range = { 0 };
|
|
VkImageViewCreateInfo image_view_information = { 0 };
|
|
VkImageMemoryBarrier image_memory_barrier = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->layout_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
|
|
|
vulkan_result (vkMapMemory (vulkan->boolean_device, transfer_memory, 0, vulkan->layout_size, 0, & transfer_v0));
|
|
|
|
memory_copy (transfer_v0, vulkan->layout_data, vulkan->layout_size);
|
|
|
|
image_extent.width = vulkan->layout_width;
|
|
image_extent.height = vulkan->layout_height;
|
|
image_extent.depth = 1;
|
|
|
|
image_information.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
image_information.imageType = VK_IMAGE_TYPE_2D;
|
|
image_information.format = vulkan->format;
|
|
image_information.extent = image_extent;
|
|
image_information.mipLevels = 1;
|
|
image_information.arrayLayers = 1;
|
|
image_information.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
image_information.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
image_information.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
image_information.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
image_information.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
image_subresource_range.baseMipLevel = 0;
|
|
image_subresource_range.levelCount = 1;
|
|
image_subresource_range.baseArrayLayer = 0;
|
|
image_subresource_range.layerCount = 1;
|
|
|
|
vulkan_result (vkCreateImage (vulkan->boolean_device, & image_information, null, & vulkan->layout_image));
|
|
|
|
vkGetImageMemoryRequirements (vulkan->boolean_device, vulkan->layout_image, & memory_requirements);
|
|
|
|
memory_allocation_information.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
memory_allocation_information.allocationSize = memory_requirements.size;
|
|
memory_allocation_information.memoryTypeIndex = vulkan_choose_memory_property (vulkan, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
|
vulkan_result (vkAllocateMemory (vulkan->boolean_device, & memory_allocation_information, null, & vulkan->layout_memory));
|
|
|
|
vulkan_result (vkBindImageMemory (vulkan->boolean_device, vulkan->layout_image, vulkan->layout_memory, 0));
|
|
|
|
vulkan_begin_command_buffer (vulkan);
|
|
|
|
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
image_memory_barrier.pNext = null;
|
|
image_memory_barrier.srcAccessMask = 0;
|
|
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
image_memory_barrier.image = vulkan->layout_image;
|
|
image_memory_barrier.subresourceRange = image_subresource_range;
|
|
|
|
vkCmdPipelineBarrier (vulkan->transfer_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, null, 0, null,
|
|
1, & image_memory_barrier);
|
|
|
|
vulkan_end_command_buffer (vulkan);
|
|
|
|
vulkan_begin_command_buffer (vulkan);
|
|
|
|
region_subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
region_subresource_layers.mipLevel = 0;
|
|
region_subresource_layers.baseArrayLayer = 0;
|
|
region_subresource_layers.layerCount = 1;
|
|
|
|
region_offset.x = 0;
|
|
region_offset.y = 0;
|
|
region_offset.z = 0;
|
|
|
|
region_extent.width = vulkan->layout_width;
|
|
region_extent.height = vulkan->layout_height;
|
|
region_extent.depth = 1;
|
|
|
|
region_copying_information.bufferOffset = 0;
|
|
region_copying_information.bufferRowLength = 0;
|
|
region_copying_information.bufferImageHeight = 0;
|
|
region_copying_information.imageSubresource = region_subresource_layers;
|
|
region_copying_information.imageOffset = region_offset;
|
|
region_copying_information.imageExtent = region_extent;
|
|
|
|
vkCmdCopyBufferToImage (vulkan->transfer_buffer, transfer_buffer, vulkan->layout_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
|
|
& region_copying_information);
|
|
|
|
vulkan_end_command_buffer (vulkan);
|
|
|
|
vulkan_begin_command_buffer (vulkan);
|
|
|
|
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
image_memory_barrier.pNext = null;
|
|
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
image_memory_barrier.image = vulkan->layout_image;
|
|
image_memory_barrier.subresourceRange = image_subresource_range;
|
|
|
|
vkCmdPipelineBarrier (vulkan->transfer_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, null, 0,
|
|
null, 1, & image_memory_barrier);
|
|
|
|
vulkan_end_command_buffer (vulkan);
|
|
|
|
component_mapping.r = VK_COMPONENT_SWIZZLE_R;
|
|
component_mapping.g = VK_COMPONENT_SWIZZLE_G;
|
|
component_mapping.b = VK_COMPONENT_SWIZZLE_B;
|
|
component_mapping.a = VK_COMPONENT_SWIZZLE_A;
|
|
|
|
image_view_information.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
image_view_information.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
image_view_information.format = vulkan->format;
|
|
image_view_information.components = component_mapping;
|
|
image_view_information.subresourceRange = image_subresource_range;
|
|
image_view_information.image = vulkan->layout_image;
|
|
|
|
vulkan_result (vkCreateImageView (vulkan->boolean_device, & image_view_information, null, & vulkan->layout_image_view));
|
|
|
|
vkDestroyBuffer (vulkan->boolean_device, transfer_buffer, null);
|
|
vkFreeMemory (vulkan->boolean_device, transfer_memory, null);
|
|
|
|
print ("/c Created /2Vulkan image layout buffer/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_sampler (vulkan_structure * vulkan) {
|
|
VkSamplerCreateInfo sampler_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
sampler_information.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
sampler_information.magFilter = VK_FILTER_NEAREST;
|
|
sampler_information.minFilter = VK_FILTER_NEAREST;
|
|
sampler_information.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
sampler_information.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
sampler_information.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
sampler_information.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
sampler_information.mipLodBias = 0;
|
|
sampler_information.anisotropyEnable = VK_FALSE;
|
|
sampler_information.maxAnisotropy = 1;
|
|
sampler_information.compareEnable = VK_FALSE;
|
|
sampler_information.compareOp = VK_COMPARE_OP_ALWAYS;
|
|
sampler_information.minLod = 0;
|
|
sampler_information.maxLod = 0;
|
|
sampler_information.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
|
sampler_information.unnormalizedCoordinates = VK_FALSE;
|
|
|
|
vulkan_result (vkCreateSampler (vulkan->boolean_device, & sampler_information, null, & vulkan->sampler));
|
|
|
|
print ("/c Created /2Vulkan sampler/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_descriptor_pool (vulkan_structure * vulkan) {
|
|
VkDescriptorPoolSize descriptor_pool_sizes [2] = { { 0 } };
|
|
VkDescriptorPoolCreateInfo descriptor_pool_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
descriptor_pool_sizes[0].descriptorCount = vulkan->image_count;
|
|
descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
descriptor_pool_sizes[1].descriptorCount = vulkan->image_count;
|
|
|
|
descriptor_pool_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
descriptor_pool_information.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
|
descriptor_pool_information.maxSets = vulkan->image_count;
|
|
descriptor_pool_information.poolSizeCount = 2;
|
|
descriptor_pool_information.pPoolSizes = descriptor_pool_sizes;
|
|
|
|
vulkan_result (vkCreateDescriptorPool (vulkan->boolean_device, & descriptor_pool_information, null, & vulkan->descriptor_pool));
|
|
|
|
print ("/c Created /2Vulkan descriptor pool/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_create_descriptor_sets (vulkan_structure * vulkan) {
|
|
VkDescriptorSetAllocateInfo descriptor_set_allocation_information = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
vulkan->descriptor_set_layouts = allocate (vulkan->image_count * sizeof (VkDescriptorSetLayout));
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
vulkan->descriptor_set_layouts [index] = vulkan->descriptor_set_layout;
|
|
}
|
|
|
|
descriptor_set_allocation_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
descriptor_set_allocation_information.descriptorPool = vulkan->descriptor_pool;
|
|
descriptor_set_allocation_information.descriptorSetCount = vulkan->image_count;
|
|
descriptor_set_allocation_information.pSetLayouts = vulkan->descriptor_set_layouts;
|
|
|
|
vulkan->descriptor_sets = allocate (vulkan->image_count * sizeof (VkDescriptorSet));
|
|
|
|
vulkan_result (vkAllocateDescriptorSets (vulkan->boolean_device, & descriptor_set_allocation_information, vulkan->descriptor_sets));
|
|
|
|
print ("/c Allocated /2Vulkan descriptor sets/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_record_descriptor_sets (vulkan_structure * vulkan) {
|
|
VkDescriptorBufferInfo descriptor_buffer_information = { 0 };
|
|
VkDescriptorImageInfo descriptor_image_information = { 0 };
|
|
VkWriteDescriptorSet write_descriptor_set = { 0 };
|
|
|
|
vulkan->time = tick_tock ();
|
|
|
|
descriptor_image_information.sampler = vulkan->sampler;
|
|
descriptor_image_information.imageView = vulkan->layout_image_view;
|
|
descriptor_image_information.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
write_descriptor_set.dstBinding = 1;
|
|
write_descriptor_set.dstArrayElement = 0;
|
|
write_descriptor_set.descriptorCount = 1;
|
|
write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
write_descriptor_set.pImageInfo = & descriptor_image_information;
|
|
write_descriptor_set.pBufferInfo = null;
|
|
|
|
for (natural index = 0; index < vulkan->image_count; ++index) {
|
|
write_descriptor_set.dstSet = vulkan->descriptor_sets [index];
|
|
|
|
vkUpdateDescriptorSets (vulkan->boolean_device, 1, & write_descriptor_set, 0, null);
|
|
}
|
|
|
|
print ("/c Recorded /2Vulkan descriptor sets/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
|
|
}
|
|
|
|
static procedure vulkan_record_command_buffers (vulkan_structure * vulkan, integer clear_colour, integer frame) {
|
|
natural index = 0;
|
|
|
|
VkCommandBufferBeginInfo command_buffer_begin_information = { 0 };
|
|
//~VkImageSubresourceRange image_subresource_range = { 0 };
|
|
VkClearValue clear_value = { 0 };
|
|
VkOffset2D render_area_offset = { 0 };
|
|
VkExtent2D render_area_extent = { 0 };
|
|
VkRect2D render_area = { 0 };
|
|
VkRenderPassBeginInfo render_pass_begin_information = { 0 };
|
|
VkDeviceSize vertex_offset = 0;
|
|
|
|
VkClearColorValue clear_colour_value = { {
|
|
(real) ((clear_colour & 0xff000000) >> 24) / 255,
|
|
(real) ((clear_colour & 0x00ff0000) >> 16) / 255,
|
|
(real) ((clear_colour & 0x0000ff00) >> 8) / 255,
|
|
(real) ((clear_colour & 0x000000ff) >> 0) / 255
|
|
} };
|
|
|
|
(none) frame;
|
|
/*
|
|
vulkan->time = tick_tock ();
|
|
*/
|
|
command_buffer_begin_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
command_buffer_begin_information.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
|
|
|
//~image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
//~image_subresource_range.baseMipLevel = 0;
|
|
//~image_subresource_range.levelCount = 1;
|
|
//~image_subresource_range.baseArrayLayer = 0;
|
|
//~image_subresource_range.layerCount = 1;
|
|
|
|
clear_value.color = clear_colour_value;
|
|
|
|
render_area_offset.x = 0;
|
|
render_area_offset.y = 0;
|
|
|
|
render_area_extent.width = vulkan->extent.width;
|
|
render_area_extent.height = vulkan->extent.height;
|
|
|
|
render_area.offset = render_area_offset;
|
|
render_area.extent = render_area_extent;
|
|
|
|
render_pass_begin_information.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
render_pass_begin_information.pNext = null;
|
|
render_pass_begin_information.renderPass = vulkan->render_pass;
|
|
render_pass_begin_information.renderArea = render_area;
|
|
render_pass_begin_information.clearValueCount = 1;
|
|
render_pass_begin_information.pClearValues = & clear_value;
|
|
|
|
for (index = 0; index < vulkan->image_count; ++index) {
|
|
render_pass_begin_information.framebuffer = vulkan->framebuffers [index];
|
|
|
|
vulkan_result (vkBeginCommandBuffer (vulkan->command_buffers [index], & command_buffer_begin_information));
|
|
|
|
vkCmdBeginRenderPass (vulkan->command_buffers [index], & render_pass_begin_information, VK_SUBPASS_CONTENTS_INLINE);
|
|
|
|
vkCmdBindPipeline (vulkan->command_buffers [index], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan->pipeline);
|
|
|
|
vkCmdBindVertexBuffers (vulkan->command_buffers [index], 0, 1, & vulkan->vertex_buffer, & vertex_offset);
|
|
|
|
vkCmdBindIndexBuffer (vulkan->command_buffers [index], vulkan->index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
|
|
vkCmdBindDescriptorSets (vulkan->command_buffers [index], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan->pipeline_layout, 0, 1,
|
|
vulkan->descriptor_sets, 0, null);
|
|
|
|
vkCmdDrawIndexed (vulkan->command_buffers [index], vulkan->index_count, 1, 0, 0, 0);
|
|
|
|
vkCmdEndRenderPass (vulkan->command_buffers [index]);
|
|
|
|
vulkan_result (vkEndCommandBuffer (vulkan->command_buffers [index]));
|
|
}
|
|
/*
|
|
render_pass_begin_information.framebuffer = vulkan_framebuffers [frame];
|
|
|
|
vulkan_result (vkBeginCommandBuffer (vulkan_command_buffers [frame], & command_buffer_begin_information));
|
|
|
|
vkCmdBeginRenderPass (vulkan_command_buffers [frame], & render_pass_begin_information, VK_SUBPASS_CONTENTS_INLINE);
|
|
|
|
vkCmdBindPipeline (vulkan_command_buffers [frame], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_pipeline);
|
|
|
|
vkCmdBindVertexBuffers (vulkan_command_buffers [frame], 0, 1, & vulkan_vertex_buffer, & vertex_offset);
|
|
|
|
vkCmdBindIndexBuffer (vulkan_command_buffers [frame], vulkan_index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
|
|
vkCmdBindDescriptorSets (vulkan_command_buffers [frame], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_pipeline_layout, 0, 1,
|
|
vulkan_descriptor_sets, 0, null);
|
|
|
|
vkCmdDrawIndexed (vulkan_command_buffers [frame], vulkan_index_count, 1, 0, 0, 0);
|
|
|
|
vkCmdEndRenderPass (vulkan_command_buffers [frame]);
|
|
|
|
vulkan_result (vkEndCommandBuffer (vulkan_command_buffers [frame]));
|
|
*/
|
|
vulkan_result (vkQueueWaitIdle (vulkan->queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan->boolean_device));
|
|
|
|
/*print ("/c Recorded /2Vulkan command buffers/-.\n");
|
|
print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
|
|
}
|
|
|
|
static natural vulkan_import_sprite (vulkan_structure * vulkan, natural * data, natural width, natural height) {
|
|
fatal_failure (vulkan->active == true, "vulkan_import_sprite: Failed to import sprite, engine was already configured.");
|
|
fatal_failure (data == null, "vulkan_import_sprite: Failed to import sprite, data is null pointer.");
|
|
fatal_failure (width <= 0, "vulkan_import_sprite: Failed to import sprite, width is equal or below zero.");
|
|
fatal_failure (height <= 0, "vulkan_import_sprite: Failed to import sprite, height is equal or below zero.");
|
|
|
|
++vulkan->sprite_count;
|
|
|
|
vulkan->sprite_data = reallocate (vulkan->sprite_data, vulkan->sprite_count * sizeof (* vulkan->sprite_data));
|
|
vulkan->sprite_width = reallocate (vulkan->sprite_width, vulkan->sprite_count * sizeof (* vulkan->sprite_width));
|
|
vulkan->sprite_height = reallocate (vulkan->sprite_height, vulkan->sprite_count * sizeof (* vulkan->sprite_height));
|
|
vulkan->sprite_u = reallocate (vulkan->sprite_u, vulkan->sprite_count * sizeof (* vulkan->sprite_u));
|
|
vulkan->sprite_v = reallocate (vulkan->sprite_v, vulkan->sprite_count * sizeof (* vulkan->sprite_v));
|
|
|
|
vulkan->sprite_data [vulkan->sprite_count - 1] = data;
|
|
vulkan->sprite_width [vulkan->sprite_count - 1] = width;
|
|
vulkan->sprite_height [vulkan->sprite_count - 1] = height;
|
|
vulkan->sprite_u [vulkan->sprite_count - 1] = 0;
|
|
vulkan->sprite_v [vulkan->sprite_count - 1] = 0;
|
|
|
|
return (vulkan->sprite_count - 1);
|
|
}
|
|
|
|
static natural vulkan_import_font (vulkan_structure * vulkan, natural * data, natural image_width, natural image_height, character begin, character end, natural empty) {
|
|
natural pointer = 0;
|
|
character index = 0;
|
|
natural width = 0;
|
|
natural height = 0;
|
|
natural x = 0;
|
|
natural y = 0;
|
|
|
|
natural * buffer = null;
|
|
|
|
++vulkan->font_count;
|
|
|
|
vulkan->font_index = reallocate (vulkan->font_index, vulkan->font_count * sizeof (* vulkan->font_index));
|
|
vulkan->font_width = reallocate (vulkan->font_width, vulkan->font_count * sizeof (* vulkan->font_width));
|
|
vulkan->font_height = reallocate (vulkan->font_height, vulkan->font_count * sizeof (* vulkan->font_height));
|
|
vulkan->font_begin = reallocate (vulkan->font_begin, vulkan->font_count * sizeof (* vulkan->font_begin));
|
|
vulkan->font_end = reallocate (vulkan->font_end, vulkan->font_count * sizeof (* vulkan->font_end));
|
|
|
|
vulkan->font_begin [vulkan->font_count - 1] = begin;
|
|
vulkan->font_end [vulkan->font_count - 1] = end;
|
|
|
|
vulkan->font_index [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_index));
|
|
vulkan->font_width [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_width));
|
|
vulkan->font_height [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_height));
|
|
|
|
for (index = begin; index <= end; ++index) {
|
|
for ( ; data [pointer] == empty; ++pointer);
|
|
for (width = 0; data [pointer + width] != empty; ++width);
|
|
for (height = 0; data [pointer + height * image_width] != empty; ++height);
|
|
|
|
buffer = allocate (width * height * sizeof (* buffer));
|
|
|
|
for (y = 0; y < height; ++y) {
|
|
for (x = 0; x < width; ++x) {
|
|
buffer [y * width + x] = data [pointer + (y * image_width) + x];
|
|
}
|
|
}
|
|
|
|
vulkan->font_index [vulkan->font_count - 1] [index - begin] = vulkan_import_sprite (vulkan, buffer, width, height);
|
|
vulkan->font_width [vulkan->font_count - 1] [index - begin] = width;
|
|
vulkan->font_height [vulkan->font_count - 1] [index - begin] = height;
|
|
|
|
pointer += width;
|
|
|
|
for (; data [pointer] == empty; ++pointer);
|
|
|
|
if (pointer % image_width == 2) {
|
|
pointer += height * image_width;
|
|
}
|
|
}
|
|
|
|
return (vulkan->font_count - 1);
|
|
}
|
|
|
|
static procedure vulkan_bundle_layout (vulkan_structure * vulkan) {
|
|
natural * order = null;
|
|
|
|
vulkan->layout_size = vulkan->layout_width * vulkan->layout_height * (natural) sizeof (* vulkan->layout_data);
|
|
|
|
vulkan->layout_data = allocate (vulkan->layout_size);
|
|
|
|
order = allocate (vulkan->sprite_count * sizeof (* order));
|
|
|
|
for (natural index = 0; index < vulkan->sprite_count; ++index) {
|
|
order [index] = index;
|
|
}
|
|
|
|
for (natural index = 0; index < vulkan->sprite_count; ++index) {
|
|
for (natural subindex = 0; subindex < vulkan->sprite_count; ++subindex) {
|
|
if (vulkan->sprite_height [order [index]] < vulkan->sprite_height [order [subindex]]) {
|
|
integer temporary = order [index];
|
|
|
|
order [index] = order [subindex];
|
|
order [subindex] = temporary;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (natural index = 0; index < vulkan->sprite_count; ++index) {
|
|
natural x = 0;
|
|
natural y = 0;
|
|
natural u = 0;
|
|
natural v = 0;
|
|
|
|
|
|
if (u + vulkan->sprite_width [order [index]] >= vulkan->layout_width) {
|
|
u *= 0;
|
|
v += vulkan->sprite_height [order [index]];
|
|
}
|
|
|
|
vulkan->sprite_u [order [index]] = (real) u / (real) vulkan->layout_width;
|
|
vulkan->sprite_v [order [index]] = (real) v / (real) vulkan->layout_height;
|
|
|
|
for (natural y = 0; y < vulkan->sprite_height [order [index]]; ++y) {
|
|
for (natural x = 0; x < vulkan->sprite_width [order [index]]; ++x) {
|
|
natural destination = (v + y) * vulkan->layout_width + (u + x);
|
|
natural source = y * vulkan->sprite_width [order [index]] + x;
|
|
|
|
vulkan->layout_data [destination] = vulkan->sprite_data [order [index]] [source];
|
|
}
|
|
}
|
|
|
|
u += vulkan->sprite_width [order [index]];
|
|
|
|
vulkan->sprite_data [order [index]] = deallocate (vulkan->sprite_data [order [index]]);
|
|
}
|
|
|
|
vulkan->sprite_data = deallocate (vulkan->sprite_data);
|
|
order = deallocate (order);
|
|
}
|
|
|
|
static procedure vulkan_configure (vulkan_structure * vulkan, integer width, integer height, character * application) {
|
|
integer index = 0;
|
|
|
|
natural * dumb_buffer = null;
|
|
|
|
if (vulkan->active == true) {
|
|
return;
|
|
}
|
|
|
|
vulkan->width = width;
|
|
vulkan->height = height;
|
|
|
|
vulkan->pixel_width = (real) 2 / (real) width;
|
|
vulkan->pixel_height = (real) 2 / (real) height;
|
|
|
|
dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
|
|
|
|
for (index = 0; index < 256; ++index) {
|
|
dumb_buffer [index] = ~0;
|
|
}
|
|
|
|
vulkan_import_sprite (vulkan, dumb_buffer, 16, 16);
|
|
|
|
vulkan_bundle_layout (vulkan);
|
|
|
|
vulkan->vertex_data = allocate (vulkan->vertex_limit * sizeof (* vulkan->vertex_data));
|
|
vulkan->index_data = allocate (vulkan->index_limit * sizeof (* vulkan->index_data));
|
|
|
|
vulkan_create_window (vulkan, application);
|
|
vulkan_create_instance (vulkan, application);
|
|
print ("/c Variable : width = %i\n", vulkan->width);
|
|
print ("/c Variable : height = %i\n", vulkan->height);
|
|
print ("/c Variable : sprite_count = %i\n", vulkan->sprite_count);
|
|
print ("/c Variable : font_count = %i\n", vulkan->font_count);
|
|
print ("/c Variable : gameplay_framerate = %i\n", vulkan->gameplay_framerate);
|
|
print ("/c Variable : animation_framerate = %i\n", vulkan->animation_framerate);
|
|
print ("/c Variable : vertex_limit = %i\n", vulkan->vertex_limit);
|
|
print ("/c Variable : index_limit = %i\n", vulkan->index_limit);
|
|
print ("/c Variable : layout_size = %i\n", vulkan->layout_size);
|
|
print ("/c Variable : layout_width = %i\n", vulkan->layout_width);
|
|
print ("/c Variable : layout_height = %i\n", vulkan->layout_height);
|
|
|
|
vulkan_create_surface (vulkan);
|
|
vulkan_create_device (vulkan);
|
|
vulkan_choose_extent (vulkan);
|
|
vulkan_choose_format (vulkan);
|
|
vulkan_choose_present_mode (vulkan);
|
|
vulkan_create_swapchain (vulkan);
|
|
vulkan_create_images (vulkan);
|
|
vulkan_create_image_views (vulkan);
|
|
vulkan_create_semaphores (vulkan);
|
|
vulkan_create_fences (vulkan);
|
|
vulkan_create_render_pass (vulkan);
|
|
vulkan_create_descriptor_set_layout (vulkan);
|
|
vulkan_create_vertex_shader (vulkan);
|
|
vulkan_create_fragment_shader (vulkan);
|
|
vulkan_create_pipeline_layout (vulkan);
|
|
vulkan_create_pipeline (vulkan);
|
|
vulkan_create_framebuffers (vulkan);
|
|
vulkan_create_command_pool (vulkan);
|
|
vulkan_create_command_buffers (vulkan);
|
|
vulkan_create_image_buffer (vulkan);
|
|
vulkan_create_sampler (vulkan);
|
|
vulkan_create_descriptor_pool (vulkan);
|
|
vulkan_create_descriptor_sets (vulkan);
|
|
vulkan_record_descriptor_sets (vulkan);
|
|
|
|
vulkan->active = true;
|
|
}
|
|
/*
|
|
static procedure vulkan_reconfigure (none) {
|
|
integer index;
|
|
|
|
vulkan_result (vkQueueWaitIdle (vulkan_queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan_boolean_device));
|
|
|
|
for (index = 0; index < vulkan_image_count; ++index) {
|
|
vkDestroyFramebuffer (vulkan_boolean_device, vulkan_framebuffers [index], null);
|
|
}
|
|
|
|
vulkan_framebuffers = deallocate (vulkan_framebuffers);
|
|
|
|
for (index = 0; index < vulkan_image_count; ++index) {
|
|
vkDestroyImageView (vulkan_boolean_device, vulkan_image_views [index], null);
|
|
}
|
|
|
|
vulkan_image_views = deallocate (vulkan_image_views);
|
|
|
|
vkDestroySwapchainKHR (vulkan_boolean_device, vulkan_swapchain, null);
|
|
|
|
vulkan_images = deallocate (vulkan_images);
|
|
|
|
vulkan_choose_extent ();
|
|
vulkan_choose_format ();
|
|
vulkan_choose_present_mode ();
|
|
vulkan_create_swapchain ();
|
|
vulkan_create_images ();
|
|
vulkan_create_image_views ();
|
|
vulkan_create_framebuffers ();
|
|
|
|
vulkan_result (vkQueueWaitIdle (vulkan_queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan_boolean_device));
|
|
|
|
vulkan_reconfigure_active = false;
|
|
}
|
|
*/
|
|
static procedure vulkan_render_core (vulkan_structure * vulkan, integer sprite, integer x, integer y, integer u, integer v, integer width, integer height,
|
|
real scale_x, real scale_y, integer flip_x, integer flip_y,
|
|
integer colour_0, natural colour_1, natural colour_2, natural colour_3) {
|
|
real screen_x = x * vulkan->pixel_width;
|
|
real screen_y = y * vulkan->pixel_height;
|
|
|
|
real unwrap_x = vulkan->sprite_u [sprite] + (real) u / vulkan->layout_width;
|
|
real unwrap_y = vulkan->sprite_v [sprite] + (real) v / vulkan->layout_height;
|
|
|
|
real screen_width = (real) width * vulkan->pixel_width * scale_x;
|
|
real screen_height = (real) height * vulkan->pixel_height * scale_y;
|
|
|
|
real unwrap_width = (real) width / vulkan->layout_width;
|
|
real unwrap_height = (real) height / vulkan->layout_height;
|
|
|
|
fatal_failure (vulkan->vertex_count + 32 >= vulkan->vertex_limit, "Reached vertex limit.");
|
|
fatal_failure (vulkan->index_count + 6 >= vulkan->index_limit, "Reached index limit.");
|
|
|
|
vulkan->vertex_data [vulkan->vertex_count + 0] = screen_x;
|
|
vulkan->vertex_data [vulkan->vertex_count + 1] = screen_y;
|
|
vulkan->vertex_data [vulkan->vertex_count + 2] = unwrap_x + unwrap_width * (flip_y != 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 3] = unwrap_y + unwrap_height * (flip_x != 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 4] = (real) ((colour_0 >> 24) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 5] = (real) ((colour_0 >> 16) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 6] = (real) ((colour_0 >> 8) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 7] = (real) ((colour_0 >> 0) & 0xff) / 255;
|
|
|
|
vulkan->vertex_data [vulkan->vertex_count + 8] = screen_x + screen_width;
|
|
vulkan->vertex_data [vulkan->vertex_count + 9] = screen_y;
|
|
vulkan->vertex_data [vulkan->vertex_count + 10] = unwrap_x + unwrap_width * (flip_y == 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 11] = unwrap_y + unwrap_height * (flip_x != 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 12] = (real) ((colour_1 >> 24) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 13] = (real) ((colour_1 >> 16) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 14] = (real) ((colour_1 >> 8) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 15] = (real) ((colour_1 >> 0) & 0xff) / 255;
|
|
|
|
vulkan->vertex_data [vulkan->vertex_count + 16] = screen_x;
|
|
vulkan->vertex_data [vulkan->vertex_count + 17] = screen_y + screen_height;
|
|
vulkan->vertex_data [vulkan->vertex_count + 18] = unwrap_x + unwrap_width * (flip_y != 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 19] = unwrap_y + unwrap_height * (flip_x == 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 20] = (real) ((colour_2 >> 24) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 21] = (real) ((colour_2 >> 16) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 22] = (real) ((colour_2 >> 8) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 23] = (real) ((colour_2 >> 0) & 0xff) / 255;
|
|
|
|
vulkan->vertex_data [vulkan->vertex_count + 24] = screen_x + screen_width;
|
|
vulkan->vertex_data [vulkan->vertex_count + 25] = screen_y + screen_height;
|
|
vulkan->vertex_data [vulkan->vertex_count + 26] = unwrap_x + unwrap_width * (flip_y == 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 27] = unwrap_y + unwrap_height * (flip_x == 0);
|
|
vulkan->vertex_data [vulkan->vertex_count + 28] = (real) ((colour_3 >> 24) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 29] = (real) ((colour_3 >> 16) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 30] = (real) ((colour_3 >> 8) & 0xff) / 255;
|
|
vulkan->vertex_data [vulkan->vertex_count + 31] = (real) ((colour_3 >> 0) & 0xff) / 255;
|
|
|
|
vulkan->index_data [vulkan->index_count + 0] = (vulkan->vertex_count >> 3) + 0;
|
|
vulkan->index_data [vulkan->index_count + 1] = (vulkan->vertex_count >> 3) + 1;
|
|
vulkan->index_data [vulkan->index_count + 2] = (vulkan->vertex_count >> 3) + 2;
|
|
vulkan->index_data [vulkan->index_count + 3] = (vulkan->vertex_count >> 3) + 1;
|
|
vulkan->index_data [vulkan->index_count + 4] = (vulkan->vertex_count >> 3) + 3;
|
|
vulkan->index_data [vulkan->index_count + 5] = (vulkan->vertex_count >> 3) + 2;
|
|
|
|
vulkan->vertex_count += 32;
|
|
vulkan->index_count += 6;
|
|
}
|
|
|
|
static procedure vulkan_render_sprite (vulkan_structure * vulkan, integer sprite, integer x, integer y, natural colour) {
|
|
vulkan_render_core (vulkan, sprite, x, y, 0, 0, vulkan->sprite_width [sprite], vulkan->sprite_height [sprite], 1.0, 1.0, 0, 0, colour, colour, colour,colour);
|
|
}
|
|
|
|
static procedure vulkan_render_sprite_scale (vulkan_structure * vulkan, integer sprite, integer x, integer y, real scale, natural colour) {
|
|
vulkan_render_core (vulkan, sprite, x, y, 0, 0, vulkan->sprite_width [sprite], vulkan->sprite_height [sprite], scale, scale, 0, 0, colour, colour, colour,colour);
|
|
}
|
|
|
|
static procedure vulkan_render_sprite_crop (vulkan_structure * vulkan, integer sprite, integer x, integer y, integer u, integer v, integer width, integer height, natural colour) {
|
|
vulkan_render_core (vulkan, sprite, x, y, u, v, width, height, 1.0, 1.0, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static procedure vulkan_render_rectangle (vulkan_structure * vulkan, integer x, integer y, integer width, integer height, natural colour) {
|
|
vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static procedure vulkan_render_rectangle_gradient_v (vulkan_structure * vulkan, integer x, integer y, integer width, integer height, natural colour_up, natural colour_down) {
|
|
vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_up, colour_up, colour_down, colour_down);
|
|
}
|
|
|
|
static procedure vulkan_render_rectangle_gradient_h (vulkan_structure * vulkan, integer x, integer y, integer width, integer height, natural colour_left, natural colour_right) {
|
|
vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_left, colour_right, colour_left, colour_right);
|
|
}
|
|
|
|
static integer vulkan_string_width (vulkan_structure * vulkan, character * string, integer font, real scale) {
|
|
integer length = 0;
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
integer character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
/*
|
|
if (string [index] == '\t') {
|
|
length += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
continue;
|
|
}
|
|
*/
|
|
length += vulkan->sprite_width [character] * scale;
|
|
}
|
|
|
|
return (length);
|
|
}
|
|
|
|
static procedure vulkan_render_string (vulkan_structure * vulkan, character * string, integer font, integer x, integer y, natural colour) {
|
|
integer offset = x;
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
integer character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
|
|
if (string [index] == '\t') {
|
|
x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
x = offset;
|
|
y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
vulkan_render_sprite (vulkan, character, x, y, colour);
|
|
|
|
x += vulkan->sprite_width [character];
|
|
}
|
|
}
|
|
|
|
static procedure vulkan_render_string_scale (vulkan_structure * vulkan, character * string, integer font, integer x, integer y, real scale, natural colour) {
|
|
integer offset = x;
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
integer character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
|
|
if (string [index] == '\t') {
|
|
x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
x = offset;
|
|
y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
|
|
0, 0, colour, colour, colour, colour);
|
|
|
|
x += vulkan->sprite_width [character];
|
|
}
|
|
}
|
|
|
|
static procedure vulkan_render_string_offset (vulkan_structure * vulkan, character * string, natural length, natural font, natural offset, integer * x, integer * y, natural colour) {
|
|
for (natural index = 0; (string [index] != '\0') && (index < length); ++index) {
|
|
natural character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
|
|
if (string [index] == '\t') {
|
|
* x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
* x = offset;
|
|
* y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
|
|
continue;
|
|
}
|
|
|
|
vulkan_render_sprite (vulkan, character, * x, * y, colour);
|
|
|
|
* x += vulkan->sprite_width [character];
|
|
}
|
|
}
|
|
|
|
static procedure vulkan_render_string_gradient_v (vulkan_structure * vulkan, character * string, integer font, integer x, integer y, real scale, natural colour_up, natural colour_down) {
|
|
integer offset = x;
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
natural character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
|
|
if (string [index] == '\t') {
|
|
x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
x = offset;
|
|
y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
|
|
continue;
|
|
}
|
|
|
|
vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
|
|
0, 0, colour_up, colour_up, colour_down, colour_down);
|
|
|
|
x += vulkan->sprite_width [character] * scale;
|
|
}
|
|
}
|
|
|
|
static procedure vulkan_render_string_gradient_h (vulkan_structure * vulkan, character * string, integer font, integer x, integer y, real scale, natural colour_left, natural colour_right) {
|
|
integer offset = x;
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
natural character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
|
|
|
|
if (string [index] == '\t') {
|
|
x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
|
|
continue;
|
|
}
|
|
|
|
if (string [index] == '\n') {
|
|
x = offset;
|
|
y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
|
|
continue;
|
|
}
|
|
|
|
vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
|
|
0, 0, colour_left, colour_right, colour_left, colour_right);
|
|
|
|
x += vulkan->sprite_width [character] * scale;
|
|
}
|
|
}
|
|
|
|
static procedure vulkan_handle_events (vulkan_structure * vulkan) {
|
|
static integer signal_code [signal_count] = {
|
|
0,
|
|
38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
|
|
24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
|
|
15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
|
|
48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
|
|
71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
|
|
112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
|
|
85, 79, 80, 81
|
|
};
|
|
|
|
integer index, key_code;
|
|
|
|
xcb_generic_event_t * generic_event;
|
|
|
|
/*generic_event = xcb_wait_for_event (vulkan_connection);*/
|
|
generic_event = xcb_poll_for_event (vulkan->connection);
|
|
|
|
if (generic_event == null) {
|
|
return;
|
|
}
|
|
|
|
switch (generic_event->response_type & 127) {
|
|
case (XCB_EXPOSE): {
|
|
xcb_flush (vulkan->connection);
|
|
} break;
|
|
/*case (XCB_CONFIGURE_NOTIFY): {
|
|
xcb_configure_notify_event_t * reconfigure = (xcb_configure_notify_event_t *) generic_event;
|
|
if ((reconfigure->width != vulkan->width) || (reconfigure->height != vulkan->height)) {
|
|
vulkan->width = reconfigure->width;
|
|
vulkan->height = reconfigure->height;
|
|
if ((vulkan->width > 0) && (vulkan->height > 0)) {
|
|
vulkan->reconfigure_active = true;
|
|
vulkan->reconfigure ();
|
|
}
|
|
}
|
|
} break;*/
|
|
case (XCB_BUTTON_PRESS): {
|
|
vulkan->cursor = (integer) ((xcb_button_press_event_t *) generic_event)->detail;
|
|
vulkan->cursor_x = (integer) ((xcb_button_press_event_t *) generic_event)->event_x;
|
|
vulkan->cursor_y = (integer) ((xcb_button_press_event_t *) generic_event)->event_y;
|
|
} break;
|
|
case (XCB_BUTTON_RELEASE): {
|
|
vulkan->cursor = cursor_none;
|
|
vulkan->cursor_x = (integer) ((xcb_button_release_event_t *) generic_event)->event_x;
|
|
vulkan->cursor_y = (integer) ((xcb_button_release_event_t *) generic_event)->event_y;
|
|
} break;
|
|
case (XCB_KEY_PRESS): {
|
|
key_code = (integer) ((xcb_key_press_event_t *) generic_event)->detail;
|
|
for (index = 0; index < signal_count; ++index) {
|
|
if (key_code == signal_code [index]) {
|
|
vulkan->signal [index] = true;
|
|
break;
|
|
}
|
|
}
|
|
} break;
|
|
case (XCB_KEY_RELEASE): {
|
|
key_code = (integer) ((xcb_key_release_event_t *) generic_event)->detail;
|
|
for (index = 0; index < signal_count; ++index) {
|
|
if (key_code == signal_code [index]) {
|
|
vulkan->signal [index] = false;
|
|
break;
|
|
}
|
|
}
|
|
} break;
|
|
/*case (XCB_MOTION_NOTIFY): {
|
|
vulkan->cursor_x = (integer) ((xcb_motion_notify_event_t *) generic_event)->event_x;
|
|
vulkan->cursor_y = (integer) ((xcb_motion_notify_event_t *) generic_event)->event_y;
|
|
} break;*/
|
|
default: {
|
|
} break;
|
|
}
|
|
|
|
generic_event = deallocate (generic_event);
|
|
}
|
|
|
|
static procedure vulkan_synchronize (vulkan_structure * vulkan, natural clear_colour) {
|
|
natural index = 0;
|
|
natural frame = 0;
|
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
generic * ubo_procedure = null;
|
|
|
|
VkPipelineStageFlags wait_stages [1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT} ;
|
|
|
|
VkSubmitInfo submit_information = { 0 };
|
|
VkPresentInfoKHR present_information = { 0 };
|
|
|
|
VkSwapchainKHR * swapchain_pointer = & vulkan->swapchain;
|
|
|
|
struct timespec frame_begin = { 0 };
|
|
struct timespec frame_end = { 0 };
|
|
|
|
clock_gettime (CLOCK_REALTIME, & frame_begin);
|
|
|
|
vulkan_handle_events (vulkan);
|
|
|
|
if ((vulkan->active == false) || (vulkan->reconfigure_active == true)) {
|
|
return;
|
|
}
|
|
|
|
if (vulkan->signal [signal_q] == true) {
|
|
vulkan->active = false;
|
|
}
|
|
|
|
vulkan_render_core (vulkan, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
vulkan_create_vertex_buffer (vulkan);
|
|
vulkan_create_index_buffer (vulkan);
|
|
|
|
vulkan_record_command_buffers (vulkan, clear_colour, frame);
|
|
|
|
vulkan_result (vkWaitForFences (vulkan->boolean_device, 1, & vulkan->fence_set_1 [vulkan->frame], VK_TRUE, ~0));
|
|
|
|
vulkan_result (vkAcquireNextImageKHR (vulkan->boolean_device, vulkan->swapchain, ~0, vulkan->semaphore_set_1 [vulkan->frame],
|
|
VK_NULL_HANDLE, & frame));
|
|
/*
|
|
result = vkAcquireNextImageKHR (vulkan->boolean_device, vulkan->swapchain, ~0, vulkan->semaphore_set_1 [vulkan->frame],
|
|
VK_NULL_HANDLE, & frame);
|
|
|
|
print ("vkAcquireNextImageKHR : /5%i/-\n", result);
|
|
|
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
|
vulkan->reconfigure_active = true;
|
|
return;
|
|
}
|
|
*/
|
|
vulkan_result (vkResetFences (vulkan->boolean_device, 1, & vulkan->fence_set_1 [vulkan->frame]));
|
|
|
|
submit_information.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
submit_information.waitSemaphoreCount = 1;
|
|
submit_information.pWaitSemaphores = & vulkan->semaphore_set_1 [vulkan->frame];
|
|
submit_information.pWaitDstStageMask = wait_stages;
|
|
submit_information.commandBufferCount = 1;
|
|
submit_information.pCommandBuffers = & vulkan->command_buffers [vulkan->frame];
|
|
//~submit_information.pCommandBuffers = & vulkan->command_buffers [frame];
|
|
submit_information.signalSemaphoreCount = 1;
|
|
submit_information.pSignalSemaphores = & vulkan->semaphore_set_2 [vulkan->frame];
|
|
|
|
vulkan_result (vkQueueSubmit (vulkan->queue, 1, & submit_information, vulkan->fence_set_1 [vulkan->frame]));
|
|
|
|
present_information.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
present_information.waitSemaphoreCount = 1;
|
|
present_information.pWaitSemaphores = & vulkan->semaphore_set_2 [vulkan->frame];
|
|
present_information.swapchainCount = 1;
|
|
present_information.pSwapchains = swapchain_pointer;
|
|
present_information.pImageIndices = & frame;
|
|
|
|
vulkan_result (vkQueuePresentKHR (vulkan->queue, & present_information));
|
|
/*
|
|
result = vkQueuePresentKHR (vulkan->queue, & present_information);
|
|
|
|
print ("vkQueuePresentKHR : /5%i/-\n", result);
|
|
|
|
if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) {
|
|
vulkan->reconfigure_active = true;
|
|
return;
|
|
}
|
|
*/
|
|
vulkan->frame = (vulkan->frame + 1) % vulkan->image_count;
|
|
|
|
vulkan_result (vkQueueWaitIdle (vulkan->queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan->boolean_device));
|
|
|
|
vkDestroyBuffer (vulkan->boolean_device, vulkan->index_buffer, null);
|
|
vkFreeMemory (vulkan->boolean_device, vulkan->index_memory, null);
|
|
vkDestroyBuffer (vulkan->boolean_device, vulkan->vertex_buffer, null);
|
|
vkFreeMemory (vulkan->boolean_device, vulkan->vertex_memory, null);
|
|
|
|
vulkan->vertex_count = 0;
|
|
vulkan->index_count = 0;
|
|
|
|
vulkan_result (vkQueueWaitIdle (vulkan->queue));
|
|
vulkan_result (vkDeviceWaitIdle (vulkan->boolean_device));
|
|
|
|
clock_gettime (CLOCK_REALTIME, & frame_end);
|
|
|
|
if (vulkan->gameplay_time % (vulkan->gameplay_framerate / 10) == 0) {
|
|
vulkan->frame_time_in_ns = (frame_end.tv_sec - frame_begin.tv_sec) * 1000000000 + frame_end.tv_nsec - frame_begin.tv_nsec;
|
|
|
|
vulkan->framerate = (integer) (1000000000 / vulkan->frame_time_in_ns);
|
|
}
|
|
|
|
if (vulkan->framerate > vulkan->gameplay_framerate) {
|
|
struct timespec wait = { 0, 0 };
|
|
|
|
wait.tv_nsec = 1000000000 / vulkan->gameplay_framerate - vulkan->frame_time_in_ns;
|
|
|
|
while (nanosleep (& wait, null) == -1) continue;
|
|
}
|
|
|
|
++vulkan->global_time;
|
|
|
|
vulkan->global_time = vulkan->global_time % (vulkan->gameplay_framerate * vulkan->animation_framerate);
|
|
vulkan->gameplay_time = vulkan->global_time % (vulkan->gameplay_framerate);
|
|
vulkan->animation_time = vulkan->global_time / (vulkan->gameplay_framerate / vulkan->animation_framerate);
|
|
}
|