Starting Out
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -50,3 +50,6 @@ modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
**/build
|
||||
**/.cache
|
||||
|
||||
16
evk/evk.h
Normal file
16
evk/evk.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#include "evkTypes.h"
|
||||
|
||||
#include "evkAllocator.h"
|
||||
|
||||
#include "evkInstance.h"
|
||||
#include "evkDevice.h"
|
||||
#include "evkSync.h"
|
||||
#include "evkShader.h"
|
||||
#include "evkSwapChain.h"
|
||||
#include "evkCommand.h"
|
||||
#include "evkPipeline.h"
|
||||
#include "evkImage.h"
|
||||
70
evk/evkAllocator.c
Normal file
70
evk/evkAllocator.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "evkAllocator.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
// PFN_vkAllocationFunction
|
||||
void* evkAllocationFunctionCallback(void* pUserData, size_t allocationSize, size_t allocationAlignment, VkSystemAllocationScope allocationScope)
|
||||
{
|
||||
/* puts("evkAllocationFunctionCallback"); */
|
||||
void* alloc = _aligned_malloc(allocationSize, allocationAlignment);
|
||||
if(alloc == NULL)
|
||||
{
|
||||
puts("Allocation Failed");
|
||||
}
|
||||
return alloc;
|
||||
}
|
||||
|
||||
// PFN_vkReallocationFunction
|
||||
void* evkReallocationFunctionCallback(void* pUserData, void* pOriginal, size_t allocationSize, size_t allocationAlignment, VkSystemAllocationScope allocationScope)
|
||||
{
|
||||
/* puts("evkReallocationFunctionCallback"); */
|
||||
return _aligned_realloc(pOriginal, allocationSize, allocationAlignment);
|
||||
}
|
||||
|
||||
// PFN_vkFreeFucntion
|
||||
void evkFreeFunctionCallback(void* pUserData, void* pMemory)
|
||||
{
|
||||
/* puts("evkFreeFunctionCallback"); */
|
||||
_aligned_free(pMemory);
|
||||
}
|
||||
|
||||
// PFN_vkInternalAllocaitonNotification
|
||||
void evkInternalAllocationCallback(void* pUserData, size_t allocationSize, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
|
||||
{
|
||||
puts("evkInternalAllocationCallback");
|
||||
}
|
||||
|
||||
// PFN_vkInternalFreeNotification
|
||||
void evkInternalFreeCallback(void* pUserData, size_t allocationSize, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
|
||||
{
|
||||
puts("evkInternalFreeCallback");
|
||||
}
|
||||
|
||||
TYPEDATA_GEN(
|
||||
VkAllocationCallbacks,
|
||||
DEFAULT(
|
||||
.pUserData = &(evkAllocationUserData){ 0 }, // EV_INVALID(evkAllocationUserData)
|
||||
.pfnAllocation = evkAllocationFunctionCallback,
|
||||
.pfnReallocation = evkReallocationFunctionCallback,
|
||||
.pfnFree = evkFreeFunctionCallback,
|
||||
.pfnInternalAllocation = evkInternalAllocationCallback,
|
||||
.pfnInternalFree = evkInternalFreeCallback
|
||||
)
|
||||
);
|
||||
|
||||
VkAllocationCallbacks def = {
|
||||
.pUserData = NULL, // EV_INVALID(evkAllocationUserData)
|
||||
.pfnAllocation = evkAllocationFunctionCallback,
|
||||
.pfnReallocation = evkReallocationFunctionCallback,
|
||||
.pfnFree = evkFreeFunctionCallback,
|
||||
.pfnInternalAllocation = evkInternalAllocationCallback,
|
||||
.pfnInternalFree = evkInternalFreeCallback
|
||||
};
|
||||
|
||||
VkAllocationCallbacks* evkGetAllocationCallbacks()
|
||||
{
|
||||
/* return &EV_DEFAULT(VkAllocationCallbacks); */
|
||||
/* return &def; */
|
||||
return NULL;
|
||||
}
|
||||
6
evk/evkAllocator.h
Normal file
6
evk/evkAllocator.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
VkAllocationCallbacks* evkGetAllocationCallbacks();
|
||||
|
||||
29
evk/evkBuffer.c
Normal file
29
evk/evkBuffer.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "evkImage.h"
|
||||
#include "evk/evkMemory.h"
|
||||
|
||||
evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo)
|
||||
{
|
||||
VkBufferCreateInfo bufferCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = createInfo.flags,
|
||||
.usage = createInfo.usage,
|
||||
.sharingMode = createInfo.exclusive?VK_SHARING_MODE_EXCLUSIVE:VK_SHARING_MODE_CONCURRENT,
|
||||
.queueFamilyIndexCount = vec_len(&createInfo.queueFamilyIndices),
|
||||
.pQueueFamilyIndices = createInfo.queueFamilyIndices,
|
||||
};
|
||||
|
||||
evkBuffer buffer = evkGPUCreateBuffer(createInfo.allocationCreateInfo, &bufferCreateInfo);
|
||||
|
||||
if(buffer.vk != VK_NULL_HANDLE)
|
||||
{
|
||||
buffer.sizeInBytes = createInfo.sizeInBytes;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void evkDestroyBuffer(evkBuffer buf)
|
||||
{
|
||||
evkGPUDestroyBuffer(buf);
|
||||
}
|
||||
6
evk/evkBuffer.h
Normal file
6
evk/evkBuffer.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
evkBuffer evkCreateBuffer(evkBufferCreateInfo createInfo);
|
||||
void evkDestroyBuffer(evkBuffer buf);
|
||||
51
evk/evkCommand.c
Normal file
51
evk/evkCommand.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "evkCommand.h"
|
||||
|
||||
evkCommandPool evkCreateCommandPool(evkCommandPoolCreateInfo createInfo)
|
||||
{
|
||||
evkCommandPool commandPool;
|
||||
commandPool.queueFamily = createInfo.device.queueFamilies[createInfo.queueFlags];
|
||||
|
||||
VkCommandPoolCreateInfo vkCreateInfo = (VkCommandPoolCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = createInfo.poolFlags,
|
||||
.queueFamilyIndex = commandPool.queueFamily.familyIndex,
|
||||
};
|
||||
|
||||
vkCreateCommandPool(createInfo.device.vk, &vkCreateInfo, NULL, &commandPool.vk);
|
||||
return commandPool;
|
||||
}
|
||||
|
||||
void evkDestroyCommandPool(evkDevice device, evkCommandPool commandPool)
|
||||
{
|
||||
vkDestroyCommandPool(device.vk, commandPool.vk, NULL);
|
||||
}
|
||||
|
||||
vec(VkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary)
|
||||
{
|
||||
vec(VkCommandBuffer) buffers = vec_init(VkCommandBuffer);
|
||||
vec_setlen(&buffers, count);
|
||||
|
||||
VkCommandBufferAllocateInfo allocateInfo = (VkCommandBufferAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = commandPool.vk,
|
||||
.commandBufferCount = count,
|
||||
.level = primary?VK_COMMAND_BUFFER_LEVEL_PRIMARY:VK_COMMAND_BUFFER_LEVEL_SECONDARY,
|
||||
};
|
||||
|
||||
vkAllocateCommandBuffers(device.vk, &allocateInfo, buffers);
|
||||
|
||||
return buffers;
|
||||
}
|
||||
|
||||
void evkBeginPrimaryCommandBuffer(VkCommandBuffer cmdBuf)
|
||||
{
|
||||
VkCommandBufferBeginInfo beginInfo = (VkCommandBufferBeginInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
};
|
||||
vkBeginCommandBuffer(cmdBuf, &beginInfo);
|
||||
}
|
||||
|
||||
void evkEndCommandBuffer(VkCommandBuffer cmdBuf)
|
||||
{
|
||||
vkEndCommandBuffer(cmdBuf);
|
||||
}
|
||||
15
evk/evkCommand.h
Normal file
15
evk/evkCommand.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "evk.h"
|
||||
#include "evkDevice.h"
|
||||
|
||||
|
||||
[[nodiscard("Leaking VkCommandPool")]]
|
||||
evkCommandPool evkCreateCommandPool(evkCommandPoolCreateInfo createInfo);
|
||||
void evkDestroyCommandPool(evkDevice device, evkCommandPool commandPool);
|
||||
|
||||
[[nodiscard("Leaking allocated CommandBuffers")]]
|
||||
vec(VkCommandBuffer) evkAllocateCommandBuffers(evkDevice device, evkCommandPool commandPool, u32 count, bool primary);
|
||||
|
||||
void evkBeginPrimaryCommandBuffer(VkCommandBuffer cmdBuf);
|
||||
void evkEndCommandBuffer(VkCommandBuffer cmdBuf);
|
||||
13
evk/evkCommon.h
Normal file
13
evk/evkCommon.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "evk_buildconfig.h"
|
||||
#include <volk.h>
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
#include <ev_numeric.h>
|
||||
#include <ev_str.h>
|
||||
|
||||
#define EV_VEC_SHORTNAMES
|
||||
#include <ev_vec.h>
|
||||
|
||||
#include "evkTypes.h"
|
||||
43
evk/evkDescriptor.c
Normal file
43
evk/evkDescriptor.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkDescriptor.h"
|
||||
|
||||
typedef struct {
|
||||
VkDescriptorSetLayout descriptorSetLayouts[4];
|
||||
} evkSetLayout;
|
||||
|
||||
evkSetLayout evkCreateDescriptorSetLayouts(vec(evkShader) shaders)
|
||||
{
|
||||
VkDescriptorSetLayoutCreateInfo createInfos[4];
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
createInfos[i] = EV_DEFAULT(
|
||||
VkDescriptorSetLayoutCreateInfo,
|
||||
pBindings = vec_init(VkDescriptorSetLayoutBinding)
|
||||
);
|
||||
}
|
||||
|
||||
for(int i = 0; i < vec_len(&shaders); i++)
|
||||
{
|
||||
vec(evkDescriptorBinding) bindings = shaders[i].reflect.bindings;
|
||||
for(int bi = 0; bi < vec_len(&bindings); bi++)
|
||||
{
|
||||
evkDescriptorBinding b = bindings[bi];
|
||||
if(b.binding >= vec_len(&createInfos[b.set].pBindings))
|
||||
{
|
||||
u32 old_len = vec_len(&createInfos[b.set].pBindings);
|
||||
vec_setlen(&createInfos[b.set].pBindings, b.binding+1);
|
||||
for(int cs = old_len; cs < b.binding+1; cs++)
|
||||
{
|
||||
/* createInfos[b.set].pBindings[cs].binding */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
createInfos[i].bindingCount = vec_len(&createInfos[i].pBindings);
|
||||
}
|
||||
}
|
||||
5
evk/evkDescriptor.h
Normal file
5
evk/evkDescriptor.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
// void evkFillSetLayoutCreateInfos(vec(evkShader) shaders, VkDescriptorSetLayoutCreateInfo layoutCreateInfos[4]);
|
||||
176
evk/evkDevice.c
Normal file
176
evk/evkDevice.c
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "evkDevice.h"
|
||||
#include "evkTypes.h"
|
||||
#include "evkAllocator.h"
|
||||
|
||||
evstring VkDynamicRenderingExtName = evstr("VK_KHR_dynamic_rendering");
|
||||
evstring VkSync2ExtName = evstr("VK_KHR_synchronization2");
|
||||
|
||||
VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeature = (VkPhysicalDeviceDynamicRenderingFeaturesKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR,
|
||||
.dynamicRendering = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceSynchronization2Features sync2Features = (VkPhysicalDeviceSynchronization2Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES,
|
||||
.synchronization2 = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDevice evkDetectPhysicalDevice(evkInstance instance, VkPhysicalDeviceType deviceType)
|
||||
{
|
||||
VkPhysicalDevice chosenDevice = EV_INVALID(VkPhysicalDevice);
|
||||
u32 deviceCount = 0;
|
||||
|
||||
vec(VkPhysicalDevice) physicalDevices = vec_init(VkPhysicalDevice);
|
||||
vkEnumeratePhysicalDevices(instance.vk, &deviceCount, NULL);
|
||||
vec_setlen(&physicalDevices, deviceCount);
|
||||
vkEnumeratePhysicalDevices(instance.vk, &deviceCount, physicalDevices);
|
||||
|
||||
// TODO Add a more robust/flexible way to pick a GPU
|
||||
for(u32 i = 0; i < deviceCount; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(physicalDevices[i], &deviceProperties);
|
||||
if(deviceProperties.deviceType == deviceType)
|
||||
{
|
||||
chosenDevice = physicalDevices[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec_fini(&physicalDevices);
|
||||
|
||||
return chosenDevice;
|
||||
}
|
||||
|
||||
evkDevice evkCreateDevice(evkDeviceCreateInfo createInfo)
|
||||
{
|
||||
evkDevice device;
|
||||
device._physicalDevice = evkDetectPhysicalDevice(createInfo.instance, createInfo.physicalDeviceType);
|
||||
device._instance = createInfo.instance;
|
||||
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||
vkGetPhysicalDeviceProperties(device._physicalDevice, &physicalDeviceProperties);
|
||||
device.limits = physicalDeviceProperties.limits;
|
||||
|
||||
for (u32 i = 0; i < MAX_QUEUE_FAMILIES; i++) {
|
||||
device.queueFamilies[i] = (evkDeviceQueueFamily){
|
||||
.familyIndex = -1,
|
||||
.allocatedQueueCount = 0
|
||||
};
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo vkDeviceCreateInfo = __EV_VEC_EMPTY_ARRAY;
|
||||
vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
void** pNext = &vkDeviceCreateInfo.pNext;
|
||||
|
||||
if(ev_vec_find(&createInfo.deviceExtensions, &VkDynamicRenderingExtName) != -1)
|
||||
{
|
||||
*pNext = &dynamicRenderingFeature;
|
||||
pNext = &dynamicRenderingFeature.pNext;
|
||||
}
|
||||
|
||||
if(ev_vec_find(&createInfo.deviceExtensions, &VkSync2ExtName) != -1)
|
||||
{
|
||||
*pNext = &sync2Features;
|
||||
pNext = &sync2Features.pNext;
|
||||
}
|
||||
|
||||
vkDeviceCreateInfo.enabledExtensionCount = vec_len(&createInfo.deviceExtensions);
|
||||
vkDeviceCreateInfo.ppEnabledExtensionNames = createInfo.deviceExtensions;
|
||||
|
||||
// Getting the total number of queues requested from the device
|
||||
u32 totalQueueCount = 0;
|
||||
for (u32 i = 0; i < vec_len(&createInfo.queueRequirements); i++) {
|
||||
totalQueueCount += createInfo.queueRequirements[i].count;
|
||||
}
|
||||
|
||||
const f32 DEFAULT_PRIORITY = 1.0f;
|
||||
// A priorities list that can be passed with any VkQueueCreteInfo (doable since we have no custom priorities)
|
||||
vec(f32) priorities = vec_init(f32);
|
||||
vec_setlen(&priorities, totalQueueCount);
|
||||
for (u32 i = 0; i < totalQueueCount; i++) {
|
||||
priorities[i] = DEFAULT_PRIORITY;
|
||||
}
|
||||
|
||||
vec(VkDeviceQueueCreateInfo) queueCreateInfoList = vec_init(VkDeviceQueueCreateInfo);
|
||||
if (createInfo.queueRequirements) {
|
||||
// Retrieving the queue family properties into a vector
|
||||
u32 queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device._physicalDevice, &queueFamilyCount, NULL);
|
||||
vec(VkQueueFamilyProperties) queueFamilyProperties = vec_init(VkQueueFamilyProperties);
|
||||
vec_setlen(&queueFamilyProperties, queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device._physicalDevice, &queueFamilyCount, queueFamilyProperties);
|
||||
|
||||
// Creating VkDeviceQueueCreateInfos from requirements and family properties
|
||||
// NOTICE: Currently, there can be no queues of a specific type in 2 different
|
||||
// families. While that can be considered a limitation, the application targeted
|
||||
// by this abstraction aren't expected to be complex enough to need it.
|
||||
for (u32 familyIndex = 0; familyIndex < queueFamilyCount; familyIndex++) {
|
||||
VkQueueFamilyProperties currentFamilyProperties = queueFamilyProperties[familyIndex];
|
||||
u32 availableQueuesInFamily = currentFamilyProperties.queueCount;
|
||||
|
||||
for (u32 reqIndex = 0; reqIndex < vec_len(&createInfo.queueRequirements); reqIndex++) {
|
||||
evkDeviceQueueRequirement currentRequirement = createInfo.queueRequirements[reqIndex];
|
||||
|
||||
// Testing compatibility of queue family and requirement
|
||||
if (currentRequirement.flags & currentFamilyProperties.queueFlags) {
|
||||
|
||||
u32 requiredCount = currentRequirement.count;
|
||||
while (availableQueuesInFamily > 0 && requiredCount > 0) {
|
||||
// If the queue family is not already in the vector, push it.
|
||||
if (vec_len(&queueCreateInfoList) <= familyIndex) {
|
||||
VkDeviceQueueCreateInfo newQueueCreateInfo = { 0 };
|
||||
newQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
newQueueCreateInfo.queueFamilyIndex = familyIndex;
|
||||
newQueueCreateInfo.pQueuePriorities = priorities;
|
||||
vec_push(&queueCreateInfoList, &newQueueCreateInfo);
|
||||
}
|
||||
|
||||
u32 allocationCount = (availableQueuesInFamily>requiredCount)?requiredCount:availableQueuesInFamily;
|
||||
queueCreateInfoList[familyIndex].queueCount += allocationCount;
|
||||
device.queueFamilies[currentRequirement.flags].familyIndex = familyIndex;
|
||||
device.queueFamilies[currentRequirement.flags].allocatedQueueCount += allocationCount;
|
||||
|
||||
// Allowing retrieval of families according to their actual flags
|
||||
device.queueFamilies[currentFamilyProperties.queueFlags].familyIndex = familyIndex;
|
||||
device.queueFamilies[currentFamilyProperties.queueFlags].allocatedQueueCount += allocationCount;
|
||||
|
||||
// Updating the loop condition variables
|
||||
availableQueuesInFamily -= allocationCount;
|
||||
requiredCount -= allocationCount;
|
||||
}
|
||||
// Updating the requirement's count after allocation
|
||||
createInfo.queueRequirements[reqIndex].count = requiredCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vkDeviceCreateInfo.pQueueCreateInfos = queueCreateInfoList;
|
||||
vkDeviceCreateInfo.queueCreateInfoCount = (u32)vec_len(&queueCreateInfoList);
|
||||
|
||||
vec_fini(&queueFamilyProperties);
|
||||
}
|
||||
|
||||
// Allowing the retrieval of non-requested, but allocated, queues is possible.
|
||||
// Example: Allocating COMPUTE | GRAPHICS then requesting GRAPHICS should
|
||||
// return the already allocated queue
|
||||
for (i32 i = MAX_QUEUE_FAMILIES - 1; i >= 0; i--) {
|
||||
for (i32 j = i - 1; j >= 0; j--) {
|
||||
if (device.queueFamilies[j].familyIndex == -1 && (i & j) == j) {
|
||||
device.queueFamilies[j] = device.queueFamilies[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vkCreateDevice(device._physicalDevice, &vkDeviceCreateInfo, evkGetAllocationCallbacks(), &device.vk);
|
||||
|
||||
vec_fini(&queueCreateInfoList);
|
||||
vec_fini(&priorities);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void evkDestroyDevice(evkDevice device)
|
||||
{
|
||||
vkDestroyDevice(device.vk, evkGetAllocationCallbacks());
|
||||
}
|
||||
9
evk/evkDevice.h
Normal file
9
evk/evkDevice.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
VkPhysicalDevice evkDetectPhysicalDevice(evkInstance instance, VkPhysicalDeviceType deviceType);
|
||||
|
||||
[[nodiscard("Leaking VkDevice")]]
|
||||
evkDevice evkCreateDevice(evkDeviceCreateInfo createInfo);
|
||||
void evkDestroyDevice(evkDevice device);
|
||||
67
evk/evkImage.c
Normal file
67
evk/evkImage.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "evkImage.h"
|
||||
#include "evk/evkMemory.h"
|
||||
|
||||
void evkDestroyImage(evkDevice device, evkImage img)
|
||||
{
|
||||
evkGPUDestroyImage(img);
|
||||
}
|
||||
|
||||
evkImageView evkCreateImageView(evkDevice device, evkImage img, evkImageViewCreateInfo createInfo)
|
||||
{
|
||||
evkImageView imgView;
|
||||
VkImageViewCreateInfo imageViewCreateInfo = (VkImageViewCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = img.vk,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D, // TODO Get from evkImage or allow overriding?
|
||||
.format = img.format,
|
||||
.components = {0,0,0,0}, // No swizzling use cases yet.
|
||||
.subresourceRange = {
|
||||
.aspectMask = createInfo.viewAspect,
|
||||
.baseMipLevel = createInfo.mipBase,
|
||||
.levelCount = createInfo.mipCount,
|
||||
.baseArrayLayer = createInfo.baseLayer,
|
||||
.layerCount = createInfo.layerCount,
|
||||
}
|
||||
};
|
||||
|
||||
vkCreateImageView(device.vk, &imageViewCreateInfo, NULL, &imgView.vk);
|
||||
return imgView;
|
||||
}
|
||||
|
||||
void evkDestroyImageView(evkDevice device, evkImageView imgv)
|
||||
{
|
||||
vkDestroyImageView(device.vk, imgv.vk, NULL);
|
||||
}
|
||||
|
||||
evkImage evkCreateImage(evkImageCreateInfo createInfo)
|
||||
{
|
||||
VkImageCreateInfo vkImageCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.flags = createInfo.flags,
|
||||
.imageType = createInfo.type,
|
||||
.format = createInfo.format,
|
||||
.extent = createInfo.extent,
|
||||
.mipLevels = createInfo.mipCount,
|
||||
.arrayLayers = createInfo.layerCount,
|
||||
.samples = createInfo.sampleCount,
|
||||
.tiling = createInfo.tiling,
|
||||
.usage = createInfo.usage,
|
||||
.sharingMode = createInfo.exclusive?VK_SHARING_MODE_EXCLUSIVE:VK_SHARING_MODE_CONCURRENT,
|
||||
.initialLayout = createInfo.layout,
|
||||
};
|
||||
if(!createInfo.exclusive)
|
||||
{
|
||||
vkImageCreateInfo.queueFamilyIndexCount = vec_len(&createInfo.queueFamilyIndices);
|
||||
vkImageCreateInfo.pQueueFamilyIndices = createInfo.queueFamilyIndices;
|
||||
}
|
||||
|
||||
evkImage img = evkGPUCreateImage(createInfo.allocationCreateInfo, &vkImageCreateInfo);
|
||||
if(img.vk != VK_NULL_HANDLE)
|
||||
{
|
||||
img.format = createInfo.format;
|
||||
img.width = createInfo.extent.width;
|
||||
img.height = createInfo.extent.height;
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
8
evk/evkImage.h
Normal file
8
evk/evkImage.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
evkImageView evkCreateImageView(evkDevice device, evkImage img, evkImageViewCreateInfo createInfo);
|
||||
void evkDestroyImageView(evkDevice device, evkImageView imgv);
|
||||
|
||||
void evkDestroyImage(evkDevice device, evkImage img);
|
||||
43
evk/evkInstance.c
Normal file
43
evk/evkInstance.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "evkInstance.h"
|
||||
|
||||
evkInstance evkCreateInstance(evkInstanceCreateInfo instanceCreateInfo)
|
||||
{
|
||||
evkInstance res = EV_INVALID(evkInstance);
|
||||
if(volkInitialize() != VK_SUCCESS)
|
||||
return res;
|
||||
|
||||
VkApplicationInfo vkAppInfo = __EV_VEC_EMPTY_ARRAY;
|
||||
vkAppInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
vkAppInfo.pNext = 0;
|
||||
vkAppInfo.pEngineName = instanceCreateInfo.applicationInfo.engineName;
|
||||
vkAppInfo.pApplicationName = instanceCreateInfo.applicationInfo.applicationName;
|
||||
vkAppInfo.engineVersion = instanceCreateInfo.applicationInfo.engineVersion;
|
||||
vkAppInfo.applicationVersion = instanceCreateInfo.applicationInfo.applicationVersion;
|
||||
vkAppInfo.apiVersion = instanceCreateInfo.applicationInfo.apiVersion;
|
||||
|
||||
VkInstanceCreateInfo vkInstanceCreateInfo = __EV_VEC_EMPTY_ARRAY;
|
||||
vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
vkInstanceCreateInfo.pApplicationInfo = &vkAppInfo;
|
||||
vkInstanceCreateInfo.enabledLayerCount = (u32)vec_len(&instanceCreateInfo.layers);
|
||||
vkInstanceCreateInfo.ppEnabledLayerNames = instanceCreateInfo.layers;
|
||||
vkInstanceCreateInfo.enabledExtensionCount = (u32)vec_len(&instanceCreateInfo.extensions);
|
||||
vkInstanceCreateInfo.ppEnabledExtensionNames = instanceCreateInfo.extensions;
|
||||
|
||||
VkResult instanceCreationResult = vkCreateInstance(&vkInstanceCreateInfo, NULL, &res.vk);
|
||||
/* VkResult instanceCreationResult = vkCreateInstance(&vkInstanceCreateInfo, evkGetAllocationCallbacks(), &res); */
|
||||
/* printf("InstanceCreationResult: %d\n", instanceCreationResult); */
|
||||
|
||||
if(instanceCreationResult == VK_SUCCESS)
|
||||
{
|
||||
volkLoadInstance(res.vk);
|
||||
res.apiVersion = vkAppInfo.apiVersion;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void evkDestroyInstance(evkInstance instance)
|
||||
{
|
||||
vkDestroyInstance(instance.vk, NULL);
|
||||
/* vkDestroyInstance(vkInstance, evkGetAllocationCallbacks()); */
|
||||
}
|
||||
7
evk/evkInstance.h
Normal file
7
evk/evkInstance.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "evk.h"
|
||||
|
||||
[[nodiscard("Leaking VkInstance")]]
|
||||
evkInstance evkCreateInstance(evkInstanceCreateInfo);
|
||||
void evkDestroyInstance(evkInstance);
|
||||
84
evk/evkMemory.c
Normal file
84
evk/evkMemory.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkMemory.h"
|
||||
|
||||
evkGPUAllocator evkGPUCreateAllocator(evkDevice device)
|
||||
{
|
||||
VmaVulkanFunctions vmaFunctions = {
|
||||
.vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties,
|
||||
.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties,
|
||||
.vkAllocateMemory = vkAllocateMemory,
|
||||
.vkFreeMemory = vkFreeMemory,
|
||||
.vkMapMemory = vkMapMemory,
|
||||
.vkUnmapMemory = vkUnmapMemory,
|
||||
.vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges,
|
||||
.vkInvalidateMappedMemoryRanges = vkInvalidateMappedMemoryRanges,
|
||||
.vkBindBufferMemory = vkBindBufferMemory,
|
||||
.vkBindImageMemory = vkBindImageMemory,
|
||||
.vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements,
|
||||
.vkGetImageMemoryRequirements = vkGetImageMemoryRequirements,
|
||||
.vkCreateBuffer = vkCreateBuffer,
|
||||
.vkDestroyBuffer = vkDestroyBuffer,
|
||||
.vkCreateImage = vkCreateImage,
|
||||
.vkDestroyImage = vkDestroyImage,
|
||||
.vkCmdCopyBuffer = vkCmdCopyBuffer,
|
||||
};
|
||||
|
||||
VmaAllocatorCreateInfo createInfo = {
|
||||
.physicalDevice = device._physicalDevice,
|
||||
.device = device.vk,
|
||||
.instance = device._instance.vk,
|
||||
.vulkanApiVersion = device._instance.apiVersion,
|
||||
.pVulkanFunctions = &vmaFunctions,
|
||||
};
|
||||
|
||||
evkGPUAllocator alloc;
|
||||
vmaCreateAllocator(&createInfo, &alloc.vma);
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void evkGPUDestroyAllocator(evkGPUAllocator alloc)
|
||||
{
|
||||
vmaDestroyAllocator(alloc.vma);
|
||||
}
|
||||
|
||||
evkImage evkGPUCreateImage(evkGPUAllocationCreateInfo allocationCreateInfo, VkImageCreateInfo* imageCreateInfo)
|
||||
{
|
||||
evkImage img;
|
||||
|
||||
VmaAllocationCreateInfo vmaAllocCreateInfo = {
|
||||
.usage = allocationCreateInfo.memoryUsage,
|
||||
.flags = allocationCreateInfo.allocationFlags,
|
||||
.pool = allocationCreateInfo.pool.vma,
|
||||
};
|
||||
|
||||
vmaCreateImage(allocationCreateInfo.allocator.vma, imageCreateInfo, &vmaAllocCreateInfo, &img.vk, &img.allocData.allocation.vma, &img.allocData.allocationInfo.vma);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void evkGPUDestroyImage(evkImage img)
|
||||
{
|
||||
vmaDestroyImage(img.allocData.allocator.vma, img.vk, img.allocData.allocation.vma);
|
||||
}
|
||||
|
||||
evkBuffer evkGPUCreateBuffer(evkGPUAllocationCreateInfo allocationCreateInfo, VkBufferCreateInfo* imageCreateInfo)
|
||||
{
|
||||
evkBuffer buf;
|
||||
|
||||
VmaAllocationCreateInfo vmaAllocCreateInfo = {
|
||||
.usage = allocationCreateInfo.memoryUsage,
|
||||
.flags = allocationCreateInfo.allocationFlags,
|
||||
.pool = allocationCreateInfo.pool.vma,
|
||||
};
|
||||
|
||||
vmaCreateBuffer(allocationCreateInfo.allocator.vma, imageCreateInfo, &vmaAllocCreateInfo, &buf.vk, &buf.allocData.allocation.vma, &buf.allocData.allocationInfo.vma);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void evkGPUDestroyBuffer(evkBuffer buf)
|
||||
{
|
||||
vmaDestroyBuffer(buf.allocData.allocator.vma, buf.vk, buf.allocData.allocation.vma);
|
||||
}
|
||||
12
evk/evkMemory.h
Normal file
12
evk/evkMemory.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
evkImage evkGPUCreateImage(evkGPUAllocationCreateInfo, VkImageCreateInfo*);
|
||||
void evkGPUDestroyImage(evkImage);
|
||||
|
||||
evkBuffer evkGPUCreateBuffer(evkGPUAllocationCreateInfo, VkBufferCreateInfo*);
|
||||
void evkGPUDestroyBuffer(evkBuffer);
|
||||
|
||||
evkGPUAllocator evkGPUCreateAllocator(evkDevice device);
|
||||
void evkGPUDestroyAllocator(evkGPUAllocator alloc);
|
||||
163
evk/evkPipeline.c
Normal file
163
evk/evkPipeline.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "evkPipeline.h"
|
||||
|
||||
#include "evk/evkTypes.h"
|
||||
#include "evkShader.h"
|
||||
|
||||
const u32 DESCRIPTOR_SET_LAYOUT_COUNT = 4;
|
||||
|
||||
evkPipelineLayout evkCreatePipelineLayout(evkDevice device, evkPipelineLayoutCreateInfo createInfo)
|
||||
{
|
||||
evkPipelineLayout layout;
|
||||
|
||||
VkPipelineLayoutCreateInfo vkCreateInfo = (VkPipelineLayoutCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
};
|
||||
|
||||
vkCreatePipelineLayout(device.vk, &vkCreateInfo, NULL, &layout.vk);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void evkDestroyPipelineLayout(evkDevice device, evkPipelineLayout layout)
|
||||
{
|
||||
vkDestroyPipelineLayout(device.vk, layout.vk, NULL);
|
||||
}
|
||||
|
||||
|
||||
evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo)
|
||||
{
|
||||
u32 shaderStageCount = vec_len(&createInfo.shaderStages);
|
||||
u32 colorAttachmentCount = vec_len(&createInfo.colorAttachments);
|
||||
u32 dynamicStateCount = vec_len(&createInfo.dynamicStates);
|
||||
|
||||
evkPipeline res;
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.dynamicStateCount = dynamicStateCount,
|
||||
.pDynamicStates = createInfo.dynamicStates,
|
||||
};
|
||||
|
||||
VkFormat colorAttachmentFormats[colorAttachmentCount];
|
||||
for(int i = 0; i < colorAttachmentCount; i++)
|
||||
colorAttachmentFormats[i] = createInfo.colorAttachments[i].format;
|
||||
|
||||
VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
|
||||
.colorAttachmentCount = colorAttachmentCount,
|
||||
.pColorAttachmentFormats = colorAttachmentFormats,
|
||||
.depthAttachmentFormat = createInfo.depthAttachmentFormat,
|
||||
.stencilAttachmentFormat = createInfo.stencilAttachmentFormat,
|
||||
.viewMask = createInfo.viewMask,
|
||||
};
|
||||
|
||||
VkPipelineColorBlendAttachmentState colorAttachmentBlendStates[colorAttachmentCount];
|
||||
for(int i = 0; i < colorAttachmentCount; i++)
|
||||
colorAttachmentBlendStates[i] = createInfo.colorAttachments[i].blendState;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlending = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0, // Update if VK_EXT_rasterization_order_attachment_access is supported
|
||||
.logicOpEnable = createInfo.blendingOp != VK_LOGIC_OP_NO_OP,
|
||||
.logicOp = createInfo.blendingOp,
|
||||
|
||||
.attachmentCount = colorAttachmentCount,
|
||||
.pAttachments = colorAttachmentBlendStates,
|
||||
};
|
||||
memcpy(colorBlending.blendConstants, createInfo.blendConstants, sizeof(f32) * 4);
|
||||
|
||||
u32 viewportCount = createInfo.viewportCountOverride;
|
||||
if(viewportCount == 0 && createInfo.viewports)
|
||||
viewportCount = vec_len(&createInfo.viewports);
|
||||
|
||||
VkViewport viewports[viewportCount];
|
||||
VkRect2D scissors[viewportCount];
|
||||
|
||||
if(createInfo.viewports)
|
||||
{
|
||||
for(int i = 0; i < viewportCount; i++)
|
||||
{
|
||||
viewports[i] = createInfo.viewports[i].vkViewport;
|
||||
|
||||
VkRect2D currScis = createInfo.viewports[i].vkScissor;
|
||||
scissors[i].offset.x = max(currScis.offset.x, viewports[i].x);
|
||||
scissors[i].offset.y = max(currScis.offset.y, viewports[i].y);
|
||||
scissors[i].extent.width = currScis.extent.width == 0? viewports[i].width : currScis.extent.width;
|
||||
scissors[i].extent.height = currScis.extent.height == 0? viewports[i].height : currScis.extent.height;
|
||||
}
|
||||
}
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = viewportCount,
|
||||
.scissorCount = viewportCount,
|
||||
.pViewports = viewports,
|
||||
.pScissors = scissors,
|
||||
};
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStageCreateInfos[shaderStageCount];
|
||||
for(int i = 0; i < vec_len(&createInfo.shaderStages); i++)
|
||||
shaderStageCreateInfos[i] = evkGetShaderStageCreateInfo(createInfo.shaderStages[i]);
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 0,
|
||||
.vertexAttributeDescriptionCount = 0,
|
||||
};
|
||||
|
||||
/* VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfos[DESCRIPTOR_SET_LAYOUT_COUNT] = {}; */
|
||||
|
||||
/* for(u32 di = 0; di < DESCRIPTOR_SET_LAYOUT_COUNT; di++) */
|
||||
/* { */
|
||||
/* descriptorSetLayoutCreateInfos[di].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; */
|
||||
/* for(u32 si = 0; si < vec_len(&createInfo.shaderStages); si++) */
|
||||
/* { */
|
||||
/**/
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfos[4];
|
||||
|
||||
svec(VkDescriptorSetLayout) descriptorSetLayouts = svec_init_w_len(VkDescriptorSetLayout, 4);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
VkDescriptorSetLayoutCreateInfo dsCreateInfo = {};
|
||||
|
||||
// Fill descriptorSetLayoutCreateInfos[i] from shader reflection data + Create descriptorSetLayouts[i]
|
||||
}
|
||||
|
||||
res.layout = evkCreatePipelineLayout(device,
|
||||
EV_DEFAULT(evkPipelineLayoutCreateInfo,
|
||||
descriptorSetLayouts = descriptorSetLayouts
|
||||
)
|
||||
);
|
||||
|
||||
VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &pipelineRenderingCreateInfo,
|
||||
.stageCount = shaderStageCount,
|
||||
.pStages = shaderStageCreateInfos,
|
||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||
.pInputAssemblyState = &EV_DEFAULT(VkPipelineInputAssemblyStateCreateInfo),
|
||||
.pViewportState = &viewportStateCreateInfo,
|
||||
.pRasterizationState = &EV_DEFAULT(VkPipelineRasterizationStateCreateInfo),
|
||||
.pMultisampleState = &EV_DEFAULT(VkPipelineMultisampleStateCreateInfo),
|
||||
.pColorBlendState = &colorBlending,
|
||||
.pDynamicState = &dynamicStateCreateInfo,
|
||||
.layout = res.layout.vk,
|
||||
};
|
||||
|
||||
vkCreateGraphicsPipelines(device.vk, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, NULL, &res.vk);
|
||||
|
||||
res._device = device;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void evkDestroyPipeline(evkPipeline pipeline)
|
||||
{
|
||||
vkDestroyPipeline(pipeline._device.vk, pipeline.vk, NULL);
|
||||
evkDestroyPipelineLayout(pipeline._device, pipeline.layout);
|
||||
}
|
||||
10
evk/evkPipeline.h
Normal file
10
evk/evkPipeline.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
[[nodiscard("Leaking VkPipelineLayout")]]
|
||||
evkPipelineLayout evkCreatePipelineLayout(evkDevice device, evkPipelineLayoutCreateInfo createInfo);
|
||||
void evkDestroyPipelineLayout(evkDevice device, evkPipelineLayout layout);
|
||||
|
||||
evkPipeline evkCreatePipeline(evkDevice device, evkPipelineCreateInfo createInfo);
|
||||
void evkDestroyPipeline(evkPipeline pipeline);
|
||||
1
evk/evkRender.c
Normal file
1
evk/evkRender.c
Normal file
@@ -0,0 +1 @@
|
||||
#include "evkRender.h"
|
||||
3
evk/evkRender.h
Normal file
3
evk/evkRender.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
138
evk/evkShader.c
Normal file
138
evk/evkShader.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "evk/evkShader.h"
|
||||
#include "shaderc/shaderc.h"
|
||||
#include "ev_helpers.h"
|
||||
|
||||
evkShader evkInitShaderFromBytes(evkDevice device, const u8* shaderBytes, u32 shaderLen)
|
||||
{
|
||||
evkShader shader;
|
||||
VkShaderModuleCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.pCode = (u32*)shaderBytes,
|
||||
.codeSize = shaderLen,
|
||||
};
|
||||
vkCreateShaderModule(device.vk, &createInfo, NULL, &shader.vk);
|
||||
|
||||
shader.reflect = evkGenerateShaderReflectionData(shaderBytes, shaderLen);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
evkShaderReflectionData evkGenerateShaderReflectionData(const u8* shaderBytes, u32 shaderLen)
|
||||
{
|
||||
evkShaderReflectionData res;
|
||||
|
||||
SpvReflectShaderModule spvref;
|
||||
SpvReflectResult result = spvReflectCreateShaderModule(shaderLen, shaderBytes, &spvref);
|
||||
assert(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||
|
||||
// Fill evkShaderReflectionData
|
||||
res.stage = spvref.shader_stage;
|
||||
res.bindings = vec_init(evkDescriptorBinding);
|
||||
|
||||
|
||||
uint32_t descSetCount = 0;
|
||||
SpvReflectResult descSetResult = spvReflectEnumerateDescriptorSets(&spvref, &descSetCount, NULL);
|
||||
if(descSetResult == SPV_REFLECT_RESULT_SUCCESS)
|
||||
{
|
||||
SpvReflectDescriptorSet* refDescriptorSets[descSetCount] = {};
|
||||
spvReflectEnumerateDescriptorSets(&spvref, &descSetCount, refDescriptorSets);
|
||||
|
||||
for(int setIdx = 0; setIdx < descSetCount; setIdx++)
|
||||
{
|
||||
SpvReflectDescriptorSet* currentSet = refDescriptorSets[setIdx];
|
||||
for(int bindingIdx = 0; bindingIdx < currentSet->binding_count; bindingIdx++)
|
||||
{
|
||||
evkDescriptorBinding binding = {
|
||||
.stageFlags = res.stage,
|
||||
.binding = currentSet->bindings[bindingIdx]->binding,
|
||||
.descriptorType = (VkDescriptorType) currentSet->bindings[bindingIdx]->descriptor_type,
|
||||
.descriptorCount = currentSet->bindings[bindingIdx]->count,
|
||||
.set = currentSet->set,
|
||||
};
|
||||
|
||||
vec_push(&res.bindings, &binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spvReflectDestroyShaderModule(&spvref);
|
||||
return res;
|
||||
}
|
||||
|
||||
void evkDestroyShaderReflectionData(evkShaderReflectionData data)
|
||||
{
|
||||
vec_fini(&data.bindings);
|
||||
}
|
||||
|
||||
void evkDestroyShader(evkDevice device, evkShader shader)
|
||||
{
|
||||
vkDestroyShaderModule(device.vk, shader.vk, NULL);
|
||||
evkDestroyShaderReflectionData(shader.reflect);
|
||||
}
|
||||
|
||||
shaderc_include_result* _shader_include_resolve(void* user_data, const char* requested_source, int type, const char* requesting_source, size_t include_depth)
|
||||
{
|
||||
shaderc_include_result* result = malloc(sizeof(shaderc_include_result));
|
||||
result->source_name = evstring_new(requested_source);
|
||||
result->source_name_length = evstring_getLength((evstring)result->source_name);
|
||||
|
||||
result->content = evstring_readFile((evstring)result->source_name);
|
||||
result->content_length = evstring_getLength((evstring)result->content);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _shader_include_release(void* user_data, shaderc_include_result* include_result)
|
||||
{
|
||||
evstring_free((evstring)include_result->content);
|
||||
evstring_free((evstring)include_result->source_name);
|
||||
free(include_result);
|
||||
}
|
||||
|
||||
evkShaderCompiler evkCreateShaderCompiler()
|
||||
{
|
||||
evkShaderCompiler compiler;
|
||||
compiler.sc = shaderc_compiler_initialize();
|
||||
compiler.scopt = shaderc_compile_options_initialize();
|
||||
shaderc_compile_options_set_include_callbacks(compiler.scopt, _shader_include_resolve, _shader_include_release, NULL);
|
||||
return compiler;
|
||||
}
|
||||
|
||||
void evkDestroyShaderCompiler(evkShaderCompiler compiler)
|
||||
{
|
||||
shaderc_compile_options_release(compiler.scopt);
|
||||
shaderc_compiler_release(compiler.sc);
|
||||
}
|
||||
|
||||
evkShader evkInitShaderFromFile(evkDevice device, evkShaderCompiler compiler, evstring shaderPath)
|
||||
{
|
||||
evstring shaderText = evstring_readFile(shaderPath);
|
||||
|
||||
shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(compiler.sc, shaderText, evstring_getLength(shaderText), shaderc_glsl_infer_from_source, shaderPath, "main", compiler.scopt);
|
||||
|
||||
shaderc_compilation_status status = shaderc_result_get_compilation_status(compilation_result);
|
||||
|
||||
u32 errorCount = shaderc_result_get_num_errors(compilation_result);
|
||||
u32 warnCount = shaderc_result_get_num_warnings(compilation_result);
|
||||
printf("[[evkShader]] %s Compilation Status: %d ( %d Errors, %d Warnings )\n", shaderPath, status, errorCount, warnCount);
|
||||
if(errorCount + warnCount > 0)
|
||||
{
|
||||
printf("Errors:\n%s\n", shaderc_result_get_error_message(compilation_result));
|
||||
}
|
||||
|
||||
evkShader shader = evkInitShaderFromBytes(device, (u8*)shaderc_result_get_bytes(compilation_result), shaderc_result_get_length(compilation_result));
|
||||
|
||||
evstring_free(shaderText);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
VkPipelineShaderStageCreateInfo evkGetShaderStageCreateInfo(evkShader shader)
|
||||
{
|
||||
return (VkPipelineShaderStageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = shader.reflect.stage,
|
||||
.module = shader.vk,
|
||||
.pName = "main",
|
||||
};
|
||||
}
|
||||
18
evk/evkShader.h
Normal file
18
evk/evkShader.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "evk/evkCommon.h"
|
||||
|
||||
[[nodiscard("Leaking VkShaderModule")]]
|
||||
evkShader evkInitShaderFromBytes(evkDevice device, const u8* shaderBytes, u32 shaderLen);
|
||||
evkShader evkInitShaderFromFile(evkDevice device, evkShaderCompiler compiler, evstring shaderPath);
|
||||
void evkDestroyShader(evkDevice device, evkShader shader);
|
||||
|
||||
[[nodiscard("Leaking Shader Compiler")]]
|
||||
evkShaderCompiler evkCreateShaderCompiler();
|
||||
void evkDestroyShaderCompiler(evkShaderCompiler compiler);
|
||||
|
||||
VkPipelineShaderStageCreateInfo evkGetShaderStageCreateInfo(evkShader shader);
|
||||
|
||||
[[nodiscard("Leaking Shader Reflection Data")]]
|
||||
evkShaderReflectionData evkGenerateShaderReflectionData(const u8* shaderBytes, u32 shaderLen);
|
||||
void evkDestroyShaderReflectionData(evkShaderReflectionData data);
|
||||
93
evk/evkSwapChain.c
Normal file
93
evk/evkSwapChain.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "evkSwapChain.h"
|
||||
#include "evk.h"
|
||||
|
||||
evkSwapChain evkCreateSwapChain(evkSwapChainCreateInfo createInfo)
|
||||
{
|
||||
evkSwapChain swapChain;
|
||||
swapChain.surface = createInfo.surface;
|
||||
|
||||
VkSurfaceCapabilitiesKHR surfaceCaps;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(createInfo.device._physicalDevice, createInfo.surface, &surfaceCaps);
|
||||
|
||||
VkCompositeAlphaFlagBitsKHR compositeAlpha =
|
||||
(surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
|
||||
? VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
|
||||
: (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
|
||||
? VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR
|
||||
: (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
|
||||
? VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR
|
||||
: VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
|
||||
|
||||
u32 surfaceFormatCount = 0;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(createInfo.device._physicalDevice, createInfo.surface, &surfaceFormatCount, NULL);
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormats[surfaceFormatCount];
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(createInfo.device._physicalDevice, createInfo.surface, &surfaceFormatCount, surfaceFormats);
|
||||
|
||||
// TODO Add format picking logic
|
||||
swapChain.surfaceFormat = surfaceFormats[0];
|
||||
|
||||
u32 buffering = min(max(createInfo.imageCount, surfaceCaps.minImageCount), surfaceCaps.maxImageCount);
|
||||
|
||||
VkExtent2D imageExtent = surfaceCaps.currentExtent;
|
||||
if(imageExtent.width == UInt32.MAX)
|
||||
imageExtent.width = createInfo.width;
|
||||
if(imageExtent.height == UInt32.MAX)
|
||||
imageExtent.height = createInfo.width;
|
||||
|
||||
VkSwapchainCreateInfoKHR swapChainCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.surface = swapChain.surface,
|
||||
.minImageCount = buffering,
|
||||
.imageFormat = swapChain.surfaceFormat.format,
|
||||
.imageColorSpace = swapChain.surfaceFormat.colorSpace,
|
||||
.imageExtent = imageExtent,
|
||||
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.preTransform = surfaceCaps.currentTransform,
|
||||
.compositeAlpha = compositeAlpha,
|
||||
.presentMode = VK_PRESENT_MODE_MAILBOX_KHR,
|
||||
.clipped = VK_TRUE,
|
||||
.oldSwapchain = VK_NULL_HANDLE,
|
||||
};
|
||||
|
||||
vkCreateSwapchainKHR(createInfo.device.vk, &swapChainCreateInfo, NULL, &swapChain.vk);
|
||||
|
||||
VkImage swapChainVkImages[buffering];
|
||||
vkGetSwapchainImagesKHR(createInfo.device.vk, swapChain.vk, &buffering, swapChainVkImages);
|
||||
|
||||
swapChain.images = vec_init(evkImage);
|
||||
swapChain.imageViews = vec_init(evkImageView);
|
||||
vec_setlen(&swapChain.images, buffering);
|
||||
vec_setlen(&swapChain.imageViews, buffering);
|
||||
for(u32 i = 0; i < buffering; i++)
|
||||
{
|
||||
swapChain.images[i] = (evkImage) {
|
||||
.vk = swapChainVkImages[i],
|
||||
.width = imageExtent.width,
|
||||
.height = imageExtent.height,
|
||||
.format = swapChain.surfaceFormat.format
|
||||
};
|
||||
swapChain.imageViews[i] = evkCreateImageView(createInfo.device, swapChain.images[i],
|
||||
EV_DEFAULT(evkImageViewCreateInfo,
|
||||
viewAspect = VK_IMAGE_ASPECT_COLOR_BIT
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return swapChain;
|
||||
}
|
||||
|
||||
void evkDestroySwapChain(evkDevice device, evkSwapChain swapChain)
|
||||
{
|
||||
for(i32 i = 0; i < vec_len(&swapChain.imageViews); i++)
|
||||
{
|
||||
vkDestroyImageView(device.vk, swapChain.imageViews[i].vk, NULL);
|
||||
}
|
||||
|
||||
vec_fini(&swapChain.imageViews);
|
||||
vec_fini(&swapChain.images);
|
||||
vkDestroySwapchainKHR(device.vk, swapChain.vk, NULL);
|
||||
}
|
||||
8
evk/evkSwapChain.h
Normal file
8
evk/evkSwapChain.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
|
||||
[[nodiscard("Leaking VkSwapChain")]]
|
||||
evkSwapChain evkCreateSwapChain(evkSwapChainCreateInfo createInfo);
|
||||
|
||||
void evkDestroySwapChain(evkDevice device, evkSwapChain swapChain);
|
||||
20
evk/evkSync.c
Normal file
20
evk/evkSync.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "evk/evkSync.h"
|
||||
|
||||
VkSemaphore evkCreateSemaphore(evkDevice device)
|
||||
{
|
||||
VkSemaphore semaphore;
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
|
||||
vkCreateSemaphore(device.vk, &semaphoreCreateInfo, NULL, &semaphore);
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
VkFence evkCreateFence(evkDevice device, bool signaled)
|
||||
{
|
||||
VkFence fence;
|
||||
VkFenceCreateInfo fenceCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.flags = signaled?VK_FENCE_CREATE_SIGNALED_BIT:0,
|
||||
};
|
||||
vkCreateFence(device.vk, &fenceCreateInfo, NULL, &fence);
|
||||
return fence;
|
||||
}
|
||||
10
evk/evkSync.h
Normal file
10
evk/evkSync.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "evk.h"
|
||||
#include "evkDevice.h"
|
||||
|
||||
[[nodiscard("Leaking VkSemaphore")]]
|
||||
VkSemaphore evkCreateSemaphore(evkDevice device);
|
||||
|
||||
[[nodiscard("Leaking VkFence")]]
|
||||
VkFence evkCreateFence(evkDevice device, bool signaled);
|
||||
448
evk/evkTypes.h
Normal file
448
evk/evkTypes.h
Normal file
@@ -0,0 +1,448 @@
|
||||
#pragma once
|
||||
|
||||
#include "evkCommon.h"
|
||||
#include "shaderc/shaderc.h"
|
||||
#include "spirv_reflect.h"
|
||||
|
||||
TYPEDATA_GEN(VkInstance, INVALID(VK_NULL_HANDLE));
|
||||
TYPEDATA_GEN(VkDevice, INVALID(VK_NULL_HANDLE));
|
||||
TYPEDATA_GEN(VkPhysicalDevice);
|
||||
TYPEDATA_GEN(VkDeviceQueueCreateInfo);
|
||||
TYPEDATA_GEN(VkQueueFamilyProperties);
|
||||
TYPEDATA_GEN(VkImage);
|
||||
TYPEDATA_GEN(VkCommandBufferBeginInfo);
|
||||
TYPEDATA_GEN(VkCommandBuffer);
|
||||
TYPEDATA_GEN(VkDynamicState);
|
||||
TYPEDATA_GEN(VkSurfaceFormatKHR);
|
||||
TYPEDATA_GEN(VkFormat);
|
||||
TYPEDATA_GEN(VkClearValue, DEFAULT(0.f,0.f,0.f,1.f));
|
||||
TYPEDATA_GEN(VkRenderingAttachmentInfoKHR,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, // Requires VK_KHR_synchronization2
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_NONE_KHR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_NONE,
|
||||
.clearValue = (VkClearValue){0.f, 0.f, 0.f, 1.f},
|
||||
)
|
||||
);
|
||||
TYPEDATA_GEN(VkViewport,
|
||||
DEFAULT(
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.maxDepth = 1.0f,
|
||||
.minDepth = 0.f,
|
||||
.width = 0,
|
||||
.height = 0
|
||||
)
|
||||
)
|
||||
|
||||
TYPEDATA_GEN(VkRect2D,
|
||||
DEFAULT(0)
|
||||
)
|
||||
|
||||
TYPEDATA_GEN(VkRenderingInfo,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.flags = 0,
|
||||
.renderArea = {0, 0, 0, 0},
|
||||
.layerCount = 1,
|
||||
.viewMask = 0,
|
||||
.colorAttachmentCount = 0,
|
||||
.pColorAttachments = VK_NULL_HANDLE,
|
||||
.pDepthAttachment = VK_NULL_HANDLE,
|
||||
.pStencilAttachment = VK_NULL_HANDLE,
|
||||
)
|
||||
)
|
||||
|
||||
TYPEDATA_GEN(VkPipelineInputAssemblyStateCreateInfo,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||
.primitiveRestartEnable = VK_FALSE,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(VkPipelineRasterizationStateCreateInfo,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
.depthClampEnable = VK_FALSE,
|
||||
.rasterizerDiscardEnable = VK_FALSE,
|
||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||
.lineWidth = 1.0f,
|
||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.depthBiasEnable = VK_FALSE,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(VkPipelineColorBlendAttachmentState,
|
||||
DEFAULT(
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
||||
.blendEnable = VK_FALSE,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(VkPipelineMultisampleStateCreateInfo,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.sampleShadingEnable = VK_FALSE,
|
||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(VkPipelineShaderStageCreateInfo);
|
||||
|
||||
TYPEDATA_GEN(VkDescriptorSetLayout);
|
||||
TYPEDATA_GEN(VkDescriptorSetLayoutBinding);
|
||||
TYPEDATA_GEN(VkDescriptorSetLayoutCreateInfo,
|
||||
DEFAULT(
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
)
|
||||
);
|
||||
|
||||
// ========================================================================================================= //
|
||||
// =================================evk Types=============================================================== //
|
||||
// ========================================================================================================= //
|
||||
|
||||
typedef u32 evkApiVersion;
|
||||
|
||||
typedef struct {
|
||||
VkInstance vk;
|
||||
evkApiVersion apiVersion;
|
||||
} evkInstance;
|
||||
|
||||
typedef struct {
|
||||
VkQueueFlags flags;
|
||||
u32 count;
|
||||
} evkDeviceQueueRequirement;
|
||||
|
||||
typedef struct {
|
||||
evkInstance instance;
|
||||
VkPhysicalDeviceType physicalDeviceType;
|
||||
ev_vec(evkDeviceQueueRequirement) queueRequirements;
|
||||
ev_vec(evstring) deviceExtensions;
|
||||
} evkDeviceCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
i32 familyIndex;
|
||||
u32 allocatedQueueCount;
|
||||
} evkDeviceQueueFamily;
|
||||
|
||||
typedef struct {
|
||||
bool dynamicRendering;
|
||||
bool multiViewport;
|
||||
} evkPhysicalDeviceFeatures;
|
||||
|
||||
#define MAX_QUEUE_FAMILIES ((VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT) + 1)
|
||||
typedef struct {
|
||||
VkDevice vk;
|
||||
VkPhysicalDevice _physicalDevice;
|
||||
evkInstance _instance;
|
||||
evkDeviceQueueFamily queueFamilies[MAX_QUEUE_FAMILIES];
|
||||
VkPhysicalDeviceLimits limits;
|
||||
evkPhysicalDeviceFeatures enabledFeatures;
|
||||
} evkDevice;
|
||||
|
||||
typedef struct {
|
||||
VkCommandPool vk;
|
||||
evkDeviceQueueFamily queueFamily;
|
||||
} evkCommandPool;
|
||||
|
||||
typedef struct {
|
||||
evkDevice device;
|
||||
VkCommandPoolCreateFlags poolFlags;
|
||||
VkQueueFlags queueFlags;
|
||||
} evkCommandPoolCreateInfo;
|
||||
|
||||
typedef u32 evkAPIVersion;
|
||||
|
||||
typedef struct {
|
||||
evkAPIVersion apiVersion;
|
||||
u32 applicationVersion;
|
||||
u32 engineVersion;
|
||||
evstring applicationName;
|
||||
evstring engineName;
|
||||
} evkApplicationInfo;
|
||||
|
||||
typedef struct {
|
||||
evkApplicationInfo applicationInfo;
|
||||
ev_vec(evstring) extensions;
|
||||
ev_vec(evstring) layers;
|
||||
} evkInstanceCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkPipelineLayout vk;
|
||||
} evkPipelineLayout;
|
||||
|
||||
typedef struct {
|
||||
vec(VkDescriptorSetLayout) descriptorSetLayouts;
|
||||
vec(VkPushConstantRange) pushConstantRanges;
|
||||
} evkPipelineLayoutCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkOffset2D renderOffset;
|
||||
VkExtent2D renderExtents;
|
||||
u32 layerCount;
|
||||
u32 viewMask;
|
||||
VkRenderingFlags renderingFlags;
|
||||
|
||||
vec(VkRenderingAttachmentInfoKHR) colorAttachments;
|
||||
VkRenderingAttachmentInfoKHR depthAttachment;
|
||||
VkRenderingAttachmentInfoKHR stencilAttachment;
|
||||
} evkRenderingInfo;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
VkViewport;
|
||||
VkRect2D scissor;
|
||||
};
|
||||
struct {
|
||||
VkViewport vkViewport;
|
||||
VkRect2D vkScissor;
|
||||
};
|
||||
} evkViewport;
|
||||
|
||||
typedef union {
|
||||
VkDescriptorSetLayoutBinding vk;
|
||||
struct {
|
||||
VkDescriptorSetLayoutBinding;
|
||||
u32 set;
|
||||
};
|
||||
} evkDescriptorBinding;
|
||||
|
||||
typedef struct {
|
||||
VkShaderStageFlags stage;
|
||||
vec(evkDescriptorBinding) bindings;
|
||||
} evkShaderReflectionData;
|
||||
|
||||
typedef struct {
|
||||
VkShaderModule vk;
|
||||
evkShaderReflectionData reflect;
|
||||
} evkShader;
|
||||
|
||||
typedef struct {
|
||||
shaderc_compiler_t sc;
|
||||
shaderc_compile_options_t scopt;
|
||||
} evkShaderCompiler;
|
||||
|
||||
typedef struct {
|
||||
u32 dummy;
|
||||
} evkAllocationUserData;
|
||||
|
||||
typedef struct {
|
||||
VmaAllocator vma;
|
||||
} evkGPUAllocator;
|
||||
|
||||
typedef struct {
|
||||
VmaAllocation vma;
|
||||
} evkGPUAllocation;
|
||||
|
||||
typedef struct {
|
||||
VmaAllocationInfo vma;
|
||||
} evkGPUAllocationInfo;
|
||||
|
||||
typedef struct {
|
||||
evkGPUAllocator allocator;
|
||||
evkGPUAllocation allocation;
|
||||
evkGPUAllocationInfo allocationInfo;
|
||||
} evkGPUAllocationData;
|
||||
|
||||
typedef enum {
|
||||
EVK_GPU_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_MAPPED_BIT = VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_DONT_BIND_BIT = VMA_ALLOCATION_CREATE_DONT_BIND_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_CAN_ALIAS_BIT = VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
|
||||
EVK_GPU_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
|
||||
} evkGPUAllocationFlags;
|
||||
|
||||
typedef enum evkGPUMemoryUsage
|
||||
{
|
||||
EVK_GPU_MEMORY_USAGE_UNKNOWN = VMA_MEMORY_USAGE_UNKNOWN,
|
||||
EVK_GPU_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED,
|
||||
EVK_GPU_MEMORY_USAGE_AUTO = VMA_MEMORY_USAGE_AUTO,
|
||||
EVK_GPU_MEMORY_USAGE_AUTO_PREFER_DEVICE = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
EVK_GPU_MEMORY_USAGE_AUTO_PREFER_HOST = VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
EVK_GPU_MEMORY_USAGE_MAX_ENUM = VMA_MEMORY_USAGE_MAX_ENUM
|
||||
} evkGPUMemoryUsage;
|
||||
|
||||
typedef struct {
|
||||
VmaPool vma;
|
||||
} evkGPUMemoryPool;
|
||||
|
||||
typedef struct {
|
||||
evkGPUAllocationFlags allocationFlags;
|
||||
evkGPUMemoryUsage memoryUsage;
|
||||
evkGPUAllocator allocator;
|
||||
evkGPUMemoryPool pool;
|
||||
} evkGPUAllocationCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkImage vk;
|
||||
u32 width;
|
||||
u32 height;
|
||||
VkFormat format;
|
||||
evkGPUAllocationData allocData;
|
||||
} evkImage;
|
||||
|
||||
typedef struct {
|
||||
VkImageAspectFlags viewAspect;
|
||||
u32 mipBase;
|
||||
u32 mipCount;
|
||||
u32 baseLayer;
|
||||
u32 layerCount;
|
||||
} evkImageViewCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkImageView vk;
|
||||
} evkImageView;
|
||||
|
||||
typedef struct {
|
||||
evkGPUAllocationCreateInfo allocationCreateInfo;
|
||||
VkBufferCreateFlags flags;
|
||||
VkDeviceSize sizeInBytes;
|
||||
VkBufferUsageFlags usage;
|
||||
bool exclusive;
|
||||
vec(u32) queueFamilyIndices;
|
||||
} evkBufferCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkBuffer vk;
|
||||
evkGPUAllocationData allocData;
|
||||
u32 sizeInBytes;
|
||||
} evkBuffer;
|
||||
|
||||
typedef struct {
|
||||
evkGPUAllocationCreateInfo allocationCreateInfo;
|
||||
VkImageCreateFlags flags;
|
||||
VkImageType type;
|
||||
VkFormat format;
|
||||
VkExtent3D extent;
|
||||
u32 mipCount;
|
||||
u32 layerCount;
|
||||
u32 sampleCount;
|
||||
VkImageTiling tiling;
|
||||
VkImageUsageFlags usage;
|
||||
bool exclusive;
|
||||
vec(u32) queueFamilyIndices;
|
||||
VkImageLayout layout;
|
||||
} evkImageCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
VkSurfaceKHR surface;
|
||||
VkSwapchainKHR vk;
|
||||
vec(evkImage) images;
|
||||
vec(evkImageView) imageViews;
|
||||
} evkSwapChain;
|
||||
|
||||
typedef struct {
|
||||
evkDevice device;
|
||||
VkSurfaceKHR surface;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 imageCount;
|
||||
// Add more stuff when needed
|
||||
} evkSwapChainCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkFormat format;
|
||||
VkPipelineColorBlendAttachmentState blendState;
|
||||
} evkColorAttachment;
|
||||
|
||||
typedef struct {
|
||||
vec(VkDynamicState) dynamicStates;
|
||||
vec(evkShader) shaderStages;
|
||||
|
||||
vec(evkColorAttachment) colorAttachments;
|
||||
VkFormat depthAttachmentFormat;
|
||||
VkFormat stencilAttachmentFormat;
|
||||
u32 viewMask;
|
||||
|
||||
VkLogicOp blendingOp;
|
||||
f32 blendConstants[4];
|
||||
|
||||
u32 viewportCountOverride;
|
||||
vec(evkViewport) viewports;
|
||||
} evkPipelineCreateInfo;
|
||||
|
||||
typedef struct {
|
||||
VkPipeline vk;
|
||||
evkPipelineLayout layout;
|
||||
evkDevice _device;
|
||||
} evkPipeline;
|
||||
|
||||
TYPEDATA_GEN(evkInstance,
|
||||
INVALID(
|
||||
.vk = VK_NULL_HANDLE,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(evkShader);
|
||||
|
||||
TYPEDATA_GEN(evkPipelineLayoutCreateInfo,
|
||||
DEFAULT(
|
||||
.descriptorSetLayouts = EV_VEC_EMPTY,
|
||||
.pushConstantRanges = EV_VEC_EMPTY,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(evkApplicationInfo,
|
||||
DEFAULT(
|
||||
.apiVersion = VK_API_VERSION_1_1,
|
||||
.applicationVersion = 0,
|
||||
.engineVersion = 0,
|
||||
.applicationName = evstr("Test Application"),
|
||||
.engineName = evstr("evk")
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(evkImage);
|
||||
TYPEDATA_GEN(evkImageView);
|
||||
TYPEDATA_GEN(evkImageViewCreateInfo,
|
||||
DEFAULT(
|
||||
.layerCount = 1,
|
||||
.baseLayer = 0,
|
||||
.mipCount = 1,
|
||||
.mipBase = 0,
|
||||
.viewAspect = VK_IMAGE_ASPECT_NONE,
|
||||
)
|
||||
);
|
||||
TYPEDATA_GEN(evkAllocationUserData, INVALID(__EV_VEC_EMPTY_ARRAY));
|
||||
TYPEDATA_GEN(evkDeviceQueueRequirement);
|
||||
|
||||
TYPEDATA_GEN(evkViewport,
|
||||
DEFAULT(
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.maxDepth = 1.0f,
|
||||
.minDepth = 0.f,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.scissor.offset.x = 0,
|
||||
.scissor.offset.y = 0,
|
||||
.scissor.extent.width = 0,
|
||||
.scissor.extent.height = 0,
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(evkColorAttachment);
|
||||
|
||||
TYPEDATA_GEN(evkPipelineCreateInfo,
|
||||
DEFAULT(
|
||||
.dynamicStates = EV_VEC_EMPTY,
|
||||
.shaderStages = EV_VEC_EMPTY,
|
||||
|
||||
.colorAttachments = EV_VEC_EMPTY,
|
||||
.viewMask = 0,
|
||||
|
||||
.blendingOp = VK_LOGIC_OP_NO_OP
|
||||
)
|
||||
);
|
||||
|
||||
TYPEDATA_GEN(evkDescriptorBinding);
|
||||
249
main.c
Normal file
249
main.c
Normal file
@@ -0,0 +1,249 @@
|
||||
#include <evk/evk.h>
|
||||
#include <ev_numeric.h>
|
||||
#include <ev_helpers.h>
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
evstring PROJECT_NAME = evstr("evk");
|
||||
|
||||
float vertexPositions[] = {
|
||||
0.f,-.5f,
|
||||
.5f, .5f,
|
||||
-.5f, .5f
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
u32 width = 1024;
|
||||
u32 height = 1024;
|
||||
|
||||
evkInstance instance = evkCreateInstance((evkInstanceCreateInfo){
|
||||
.applicationInfo = EV_DEFAULT(evkApplicationInfo),
|
||||
.layers = svec_init(evstring, {
|
||||
evstr("VK_LAYER_KHRONOS_validation"),
|
||||
}),
|
||||
.extensions = svec_init(evstring, {
|
||||
evstr("VK_KHR_surface"),
|
||||
evstr("VK_KHR_win32_surface"),
|
||||
}),
|
||||
});
|
||||
|
||||
if(instance.vk == EV_INVALID(VkInstance))
|
||||
{
|
||||
puts("Instance creation failed.");
|
||||
goto InstanceCreationFailed;
|
||||
}
|
||||
puts("Instance was created successfully.");
|
||||
|
||||
evkDevice device = evkCreateDevice((evkDeviceCreateInfo) {
|
||||
.instance = instance,
|
||||
.physicalDeviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
|
||||
.queueRequirements = svec_init(evkDeviceQueueRequirement, {
|
||||
{ VK_QUEUE_GRAPHICS_BIT, 1 },
|
||||
{ VK_QUEUE_COMPUTE_BIT , 1 },
|
||||
}),
|
||||
.deviceExtensions = svec_init(evstring, {
|
||||
evstr("VK_KHR_swapchain"),
|
||||
evstr("VK_KHR_dynamic_rendering"),
|
||||
evstr("VK_KHR_depth_stencil_resolve"),
|
||||
evstr("VK_KHR_create_renderpass2"),
|
||||
evstr("VK_KHR_synchronization2"),
|
||||
evstr("VK_KHR_buffer_device_address"),
|
||||
evstr("VK_EXT_descriptor_indexing"),
|
||||
}),
|
||||
});
|
||||
|
||||
if(device.vk == EV_INVALID(VkDevice))
|
||||
{
|
||||
puts("Couldn't create a VkDevice");
|
||||
goto DeviceCreationFailed;
|
||||
}
|
||||
puts("Logical Device created successfully.");
|
||||
VkQueue graphicsQueue;
|
||||
vkGetDeviceQueue(device.vk, device.queueFamilies[VK_QUEUE_GRAPHICS_BIT].familyIndex, 0, &graphicsQueue);
|
||||
|
||||
if (!glfwInit())
|
||||
{
|
||||
puts("GLFW Initialization failed.");
|
||||
goto GLFWInitFailed;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1024,1024, "evk", NULL, NULL);
|
||||
if(!window)
|
||||
{
|
||||
puts("Window Creation Failed.");
|
||||
goto WindowCreationFailed;
|
||||
}
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = glfwCreateWindowSurface(instance.vk, window, NULL, &surface);
|
||||
if (err)
|
||||
{
|
||||
goto VKSurfaceCreationFailed;
|
||||
puts("Surface creation failed.");
|
||||
}
|
||||
|
||||
evkSwapChain swapChain = evkCreateSwapChain((evkSwapChainCreateInfo){
|
||||
.device = device,
|
||||
.surface = surface,
|
||||
.width = width,
|
||||
.height = height,
|
||||
.imageCount = 3,
|
||||
});
|
||||
|
||||
evkCommandPool commandPool = evkCreateCommandPool((evkCommandPoolCreateInfo) {
|
||||
.device = device,
|
||||
.queueFlags = VK_QUEUE_GRAPHICS_BIT,
|
||||
.poolFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
|
||||
});
|
||||
|
||||
vec(VkCommandBuffer) commandBuffers = evkAllocateCommandBuffers(device, commandPool, vec_len(&swapChain.images), true);
|
||||
|
||||
evkShaderCompiler compiler = evkCreateShaderCompiler();
|
||||
|
||||
evkShader vertShader = evkInitShaderFromFile(device, compiler, "shaders/tri.vert");
|
||||
evkShader fragShader = evkInitShaderFromFile(device, compiler, "shaders/tri.frag");
|
||||
|
||||
evkDestroyShaderCompiler(compiler);
|
||||
|
||||
evkColorAttachment colorAttachment0 = {
|
||||
swapChain.surfaceFormat.format,
|
||||
EV_DEFAULT(VkPipelineColorBlendAttachmentState)
|
||||
};
|
||||
|
||||
evkPipelineCreateInfo pipelineCreateInfo = EV_DEFAULT(evkPipelineCreateInfo,
|
||||
dynamicStates = svec_init(VkDynamicState, {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR,
|
||||
}),
|
||||
shaderStages = svec_init(evkShader, {
|
||||
vertShader,
|
||||
fragShader,
|
||||
}),
|
||||
colorAttachments = svec_init(evkColorAttachment, {
|
||||
colorAttachment0,
|
||||
}),
|
||||
viewportCountOverride = 1,
|
||||
);
|
||||
|
||||
VkViewport viewport = EV_DEFAULT(VkViewport, width=width, height=height);
|
||||
VkRect2D scissor = EV_DEFAULT(VkRect2D,extent.width=width, extent.height=height);
|
||||
|
||||
evkPipeline graphicsPipeline = evkCreatePipeline(device, pipelineCreateInfo);
|
||||
|
||||
VkFence drawFence = evkCreateFence(device, false);
|
||||
VkSemaphore imageAcquiredSemaphore = evkCreateSemaphore(device);
|
||||
VkSemaphore drawFinishedSemaphore = evkCreateSemaphore(device);
|
||||
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
u32 imageIdx;
|
||||
vkAcquireNextImageKHR(device.vk, swapChain.vk, UInt64.MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &imageIdx);
|
||||
|
||||
VkCommandBuffer cmdbuf = commandBuffers[imageIdx];
|
||||
|
||||
VkRenderingAttachmentInfoKHR colorAttachment = EV_DEFAULT(VkRenderingAttachmentInfoKHR,
|
||||
imageView = swapChain.imageViews[imageIdx].vk,
|
||||
loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
storeOp= VK_ATTACHMENT_STORE_OP_STORE,
|
||||
);
|
||||
|
||||
VkRenderingInfo renderingInfo = EV_DEFAULT(VkRenderingInfo,
|
||||
renderArea.extent = ((VkExtent2D){width, height}),
|
||||
pColorAttachments = &colorAttachment,
|
||||
colorAttachmentCount = 1,
|
||||
);
|
||||
|
||||
evkBeginPrimaryCommandBuffer(cmdbuf);
|
||||
|
||||
vkCmdSetScissor(cmdbuf, 0, 1, &scissor);
|
||||
vkCmdSetViewport(cmdbuf, 0, 1, &viewport);
|
||||
|
||||
vkCmdBeginRenderingKHR(cmdbuf, &renderingInfo);
|
||||
|
||||
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.vk);
|
||||
vkCmdDraw(cmdbuf, 3, 1, 0, 0);
|
||||
|
||||
vkCmdEndRenderingKHR(cmdbuf);
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = swapChain.images[imageIdx].vk,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.layerCount = 1,
|
||||
.levelCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(cmdbuf, 0, 0, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier);
|
||||
|
||||
evkEndCommandBuffer(cmdbuf);
|
||||
|
||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
|
||||
VkSubmitInfo submitInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pCommandBuffers = &cmdbuf,
|
||||
.commandBufferCount = 1,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &imageAcquiredSemaphore,
|
||||
.pWaitDstStageMask = waitStages,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &drawFinishedSemaphore,
|
||||
};
|
||||
|
||||
vkQueueSubmit(graphicsQueue, 1, &submitInfo, drawFence);
|
||||
vkWaitForFences(device.vk, 1, &drawFence, VK_TRUE, UInt64.MAX);
|
||||
vkResetFences(device.vk, 1, &drawFence);
|
||||
|
||||
VkPresentInfoKHR presentInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &drawFinishedSemaphore,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapChain.vk,
|
||||
.pImageIndices = &imageIdx,
|
||||
};
|
||||
vkQueuePresentKHR(graphicsQueue, &presentInfo);
|
||||
|
||||
vkResetCommandBuffer(cmdbuf,VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
|
||||
// Main Loop
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
vkQueueWaitIdle(graphicsQueue);
|
||||
|
||||
vkDestroyFence(device.vk, drawFence, NULL);
|
||||
vkDestroySemaphore(device.vk, imageAcquiredSemaphore, NULL);
|
||||
vkDestroySemaphore(device.vk, drawFinishedSemaphore, NULL);
|
||||
|
||||
evkDestroyPipeline(graphicsPipeline);
|
||||
|
||||
evkDestroyShader(device, vertShader);
|
||||
evkDestroyShader(device, fragShader);
|
||||
|
||||
vkFreeCommandBuffers(device.vk, commandPool.vk, vec_len(&commandBuffers), commandBuffers);
|
||||
evkDestroyCommandPool(device, commandPool);
|
||||
|
||||
evkDestroySwapChain(device, swapChain);
|
||||
|
||||
SwapchainCreationFailed:
|
||||
vkDestroySurfaceKHR(instance.vk, swapChain.surface, NULL);
|
||||
|
||||
VKSurfaceCreationFailed:
|
||||
WindowCreationFailed:
|
||||
glfwTerminate();
|
||||
|
||||
GLFWInitFailed:
|
||||
evkDestroyDevice(device);
|
||||
|
||||
DeviceCreationFailed:
|
||||
evkDestroyInstance(instance);
|
||||
InstanceCreationFailed:
|
||||
return 0;
|
||||
}
|
||||
8
meson-native-clang
Normal file
8
meson-native-clang
Normal file
@@ -0,0 +1,8 @@
|
||||
[binaries]
|
||||
c = 'clang.exe'
|
||||
c_ld = 'lld'
|
||||
cpp = 'clang++.exe'
|
||||
cpp_ld = 'lld'
|
||||
|
||||
[properties]
|
||||
c_args = ['-DEV_CC_CLANG=1']
|
||||
69
meson.build
Normal file
69
meson.build
Normal file
@@ -0,0 +1,69 @@
|
||||
project('evk', ['c','cpp'],
|
||||
version : '0.1',
|
||||
default_options : ['c_std=gnu23'])
|
||||
|
||||
build_config = configuration_data()
|
||||
|
||||
buildtype = get_option('buildtype')
|
||||
if buildtype == 'debug'
|
||||
build_config.set('EV_BUILDTYPE_DEBUG', 1)
|
||||
elif buildtype == 'debugoptimized'
|
||||
build_config.set('EV_BUILDTYPE_DEBUGOPT', 1)
|
||||
else
|
||||
build_config.set('EV_BUILDTYPE_RELEASE', 1)
|
||||
endif
|
||||
|
||||
configure_file(output: 'evk_buildconfig.h', configuration: build_config)
|
||||
|
||||
subproject('evol-headers')
|
||||
|
||||
evh_c_args = []
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
if cc.get_id() == 'msvc'
|
||||
evh_c_args += '/Zc:preprocessor'
|
||||
elif cc.get_id() == 'clang'
|
||||
evh_c_args += '-DEV_CC_CLANG=1'
|
||||
endif
|
||||
|
||||
evk_incdir = [
|
||||
'.',
|
||||
]
|
||||
|
||||
evk_src = [
|
||||
'main.c',
|
||||
|
||||
'evk/evkInstance.c',
|
||||
'evk/evkDevice.c',
|
||||
'evk/evkAllocator.c',
|
||||
'evk/evkSync.c',
|
||||
'evk/evkShader.c',
|
||||
'evk/evkSwapChain.c',
|
||||
'evk/evkAllocator.c',
|
||||
'evk/evkCommand.c',
|
||||
'evk/evkPipeline.c',
|
||||
'evk/evkDescriptor.c',
|
||||
'evk/evkRender.c',
|
||||
'evk/evkImage.c',
|
||||
'evk/evkMemory.c',
|
||||
]
|
||||
|
||||
executable(
|
||||
'evk',
|
||||
evk_src,
|
||||
include_directories: include_directories(evk_incdir),
|
||||
dependencies: [
|
||||
dependency('ev_vec'),
|
||||
dependency('ev_str'),
|
||||
dependency('ev_helpers'),
|
||||
|
||||
dependency('vma'),
|
||||
|
||||
dependency('volk'),
|
||||
dependency('glfw3'),
|
||||
|
||||
dependency('shaderc'),
|
||||
dependency('spvref'),
|
||||
],
|
||||
c_args: evh_c_args,
|
||||
)
|
||||
9
shaders/tri.frag
Normal file
9
shaders/tri.frag
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(0.f, 1.f, 0.f, 1.f);
|
||||
}
|
||||
15
shaders/tri.vert
Normal file
15
shaders/tri.vert
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(0.0, -0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-0.5, 0.5)
|
||||
);
|
||||
|
||||
// in layout(location=0) vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
// gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
7
subprojects/evol-headers.wrap
Normal file
7
subprojects/evol-headers.wrap
Normal file
@@ -0,0 +1,7 @@
|
||||
[wrap-git]
|
||||
directory = evol-headers
|
||||
url = https://github.com/evol3d/evol-headers
|
||||
revision = master
|
||||
|
||||
[provide]
|
||||
dependency_names = ev_str, ev_vec, evol-headers
|
||||
13
subprojects/glfw.wrap
Normal file
13
subprojects/glfw.wrap
Normal file
@@ -0,0 +1,13 @@
|
||||
[wrap-file]
|
||||
directory = glfw-3.3.10
|
||||
source_url = https://github.com/glfw/glfw/archive/refs/tags/3.3.10.tar.gz
|
||||
source_filename = glfw-3.3.10.tar.gz
|
||||
source_hash = 4ff18a3377da465386374d8127e7b7349b685288cb8e17122f7e1179f73769d5
|
||||
patch_filename = glfw_3.3.10-1_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/glfw_3.3.10-1/get_patch
|
||||
patch_hash = 3567f96c2576a5fc8c9cafd9059f919d7da404f6c22450c6c2ce3f9938909b8b
|
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/glfw_3.3.10-1/glfw-3.3.10.tar.gz
|
||||
wrapdb_version = 3.3.10-1
|
||||
|
||||
[provide]
|
||||
glfw3 = glfw_dep
|
||||
13
subprojects/packagefiles/libshaderc/meson.build
Normal file
13
subprojects/packagefiles/libshaderc/meson.build
Normal file
@@ -0,0 +1,13 @@
|
||||
project('libshaderc', 'cpp', default_options: ['buildtype=release'])
|
||||
|
||||
fs = import('fs')
|
||||
cxxc = meson.get_compiler('cpp')
|
||||
|
||||
shaderc_inc = include_directories('install/include')
|
||||
|
||||
shaderc_dep = declare_dependency(
|
||||
dependencies: cxxc.find_library('shaderc_combined', dirs: meson.current_source_dir()/'install/lib'),
|
||||
include_directories: shaderc_inc,
|
||||
)
|
||||
|
||||
meson.override_dependency('shaderc', shaderc_dep)
|
||||
22
subprojects/packagefiles/spvref/meson.build
Normal file
22
subprojects/packagefiles/spvref/meson.build
Normal file
@@ -0,0 +1,22 @@
|
||||
project('spvref', 'c')
|
||||
|
||||
vulkan_dep = dependency('vulkan').partial_dependency(compile_args : true)
|
||||
|
||||
spvref_inc = include_directories('.')
|
||||
|
||||
spvref_src = files('spirv_reflect.c')
|
||||
|
||||
spvref_lib = static_library(
|
||||
'spvref',
|
||||
spvref_src,
|
||||
include_directories: spvref_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
spvref_dep = declare_dependency(
|
||||
link_with: spvref_lib,
|
||||
include_directories: spvref_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
meson.override_dependency('spvref', spvref_dep)
|
||||
22
subprojects/packagefiles/vma/meson.build
Normal file
22
subprojects/packagefiles/vma/meson.build
Normal file
@@ -0,0 +1,22 @@
|
||||
project('vma', ['c','cpp'])
|
||||
|
||||
vulkan_dep = dependency('vulkan').partial_dependency(compile_args : true)
|
||||
|
||||
vma_inc = include_directories('include')
|
||||
|
||||
vma_src = files('vk_mem_alloc.cpp')
|
||||
|
||||
vma_lib = static_library(
|
||||
'vma',
|
||||
vma_src,
|
||||
include_directories: vma_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
vma_dep = declare_dependency(
|
||||
link_with: vma_lib,
|
||||
include_directories: vma_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
meson.override_dependency('vma', vma_dep)
|
||||
4
subprojects/packagefiles/vma/vk_mem_alloc.cpp
Normal file
4
subprojects/packagefiles/vma/vk_mem_alloc.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_IMPLEMENTATION
|
||||
#include <vk_mem_alloc.h>
|
||||
26
subprojects/packagefiles/volk/meson.build
Normal file
26
subprojects/packagefiles/volk/meson.build
Normal file
@@ -0,0 +1,26 @@
|
||||
project('volk', 'c',
|
||||
default_options: [
|
||||
'default_library=static',
|
||||
],
|
||||
)
|
||||
|
||||
vulkan_dep = dependency('vulkan').partial_dependency(compile_args : true)
|
||||
|
||||
volk_inc = include_directories('.')
|
||||
|
||||
volk_src = files('volk_impl.c')
|
||||
|
||||
volk_lib = library(
|
||||
'volk',
|
||||
volk_src,
|
||||
include_directories: volk_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
volk_dep = declare_dependency(
|
||||
link_with: volk_lib,
|
||||
include_directories: volk_inc,
|
||||
dependencies: vulkan_dep
|
||||
)
|
||||
|
||||
meson.override_dependency('volk', volk_dep)
|
||||
2
subprojects/packagefiles/volk/volk_impl.c
Normal file
2
subprojects/packagefiles/volk/volk_impl.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#define VOLK_IMPLEMENTATION
|
||||
#include "volk.h"
|
||||
12
subprojects/shaderc.wrap
Normal file
12
subprojects/shaderc.wrap
Normal file
@@ -0,0 +1,12 @@
|
||||
[wrap-file]
|
||||
directory = libshaderc
|
||||
|
||||
source_url = https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/windows/continuous_release_2019/64/20241106-090939/install.zip
|
||||
source_filename = libshaderc-upstream-msvc.zip
|
||||
source_hash = a6879869e580d5991ebd9909f3665d1f6fe39cdb9830adf4f48b35dfd3782a78
|
||||
lead_directory_missing = libshaderc
|
||||
|
||||
patch_directory = libshaderc
|
||||
|
||||
[provide]
|
||||
dependency_names = shaderc
|
||||
7
subprojects/spvref.wrap
Normal file
7
subprojects/spvref.wrap
Normal file
@@ -0,0 +1,7 @@
|
||||
[wrap-git]
|
||||
directory = spvref
|
||||
url = https://github.com/KhronosGroup/SPIRV-Reflect
|
||||
revision = main
|
||||
depth = 1
|
||||
|
||||
patch_directory = spvref
|
||||
7
subprojects/vma.wrap
Normal file
7
subprojects/vma.wrap
Normal file
@@ -0,0 +1,7 @@
|
||||
[wrap-git]
|
||||
directory = vma
|
||||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
|
||||
revision = master
|
||||
depth = 1
|
||||
|
||||
patch_directory = vma
|
||||
9
subprojects/volk.wrap
Normal file
9
subprojects/volk.wrap
Normal file
@@ -0,0 +1,9 @@
|
||||
[wrap-git]
|
||||
directory = volk
|
||||
url = https://github.com/zeux/volk
|
||||
revision = master
|
||||
|
||||
patch_directory = volk
|
||||
|
||||
[provide]
|
||||
dependency_names = volk
|
||||
Reference in New Issue
Block a user