diff --git a/ICE/Assets/include/Texture.h b/ICE/Assets/include/Texture.h index 162e192c..a43d83c6 100644 --- a/ICE/Assets/include/Texture.h +++ b/ICE/Assets/include/Texture.h @@ -19,12 +19,18 @@ enum class TextureType { Tex2D = 0, CubeMap = 1 }; class Texture : public Asset { public: + Texture() = default; virtual ~Texture() { - if (data_ != nullptr) { - //stbi_image_free(data_); TODO: Might need need free-ing - data_ = nullptr; + if (m_owns_data && data_ != nullptr) { + stbi_image_free(data_); } + data_ = nullptr; } + + // Owns its pixel buffer when loaded from file; non-copyable to avoid a double-free. + Texture(const Texture&) = delete; + Texture& operator=(const Texture&) = delete; + const void* data() const { return data_; } TextureFormat getFormat() const { return m_format; } @@ -43,6 +49,10 @@ class Texture : public Asset { } void* data_ = nullptr; + // True when data_ was allocated by stb (file load) and this object must free it. + // Externally-supplied buffers (the void* constructors) default to non-owning until + // the loader path is hardened to copy/own them (Phase 1B). + bool m_owns_data = false; TextureWrap m_wrap = TextureWrap::Repeat; TextureFormat m_format = TextureFormat::None; int m_width = 0; diff --git a/ICE/Assets/src/GPURegistry.cpp b/ICE/Assets/src/GPURegistry.cpp index 10513c71..db74fef8 100644 --- a/ICE/Assets/src/GPURegistry.cpp +++ b/ICE/Assets/src/GPURegistry.cpp @@ -1,7 +1,5 @@ #include "GPURegistry.h" -#include - namespace ICE { GPURegistry::GPURegistry(const std::shared_ptr &factory, const std::shared_ptr &bank) : m_graphics_factory(factory), @@ -42,15 +40,18 @@ std::shared_ptr GPURegistry::getMesh(AssetUID id) { auto boneWeightBuffer = m_graphics_factory->createVertexBuffer(); auto indexBuffer = m_graphics_factory->createIndexBuffer(); - auto data = mesh_asset->getMeshData(); - vertexBuffer->putData(BufferUtils::CreateFloatBuffer(data.vertices), 3 * data.vertices.size() * sizeof(float)); - normalsBuffer->putData(BufferUtils::CreateFloatBuffer(data.normals), 3 * data.normals.size() * sizeof(float)); - tangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.tangents), 3 * data.tangents.size() * sizeof(float)); - biTangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.bitangents), 3 * data.bitangents.size() * sizeof(float)); - boneIDBuffer->putData(BufferUtils::CreateIntBuffer(data.boneIDs), 4 * data.boneIDs.size() * sizeof(int)); - boneWeightBuffer->putData(BufferUtils::CreateFloatBuffer(data.boneWeights), 4 * data.boneWeights.size() * sizeof(float)); - uvBuffer->putData(BufferUtils::CreateFloatBuffer(data.uvCoords), 2 * data.uvCoords.size() * sizeof(float)); - indexBuffer->putData(BufferUtils::CreateIntBuffer(data.indices), 3 * data.indices.size() * sizeof(int)); + // Fixed-size Eigen vectors are tightly packed (e.g. sizeof(Vector3f) == 3 floats), + // so a std::vector of them is a contiguous float/int array we can upload directly + // -- no intermediate malloc'd staging buffers (which were previously leaked). + const auto &data = mesh_asset->getMeshData(); + vertexBuffer->putData(data.vertices.data(), 3 * data.vertices.size() * sizeof(float)); + normalsBuffer->putData(data.normals.data(), 3 * data.normals.size() * sizeof(float)); + tangentBuffer->putData(data.tangents.data(), 3 * data.tangents.size() * sizeof(float)); + biTangentBuffer->putData(data.bitangents.data(), 3 * data.bitangents.size() * sizeof(float)); + boneIDBuffer->putData(data.boneIDs.data(), 4 * data.boneIDs.size() * sizeof(int)); + boneWeightBuffer->putData(data.boneWeights.data(), 4 * data.boneWeights.size() * sizeof(float)); + uvBuffer->putData(data.uvCoords.data(), 2 * data.uvCoords.size() * sizeof(float)); + indexBuffer->putData(data.indices.data(), 3 * data.indices.size() * sizeof(int)); vertexArray->pushVertexBuffer(vertexBuffer, 0, 3); vertexArray->pushVertexBuffer(normalsBuffer, 1, 3); diff --git a/ICE/Assets/src/Mesh.cpp b/ICE/Assets/src/Mesh.cpp index 57614160..284aaecf 100644 --- a/ICE/Assets/src/Mesh.cpp +++ b/ICE/Assets/src/Mesh.cpp @@ -4,7 +4,6 @@ #include "Mesh.h" -#include #include #include diff --git a/ICE/Assets/src/Texture.cpp b/ICE/Assets/src/Texture.cpp index 36b9e101..5a832260 100644 --- a/ICE/Assets/src/Texture.cpp +++ b/ICE/Assets/src/Texture.cpp @@ -5,6 +5,7 @@ namespace ICE { Texture2D::Texture2D(const std::string& path) { int channels = 0; data_ = getDataFromFile(path, &m_width, &m_height, &channels); + m_owns_data = true; // stb-allocated; freed in ~Texture if (channels == 3) { m_format = TextureFormat::RGB8; } else if (channels == 4) { diff --git a/ICE/Graphics/include/Buffers.h b/ICE/Graphics/include/Buffers.h index 50d4baa0..3e51aacb 100644 --- a/ICE/Graphics/include/Buffers.h +++ b/ICE/Graphics/include/Buffers.h @@ -10,6 +10,7 @@ namespace ICE { class VertexBuffer { public: + virtual ~VertexBuffer() = default; virtual void bind() const = 0; virtual void unbind() const = 0; virtual void putData(const void* data, uint32_t size) = 0; @@ -18,6 +19,7 @@ class VertexBuffer { class IndexBuffer { public: + virtual ~IndexBuffer() = default; virtual void bind() const = 0; virtual void unbind() const = 0; virtual void putData(const void* data, uint32_t size) = 0; diff --git a/ICE/Graphics/include/Camera.h b/ICE/Graphics/include/Camera.h index 6823e0cc..90a776a2 100644 --- a/ICE/Graphics/include/Camera.h +++ b/ICE/Graphics/include/Camera.h @@ -11,6 +11,7 @@ enum ProjectionType { Perspective, Orthographic }; class Camera { public: + virtual ~Camera() = default; virtual Eigen::Matrix4f lookThrough() = 0; virtual void forward(float delta) = 0; diff --git a/ICE/Graphics/include/Context.h b/ICE/Graphics/include/Context.h index 7ca6da6d..341bf846 100644 --- a/ICE/Graphics/include/Context.h +++ b/ICE/Graphics/include/Context.h @@ -7,6 +7,7 @@ namespace ICE { class Context { public: + virtual ~Context() = default; virtual void initialize() = 0; virtual void swapBuffers() = 0; virtual void wireframeMode() = 0; diff --git a/ICE/Graphics/include/Framebuffer.h b/ICE/Graphics/include/Framebuffer.h index a837feef..7f1e2a8a 100644 --- a/ICE/Graphics/include/Framebuffer.h +++ b/ICE/Graphics/include/Framebuffer.h @@ -13,6 +13,7 @@ struct FrameBufferFormat { class Framebuffer { public: + virtual ~Framebuffer() = default; virtual void bind() = 0; virtual void unbind() = 0; virtual void resize(int width, int height) = 0; diff --git a/ICE/Graphics/include/GeometryPass.h b/ICE/Graphics/include/GeometryPass.h index 1c968afb..21fd7149 100644 --- a/ICE/Graphics/include/GeometryPass.h +++ b/ICE/Graphics/include/GeometryPass.h @@ -20,6 +20,9 @@ class GeometryPass : public RenderPass { std::shared_ptr m_api; std::shared_ptr m_factory; std::shared_ptr m_framebuffer; + // Reused every draw for per-instance data instead of allocating a fresh GL buffer + // per command per frame. + std::shared_ptr m_instance_buffer; std::vector* m_render_queue; }; } // namespace ICE \ No newline at end of file diff --git a/ICE/Graphics/include/GraphicsAPI.h b/ICE/Graphics/include/GraphicsAPI.h index aa2c6ba6..258bd3eb 100644 --- a/ICE/Graphics/include/GraphicsAPI.h +++ b/ICE/Graphics/include/GraphicsAPI.h @@ -17,6 +17,7 @@ enum GraphicsAPI { class RendererAPI { public: + virtual ~RendererAPI() = default; virtual void initialize() const = 0; virtual void bindDefaultFramebuffer() const = 0; virtual void setViewport(int x, int y, int width, int height) const = 0; diff --git a/ICE/Graphics/include/GraphicsFactory.h b/ICE/Graphics/include/GraphicsFactory.h index d21c36b8..29ec3490 100644 --- a/ICE/Graphics/include/GraphicsFactory.h +++ b/ICE/Graphics/include/GraphicsFactory.h @@ -17,6 +17,7 @@ namespace ICE { class GraphicsFactory { public: + virtual ~GraphicsFactory() = default; virtual std::shared_ptr createContext(const std::shared_ptr& window) const = 0; virtual std::shared_ptr createFramebuffer(const FrameBufferFormat& format) const = 0; diff --git a/ICE/Graphics/include/Renderer.h b/ICE/Graphics/include/Renderer.h index 177e9668..f7bf282f 100644 --- a/ICE/Graphics/include/Renderer.h +++ b/ICE/Graphics/include/Renderer.h @@ -68,6 +68,7 @@ struct Light { class Renderer { public: + virtual ~Renderer() = default; virtual void submitSkybox(const Skybox& e) = 0; virtual void submitDrawable(const Drawable& e) = 0; virtual void submitLight(const Light& e) = 0; diff --git a/ICE/Graphics/include/ShaderProgram.h b/ICE/Graphics/include/ShaderProgram.h index 5d2521fc..57f0747d 100644 --- a/ICE/Graphics/include/ShaderProgram.h +++ b/ICE/Graphics/include/ShaderProgram.h @@ -6,6 +6,7 @@ namespace ICE { class ShaderProgram { public: + virtual ~ShaderProgram() = default; virtual void bind() const = 0; virtual void unbind() const = 0; diff --git a/ICE/Graphics/include/VertexArray.h b/ICE/Graphics/include/VertexArray.h index 1d7c0d32..85ef5052 100644 --- a/ICE/Graphics/include/VertexArray.h +++ b/ICE/Graphics/include/VertexArray.h @@ -16,6 +16,7 @@ class IndexBuffer; class VertexArray { public: + virtual ~VertexArray() = default; virtual void bind() const = 0; virtual void unbind() const = 0; virtual void pushVertexBuffer(const std::shared_ptr& buffer, int size) = 0; diff --git a/ICE/Graphics/src/GeometryPass.cpp b/ICE/Graphics/src/GeometryPass.cpp index 3fc1a7bc..68f644d4 100644 --- a/ICE/Graphics/src/GeometryPass.cpp +++ b/ICE/Graphics/src/GeometryPass.cpp @@ -7,6 +7,7 @@ GeometryPass::GeometryPass(const std::shared_ptr& api, const std::s : m_api(api), m_factory(factory) { m_framebuffer = factory->createFramebuffer(format); + m_instance_buffer = factory->createVertexBuffer(); } void GeometryPass::execute() { @@ -86,21 +87,15 @@ void GeometryPass::execute() { va->getIndexBuffer()->bind(); } - // Instanced vs regular rendering - //TODO: Do not recreate instance buffer every frame, update existing one instead - //TODO: If not instanced, is there performance drop + // Reuse the pass-owned instance buffer: upload this command's per-instance data + // and (re)bind it at attribute slot 7 of the current mesh's vertex array. auto va = mesh->getVertexArray(); if (command.is_instanced && command.instance_data) { - auto instance_buffer = m_factory->createVertexBuffer(); - instance_buffer->putData(command.instance_data->data(), command.instance_count * sizeof(InstanceData)); - - va->pushVertexBuffer(instance_buffer, 7, 16, 1); + m_instance_buffer->putData(command.instance_data->data(), command.instance_count * sizeof(InstanceData)); } else { - auto instance_buffer = m_factory->createVertexBuffer(); - instance_buffer->putData(command.model_matrix.data(), sizeof(Eigen::Matrix4f)); - - va->pushVertexBuffer(instance_buffer, 7, 16, 1); + m_instance_buffer->putData(command.model_matrix.data(), sizeof(Eigen::Matrix4f)); } + va->pushVertexBuffer(m_instance_buffer, 7, 16, 1); m_api->renderVertexArrayInstanced(va, command.instance_count); } } diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLBuffers.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLBuffers.h index 57de3812..71ac4165 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLBuffers.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLBuffers.h @@ -18,6 +18,11 @@ class OpenGLVertexBuffer : public VertexBuffer { uint32_t getSize() const override; OpenGLVertexBuffer() : OpenGLVertexBuffer(0) {} OpenGLVertexBuffer(uint32_t size); + ~OpenGLVertexBuffer() override; + + // Owns a GL buffer name; copying would double-delete it. + OpenGLVertexBuffer(const OpenGLVertexBuffer &) = delete; + OpenGLVertexBuffer &operator=(const OpenGLVertexBuffer &) = delete; private: GLuint id; @@ -32,6 +37,10 @@ class OpenGLIndexBuffer : public IndexBuffer { void putData(const void *data, uint32_t size) override; OpenGLIndexBuffer(); + ~OpenGLIndexBuffer() override; + + OpenGLIndexBuffer(const OpenGLIndexBuffer &) = delete; + OpenGLIndexBuffer &operator=(const OpenGLIndexBuffer &) = delete; private: GLuint id; @@ -47,6 +56,9 @@ class OpenGLUniformBuffer : public UniformBuffer { OpenGLUniformBuffer(uint32_t _size, uint32_t _binding); ~OpenGLUniformBuffer() override; + OpenGLUniformBuffer(const OpenGLUniformBuffer &) = delete; + OpenGLUniformBuffer &operator=(const OpenGLUniformBuffer &) = delete; + private: GLuint id; uint32_t size; diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLFramebuffer.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLFramebuffer.h index b8bbc03d..1ce1a067 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLFramebuffer.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLFramebuffer.h @@ -13,6 +13,11 @@ namespace ICE { class OpenGLFramebuffer : public Framebuffer { public: OpenGLFramebuffer(FrameBufferFormat fmt); + ~OpenGLFramebuffer() override; + + // Owns GL framebuffer/texture/renderbuffer names; copying would double-delete them. + OpenGLFramebuffer(const OpenGLFramebuffer &) = delete; + OpenGLFramebuffer &operator=(const OpenGLFramebuffer &) = delete; void bind() override; diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h index caf29ba2..b2e6ab9a 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h @@ -17,6 +17,11 @@ namespace ICE { class OpenGLShader : public ShaderProgram { public: explicit OpenGLShader(const Shader &shader_asset); + ~OpenGLShader() override; + + // Owns a GL program object; copying would double-delete it. + OpenGLShader(const OpenGLShader &) = delete; + OpenGLShader &operator=(const OpenGLShader &) = delete; void bind() const override; @@ -39,7 +44,9 @@ class OpenGLShader : public ShaderProgram { private: GLint getLocation(const std::string &name); - void compileAndAttachStage(ShaderStage stage, const std::string &source); + // Compiles and attaches a stage, returning its GL shader name so the caller can + // detach and delete it after linking. + GLuint compileAndAttachStage(ShaderStage stage, const std::string &source); GLenum stageToGLStage(ShaderStage stage); diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h index ba3eb877..ed1c5ac1 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h @@ -67,6 +67,11 @@ constexpr int textureFormatToChannels(TextureFormat format) { class OpenGLTexture2D : public GPUTexture { public: OpenGLTexture2D(const Texture2D &tex); + ~OpenGLTexture2D() override; + + // Owns a GL texture name; copying would double-delete it. + OpenGLTexture2D(const OpenGLTexture2D &) = delete; + OpenGLTexture2D &operator=(const OpenGLTexture2D &) = delete; void bind(uint32_t slot) const override; int id() const override; @@ -78,6 +83,10 @@ class OpenGLTexture2D : public GPUTexture { class OpenGLTextureCube : public GPUTexture { public: OpenGLTextureCube(const TextureCube &tex); + ~OpenGLTextureCube() override; + + OpenGLTextureCube(const OpenGLTextureCube &) = delete; + OpenGLTextureCube &operator=(const OpenGLTextureCube &) = delete; void bind(uint32_t slot) const override; int id() const override; diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLVertexArray.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLVertexArray.h index f7d74b7c..00bbd6ce 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLVertexArray.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLVertexArray.h @@ -15,6 +15,11 @@ namespace ICE { class OpenGLVertexArray : public VertexArray { public: OpenGLVertexArray(); + ~OpenGLVertexArray() override; + + // Owns a GL vertex-array name; copying would double-delete it. + OpenGLVertexArray(const OpenGLVertexArray&) = delete; + OpenGLVertexArray& operator=(const OpenGLVertexArray&) = delete; void bind() const override; diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLBuffers.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLBuffers.cpp index d54faa2a..848eb3d9 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLBuffers.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLBuffers.cpp @@ -34,12 +34,20 @@ OpenGLIndexBuffer::OpenGLIndexBuffer() { glGenBuffers(1, &id); } +OpenGLIndexBuffer::~OpenGLIndexBuffer() { + glDeleteBuffers(1, &id); +} + /////////////////////////////////// VERTEX BUFFER ////////////////////////////////// OpenGLVertexBuffer::OpenGLVertexBuffer(uint32_t size) : size(size) { glGenBuffers(1, &id); } +OpenGLVertexBuffer::~OpenGLVertexBuffer() { + glDeleteBuffers(1, &id); +} + void OpenGLVertexBuffer::bind() const { glBindBuffer(GL_ARRAY_BUFFER, this->id); } diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp index c5b67d5a..ce406ece 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp @@ -69,6 +69,12 @@ OpenGLFramebuffer::OpenGLFramebuffer(FrameBufferFormat fmt) : Framebuffer(fmt) { unbind(); } +OpenGLFramebuffer::~OpenGLFramebuffer() { + glDeleteFramebuffers(1, &uid); + glDeleteTextures(1, &texture); + glDeleteRenderbuffers(1, &depth); +} + void OpenGLFramebuffer::bindAttachment(int slot) const { glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, texture); diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp index 414203cd..679bcf1d 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp @@ -15,8 +15,9 @@ OpenGLShader::OpenGLShader(const Shader &shader_asset) { m_programID = glCreateProgram(); Logger::Log(Logger::VERBOSE, "Graphics", "Compiling shader..."); + std::vector stage_shaders; for (const auto& [stage, source] : shader_asset.getStageSources()) { - compileAndAttachStage(stage, source.second); + stage_shaders.push_back(compileAndAttachStage(stage, source.second)); } glLinkProgram(m_programID); @@ -31,6 +32,16 @@ OpenGLShader::OpenGLShader(const Shader &shader_asset) { glGetProgramInfoLog(m_programID, maxLength, &maxLength, &errorLog[0]); Logger::Log(Logger::FATAL, "Graphics", "Shader linking error: %s", errorLog.data()); } + + // Stage objects are no longer needed once linked into the program. + for (GLuint shader : stage_shaders) { + glDetachShader(m_programID, shader); + glDeleteShader(shader); + } +} + +OpenGLShader::~OpenGLShader() { + glDeleteProgram(m_programID); } void OpenGLShader::bind() const { @@ -100,13 +111,14 @@ bool compileShader(GLenum type, const std::string &source, GLint *shader) { return compileStatus == GL_TRUE; } -void OpenGLShader::compileAndAttachStage(ShaderStage stage, const std::string &source) { +GLuint OpenGLShader::compileAndAttachStage(ShaderStage stage, const std::string &source) { GLint shader; Logger::Log(Logger::VERBOSE, "Graphics", "\t + Compiling shader stage..."); if (!compileShader(stageToGLStage(stage), source, &shader)) { Logger::Log(Logger::FATAL, "Graphics", "Error while compiling shader stage"); } glAttachShader(m_programID, shader); + return static_cast(shader); } diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp index bded6daa..229ab9ac 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp @@ -32,6 +32,10 @@ OpenGLTexture2D::OpenGLTexture2D(const Texture2D &tex) { glTexImage2D(GL_TEXTURE_2D, 0, storageFormat, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, tex.data()); } +OpenGLTexture2D::~OpenGLTexture2D() { + glDeleteTextures(1, &m_id); +} + int OpenGLTexture2D::id() const { return m_id; } diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp index ee0c6fa6..a2c7271c 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp @@ -29,6 +29,10 @@ OpenGLTextureCube::OpenGLTextureCube(const TextureCube &texture_asset) { } +OpenGLTextureCube::~OpenGLTextureCube() { + glDeleteTextures(1, &m_id); +} + int OpenGLTextureCube::id() const { return m_id; } diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLVertexArray.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLVertexArray.cpp index 32663407..c81eb362 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLVertexArray.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLVertexArray.cpp @@ -13,6 +13,10 @@ OpenGLVertexArray::OpenGLVertexArray() { glGenVertexArrays(1, &vaoID); } +OpenGLVertexArray::~OpenGLVertexArray() { + glDeleteVertexArrays(1, &vaoID); +} + void OpenGLVertexArray::bind() const { glBindVertexArray(this->vaoID); } diff --git a/ICE/IO/src/MeshLoader.cpp b/ICE/IO/src/MeshLoader.cpp index 65f054f8..f338bb7d 100644 --- a/ICE/IO/src/MeshLoader.cpp +++ b/ICE/IO/src/MeshLoader.cpp @@ -5,7 +5,6 @@ #include "MeshLoader.h" #include -#include #include #include #include diff --git a/ICE/IO/src/ModelLoader.cpp b/ICE/IO/src/ModelLoader.cpp index 9efaef4a..cf453a5b 100644 --- a/ICE/IO/src/ModelLoader.cpp +++ b/ICE/IO/src/ModelLoader.cpp @@ -5,7 +5,6 @@ #include "ModelLoader.h" #include -#include #include #include #include diff --git a/ICE/Util/CMakeLists.txt b/ICE/Util/CMakeLists.txt index da20ae38..52158d04 100644 --- a/ICE/Util/CMakeLists.txt +++ b/ICE/Util/CMakeLists.txt @@ -6,7 +6,6 @@ message(STATUS "Building ${PROJECT_NAME} module") add_library(${PROJECT_NAME} STATIC) target_sources(${PROJECT_NAME} PRIVATE - src/BufferUtils.cpp src/ICEException.cpp src/Logger.cpp src/WindowFactory.cpp diff --git a/ICE/Util/include/BufferUtils.h b/ICE/Util/include/BufferUtils.h deleted file mode 100644 index c02bb62a..00000000 --- a/ICE/Util/include/BufferUtils.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by Thomas Ibanez on 22.11.20. -// - -#ifndef ICE_BUFFERUTILS_H -#define ICE_BUFFERUTILS_H - -#include -#include -#include - -namespace ICE { - class BufferUtils { - public: - //TODO: Might be able to make it all in one with VectorXd and the data() function - static float* CreateFloatBuffer(const std::vector& vectors) { - auto buffer = static_cast(malloc(sizeof(float) * 3 * vectors.size())); - uint32_t i = 0; - for(const auto &v : vectors) { - buffer[i] = (float) v.x(); - buffer[i+1] = (float) v.y(); - buffer[i+2] = (float) v.z(); - i += 3; - } - return buffer; - } - - static float* CreateFloatBuffer(const std::vector& vectors) { - auto buffer = static_cast(malloc(sizeof(float) * 4 * vectors.size())); - uint32_t i = 0; - for (const auto& v : vectors) { - buffer[i] = (float) v.x(); - buffer[i + 1] = (float) v.y(); - buffer[i + 2] = (float) v.z(); - buffer[i + 3] = (float) v.w(); - i += 4; - } - return buffer; - } - - static float* CreateFloatBuffer(const std::vector& vectors) { - auto* buffer = static_cast(malloc(sizeof(float) * 2 * vectors.size())); - uint32_t i = 0; - for(const auto &v : vectors) { - buffer[i] = (float) v.x(); - buffer[i+1] = (float) v.y(); - i += 2; - } - return buffer; - } - - static int* CreateIntBuffer(const std::vector& vectors) { - auto* buffer = static_cast(malloc(sizeof(int) * 3 * vectors.size())); - uint32_t i = 0; - for(const auto &v : vectors) { - buffer[i] = v.x(); - buffer[i+1] = v.y(); - buffer[i+2] = v.z(); - i += 3; - } - return buffer; - } - - static int* CreateIntBuffer(const std::vector& vectors) { - auto* buffer = static_cast(malloc(sizeof(int) * 4 * vectors.size())); - uint32_t i = 0; - for (const auto& v : vectors) { - buffer[i] = v.x(); - buffer[i + 1] = v.y(); - buffer[i + 2] = v.z(); - buffer[i + 3] = v.w(); - i += 4; - } - return buffer; - } - - static std::vector CreateCharBuffer(const std::vector& strings) { - std::vector pointerVec(strings.size()); - for(unsigned i = 0; i < strings.size(); ++i) - { - pointerVec[i] = strings[i].data(); - } //you can use transform instead of this loop - return pointerVec; - } - }; -} - - -#endif //ICE_BUFFERUTILS_H diff --git a/ICE/Util/include/GLFWWindow.h b/ICE/Util/include/GLFWWindow.h index ae5fdd04..37a7cce3 100644 --- a/ICE/Util/include/GLFWWindow.h +++ b/ICE/Util/include/GLFWWindow.h @@ -10,6 +10,11 @@ namespace ICE { class GLFWWindow : public Window { public: GLFWWindow(int width, int height, const std::string& title); + ~GLFWWindow() override; + + // Owns a GLFWwindow handle; non-copyable. + GLFWWindow(const GLFWWindow&) = delete; + GLFWWindow& operator=(const GLFWWindow&) = delete; void* getHandle() const override; bool shouldClose() override; diff --git a/ICE/Util/src/BufferUtils.cpp b/ICE/Util/src/BufferUtils.cpp deleted file mode 100644 index e9cd86fc..00000000 --- a/ICE/Util/src/BufferUtils.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by Thomas Ibanez on 22.11.20. -// - -#include "BufferUtils.h" diff --git a/ICE/Util/src/GLFWWindow.cpp b/ICE/Util/src/GLFWWindow.cpp index 193d29c6..fc56b523 100644 --- a/ICE/Util/src/GLFWWindow.cpp +++ b/ICE/Util/src/GLFWWindow.cpp @@ -8,9 +8,14 @@ namespace ICE { +// Number of live GLFWWindow instances. GLFW is initialized on the first window and +// terminated when the last one is destroyed. +static int s_window_count = 0; + GLFWWindow::GLFWWindow(int width, int height, const std::string& title) : m_width(width), m_height(height) { - if (!glfwInit()) + if (s_window_count == 0 && !glfwInit()) throw ICEException("Couldn't init GLFW"); + s_window_count++; // Decide GL+GLSL versions #ifdef __APPLE__ // GL 3.2 + GLSL 150 @@ -27,8 +32,11 @@ GLFWWindow::GLFWWindow(int width, int height, const std::string& title) : m_widt #endif // Create window with graphics context m_handle = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); - if (m_handle == NULL) + if (m_handle == NULL) { + if (--s_window_count == 0) + glfwTerminate(); throw ICEException("Couldn't create window"); + } m_mouse_handler = std::make_shared(*this); m_keyboard_handler = std::make_shared(*this); @@ -41,6 +49,15 @@ GLFWWindow::GLFWWindow(int width, int height, const std::string& title) : m_widt }); } +GLFWWindow::~GLFWWindow() { + if (m_handle != nullptr) { + glfwDestroyWindow(m_handle); + } + if (--s_window_count == 0) { + glfwTerminate(); + } +} + std::pair, std::shared_ptr> GLFWWindow::getInputHandlers() const { return {m_mouse_handler, m_keyboard_handler}; }