Add Offscreen Framebuffer support
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
#include "Texture2D.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
Texture2D::Texture2D(Instance& instance, const std::string& filename)
|
||||
: instance{instance}, type{Type::Static}, format{Format::Image}
|
||||
{
|
||||
InitializeTextureImage(filename);
|
||||
InitializeSampler();
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format)
|
||||
: instance{instance}, type{type}, format{format}
|
||||
{
|
||||
InitializeTexture(width, height);
|
||||
InitializeSampler();
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
for(auto&& image : images)
|
||||
vkDestroyImage(instance.GetDevice(), image, nullptr);
|
||||
for(auto&& imageMemory : imageMemories)
|
||||
vkFreeMemory(instance.GetDevice(), imageMemory, nullptr);
|
||||
for(auto&& imageView : imageViews)
|
||||
vkDestroyImageView(instance.GetDevice(), imageView, nullptr);
|
||||
vkDestroySampler(instance.GetDevice(), sampler, nullptr);
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const
|
||||
{
|
||||
VkDescriptorImageInfo imageInfo{};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.sampler = sampler;
|
||||
|
||||
switch (type) {
|
||||
case Type::Static:
|
||||
imageInfo.imageView = imageViews.front();
|
||||
break;
|
||||
case Type::Dynamic:
|
||||
CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for dynamic texture");
|
||||
imageInfo.imageView = imageViews[index];
|
||||
break;
|
||||
default:
|
||||
CP_ABORT("GetDescriptorImageInfo : Unreachable switch case");
|
||||
}
|
||||
|
||||
return imageInfo;
|
||||
}
|
||||
|
||||
VkImageView Texture2D::GetImageView() const
|
||||
{
|
||||
CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static");
|
||||
return imageViews.front();
|
||||
}
|
||||
|
||||
VkImageView Texture2D::GetImageView(int index)
|
||||
{
|
||||
CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture");
|
||||
return imageViews[index];
|
||||
}
|
||||
|
||||
void Texture2D::InitializeTextureImage(const std::string& filename)
|
||||
{
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
int texChannels;
|
||||
stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
||||
|
||||
CP_ASSERT(pixels, "InitializeTextureImage : Failed to load texture image");
|
||||
|
||||
VkDeviceSize bufferSize = texWidth * texHeight * 4;
|
||||
Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
|
||||
void* data = stagingBuffer.Map();
|
||||
memcpy(data, pixels, bufferSize);
|
||||
stagingBuffer.Unmap();
|
||||
stbi_image_free(pixels);
|
||||
|
||||
images.resize(1);
|
||||
imageMemories.resize(1);
|
||||
imageViews.resize(1);
|
||||
Image::InitializeImage(instance, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images.front(), &imageMemories.front());
|
||||
Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight);
|
||||
Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
|
||||
void Texture2D::InitializeTexture(int width, int height)
|
||||
{
|
||||
int count = 1;
|
||||
if (type == Type::Dynamic)
|
||||
count = instance.GetMaxFramesInFlight();
|
||||
images.resize(count);
|
||||
imageMemories.resize(count);
|
||||
imageViews.resize(count);
|
||||
for (size_t i = 0; i < images.size(); i++)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case Format::Color:
|
||||
{
|
||||
Image::InitializeImage(instance, width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]);
|
||||
// Image::TransitionImageLayout(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
break;
|
||||
}
|
||||
case Format::Depth:
|
||||
{
|
||||
VkFormat depthFormat = Image::SelectDepthFormat(instance);
|
||||
Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]);
|
||||
// Image::TransitionImageLayout(instance, images[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
imageViews[i] = Image::InitializeImageView(instance, images[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
break;
|
||||
}
|
||||
case Format::Image:
|
||||
{
|
||||
CP_ABORT("InitializeTexture : Image format currently not supported");
|
||||
}
|
||||
default:
|
||||
CP_ABORT("InitializeTexture : Unreachable switch case");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::InitializeSampler()
|
||||
{
|
||||
VkPhysicalDeviceProperties properties{};
|
||||
vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties);
|
||||
|
||||
VkSamplerCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
createInfo.magFilter = VK_FILTER_LINEAR;
|
||||
createInfo.minFilter = VK_FILTER_LINEAR;
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
createInfo.anisotropyEnable = VK_TRUE;
|
||||
createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
|
||||
createInfo.unnormalizedCoordinates = VK_FALSE;
|
||||
createInfo.compareEnable = VK_FALSE;
|
||||
createInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
createInfo.mipLodBias = 0.0f;
|
||||
createInfo.minLod = 0.0f;
|
||||
createInfo.maxLod = 0.0f;
|
||||
|
||||
CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler");
|
||||
}
|
||||
Reference in New Issue
Block a user