diff --git a/engine/xe_engine.cpp b/engine/xe_engine.cpp index eabbdb1..70dda64 100644 --- a/engine/xe_engine.cpp +++ b/engine/xe_engine.cpp @@ -20,7 +20,8 @@ Engine::Engine(int width, int height, std::string name, const char *icon) : xeWi }; Engine::~Engine() { - xe::Model::submitDeleteQueue(); + Model::submitDeleteQueue(true); + Image::submitDeleteQueue(true); alutExit(); }; diff --git a/engine/xe_image.cpp b/engine/xe_image.cpp index 1ac82e2..cd53663 100644 --- a/engine/xe_image.cpp +++ b/engine/xe_image.cpp @@ -11,6 +11,10 @@ namespace xe { +// +// CONSTRUCTORS AND DECONSTUCTORS +// + Image::Image(const std::string &filename, bool anisotropic) : xeDevice{Engine::getInstance()->xeDevice} { createTextureImage(filename); createTextureImageView(); @@ -24,6 +28,43 @@ Image::~Image() { vkDestroyImageView(xeDevice.device(), textureImageView, nullptr); } +// +// LOADERS AND DELETORS +// + +static std::set CREATED_IMAGES{}; +static std::set 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) { int texWidth, texHeight, texChannels; 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) { VkImageCreateInfo imageInfo{}; @@ -279,6 +324,10 @@ void Image::createImage(Device& device, uint32_t width, uint32_t height, uint32_ vkBindImageMemory(device.device(), image, imageMemory, 0); } +// +// STATIC CREATE IMAGE VIEW +// + VkImageView Image::createImageView(Device& device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels) { VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; diff --git a/engine/xe_image.hpp b/engine/xe_image.hpp index bc1dad2..7884dd6 100644 --- a/engine/xe_image.hpp +++ b/engine/xe_image.hpp @@ -3,6 +3,7 @@ #include "xe_device.hpp" #include +#include namespace xe { @@ -10,7 +11,9 @@ class Image { public: - Image(const std::string &filename, bool anisotropic); + static Image* createImage(const std::string &filename, bool anisotropic); + static void deleteImage(Image* image); + ~Image(); Image(const Image&) = delete; @@ -18,6 +21,10 @@ class Image { private: + static void submitDeleteQueue(bool purge); + + Image(const std::string &filename, bool anisotropic); + void createTextureImage(const std::string &filename); 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); @@ -38,6 +45,7 @@ class Image { friend class RenderSystem; friend class SwapChain; + friend class Engine; }; diff --git a/engine/xe_model.cpp b/engine/xe_model.cpp index f8001fd..49d4c9d 100644 --- a/engine/xe_model.cpp +++ b/engine/xe_model.cpp @@ -14,6 +14,10 @@ namespace xe { +// +// CONSTRUCTORS AND DECONSTUCTORS +// + Model::Model(const Model::Builder &builder) : xeDevice{Engine::getInstance()->xeDevice} { createVertexBuffers(builder.vertexData.data, builder.vertexSize); createIndexBuffers(builder.indices); @@ -21,12 +25,49 @@ Model::Model(const Model::Builder &builder) : xeDevice{Engine::getInstance()->xe Model::~Model() {} -Model* Model::createModelFromFile(const std::string &filepath) { +// +// LOADERS AND DELETORS +// + +static std::set CREATED_MODELS{}; +static std::set DELETION_QUEUE{}; + +Model* Model::createModel(const std::string &filepath) { Builder builder{}; 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 &vertexData, uint32_t vertexSize) { vertexCount = static_cast(vertexData.size()) / vertexSize; assert(vertexCount >= 3 && "Vertex count must be atleast 3"); @@ -155,21 +196,4 @@ void Model::Builder::loadModel(const std::string &filepath) { } -static std::vector 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(); -} - - } \ No newline at end of file diff --git a/engine/xe_model.hpp b/engine/xe_model.hpp index e331ed1..9f0a42d 100644 --- a/engine/xe_model.hpp +++ b/engine/xe_model.hpp @@ -34,20 +34,24 @@ class Model { 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(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 draw(VkCommandBuffer commandBuffer); private: + + static void submitDeleteQueue(bool purge); + + Model(const Model::Builder &builder); + void createVertexBuffers(const std::vector &vertexData, uint32_t vertexSize); void createIndexBuffers(const std::vector &indexData); @@ -59,6 +63,9 @@ class Model { bool hasIndexBuffer = false; std::unique_ptr indexBuffer; uint32_t indexCount; + + friend class SwapChain; + friend class Engine; }; } \ No newline at end of file diff --git a/engine/xe_swap_chain.cpp b/engine/xe_swap_chain.cpp index c631209..f6b194d 100755 --- a/engine/xe_swap_chain.cpp +++ b/engine/xe_swap_chain.cpp @@ -88,7 +88,8 @@ VkResult SwapChain::submitCommandBuffers( vkWaitForFences(device.device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); } - Model::submitDeleteQueue(); + Model::submitDeleteQueue(false); + Image::submitDeleteQueue(false); imagesInFlight[*imageIndex] = inFlightFences[currentFrame]; diff --git a/src/chunk.cpp b/src/chunk.cpp index cda92e8..c52eeb3 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -57,7 +57,7 @@ static std::map texturesIds{}; static std::vector textures{}; 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(textures.size()); textures.push_back(image); } @@ -80,7 +80,7 @@ void Chunk::load() { void Chunk::unload() { for(const auto &image: textures) { - delete image; + xe::Image::deleteImage(image); } for(const auto &[key, chunk]: chunks) { delete chunk; @@ -163,7 +163,7 @@ xe::Model* Chunk::getMesh() { xe::Model::Builder builder{}; builder.vertexData = vertexData; builder.vertexSize = 36; - chunkMesh = new xe::Model(builder); + chunkMesh = xe::Model::createModel(builder); reloadRequired = false; } return chunkMesh;