get supported surface formats

This commit is contained in:
Greg Wells
2025-05-24 17:16:42 -04:00
parent 38799cb663
commit 410eab007e
118 changed files with 84 additions and 4217 deletions

View File

@@ -1,238 +0,0 @@
#include <vulkan/vulkan.h>
#include "gryphn/gryphn_utils.h"
#include "vulkan_texture.h"
#include "core/textures/gryphn_texture.h"
#include "../output_device/vulkan_output_devices.h"
#include "../vertex_buffers/vulkan_buffers.h"
void vulkanTexture(gnTexture* texture) {
if (texture->texture == nullptr) texture->texture = new gnPlatformTexture();
}
gnReturnCode findDepthFormat(const gnOutputDevice& outputDevice, VkFormat& format) {
return findSupportedFormat(outputDevice,
{VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, format
);
}
VkFormat findDepthFormat(const gnOutputDevice& outputDevice) {
VkFormat format;
findSupportedFormat(outputDevice,
{VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, format
);
return format;
}
VkFormat vulkanFormatFromGryphnFormat(const gnOutputDevice& outputDevice, gnColorMode colorMode) {
switch (colorMode) {
case GN_RED: return VK_FORMAT_R8_UNORM;
case GN_RGB8: return VK_FORMAT_R8G8B8A8_SRGB;
case GN_RGBA8: return VK_FORMAT_R8G8B8A8_SRGB;
case GN_BGRA8: return VK_FORMAT_B8G8R8A8_SRGB;
case GN_DEPTH_STENCIL: return findDepthFormat(outputDevice);
}
return VK_FORMAT_R8_UNORM;
}
GN_EXPORT void gnTextureDataFn(const gnTexture& texture, gnSize dataSize, const void* inputData) {
texture.texture->size = dataSize;
texture.texture->data = inputData;
vulkanCreateBuffer(
*texture.texture->outputDevice, texture.texture->size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
texture.texture->stagingBuffer, texture.texture->stagingBufferMemory
);
void* data;
vkMapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, 0, texture.texture->size, 0, &data);
memcpy(data, texture.texture->data, texture.texture->size);
vkUnmapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory);
VkFormat format = vulkanFormatFromGryphnFormat(*texture.texture->outputDevice, texture.textureColorFormat);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyBufferToImage(*texture.texture->outputDevice, texture.texture->stagingBuffer, texture.texture->textureImage, texture.textureExtent.x, texture.textureExtent.y);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vkDestroyBuffer(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBuffer, nullptr);
vkFreeMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, nullptr);
}
GN_EXPORT void gnTextureCubeMapDataFn(const gnTexture& texture, gnSize imageDataSize, void* face1, void* face2, void* face3, void* face4, void* face5, void* face6) {
texture.texture->size = imageDataSize;
uint32_t faceSize = imageDataSize / 6;
if (vulkanCreateBuffer(
*texture.texture->outputDevice, texture.texture->size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
texture.texture->stagingBuffer, texture.texture->stagingBufferMemory
) != GN_SUCCESS) {
// return GN_FAILED;
}
void* data;
vkMapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, 0, texture.texture->size, 0, &data);
memcpy((char*)data + (faceSize * 0), face1, faceSize);
memcpy((char*)data + (faceSize * 1), face2, faceSize);
memcpy((char*)data + (faceSize * 2), face3, faceSize);
memcpy((char*)data + (faceSize * 3), face4, faceSize);
memcpy((char*)data + (faceSize * 4), face5, faceSize);
memcpy((char*)data + (faceSize * 5), face6, faceSize);
vkUnmapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory);
VkFormat format = vulkanFormatFromGryphnFormat(*texture.texture->outputDevice, texture.textureColorFormat);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 6);
copyBufferToImage(*texture.texture->outputDevice, texture.texture->stagingBuffer, texture.texture->textureImage, texture.textureExtent.x, texture.textureExtent.y, 6);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 6);
vkDestroyBuffer(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBuffer, nullptr);
vkFreeMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, nullptr);
}
void gnTextureSubData(const gnTexture& texture, gnSize offset, gnSize dataSize, void* inputData) {
texture.texture->size = texture.dataSize;
if (vulkanCreateBuffer(
*texture.texture->outputDevice, texture.texture->size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
texture.texture->stagingBuffer, texture.texture->stagingBufferMemory
) != GN_SUCCESS) {
// return GN_FAILED;
}
void* data;
vkMapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, 0, texture.texture->size, 0, &data);
memcpy((char*)data + offset, inputData, dataSize);
vkUnmapMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory);
VkFormat format = vulkanFormatFromGryphnFormat(*texture.texture->outputDevice, texture.textureColorFormat);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyBufferToImage(*texture.texture->outputDevice, texture.texture->stagingBuffer, texture.texture->textureImage, texture.textureExtent.x, texture.textureExtent.y);
transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vkDestroyBuffer(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBuffer, nullptr);
vkFreeMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->stagingBufferMemory, nullptr);
}
GN_EXPORT gnReturnCode gnCreateTextureFn(gnTexture* texture, const gnOutputDevice& outputDevice) {
if (texture->texture == nullptr) texture->texture = new gnPlatformTexture();
texture->texture->outputDevice = const_cast<gnOutputDevice*>(&outputDevice);
// VkFormat textureFormat
if (texture->textureType == GN_TEXTURE_2D) {
if (texture->textureColorFormat == GN_RGBA8) {
gnReturnCode res = vulkanCreateImage(outputDevice, texture->textureExtent.x, texture->textureExtent.y,
VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
texture->texture->textureImage, texture->texture->textureImageMemory);
if (res != GN_SUCCESS) return res;
gnReturnCode errorCode = createImageView(outputDevice, texture->texture->textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, &texture->texture->textureImageView);
if (errorCode != GN_SUCCESS) return errorCode;
} else if (texture->textureColorFormat == GN_RGB8) {
VkFormat textureFormat = VK_FORMAT_R8G8B8A8_SRGB;
// if (formatSupported(outputDevice,
// VK_FORMAT_R8G8B8_SRGB,
// VK_IMAGE_TILING_OPTIMAL,
// VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
// )) {
// textureFormat = VK_FORMAT_R8G8B8_SRGB;
// }
if (vulkanCreateImage(outputDevice, texture->textureExtent.x, texture->textureExtent.y,
textureFormat, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
texture->texture->textureImage, texture->texture->textureImageMemory) != GN_SUCCESS) {
return GN_FAILED;
}
gnReturnCode errorCode = createImageView(outputDevice, texture->texture->textureImage, textureFormat, VK_IMAGE_ASPECT_COLOR_BIT, &texture->texture->textureImageView);
if (errorCode != GN_SUCCESS) return errorCode;
} else if (texture->textureColorFormat == GN_RED) {
if (vulkanCreateImage(outputDevice, texture->textureExtent.x, texture->textureExtent.y,
VK_FORMAT_R8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
texture->texture->textureImage, texture->texture->textureImageMemory) != GN_SUCCESS) {
return GN_FAILED;
}
gnReturnCode errorCode = createImageView(outputDevice, texture->texture->textureImage, VK_FORMAT_R8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT, &texture->texture->textureImageView);
if (errorCode != GN_SUCCESS) return errorCode;
} else if (texture->textureColorFormat == GN_BGRA8) {
if (vulkanCreateImage(outputDevice, texture->textureExtent.x, texture->textureExtent.y,
VK_FORMAT_B8G8R8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
texture->texture->textureImage, texture->texture->textureImageMemory, VK_IMAGE_LAYOUT_UNDEFINED) != GN_SUCCESS) {
return GN_FAILED;
}
gnReturnCode errorCode = createImageView(outputDevice, texture->texture->textureImage, VK_FORMAT_B8G8R8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, &texture->texture->textureImageView);
if (errorCode != GN_SUCCESS) return errorCode;
//GN_ERROR_CODE code = transitionImageLayout(*texture.texture->outputDevice, texture.texture->textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
gnReturnCode transitionErrorCode = transitionImageLayout(outputDevice, texture->texture->textureImage, VK_FORMAT_B8G8R8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (transitionErrorCode != GN_SUCCESS) return transitionErrorCode;
} else if (texture->textureColorFormat == GN_DEPTH_STENCIL) {
VkFormat depthFormat;
gnReturnCode depthFormatReturnCode = findDepthFormat(outputDevice, depthFormat);
if (depthFormatReturnCode != GN_SUCCESS) return depthFormatReturnCode;
if (vulkanCreateImage(outputDevice, texture->textureExtent.x, texture->textureExtent.y,
depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
texture->texture->textureImage, texture->texture->textureImageMemory) != GN_SUCCESS) {
return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, "Failed to create depth image");
}
gnReturnCode errorCode = createImageView(outputDevice, texture->texture->textureImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, &texture->texture->textureImageView);
if (transitionImageLayout(outputDevice, texture->texture->textureImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) != GN_SUCCESS) return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, "Failed to transition image layout");
}
} else {
if (vulkanCreateCubeMap(outputDevice, texture->textureExtent.x, texture->textureExtent.y, texture->texture->textureImage, texture->texture->textureImageMemory) != GN_SUCCESS)
return GN_FAILED;
if (vulkanCreateCubeMapImageView(outputDevice, texture->texture->textureImage, &texture->texture->textureImageView) != GN_SUCCESS)
return GN_FAILED;
}
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = (texture->magFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
samplerInfo.minFilter = (texture->minFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.anisotropyEnable = VK_TRUE;
VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(outputDevice.physicalOutputDevice->physicalOutputDevice->device, &properties);
samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
if (vkCreateSampler(outputDevice.outputDevice->device, &samplerInfo, nullptr, &texture->texture->textureSampler) != VK_SUCCESS)
return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, "Failed to create texture sampler");
}
return GN_SUCCESS;
}
GN_EXPORT void gnDestroyTextureFn(const gnTexture& texture) {
vkDestroySampler(texture.texture->outputDevice->outputDevice->device, texture.texture->textureSampler, nullptr);
vkDestroyImageView(texture.texture->outputDevice->outputDevice->device, texture.texture->textureImageView, nullptr);
vkDestroyImage(texture.texture->outputDevice->outputDevice->device, texture.texture->textureImage, nullptr);
vkFreeMemory(texture.texture->outputDevice->outputDevice->device, texture.texture->textureImageMemory, nullptr);
}

View File

@@ -1,38 +0,0 @@
#pragma once
#include <vulkan/vulkan.h>
#include "gryphn/gryphn_utils.h"
struct gnOutputDevice;
struct gnPlatformTexture {
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
VkImage textureImage;
VkImageView textureImageView;
VkDeviceMemory textureImageMemory;
VkSampler textureSampler;
gnSize size;
const void* data;
gnOutputDevice* outputDevice;
bool swapchainImage = false;
};
gnReturnCode vulkanCreateImage(const gnOutputDevice& device,
uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory
);
gnReturnCode vulkanCreateImage(const gnOutputDevice& device,
uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory, VkImageLayout imageLayout
);
gnReturnCode vulkanCreateCubeMap(const gnOutputDevice& device, uint32_t width, uint32_t height, VkImage& image, VkDeviceMemory& imageMemory);
gnReturnCode vulkanCreateCubeMapImageView(const gnOutputDevice& outputDevice, VkImage image, VkImageView* imageView);
gnReturnCode createImageView(const gnOutputDevice& outputDevice, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, VkImageView* imageView);
gnReturnCode findSupportedFormat(const gnOutputDevice& outputDevice, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat& outFormat);
gnReturnCode transitionImageLayout(const gnOutputDevice& outputDevice, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, int level_count = 1);
void copyBufferToImage(const gnOutputDevice& outputDevice, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, int level_count = 1);
gnReturnCode findDepthFormat(const gnOutputDevice& outputDevice, VkFormat& format);
bool formatSupported(const gnOutputDevice& outputDevice, const VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features);

View File

@@ -1,284 +0,0 @@
#include <vulkan/vulkan.h>
#include "gryphn/gryphn_utils.h"
#include "vulkan_texture.h"
#include "core/textures/gryphn_texture.h"
#include "../vertex_buffers/vulkan_buffers.h"
#include "../output_device/vulkan_output_devices.h"
#include "../commands/vulkan_command_buffer.h"
void copyBufferToImage(const gnOutputDevice& outputDevice, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, int level_count) {
VkCommandBuffer commandBuffer = beginSingleTimeCommands(outputDevice);
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = level_count;
region.imageOffset = {0, 0, 0};
region.imageExtent = {
width,
height,
1
};
vkCmdCopyBufferToImage(
commandBuffer,
buffer,
image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&region
);
endSingleTimeCommands(commandBuffer, outputDevice);
}
bool hasStencilComponent(VkFormat format) {
return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
}
gnReturnCode transitionImageLayout(const gnOutputDevice& outputDevice, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, int level_count) {
VkCommandBuffer commandBuffer = beginSingleTimeCommands(outputDevice);
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = level_count;
VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
} else {
return GN_FAILED;
}
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (hasStencilComponent(format)) {
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
} else {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
vkCmdPipelineBarrier(
commandBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
endSingleTimeCommands(commandBuffer, outputDevice);
return GN_SUCCESS;
}
gnReturnCode vulkanCreateCubeMap(const gnOutputDevice& outputDevice, uint32_t width, uint32_t height, VkImage& image, VkDeviceMemory& imageMemory) {
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imageInfo.mipLevels = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.extent = { width, height, 1 };
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.arrayLayers = 6;
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // Optional
if (vkCreateImage(outputDevice.outputDevice->device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
return GN_FAILED;
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(outputDevice.outputDevice->device, image, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
uint32_t memoryTypeIndex;
if (findMemoryType(
outputDevice.physicalOutputDevice->physicalOutputDevice->device,
memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&memoryTypeIndex) != GN_SUCCESS) {
return GN_FAILED;
}
allocInfo.memoryTypeIndex = memoryTypeIndex;
if (vkAllocateMemory(outputDevice.outputDevice->device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
return GN_FAILED;
}
vkBindImageMemory(outputDevice.outputDevice->device, image, imageMemory, 0);
return GN_SUCCESS;
}
gnReturnCode vulkanCreateImage(const gnOutputDevice& outputDevice,
uint32_t width, uint32_t height,
VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties,
VkImage& image, VkDeviceMemory& imageMemory, VkImageLayout imageLayout
) {
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = static_cast<uint32_t>(width);
imageInfo.extent.height = static_cast<uint32_t>(height);
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.tiling = tiling;
imageInfo.initialLayout = imageLayout;
imageInfo.usage = usage;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.flags = 0; // Optional
VkResult result = vkCreateImage(outputDevice.outputDevice->device, &imageInfo, nullptr, &image);
if (result != VK_SUCCESS) {
return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, std::to_string(result).c_str());
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(outputDevice.outputDevice->device, image, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
uint32_t memoryTypeIndex;
if (findMemoryType(
outputDevice.physicalOutputDevice->physicalOutputDevice->device,
memRequirements.memoryTypeBits, properties,
&memoryTypeIndex) != GN_SUCCESS) {
return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, "Failed to find memory type");
}
allocInfo.memoryTypeIndex = memoryTypeIndex;
if (vkAllocateMemory(outputDevice.outputDevice->device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
return gnReturnError(GN_FAILED_TO_CREATE_IMAGE, "Failed to allocate memory");
}
vkBindImageMemory(outputDevice.outputDevice->device, image, imageMemory, 0);
return GN_SUCCESS;
}
gnReturnCode vulkanCreateImage(const gnOutputDevice& outputDevice,
uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory
) {
return vulkanCreateImage(outputDevice, width, height, format, tiling, usage, properties, image, imageMemory, VK_IMAGE_LAYOUT_UNDEFINED);
}
gnReturnCode vulkanCreateCubeMapImageView(const gnOutputDevice& outputDevice, VkImage image, VkImageView* imageView) {
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
viewInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
viewInfo.subresourceRange.layerCount = 6;
viewInfo.subresourceRange.levelCount = 1;
if (vkCreateImageView(outputDevice.outputDevice->device, &viewInfo, nullptr, imageView) != VK_SUCCESS) {
return GN_FAILED;
}
return GN_SUCCESS;
}
gnReturnCode createImageView(const gnOutputDevice& outputDevice, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, VkImageView* imageView) {
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = aspectFlags;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
VkResult restult = vkCreateImageView(outputDevice.outputDevice->device, &viewInfo, nullptr, imageView);
// std::cout << "Result:" << restult << "\n";
if (restult != VK_SUCCESS) {
return GN_FAILED;
}
return GN_SUCCESS;
}
gnReturnCode findSupportedFormat(const gnOutputDevice& outputDevice, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat& outFormat) {
for (VkFormat format : candidates) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(outputDevice.physicalOutputDevice->physicalOutputDevice->device, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
outFormat = format;
return GN_SUCCESS;
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
outFormat = format;
return GN_SUCCESS;
}
}
return GN_FAILED;
}
bool formatSupported(const gnOutputDevice& outputDevice, const VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(outputDevice.physicalOutputDevice->physicalOutputDevice->device, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
return true;
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
return true;
}
return false;
}