get supported surface formats
This commit is contained in:
@@ -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);
|
||||
}
|
@@ -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);
|
@@ -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,
|
||||
®ion
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user