math functions and UBO
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
|||||||
LDFLAGS = -lglfw -lvulkan -ldl -lpthread
|
LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lm
|
||||||
|
|
||||||
CFLAGS = -g -pedantic -Wall -Wextra -Wshadow -Wunused-macros
|
CFLAGS = -g -pedantic -Wall -Wextra -Wshadow -Wunused-macros
|
||||||
|
|
||||||
|
328
main.c
328
main.c
@@ -2,32 +2,33 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
#include <GLFW/glfw3native.h>
|
#include <GLFW/glfw3native.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
enum bool {
|
typedef enum bool {
|
||||||
false = 0,
|
false = 0,
|
||||||
true = 1,
|
true = 1,
|
||||||
};
|
} bool;
|
||||||
typedef int bool;
|
|
||||||
|
|
||||||
const uint32_t WIDTH = 800;
|
static const uint32_t WIDTH = 800;
|
||||||
const uint32_t HEIGHT = 600;
|
static const uint32_t HEIGHT = 600;
|
||||||
#define MAX_FRAMES_IN_FLIGHT 2
|
#define MAX_FRAMES_IN_FLIGHT 2
|
||||||
|
|
||||||
const char* VALIDATION_LAYERS[] = { "VK_LAYER_KHRONOS_validation" };
|
static const char* VALIDATION_LAYERS[] = { "VK_LAYER_KHRONOS_validation" };
|
||||||
#define VALIDATION_LAYER_COUNT 1
|
#define VALIDATION_LAYER_COUNT 1
|
||||||
|
|
||||||
const char* DEVICE_EXTENSIONS[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
static const char* DEVICE_EXTENSIONS[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||||
#define DEVICE_EXTENSION_COUNT 1
|
#define DEVICE_EXTENSION_COUNT 1
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
const bool enableValidationLayers = false;
|
static const bool enableValidationLayers = false;
|
||||||
#else
|
#else
|
||||||
const bool enableValidationLayers = true;
|
static const bool enableValidationLayers = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct Vec2 {
|
typedef struct Vec2 {
|
||||||
@@ -41,13 +42,33 @@ typedef struct Vec3 {
|
|||||||
float z;
|
float z;
|
||||||
} Vec3;
|
} Vec3;
|
||||||
|
|
||||||
|
typedef struct Vec4 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
} Vec4;
|
||||||
|
|
||||||
|
typedef struct Mat4 {
|
||||||
|
Vec4 x;
|
||||||
|
Vec4 y;
|
||||||
|
Vec4 z;
|
||||||
|
Vec4 w;
|
||||||
|
} Mat4;
|
||||||
|
|
||||||
|
struct UniformBufferObject {
|
||||||
|
Mat4 model;
|
||||||
|
Mat4 view;
|
||||||
|
Mat4 proj;
|
||||||
|
} UniformBufferObject;
|
||||||
|
|
||||||
typedef struct Vertex {
|
typedef struct Vertex {
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
Vec3 color;
|
Vec3 color;
|
||||||
} Vertex;
|
} Vertex;
|
||||||
|
|
||||||
#define VERTEX_COUNT 4
|
#define VERTEX_COUNT 4
|
||||||
const Vertex vertices[VERTEX_COUNT] = {
|
static const Vertex vertices[VERTEX_COUNT] = {
|
||||||
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||||
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||||
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||||
@@ -55,7 +76,7 @@ const Vertex vertices[VERTEX_COUNT] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define INDEX_COUNT 6
|
#define INDEX_COUNT 6
|
||||||
const uint16_t indices[INDEX_COUNT] = {
|
static const uint16_t indices[INDEX_COUNT] = {
|
||||||
0, 1, 2, 2, 3, 0
|
0, 1, 2, 2, 3, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,6 +95,7 @@ struct VulkanData {
|
|||||||
VkExtent2D swapChainExtent;
|
VkExtent2D swapChainExtent;
|
||||||
VkImageView swapChainImageViews[4];
|
VkImageView swapChainImageViews[4];
|
||||||
int imageCount;
|
int imageCount;
|
||||||
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VkPipeline graphicsPipeline;
|
VkPipeline graphicsPipeline;
|
||||||
@@ -90,6 +112,11 @@ struct VulkanData {
|
|||||||
VkDeviceMemory vertexBufferMemory;
|
VkDeviceMemory vertexBufferMemory;
|
||||||
VkBuffer indexBuffer;
|
VkBuffer indexBuffer;
|
||||||
VkDeviceMemory indexBufferMemory;
|
VkDeviceMemory indexBufferMemory;
|
||||||
|
VkBuffer uniformBuffers[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
VkDeviceMemory uniformBuffersMemory[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
void* uniformBuffersMapped[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
|
VkDescriptorSet descriptorSets[MAX_FRAMES_IN_FLIGHT];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwapChainSupportDetails {
|
struct SwapChainSupportDetails {
|
||||||
@@ -109,6 +136,73 @@ struct QueueFamilyIndices {
|
|||||||
struct Optional transferFamily;
|
struct Optional transferFamily;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Vec3 normalize(Vec3 v) {
|
||||||
|
float size = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
Vec3 result = {
|
||||||
|
v.x / size,
|
||||||
|
v.y / size,
|
||||||
|
v.z / size,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec3 crossProduct(Vec3 a, Vec3 b) {
|
||||||
|
Vec3 result = {
|
||||||
|
a.y * b.z - a.z * b.y,
|
||||||
|
a.z * b.x - a.x * b.z,
|
||||||
|
a.x * b.y - a.y * b.x,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float dotProduct(Vec3 a, Vec3 b) {
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mat4 rotate(float angle, Vec3 v) {
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
float x = v.x, y = v.y, z = v.z;
|
||||||
|
Mat4 result = {
|
||||||
|
{c + x * x * (1. - c), x * y * (1. - c) - z * s, x * z * (1. - c) + y * s, 0.},
|
||||||
|
{x * y * (1. - c) + z * s, c + y * y * (1. - c), y * z * (1. - c) - x * s, 0.},
|
||||||
|
{x * z * (1. - c) - y * s, y * z * (1. - c) + x * s, c + z * z * (1. - c), 0.},
|
||||||
|
{0., 0., 0., 1.}
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mat4 lookAt(Vec3 eye, Vec3 center, Vec3 up) {
|
||||||
|
Vec3 f = {
|
||||||
|
center.x - eye.x,
|
||||||
|
center.y - eye.y,
|
||||||
|
center.z - eye.z,
|
||||||
|
};
|
||||||
|
f = normalize(f);
|
||||||
|
up = normalize(up);
|
||||||
|
Vec3 s = normalize(crossProduct(f, up));
|
||||||
|
Vec3 u = crossProduct(s, f);
|
||||||
|
|
||||||
|
Mat4 mat = {
|
||||||
|
{s.x, u.x, -f.x, 0.},
|
||||||
|
{s.y, u.y, -f.y, 0.},
|
||||||
|
{s.z, u.z, -f.z, 0.},
|
||||||
|
{-dotProduct(s, eye), -dotProduct(u, eye), dotProduct(f, eye), 1.},
|
||||||
|
};
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Mat4 perspective(float angle, float aspectRatio, float near, float far) {
|
||||||
|
float f = cos(angle / 2.) / sin(angle / 2.);
|
||||||
|
Mat4 mat = {
|
||||||
|
{f / aspectRatio, 0., 0., 0.},
|
||||||
|
{0., f, 0., 0.},
|
||||||
|
{0., 0., (far + near)/(near - far), -1.},
|
||||||
|
{0., 0., (2. * far * near)/(near - far), 0.},
|
||||||
|
};
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
static VkVertexInputBindingDescription getBindingDescription() {
|
static VkVertexInputBindingDescription getBindingDescription() {
|
||||||
VkVertexInputBindingDescription bindingDescription = {
|
VkVertexInputBindingDescription bindingDescription = {
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
@@ -141,10 +235,11 @@ GLFWwindow* initWindow(struct VulkanData* data) {
|
|||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSetWindowUserPointer(window, data);
|
glfwSetWindowUserPointer(window, data);
|
||||||
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
|
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
|
||||||
|
GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||||
|
glfwSetCursor(window, cursor);
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INDIRECTION: main->run->initVulkan->createInstance
|
|
||||||
static bool checkValidationLayerSupport() {
|
static bool checkValidationLayerSupport() {
|
||||||
uint32_t layerCount;
|
uint32_t layerCount;
|
||||||
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
|
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
|
||||||
@@ -172,7 +267,6 @@ static bool checkValidationLayerSupport() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INDIRECTION: main->run->initVulkan->createInstance
|
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
||||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||||
@@ -186,7 +280,6 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
|||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INDIRECTION: main->run->initVulkan
|
|
||||||
static void createInstance(struct VulkanData* data) {
|
static void createInstance(struct VulkanData* data) {
|
||||||
if (enableValidationLayers && !checkValidationLayerSupport()) {
|
if (enableValidationLayers && !checkValidationLayerSupport()) {
|
||||||
printf("ERROR: Validation layers requested, but not available\n");
|
printf("ERROR: Validation layers requested, but not available\n");
|
||||||
@@ -272,7 +365,6 @@ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMes
|
|||||||
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
|
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setupDebugMessenger(struct VulkanData* data) {
|
static void setupDebugMessenger(struct VulkanData* data) {
|
||||||
if (!enableValidationLayers) return;
|
if (!enableValidationLayers) return;
|
||||||
|
|
||||||
@@ -290,16 +382,7 @@ static void setupDebugMessenger(struct VulkanData* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void createSurface(struct VulkanData* data, GLFWwindow* window) {
|
static void createSurface(struct VulkanData* data, GLFWwindow* window) {
|
||||||
VkWaylandSurfaceCreateInfoKHR createInfo = {
|
if (glfwCreateWindowSurface(data->instance, window, NULL, &data->surface) != VK_SUCCESS) {
|
||||||
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
|
||||||
.display = glfwGetWaylandDisplay(),
|
|
||||||
.surface = glfwGetWaylandWindow(window),
|
|
||||||
};
|
|
||||||
// if (glfwCreateWindowSurface(data->instance, window, NULL, &surface) != VK_SUCCESS) {
|
|
||||||
// fprintf(stderr, "ERROR: Failed to create window surface\n");
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
if (vkCreateWaylandSurfaceKHR(data->instance, &createInfo, NULL, &data->surface) != VK_SUCCESS) {
|
|
||||||
fprintf(stderr, "ERROR: Failed to create window surface\n");
|
fprintf(stderr, "ERROR: Failed to create window surface\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -318,7 +401,6 @@ static uint32_t clamp(uint32_t value, uint32_t min, uint32_t max) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int checkDeviceExtensionSupport(VkPhysicalDevice device) {
|
static int checkDeviceExtensionSupport(VkPhysicalDevice device) {
|
||||||
uint32_t extensionCount;
|
uint32_t extensionCount;
|
||||||
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
|
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
|
||||||
@@ -785,8 +867,9 @@ static void createGraphicsPipeline(struct VulkanData* data) {
|
|||||||
.rasterizerDiscardEnable = VK_FALSE,
|
.rasterizerDiscardEnable = VK_FALSE,
|
||||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||||
.lineWidth = 1.0f,
|
.lineWidth = 1.0f,
|
||||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
// .cullMode = VK_CULL_MODE_BACK_BIT,
|
||||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
.cullMode = 0,
|
||||||
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
.depthBiasEnable = VK_FALSE,
|
.depthBiasEnable = VK_FALSE,
|
||||||
.depthBiasConstantFactor = 0.0f, // Optional
|
.depthBiasConstantFactor = 0.0f, // Optional
|
||||||
.depthBiasClamp = 0.0f, // Optional
|
.depthBiasClamp = 0.0f, // Optional
|
||||||
@@ -828,8 +911,8 @@ static void createGraphicsPipeline(struct VulkanData* data) {
|
|||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
.setLayoutCount = 0, // Optional
|
.setLayoutCount = 1,
|
||||||
.pSetLayouts = NULL, // Optional
|
.pSetLayouts = &data->descriptorSetLayout,
|
||||||
.pushConstantRangeCount = 0, // Optional
|
.pushConstantRangeCount = 0, // Optional
|
||||||
.pPushConstantRanges = NULL, // Optional
|
.pPushConstantRanges = NULL, // Optional
|
||||||
};
|
};
|
||||||
@@ -1026,6 +1109,7 @@ static void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageInd
|
|||||||
.extent = data->swapChainExtent,
|
.extent = data->swapChainExtent,
|
||||||
};
|
};
|
||||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipelineLayout, 0, 1, &data->descriptorSets[data->currentFrame], 0, NULL);
|
||||||
vkCmdDrawIndexed(commandBuffer, INDEX_COUNT, 1, 0, 0, 0);
|
vkCmdDrawIndexed(commandBuffer, INDEX_COUNT, 1, 0, 0, 0);
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||||
@@ -1060,7 +1144,31 @@ static void recreateSwapChain(struct VulkanData* data, GLFWwindow* window) {
|
|||||||
createFramebuffers(data);
|
createFramebuffers(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawFrame(struct VulkanData* data, GLFWwindow* window) {
|
static void updateUniformBuffer(uint32_t currentImage, struct VulkanData* data, struct timespec* start) {
|
||||||
|
struct timespec end;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &end) != 0) {
|
||||||
|
perror("clock_gettime");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double elapsed = (end.tv_sec - start->tv_sec) + (end.tv_nsec - start->tv_nsec) / 1e9;
|
||||||
|
|
||||||
|
Vec3 v1 = { 2., 2., 2. };
|
||||||
|
Vec3 v2 = { 0., 0., 0. };
|
||||||
|
Vec3 v3 = { 0., 0., 1. };
|
||||||
|
|
||||||
|
struct UniformBufferObject ubo = {
|
||||||
|
.model = rotate(elapsed * M_PI / 2., v3),
|
||||||
|
.view = lookAt(v1, v2, v3),
|
||||||
|
.proj = perspective(M_PI / 4., data->swapChainExtent.width / (float) data->swapChainExtent.height, 0.1, 10.),
|
||||||
|
};
|
||||||
|
|
||||||
|
ubo.proj.y.y *= -1.;
|
||||||
|
memcpy(data->uniformBuffersMapped[currentImage], &ubo, sizeof(ubo));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawFrame(struct VulkanData* data, GLFWwindow* window, struct timespec* start) {
|
||||||
vkWaitForFences(data->device, 1, &data->inFlightFences[data->currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(data->device, 1, &data->inFlightFences[data->currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
|
|
||||||
uint32_t imageIndex;
|
uint32_t imageIndex;
|
||||||
@@ -1081,6 +1189,8 @@ static void drawFrame(struct VulkanData* data, GLFWwindow* window) {
|
|||||||
VkSemaphore waitSemaphores[] = {data->imageAvailableSemaphores[data->currentFrame]};
|
VkSemaphore waitSemaphores[] = {data->imageAvailableSemaphores[data->currentFrame]};
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
VkSemaphore signalSemaphores[] = {data->renderFinishedSemaphores[data->currentFrame]};
|
VkSemaphore signalSemaphores[] = {data->renderFinishedSemaphores[data->currentFrame]};
|
||||||
|
|
||||||
|
updateUniformBuffer(data->currentFrame, data, start);
|
||||||
VkSubmitInfo submitInfo = {
|
VkSubmitInfo submitInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
@@ -1255,33 +1365,126 @@ static void createVertexBuffer(struct VulkanData* data) {
|
|||||||
vkFreeMemory(data->device, stagingBufferMemory, NULL);
|
vkFreeMemory(data->device, stagingBufferMemory, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct VulkanData initVulkan(GLFWwindow* window) {
|
static void createDescriptorSetLayout(struct VulkanData* data) {
|
||||||
struct VulkanData data;
|
VkDescriptorSetLayoutBinding uboLayoutBinding = {
|
||||||
data.currentFrame = 0;
|
.binding = 0,
|
||||||
data.framebufferResized = 0;
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
createInstance(&data);
|
.descriptorCount = 1,
|
||||||
setupDebugMessenger(&data);
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
createSurface(&data, window);
|
.pImmutableSamplers = NULL,
|
||||||
pickPhysicalDevice(&data);
|
};
|
||||||
createLogicalDevice(&data);
|
|
||||||
createSwapChain(&data, window);
|
VkDescriptorSetLayoutCreateInfo layoutInfo = {
|
||||||
createImageViews(&data);
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
createRenderPass(&data);
|
.bindingCount = 1,
|
||||||
createGraphicsPipeline(&data);
|
.pBindings = &uboLayoutBinding,
|
||||||
createFramebuffers(&data);
|
};
|
||||||
createCommandPool(&data);
|
|
||||||
createIndexBuffer(&data);
|
if (vkCreateDescriptorSetLayout(data->device, &layoutInfo, NULL, &data->descriptorSetLayout) != VK_SUCCESS) {
|
||||||
createVertexBuffer(&data);
|
fprintf(stderr, "ERROR: Failed to create descriptor set layout\n");
|
||||||
createCommandBuffers(&data);
|
exit(1);
|
||||||
createSyncObjects(&data);
|
}
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mainLoop(GLFWwindow* window, struct VulkanData* data) {
|
static void createUniformBuffers(struct VulkanData* data) {
|
||||||
|
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &data->uniformBuffers[i], &data->uniformBuffersMemory[i], data);
|
||||||
|
vkMapMemory(data->device, data->uniformBuffersMemory[i], 0, bufferSize, 0, &data->uniformBuffersMapped[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createDescriptorPool(struct VulkanData* data) {
|
||||||
|
VkDescriptorPoolSize poolSize = {
|
||||||
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = MAX_FRAMES_IN_FLIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo poolInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
|
.poolSizeCount = 1,
|
||||||
|
.pPoolSizes = &poolSize,
|
||||||
|
.maxSets = MAX_FRAMES_IN_FLIGHT,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (vkCreateDescriptorPool(data->device, &poolInfo, NULL, &data->descriptorPool) != VK_SUCCESS) {
|
||||||
|
fprintf(stderr, "ERROR: Failed to create descriptor pool\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createDescriptorSets(struct VulkanData* data) {
|
||||||
|
VkDescriptorSetLayout layouts[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
layouts[i] = data->descriptorSetLayout;
|
||||||
|
}
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.descriptorPool = data->descriptorPool,
|
||||||
|
.descriptorSetCount = MAX_FRAMES_IN_FLIGHT,
|
||||||
|
.pSetLayouts = layouts,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vkAllocateDescriptorSets(data->device, &allocInfo, data->descriptorSets) != VK_SUCCESS) {
|
||||||
|
fprintf(stderr, "ERROR: Failed to allocate descriptor sets\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
VkDescriptorBufferInfo bufferInfo = {
|
||||||
|
.buffer = data->uniformBuffers[i],
|
||||||
|
.offset = 0,
|
||||||
|
.range = sizeof(UniformBufferObject),
|
||||||
|
};
|
||||||
|
|
||||||
|
VkWriteDescriptorSet descriptorWrite = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = data->descriptorSets[i],
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.pBufferInfo = &bufferInfo,
|
||||||
|
.pImageInfo = NULL,
|
||||||
|
.pTexelBufferView = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(data->device, 1, &descriptorWrite, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initVulkan(GLFWwindow* window, struct VulkanData* data) {
|
||||||
|
data->currentFrame = 0;
|
||||||
|
data->framebufferResized = 0;
|
||||||
|
createInstance(data);
|
||||||
|
setupDebugMessenger(data);
|
||||||
|
createSurface(data, window);
|
||||||
|
pickPhysicalDevice(data);
|
||||||
|
createLogicalDevice(data);
|
||||||
|
createSwapChain(data, window);
|
||||||
|
createImageViews(data);
|
||||||
|
createRenderPass(data);
|
||||||
|
createDescriptorSetLayout(data);
|
||||||
|
createGraphicsPipeline(data);
|
||||||
|
createFramebuffers(data);
|
||||||
|
createCommandPool(data);
|
||||||
|
createVertexBuffer(data);
|
||||||
|
createIndexBuffer(data);
|
||||||
|
createUniformBuffers(data);
|
||||||
|
createDescriptorPool(data);
|
||||||
|
createDescriptorSets(data);
|
||||||
|
createCommandBuffers(data);
|
||||||
|
createSyncObjects(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mainLoop(GLFWwindow* window, struct VulkanData* data, struct timespec* start) {
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
drawFrame(data, window);
|
drawFrame(data, window, start);
|
||||||
int state = glfwGetKey(window, GLFW_KEY_Q);
|
int state = glfwGetKey(window, GLFW_KEY_Q);
|
||||||
if (state == GLFW_PRESS) {
|
if (state == GLFW_PRESS) {
|
||||||
break;
|
break;
|
||||||
@@ -1293,6 +1496,13 @@ static void mainLoop(GLFWwindow* window, struct VulkanData* data) {
|
|||||||
|
|
||||||
static void cleanup(GLFWwindow* window, struct VulkanData* data) {
|
static void cleanup(GLFWwindow* window, struct VulkanData* data) {
|
||||||
cleanupSwapChain(data);
|
cleanupSwapChain(data);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
vkDestroyBuffer(data->device, data->uniformBuffers[i], NULL);
|
||||||
|
vkFreeMemory(data->device, data->uniformBuffersMemory[i], NULL);
|
||||||
|
}
|
||||||
|
vkDestroyDescriptorPool(data->device, data->descriptorPool, NULL);
|
||||||
|
vkDestroyDescriptorSetLayout(data->device, data->descriptorSetLayout, NULL);
|
||||||
vkDestroyBuffer(data->device, data->vertexBuffer, NULL);
|
vkDestroyBuffer(data->device, data->vertexBuffer, NULL);
|
||||||
vkFreeMemory(data->device, data->vertexBufferMemory, NULL);
|
vkFreeMemory(data->device, data->vertexBufferMemory, NULL);
|
||||||
vkDestroyBuffer(data->device, data->indexBuffer, NULL);
|
vkDestroyBuffer(data->device, data->indexBuffer, NULL);
|
||||||
@@ -1320,9 +1530,15 @@ static void cleanup(GLFWwindow* window, struct VulkanData* data) {
|
|||||||
|
|
||||||
static void run() {
|
static void run() {
|
||||||
struct VulkanData data;
|
struct VulkanData data;
|
||||||
|
printf("INFO: Size of data struct: %ld bytes\n", sizeof(data));
|
||||||
GLFWwindow* window = initWindow(&data);
|
GLFWwindow* window = initWindow(&data);
|
||||||
data = initVulkan(window);
|
initVulkan(window, &data);
|
||||||
mainLoop(window, &data);
|
struct timespec start;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &start) != 0) {
|
||||||
|
perror("clock_gettime");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
mainLoop(window, &data, &start);
|
||||||
cleanup(window, &data);
|
cleanup(window, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,13 @@ layout(location = 1) in vec3 inColor;
|
|||||||
|
|
||||||
layout(location = 0) out vec3 fragColor;
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform UniformBufferObject {
|
||||||
|
mat4 model;
|
||||||
|
mat4 view;
|
||||||
|
mat4 proj;
|
||||||
|
} ubo;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(inPosition, 0.0, 1.0);
|
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
|
||||||
fragColor = inColor;
|
fragColor = inColor;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user