146 lines
6.6 KiB
C++
146 lines
6.6 KiB
C++
#include "texture_manager.hpp"
|
|
#include "exceptions.hpp"
|
|
#include "vulkan_instance.hpp"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <vulkan/vulkan_core.h>
|
|
|
|
namespace gz::vk {
|
|
TextureManager::TextureManager(VulkanInstance& instance)
|
|
: vk(instance)
|
|
{
|
|
vk.registerCleanupCallback(std::bind(&TextureManager::cleanup, this));
|
|
atlases.insert({ 0, TextureAtlas(vk, 24, 24, 24, 24) });
|
|
createDescriptorSetLayout();
|
|
createDescriptorPool();
|
|
createDescriptorSet();
|
|
VulkanInstance::registerObjectUsingVulkan(ObjectUsingVulkan("TextureManager",
|
|
{ &descriptorSetLayout, &descriptorPool, &descriptorSet },
|
|
{}));
|
|
}
|
|
|
|
|
|
void TextureManager::cleanup() {
|
|
/* vkFreeDescriptorSets(vk.device, descriptorPool, 1, &descriptorSet); */
|
|
vkDestroyDescriptorSetLayout(vk.device, descriptorSetLayout, NO_ALLOC);
|
|
vkDestroyDescriptorPool(vk.device, descriptorPool, NO_ALLOC);
|
|
}
|
|
|
|
|
|
void TextureManager::getTexCoords(const std::string& textureName, glm::vec2& texCoords) {
|
|
if (!textureInfos.contains(textureName)) {
|
|
loadTextureFromFile(textureName);
|
|
}
|
|
TextureInfo& texI = textureInfos[textureName];
|
|
VulkanInstance::vLog("getTexCoords", texCoords, "textureInfo: topleft", texI.texCoordTopLeft, "botright", texI.texCoordBottomRight);
|
|
/* texCoords.x = texI.texCoordTopLeft.x + texCoords.x * (texI.texCoordBottomRight.x - texI.texCoordTopLeft.x); */
|
|
/* texCoords.y = texI.texCoordTopLeft.y + texCoords.y * (texI.texCoordBottomRight.y - texI.texCoordTopLeft.y); */
|
|
texCoords = texI.texCoordTopLeft + texCoords * (texI.texCoordBottomRight - texI.texCoordTopLeft);
|
|
}
|
|
|
|
|
|
void TextureManager::loadTextureFromFile(const std::string& textureName) {
|
|
int textureWidth, textureHeight, textureChannels;
|
|
stbi_uc* pixels = stbi_load(("textures/" + textureName).c_str(), &textureWidth, &textureHeight, &textureChannels, STBI_rgb_alpha);
|
|
if (!pixels) {
|
|
throw Exception("Failed to load texture: textures/" + textureName, "TextureManager::loadTexture");
|
|
}
|
|
TextureInfo& texI = textureInfos[textureName];
|
|
texI.atlas = 0;
|
|
auto texCoords = atlases.at(0).addTexture(pixels, textureWidth, textureHeight);
|
|
stbi_image_free(pixels);
|
|
VulkanInstance::vLog("TextureManager::loadTextureFromFile: TexCoords of new image:", texCoords.first, texCoords.second);
|
|
texI.texCoordTopLeft = std::move(texCoords.first);
|
|
texI.texCoordBottomRight = std::move(texCoords.second);
|
|
VulkanInstance::vLog("TextureManager::loadTextureFromFile: After loading:", atlases.at(0));
|
|
}
|
|
|
|
|
|
//
|
|
// DESCRIPTOR SET
|
|
//
|
|
void TextureManager::createDescriptorSetLayout() {
|
|
// combined image sampler
|
|
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
|
|
samplerLayoutBinding.binding = 0;
|
|
samplerLayoutBinding.descriptorCount = 1;
|
|
samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
/* samplerLayoutBinding.pImmutableSamplers = nullptr; */
|
|
|
|
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI{};
|
|
descriptorSetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
descriptorSetLayoutCI.bindingCount = 1;
|
|
descriptorSetLayoutCI.pBindings = &samplerLayoutBinding;
|
|
|
|
VkResult result = vkCreateDescriptorSetLayout(vk.device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout);
|
|
if (result != VK_SUCCESS) {
|
|
throw getVkException(result, "Could not create descriptorSetLayout", "TextureManager::createDescriptorSetLayout");
|
|
}
|
|
/* vLog("createDescriptorSetLayout: Created descriptor set layout."); */
|
|
}
|
|
|
|
|
|
void TextureManager::createDescriptorPool() {
|
|
std::array<VkDescriptorPoolSize, 1> poolSizes;
|
|
/* poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; */
|
|
/* poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT); */
|
|
poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
|
|
|
|
VkDescriptorPoolCreateInfo poolCI{};
|
|
poolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
poolCI.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
|
|
poolCI.pPoolSizes = poolSizes.data();
|
|
poolCI.maxSets = 1;
|
|
VkResult result = vkCreateDescriptorPool(vk.device, &poolCI, nullptr, &descriptorPool);
|
|
if (result != VK_SUCCESS) {
|
|
throw getVkException(result, "Failed to create descriptor pool", "TextureManager::createDescriptorPool");
|
|
}
|
|
/* vLog("createDescriptorPool: Created descriptor pool."); */
|
|
}
|
|
|
|
|
|
void TextureManager::createDescriptorSet() {
|
|
/* std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout); */
|
|
VkDescriptorSetAllocateInfo setAI{};
|
|
setAI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
setAI.descriptorPool = descriptorPool;
|
|
/* setAI.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT); */
|
|
/* setAI.pSetLayouts = layouts.data(); */
|
|
setAI.descriptorSetCount = 1;
|
|
setAI.pSetLayouts = &descriptorSetLayout;
|
|
|
|
/* descriptorSets.resize(MAX_FRAMES_IN_FLIGHT); */
|
|
/* VkResult result = vkAllocateDescriptorSets(vk.device, &setAI, descriptorSets.data()); */
|
|
VkResult result = vkAllocateDescriptorSets(vk.device, &setAI, &descriptorSet);
|
|
if (result != VK_SUCCESS) {
|
|
throw getVkException(result, "Failed to create descriptor set", "TextureManager::createDescriptorPool");
|
|
}
|
|
|
|
// configure sets
|
|
std::vector<VkDescriptorImageInfo> imageInfos;
|
|
for (auto it = atlases.cbegin(); it != atlases.cend(); it++) {
|
|
imageInfos.emplace_back();
|
|
imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
imageInfos.back().imageView = it->second.getTextureImageView();
|
|
imageInfos.back().sampler = it->second.getTextureSampler();
|
|
}
|
|
|
|
std::array<VkWriteDescriptorSet, 1> descriptorW{};
|
|
descriptorW[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
descriptorW[0].dstSet = descriptorSet;
|
|
descriptorW[0].dstBinding = 0;
|
|
descriptorW[0].dstArrayElement = 0;
|
|
descriptorW[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
descriptorW[0].descriptorCount = static_cast<uint32_t>(imageInfos.size());
|
|
descriptorW[0].pImageInfo = imageInfos.data();
|
|
|
|
uint32_t descriptorWriteCount = static_cast<uint32_t>(descriptorW.size());
|
|
uint32_t descriptorCopyCount = 0;
|
|
vkUpdateDescriptorSets(vk.device, descriptorWriteCount, descriptorW.data(), descriptorCopyCount, nullptr);
|
|
/* } */
|
|
/* vLog("createDescriptorSets: Created descriptor sets."); */
|
|
}
|
|
} // namespace gz::vk
|