Fix non-srgb texture loads and unnecessary dedicated memory.

This commit is contained in:
Anish Bhobe 2024-07-23 15:34:20 +02:00
parent 44121f1930
commit b9ee037216
3 changed files with 48 additions and 42 deletions

View File

@ -44,7 +44,7 @@ Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageF
.initialLayout = vk::ImageLayout::eUndefined, .initialLayout = vk::ImageLayout::eUndefined,
}; };
constexpr VmaAllocationCreateInfo allocationCreateInfo = { constexpr VmaAllocationCreateInfo allocationCreateInfo = {
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, .flags = {},
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };

View File

@ -19,6 +19,7 @@
#include "image.h" #include "image.h"
#include <EASTL/array.h> #include <EASTL/array.h>
#include <EASTL/hash_map.h>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
vec4 vec4
@ -46,15 +47,17 @@ VectorToVec3(const std::vector<double> &vec)
} }
TextureHandle 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); assert(image->component == 4);
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
Texture texture; Texture texture;
usize byteSize = image->image.size(); usize byteSize = image->image.size();
texture.Init(m_ResourceManager->m_Device, {.width = Cast<u32>(image->width), .height = Cast<u32>(image->height)}, texture.Init(m_ResourceManager->m_Device, {.width = Cast<u32>(image->width), .height = Cast<u32>(image->height)},
vk::Format::eR8G8B8A8Srgb, true, image->name.data()); imageFormat, true, image->name.data());
stagingBuffer->Init(m_ResourceManager->m_Device, byteSize); stagingBuffer->Init(m_ResourceManager->m_Device, byteSize);
stagingBuffer->Write(m_ResourceManager->m_Device, 0, byteSize, image->image.data()); stagingBuffer->Write(m_ResourceManager->m_Device, 0, byteSize, image->image.data());
@ -127,11 +130,11 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
.imageExtent = texture.m_Extent, .imageExtent = texture.m_Extent,
}; };
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0,
nullptr, 0, nullptr, 1, &imageStartBarrier); nullptr, 0, nullptr, 1, &imageStartBarrier);
commandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture.m_Image, vk::ImageLayout::eTransferDstOptimal, 1, m_CommandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture.m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
&imageCopy); &imageCopy);
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0, m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0,
nullptr, 0, nullptr, 1, &nextMipBarrier); nullptr, 0, nullptr, 1, &nextMipBarrier);
auto calcNextMip = [](i32 prev) { return eastl::max(prev / 2, 1); }; 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; nextMipBarrier.subresourceRange.baseMipLevel = currentMipLevel;
commandBuffer.blitImage(texture.m_Image, vk::ImageLayout::eTransferSrcOptimal, texture.m_Image, m_CommandBuffer.blitImage(texture.m_Image, vk::ImageLayout::eTransferSrcOptimal, texture.m_Image,
vk::ImageLayout::eTransferDstOptimal, 1, &blitRegion, vk::Filter::eLinear); vk::ImageLayout::eTransferDstOptimal, 1, &blitRegion, vk::Filter::eLinear);
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0, m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {},
nullptr, 0, nullptr, 1, &nextMipBarrier); 0, nullptr, 0, nullptr, 1, &nextMipBarrier);
prevMipHeight = currentMipHeight; prevMipHeight = currentMipHeight;
prevMipWidth = currentMipWidth; prevMipWidth = currentMipWidth;
} }
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, m_CommandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader,
0, nullptr, 0, nullptr, 1, &imageReadyBarrier); {}, 0, nullptr, 0, nullptr, 1, &imageReadyBarrier);
return m_ResourceManager->Commit(&texture); return m_ResourceManager->Commit(&texture);
} }
@ -227,23 +230,8 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
} }
eastl::vector<StagingBuffer> stagingBuffers; eastl::vector<StagingBuffer> stagingBuffers;
eastl::vector<TextureHandle> textureHandles;
// TODO: MetalRough and Occlusion Textures are non-sRGB eastl::hash_map<i32, TextureHandle> textureHandleMap;
if (!model.images.empty())
{
u32 numImages = Cast<u32>(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::vector<Material> materials; eastl::vector<Material> materials;
StorageBuffer materialsBuffer; StorageBuffer materialsBuffer;
@ -251,12 +239,22 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
if (!model.materials.empty()) if (!model.materials.empty())
{ {
auto getTextureHandle = [&textureHandles](i32 index) -> TextureHandle { auto getTextureHandle = [this, &textureHandleMap, &stagingBuffers, &model](i32 index,
if (index >= 0) 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()); materials.reserve(model.materials.size());
@ -267,11 +265,12 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
.m_EmissionFactor = VectorToVec3(material.emissiveFactor), .m_EmissionFactor = VectorToVec3(material.emissiveFactor),
.m_MetalFactor = Cast<f32>(material.pbrMetallicRoughness.metallicFactor), .m_MetalFactor = Cast<f32>(material.pbrMetallicRoughness.metallicFactor),
.m_RoughFactor = Cast<f32>(material.pbrMetallicRoughness.roughnessFactor), .m_RoughFactor = Cast<f32>(material.pbrMetallicRoughness.roughnessFactor),
.m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index), .m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index, true),
.m_NormalTex = getTextureHandle(material.normalTexture.index), .m_NormalTex = getTextureHandle(material.normalTexture.index, false),
.m_MetalRoughTex = getTextureHandle(material.pbrMetallicRoughness.metallicRoughnessTexture.index), .m_MetalRoughTex =
.m_OcclusionTex = getTextureHandle(material.occlusionTexture.index), getTextureHandle(material.pbrMetallicRoughness.metallicRoughnessTexture.index, false),
.m_EmissionTex = getTextureHandle(material.emissiveTexture.index), .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, .m_NodeHandle = nodeHandle,
}; };
eastl::vector<TextureHandle> textureHandles;
textureHandles.reserve(textureHandleMap.size());
for (auto &[key, val] : textureHandleMap)
{
textureHandles.emplace_back(val);
}
return Model{ return Model{
m_ResourceManager, std::move(textureHandles), std::move(nodes), handles, indexBuffer, meshPrimitives, m_ResourceManager, std::move(textureHandles), std::move(nodes), handles, indexBuffer, meshPrimitives,
}; };

View File

@ -92,8 +92,7 @@ struct ModelLoader
u32 m_TransferQueueIndex; u32 m_TransferQueueIndex;
u32 m_GraphicsQueueIndex; u32 m_GraphicsQueueIndex;
TextureHandle TextureHandle LoadImage(StagingBuffer *stagingBuffer, tinygltf::Image *image, bool isSrgb) const;
LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer, tinygltf::Image *image) const;
Model LoadModel(cstr path, cstr name = nullptr, bool batched = false); Model LoadModel(cstr path, cstr name = nullptr, bool batched = false);
constexpr static auto ANormal = "NORMAL"; constexpr static auto ANormal = "NORMAL";