better model and texture cleanup

This commit is contained in:
Tyler Murphy 2022-09-28 09:38:25 -04:00
parent b269e8059a
commit 9d0262e8a2
7 changed files with 120 additions and 30 deletions

View file

@ -20,7 +20,8 @@ Engine::Engine(int width, int height, std::string name, const char *icon) : xeWi
}; };
Engine::~Engine() { Engine::~Engine() {
xe::Model::submitDeleteQueue(); Model::submitDeleteQueue(true);
Image::submitDeleteQueue(true);
alutExit(); alutExit();
}; };

View file

@ -11,6 +11,10 @@
namespace xe { namespace xe {
//
// CONSTRUCTORS AND DECONSTUCTORS
//
Image::Image(const std::string &filename, bool anisotropic) : xeDevice{Engine::getInstance()->xeDevice} { Image::Image(const std::string &filename, bool anisotropic) : xeDevice{Engine::getInstance()->xeDevice} {
createTextureImage(filename); createTextureImage(filename);
createTextureImageView(); createTextureImageView();
@ -24,6 +28,43 @@ Image::~Image() {
vkDestroyImageView(xeDevice.device(), textureImageView, nullptr); vkDestroyImageView(xeDevice.device(), textureImageView, nullptr);
} }
//
// LOADERS AND DELETORS
//
static std::set<Image*> CREATED_IMAGES{};
static std::set<Image*> DELETION_QUEUE{};
Image* Image::createImage(const std::string &filename, bool anisotropic) {
Image* image = new Image(filename, anisotropic);
CREATED_IMAGES.insert(image);
return image;
}
void Image::deleteImage(Image* image) {
if(CREATED_IMAGES.count(image)) {
CREATED_IMAGES.erase(image);
DELETION_QUEUE.insert(image);
}
}
void Image::submitDeleteQueue(bool purge) {
for(Image* image: DELETION_QUEUE) {
try { delete image; } catch(int err) {};
}
DELETION_QUEUE.clear();
if (purge) {
for(Image* image: CREATED_IMAGES) {
try { delete image; } catch(int err) {};
}
CREATED_IMAGES.clear();
}
}
//
// IMAGE CREATION FUNCTIONS
//
void Image::createTextureImage(const std::string &filename) { void Image::createTextureImage(const std::string &filename) {
int texWidth, texHeight, texChannels; int texWidth, texHeight, texChannels;
stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
@ -243,6 +284,10 @@ void Image::createTextureSampler(bool anisotropic) {
} }
} }
//
// STATIC CREATE IMAGE
//
void Image::createImage(Device& device, uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) { void Image::createImage(Device& device, uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
VkImageCreateInfo imageInfo{}; VkImageCreateInfo imageInfo{};
@ -279,6 +324,10 @@ void Image::createImage(Device& device, uint32_t width, uint32_t height, uint32_
vkBindImageMemory(device.device(), image, imageMemory, 0); vkBindImageMemory(device.device(), image, imageMemory, 0);
} }
//
// STATIC CREATE IMAGE VIEW
//
VkImageView Image::createImageView(Device& device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels) { VkImageView Image::createImageView(Device& device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels) {
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;

View file

@ -3,6 +3,7 @@
#include "xe_device.hpp" #include "xe_device.hpp"
#include <string> #include <string>
#include <set>
namespace xe { namespace xe {
@ -10,7 +11,9 @@ class Image {
public: public:
Image(const std::string &filename, bool anisotropic); static Image* createImage(const std::string &filename, bool anisotropic);
static void deleteImage(Image* image);
~Image(); ~Image();
Image(const Image&) = delete; Image(const Image&) = delete;
@ -18,6 +21,10 @@ class Image {
private: private:
static void submitDeleteQueue(bool purge);
Image(const std::string &filename, bool anisotropic);
void createTextureImage(const std::string &filename); void createTextureImage(const std::string &filename);
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout); void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels); void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels);
@ -38,6 +45,7 @@ class Image {
friend class RenderSystem; friend class RenderSystem;
friend class SwapChain; friend class SwapChain;
friend class Engine;
}; };

View file

@ -14,6 +14,10 @@
namespace xe { namespace xe {
//
// CONSTRUCTORS AND DECONSTUCTORS
//
Model::Model(const Model::Builder &builder) : xeDevice{Engine::getInstance()->xeDevice} { Model::Model(const Model::Builder &builder) : xeDevice{Engine::getInstance()->xeDevice} {
createVertexBuffers(builder.vertexData.data, builder.vertexSize); createVertexBuffers(builder.vertexData.data, builder.vertexSize);
createIndexBuffers(builder.indices); createIndexBuffers(builder.indices);
@ -21,12 +25,49 @@ Model::Model(const Model::Builder &builder) : xeDevice{Engine::getInstance()->xe
Model::~Model() {} Model::~Model() {}
Model* Model::createModelFromFile(const std::string &filepath) { //
// LOADERS AND DELETORS
//
static std::set<Model*> CREATED_MODELS{};
static std::set<Model*> DELETION_QUEUE{};
Model* Model::createModel(const std::string &filepath) {
Builder builder{}; Builder builder{};
builder.loadModel(filepath); builder.loadModel(filepath);
return new Model(builder); return createModel(builder);
} }
Model* Model::createModel(Builder& builder) {
Model* model = new Model(builder);
CREATED_MODELS.insert(model);
return model;
}
void Model::deleteModel(Model* model) {
if(CREATED_MODELS.count(model)) {
CREATED_MODELS.erase(model);
DELETION_QUEUE.insert(model);
}
}
void Model::submitDeleteQueue(bool purge) {
for(Model* model: DELETION_QUEUE) {
try { delete model; } catch(int err) {};
}
DELETION_QUEUE.clear();
if (purge) {
for(Model* model: CREATED_MODELS) {
try { delete model; } catch(int err) {};
}
CREATED_MODELS.clear();
}
}
//
// MODEL CREATION FUNCTIONS
//
void Model::createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize) { void Model::createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize) {
vertexCount = static_cast<uint32_t>(vertexData.size()) / vertexSize; vertexCount = static_cast<uint32_t>(vertexData.size()) / vertexSize;
assert(vertexCount >= 3 && "Vertex count must be atleast 3"); assert(vertexCount >= 3 && "Vertex count must be atleast 3");
@ -155,21 +196,4 @@ void Model::Builder::loadModel(const std::string &filepath) {
} }
static std::vector<Model*> deleteQueue{};
void Model::deleteModel(Model* model) {
deleteQueue.push_back(model);
}
void Model::submitDeleteQueue() {
for(Model* model : deleteQueue) {
if(model == nullptr) return;
try {
delete model;
} catch (int err) {}
}
deleteQueue.clear();
}
} }

View file

@ -34,20 +34,24 @@ class Model {
void loadModel(const std::string &filepath); void loadModel(const std::string &filepath);
}; };
Model(const Model::Builder &builder); static Model* createModel(const std::string &filepath);
static Model* createModel(Builder& builder);
static void deleteModel(Model* model);
~Model(); ~Model();
Model(const Model &) = delete; Model(const Model &) = delete;
Model operator=(const Model &) = delete; Model operator=(const Model &) = delete;
static Model* createModelFromFile(const std::string &filepath);
static void deleteModel(Model* model);
static void submitDeleteQueue();
void bind(VkCommandBuffer commandBuffer); void bind(VkCommandBuffer commandBuffer);
void draw(VkCommandBuffer commandBuffer); void draw(VkCommandBuffer commandBuffer);
private: private:
static void submitDeleteQueue(bool purge);
Model(const Model::Builder &builder);
void createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize); void createVertexBuffers(const std::vector<unsigned char> &vertexData, uint32_t vertexSize);
void createIndexBuffers(const std::vector<uint32_t> &indexData); void createIndexBuffers(const std::vector<uint32_t> &indexData);
@ -59,6 +63,9 @@ class Model {
bool hasIndexBuffer = false; bool hasIndexBuffer = false;
std::unique_ptr<Buffer> indexBuffer; std::unique_ptr<Buffer> indexBuffer;
uint32_t indexCount; uint32_t indexCount;
friend class SwapChain;
friend class Engine;
}; };
} }

View file

@ -88,7 +88,8 @@ VkResult SwapChain::submitCommandBuffers(
vkWaitForFences(device.device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); vkWaitForFences(device.device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX);
} }
Model::submitDeleteQueue(); Model::submitDeleteQueue(false);
Image::submitDeleteQueue(false);
imagesInFlight[*imageIndex] = inFlightFences[currentFrame]; imagesInFlight[*imageIndex] = inFlightFences[currentFrame];

View file

@ -57,7 +57,7 @@ static std::map<std::string, uint32_t> texturesIds{};
static std::vector<xe::Image*> textures{}; static std::vector<xe::Image*> textures{};
void loadTexture(const std::string& filePath) { void loadTexture(const std::string& filePath) {
xe::Image* image = new xe::Image(filePath, false); xe::Image* image = xe::Image::createImage(filePath, false);
texturesIds[filePath] = static_cast<uint32_t>(textures.size()); texturesIds[filePath] = static_cast<uint32_t>(textures.size());
textures.push_back(image); textures.push_back(image);
} }
@ -80,7 +80,7 @@ void Chunk::load() {
void Chunk::unload() { void Chunk::unload() {
for(const auto &image: textures) { for(const auto &image: textures) {
delete image; xe::Image::deleteImage(image);
} }
for(const auto &[key, chunk]: chunks) { for(const auto &[key, chunk]: chunks) {
delete chunk; delete chunk;
@ -163,7 +163,7 @@ xe::Model* Chunk::getMesh() {
xe::Model::Builder builder{}; xe::Model::Builder builder{};
builder.vertexData = vertexData; builder.vertexData = vertexData;
builder.vertexSize = 36; builder.vertexSize = 36;
chunkMesh = new xe::Model(builder); chunkMesh = xe::Model::createModel(builder);
reloadRequired = false; reloadRequired = false;
} }
return chunkMesh; return chunkMesh;