Program Listing for File textureStorage.cpp
↰ Return to documentation for file (PrismEngine/src/textureStorage.cpp)
#include "memory"
#include "textureStorage.h"
#include "textureLoader.h"
void prism::PGC::L1::TextureStorage::createImpl() {
textureLoader = new PGC::L2::TextureLoader(context, settings);
textures.push_back(PGC::Texture{});
}
prism::TextureId prism::PGC::L1::TextureStorage::load(std::string texturePath) {
Texture texture = textureLoader->load(texturePath);
if (texture.image == VK_NULL_HANDLE) {
return INVALID_TEXTURE_ID;
}
uint32_t index = getNextAvailableIndex(context);
texture.bindlessIndex = index;
if (index >= textures.size()) {
textures.push_back(texture);
}
else {
textures[index] = texture;
}
updateDescriptors();
return index;
}
std::shared_ptr<prism::PGC::Texture> prism::PGC::L1::TextureStorage::get(TextureId textureId)
{
return std::make_shared<prism::PGC::Texture>(textures[textureId]);
}
bool prism::PGC::L1::TextureStorage::remove(TextureId textureId)
{
if (textureId == INVALID_TEXTURE_ID || textureId >= textures.size()) {
return false;
}
textureLoader->cleanup(&textures[textureId]);
freeTextureIndices.push_back(textureId);
updateDescriptors();
}
void prism::PGC::L1::TextureStorage::cleanupImpl()
{
for (uint32_t i = INVALID_TEXTURE_ID + 1; i < textures.size(); i++) {
auto& texture = textures[i];
if (texture.image != VK_NULL_HANDLE) {
textureLoader->cleanup(&texture);
}
}
textures.clear();
freeTextureIndices.clear();
if (context->textureDescriptorSetLayout != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(context->device, context->textureDescriptorSetLayout, nullptr);
context->textureDescriptorSetLayout = VK_NULL_HANDLE;
}
delete textureLoader;
}
void prism::PGC::L1::TextureStorage::updateDescriptors()
{
if (context->textureDescriptorSet == VK_NULL_HANDLE) {
return;
}
std::vector<std::pair<uint32_t, VkDescriptorImageInfo>> validTextures;
for (uint32_t i = INVALID_TEXTURE_ID + 1; i < textures.size(); i++) {
if (textures[i].image != VK_NULL_HANDLE) {
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = textures[i].imageView;
imageInfo.sampler = textures[i].sampler;
validTextures.emplace_back(i, imageInfo);
}
}
if (validTextures.empty()) {
return;
}
std::vector<VkWriteDescriptorSet> descriptorWrites;
descriptorWrites.reserve(validTextures.size());
for (const auto& [index, imageInfo] : validTextures) {
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = context->textureDescriptorSet;
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = index;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pImageInfo = &imageInfo;
descriptorWrites.push_back(descriptorWrite);
}
vkUpdateDescriptorSets(context->device,
static_cast<uint32_t>(descriptorWrites.size()),
descriptorWrites.data(), 0, nullptr);
}
uint32_t prism::PGC::L1::TextureStorage::getNextAvailableIndex(utils::Context* context) {
if (!freeTextureIndices.empty()) {
uint32_t index = freeTextureIndices.back();
freeTextureIndices.pop_back();
return index >= INVALID_TEXTURE_ID + 1 ? index : getNextAvailableIndex(context);
}
return static_cast<uint32_t>(textures.size() > 0 ? textures.size() : INVALID_TEXTURE_ID + 1);
}