Skip to content

Commit

Permalink
Allow pre-building materials with descriptors and return handles
Browse files Browse the repository at this point in the history
  • Loading branch information
SirBob01 committed Oct 24, 2024
1 parent 4eeed6a commit 483702d
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 38 deletions.
16 changes: 11 additions & 5 deletions src/Graphics/Material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
#include <Utils/IdGenerator.hpp>

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

/**
* @brief Topology modes.
*
Expand Down Expand Up @@ -38,7 +44,7 @@ namespace Dynamo::Graphics {
* @brief Material descriptor.
*
*/
struct Material {
struct MaterialDescriptor {
/**
* @brief Vertex shader handle.
*
Expand Down Expand Up @@ -76,21 +82,21 @@ namespace Dynamo::Graphics {
* @return true
* @return false
*/
inline bool operator==(const Material &other) const {
inline bool operator==(const MaterialDescriptor &other) const {
return vertex == other.vertex && fragment == other.fragment && topology == other.topology &&
fill == other.fill && cull == other.cull;
}
};
} // namespace Dynamo::Graphics

/**
* @brief Hash function implementation for Graphics Material.
* @brief Hash function implementation for Graphics MaterialDescriptor.
*
* @tparam
*/
template <>
struct std::hash<Dynamo::Graphics::Material> {
inline size_t operator()(const Dynamo::Graphics::Material &material) const {
struct std::hash<Dynamo::Graphics::MaterialDescriptor> {
inline size_t operator()(const Dynamo::Graphics::MaterialDescriptor &material) const {
size_t hash0 = std::hash<Dynamo::Graphics::Shader>{}(material.vertex);
size_t hash1 = std::hash<Dynamo::Graphics::Shader>{}(material.fragment);
size_t hash2 = std::hash<unsigned>{}(static_cast<unsigned>(material.topology));
Expand Down
6 changes: 5 additions & 1 deletion src/Graphics/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ namespace Dynamo::Graphics::Vulkan {

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

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

void Renderer::render() {
const FrameContext &frame = _frame_contexts.next();
vkWaitForFences(_device, 1, &frame.sync_fence, VK_TRUE, UINT64_MAX);
Expand Down Expand Up @@ -155,7 +159,7 @@ namespace Dynamo::Graphics::Vulkan {

// Iterate over models and draw
for (Model model : _models) {
MaterialInstance pipeline_pass = _materials.get(model.material, _swapchain, _shaders);
MaterialInstance pipeline_pass = _materials.get(model.material);

FramebufferSettings framebuffer_settings;
framebuffer_settings.view = _swapchain.views[image_index];
Expand Down
8 changes: 8 additions & 0 deletions src/Graphics/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ namespace Dynamo::Graphics::Vulkan {
*/
void destroy_shader(Shader shader);

/**
* @brief Build a material.
*
* @param descriptor
* @return Material
*/
Material build_material(const MaterialDescriptor &descriptor);

/**
* @brief Draw a model in the current frame.
*
Expand Down
32 changes: 12 additions & 20 deletions src/Graphics/Vulkan/MaterialRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,12 @@ namespace Dynamo::Graphics::Vulkan {
return pipeline;
}

MaterialInstance
MaterialRegistry::build(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders) {
Material MaterialRegistry::build(const MaterialDescriptor &descriptor,
const Swapchain &swapchain,
const ShaderSet &shaders) {
MaterialInstance instance;
const ShaderModule &vertex_module = shaders.get(material.vertex);
const ShaderModule &fragment_module = shaders.get(material.fragment);
const ShaderModule &vertex_module = shaders.get(descriptor.vertex);
const ShaderModule &fragment_module = shaders.get(descriptor.fragment);

// Aggregate descriptor layouts
std::vector<VkDescriptorSetLayout> descriptor_layouts;
Expand Down Expand Up @@ -251,9 +252,9 @@ namespace Dynamo::Graphics::Vulkan {
GraphicsPipelineSettings pipeline_settings;
pipeline_settings.vertex = vertex_module;
pipeline_settings.fragment = fragment_module;
pipeline_settings.topology = convert_topology(material.topology);
pipeline_settings.cull_mode = convert_cull(material.cull);
pipeline_settings.polygon_mode = convert_fill(material.fill);
pipeline_settings.topology = convert_topology(descriptor.topology);
pipeline_settings.cull_mode = convert_cull(descriptor.cull);
pipeline_settings.polygon_mode = convert_fill(descriptor.fill);
pipeline_settings.renderpass = instance.renderpass;
pipeline_settings.layout = instance.layout;
auto pipeline_it = _pipelines.find(pipeline_settings);
Expand All @@ -264,22 +265,13 @@ namespace Dynamo::Graphics::Vulkan {
_pipelines.emplace(pipeline_settings, instance.pipeline);
}

return instance;
}

MaterialInstance
MaterialRegistry::get(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders) {
// It's expensive to index into pipeline/layout/pass caches every time, so check if dirty before rebuilding
auto instance_it = _instances.find(material);
if (instance_it != _instances.end()) {
return instance_it->second;
}

MaterialInstance instance = build(material, swapchain, shaders);
Material material = IdGenerator<Material>::generate();
_instances.emplace(material, instance);
return instance;
return material;
}

MaterialInstance &MaterialRegistry::get(Material material) { return _instances.at(material); }

void MaterialRegistry::destroy() {
// Clean up pipelines
vkDestroyPipelineCache(_device, _pipeline_cache, nullptr);
Expand Down
22 changes: 10 additions & 12 deletions src/Graphics/Vulkan/MaterialRegistry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,29 +173,27 @@ namespace Dynamo::Graphics::Vulkan {
*/
VkPipeline build_pipeline(const GraphicsPipelineSettings &settings) const;

public:
MaterialRegistry(VkDevice device, const std::string &filename);
MaterialRegistry() = default;

/**
* @brief Build the material instance.
* @brief Build a material and its resources.
*
* @param material
* @param descriptor
* @param swapchain
* @param shaders
* @return MaterialInstance
*/
MaterialInstance build(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders);

public:
MaterialRegistry(VkDevice device, const std::string &filename);
MaterialRegistry() = default;
Material build(const MaterialDescriptor &descriptor, const Swapchain &swapchain, const ShaderSet &shaders);

/**
* @brief Build a Vulkan material instance.
* @brief Get a material instance.
*
* @param material
* @param swapchain
* @param shaders
* @return MaterialInstance
* @return MaterialInstance&
*/
MaterialInstance get(const Material &material, const Swapchain &swapchain, const ShaderSet &shaders);
MaterialInstance &get(Material material);

/**
* @brief Destroy all Vulkan resources.
Expand Down

0 comments on commit 483702d

Please sign in to comment.