better model and texture cleanup
This commit is contained in:
parent
b269e8059a
commit
9d0262e8a2
7 changed files with 120 additions and 30 deletions
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue