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
|
Module.symvers
|
||||||
Mkfile.old
|
Mkfile.old
|
||||||
dkms.conf
|
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