diff --git a/aster/image.cpp b/aster/image.cpp index eefd4bb..6d72a62 100644 --- a/aster/image.cpp +++ b/aster/image.cpp @@ -44,7 +44,7 @@ Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageF .initialLayout = vk::ImageLayout::eUndefined, }; constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, + .flags = {}, .usage = VMA_MEMORY_USAGE_AUTO, }; diff --git a/samples/03_model_render/model_loader.cpp b/samples/03_model_render/model_loader.cpp index 44e0598..566d6d9 100644 --- a/samples/03_model_render/model_loader.cpp +++ b/samples/03_model_render/model_loader.cpp @@ -19,6 +19,7 @@ #include "image.h" #include +#include #include vec4 @@ -46,15 +47,17 @@ VectorToVec3(const std::vector &vec) } TextureHandle -ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer, tinygltf::Image *image) const +ModelLoader::LoadImage(StagingBuffer *stagingBuffer, tinygltf::Image *image, bool isSrgb) const { assert(image->component == 4); + vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm; + Texture texture; usize byteSize = image->image.size(); texture.Init(m_ResourceManager->m_Device, {.width = Cast(image->width), .height = Cast(image->height)}, - vk::Format::eR8G8B8A8Srgb, true, image->name.data()); + imageFormat, true, image->name.data()); stagingBuffer->Init(m_ResourceManager->m_Device, byteSize); stagingBuffer->Write(m_ResourceManager->m_Device, 0, byteSize, image->image.data()); @@ -127,12 +130,12 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu .imageExtent = texture.m_Extent, }; - commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, - nullptr, 0, nullptr, 1, &imageStartBarrier); - commandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture.m_Image, vk::ImageLayout::eTransferDstOptimal, 1, - &imageCopy); - commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0, - nullptr, 0, nullptr, 1, &nextMipBarrier); + m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, + nullptr, 0, nullptr, 1, &imageStartBarrier); + m_CommandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture.m_Image, vk::ImageLayout::eTransferDstOptimal, 1, + &imageCopy); + m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0, + nullptr, 0, nullptr, 1, &nextMipBarrier); auto calcNextMip = [](i32 prev) { return eastl::max(prev / 2, 1); }; @@ -174,17 +177,17 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu }; nextMipBarrier.subresourceRange.baseMipLevel = currentMipLevel; - commandBuffer.blitImage(texture.m_Image, vk::ImageLayout::eTransferSrcOptimal, texture.m_Image, - vk::ImageLayout::eTransferDstOptimal, 1, &blitRegion, vk::Filter::eLinear); - commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0, - nullptr, 0, nullptr, 1, &nextMipBarrier); + m_CommandBuffer.blitImage(texture.m_Image, vk::ImageLayout::eTransferSrcOptimal, texture.m_Image, + vk::ImageLayout::eTransferDstOptimal, 1, &blitRegion, vk::Filter::eLinear); + m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, + 0, nullptr, 0, nullptr, 1, &nextMipBarrier); prevMipHeight = currentMipHeight; prevMipWidth = currentMipWidth; } - commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, - 0, nullptr, 0, nullptr, 1, &imageReadyBarrier); + m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, + {}, 0, nullptr, 0, nullptr, 1, &imageReadyBarrier); return m_ResourceManager->Commit(&texture); } @@ -227,23 +230,8 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) } eastl::vector stagingBuffers; - eastl::vector textureHandles; - // TODO: MetalRough and Occlusion Textures are non-sRGB - if (!model.images.empty()) - { - u32 numImages = Cast(model.images.size()); - - stagingBuffers.resize(numImages); - textureHandles.resize(numImages); - - auto stagingPtr = stagingBuffers.data(); - auto imagePtr = model.images.data(); - for (TextureHandle &handle : textureHandles) - { - handle = LoadImage(m_CommandBuffer, stagingPtr++, imagePtr++); - } - } + eastl::hash_map textureHandleMap; eastl::vector materials; StorageBuffer materialsBuffer; @@ -251,12 +239,22 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) if (!model.materials.empty()) { - auto getTextureHandle = [&textureHandles](i32 index) -> TextureHandle { - if (index >= 0) + auto getTextureHandle = [this, &textureHandleMap, &stagingBuffers, &model](i32 index, + bool isSrgb) -> TextureHandle { + if (index < 0) { - return textureHandles[index]; + return {}; } - return {}; + const auto iter = textureHandleMap.find(index); + if (iter != textureHandleMap.end()) + { + return iter->second; + } + + auto *image = &model.images[index]; + TextureHandle handle = LoadImage(&stagingBuffers.push_back(), image, isSrgb); + textureHandleMap.emplace(index, handle); + return handle; }; materials.reserve(model.materials.size()); @@ -267,11 +265,12 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) .m_EmissionFactor = VectorToVec3(material.emissiveFactor), .m_MetalFactor = Cast(material.pbrMetallicRoughness.metallicFactor), .m_RoughFactor = Cast(material.pbrMetallicRoughness.roughnessFactor), - .m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index), - .m_NormalTex = getTextureHandle(material.normalTexture.index), - .m_MetalRoughTex = getTextureHandle(material.pbrMetallicRoughness.metallicRoughnessTexture.index), - .m_OcclusionTex = getTextureHandle(material.occlusionTexture.index), - .m_EmissionTex = getTextureHandle(material.emissiveTexture.index), + .m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index, true), + .m_NormalTex = getTextureHandle(material.normalTexture.index, false), + .m_MetalRoughTex = + getTextureHandle(material.pbrMetallicRoughness.metallicRoughnessTexture.index, false), + .m_OcclusionTex = getTextureHandle(material.occlusionTexture.index, false), + .m_EmissionTex = getTextureHandle(material.emissiveTexture.index, true), }); } @@ -634,6 +633,14 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) .m_NodeHandle = nodeHandle, }; + eastl::vector textureHandles; + textureHandles.reserve(textureHandleMap.size()); + + for (auto &[key, val] : textureHandleMap) + { + textureHandles.emplace_back(val); + } + return Model{ m_ResourceManager, std::move(textureHandles), std::move(nodes), handles, indexBuffer, meshPrimitives, }; diff --git a/samples/03_model_render/model_loader.h b/samples/03_model_render/model_loader.h index 8db08da..2c8d31b 100644 --- a/samples/03_model_render/model_loader.h +++ b/samples/03_model_render/model_loader.h @@ -92,8 +92,7 @@ struct ModelLoader u32 m_TransferQueueIndex; u32 m_GraphicsQueueIndex; - TextureHandle - LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer, tinygltf::Image *image) const; + TextureHandle LoadImage(StagingBuffer *stagingBuffer, tinygltf::Image *image, bool isSrgb) const; Model LoadModel(cstr path, cstr name = nullptr, bool batched = false); constexpr static auto ANormal = "NORMAL";