diff --git a/CopiumEngine/src/copium/asset/Asset.h b/CopiumEngine/src/copium/asset/Asset.h index 95c6a70..8bf7c55 100644 --- a/CopiumEngine/src/copium/asset/Asset.h +++ b/CopiumEngine/src/copium/asset/Asset.h @@ -3,6 +3,7 @@ #include #include "copium/asset/AssetMeta.h" +#include "copium/util/Common.h" #include "copium/util/Uuid.h" namespace Copium @@ -15,6 +16,7 @@ namespace Copium public: Asset(); virtual ~Asset(); + CP_DELETE_COPY_AND_MOVE_CTOR(Asset); const std::string& GetName() const; Uuid GetUuid() const; diff --git a/CopiumEngine/src/copium/asset/AssetManager.h b/CopiumEngine/src/copium/asset/AssetManager.h index 03d2b26..1ced991 100644 --- a/CopiumEngine/src/copium/asset/AssetManager.h +++ b/CopiumEngine/src/copium/asset/AssetManager.h @@ -42,6 +42,8 @@ namespace Copium template static void RegisterAssetType(const std::string& assetType) { + static_assert(std::is_constructible_v, + "AssetType must be constructable from MetaFileClass"); CP_ASSERT(assetTypes.emplace(assetType, &AssetManager::CreateAsset).second, "Asset type already exists: {}", assetType.c_str()); @@ -97,14 +99,16 @@ namespace Copium static Asset& LoadAssetFromPath(const std::string& filepath); template - static Asset& CreateAsset(const MetaFile& metaFile, const std::string& metaFileClass) + static Asset& CreateAsset(const MetaFile& metaFile, const std::string& assetName) { + const MetaFileClass& metaFileClass = metaFile.GetMetaClass(assetName); + AssetId id = assetId++; pathToAssetCache.emplace(metaFile.GetFilePath(), id); - Asset& asset = *assets.emplace(id, std::make_unique(metaFile)).first->second.get(); + Asset& asset = *assets.emplace(id, std::make_unique(metaFileClass)).first->second.get(); asset.metaData.id = id; asset.metaData.name = metaFile.GetFilePath(); - asset.metaData.uuid = Uuid{metaFile.GetMetaClass(metaFileClass).GetValue("uuid")}; + asset.metaData.uuid = Uuid{metaFileClass.GetValue("uuid")}; asset.metaData.isRuntime = false; return asset; } diff --git a/CopiumEngine/src/copium/buffer/Framebuffer.cpp b/CopiumEngine/src/copium/buffer/Framebuffer.cpp index da42cf1..535e706 100644 --- a/CopiumEngine/src/copium/buffer/Framebuffer.cpp +++ b/CopiumEngine/src/copium/buffer/Framebuffer.cpp @@ -6,9 +6,8 @@ namespace Copium { - Framebuffer::Framebuffer(const MetaFile& metaFile) + Framebuffer::Framebuffer(const MetaFileClass& metaClass) { - const MetaFileClass& metaClass = metaFile.GetMetaClass("Framebuffer"); colorAttachment = AssetRef(Uuid{metaClass.GetValue("rendertexture-uuid")}); ColorAttachment& attachment = colorAttachment.GetAsset(); diff --git a/CopiumEngine/src/copium/buffer/Framebuffer.h b/CopiumEngine/src/copium/buffer/Framebuffer.h index 83a54d6..f0a909b 100644 --- a/CopiumEngine/src/copium/buffer/Framebuffer.h +++ b/CopiumEngine/src/copium/buffer/Framebuffer.h @@ -25,7 +25,7 @@ namespace Copium int height; public: - Framebuffer(const MetaFile& metaFile); + Framebuffer(const MetaFileClass& metaClass); Framebuffer(int width, int height, const SamplerCreator& samplerCreator); ~Framebuffer(); diff --git a/CopiumEngine/src/copium/core/SwapChain.cpp b/CopiumEngine/src/copium/core/SwapChain.cpp index 58a2ddc..77f9e3f 100644 --- a/CopiumEngine/src/copium/core/SwapChain.cpp +++ b/CopiumEngine/src/copium/core/SwapChain.cpp @@ -264,7 +264,8 @@ namespace Copium imageViews.resize(images.size()); for (size_t i = 0; i < images.size(); i++) { - imageViews[i] = Image::InitializeImageView(images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT); + imageViews[i] = + Image::InitializeImageView(images[i], imageFormat, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); } } diff --git a/CopiumEngine/src/copium/core/Vulkan.cpp b/CopiumEngine/src/copium/core/Vulkan.cpp index 0c12bd0..b6272b9 100644 --- a/CopiumEngine/src/copium/core/Vulkan.cpp +++ b/CopiumEngine/src/copium/core/Vulkan.cpp @@ -6,6 +6,7 @@ #include "copium/sampler/ColorAttachment.h" #include "copium/sampler/Font.h" #include "copium/sampler/Texture2D.h" +#include "copium/sampler/Texture2DArray.h" #include "copium/util/Timer.h" namespace Copium @@ -35,6 +36,7 @@ namespace Copium timer.Start(); AssetManager::RegisterAssetType("Texture2D"); + AssetManager::RegisterAssetType("Texture2DArray"); AssetManager::RegisterAssetType("RenderTexture"); AssetManager::RegisterAssetType("Pipeline"); AssetManager::RegisterAssetType("Framebuffer"); diff --git a/CopiumEngine/src/copium/pipeline/Pipeline.cpp b/CopiumEngine/src/copium/pipeline/Pipeline.cpp index 8527b51..fb2bc54 100644 --- a/CopiumEngine/src/copium/pipeline/Pipeline.cpp +++ b/CopiumEngine/src/copium/pipeline/Pipeline.cpp @@ -10,15 +10,13 @@ namespace Copium { - Pipeline::Pipeline(const MetaFile& metaFile) - : shaderReflector{ShaderReflector{metaFile.GetMetaClass("Pipeline").GetValue("vert-filepath"), - metaFile.GetMetaClass("Pipeline").GetValue("frag-filepath")}} + Pipeline::Pipeline(const MetaFileClass& metaClass) + : shaderReflector{ShaderReflector{metaClass.GetValue("vert-filepath"), metaClass.GetValue("frag-filepath")}} { - const MetaFileClass& metaFileClass = metaFile.GetMetaClass("Pipeline"); VkRenderPass renderPass; - if (metaFileClass.HasValue("framebuffer-uuid")) + if (metaClass.HasValue("framebuffer-uuid")) { - framebuffer = AssetRef(Uuid{metaFileClass.GetValue("framebuffer-uuid")}); + framebuffer = AssetRef(Uuid{metaClass.GetValue("framebuffer-uuid")}); Framebuffer& fb = framebuffer.GetAsset(); renderPass = fb.GetRenderPass(); } @@ -26,9 +24,8 @@ namespace Copium { renderPass = Vulkan::GetSwapChain().GetRenderPass(); } - PipelineCreator creator{ - renderPass, metaFileClass.GetValue("vert-filepath"), metaFileClass.GetValue("frag-filepath")}; - std::string type = metaFileClass.GetValue("type"); + PipelineCreator creator{renderPass, metaClass.GetValue("vert-filepath"), metaClass.GetValue("frag-filepath")}; + std::string type = metaClass.GetValue("type"); if (type == "Renderer") { creator.SetVertexDescriptor(RendererVertex::GetDescriptor()); @@ -43,14 +40,14 @@ namespace Copium else if (type == "Mesh") { creator.SetVertexDescriptor(Vertex::GetDescriptor()); - creator.SetBlending(metaFileClass.GetValue("alpha-blending", "false") == "true" ? true : false); - creator.SetDepthTest(metaFileClass.GetValue("depth-test", "true") == "true" ? true : false); + creator.SetBlending(metaClass.GetValue("alpha-blending", "false") == "true" ? true : false); + creator.SetDepthTest(metaClass.GetValue("depth-test", "true") == "true" ? true : false); } else if (type == "LineRenderer") { creator.SetVertexDescriptor(LineVertex::GetDescriptor()); creator.SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST); - creator.SetDepthTest(metaFileClass.GetValue("depth-test", "false") == "true" ? true : false); + creator.SetDepthTest(metaClass.GetValue("depth-test", "false") == "true" ? true : false); } InitializeDescriptorSetLayout(creator); InitializePipeline(creator); diff --git a/CopiumEngine/src/copium/pipeline/Pipeline.h b/CopiumEngine/src/copium/pipeline/Pipeline.h index a77d8e4..a12c8e4 100644 --- a/CopiumEngine/src/copium/pipeline/Pipeline.h +++ b/CopiumEngine/src/copium/pipeline/Pipeline.h @@ -26,7 +26,7 @@ namespace Copium AssetRef framebuffer; public: - Pipeline(const MetaFile& metaFile); + Pipeline(const MetaFileClass& metaClass); Pipeline(PipelineCreator creator); ~Pipeline(); void Bind(const CommandBuffer& commandBuffer); diff --git a/CopiumEngine/src/copium/pipeline/ShaderReflector.cpp b/CopiumEngine/src/copium/pipeline/ShaderReflector.cpp index 4d220e5..44285fe 100644 --- a/CopiumEngine/src/copium/pipeline/ShaderReflector.cpp +++ b/CopiumEngine/src/copium/pipeline/ShaderReflector.cpp @@ -103,7 +103,7 @@ namespace Copium } ParseLine(str, index); - if (type == "sampler2D") + if (type == "sampler2D" || type == "sampler2DArray") shaderBinding.bindingType = BindingType::Sampler2D; else shaderBinding.bindingType = BindingType::UniformBuffer; diff --git a/CopiumEngine/src/copium/sampler/ColorAttachment.cpp b/CopiumEngine/src/copium/sampler/ColorAttachment.cpp index d539a8b..c007b00 100644 --- a/CopiumEngine/src/copium/sampler/ColorAttachment.cpp +++ b/CopiumEngine/src/copium/sampler/ColorAttachment.cpp @@ -6,10 +6,9 @@ namespace Copium { - ColorAttachment::ColorAttachment(const MetaFile& metaFile) - : Sampler{SamplerCreator{metaFile.GetMetaClass("RenderTexture")}} + ColorAttachment::ColorAttachment(const MetaFileClass& metaClass) + : Sampler{SamplerCreator{metaClass}} { - const MetaFileClass& metaClass = metaFile.GetMetaClass("RenderTexture"); if (metaClass.HasValue("width")) { char* endPtr; @@ -109,7 +108,8 @@ namespace Copium VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]); - imageViews[i] = Image::InitializeImageView(images[i], VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + imageViews[i] = Image::InitializeImageView( + images[i], VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); } } } diff --git a/CopiumEngine/src/copium/sampler/ColorAttachment.h b/CopiumEngine/src/copium/sampler/ColorAttachment.h index c50e47a..f2008ba 100644 --- a/CopiumEngine/src/copium/sampler/ColorAttachment.h +++ b/CopiumEngine/src/copium/sampler/ColorAttachment.h @@ -19,7 +19,7 @@ namespace Copium int height; public: - ColorAttachment(const MetaFile& metaFile); + ColorAttachment(const MetaFileClass& metaClass); ColorAttachment(int width, int height, const SamplerCreator& samplerCreator); ~ColorAttachment() override; diff --git a/CopiumEngine/src/copium/sampler/DepthAttachment.cpp b/CopiumEngine/src/copium/sampler/DepthAttachment.cpp index 35981ba..bc8d7c8 100644 --- a/CopiumEngine/src/copium/sampler/DepthAttachment.cpp +++ b/CopiumEngine/src/copium/sampler/DepthAttachment.cpp @@ -58,6 +58,6 @@ namespace Copium VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory); - imageView = Image::InitializeImageView(image, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + imageView = Image::InitializeImageView(image, depthFormat, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT); } -} \ No newline at end of file +} diff --git a/CopiumEngine/src/copium/sampler/Font.cpp b/CopiumEngine/src/copium/sampler/Font.cpp index 8154ff3..69a1b81 100644 --- a/CopiumEngine/src/copium/sampler/Font.cpp +++ b/CopiumEngine/src/copium/sampler/Font.cpp @@ -8,12 +8,12 @@ namespace Copium { - Font::Font(const MetaFile& metaFile) - : Sampler{SamplerCreator{metaFile.GetMetaClass("Font")}} + Font::Font(const MetaFileClass& metaClass) + : Sampler{SamplerCreator{metaClass}} { msdfgen::FreetypeHandle* ft = msdfgen::initializeFreetype(); CP_ASSERT(ft, "Failed to initialize FreeType"); // TODO: Move to Vulkan singleton class? - std::string fontPath = metaFile.GetMetaClass("Font").GetValue("filepath"); + std::string fontPath = metaClass.GetValue("filepath"); msdfgen::FontHandle* font = msdfgen::loadFont(ft, fontPath.c_str()); CP_ASSERT(font, "Failed to initialize font: {}", fontPath); @@ -178,6 +178,7 @@ namespace Copium Image::CopyBufferToImage(stagingBuffer, image, width, height); Image::TransitionImageLayout( image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageView = Image::InitializeImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + imageView = + Image::InitializeImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); } } diff --git a/CopiumEngine/src/copium/sampler/Font.h b/CopiumEngine/src/copium/sampler/Font.h index a64d688..f045ae1 100644 --- a/CopiumEngine/src/copium/sampler/Font.h +++ b/CopiumEngine/src/copium/sampler/Font.h @@ -20,7 +20,7 @@ namespace Copium float baseHeight; public: - Font(const MetaFile& metaFile); + Font(const MetaFileClass& metaClass); ~Font() override; VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override; diff --git a/CopiumEngine/src/copium/sampler/Image.cpp b/CopiumEngine/src/copium/sampler/Image.cpp index fb366ab..9c3c398 100644 --- a/CopiumEngine/src/copium/sampler/Image.cpp +++ b/CopiumEngine/src/copium/sampler/Image.cpp @@ -3,6 +3,9 @@ #include "copium/buffer/CommandBufferScoped.h" #include "copium/core/Vulkan.h" +#define STB_IMAGE_IMPLEMENTATION +#include + namespace Copium { void Image::InitializeImage(uint32_t width, @@ -13,6 +16,19 @@ namespace Copium VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory) + { + InitializeImage(width, height, 1, format, tiling, usage, properties, image, imageMemory); + } + + void Image::InitializeImage(uint32_t width, + uint32_t height, + uint32_t layers, + VkFormat format, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkMemoryPropertyFlags properties, + VkImage* image, + VkDeviceMemory* imageMemory) { VkImageCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -21,7 +37,7 @@ namespace Copium createInfo.extent.height = height; createInfo.extent.depth = 1; createInfo.mipLevels = 1; - createInfo.arrayLayers = 1; + createInfo.arrayLayers = layers; createInfo.format = format; createInfo.tiling = tiling; createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -46,13 +62,14 @@ namespace Copium vkBindImageMemory(Vulkan::GetDevice(), *image, *imageMemory, 0); } - VkImageView Image::InitializeImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) + VkImageView Image::InitializeImageView( + VkImage image, VkFormat format, VkImageViewType imageViewType, VkImageAspectFlags aspectFlags, uint32_t layers) { VkImageView imageView; VkImageViewCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.image = image; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.viewType = imageViewType; createInfo.format = format; createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; @@ -62,13 +79,18 @@ namespace Copium createInfo.subresourceRange.baseMipLevel = 0; createInfo.subresourceRange.levelCount = 1; createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; + createInfo.subresourceRange.layerCount = layers; CP_VK_ASSERT(vkCreateImageView(Vulkan::GetDevice(), &createInfo, nullptr, &imageView), "Failed to initialize image view"); return imageView; } - void Image::TransitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) + void Image::TransitionImageLayout(VkImage image, + VkFormat format, + VkImageLayout oldLayout, + VkImageLayout newLayout, + uint32_t baseLayer, + uint32_t layers) { CommandBufferScoped commandBuffer{}; @@ -81,8 +103,8 @@ namespace Copium barrier.image = image; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.baseArrayLayer = baseLayer; + barrier.subresourceRange.layerCount = layers; barrier.srcAccessMask = 0; barrier.dstAccessMask = 0; @@ -144,7 +166,8 @@ namespace Copium vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); } - void Image::CopyBufferToImage(const Buffer& buffer, VkImage image, uint32_t width, uint32_t height) + void Image::CopyBufferToImage( + const Buffer& buffer, VkImage image, uint32_t width, uint32_t height, uint32_t baseLayer, uint32_t layers) { CommandBufferScoped commandBuffer{}; @@ -155,8 +178,8 @@ namespace Copium region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; + region.imageSubresource.baseArrayLayer = baseLayer; + region.imageSubresource.layerCount = layers; region.imageOffset = {0, 0, 0}; region.imageExtent = {width, height, 1}; diff --git a/CopiumEngine/src/copium/sampler/Image.h b/CopiumEngine/src/copium/sampler/Image.h index 90d5754..65f302c 100644 --- a/CopiumEngine/src/copium/sampler/Image.h +++ b/CopiumEngine/src/copium/sampler/Image.h @@ -20,9 +20,33 @@ namespace Copium VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory); - static VkImageView InitializeImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags); - static void TransitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout); - static void CopyBufferToImage(const Buffer& buffer, VkImage image, uint32_t width, uint32_t height); + static void InitializeImage(uint32_t width, + uint32_t height, + uint32_t layers, + VkFormat format, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkMemoryPropertyFlags properties, + VkImage* image, + VkDeviceMemory* imageMemory); + + static VkImageView InitializeImageView(VkImage image, + VkFormat format, + VkImageViewType imageViewType, + VkImageAspectFlags aspectFlags, + uint32_t layers = 1); + static void TransitionImageLayout(VkImage image, + VkFormat format, + VkImageLayout oldLayout, + VkImageLayout newLayout, + uint32_t baseLayer = 0, + uint32_t layers = 1); + static void CopyBufferToImage(const Buffer& buffer, + VkImage image, + uint32_t width, + uint32_t height, + uint32_t baseLayer = 0, + uint32_t layers = 1); static VkFormat SelectDepthFormat(); private: diff --git a/CopiumEngine/src/copium/sampler/Texture2D.cpp b/CopiumEngine/src/copium/sampler/Texture2D.cpp index 9535927..0635886 100644 --- a/CopiumEngine/src/copium/sampler/Texture2D.cpp +++ b/CopiumEngine/src/copium/sampler/Texture2D.cpp @@ -1,17 +1,16 @@ #include "copium/sampler/Texture2D.h" +#include + #include "copium/core/Vulkan.h" #include "copium/sampler/Image.h" -#define STB_IMAGE_IMPLEMENTATION -#include - namespace Copium { - Texture2D::Texture2D(const MetaFile& metaFile) - : Sampler{metaFile.GetMetaClass("Texture2D")} + Texture2D::Texture2D(const MetaFileClass& metaClass) + : Sampler{metaClass} { - const std::string& filepath = metaFile.GetMetaClass("Texture2D").GetValue("filepath"); + const std::string& filepath = metaClass.GetValue("filepath"); CP_DEBUG("Loading texture file: {}", filepath); InitializeTextureImageFromFile(filepath); } @@ -106,6 +105,7 @@ namespace Copium Image::CopyBufferToImage(stagingBuffer, image, width, height); Image::TransitionImageLayout( image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageView = Image::InitializeImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + imageView = + Image::InitializeImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); } } diff --git a/CopiumEngine/src/copium/sampler/Texture2D.h b/CopiumEngine/src/copium/sampler/Texture2D.h index d635dc8..ef1c516 100644 --- a/CopiumEngine/src/copium/sampler/Texture2D.h +++ b/CopiumEngine/src/copium/sampler/Texture2D.h @@ -18,7 +18,7 @@ namespace Copium int height; public: - Texture2D(const MetaFile& metaFile); + Texture2D(const MetaFileClass& metaClass); Texture2D(const std::vector& rgbaData, int width, int height, const SamplerCreator& samplerCreator); ~Texture2D() override; diff --git a/CopiumEngine/src/copium/sampler/Texture2DArray.cpp b/CopiumEngine/src/copium/sampler/Texture2DArray.cpp new file mode 100644 index 0000000..d21eaa4 --- /dev/null +++ b/CopiumEngine/src/copium/sampler/Texture2DArray.cpp @@ -0,0 +1,186 @@ +#include "copium/sampler/Texture2DArray.h" + +#include + +#include "copium/core/Vulkan.h" +#include "copium/sampler/Image.h" + +namespace Copium +{ +#define IMAGE_SIZE_BYTES (width * height * 4u) + + Texture2DArray::Texture2DArray(const MetaFileClass& metaClass) + : Sampler{metaClass}, + width{std::stoi(metaClass.GetValue("width"))}, + height{std::stoi(metaClass.GetValue("height"))}, + layers{std::stoi(metaClass.GetValue("layers"))} + { + InitializeTextureImage(); + } + + Texture2DArray::Texture2DArray(const SamplerCreator& samplerCreator, int width, int height, int layers) + : Sampler{samplerCreator}, + width{width}, + height{height}, + layers{layers} + { + InitializeTextureImage(); + } + + Texture2DArray::~Texture2DArray() + { + VkImage imageCpy = image; + VkDeviceMemory imageMemoryCpy = imageMemory; + VkImageView imageViewCpy = imageView; + Vulkan::GetDevice().QueueIdleCommand( + [imageCpy, imageMemoryCpy, imageViewCpy]() + { + vkDestroyImage(Vulkan::GetDevice(), imageCpy, nullptr); + vkFreeMemory(Vulkan::GetDevice(), imageMemoryCpy, nullptr); + vkDestroyImageView(Vulkan::GetDevice(), imageViewCpy, nullptr); + }); + } + + VkDescriptorImageInfo Texture2DArray::GetDescriptorImageInfo(int index) const + { + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.sampler = sampler; + imageInfo.imageView = imageView; + + return imageInfo; + } + + int Texture2DArray::GetWidth() const + { + return width; + } + + int Texture2DArray::GetHeight() const + { + return height; + } + + void Texture2DArray::InitializeTextureImage() + { + Image::InitializeImage(width, + height, + layers, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &image, + &imageMemory); + imageView = Image::InitializeImageView( + image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT, layers); + + imageData.resize(width * height * layers * 4); + for (int i = 0; i < layers; i++) + { + for (int j = 0; j < width * height; j++) + { + imageData[i * IMAGE_SIZE_BYTES + j * 4 + 0] = 255; + imageData[i * IMAGE_SIZE_BYTES + j * 4 + 1] = 0; + imageData[i * IMAGE_SIZE_BYTES + j * 4 + 2] = 255; + imageData[i * IMAGE_SIZE_BYTES + j * 4 + 3] = 255; + } + } + used.resize(layers, false); + Update(); + } + + size_t Texture2DArray::AddImage(const std::string& filePath) + { + stbi_set_flip_vertically_on_load(true); + int texWidth; + int texHeight; + int texChannels; + stbi_uc* pixels = stbi_load(filePath.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); + + CP_ASSERT(pixels, "Failed to load texture image"); + CP_ASSERT(texWidth == width, "width={} of {} doesn't match width={} of Texture2DArray", texWidth, filePath, width); + CP_ASSERT( + texHeight == height, "height={} of {} doesn't match height={} of Texture2DArray", texHeight, filePath, height); + return AddImage(pixels); + } + + size_t Texture2DArray::AddImage(const std::vector& rgbaData) + { + CP_ASSERT(rgbaData.size() == width * height * 4, + "Invalid rgbaData size. size = {}, but expected size is {}", + rgbaData.size(), + width * height * 4); + return AddImage(rgbaData.data()); + } + + size_t Texture2DArray::AddImage(const uint8_t* rgbaData) + { + for (int i = 0; i < used.size(); i++) + { + if (used[i]) + continue; + + used[i] = true; + for (int j = 0; j < width * height * 4; j++) + { + imageData[i * width * height * 4 + j] = rgbaData[j]; + } + // TODO: Probably shouldn't run this every time an image is added (especially when initializing the Texture2DArray + Update(i); + return i; + } + + CP_ABORT("Texture2DArray is full"); + return 0; + } + + void Texture2DArray::RemoveImage(size_t index) + { + CP_ASSERT(index < layers, "index={} out of range of texture array with size={}", index, layers); + CP_ASSERT(used[index], "index={} is not in use", index); + + used[index] = false; + } + + void Texture2DArray::Update(uint32_t layer) + { + Buffer stagingBuffer{VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + IMAGE_SIZE_BYTES, + 1}; + void* data = stagingBuffer.Map(); + memcpy(data, imageData.data() + layer * IMAGE_SIZE_BYTES, IMAGE_SIZE_BYTES); + stagingBuffer.Unmap(); + + Image::TransitionImageLayout( + image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layer); + Image::CopyBufferToImage(stagingBuffer, image, width, height, layer); + Image::TransitionImageLayout(image, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + layer); + } + + void Texture2DArray::Update() + { + Buffer stagingBuffer{VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + imageData.size(), + 1}; + void* data = stagingBuffer.Map(); + memcpy(data, imageData.data(), imageData.size()); + stagingBuffer.Unmap(); + + Image::TransitionImageLayout( + image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, layers); + Image::CopyBufferToImage(stagingBuffer, image, width, height, 0, layers); + Image::TransitionImageLayout(image, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + 0, + layers); + } +} diff --git a/CopiumEngine/src/copium/sampler/Texture2DArray.h b/CopiumEngine/src/copium/sampler/Texture2DArray.h new file mode 100644 index 0000000..6aeb956 --- /dev/null +++ b/CopiumEngine/src/copium/sampler/Texture2DArray.h @@ -0,0 +1,45 @@ +#pragma once + +#include "copium/sampler/Sampler.h" +#include "copium/util/Common.h" + +namespace Copium +{ + class Texture2DArray final : public Sampler + { + CP_DELETE_COPY_AND_MOVE_CTOR(Texture2DArray); + + private: + VkImage image; + VkDeviceMemory imageMemory; + VkImageView imageView; + + int width; + int height; + int layers; + + std::vector imageData; + std::vector used; + + public: + Texture2DArray(const MetaFileClass& metaClass); + Texture2DArray(const SamplerCreator& samplerCreator, int width, int height, int layers); + ~Texture2DArray() override; + + size_t AddImage(const std::string& filePath); + size_t AddImage(const std::vector& rgbaData); + void RemoveImage(size_t index); + + void Update(); + void Update(uint32_t layer); + + VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override; + + int GetWidth() const; + int GetHeight() const; + + private: + void InitializeTextureImage(); + size_t AddImage(const uint8_t* rgbaData); + }; +} diff --git a/CopiumEngine/src/copium/util/Mapper.h b/CopiumEngine/src/copium/util/Mapper.h new file mode 100644 index 0000000..9143b0d --- /dev/null +++ b/CopiumEngine/src/copium/util/Mapper.h @@ -0,0 +1,122 @@ +#pragma once + +#include + +#include "copium/util/Trace.h" + +namespace Copium +{ + template + class Mapper + { + public: + Mapper() = default; + + Mapper(const std::map& map) + { + for (const auto& [first, second] : map) + { + Emplace(first, second); + } + } + + void Emplace(const First& first, const Second& second) + { + CP_ASSERT(secondToFirst.count(second) == 0, "Duplicate second key={}", second); + + firstToSecond.emplace(first, second); + secondToFirst.emplace(second, first); + } + + Second& operator[](const First& first) + { + return firstToSecond[first]; + } + + void Erase(const First& first) + { + auto it = firstToSecond.find(first); + CP_ASSERT(it != firstToSecond.end(), "First key={} not found in Mapper", first); + + const auto& second = it->second; + secondToFirst.erase(second); + firstToSecond.erase(first); + } + + void Erase(const Second& second) + { + auto it = secondToFirst.find(second); + CP_ASSERT(it != secondToFirst.end(), "Second key={} not found in Mapper", second); + + const auto& first = it->second; + secondToFirst.erase(first); + firstToSecond.erase(second); + } + + const Second& GetSecond(const First& first) const + { + auto it = firstToSecond.find(first); + CP_ASSERT(it != firstToSecond.end(), "First key={} not found in Mapper", first); + } + + const First& GetFirst(const Second& second) const + { + auto it = secondToFirst.find(second); + CP_ASSERT(it != secondToFirst.end(), "Second key={} not found in Mapper", second); + } + + bool HasSecond(const First& first) const + { + return firstToSecond.find(first) != firstToSecond.end(); + } + + bool HasFirst(const Second& second) const + { + return secondToFirst.find(second) != secondToFirst.end(); + } + + typename std::map::const_iterator FindSecond(const First& first) const + { + return firstToSecond.find(first); + } + + typename std::map::const_iterator FindFirst(const Second& second) const + { + return secondToFirst.find(second); + } + + typename std::map::iterator begin() + { + return firstToSecond.begin(); + } + + typename std::map::iterator end() + { + return firstToSecond.end(); + } + + typename std::map::const_iterator begin() const + { + return firstToSecond.cbegin(); + } + + typename std::map::const_iterator end() const + { + return firstToSecond.cend(); + } + + typename std::map::const_iterator cbegin() const + { + return firstToSecond.cbegin(); + } + + typename std::map::const_iterator cend() const + { + return firstToSecond.cend(); + } + + private: + std::map firstToSecond; + std::map secondToFirst; + }; +} diff --git a/CopiumEngine/src/copium/util/StateMachine.h b/CopiumEngine/src/copium/util/StateMachine.h index 34514fa..a25d420 100644 --- a/CopiumEngine/src/copium/util/StateMachine.h +++ b/CopiumEngine/src/copium/util/StateMachine.h @@ -3,7 +3,7 @@ #include #include -namespace copium +namespace Copium { template class StateMachine