Skip to content

Commit

Permalink
Implement Texture binding system for Uniforms
Browse files Browse the repository at this point in the history
* Implement MemoryPool to manage all device memory allocations
* Remove Buffer class
* Rename VkResult_log to VkResult_check
* Remove redundant/verbose documentation for internal submodules (annoying to maintain)
  • Loading branch information
SirBob01 committed Nov 2, 2024
1 parent 660657f commit f232f0a
Show file tree
Hide file tree
Showing 29 changed files with 1,175 additions and 1,073 deletions.
1 change: 1 addition & 0 deletions src/Dynamo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Graphics/Model.hpp>
#include <Graphics/Renderer.hpp>
#include <Graphics/Shader.hpp>
#include <Graphics/Texture.hpp>
#include <Input.hpp>
#include <Math/Box2.hpp>
#include <Math/Circle.hpp>
Expand Down
2 changes: 1 addition & 1 deletion src/Graphics/Mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace Dynamo::Graphics {
*
*/
struct MeshDescriptor {
using AttributeBuffer = std::vector<char>;
using AttributeBuffer = std::vector<unsigned char>;

std::vector<AttributeBuffer> attributes;
unsigned vertex_count;
Expand Down
53 changes: 35 additions & 18 deletions src/Graphics/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Dynamo::Graphics {
_surface = _display.create_vulkan_surface(_instance);

// Create the logical device
_physical = PhysicalDevice::select(_instance, _surface);
_physical = PhysicalDevice::select_best(_instance, _surface);
_device = VkDevice_create(_physical);

// Build the swapchain and its views
Expand All @@ -20,10 +20,12 @@ namespace Dynamo::Graphics {
_transfer_pool = VkCommandPool_create(_device, _physical.transfer_queues);

// Vulkan object registries
_meshes = MeshRegistry(_device, _physical, _transfer_pool);
_memory = MemoryPool(_device, _physical);
_shaders = ShaderRegistry(_device);
_materials = MaterialRegistry(_device, root_asset_directory + "/vulkan_cache.bin");
_meshes = MeshRegistry(_device, _physical, _transfer_pool);
_uniforms = UniformRegistry(_device, _physical, _transfer_pool);
_textures = TextureRegistry(_device, _physical, _transfer_pool);
_materials = MaterialRegistry(_device, root_asset_directory + "/vulkan_cache.bin");
_framebuffers = FramebufferCache(_device);

// Frame contexts
Expand All @@ -46,10 +48,12 @@ namespace Dynamo::Graphics {
// High-level objects
_frame_contexts.destroy();
_framebuffers.destroy();
_uniforms.destroy();
_materials.destroy();
_textures.destroy(_memory);
_uniforms.destroy(_memory);
_meshes.destroy(_memory);
_shaders.destroy();
_meshes.destroy();
_memory.destroy();
_swapchain.destroy();

// Vulkan core objects
Expand Down Expand Up @@ -79,19 +83,25 @@ namespace Dynamo::Graphics {
_clear.color.float32[3] = color.a;
}

Mesh Renderer::build_mesh(const MeshDescriptor &descriptor) { return _meshes.build(descriptor); }
Mesh Renderer::build_mesh(const MeshDescriptor &descriptor) { return _meshes.build(descriptor, _memory); }

void Renderer::destroy_mesh(Mesh mesh) { _meshes.destroy(mesh); }
void Renderer::destroy_mesh(Mesh mesh) { _meshes.destroy(mesh, _memory); }

Shader Renderer::build_shader(const ShaderDescriptor &descriptor) { return _shaders.build(descriptor); }

void Renderer::destroy_shader(Shader shader) { _shaders.destroy(shader); }

Texture Renderer::build_texture(const TextureDescriptor &descriptor) {
return _textures.build(descriptor, _memory);
}

void Renderer::destroy_texture(Texture texture) { _textures.destroy(texture, _memory); }

Material Renderer::build_material(const MaterialDescriptor &descriptor) {
return _materials.build(descriptor, _swapchain, _shaders, _uniforms);
return _materials.build(descriptor, _swapchain, _shaders, _uniforms, _memory);
}

void Renderer::destroy_material(Material material) { _materials.destroy(material, _uniforms); }
void Renderer::destroy_material(Material material) { _materials.destroy(material, _uniforms, _memory); }

std::optional<Uniform> Renderer::get_uniform(Material material, const std::string &name) {
MaterialInstance &instance = _materials.get(material);
Expand All @@ -104,7 +114,14 @@ namespace Dynamo::Graphics {
return {};
}

void Renderer::write_uniform(Uniform uniform, void *data) { _uniforms.write(uniform, data); }
void Renderer::write_uniform(Uniform uniform, void *data, unsigned index, unsigned count) {
_uniforms.write(uniform, data, index, count);
}

void Renderer::bind_texture(Uniform uniform, Texture texture, unsigned index) {
const TextureInstance &instance = _textures.get(texture);
_uniforms.bind(uniform, instance, index);
}

void Renderer::draw(const Model &model) { _models.push_back(model); }

Expand All @@ -123,18 +140,18 @@ namespace Dynamo::Graphics {
rebuild_swapchain();
return;
} else if (acquire_result != VK_SUCCESS && acquire_result != VK_SUBOPTIMAL_KHR) {
VkResult_log("Acquire Image", acquire_result);
VkResult_check("Acquire Image", acquire_result);
}

VkResult_log("Reset Fence", vkResetFences(_device, 1, &frame.sync_fence));
VkResult_log("Reset Command Buffer", vkResetCommandBuffer(frame.command_buffer, 0));
VkResult_check("Reset Fence", vkResetFences(_device, 1, &frame.sync_fence));
VkResult_check("Reset Command Buffer", vkResetCommandBuffer(frame.command_buffer, 0));

VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = 0;
begin_info.pInheritanceInfo = nullptr;

VkResult_log("Begin Command Recording", vkBeginCommandBuffer(frame.command_buffer, &begin_info));
VkResult_check("Begin Command Recording", vkBeginCommandBuffer(frame.command_buffer, &begin_info));

// Group models by material and geometry
std::sort(_models.begin(), _models.end(), [](const Model &a, const Model &b) {
Expand All @@ -161,7 +178,7 @@ namespace Dynamo::Graphics {
VkPipeline prev_pipeline = VK_NULL_HANDLE;
Mesh prev_mesh = reinterpret_cast<Mesh>(-1);
for (Model model : _models) {
const MeshAllocation &mesh = _meshes.get(model.mesh);
const MeshInstance &mesh = _meshes.get(model.mesh);
const MaterialInstance &material = _materials.get(model.material);

// Rebind renderpass if changed
Expand Down Expand Up @@ -248,7 +265,7 @@ namespace Dynamo::Graphics {
if (prev_renderpass != VK_NULL_HANDLE) {
vkCmdEndRenderPass(frame.command_buffer);
}
VkResult_log("End Command Buffer", vkEndCommandBuffer(frame.command_buffer));
VkResult_check("End Command Buffer", vkEndCommandBuffer(frame.command_buffer));

// Submit commands
VkQueue queue;
Expand All @@ -265,7 +282,7 @@ namespace Dynamo::Graphics {
submit_info.pSignalSemaphores = &frame.sync_render_done;
submit_info.pWaitDstStageMask = &wait_stage_mask;

VkResult_log("Graphics Submit", vkQueueSubmit(queue, 1, &submit_info, frame.sync_fence));
VkResult_check("Graphics Submit", vkQueueSubmit(queue, 1, &submit_info, frame.sync_fence));

// Present the render
VkPresentInfoKHR present_info = {};
Expand All @@ -282,7 +299,7 @@ namespace Dynamo::Graphics {
if (present_result == VK_ERROR_OUT_OF_DATE_KHR || present_result == VK_SUBOPTIMAL_KHR) {
rebuild_swapchain();
} else if (present_result != VK_SUCCESS) {
VkResult_log("Present Render", present_result);
VkResult_check("Present Render", present_result);
}
}
} // namespace Dynamo::Graphics
40 changes: 35 additions & 5 deletions src/Graphics/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
#include <Display.hpp>
#include <Graphics/Mesh.hpp>
#include <Graphics/Model.hpp>
#include <Graphics/Vulkan/Buffer.hpp>
#include <Graphics/Texture.hpp>
#include <Graphics/Vulkan/FrameContext.hpp>
#include <Graphics/Vulkan/FramebufferCache.hpp>
#include <Graphics/Vulkan/MaterialRegistry.hpp>
#include <Graphics/Vulkan/MeshRegistry.hpp>
#include <Graphics/Vulkan/PhysicalDevice.hpp>
#include <Graphics/Vulkan/ShaderRegistry.hpp>
#include <Graphics/Vulkan/Swapchain.hpp>
#include <Graphics/Vulkan/TextureRegistry.hpp>
#include <Graphics/Vulkan/UniformRegistry.hpp>
#include <Math/Color.hpp>

Expand All @@ -38,10 +39,12 @@ namespace Dynamo::Graphics {
VkCommandPool _graphics_pool;
VkCommandPool _transfer_pool;

MemoryPool _memory;
MeshRegistry _meshes;
ShaderRegistry _shaders;
MaterialRegistry _materials;
UniformRegistry _uniforms;
TextureRegistry _textures;
FramebufferCache _framebuffers;

FrameContextList _frame_contexts;
Expand All @@ -51,11 +54,10 @@ namespace Dynamo::Graphics {

// TODO - Fixes:
// * Pre-defined render pass ---- Define a default render pass to handle the no-draw case
// * Let Buffer take in fallback memory types, only throw when all options exhausted

// TODO - Features:
// * Live update texture? --- Support non-shader-optimal image layouts
// * Depth-stencil buffer ---- Update jukebox to showcase 3d perspective (to visualize depth buffering)
// * Texture system ---- Similar to shaders / meshes, generate a handle and return
// * Draw-to-texture ---- overload render(), render(Texture texture)

/**
Expand Down Expand Up @@ -116,6 +118,21 @@ namespace Dynamo::Graphics {
*/
void destroy_shader(Shader shader);

/**
* @brief Build a texture.
*
* @param descriptor
* @return Texture
*/
Texture build_texture(const TextureDescriptor &descriptor);

/**
* @brief Free texture resources.
*
* @param texture
*/
void destroy_texture(Texture texture);

/**
* @brief Build a material.
*
Expand Down Expand Up @@ -143,12 +160,25 @@ namespace Dynamo::Graphics {
/**
* @brief Write to a uniform.
*
* Data must match the size of the uniform variable.
* If the uniform is an array, an index offset and count can be provided.
*
* @param uniform
* @param data
* @param index
* @param count
*/
void write_uniform(Uniform uniform, void *data, unsigned index = 0, unsigned count = 1);

/**
* @brief Bind a texture to a uniform variable.
*
* If the uniform is an array, an index offset can be provided.
*
* @param uniform
* @param texture
* @param index
*/
void write_uniform(Uniform uniform, void *data);
void bind_texture(Uniform uniform, Texture texture, unsigned index = 0);

/**
* @brief Draw a model in the current frame.
Expand Down
104 changes: 104 additions & 0 deletions src/Graphics/Texture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#pragma once

#include <vector>

#include <Utils/SparseArray.hpp>

namespace Dynamo::Graphics {
/**
* @brief Texture resource handle.
*
*/
DYN_DEFINE_ID_TYPE(Texture);

/**
* @brief Texture formats.
*
*/
enum class TextureFormat {
F32_R_Norm,
U8_RGB_Norm,
U8_RGBA_Norm,
};

/**
* @brief Texture filter modes.
*
*/
enum class TextureFilter {
Nearest,
Linear,
};

/**
* @brief Texture addressing modes.
*
*/
enum class TextureAddressMode {
Repeat,
RepeatMirror,
Clamp,
ClampMirror,
ClampBorder,
};

/**
* @brief Texture descriptor.
*
*/
struct TextureDescriptor {
/**
* @brief Texture unit byte buffer.
*
*/
std::vector<unsigned char> texels;

/**
* @brief Width of the texture in texture units.
*
*/
unsigned width = 0;

/**
* @brief Height of the texture in texture units.
*
*/
unsigned height = 0;

/**
* @brief Format of the texture determines how the byte buffer is interpreted.
*
*/
TextureFormat format = TextureFormat::U8_RGBA_Norm;

/**
* @brief Minification filter.
*
*/
TextureFilter min_filter = TextureFilter::Nearest;

/**
* @brief Magnification filter.
*
*/
TextureFilter mag_filter = TextureFilter::Nearest;

/**
* @brief How U coordinates are addressed outside [0, 1).
*
*/
TextureAddressMode u_address_mode = TextureAddressMode::Repeat;

/**
* @brief How V coordinates are addressed outside [0, 1).
*
*/
TextureAddressMode v_address_mode = TextureAddressMode::Repeat;

/**
* @brief How W coordinates are addressed outside [0, 1).
*
*/
TextureAddressMode w_address_mode = TextureAddressMode::Repeat;
};
} // namespace Dynamo::Graphics
Loading

0 comments on commit f232f0a

Please sign in to comment.