rename to projects (DOES NOT COMPILE)
This commit is contained in:
43
projects/apis/vulkan/CMakeLists.txt
Normal file
43
projects/apis/vulkan/CMakeLists.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS on)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
project(GryphnVulkanImpl)
|
||||
|
||||
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS
|
||||
"src/*.c" "src/*.h"
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
file(GLOB_RECURSE METAL_FILES CONFIGURE_DEPENDS
|
||||
"src/*.m"
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(Vulkan REQUIRED)
|
||||
add_library(GryphnVulkanImpl STATIC ${SOURCE_FILES} ${METAL_FILES})
|
||||
target_include_directories(GryphnVulkanImpl PUBLIC
|
||||
${Vulkan_INCLUDE_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../utils/
|
||||
src/
|
||||
)
|
||||
add_compile_definitions(GN_REVEAL_IMPL)
|
||||
target_link_libraries(GryphnVulkanImpl ${Vulkan_LIBRARY})
|
||||
|
||||
if(WIN32)
|
||||
add_compile_definitions(GN_PLATFORM_WIN32)
|
||||
endif()
|
||||
if(APPLE)
|
||||
target_link_libraries(GryphnVulkanImpl
|
||||
"-framework IOKit"
|
||||
"-framework CoreFoundation"
|
||||
"-framework CoreGraphics"
|
||||
"-framework AppKit"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore"
|
||||
)
|
||||
add_compile_definitions(GN_PLATFORM_MACOS)
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
add_compile_definitions(GN_PLATFORM_LINUX)
|
||||
endif()
|
132
projects/apis/vulkan/src/buffers/vulkan_buffer.c
Normal file
132
projects/apis/vulkan/src/buffers/vulkan_buffer.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "vulkan_buffer.h"
|
||||
#include "core/buffers/gryphn_buffer.h"
|
||||
#include "core/output_device/gryphn_output_device.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "output_device/vulkan_physical_device.h"
|
||||
#include "commands/command_buffer/vulkan_command_buffer.h"
|
||||
|
||||
VkBufferUsageFlags vkGryphnBufferType(gnBufferType type) {
|
||||
VkBufferUsageFlags usageFlags = 0;
|
||||
switch (type) {
|
||||
case GN_VERTEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; break;
|
||||
case GN_INDEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break;
|
||||
case GN_UNIFORM_BUFFER: usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
|
||||
}
|
||||
return usageFlags;
|
||||
}
|
||||
|
||||
uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory) {
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(device, &memoryProperties);
|
||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
||||
if ((memoryType & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) {
|
||||
*foundMemory = gnTrue;
|
||||
return i;
|
||||
}
|
||||
} // this whole thing was adapted from vulkan-tutorial.com
|
||||
return 0;
|
||||
}
|
||||
gnReturnCode VkCreateBuffer(
|
||||
VkGryphnBuffer* buffer, size_t size, gnDevice device,
|
||||
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
|
||||
) {
|
||||
VkBufferCreateInfo bufferInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = size,
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||
};
|
||||
|
||||
if (vkCreateBuffer(device->outputDevice->device, &bufferInfo, NULL, &buffer->buffer) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_BUFFER;
|
||||
|
||||
VkMemoryRequirements bufferRequirements;
|
||||
vkGetBufferMemoryRequirements(device->outputDevice->device, buffer->buffer, &bufferRequirements);
|
||||
|
||||
gnBool foundMemory = gnFalse;
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = bufferRequirements.size,
|
||||
.memoryTypeIndex = VkMemoryIndex(device->physicalDevice.physicalDevice->device, bufferRequirements.memoryTypeBits, flags, &foundMemory)
|
||||
};
|
||||
if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY;
|
||||
|
||||
if (vkAllocateMemory(device->outputDevice->device, &memoryAllocateInfo, NULL, &buffer->memory) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ALLOCATE_MEMORY;
|
||||
vkBindBufferMemory(device->outputDevice->device, buffer->buffer, buffer->memory, 0);
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void VkCopyBuffer(VkBuffer source, VkBuffer destination, size_t size, VkCommandPool pool, VkDevice device, VkQueue queue) {
|
||||
VkCommandBuffer transferBuffer = VkBeginTransferOperation(device, pool);
|
||||
VkBufferCopy copyRegion = {
|
||||
.size = size
|
||||
};
|
||||
vkCmdCopyBuffer(transferBuffer, source, destination, 1, ©Region);
|
||||
VkEndTransferOperation(transferBuffer, pool, queue, device);
|
||||
}
|
||||
|
||||
gnReturnCode gnCreateBufferFn(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
|
||||
buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t));
|
||||
VkBufferUsageFlags usage = vkGryphnBufferType(info.type);
|
||||
buffer->buffer->useStagingBuffer = gnFalse;
|
||||
if (info.usage == GN_STATIC_DRAW) {
|
||||
buffer->buffer->useStagingBuffer = gnTrue;
|
||||
VkCreateBuffer(
|
||||
&buffer->buffer->stagingBuffer,
|
||||
info.size, device,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||
);
|
||||
|
||||
return VkCreateBuffer(
|
||||
&buffer->buffer->buffer,
|
||||
info.size, device,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
vkGryphnBufferType(info.type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
);
|
||||
} else {
|
||||
return VkCreateBuffer(
|
||||
&buffer->buffer->buffer,
|
||||
info.size, device,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
vkGryphnBufferType(info.type)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
void gnBufferDataFn(gnBufferHandle buffer, size_t dataSize, void* data) {
|
||||
void* bufferData;
|
||||
if (buffer->buffer->useStagingBuffer) {
|
||||
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory, 0, dataSize, 0, &bufferData);
|
||||
memcpy(bufferData, data, dataSize);
|
||||
vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory);
|
||||
VkCopyBuffer(
|
||||
buffer->buffer->stagingBuffer.buffer, buffer->buffer->buffer.buffer, dataSize,
|
||||
buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device,
|
||||
buffer->device->outputDevice->transferQueue);
|
||||
} else {
|
||||
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData);
|
||||
memcpy(bufferData, data, dataSize);
|
||||
vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory);
|
||||
}
|
||||
}
|
||||
void* gnMapBufferFn(gnBufferHandle buffer) {
|
||||
void* data;
|
||||
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, buffer->info.size, 0, &data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device) {
|
||||
vkDestroyBuffer(device, buffer->buffer, NULL);
|
||||
vkFreeMemory(device, buffer->memory, NULL);
|
||||
}
|
||||
|
||||
void gnDestroyBufferFn(gnBufferHandle buffer) {
|
||||
if (buffer->buffer->useStagingBuffer == gnTrue) gnDestroyVulkanBuffer(&buffer->buffer->stagingBuffer, buffer->device->outputDevice->device);
|
||||
gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device->outputDevice->device);
|
||||
free(buffer->buffer);
|
||||
}
|
24
projects/apis/vulkan/src/buffers/vulkan_buffer.h
Normal file
24
projects/apis/vulkan/src/buffers/vulkan_buffer.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "utils/gryphn_bool.h"
|
||||
#include <core/buffers/gryphn_buffer.h>
|
||||
|
||||
typedef struct VkGryphnBuffer {
|
||||
VkBuffer buffer;
|
||||
VkDeviceMemory memory;
|
||||
} VkGryphnBuffer;
|
||||
void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device);
|
||||
|
||||
struct gnPlatformBuffer_t {
|
||||
VkGryphnBuffer buffer;
|
||||
|
||||
// for if static draw
|
||||
VkGryphnBuffer stagingBuffer;
|
||||
gnBool useStagingBuffer;
|
||||
};
|
||||
|
||||
gnReturnCode VkCreateBuffer(
|
||||
VkGryphnBuffer* buffer, size_t size, gnDevice device,
|
||||
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
|
||||
);
|
||||
uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory);
|
@@ -0,0 +1,80 @@
|
||||
#include "vulkan_command_buffer.h"
|
||||
#include "commands/command_pool/vulkan_command_pool.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnCommandPoolAllocateCommandBuffersFn(gnCommandBufferHandle* commandBuffers, uint32_t count, struct gnCommandPool_t* pool) {
|
||||
VkCommandBufferAllocateInfo allocInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = pool->commandPool->commandPool,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = count,
|
||||
};
|
||||
|
||||
VkCommandBuffer* buffers = malloc(sizeof(VkCommandBuffer) * count);
|
||||
|
||||
if (vkAllocateCommandBuffers(pool->device->outputDevice->device, &allocInfo, buffers) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ALLOCATE_COMMAND_BUFFERS;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
commandBuffers[i]->commandBuffer = malloc(sizeof(gnPlatformCommandBuffer));
|
||||
commandBuffers[i]->commandBuffer->buffer = buffers[i];
|
||||
}
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnResetCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
|
||||
vkResetCommandBuffer(commandBuffer->commandBuffer->buffer, 0);
|
||||
}
|
||||
|
||||
|
||||
gnReturnCode gnBeginCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
|
||||
};
|
||||
|
||||
if (vkBeginCommandBuffer(commandBuffer->commandBuffer->buffer, &beginInfo) != VK_SUCCESS) {
|
||||
return GN_FAILED_TO_BEGIN_RECORDING;
|
||||
}
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
gnReturnCode gnEndCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
|
||||
if (vkEndCommandBuffer(commandBuffer->commandBuffer->buffer) != VK_SUCCESS)
|
||||
return GN_FAIELD_TO_END_RECORDING;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
VkCommandBuffer VkBeginTransferOperation(VkDevice device, VkCommandPool pool) {
|
||||
VkCommandBufferAllocateInfo allocInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandPool = pool,
|
||||
.commandBufferCount = 1
|
||||
};
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
};
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
void VkEndTransferOperation(VkCommandBuffer transferBuffer, VkCommandPool pool, VkQueue syncQueue, VkDevice device) {
|
||||
vkEndCommandBuffer(transferBuffer);
|
||||
|
||||
VkSubmitInfo submitInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &transferBuffer
|
||||
};
|
||||
|
||||
vkQueueSubmit(syncQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(syncQueue);
|
||||
vkFreeCommandBuffers(device, pool, 1, &transferBuffer);
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "core/command/command_buffer/gryphn_command_buffer.h"
|
||||
#include "utils/gryphn_bool.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformCommandBuffer_t {
|
||||
VkCommandBuffer buffer;
|
||||
|
||||
gnBool changedBuffer;
|
||||
gnBufferHandle boundIndexBuffer;
|
||||
gnGraphicsPipeline boundGraphicsPipeline;
|
||||
} gnPlatformCommandBuffer;
|
||||
|
||||
VkCommandBuffer VkBeginTransferOperation(VkDevice device, VkCommandPool pool);
|
||||
void VkEndTransferOperation(VkCommandBuffer transferBuffer, VkCommandPool pool, VkQueue syncQueue, VkDevice device);
|
@@ -0,0 +1,23 @@
|
||||
#include "vulkan_command_pool.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnCreateCommandPoolFn(struct gnCommandPool_t* commandPool, struct gnOutputDevice_t* device, struct gnCommandPoolInfo_t info) {
|
||||
commandPool->commandPool = malloc(sizeof(gnPlatformCommandPool));
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = info.queueIndex,
|
||||
};
|
||||
|
||||
if (vkCreateCommandPool(device->outputDevice->device, &poolInfo, NULL, &commandPool->commandPool->commandPool) != VK_SUCCESS) {
|
||||
return GN_FAILED_TO_CREATE_COMMAND_POOL;
|
||||
}
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyCommandPoolFn(struct gnCommandPool_t* commandPool) {
|
||||
vkDestroyCommandPool(commandPool->device->outputDevice->device, commandPool->commandPool->commandPool, NULL);
|
||||
free(commandPool->commandPool);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/command/command_pool/gryphn_command_pool.h"
|
||||
|
||||
typedef struct gnPlatformCommandPool_t {
|
||||
VkCommandPool commandPool;
|
||||
} gnPlatformCommandPool;
|
97
projects/apis/vulkan/src/commands/commands/vulkan_commands.c
Normal file
97
projects/apis/vulkan/src/commands/commands/vulkan_commands.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/command/commands/gryphn_command.h"
|
||||
#include <renderpass/vulkan_render_pass_descriptor.h>
|
||||
#include "framebuffers/vulkan_framebuffer.h"
|
||||
#include "commands/command_buffer/vulkan_command_buffer.h"
|
||||
#include "pipelines/graphics_pipeline/vulkan_graphics_pipeline.h"
|
||||
#include "buffers/vulkan_buffer.h"
|
||||
#include "uniforms/vulkan_uniform.h"
|
||||
#include "shader_module/vulkan_shader_module.h"
|
||||
|
||||
void gnCommandBeginRenderPassFn(gnCommandBuffer buffer, struct gnRenderPassInfo_t passInfo) {
|
||||
VkClearValue* values = malloc(sizeof(VkClearValue) * passInfo.clearValueCount);
|
||||
for (int i = 0; i < passInfo.clearValueCount; i++) {
|
||||
values[i] = (VkClearValue){{{
|
||||
passInfo.clearValues[i].red,
|
||||
passInfo.clearValues[i].green,
|
||||
passInfo.clearValues[i].blue,
|
||||
passInfo.clearValues[i].alpha
|
||||
}}};
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo ={
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = passInfo.renderPassDescriptor->renderPassDescriptor->renderPass,
|
||||
.framebuffer = passInfo.framebuffer->framebuffer->framebuffer,
|
||||
.renderArea = {
|
||||
.extent = { passInfo.size.x, passInfo.size.y },
|
||||
.offset = { passInfo.offset.x, passInfo.offset.y }
|
||||
},
|
||||
.clearValueCount = passInfo.clearValueCount,
|
||||
.pClearValues = values,
|
||||
};
|
||||
|
||||
vkCmdBeginRenderPass(buffer->commandBuffer->buffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
void gnCommandEndRenderPassFn(gnCommandBuffer buffer) {
|
||||
vkCmdEndRenderPass(buffer->commandBuffer->buffer);
|
||||
}
|
||||
void gnCommandBindGraphicsPipelineFn(gnCommandBuffer buffer, gnGraphicsPipeline graphicsPipeline) {
|
||||
buffer->commandBuffer->boundGraphicsPipeline = graphicsPipeline;
|
||||
vkCmdBindPipeline(buffer->commandBuffer->buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->graphicsPipeline->graphicsPipeline);
|
||||
}
|
||||
void gnCommandSetViewportFn(gnCommandBuffer buffer, gnViewport viewport) {
|
||||
VkViewport vkViewport = {
|
||||
.x = viewport.position.x,
|
||||
.y = viewport.size.y,
|
||||
.width = viewport.size.x,
|
||||
.height = -viewport.size.y,
|
||||
.minDepth = viewport.minDepth,
|
||||
.maxDepth = viewport.maxDepth
|
||||
};
|
||||
vkCmdSetViewport(buffer->commandBuffer->buffer, 0, 1, &vkViewport);
|
||||
}
|
||||
void gnCommandSetScissorFn(gnCommandBuffer buffer, struct gnScissor_t scissor) {
|
||||
VkRect2D vkScissor = {
|
||||
.extent = { scissor.size.x, scissor.size.y },
|
||||
.offset = { scissor.position.x, scissor.position.y }
|
||||
};
|
||||
vkCmdSetScissor(buffer->commandBuffer->buffer, 0, 1, &vkScissor);
|
||||
}
|
||||
VkDeviceSize offsets[] = {0};
|
||||
void gnCommandBindBufferFn(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type) {
|
||||
if (type == GN_VERTEX_BUFFER)
|
||||
vkCmdBindVertexBuffers(buffer->commandBuffer->buffer, 0, 1, &bufferToBind->buffer->buffer.buffer, offsets);
|
||||
else if (type == GN_INDEX_BUFFER) {
|
||||
buffer->commandBuffer->changedBuffer = gnTrue;
|
||||
buffer->commandBuffer->boundIndexBuffer = bufferToBind;
|
||||
}
|
||||
}
|
||||
void gnCommandDrawFn(gnCommandBuffer buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance) {
|
||||
vkCmdDraw(buffer->commandBuffer->buffer, vertexCount, instanceCount, firstVertex, firstInstance);
|
||||
}
|
||||
void gnCommandDrawIndexedFn(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance) {
|
||||
if (buffer->commandBuffer->changedBuffer) vkCmdBindIndexBuffer(buffer->commandBuffer->buffer, buffer->commandBuffer->boundIndexBuffer->buffer->buffer.buffer, 0, (type == GN_UINT32) ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
|
||||
vkCmdDrawIndexed(buffer->commandBuffer->buffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
||||
buffer->commandBuffer->changedBuffer = gnFalse;
|
||||
}
|
||||
|
||||
void gnCommandBindUniformFn(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set) {
|
||||
vkCmdBindDescriptorSets(
|
||||
buffer->commandBuffer->buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->pipelineLayout, set, 1,
|
||||
&uniform->uniform->set, 0, NULL
|
||||
);
|
||||
}
|
||||
|
||||
void gnCommandPushConstantFn(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) {
|
||||
vkCmdPushConstants(
|
||||
buffer->commandBuffer->buffer,
|
||||
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->pipelineLayout,
|
||||
vkGryphnShaderModuleStage(layout.stage),
|
||||
layout.offset,
|
||||
layout.size,
|
||||
data
|
||||
);
|
||||
}
|
158
projects/apis/vulkan/src/debugger/vulkan_debugger.c
Normal file
158
projects/apis/vulkan/src/debugger/vulkan_debugger.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "vulkan_debugger.h"
|
||||
#include <instance/vulkan_instance.h>
|
||||
|
||||
void vkPopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT* createInfo) {
|
||||
createInfo->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||
createInfo->messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
createInfo->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
}
|
||||
|
||||
// gnBool vkCheckValidationLayerSupport(uint32_t count, const char** layers) {
|
||||
// uint32_t layerCount;
|
||||
// vkEnumerateInstanceLayerProperties(&layerCount, NULL);
|
||||
// if (layerCount == 0) return gnFalse;
|
||||
|
||||
// VkLayerProperties* properties = malloc(sizeof(VkLayerProperties) * layerCount);
|
||||
// vkEnumerateInstanceLayerProperties(&layerCount, properties);
|
||||
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// gnBool layerFound = gnFalse;
|
||||
|
||||
// for (int c = 0; c < layerCount; c++) {
|
||||
// if (strcmp(layers[i], properties[c].layerName) == 0) {
|
||||
// layerFound = gnTrue;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (layerFound == gnFalse)
|
||||
// return gnFalse;
|
||||
// }
|
||||
|
||||
// return gnTrue;
|
||||
// }
|
||||
|
||||
// typedef struct vk_userData_t {
|
||||
// gnDebuggerCallback debuggerCallback;
|
||||
// void* userData;
|
||||
// } vkUserData;
|
||||
|
||||
// static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debuggerDebugCallback(
|
||||
// VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
// VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
// const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
// void* pUserData) {
|
||||
// struct vk_userData_t userData = *(struct vk_userData_t*)pUserData;
|
||||
|
||||
// gnMessageSeverity severity;
|
||||
// gnMessageType type;
|
||||
// gnMessageData data = {
|
||||
// .message = gnCreateString(pCallbackData->pMessage)
|
||||
// };
|
||||
|
||||
// switch (messageSeverity) {
|
||||
// default: break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: severity = GN_MESSAGE_VERBOSE; break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: severity = GN_MESSAGE_INFO; break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: severity = GN_MESSAGE_WARNING; break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: severity = GN_MESSAGE_ERROR; break;
|
||||
// }
|
||||
|
||||
// switch (messageType) {
|
||||
// default: break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: type = GN_DEBUG_MESSAGE_GENERAL; break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: type = GN_DEBUG_MESSAGE_VALIDATION; break;
|
||||
// case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: type = GN_DEBUG_MESSAGE_PERFORMANCE; break;
|
||||
// }
|
||||
|
||||
// gnDebuggerCallback callback = *userData.debuggerCallback;
|
||||
// gnBool result = callback(severity, type, data, userData.userData);
|
||||
// if (result == gnFalse) return VK_FALSE;
|
||||
// return VK_TRUE;
|
||||
// }
|
||||
|
||||
// VkResult vk_createDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
|
||||
// PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
|
||||
// if (vkCreateDebugUtilsMessengerEXT != NULL) {
|
||||
// return vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, NULL, pDebugMessenger);
|
||||
// }else
|
||||
// return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
// return VK_SUCCESS;
|
||||
// }
|
||||
|
||||
// void vk_destroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {
|
||||
// PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
|
||||
// if (vkDestroyDebugUtilsMessengerEXT != NULL) {
|
||||
// vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, pAllocator);
|
||||
// }
|
||||
// }
|
||||
|
||||
// gnReturnCode gnCreateDebuggerFn(gnDebuggerHandle debugger, gnInstanceHandle instance, const struct gnDebuggerInfo_t info) {
|
||||
// debugger->debugger = malloc(sizeof(gnPlatformDebugger));
|
||||
|
||||
// if (instance->valid == gnFalse) {
|
||||
// for (int i = 0; i < instance->instance->instanceMessageCount; i++) {
|
||||
// info.callback(
|
||||
// instance->instance->instanceMessages[i].severity,
|
||||
// instance->instance->instanceMessages[i].type,
|
||||
// instance->instance->instanceMessages[i].data,
|
||||
// info.userData
|
||||
// );
|
||||
// }
|
||||
// return GN_INVALID_INSTANCE;
|
||||
// } else {
|
||||
// for (int i = 0; i < instance->instance->instanceMessageCount; i++) {
|
||||
// info.callback(
|
||||
// instance->instance->instanceMessages[i].severity,
|
||||
// instance->instance->instanceMessages[i].type,
|
||||
// instance->instance->instanceMessages[i].data,
|
||||
// info.userData
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (instance->instance->instanceMessageCount > 0) free(instance->instance->instanceMessages);
|
||||
// instance->instance->instanceMessageCount = 0;
|
||||
|
||||
// const char* layers[] = {
|
||||
// "VK_LAYER_KHRONOS_validation"
|
||||
// };
|
||||
// if (!checkValidationLayerSupport(1, layers))
|
||||
// return GN_FAILED_TO_CREATE_DEBUGGER;
|
||||
|
||||
|
||||
// struct vk_userData_t* userData = (struct vk_userData_t*)malloc(sizeof(struct vk_userData_t));
|
||||
// userData->debuggerCallback = info.callback;
|
||||
// userData->userData = info.userData;
|
||||
|
||||
// VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
|
||||
// createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||
// createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
// createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
// createInfo.pUserData = (void*)userData;
|
||||
// createInfo.pfnUserCallback = vk_debuggerDebugCallback;
|
||||
|
||||
// VkResult result = vk_createDebugUtilsMessengerEXT(instance->instance->vk_instance, &createInfo, NULL, &debugger->debugger->debugMessenger); if (result != VK_SUCCESS) {
|
||||
// gnMessageSeverity severity = GN_MESSAGE_ERROR;
|
||||
// gnMessageType type = GN_DEBUG_MESSAGE_VALIDATION;
|
||||
// gnMessageData data = {
|
||||
// .message = gnCombineStrings(
|
||||
// gnCreateString("Failed to create gnDebuggerObject with api vulkan\n"),
|
||||
// gnCombineStrings(gnCreateString("Returned with a vulkan error code of: (please do this)"), "")
|
||||
// )
|
||||
// };
|
||||
// info.callback(
|
||||
// severity,
|
||||
// type,
|
||||
// data,
|
||||
// info.userData
|
||||
// );
|
||||
|
||||
// return GN_FAILED_TO_CREATE_DEBUGGER;
|
||||
// }
|
||||
// return GN_SUCCESS;
|
||||
// }
|
||||
|
||||
// void gnDestroyDebuggerFn(gnDebuggerHandle debugger) {
|
||||
// vk_destroyDebugUtilsMessengerEXT(debugger->instance->instance->vk_instance, debugger->debugger->debugMessenger, NULL);
|
||||
// }
|
9
projects/apis/vulkan/src/debugger/vulkan_debugger.h
Normal file
9
projects/apis/vulkan/src/debugger/vulkan_debugger.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/debugger/gryphn_debugger.h>
|
||||
|
||||
typedef struct gnPlatformDebugger_t {
|
||||
VkDebugUtilsMessengerEXT debugMessenger;
|
||||
} gnPlatformDebugger;
|
||||
|
||||
void vkPopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT* createInfo);
|
34
projects/apis/vulkan/src/framebuffers/vulkan_framebuffer.c
Normal file
34
projects/apis/vulkan/src/framebuffers/vulkan_framebuffer.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "vulkan_framebuffer.h"
|
||||
#include "textures/vulkan_texture.h"
|
||||
#include "renderpass/vulkan_render_pass_descriptor.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct gnOutputDevice_t* device, struct gnFramebufferInfo_t info) {
|
||||
framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t));
|
||||
|
||||
VkImageView* attachments = malloc(sizeof(VkImageView) * info.attachmentCount);
|
||||
for (int i = 0; i < info.attachmentCount; i++)
|
||||
attachments[i] = info.attachments[i]->texture->image.imageView;
|
||||
|
||||
VkFramebufferCreateInfo framebufferInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = info.renderPassDescriptor->renderPassDescriptor->renderPass,
|
||||
.attachmentCount = info.attachmentCount,
|
||||
.pAttachments = attachments,
|
||||
.width = info.size.x,
|
||||
.height = info.size.y,
|
||||
.layers = 1
|
||||
};
|
||||
|
||||
if (vkCreateFramebuffer(device->outputDevice->device, &framebufferInfo, NULL, &framebuffer->framebuffer->framebuffer) != VK_SUCCESS) {
|
||||
return GN_FAILED_TO_CREATE_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
free(attachments);
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyFramebufferFn(struct gnFramebuffer_t* framebuffer) {
|
||||
vkDestroyFramebuffer(framebuffer->device->outputDevice->device, framebuffer->framebuffer->framebuffer, NULL);
|
||||
free(framebuffer->framebuffer);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "core/framebuffer/gryphn_framebuffer.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformFramebuffer_t {
|
||||
VkFramebuffer framebuffer;
|
||||
} gnPlatformFramebuffer;
|
136
projects/apis/vulkan/src/instance/vulkan_instance.c
Normal file
136
projects/apis/vulkan/src/instance/vulkan_instance.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "vulkan_instance.h"
|
||||
#include <debugger/vulkan_debugger.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct vkUserData {
|
||||
gnDebuggerCallback debuggerCallback;
|
||||
void* userData;
|
||||
} vkUserData;
|
||||
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debuggerDebugCallback(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
void* pUserData) {
|
||||
|
||||
gnMessageSeverity severity;
|
||||
gnMessageType type;
|
||||
gnMessageData data = {
|
||||
.message = gnCreateString(pCallbackData->pMessage)
|
||||
};
|
||||
|
||||
switch (messageSeverity) {
|
||||
default: break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: severity = GN_MESSAGE_VERBOSE; break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: severity = GN_MESSAGE_INFO; break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: severity = GN_MESSAGE_WARNING; break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: severity = GN_MESSAGE_ERROR; break;
|
||||
}
|
||||
|
||||
switch (messageType) {
|
||||
default: break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: type = GN_DEBUG_MESSAGE_GENERAL; break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: type = GN_DEBUG_MESSAGE_VALIDATION; break;
|
||||
case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: type = GN_DEBUG_MESSAGE_PERFORMANCE; break;
|
||||
}
|
||||
|
||||
vkUserData* userData = (vkUserData*)pUserData;
|
||||
gnDebuggerCallback callback = userData->debuggerCallback;
|
||||
gnBool result = callback(severity, type, data, userData->userData);
|
||||
if (result == gnFalse) return VK_FALSE;
|
||||
return VK_TRUE;
|
||||
}
|
||||
|
||||
gnReturnCode gnCreateInstanceFn(gnInstanceHandle instance, gnInstanceInfo instanceInfo) {
|
||||
instance->instance = malloc(sizeof(gnPlatformInstance));
|
||||
instance->instance->instanceMessageCount = 0;
|
||||
|
||||
#ifdef GN_PLATFORM_LINUX
|
||||
gnBool isX11 = gnTrue;
|
||||
uint32_t extensionCount = 3;
|
||||
const char* extensions[3];
|
||||
if (isX11) {
|
||||
extensions[0] = "VK_KHR_xlib_surface";
|
||||
extensions[1] = "VK_KHR_surface";
|
||||
extensions[2] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
||||
} else {
|
||||
extensions[0] = "VK_KHR_wayland_surface";
|
||||
extensions[1] = "VK_KHR_surface";
|
||||
extensions[2] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
||||
}
|
||||
#endif
|
||||
#ifdef GN_PLATFORM_WINDOWS
|
||||
uint32_t extensionCount = 3;
|
||||
const char* extensions[] = {
|
||||
"VK_KHR_win32_surface",
|
||||
"VK_KHR_surface",
|
||||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
|
||||
};
|
||||
#endif
|
||||
#ifdef GN_PLATFORM_MACOS
|
||||
uint32_t extensionCount = 4;
|
||||
const char* extensions[] = {
|
||||
"VK_KHR_portability_enumeration",
|
||||
"VK_EXT_metal_surface",
|
||||
"VK_KHR_surface",
|
||||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
VkApplicationInfo appInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pApplicationName = gnToCString(instanceInfo.applicationName),
|
||||
.applicationVersion = instanceInfo.applicationVersion,
|
||||
.pEngineName = gnToCString(instanceInfo.engineName),
|
||||
.engineVersion = instanceInfo.engineVersion,
|
||||
.apiVersion = VK_API_VERSION_1_3,
|
||||
};
|
||||
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
VkInstanceCreateFlags createFlags = 0;
|
||||
#ifdef GN_PLATFORM_MACOS
|
||||
createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
#endif
|
||||
|
||||
createInfo.flags = createFlags;
|
||||
|
||||
if (instanceInfo.debugger != NULL) {
|
||||
for (int i = 0; i < instanceInfo.debugger->info.layerCount; i++) {
|
||||
if (instanceInfo.debugger->info.layers[i] == GN_DEBUGGER_LAYER_PLATFORM) {
|
||||
const char* validation_layers[1] = { "VK_LAYER_KHRONOS_validation" };
|
||||
createInfo.enabledLayerCount = 1;
|
||||
createInfo.ppEnabledLayerNames = (const char*[]){ "VK_LAYER_KHRONOS_validation" };
|
||||
|
||||
vkUserData* userData = malloc(sizeof(vkUserData));
|
||||
userData->debuggerCallback = instanceInfo.debugger->info.callback;
|
||||
userData->userData = instanceInfo.debugger->info.userData;
|
||||
|
||||
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {};
|
||||
vkPopulateDebugMessengerCreateInfo(&debugCreateInfo);
|
||||
debugCreateInfo.pfnUserCallback = vk_debuggerDebugCallback;
|
||||
debugCreateInfo.pUserData = userData;
|
||||
createInfo.pNext = &debugCreateInfo;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
createInfo.enabledExtensionCount = extensionCount;
|
||||
createInfo.ppEnabledExtensionNames = extensions;
|
||||
|
||||
VkResult result = vkCreateInstance(&createInfo, NULL, &instance->instance->vk_instance);
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_CREATE_INSTANCE;
|
||||
instance->valid = gnTrue;
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyInstanceFn(gnInstanceHandle instance) {
|
||||
instance->valid = gnFalse;
|
||||
vkDestroyInstance(instance->instance->vk_instance, NULL);
|
||||
}
|
18
projects/apis/vulkan/src/instance/vulkan_instance.h
Normal file
18
projects/apis/vulkan/src/instance/vulkan_instance.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/debugger/gryphn_debugger.h"
|
||||
#include "core/instance/gryphn_instance.h"
|
||||
|
||||
struct gnInstanceMessage {
|
||||
gnMessageSeverity severity;
|
||||
gnMessageType type;
|
||||
gnMessageData data;
|
||||
};
|
||||
|
||||
typedef struct gnPlatformInstance_t {
|
||||
VkInstance vk_instance;
|
||||
VkApplicationInfo appInfo;
|
||||
|
||||
uint16_t instanceMessageCount;
|
||||
struct gnInstanceMessage* instanceMessages;
|
||||
} gnPlatformInstance;
|
@@ -0,0 +1,41 @@
|
||||
#include "vulkan_device_extensions.h"
|
||||
#include "utils/gryphn_bool.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
const char* *vkGetGryphnDeviceExtensions(uint32_t* outCount, VkPhysicalDevice device) {
|
||||
uint32_t count = 1;
|
||||
const char* *extensiosns = malloc(sizeof(const char*) * count);
|
||||
extensiosns[count-1] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
|
||||
|
||||
#ifdef GN_PLATFORM_MACOS
|
||||
count++;
|
||||
extensiosns = realloc(extensiosns, sizeof(const char*) * count);
|
||||
extensiosns[(count - 1)] = "VK_KHR_portability_subset";
|
||||
#endif
|
||||
|
||||
uint32_t extensionCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
|
||||
VkExtensionProperties* vkExtensions = malloc(sizeof(VkExtensionProperties) * extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, vkExtensions);
|
||||
|
||||
gnBool supportsDescriptorPoolOverallocation = gnFalse;
|
||||
for (uint32_t i = 0; i < extensionCount; i++) {
|
||||
if (strcmp(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME, vkExtensions[i].extensionName) == 0) {
|
||||
supportsDescriptorPoolOverallocation = gnTrue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(vkExtensions);
|
||||
|
||||
if (supportsDescriptorPoolOverallocation) {
|
||||
count++;
|
||||
extensiosns = realloc(extensiosns, sizeof(const char*) * count);
|
||||
extensiosns[(count - 1)] = VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
*outCount = count;
|
||||
|
||||
return extensiosns;
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
const char* *vkGetGryphnDeviceExtensions(uint32_t* count, VkPhysicalDevice device);
|
109
projects/apis/vulkan/src/output_device/vulkan_output_device.c
Normal file
109
projects/apis/vulkan/src/output_device/vulkan_output_device.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <output_device/vulkan_physical_device.h>
|
||||
#include <output_device/vulkan_output_devices.h>
|
||||
#include "vulkan_device_extensions.h"
|
||||
#include "core/instance/gryphn_instance.h"
|
||||
#include "commands/command_buffer/vulkan_command_buffer.h"
|
||||
|
||||
gnReturnCode gnCreateOutputDeviceFn(gnOutputDeviceHandle outputDevice, gnInstanceHandle instance, gnOutputDeviceInfo deviceInfo) {
|
||||
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
|
||||
|
||||
VkDeviceQueueCreateInfo* queueCreateInfos = malloc(sizeof(VkDeviceQueueCreateInfo) * deviceInfo.queueInfoCount);
|
||||
float queuePriority = 1.0f;
|
||||
for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
|
||||
queueCreateInfos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfos[i].flags = 0;
|
||||
queueCreateInfos[i].queueFamilyIndex = deviceInfo.queueInfos[i].queueIndex;
|
||||
queueCreateInfos[i].queueCount = deviceInfo.queueInfos[i].queueCount;
|
||||
queueCreateInfos[i].pQueuePriorities = &queuePriority;
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures = {
|
||||
.samplerAnisotropy = VK_TRUE
|
||||
};
|
||||
|
||||
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = deviceInfo.queueInfoCount,
|
||||
.pQueueCreateInfos = queueCreateInfos,
|
||||
.pEnabledFeatures = &deviceFeatures
|
||||
};
|
||||
deviceCreateInfo.ppEnabledExtensionNames = vkGetGryphnDeviceExtensions(&deviceCreateInfo.enabledExtensionCount, deviceInfo.physicalDevice.physicalDevice->device);
|
||||
|
||||
outputDevice->outputDevice->enabledOversizedDescriptorPools = gnFalse;
|
||||
for (int i = 0; i < deviceCreateInfo.enabledExtensionCount; i++)
|
||||
if (strcmp(deviceCreateInfo.ppEnabledExtensionNames[i], VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME) == 0) outputDevice->outputDevice->enabledOversizedDescriptorPools = gnTrue;
|
||||
|
||||
if (instance->debugger == NULL)
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
else {
|
||||
const char* validation_layers[1] = { "VK_LAYER_KHRONOS_validation" };
|
||||
deviceCreateInfo.enabledLayerCount = 1;
|
||||
deviceCreateInfo.ppEnabledLayerNames = validation_layers;
|
||||
}
|
||||
|
||||
if (vkCreateDevice(deviceInfo.physicalDevice.physicalDevice->device, &deviceCreateInfo, NULL, &outputDevice->outputDevice->device) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_DEVICE;
|
||||
|
||||
outputDevice->outputDevice->queues = malloc(sizeof(VkQueue) * deviceInfo.queueInfoCount);
|
||||
for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
|
||||
vkGetDeviceQueue(outputDevice->outputDevice->device, deviceInfo.queueInfos[i].queueIndex, 0, &outputDevice->outputDevice->queues[i]);
|
||||
}
|
||||
|
||||
uint32_t queueCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(
|
||||
deviceInfo.physicalDevice.physicalDevice->device,
|
||||
&queueCount,
|
||||
NULL
|
||||
);
|
||||
|
||||
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * queueCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(
|
||||
deviceInfo.physicalDevice.physicalDevice->device,
|
||||
&queueCount,
|
||||
queueFamilies
|
||||
);
|
||||
|
||||
uint32_t transferQueueIndex = 0;
|
||||
for (int i = 0; i < queueCount; i++) {
|
||||
if ((queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT) {
|
||||
transferQueueIndex = i;
|
||||
vkGetDeviceQueue(outputDevice->outputDevice->device, deviceInfo.queueInfos[i].queueIndex, 0, &outputDevice->outputDevice->transferQueue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = transferQueueIndex
|
||||
};
|
||||
|
||||
if (vkCreateCommandPool(outputDevice->outputDevice->device, &poolInfo, NULL, &outputDevice->outputDevice->transferCommandPool) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_COMMAND_POOL;
|
||||
|
||||
free(queueCreateInfos);
|
||||
free(queueFamilies);
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnWaitForDeviceFn(const gnOutputDeviceHandle device) {
|
||||
vkDeviceWaitIdle(device->outputDevice->device);
|
||||
}
|
||||
|
||||
void gnDestroyOutputDeviceFn(gnOutputDeviceHandle device) {
|
||||
vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL);
|
||||
vkDestroyDevice(device->outputDevice->device, NULL);
|
||||
free(device->outputDevice);
|
||||
}
|
||||
|
||||
|
||||
VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device) {
|
||||
return VkBeginTransferOperation(device->outputDevice->device, device->outputDevice->transferCommandPool);
|
||||
}
|
||||
void gnEndVulkanTransferOperation(gnDevice device, VkCommandBuffer buffer) {
|
||||
VkEndTransferOperation(buffer, device->outputDevice->transferCommandPool, device->outputDevice->transferQueue, device->outputDevice->device);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/output_device/gryphn_output_device.h>
|
||||
|
||||
typedef struct gnPlatformOutputDevice_t {
|
||||
VkDevice device;
|
||||
uint32_t queueCount;
|
||||
VkQueue* queues;
|
||||
|
||||
VkQueue transferQueue;
|
||||
VkCommandPool transferCommandPool;
|
||||
|
||||
gnBool enabledOversizedDescriptorPools;
|
||||
} gnPlatformOutputDevice;
|
||||
|
||||
VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device);
|
||||
void gnEndVulkanTransferOperation(gnDevice device, VkCommandBuffer commandBuffer);
|
@@ -0,0 +1,58 @@
|
||||
#include "vulkan_physical_device.h"
|
||||
#include <instance/vulkan_instance.h>
|
||||
#include <output_device/vulkan_device_extensions.h>
|
||||
#include <vulkan_surface/vulkan_surface.h>
|
||||
|
||||
gnPhysicalDevice* gnGetPhysicalDevicesFn(gnInstanceHandle instance, uint32_t* deviceCount) {
|
||||
vkEnumeratePhysicalDevices(instance->instance->vk_instance, deviceCount, NULL);
|
||||
if (deviceCount == 0)
|
||||
return NULL;
|
||||
|
||||
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * *deviceCount);
|
||||
vkEnumeratePhysicalDevices(instance->instance->vk_instance, deviceCount, physicalDevices);
|
||||
gnPhysicalDevice* outputDevices = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * *deviceCount);
|
||||
|
||||
for (int i = 0; i < *deviceCount; i++) {
|
||||
outputDevices[i].physicalDevice = malloc(sizeof(struct gnPlatformPhysicalDevice_t));
|
||||
outputDevices[i].physicalDevice->device = physicalDevices[i];
|
||||
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(physicalDevices[i], &deviceProperties);
|
||||
outputDevices[i].properties.name = gnCreateString(deviceProperties.deviceName);
|
||||
switch(deviceProperties.deviceType) {
|
||||
case VK_PHYSICAL_DEVICE_TYPE_OTHER: outputDevices[i].properties.deviceType = GN_EXTERNAL_DEVICE;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: outputDevices[i].properties.deviceType = GN_DEDICATED_DEVICE;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_CPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
|
||||
}
|
||||
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &outputDevices[i].queueProperties.queueCount, NULL);
|
||||
|
||||
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * outputDevices[i].queueProperties.queueCount);
|
||||
outputDevices[i].queueProperties.queueProperties = malloc(sizeof(gnQueueProperties) * outputDevices[i].queueProperties.queueCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &outputDevices[i].queueProperties.queueCount, queueFamilies);
|
||||
for (int c = 0; c < outputDevices[i].queueProperties.queueCount; c++) {
|
||||
outputDevices[i].queueProperties.queueProperties[i].queueCount = queueFamilies[i].queueCount;
|
||||
|
||||
gnQueueTypeFlags finalQueueType = 0;
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) finalQueueType |= GN_QUEUE_GRAPHICS;
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT) finalQueueType |= GN_QUEUE_COMPUTE;
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) finalQueueType |= GN_QUEUE_TRANSFER;
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) finalQueueType |= GN_QUEUE_SPARSE_BINDING;
|
||||
outputDevices[i].queueProperties.queueProperties[i].queueType = finalQueueType;
|
||||
}
|
||||
}
|
||||
free(physicalDevices);
|
||||
|
||||
return outputDevices;
|
||||
}
|
||||
|
||||
gnBool gnQueueCanPresentToSurfaceFn(const struct gnPhysicalDevice_t device, uint32_t queueIndex, gnWindowSurfaceHandle windowSurface) {
|
||||
VkBool32 supportsPresent = VK_FALSE;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device.physicalDevice->device, queueIndex, windowSurface->windowSurface->surface, &supportsPresent);
|
||||
if (supportsPresent)
|
||||
return gnTrue;
|
||||
return gnFalse;
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/output_device/gryphn_physical_output_device.h>
|
||||
|
||||
typedef struct gnPlatformPhysicalDevice_t {
|
||||
VkPhysicalDevice device;
|
||||
} gnPlatformPhysicalDevice;
|
@@ -0,0 +1,306 @@
|
||||
#include "vulkan_graphics_pipeline.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "shader_module/vulkan_shader_module.h"
|
||||
#include "renderpass/vulkan_render_pass_descriptor.h"
|
||||
#include "uniforms/vulkan_uniform_layout.h"
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
VkDynamicState vkGryphnDynamicStateToVulkanDynamicState(enum gnDynamicState_e state) {
|
||||
switch (state) {
|
||||
case GN_DYNAMIC_VIEWPORT: return VK_DYNAMIC_STATE_VIEWPORT;
|
||||
case GN_DYNAMIC_SCISSOR: return VK_DYNAMIC_STATE_SCISSOR;
|
||||
|
||||
case GN_DYNAMIC_STATE_MAX: return VK_DYNAMIC_STATE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
VkPrimitiveTopology vkGryphnPrimitiveType(gnPrimitiveType primitiveType) {
|
||||
switch (primitiveType) {
|
||||
case GN_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
|
||||
case GN_PRIMITIVE_LINES: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||
case GN_PRIMITIVE_LINE_STRIP: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
||||
case GN_PRIMITIVE_TRIANGLES: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
case GN_PRIMITIVE_TRIANGLE_STRIP: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
}
|
||||
}
|
||||
|
||||
VkPolygonMode vkGryphnPolygonMode(enum gnFillMode_e fillMode) {
|
||||
switch (fillMode) {
|
||||
case GN_FILL_MODE_FILL: return VK_POLYGON_MODE_FILL;
|
||||
case GN_FILL_MODE_LINE: return VK_POLYGON_MODE_LINE;
|
||||
case GN_FILL_MODE_POINT: return VK_POLYGON_MODE_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
VkCullModeFlags vkGryphnCullMode(enum gnCullFace_e face) {
|
||||
switch (face) {
|
||||
case GN_CULL_FACE_NONE: return VK_CULL_MODE_NONE;
|
||||
case GN_CULL_FACE_BACK: return VK_CULL_MODE_BACK_BIT;
|
||||
case GN_CULL_FACE_FRONT: return VK_CULL_MODE_FRONT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
VkBlendFactor vkGryphnBlendFactor(enum gnBlendFactor_e factor) {
|
||||
switch (factor) {
|
||||
case GN_BLEND_FACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
|
||||
case GN_BLEND_FACTOR_ONE: return VK_BLEND_FACTOR_ONE;
|
||||
case GN_BLEND_FACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
case GN_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
VkBlendOp vkGryphnBlendOperation(enum gnBlendOperation_e operation) {
|
||||
switch(operation) {
|
||||
case GN_OPERATION_ADD: return VK_BLEND_OP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
VkFormat vkGryphnVertexFormat(gnVertexFormat format) {
|
||||
switch (format) {
|
||||
case GN_FLOAT2: return VK_FORMAT_R32G32_SFLOAT;
|
||||
case GN_FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
VkCompareOp vkGrypnCompareOperation(gnCompareOperation operation) {
|
||||
switch(operation) {
|
||||
case GN_COMPARE_NEVER: return VK_COMPARE_OP_NEVER;
|
||||
case GN_COMPARE_LESS: return VK_COMPARE_OP_LESS;
|
||||
case GN_COMPARE_EQUAL: return VK_COMPARE_OP_EQUAL;
|
||||
case GN_COMPARE_LESS_OR_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||
case GN_COMPARE_GREATER: return VK_COMPARE_OP_GREATER;
|
||||
case GN_COMPARE_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL;
|
||||
case GN_COMPARE_GREATER_OR_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
case GN_COMPARE_ALWAYS: return VK_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
VkStencilOp vkGryphnStencilOperation(gnStencilOperation operation) {
|
||||
switch(operation) {
|
||||
case GN_STENCIL_KEEP: return VK_STENCIL_OP_KEEP;
|
||||
case GN_STENCIL_ZERO: return VK_STENCIL_OP_ZERO;
|
||||
case GN_STENCIL_REPLACE: return VK_STENCIL_OP_REPLACE;
|
||||
case GN_STENCIL_INCREMENT_AND_CLAMP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
||||
case GN_STENCIL_DECREMENT_AND_CLAMP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
||||
case GN_STENCIL_INVERT: return VK_STENCIL_OP_INVERT;
|
||||
case GN_STENCIL_INCREMENT_AND_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
|
||||
case GN_STENCIL_DECREMENT_AND_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
|
||||
}
|
||||
}
|
||||
|
||||
gnReturnCode gnCreateGraphicsPipelineFn(gnGraphicsPipeline graphicsPipeline, gnDevice device, gnGraphicsPipelineInfo info) {
|
||||
graphicsPipeline->graphicsPipeline = malloc(sizeof(gnPlatformGraphicsPipeline));
|
||||
for (int i = 0; i < GN_DYNAMIC_STATE_MAX; i++) graphicsPipeline->graphicsPipeline->isDynamic[i] = gnFalse;
|
||||
|
||||
graphicsPipeline->graphicsPipeline->dynamicStates = malloc(sizeof(VkDynamicState) * info.dynamicState.dynamicStateCount);
|
||||
for (int i = 0; i < info.dynamicState.dynamicStateCount; i++) {
|
||||
graphicsPipeline->graphicsPipeline->isDynamic[info.dynamicState.dynamicStates[i]] = gnTrue;
|
||||
graphicsPipeline->graphicsPipeline->dynamicStates[i] = vkGryphnDynamicStateToVulkanDynamicState(info.dynamicState.dynamicStates[i]);
|
||||
}
|
||||
|
||||
graphicsPipeline->graphicsPipeline->dynamicState = (VkPipelineDynamicStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.dynamicStateCount = info.dynamicState.dynamicStateCount,
|
||||
.pDynamicStates = graphicsPipeline->graphicsPipeline->dynamicStates
|
||||
};
|
||||
|
||||
int vertexAttributeCount = 0;
|
||||
graphicsPipeline->graphicsPipeline->bindingDescriptions = malloc(sizeof(VkVertexInputBindingDescription) * info.shaderInputLayout.bufferCount);
|
||||
for (int i = 0; i < info.shaderInputLayout.bufferCount; i++) {
|
||||
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].binding = info.shaderInputLayout.bufferAttributes[i].binding;
|
||||
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].stride = info.shaderInputLayout.bufferAttributes[i].size;
|
||||
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
vertexAttributeCount += info.shaderInputLayout.bufferAttributes[i].attributeCount;
|
||||
}
|
||||
graphicsPipeline->graphicsPipeline->attributeDescriptions = malloc(sizeof(VkVertexInputAttributeDescription) * vertexAttributeCount);
|
||||
for (int i = 0, j = 0; j < info.shaderInputLayout.bufferCount; j++) {
|
||||
for (int k = 0; k < info.shaderInputLayout.bufferAttributes[j].attributeCount; k++) {
|
||||
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].binding = j;
|
||||
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].location = info.shaderInputLayout.bufferAttributes[j].attributes[k].location;
|
||||
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].offset = info.shaderInputLayout.bufferAttributes[j].attributes[k].offset;
|
||||
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].format = vkGryphnVertexFormat(info.shaderInputLayout.bufferAttributes[j].attributes[k].format);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
graphicsPipeline->graphicsPipeline->vertexInfo = (VkPipelineVertexInputStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = info.shaderInputLayout.bufferCount,
|
||||
.pVertexBindingDescriptions = graphicsPipeline->graphicsPipeline->bindingDescriptions,
|
||||
.vertexAttributeDescriptionCount = vertexAttributeCount,
|
||||
.pVertexAttributeDescriptions = graphicsPipeline->graphicsPipeline->attributeDescriptions
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->inputAssembly = (VkPipelineInputAssemblyStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = vkGryphnPrimitiveType(info.primitiveType),
|
||||
.primitiveRestartEnable = VK_FALSE
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->viewportState = (VkPipelineViewportStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1
|
||||
};
|
||||
|
||||
if (!graphicsPipeline->graphicsPipeline->isDynamic[GN_DYNAMIC_VIEWPORT]) {
|
||||
graphicsPipeline->graphicsPipeline->viewport = (VkViewport) {
|
||||
.x = info.viewport.position.x,
|
||||
.y = info.viewport.position.y,
|
||||
.width = info.viewport.size.x,
|
||||
.height = info.viewport.size.y,
|
||||
.minDepth = info.viewport.minDepth,
|
||||
.maxDepth = info.viewport.maxDepth
|
||||
};
|
||||
graphicsPipeline->graphicsPipeline->viewportState.pViewports = &graphicsPipeline->graphicsPipeline->viewport;
|
||||
}
|
||||
|
||||
if (!graphicsPipeline->graphicsPipeline->isDynamic[GN_DYNAMIC_SCISSOR]) {
|
||||
graphicsPipeline->graphicsPipeline->scissor = (VkRect2D){
|
||||
.offset = { info.scissor.position.x, info.scissor.position.y },
|
||||
.extent = { info.scissor.size.x, info.scissor.size.y }
|
||||
};
|
||||
graphicsPipeline->graphicsPipeline->viewportState.pScissors = &graphicsPipeline->graphicsPipeline->scissor;
|
||||
}
|
||||
|
||||
graphicsPipeline->graphicsPipeline->rasterizer = (VkPipelineRasterizationStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
.polygonMode = vkGryphnPolygonMode(info.fillMode),
|
||||
.lineWidth = 1.0f,
|
||||
.frontFace = ( info.cullMode.direction == GN_DIRECTION_CLOCK_WISE ) ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE,
|
||||
.cullMode = vkGryphnCullMode(info.cullMode.face),
|
||||
.depthBiasEnable = VK_FALSE,
|
||||
.depthBiasConstantFactor = 0.0f,
|
||||
.depthBiasClamp = 0.0f,
|
||||
.depthBiasSlopeFactor = 0.0f
|
||||
};
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampling = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.sampleShadingEnable = VK_FALSE,
|
||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->colorBlendAttachment = (VkPipelineColorBlendAttachmentState){
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
||||
.blendEnable = ( info.colorBlending.enable == gnTrue ) ? VK_TRUE : VK_FALSE,
|
||||
.srcColorBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceColorBlendFactor),
|
||||
.dstColorBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationColorBlendFactor),
|
||||
.colorBlendOp = vkGryphnBlendOperation(info.colorBlending.colorBlendOperation),
|
||||
.srcAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceAlphaBlendFactor),
|
||||
.dstAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationAlphaBlendFactor),
|
||||
.alphaBlendOp = vkGryphnBlendOperation(info.colorBlending.alphaBlendOperation),
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->colorBlending = (VkPipelineColorBlendStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||
.logicOpEnable = VK_FALSE,
|
||||
.logicOp = VK_LOGIC_OP_COPY,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &graphicsPipeline->graphicsPipeline->colorBlendAttachment,
|
||||
.blendConstants[0] = 0.0f,
|
||||
.blendConstants[1] = 0.0f,
|
||||
.blendConstants[2] = 0.0f,
|
||||
.blendConstants[3] = 0.0f
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->depthStencil = (VkPipelineDepthStencilStateCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.depthWriteEnable = info.depthStencil.depthWriteEnable,
|
||||
.depthTestEnable = info.depthStencil.depthWriteEnable,
|
||||
.depthCompareOp = vkGrypnCompareOperation(info.depthStencil.operation),
|
||||
.depthBoundsTestEnable = VK_FALSE,
|
||||
.stencilTestEnable = info.depthStencil.stencilTestEnable,
|
||||
};
|
||||
|
||||
if (info.depthStencil.stencilTestEnable) {
|
||||
graphicsPipeline->graphicsPipeline->depthStencil.front = (VkStencilOpState){
|
||||
.failOp = vkGryphnStencilOperation(info.depthStencil.front.failOperation),
|
||||
.passOp = vkGryphnStencilOperation(info.depthStencil.front.passOperation),
|
||||
.depthFailOp = vkGryphnStencilOperation(info.depthStencil.front.depthFailOperation),
|
||||
.compareOp = vkGrypnCompareOperation(info.depthStencil.front.compareOperation),
|
||||
.compareMask = info.depthStencil.front.compareMask,
|
||||
.writeMask = info.depthStencil.front.writeMask,
|
||||
.reference = info.depthStencil.front.reference,
|
||||
};
|
||||
|
||||
graphicsPipeline->graphicsPipeline->depthStencil.back = (VkStencilOpState){
|
||||
.failOp = vkGryphnStencilOperation(info.depthStencil.back.failOperation),
|
||||
.passOp = vkGryphnStencilOperation(info.depthStencil.back.passOperation),
|
||||
.depthFailOp = vkGryphnStencilOperation(info.depthStencil.back.depthFailOperation),
|
||||
.compareOp = vkGrypnCompareOperation(info.depthStencil.back.compareOperation),
|
||||
.compareMask = info.depthStencil.back.compareMask,
|
||||
.writeMask = info.depthStencil.back.writeMask,
|
||||
.reference = info.depthStencil.back.reference,
|
||||
};
|
||||
}
|
||||
|
||||
graphicsPipeline->graphicsPipeline->setCount = info.uniformLayout.setCount;
|
||||
graphicsPipeline->graphicsPipeline->sets = malloc(sizeof(VkDescriptorSetLayout) * info.uniformLayout.setCount);
|
||||
for (int i = 0; i < info.uniformLayout.setCount; i++) graphicsPipeline->graphicsPipeline->sets[i] = vkGryphnCreateSetLayouts(&info.uniformLayout.sets[i], device->outputDevice->device);
|
||||
|
||||
graphicsPipeline->graphicsPipeline->ranges = malloc(sizeof(VkPushConstantRange) * info.uniformLayout.pushConstantCount);
|
||||
for (int i = 0; i < info.uniformLayout.pushConstantCount; i++) {
|
||||
graphicsPipeline->graphicsPipeline->ranges[i] = (VkPushConstantRange) {
|
||||
.offset = info.uniformLayout.pushConstants[i].offset,
|
||||
.size = info.uniformLayout.pushConstants[i].size,
|
||||
.stageFlags = vkGryphnShaderModuleStage(info.uniformLayout.pushConstants[i].stage)
|
||||
};
|
||||
}
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = graphicsPipeline->graphicsPipeline->setCount,
|
||||
pipelineLayoutInfo.pSetLayouts = graphicsPipeline->graphicsPipeline->sets,
|
||||
pipelineLayoutInfo.pushConstantRangeCount = info.uniformLayout.pushConstantCount,
|
||||
pipelineLayoutInfo.pPushConstantRanges = graphicsPipeline->graphicsPipeline->ranges
|
||||
};
|
||||
|
||||
if (vkCreatePipelineLayout(device->outputDevice->device, &pipelineLayoutInfo, NULL, &graphicsPipeline->graphicsPipeline->pipelineLayout) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_UNIFORM_LAYOUT;
|
||||
|
||||
graphicsPipeline->graphicsPipeline->modules = malloc(sizeof(VkPipelineShaderStageCreateInfo) * info.shaderModuleCount);
|
||||
for (int i = 0; i < info.shaderModuleCount; i++) {
|
||||
graphicsPipeline->graphicsPipeline->modules[i] = info.shaderModules[i]->shaderModule->shaderStageInfo;
|
||||
}
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.stageCount = info.shaderModuleCount,
|
||||
.pStages = graphicsPipeline->graphicsPipeline->modules,
|
||||
.pVertexInputState = &graphicsPipeline->graphicsPipeline->vertexInfo,
|
||||
.pInputAssemblyState = &graphicsPipeline->graphicsPipeline->inputAssembly,
|
||||
.pViewportState = &graphicsPipeline->graphicsPipeline->viewportState,
|
||||
.pRasterizationState = &graphicsPipeline->graphicsPipeline->rasterizer,
|
||||
.pMultisampleState = &multisampling,
|
||||
.pDepthStencilState = &graphicsPipeline->graphicsPipeline->depthStencil,
|
||||
.pColorBlendState = &graphicsPipeline->graphicsPipeline->colorBlending,
|
||||
.pDynamicState = &graphicsPipeline->graphicsPipeline->dynamicState,
|
||||
.layout = graphicsPipeline->graphicsPipeline->pipelineLayout,
|
||||
.renderPass = info.renderPassDescriptor->renderPassDescriptor->renderPass,
|
||||
.subpass = info.subpassIndex,
|
||||
.basePipelineHandle = VK_NULL_HANDLE,
|
||||
.basePipelineIndex = -1,
|
||||
};
|
||||
|
||||
if (vkCreateGraphicsPipelines(device->outputDevice->device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &graphicsPipeline->graphicsPipeline->graphicsPipeline) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_GRAPHICS_PIPELINE;
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyGraphicsPipelineFn(struct gnGraphicsPipeline_t *graphicsPipeline) {
|
||||
free(graphicsPipeline->graphicsPipeline->dynamicStates);
|
||||
free(graphicsPipeline->graphicsPipeline->bindingDescriptions);
|
||||
free(graphicsPipeline->graphicsPipeline->attributeDescriptions);
|
||||
free(graphicsPipeline->graphicsPipeline->ranges);
|
||||
for (int i = 0; i < graphicsPipeline->graphicsPipeline->setCount; i++)
|
||||
vkDestroyDescriptorSetLayout(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->sets[i], NULL);
|
||||
free(graphicsPipeline->graphicsPipeline->modules);
|
||||
|
||||
vkDestroyPipeline(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->graphicsPipeline, NULL);
|
||||
vkDestroyPipelineLayout(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->pipelineLayout, NULL);
|
||||
free(graphicsPipeline->graphicsPipeline);
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformGraphicsPipeline_t {
|
||||
VkPipelineDynamicStateCreateInfo dynamicState;
|
||||
gnBool isDynamic[GN_DYNAMIC_STATE_MAX];
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInfo;
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly;
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
VkPipelineViewportStateCreateInfo viewportState;
|
||||
VkPipelineRasterizationStateCreateInfo rasterizer;
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment;
|
||||
VkPipelineColorBlendStateCreateInfo colorBlending;
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencil;
|
||||
|
||||
// gnBool createdPipelineLayout;
|
||||
uint32_t setCount;
|
||||
VkDescriptorSetLayout* sets;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
|
||||
|
||||
VkPipeline graphicsPipeline;
|
||||
|
||||
|
||||
|
||||
// memory that needs to be freeed
|
||||
VkDynamicState* dynamicStates;
|
||||
VkVertexInputBindingDescription* bindingDescriptions;
|
||||
VkVertexInputAttributeDescription* attributeDescriptions;
|
||||
VkPipelineShaderStageCreateInfo* modules;
|
||||
VkPushConstantRange* ranges;
|
||||
} gnPlatformGraphicsPipeline;
|
29
projects/apis/vulkan/src/present/vulkan_present.c
Normal file
29
projects/apis/vulkan/src/present/vulkan_present.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "core/present/gryphn_present.h"
|
||||
#include "sync/semaphore/vulkan_semaphore.h"
|
||||
#include "presentation_queue/vulkan_presentation_queue.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnPresentFn(struct gnOutputDevice_t* device, struct gnPresentInfo_t info) {
|
||||
VkSemaphore* waitSemaphores = malloc(sizeof(VkSemaphore) * info.waitCount);
|
||||
for (int i = 0; i < info.waitCount; i++) waitSemaphores[i] = info.waitSemaphores[i]->semaphore->semaphore;
|
||||
|
||||
VkSwapchainKHR* swapchains = malloc(sizeof(VkSwapchainKHR) * info.presentationQueueCount);
|
||||
for (int i = 0; i < info.presentationQueueCount; i++) swapchains[i] = info.presentationQueues[i]->presentationQueue->swapChain;
|
||||
|
||||
VkPresentInfoKHR presentInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = info.waitCount,
|
||||
.pWaitSemaphores = waitSemaphores,
|
||||
.swapchainCount = info.presentationQueueCount,
|
||||
.pSwapchains = swapchains,
|
||||
.pImageIndices = info.imageIndices
|
||||
};
|
||||
|
||||
VkQueue queue;
|
||||
vkGetDeviceQueue(device->outputDevice->device, info.queueIndex, 0, &queue);
|
||||
|
||||
VkResult result = vkQueuePresentKHR(queue, &presentInfo);
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) return GN_OUT_OF_DATE_PRESENTATION_QUEUE;
|
||||
if (result == VK_SUBOPTIMAL_KHR) return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
|
||||
return GN_SUCCESS;
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
#include <presentation_queue/vulkan_presentation_queue.h>
|
||||
#include "vulkan_swapchain_support.h"
|
||||
#include <output_device/vulkan_physical_device.h>
|
||||
#include "vulkan_surface/vulkan_surface.h"
|
||||
#include "core/debugger/gryphn_debugger.h"
|
||||
#include "textures/vulkan_texture.h"
|
||||
#include "sync/semaphore/vulkan_semaphore.h"
|
||||
#include "stdio.h"
|
||||
|
||||
gnReturnCode gnCreatePresentationQueueFn(gnPresentationQueueHandle presentationQueue, const gnOutputDeviceHandle device, struct gnPresentationQueueInfo_t presentationInfo) {
|
||||
presentationQueue->presentationQueue = malloc(sizeof(struct gnPlatformPresentationQueue_t));
|
||||
|
||||
vkSwapchainSupportDetails details = vkGetSwapchainSupport(device->physicalDevice.physicalDevice->device, presentationInfo.surface->windowSurface->surface);
|
||||
|
||||
if (details.capabilities.currentExtent.width != presentationInfo.imageSize.x || details.capabilities.currentExtent.height != presentationInfo.imageSize.y) {
|
||||
gnDebuggerSetErrorMessage(device->instance->debugger,
|
||||
(gnMessageData){
|
||||
.message = gnCreateString("Image size is unsupposed for presentation queue")
|
||||
}
|
||||
);
|
||||
|
||||
presentationInfo.imageSize = (gnUInt2){ details.capabilities.currentExtent.width, details.capabilities.currentExtent.height };
|
||||
}
|
||||
|
||||
if (details.formatCount == 0) {
|
||||
gnDebuggerSetErrorMessage(device->instance->debugger,
|
||||
(gnMessageData){
|
||||
.message = gnCreateString("Format count for presentation queue is zero")
|
||||
}
|
||||
);
|
||||
return GN_NO_SUPPORTED_FORMATS;
|
||||
}
|
||||
if (details.presentModeCount == 0) {
|
||||
gnDebuggerSetErrorMessage(device->instance->debugger,
|
||||
(gnMessageData){
|
||||
.message = gnCreateString("Present mode count for presentation queue is zero")
|
||||
}
|
||||
);
|
||||
return GN_NO_SUPPORTED_PRESENT_MODES;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
VkFormat convertedFormat = vkGryphnFormatToVulkanFormat(presentationInfo.format.format);
|
||||
VkColorSpaceKHR convertedColorSpace = vkGryphnColorSpaceToVulkanColorSpace(presentationInfo.format.colorSpace);
|
||||
for (int i = 0; i < details.formatCount; i++) {
|
||||
if (details.formats[i].format == convertedFormat && details.formats[i].colorSpace == convertedColorSpace) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
|
||||
.message = gnCreateString("Unsupported color format passed to Gryphn")
|
||||
});
|
||||
return GN_UNKNOWN_IMAGE_FORMAT;
|
||||
}
|
||||
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
VkExtent2D extent = {
|
||||
.width = presentationInfo.imageSize.x,
|
||||
.height = presentationInfo.imageSize.y
|
||||
};
|
||||
|
||||
VkSwapchainCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
createInfo.surface = presentationInfo.surface->windowSurface->surface;
|
||||
|
||||
createInfo.minImageCount = presentationInfo.minImageCount;
|
||||
createInfo.imageFormat = details.formats[index].format;
|
||||
createInfo.imageColorSpace = details.formats[index].colorSpace;
|
||||
createInfo.imageExtent = extent;
|
||||
createInfo.imageArrayLayers = 1;
|
||||
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
if (presentationInfo.imageSharingMode == GN_SHARING_MODE_EXCLUSIVE)
|
||||
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
else
|
||||
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
createInfo.queueFamilyIndexCount = presentationInfo.queueFamilyCount;
|
||||
createInfo.pQueueFamilyIndices = presentationInfo.queueFamilies;
|
||||
createInfo.preTransform = details.capabilities.currentTransform;
|
||||
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
createInfo.presentMode = presentMode;
|
||||
createInfo.clipped = VK_TRUE;
|
||||
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||
|
||||
VkResult result = vkCreateSwapchainKHR(device->outputDevice->device, &createInfo, NULL, &presentationQueue->presentationQueue->swapChain);
|
||||
if (result == VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) return GN_WINDOW_IN_USE;
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_PRESENTATION_QUEUE;
|
||||
|
||||
vkGetSwapchainImagesKHR(device->outputDevice->device, presentationQueue->presentationQueue->swapChain, &presentationQueue->imageCount, NULL);
|
||||
presentationQueue->presentationQueue->swapChainImages = malloc(sizeof(VkImage) * presentationQueue->imageCount);
|
||||
presentationQueue->presentationQueue->swapChainImageViews = malloc(sizeof(VkImageView) * presentationQueue->imageCount);
|
||||
vkGetSwapchainImagesKHR(device->outputDevice->device, presentationQueue->presentationQueue->swapChain, &presentationQueue->imageCount, presentationQueue->presentationQueue->swapChainImages);
|
||||
|
||||
VkImageViewCreateInfo imageViewCreateInfo = {};
|
||||
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewCreateInfo.format = convertedFormat;
|
||||
imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
||||
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
presentationQueue->images = malloc(sizeof(gnTextureHandle) * presentationQueue->imageCount);
|
||||
for (int i = 0; i < presentationQueue->imageCount; i++) {
|
||||
presentationQueue->images[i] = malloc(sizeof(struct gnTexture_t));
|
||||
presentationQueue->images[i]->texture = malloc(sizeof(gnPlatformTexture));
|
||||
imageViewCreateInfo.image = presentationQueue->presentationQueue->swapChainImages[i];
|
||||
if (vkCreateImageView(device->outputDevice->device, &imageViewCreateInfo, NULL, &presentationQueue->presentationQueue->swapChainImageViews[i]) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_IMAGE_VIEW;
|
||||
|
||||
presentationQueue->images[i]->texture->image.image = presentationQueue->presentationQueue->swapChainImages[i];
|
||||
presentationQueue->images[i]->texture->image.imageView = presentationQueue->presentationQueue->swapChainImageViews[i];
|
||||
}
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
gnReturnCode gnPresentationQueueGetImageFn(gnPresentationQueueHandle presentationQueue, uint64_t timeout, struct gnSemaphore_t* semaphore, uint32_t* imageIndex) {
|
||||
VkResult result = vkAcquireNextImageKHR(
|
||||
presentationQueue->outputDevice->outputDevice->device,
|
||||
presentationQueue->presentationQueue->swapChain,
|
||||
timeout, semaphore->semaphore->semaphore, VK_NULL_HANDLE, imageIndex);
|
||||
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) return GN_OUT_OF_DATE_PRESENTATION_QUEUE;
|
||||
if (result == VK_SUBOPTIMAL_KHR) return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyPresentationQueueFn(gnPresentationQueueHandle queue) {
|
||||
for (int i = 0; i < queue->imageCount; i++)
|
||||
vkDestroyImageView(queue->outputDevice->outputDevice->device, queue->presentationQueue->swapChainImageViews[i], NULL);
|
||||
vkDestroySwapchainKHR(queue->outputDevice->outputDevice->device, queue->presentationQueue->swapChain, NULL);
|
||||
free(queue->presentationQueue->swapChainImageViews);
|
||||
free(queue->presentationQueue->swapChainImages);
|
||||
free(queue->presentationQueue);
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "core/presentation_queue/gryphn_presentation_queue.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformPresentationQueue_t {
|
||||
VkSwapchainKHR swapChain;
|
||||
|
||||
VkImage* swapChainImages;
|
||||
VkImageView* swapChainImageViews;
|
||||
} gnPlatformPresentationQueue;
|
@@ -0,0 +1,35 @@
|
||||
#include "vulkan_swapchain_support.h"
|
||||
|
||||
struct vkSwapchainSupportDetails_t vkGetSwapchainSupport(
|
||||
const VkPhysicalDevice device,
|
||||
const VkSurfaceKHR surface
|
||||
) {
|
||||
struct vkSwapchainSupportDetails_t details;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
|
||||
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &details.formatCount, NULL);
|
||||
if (details.formatCount > 0) {
|
||||
details.formats = malloc(sizeof(VkSurfaceFormatKHR) * details.formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &details.formatCount, details.formats);
|
||||
}
|
||||
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &details.presentModeCount, NULL);
|
||||
if (details.presentModeCount > 0) {
|
||||
details.presentModes = malloc(sizeof(VkPresentModeKHR) * details.presentModeCount);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &details.presentModeCount, details.presentModes);
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
struct vkSwapchainDetails_t vkGetSwapchainDetails(
|
||||
const struct vkSwapchainSupportDetails_t supportDetails
|
||||
) {
|
||||
struct vkSwapchainDetails_t details;
|
||||
|
||||
for (int i = 0; i < supportDetails.formatCount; i++) {
|
||||
// if (supportDetails.)
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <output_device/vulkan_output_devices.h>
|
||||
|
||||
typedef struct vkSwapchainSupportDetails_t {
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
uint32_t formatCount;
|
||||
VkSurfaceFormatKHR* formats;
|
||||
|
||||
uint32_t presentModeCount;
|
||||
VkPresentModeKHR* presentModes;
|
||||
} vkSwapchainSupportDetails;
|
||||
|
||||
typedef struct vkSwapchainDetails_t {
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
} vkSwapchainDetails;
|
||||
|
||||
struct vkSwapchainSupportDetails_t vkGetSwapchainSupport(
|
||||
const VkPhysicalDevice device,
|
||||
const VkSurfaceKHR surface
|
||||
);
|
||||
|
||||
struct vkSwapchainDetails_t vkGetSwapchainDetails(
|
||||
const struct vkSwapchainSupportDetails_t supportDetails
|
||||
);
|
@@ -0,0 +1,135 @@
|
||||
#include "vulkan_render_pass_descriptor.h"
|
||||
#include "vulkan_surface/vulkan_surface.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "stdio.h"
|
||||
|
||||
VkAttachmentLoadOp vkGryphnLoadOperation(gnLoadOperation loadOperation) {
|
||||
switch(loadOperation) {
|
||||
case GN_LOAD_OPERATION_LOAD: return VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
case GN_LOAD_OPERATION_CLEAR: return VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
case GN_LOAD_OPERATION_DONT_CARE: return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
}
|
||||
}
|
||||
|
||||
VkAttachmentStoreOp vkGryphnStoreOperation(gnStoreOperation storeOperation) {
|
||||
switch (storeOperation) {
|
||||
case GN_STORE_OPERATION_STORE: return VK_ATTACHMENT_STORE_OP_STORE;
|
||||
case GN_STORE_OPERATION_DONT_CARE: return VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageLayout vkGryphnImageLayout(gnImageLayout layout) {
|
||||
switch(layout) {
|
||||
case GN_LAYOUT_UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
case GN_LAYOUT_PRESENTATION_QUEUE_IMAGE: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
case GN_LAYOUT_TRANSFER_DESTINATION: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
case GN_LAYOUT_COLOR_ATTACHMENT: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
case GN_LAYOUT_DEPTH_STENCIL: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
VkPipelineStageFlags vkGryphnRenderPassStage(gnRenderPassStage stage) {
|
||||
VkPipelineStageFlags flags = 0;
|
||||
if ((stage & GN_COLOR_ATTACHMENT_OUTPUT) == GN_COLOR_ATTACHMENT_OUTPUT) flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
if ((stage & GN_EARLY_FRAGMENT_TEST) == GN_EARLY_FRAGMENT_TEST) flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
return flags;
|
||||
}
|
||||
|
||||
VkAccessFlags vkGryphnRenderPassAccess(gnRenderPassAccess access) {
|
||||
VkAccessFlags flags = 0;
|
||||
if ((flags & GN_COLOR_ATTACHMENT_WRITE) == GN_COLOR_ATTACHMENT_WRITE) flags |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
if ((flags & GN_DEPTH_STENCIL_WRITE) == GN_DEPTH_STENCIL_WRITE) flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
return flags;
|
||||
}
|
||||
|
||||
gnReturnCode gnCreateRenderPassDescriptorFn(struct gnRenderPassDescriptor_t* renderPass, struct gnOutputDevice_t* device, gnRenderPassDescriptorInfo info) {
|
||||
renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor));
|
||||
|
||||
renderPass->renderPassDescriptor->attachmentCount = info.attachmentCount;
|
||||
renderPass->renderPassDescriptor->attachments = malloc(sizeof(VkAttachmentDescription) * info.attachmentCount);
|
||||
for (int i = 0; i < info.attachmentCount; i++) {
|
||||
renderPass->renderPassDescriptor->attachments[i].format = vkGryphnFormatToVulkanFormat(info.attachmentInfos[i].format);
|
||||
renderPass->renderPassDescriptor->attachments[i].flags = 0;
|
||||
renderPass->renderPassDescriptor->attachments[i].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
renderPass->renderPassDescriptor->attachments[i].loadOp = vkGryphnLoadOperation(info.attachmentInfos[i].loadOperation);
|
||||
renderPass->renderPassDescriptor->attachments[i].storeOp = vkGryphnStoreOperation(info.attachmentInfos[i].storeOperation);
|
||||
|
||||
renderPass->renderPassDescriptor->attachments[i].stencilLoadOp = vkGryphnLoadOperation(info.attachmentInfos[i].stencilLoadOperation);
|
||||
renderPass->renderPassDescriptor->attachments[i].stencilStoreOp = vkGryphnStoreOperation(info.attachmentInfos[i].stencilStoreOperation);
|
||||
|
||||
renderPass->renderPassDescriptor->attachments[i].initialLayout = vkGryphnImageLayout(info.attachmentInfos[i].initialLayout);
|
||||
renderPass->renderPassDescriptor->attachments[i].finalLayout = vkGryphnImageLayout(info.attachmentInfos[i].finalLayout);
|
||||
}
|
||||
|
||||
renderPass->renderPassDescriptor->subpassCount = info.subpassCount;
|
||||
renderPass->renderPassDescriptor->subpasses = malloc(sizeof(VkSubpassDescription) * info.subpassCount);
|
||||
renderPass->renderPassDescriptor->colorAttachments = malloc(sizeof(VkAttachmentReference*) * info.subpassCount);
|
||||
renderPass->renderPassDescriptor->depthAttachments = malloc(sizeof(VkAttachmentReference) * info.subpassCount);
|
||||
|
||||
for (int i = 0; i < info.subpassCount; i++) {
|
||||
renderPass->renderPassDescriptor->colorAttachments[i] = malloc(sizeof(VkAttachmentReference) * info.subpassInfos[i].colorAttachmentCount);
|
||||
|
||||
for (int c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) {
|
||||
renderPass->renderPassDescriptor->colorAttachments[i][c] = (VkAttachmentReference){
|
||||
.attachment = info.subpassInfos[i].colorAttachments[c].index,
|
||||
.layout = vkGryphnImageLayout(info.subpassInfos[i].colorAttachments[c].imageLayout)
|
||||
};
|
||||
}
|
||||
|
||||
renderPass->renderPassDescriptor->subpasses[i] = (VkSubpassDescription){
|
||||
.flags = 0,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.colorAttachmentCount = info.subpassInfos[i].colorAttachmentCount,
|
||||
.pColorAttachments = renderPass->renderPassDescriptor->colorAttachments[i]
|
||||
};
|
||||
|
||||
if (info.subpassInfos[i].depthAttachment != NULL) {
|
||||
renderPass->renderPassDescriptor->depthAttachments[i] = (VkAttachmentReference){
|
||||
.attachment = info.subpassInfos[i].depthAttachment->index,
|
||||
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||
};
|
||||
renderPass->renderPassDescriptor->subpasses[i].pDepthStencilAttachment = &renderPass->renderPassDescriptor->depthAttachments[i];
|
||||
}
|
||||
}
|
||||
|
||||
renderPass->renderPassDescriptor->dependencies = malloc(sizeof(VkSubpassDependency) * info.dependencyCount);
|
||||
for (int i = 0; i < info.dependencyCount; i++) {
|
||||
renderPass->renderPassDescriptor->dependencies[i] = (VkSubpassDependency) {
|
||||
.srcSubpass = (info.dependencies[i].source == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].source,
|
||||
.dstSubpass = (info.dependencies[i].destination == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].destination,
|
||||
.srcStageMask = vkGryphnRenderPassStage(info.dependencies[i].soruceStageMask),
|
||||
.srcAccessMask = vkGryphnRenderPassAccess(info.dependencies[i].sourceAccessMask),
|
||||
.dstStageMask = vkGryphnRenderPassStage(info.dependencies[i].destinationStageMask),
|
||||
.dstAccessMask = vkGryphnRenderPassAccess(info.dependencies[i].destinationAccessMask)
|
||||
};
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo renderPassInfo = (VkRenderPassCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.attachmentCount = info.attachmentCount,
|
||||
.pAttachments = renderPass->renderPassDescriptor->attachments,
|
||||
.subpassCount = info.subpassCount,
|
||||
.pSubpasses = renderPass->renderPassDescriptor->subpasses,
|
||||
.dependencyCount = info.dependencyCount,
|
||||
.pDependencies = renderPass->renderPassDescriptor->dependencies,
|
||||
};
|
||||
|
||||
if (vkCreateRenderPass(device->outputDevice->device, &renderPassInfo, NULL, &renderPass->renderPassDescriptor->renderPass) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_RENDER_PASS;
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void gnDestroyRenderPassDescriptorFn(gnRenderPassDescriptor renderPass) {
|
||||
vkDestroyRenderPass(renderPass->device->outputDevice->device, renderPass->renderPassDescriptor->renderPass, NULL);
|
||||
|
||||
|
||||
free(renderPass->renderPassDescriptor->attachments);
|
||||
free(renderPass->renderPassDescriptor->subpasses);
|
||||
free(renderPass->renderPassDescriptor->dependencies);
|
||||
free(renderPass->renderPassDescriptor->depthAttachments);
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "core/renderpass/gryphn_render_pass_descriptor.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformRenderPassDescriptor_t {
|
||||
VkRenderPass renderPass;
|
||||
|
||||
uint32_t attachmentCount;
|
||||
VkAttachmentDescription* attachments;
|
||||
|
||||
uint32_t subpassCount;
|
||||
VkSubpassDescription* subpasses;
|
||||
VkSubpassDependency* dependencies;
|
||||
|
||||
VkAttachmentReference** colorAttachments;
|
||||
VkAttachmentReference* depthAttachments;
|
||||
} gnPlatformRenderPassDescriptor;
|
||||
|
||||
VkPipelineStageFlags vkGryphnRenderPassStage(gnRenderPassStage stage);
|
@@ -0,0 +1,39 @@
|
||||
#include "vulkan_shader_module.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "stdio.h"
|
||||
|
||||
VkShaderStageFlagBits vkGryphnShaderModuleStage(gnShaderModuleStage stage) {
|
||||
VkShaderStageFlagBits outStage = 0;
|
||||
|
||||
if ((stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) outStage |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||
if ((stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) outStage |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
if ((stage & GN_ALL_SHADER_MODULE) == GN_ALL_SHADER_MODULE) return VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||
|
||||
return outStage;
|
||||
}
|
||||
|
||||
gnReturnCode gnCreateShaderModuleFn(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) {
|
||||
module->shaderModule = malloc(sizeof(struct gnPlatformShaderModule_t));
|
||||
|
||||
VkShaderModuleCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = shaderModuleInfo.size,
|
||||
.pCode = shaderModuleInfo.code
|
||||
};
|
||||
|
||||
if (vkCreateShaderModule(device->outputDevice->device, &createInfo, NULL, &module->shaderModule->shaderModule) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_SHADER_MODULE;
|
||||
|
||||
module->shaderModule->shaderStageInfo = (VkPipelineShaderStageCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = vkGryphnShaderModuleStage(shaderModuleInfo.stage),
|
||||
.module = module->shaderModule->shaderModule,
|
||||
.pName = shaderModuleInfo.entryPoint.value
|
||||
};
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnDestroyShaderModuleFn(struct gnShaderModule_t* module) {
|
||||
vkDestroyShaderModule(module->device->outputDevice->device, module->shaderModule->shaderModule, NULL);
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <core/shader_module/gryphn_shader_module.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformShaderModule_t {
|
||||
VkShaderModule shaderModule;
|
||||
VkPipelineShaderStageCreateInfo shaderStageInfo;
|
||||
} gnPlatformShaderModule;
|
||||
|
||||
VkShaderStageFlagBits vkGryphnShaderModuleStage(gnShaderModuleStage stage);
|
50
projects/apis/vulkan/src/submit/vulkan_submit.c
Normal file
50
projects/apis/vulkan/src/submit/vulkan_submit.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/submit/gryphn_submit.h"
|
||||
#include "sync/semaphore/vulkan_semaphore.h"
|
||||
#include "sync/fence/vulkan_fence.h"
|
||||
#include "commands/command_buffer/vulkan_command_buffer.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "renderpass/vulkan_render_pass_descriptor.h"
|
||||
|
||||
|
||||
gnReturnCode gnSubmitFn(struct gnOutputDevice_t* device, struct gnSubmitInfo_t info) {
|
||||
VK_SUBPASS_EXTERNAL;
|
||||
|
||||
VkSemaphore* waitSemaphores = malloc(sizeof(VkSemaphore) * info.waitCount);
|
||||
VkPipelineStageFlags* waitStages = malloc(sizeof(VkPipelineStageFlags) * info.waitCount);
|
||||
for (int i = 0; i < info.waitCount; i++) waitSemaphores[i] = info.waitSemaphores[i]->semaphore->semaphore;
|
||||
for (int i = 0; i < info.waitCount; i++) waitStages[i] = vkGryphnRenderPassStage(info.waitStages[i]);
|
||||
|
||||
VkCommandBuffer* commandBuffers = malloc(sizeof(VkCommandBuffer) * info.commandBufferCount);
|
||||
for (int i = 0; i < info.commandBufferCount; i++) commandBuffers[i] = info.commandBuffers[i]->commandBuffer->buffer;
|
||||
|
||||
VkSemaphore* signalSemaphores = malloc(sizeof(VkSemaphore) * info.signalCount);
|
||||
for (int i = 0; i < info.signalCount; i++) signalSemaphores[i] = info.signalSemaphores[i]->semaphore->semaphore;
|
||||
|
||||
VkSubmitInfo submitInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = info.waitCount,
|
||||
.pWaitSemaphores = waitSemaphores,
|
||||
.pWaitDstStageMask = waitStages,
|
||||
.commandBufferCount = info.commandBufferCount,
|
||||
.pCommandBuffers = commandBuffers,
|
||||
.signalSemaphoreCount = info.signalCount,
|
||||
.pSignalSemaphores = signalSemaphores
|
||||
};
|
||||
|
||||
VkQueue queue;
|
||||
vkGetDeviceQueue(device->outputDevice->device, info.queueIndex, 0, &queue);
|
||||
|
||||
if (vkQueueSubmit(queue, 1, &submitInfo, info.fence->fence->fence) != VK_SUCCESS) {
|
||||
free(waitSemaphores);
|
||||
free(waitStages);
|
||||
free(commandBuffers);
|
||||
free(signalSemaphores);
|
||||
return GN_FAILED_TO_SUBMIT_COMMAND_BUFFER;
|
||||
}
|
||||
free(waitSemaphores);
|
||||
free(waitStages);
|
||||
free(commandBuffers);
|
||||
free(signalSemaphores);
|
||||
return GN_SUCCESS;
|
||||
}
|
23
projects/apis/vulkan/src/sync/fence/vulkan_fence.c
Normal file
23
projects/apis/vulkan/src/sync/fence/vulkan_fence.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "vulkan_fence.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnCreateFenceFn(struct gnFence_t* fence, struct gnOutputDevice_t* device) {
|
||||
fence->fence = malloc(sizeof(gnPlatformFence));
|
||||
VkFenceCreateInfo fenceInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
|
||||
};
|
||||
if (vkCreateFence(device->outputDevice->device, &fenceInfo, NULL, &fence->fence->fence) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_FENCE;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
void gnSignalFenceFn(struct gnFence_t* fence) {}
|
||||
void gnWaitForFenceFn(struct gnFence_t* fence, uint64_t timeout) {
|
||||
vkWaitForFences(fence->device->outputDevice->device, 1, &fence->fence->fence, VK_TRUE, timeout);
|
||||
}
|
||||
void gnResetFenceFn(struct gnFence_t* fence) {
|
||||
vkResetFences(fence->device->outputDevice->device, 1, &fence->fence->fence);
|
||||
}
|
||||
void gnDestroyFenceFn(struct gnFence_t* fence) {
|
||||
vkDestroyFence(fence->device->outputDevice->device, fence->fence->fence, NULL);
|
||||
free(fence->fence);
|
||||
}
|
7
projects/apis/vulkan/src/sync/fence/vulkan_fence.h
Normal file
7
projects/apis/vulkan/src/sync/fence/vulkan_fence.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/sync/fence/gryphn_fence.h"
|
||||
|
||||
typedef struct gnPlatformFence_t {
|
||||
VkFence fence;
|
||||
} gnPlatformFence;
|
17
projects/apis/vulkan/src/sync/semaphore/vulkan_semaphore.c
Normal file
17
projects/apis/vulkan/src/sync/semaphore/vulkan_semaphore.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "vulkan_semaphore.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
|
||||
gnReturnCode gnCreateSemaphoreFn(struct gnSemaphore_t* semaphore, struct gnOutputDevice_t* device) {
|
||||
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
|
||||
VkSemaphoreCreateInfo semaphoreInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
|
||||
};
|
||||
|
||||
if (vkCreateSemaphore(device->outputDevice->device, &semaphoreInfo, NULL, &semaphore->semaphore->semaphore))
|
||||
return GN_FAILED_TO_CREATE_SEMAPHORE;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
void gnDestroySemaphoreFn(struct gnSemaphore_t* semaphore) {
|
||||
vkDestroySemaphore(semaphore->device->outputDevice->device, semaphore->semaphore->semaphore, NULL);
|
||||
free(semaphore->semaphore);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/sync/semaphore/gryphn_semaphore.h"
|
||||
|
||||
typedef struct gnPlatformSemaphore_t {
|
||||
VkSemaphore semaphore;
|
||||
} gnPlatformSemaphore;
|
273
projects/apis/vulkan/src/textures/vulkan_texture.c
Normal file
273
projects/apis/vulkan/src/textures/vulkan_texture.c
Normal file
@@ -0,0 +1,273 @@
|
||||
#include "vulkan_surface/vulkan_surface.h"
|
||||
#include "vulkan_texture.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "output_device/vulkan_physical_device.h"
|
||||
#include "core/debugger/gryphn_debugger.h"
|
||||
|
||||
VkImageType vkGryphnTextureType(gnTextureType type) {
|
||||
switch(type) {
|
||||
case GN_TEXTURE_2D: return VK_IMAGE_TYPE_2D;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageViewType vkGryphnTextureTypeView(gnTextureType type) {
|
||||
switch(type) {
|
||||
case GN_TEXTURE_2D: return VK_IMAGE_VIEW_TYPE_2D;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerAddressMode vkGryphnTextureWrap(gnTextureWrap wrap) {
|
||||
switch(wrap) {
|
||||
case GN_REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case GN_MIRRORED_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
case GN_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case GN_CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageAspectFlags vkGryphnGetAspectFlags(gnImageFormat format) {
|
||||
VkImageAspectFlags aspectMask = 0;
|
||||
|
||||
if (format == GN_FORMAT_D32S8_UINT || format == GN_FORMAT_D24S8_UINT) aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
else { aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; }
|
||||
|
||||
return aspectMask;
|
||||
}
|
||||
|
||||
gnBool vkGryphnIsDepthStencil(gnImageFormat format) { return (format == GN_FORMAT_D32S8_UINT || format == GN_FORMAT_D24S8_UINT); }
|
||||
|
||||
void VkTransitionImageLayout(gnDevice device, VkImage image, gnImageFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
|
||||
VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device);
|
||||
|
||||
VkPipelineStageFlags sourceStage, destinationStage;
|
||||
VkAccessFlags sourceAccessMask, destinationAccessMask;
|
||||
|
||||
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||
sourceAccessMask = 0;
|
||||
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
|
||||
destinationAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||
sourceAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
|
||||
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
destinationAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
|
||||
sourceAccessMask = 0;
|
||||
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
|
||||
destinationAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = image,
|
||||
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.srcAccessMask = sourceAccessMask,
|
||||
.oldLayout = oldLayout,
|
||||
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstAccessMask = destinationAccessMask,
|
||||
.newLayout = newLayout,
|
||||
|
||||
|
||||
.subresourceRange.aspectMask = vkGryphnGetAspectFlags(format),
|
||||
.subresourceRange.baseMipLevel = 0,
|
||||
.subresourceRange.levelCount = 1,
|
||||
.subresourceRange.baseArrayLayer = 0,
|
||||
.subresourceRange.layerCount = 1,
|
||||
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
transferBuffer,
|
||||
sourceStage, destinationStage,
|
||||
0,
|
||||
0, NULL,
|
||||
0, NULL,
|
||||
1, &barrier
|
||||
);
|
||||
|
||||
gnEndVulkanTransferOperation(device, transferBuffer);
|
||||
}
|
||||
|
||||
void VkCopyBufferToImage(VkGryphnBuffer buffer, VkGryphnImage image, uint32_t width, uint32_t height, gnDevice device) {
|
||||
VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device);
|
||||
|
||||
VkBufferImageCopy region = {
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
|
||||
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.imageSubresource.mipLevel = 0,
|
||||
.imageSubresource.baseArrayLayer = 0,
|
||||
.imageSubresource.layerCount = 1,
|
||||
|
||||
.imageOffset = (VkOffset3D){0, 0, 0},
|
||||
.imageExtent = (VkExtent3D){
|
||||
width,
|
||||
height,
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
vkCmdCopyBufferToImage(
|
||||
transferBuffer,
|
||||
buffer.buffer, image.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion
|
||||
);
|
||||
|
||||
gnEndVulkanTransferOperation(device, transferBuffer);
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
gnReturnCode gnCreateTextureFn(gnTexture texture, gnDevice device, const gnTextureInfo info) {
|
||||
texture->texture = malloc(sizeof(struct gnPlatformTexture_t));
|
||||
|
||||
size_t imageSize = info.width * info.height;
|
||||
if (info.format == GN_FORMAT_BGRA8_SRGB) { imageSize *= 4; }
|
||||
if (info.format == GN_FORMAT_RGBA8_SRGB) { imageSize *= 4; }
|
||||
|
||||
gnReturnCode staginBufferCreateCode = VkCreateBuffer(
|
||||
&texture->texture->buffer, imageSize, device,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||
);
|
||||
if (staginBufferCreateCode != GN_SUCCESS) return GN_FAILED_TO_CREATE_BUFFER;
|
||||
texture->texture->size = imageSize;
|
||||
|
||||
VkImageCreateInfo imageInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.extent = {
|
||||
.width = info.width,
|
||||
.height = info.height,
|
||||
.depth = 1
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.imageType = vkGryphnTextureType(info.type),
|
||||
.format = vkGryphnFormatToVulkanFormat(info.format)
|
||||
};
|
||||
|
||||
if (vkGryphnIsDepthStencil(info.format))
|
||||
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
else
|
||||
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
if (vkCreateImage(device->outputDevice->device, &imageInfo, NULL, &texture->texture->image.image) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_IMAGE;
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetImageMemoryRequirements(device->outputDevice->device, texture->texture->image.image, &memRequirements);
|
||||
|
||||
gnBool foundMemory = gnFalse;
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = memRequirements.size,
|
||||
.memoryTypeIndex = VkMemoryIndex(device->physicalDevice.physicalDevice->device, memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &foundMemory)
|
||||
};
|
||||
if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY;
|
||||
|
||||
if (vkAllocateMemory(device->outputDevice->device, &allocInfo, NULL, &texture->texture->image.memory) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ALLOCATE_MEMORY;
|
||||
|
||||
vkBindImageMemory(device->outputDevice->device, texture->texture->image.image, texture->texture->image.memory, 0);
|
||||
|
||||
texture->texture->width = info.width;
|
||||
texture->texture->height = info.height;
|
||||
|
||||
texture->texture->beenWrittenToo = gnFalse;
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = texture->texture->image.image,
|
||||
.viewType = vkGryphnTextureTypeView(info.type),
|
||||
.format = vkGryphnFormatToVulkanFormat(info.format),
|
||||
|
||||
.subresourceRange.aspectMask = vkGryphnGetAspectFlags(info.format),
|
||||
.subresourceRange.baseMipLevel = 0,
|
||||
.subresourceRange.levelCount = 1,
|
||||
.subresourceRange.baseArrayLayer = 0,
|
||||
.subresourceRange.layerCount = 1,
|
||||
};
|
||||
|
||||
if (vkCreateImageView(device->outputDevice->device, &viewInfo, NULL, &texture->texture->image.imageView) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_IMAGE_VIEW;
|
||||
|
||||
VkPhysicalDeviceProperties properties = {};
|
||||
vkGetPhysicalDeviceProperties(device->physicalDevice.physicalDevice->device, &properties);
|
||||
|
||||
VkSamplerCreateInfo samplerInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.minFilter = (info.minFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
|
||||
.magFilter = (info.magFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
|
||||
|
||||
.addressModeU = vkGryphnTextureWrap(info.wrapU),
|
||||
.addressModeV = vkGryphnTextureWrap(info.wrapV),
|
||||
.addressModeW = vkGryphnTextureWrap(info.wrapW),
|
||||
|
||||
.anisotropyEnable = VK_TRUE,
|
||||
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
|
||||
.compareEnable = VK_FALSE,
|
||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||
.mipLodBias = 0.0f,
|
||||
.minLod = 0.0f,
|
||||
.maxLod = 0.0f,
|
||||
};
|
||||
|
||||
if (vkCreateSampler(device->outputDevice->device, &samplerInfo, NULL, &texture->texture->sampler) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_CREATE_SAMPLER;
|
||||
|
||||
if (vkGryphnIsDepthStencil(info.format))
|
||||
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
void gnTextureDataFn(gnTextureHandle texture, void* pixelData) {
|
||||
void* data;
|
||||
vkMapMemory(texture->device->outputDevice->device, texture->texture->buffer.memory, 0, texture->texture->size, 0, &data);
|
||||
memcpy(data, pixelData, texture->texture->size);
|
||||
vkUnmapMemory(texture->device->outputDevice->device, texture->texture->buffer.memory);
|
||||
|
||||
if (texture->texture->beenWrittenToo) {
|
||||
gnDebuggerSetErrorMessage(texture->device->instance->debugger, (gnMessageData){
|
||||
.message = gnCreateString("this texture has alreay been written too with gnTextureData (vulkan) i need to implement the functionality to write to it multible times")
|
||||
});
|
||||
}
|
||||
|
||||
//gnDevice device, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout
|
||||
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
VkCopyBufferToImage(texture->texture->buffer, texture->texture->image, texture->texture->width, texture->texture->height, texture->device);
|
||||
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
texture->texture->beenWrittenToo = gnTrue;
|
||||
}
|
||||
|
||||
void gnDestroyVulkanImage(VkGryphnImage* image, VkDevice device) {
|
||||
vkDestroyImage(device, image->image, NULL);
|
||||
vkDestroyImageView(device, image->imageView, NULL);
|
||||
vkFreeMemory(device, image->memory, NULL);
|
||||
}
|
||||
|
||||
void gnDestroyTextureFn(gnTexture texture) {
|
||||
vkDestroySampler(texture->device->outputDevice->device, texture->texture->sampler, NULL);
|
||||
|
||||
gnDestroyVulkanBuffer(&texture->texture->buffer, texture->device->outputDevice->device);
|
||||
gnDestroyVulkanImage(&texture->texture->image, texture->device->outputDevice->device);
|
||||
}
|
21
projects/apis/vulkan/src/textures/vulkan_texture.h
Normal file
21
projects/apis/vulkan/src/textures/vulkan_texture.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/textures/gryphn_texture.h"
|
||||
#include "buffers/vulkan_buffer.h"
|
||||
|
||||
typedef struct VkGryphnImage {
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
VkImageView imageView;
|
||||
} VkGryphnImage;
|
||||
void gnDestroyVulkanImage(VkGryphnImage* image, VkDevice device);
|
||||
|
||||
typedef struct gnPlatformTexture_t {
|
||||
VkGryphnBuffer buffer;
|
||||
VkGryphnImage image;
|
||||
VkSampler sampler;
|
||||
|
||||
size_t size;
|
||||
uint32_t width, height;
|
||||
gnBool beenWrittenToo;
|
||||
} gnPlatformTexture;
|
45
projects/apis/vulkan/src/uniforms/vulkan_uniform.c
Normal file
45
projects/apis/vulkan/src/uniforms/vulkan_uniform.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "vulkan_uniform.h"
|
||||
#include "buffers/vulkan_buffer.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "core/uniforms/gryphn_uniform_pool.h"
|
||||
#include "textures/vulkan_texture.h"
|
||||
|
||||
void gnUpdateBufferUniformFn(gnUniform uniform, gnBufferUniformInfo* info) {
|
||||
VkDescriptorBufferInfo bufferInfo = {
|
||||
.buffer = info->buffer->buffer->buffer.buffer,
|
||||
.offset = info->offset,
|
||||
.range = info->size
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.pBufferInfo = &bufferInfo,
|
||||
.dstSet = uniform->uniform->set,
|
||||
.dstBinding = info->binding,
|
||||
.dstArrayElement = 0
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL);
|
||||
}
|
||||
|
||||
void gnUpdateImageUniformFn(gnUniform uniform, gnImageUniformInfo* info) {
|
||||
VkDescriptorImageInfo imageInfo = {
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.imageView = info->texture->texture->image.imageView,
|
||||
.sampler = info->texture->texture->sampler
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.pImageInfo = &imageInfo,
|
||||
.dstSet = uniform->uniform->set,
|
||||
.dstBinding = info->binding,
|
||||
.dstArrayElement = 0
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL);
|
||||
}
|
7
projects/apis/vulkan/src/uniforms/vulkan_uniform.h
Normal file
7
projects/apis/vulkan/src/uniforms/vulkan_uniform.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/uniforms/gryphn_uniform.h"
|
||||
|
||||
typedef struct gnPlatformUniform_t {
|
||||
VkDescriptorSet set;
|
||||
} gnPlatformUniform;
|
39
projects/apis/vulkan/src/uniforms/vulkan_uniform_layout.c
Normal file
39
projects/apis/vulkan/src/uniforms/vulkan_uniform_layout.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "vulkan_uniform_layout.h"
|
||||
#include <shader_module/vulkan_shader_module.h>
|
||||
|
||||
VkDescriptorType vkGryphnUniformType(gnUniformType type) {
|
||||
switch(type) {
|
||||
case GN_UNIFORM_BUFFER_DESCRIPTOR: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
case GN_IMAGE_DESCRIPTOR: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
case GN_UNIFORM_TYPE_MAX: return VK_DESCRIPTOR_TYPE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout vkGryphnCreateSetLayouts(
|
||||
const gnUniformSet* set,
|
||||
VkDevice device
|
||||
) {
|
||||
VkDescriptorSetLayout vkLayout;
|
||||
gnUniformSet uniformSet = *set;
|
||||
|
||||
VkDescriptorSetLayoutBinding* bindings = malloc(sizeof(VkDescriptorSetLayoutBinding) * uniformSet.uniformBindingCount);
|
||||
for (int i = 0; i < uniformSet.uniformBindingCount; i++) {
|
||||
bindings[i] = (VkDescriptorSetLayoutBinding){
|
||||
.binding = uniformSet.uniformBindings[i].binding,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vkGryphnUniformType(uniformSet.uniformBindings[i].type),
|
||||
.stageFlags = vkGryphnShaderModuleStage(uniformSet.uniformBindings[i].stage)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = uniformSet.uniformBindingCount,
|
||||
.pBindings = bindings
|
||||
};
|
||||
|
||||
if (vkCreateDescriptorSetLayout(device, &info, NULL, &vkLayout) != VK_SUCCESS)
|
||||
return NULL;
|
||||
return vkLayout;
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/uniforms/gryphn_uniform_layout.h>
|
||||
|
||||
VkDescriptorSetLayout vkGryphnCreateSetLayouts(const gnUniformSet* set, VkDevice device);
|
||||
VkDescriptorType vkGryphnUniformType(gnUniformType type);
|
136
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c
Normal file
136
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "vulkan_uniform_pool.h"
|
||||
#include "vulkan_uniform_layout.h"
|
||||
#include "stdlib.h"
|
||||
#include "output_device/vulkan_output_devices.h"
|
||||
#include "core/uniforms/gryphn_uniform.h"
|
||||
#include "vulkan_uniform.h"
|
||||
#include "stdio.h"
|
||||
|
||||
VkGryphnUniformPool* GetLastUniformPool(VkGryphnUniformPoolArrayList* list) { return &list->data[list->count - 1]; }
|
||||
|
||||
gnReturnCode gnCreateUniformPoolFn(gnUniformPool pool, gnDeviceHandle device) {
|
||||
pool->uniformPool = malloc(sizeof(struct gnPlatformUniformPool_t));
|
||||
pool->uniformPool->pools = VkGryphnUniformPoolArrayListCreate();
|
||||
|
||||
if (device->outputDevice->enabledOversizedDescriptorPools == gnTrue) {
|
||||
{
|
||||
VkGryphnUniformPool firstPool = {
|
||||
.pool = VK_NULL_HANDLE,
|
||||
.layouts = VkDescriptorSetLayoutArrayListCreate()
|
||||
};
|
||||
VkGryphnUniformPoolArrayListAdd(&pool->uniformPool->pools, firstPool);
|
||||
} // scopped because the add function copies and I don't want it lying around
|
||||
|
||||
VkGryphnUniformPool* currentPool = GetLastUniformPool(&pool->uniformPool->pools);
|
||||
VkDescriptorPoolCreateInfo poolInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV,
|
||||
.poolSizeCount = 0,
|
||||
.pPoolSizes = NULL,
|
||||
.maxSets = 0
|
||||
};
|
||||
|
||||
if (vkCreateDescriptorPool(
|
||||
pool->device->outputDevice->device, &poolInfo, NULL,
|
||||
¤tPool->pool
|
||||
) != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ALLOCATE_MEMORY;
|
||||
}
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
gnUniform* gnUniformPoolAllocateUniformsFn(gnUniformPool pool, gnUniformAllocationInfo allocInfo) {
|
||||
gnBool fixedAllocation = !pool->device->outputDevice->enabledOversizedDescriptorPools;
|
||||
if (fixedAllocation) {
|
||||
VkGryphnUniformPool newPool = {
|
||||
.pool = VK_NULL_HANDLE,
|
||||
.layouts = VkDescriptorSetLayoutArrayListCreate()
|
||||
};
|
||||
|
||||
// TODO: redo this, its not warning me IDK why cuz its totally wrong
|
||||
VkDescriptorPoolSize uniformBufferSize = {
|
||||
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 0
|
||||
};
|
||||
|
||||
VkDescriptorPoolSize imageSize = {
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 0
|
||||
};
|
||||
|
||||
for (int i = 0; i < allocInfo.setCount; i++) {
|
||||
for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) {
|
||||
if (allocInfo.sets[i].uniformBindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) uniformBufferSize.descriptorCount++;
|
||||
if (allocInfo.sets[i].uniformBindings[i].type == GN_IMAGE_DESCRIPTOR) imageSize.descriptorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
VkDescriptorPoolSize poolSizes[2] = {};
|
||||
|
||||
if (uniformBufferSize.descriptorCount > 0) {
|
||||
poolSizes[count] = uniformBufferSize;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (imageSize.descriptorCount > 0) {
|
||||
poolSizes[count] = imageSize;
|
||||
count++;
|
||||
}
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.poolSizeCount = count,
|
||||
.pPoolSizes = poolSizes,
|
||||
.maxSets = allocInfo.setCount
|
||||
};
|
||||
|
||||
if (vkCreateDescriptorPool(
|
||||
pool->device->outputDevice->device, &poolInfo, NULL,
|
||||
&newPool.pool
|
||||
) != VK_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
VkGryphnUniformPoolArrayListAdd(&pool->uniformPool->pools, newPool);
|
||||
} // scopped for same reasons as before
|
||||
|
||||
VkGryphnUniformPool* currentPool = GetLastUniformPool(&pool->uniformPool->pools);
|
||||
|
||||
uint32_t startingCount = currentPool->layouts.count;
|
||||
VkDescriptorSetLayoutArrayListExpand(¤tPool->layouts, allocInfo.setCount);
|
||||
|
||||
for (int i = 0; i < allocInfo.setCount; i++) {
|
||||
VkDescriptorSetLayoutArrayListAdd(
|
||||
¤tPool->layouts,
|
||||
vkGryphnCreateSetLayouts(&allocInfo.sets[i], pool->device->outputDevice->device)
|
||||
);
|
||||
}
|
||||
|
||||
VkDescriptorSetAllocateInfo vkAllocInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = currentPool->pool,
|
||||
.descriptorSetCount = allocInfo.setCount,
|
||||
.pSetLayouts = ¤tPool->layouts.data[startingCount]
|
||||
};
|
||||
|
||||
VkDescriptorSet* sets = malloc(sizeof(VkDescriptorSet) * allocInfo.setCount);
|
||||
if (vkAllocateDescriptorSets(pool->device->outputDevice->device, &vkAllocInfo, sets) != VK_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
gnUniform* uniforms = malloc(sizeof(gnUniform) * allocInfo.setCount);
|
||||
for (int i = 0; i < allocInfo.setCount; i++) {
|
||||
uniforms[i] = malloc(sizeof(struct gnUniform_t));
|
||||
uniforms[i]->uniform = malloc(sizeof(struct gnPlatformUniform_t));
|
||||
uniforms[i]->uniform->set = sets[i];
|
||||
}
|
||||
return uniforms;
|
||||
}
|
||||
|
||||
void gnDestroyUniformPoolFn(gnUniformPool pool) {
|
||||
for (int k = 0; k < pool->uniformPool->pools.count; k++) {
|
||||
vkDestroyDescriptorPool(pool->device->outputDevice->device, pool->uniformPool->pools.data[k].pool, NULL);
|
||||
for (int i = 0; i < pool->uniformPool->pools.data[k].layouts.count; i++)
|
||||
vkDestroyDescriptorSetLayout(pool->device->outputDevice->device, pool->uniformPool->pools.data[k].layouts.data[i], NULL);
|
||||
}
|
||||
}
|
15
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.h
Normal file
15
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/uniforms/gryphn_uniform_pool.h>
|
||||
|
||||
GN_ARRAY_LIST(VkDescriptorSetLayout);
|
||||
|
||||
typedef struct VkGryphnUniformPool {
|
||||
VkDescriptorPool pool;
|
||||
VkDescriptorSetLayoutArrayList layouts;
|
||||
} VkGryphnUniformPool;
|
||||
GN_ARRAY_LIST(VkGryphnUniformPool);
|
||||
|
||||
struct gnPlatformUniformPool_t {
|
||||
VkGryphnUniformPoolArrayList pools;
|
||||
};
|
124
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.c
Normal file
124
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.c
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <core/window_surface/gryphn_surface_create_functions.h>
|
||||
#include <instance/vulkan_instance.h>
|
||||
#include "vulkan_surface.h"
|
||||
#include <output_device/vulkan_physical_device.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef GN_PLATFORM_LINUX
|
||||
#ifdef GN_WINDOW_X11
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
gnReturnCode gnCreateX11WindowSurfaceFn(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, gnX11WindowSurfaceInfo createInfo) {
|
||||
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
|
||||
VkXlibSurfaceCreateInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
info.dpy = createInfo.display;
|
||||
info.window = createInfo.window;
|
||||
|
||||
VkResult result = vkCreateXlibSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ATTACH_WINDOW;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GN_WINFDOW_WAYLAND
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
gnReturnCode gnCreateWaylandWindowSurface(struct gnWindowSurface_t* windowSurface, gnInstanceHandle instance, struct gnWaylandWindowSurfaceInfo_t createInfo) {
|
||||
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
|
||||
VkWaylandSurfaceCreateInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
info.display = createInfo.display;
|
||||
info.surface = createInfo.surface;
|
||||
|
||||
VkResult result = vkCreateWaylandSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ATTACH_WINDOW;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GN_PLATFORM_WINDOWS
|
||||
#include "vulkan/vulkan_win32.h"
|
||||
gnReturnCode gnCreateWin32WindowSurface(struct gnWindowSurface_t* windowSurface, gnInstanceHandle instance, struct gnWin32WindowSurfaceInfo_t createInfo) {
|
||||
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
|
||||
VkWin32SurfaceCreateInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||
info.hwnd = createInfo.window;
|
||||
info.hinstance = createInfo.instance;
|
||||
|
||||
VkResult result = vkCreateWin32SurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ATTACH_WINDOW;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void gnDestroyWindowSurfaceFn(struct gnWindowSurface_t* windowSurface) {
|
||||
vkDestroySurfaceKHR(windowSurface->instance->instance->vk_instance, windowSurface->windowSurface->surface, NULL);
|
||||
}
|
||||
|
||||
struct gnSurfaceFormat_t* vkGetSurfaceFormats(
|
||||
struct gnWindowSurface_t* windowSurface, struct gnPhysicalDevice_t device, uint32_t* formatCount
|
||||
) {
|
||||
struct gnSurfaceFormat_t* formats = NULL;
|
||||
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, formatCount, NULL);
|
||||
formats = malloc(sizeof(struct gnSurfaceFormat_t) * *formatCount);
|
||||
VkSurfaceFormatKHR* vkFormats = malloc(sizeof(VkSurfaceFormatKHR) * *formatCount);;
|
||||
|
||||
if (*formatCount > 0) {
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, formatCount, vkFormats);
|
||||
for (int i = 0; i < *formatCount; i++) {
|
||||
switch (vkFormats[i].format) {
|
||||
case VK_FORMAT_B8G8R8A8_SRGB: { formats[i].format = GN_FORMAT_BGRA8_SRGB; break; }
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (vkFormats[i].colorSpace) {
|
||||
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: { formats[i].colorSpace = GN_COLOR_SPACE_SRGB_NONLINEAR; break; }
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
gnSurfaceDetails gnGetSurfaceDetailsFn(
|
||||
gnWindowSurfaceHandle windowSurface, gnPhysicalDevice device
|
||||
) {
|
||||
gnSurfaceDetails surfaceDetails;
|
||||
surfaceDetails.formats = vkGetSurfaceFormats(windowSurface, device, &surfaceDetails.formatCount);
|
||||
|
||||
VkSurfaceCapabilitiesKHR details;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, &details);
|
||||
|
||||
surfaceDetails.minImageCount = details.minImageCount;
|
||||
surfaceDetails.maxImageCount = details.maxImageCount;
|
||||
|
||||
surfaceDetails.minImageSize = (gnUInt2){ details.minImageExtent.width, details.minImageExtent.height };
|
||||
surfaceDetails.maxImageSize = (gnUInt2){ details.maxImageExtent.width, details.maxImageExtent.height };
|
||||
surfaceDetails.currentSize = (gnUInt2){ details.currentExtent.width, details.currentExtent.height };
|
||||
|
||||
return surfaceDetails;
|
||||
}
|
||||
|
||||
|
||||
VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format) {
|
||||
switch (format) {
|
||||
case GN_FORMAT_NONE: return VK_FORMAT_UNDEFINED;
|
||||
case GN_FORMAT_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
|
||||
case GN_FORMAT_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
|
||||
case GN_FORMAT_D32S8_UINT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
case GN_FORMAT_D24S8_UINT: return VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
}
|
||||
}
|
||||
VkColorSpaceKHR vkGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace) {
|
||||
switch (colorSpace) {
|
||||
case GN_COLOR_SPACE_SRGB_NONLINEAR: { return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; }
|
||||
}
|
||||
}
|
10
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.h
Normal file
10
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <core/window_surface/gryphn_surface.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformWindowSurface_t {
|
||||
VkSurfaceKHR surface;
|
||||
} gnPlatformWindowSurface;
|
||||
|
||||
VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format);
|
||||
VkColorSpaceKHR vkGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace);
|
27
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.m
Normal file
27
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.m
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifdef GN_PLATFORM_MACOS
|
||||
#include "vulkan_surface.h"
|
||||
#include "core/window_surface/gryphn_surface_create_functions.h"
|
||||
#include "../instance/vulkan_instance.h"
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <vulkan/vulkan_metal.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
|
||||
#include "vulkan/vulkan_metal.h"
|
||||
gnReturnCode gnCreateMacOSWindowSurfaceFn(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, struct gnMacOSWindowSurfaceInfo_t createInfo) {
|
||||
windowSurface->windowSurface = malloc(sizeof(gnPlatformWindowSurface));
|
||||
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo = {};
|
||||
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||
surfaceCreateInfo.pNext = NULL;
|
||||
surfaceCreateInfo.flags = 0;
|
||||
surfaceCreateInfo.pLayer = createInfo.layer;
|
||||
|
||||
VkResult result = vkCreateMetalSurfaceEXT(instance->instance->vk_instance, &surfaceCreateInfo, NULL, &windowSurface->windowSurface->surface);
|
||||
if (result != VK_SUCCESS)
|
||||
return GN_FAILED_TO_ATTACH_WINDOW;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user