Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions ICE/Assets/include/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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;
Expand Down
23 changes: 12 additions & 11 deletions ICE/Assets/src/GPURegistry.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "GPURegistry.h"

#include <BufferUtils.h>

namespace ICE {
GPURegistry::GPURegistry(const std::shared_ptr<GraphicsFactory> &factory, const std::shared_ptr<AssetBank> &bank)
: m_graphics_factory(factory),
Expand Down Expand Up @@ -42,15 +40,18 @@ std::shared_ptr<GPUMesh> 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);
Expand Down
1 change: 0 additions & 1 deletion ICE/Assets/src/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "Mesh.h"

#include <BufferUtils.h>
#include <VertexArray.h>

#include <iostream>
Expand Down
1 change: 1 addition & 0 deletions ICE/Assets/src/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions ICE/Graphics/include/Buffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace ICE {
class Context {
public:
virtual ~Context() = default;
virtual void initialize() = 0;
virtual void swapBuffers() = 0;
virtual void wireframeMode() = 0;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions ICE/Graphics/include/GeometryPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class GeometryPass : public RenderPass {
std::shared_ptr<RendererAPI> m_api;
std::shared_ptr<GraphicsFactory> m_factory;
std::shared_ptr<Framebuffer> m_framebuffer;
// Reused every draw for per-instance data instead of allocating a fresh GL buffer
// per command per frame.
std::shared_ptr<VertexBuffer> m_instance_buffer;
std::vector<RenderCommand>* m_render_queue;
};
} // namespace ICE
1 change: 1 addition & 0 deletions ICE/Graphics/include/GraphicsAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/GraphicsFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace ICE {
class GraphicsFactory {
public:
virtual ~GraphicsFactory() = default;
virtual std::shared_ptr<Context> createContext(const std::shared_ptr<Window>& window) const = 0;

virtual std::shared_ptr<Framebuffer> createFramebuffer(const FrameBufferFormat& format) const = 0;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/ShaderProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
namespace ICE {
class ShaderProgram {
public:
virtual ~ShaderProgram() = default;
virtual void bind() const = 0;
virtual void unbind() const = 0;

Expand Down
1 change: 1 addition & 0 deletions ICE/Graphics/include/VertexArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<VertexBuffer>& buffer, int size) = 0;
Expand Down
17 changes: 6 additions & 11 deletions ICE/Graphics/src/GeometryPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ GeometryPass::GeometryPass(const std::shared_ptr<RendererAPI>& api, const std::s
: m_api(api),
m_factory(factory) {
m_framebuffer = factory->createFramebuffer(format);
m_instance_buffer = factory->createVertexBuffer();
}

void GeometryPass::execute() {
Expand Down Expand Up @@ -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);
}
}
Expand Down
12 changes: 12 additions & 0 deletions ICE/GraphicsAPI/OpenGL/include/OpenGLBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions ICE/GraphicsAPI/OpenGL/include/OpenGLFramebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 8 additions & 1 deletion ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

Expand Down
9 changes: 9 additions & 0 deletions ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions ICE/GraphicsAPI/OpenGL/include/OpenGLVertexArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
8 changes: 8 additions & 0 deletions ICE/GraphicsAPI/OpenGL/src/OpenGLBuffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
6 changes: 6 additions & 0 deletions ICE/GraphicsAPI/OpenGL/src/OpenGLFramebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 14 additions & 2 deletions ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ OpenGLShader::OpenGLShader(const Shader &shader_asset) {
m_programID = glCreateProgram();
Logger::Log(Logger::VERBOSE, "Graphics", "Compiling shader...");

std::vector<GLuint> 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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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<GLuint>(shader);
}


Expand Down
Loading
Loading