Finish pipeline rewrite

This commit is contained in:
2024-10-11 11:58:39 -04:00
parent 32de4cdc0c
commit 59fda55356
71 changed files with 1075 additions and 950 deletions

View File

@@ -18,6 +18,7 @@
#include "engine/assets/transfer/TransferManager.hpp"
#include "engine/math/Average.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
namespace fgl::engine
{

View File

@@ -21,7 +21,7 @@ namespace fgl::engine
return camera->getDescriptor( frame_idx );
}
void FrameInfo::bindCamera( internal::Pipeline& pipeline )
void FrameInfo::bindCamera( [[maybe_unused]] internal::Pipeline& pipeline )
{
//TODO: This
}

View File

@@ -42,29 +42,28 @@ namespace fgl::engine
alignas( 16 ) int num_lights { 0 };
};
//using GlobalDescriptorSet = descriptors::DescriptorSetLayout< 0, descriptors::EmptyDescriptor< 0 > >;
constexpr descriptors::Descriptor texture_descriptor { 0,
vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eAllGraphics,
512,
vk::DescriptorBindingFlagBits::eUpdateAfterBind
| vk::DescriptorBindingFlagBits::ePartiallyBound };
using TextureDescriptor = descriptors::Descriptor<
0,
vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eAllGraphics,
512,
vk::DescriptorBindingFlagBits::eUpdateAfterBind | vk::DescriptorBindingFlagBits::ePartiallyBound >;
inline static descriptors::DescriptorSetLayout texture_descriptor_set { 2, texture_descriptor };
using TextureDescriptorSet = descriptors::DescriptorSetLayout< 2, TextureDescriptor >;
constexpr vk::ShaderStageFlags FRAG_STAGE { vk::ShaderStageFlagBits::eFragment };
using PositionDescriptor = descriptors::AttachmentDescriptor< 0, vk::ShaderStageFlagBits::eFragment >;
using NormalDescriptor = descriptors::AttachmentDescriptor< 1, vk::ShaderStageFlagBits::eFragment >;
using AlbedoDescriptor = descriptors::AttachmentDescriptor< 2, vk::ShaderStageFlagBits::eFragment >;
constexpr descriptors::AttachmentDescriptor position_descriptor { 0, FRAG_STAGE };
constexpr descriptors::AttachmentDescriptor normal_descriptor { 1, FRAG_STAGE };
constexpr descriptors::AttachmentDescriptor albedo_descriptor { 2, FRAG_STAGE };
static_assert( is_descriptor< PositionDescriptor > );
inline static descriptors::DescriptorSetLayout gbuffer_set {
0, position_descriptor, normal_descriptor, albedo_descriptor
};
using GBufferDescriptorSet =
descriptors::DescriptorSetLayout< 0, PositionDescriptor, NormalDescriptor, AlbedoDescriptor >;
constexpr descriptors::AttachmentDescriptor input_descriptor { 0, vk::ShaderStageFlagBits::eFragment };
using InputDescriptor = descriptors::AttachmentDescriptor< 0, vk::ShaderStageFlagBits::eFragment >;
using GuiInputDescriptorSet = descriptors::DescriptorSetLayout< 0, InputDescriptor >;
inline static descriptors::DescriptorSetLayout gui_descriptor_set { 0, input_descriptor };
class OctTreeNode;

View File

@@ -52,6 +52,24 @@ namespace fgl::engine
return info;
}
ImageView::~ImageView()
{
}
void ImageView::setName( const std::string str )
{
m_name = str;
m_sampler.setName( str + " Sampler" );
m_resource->setName( str + " Resource" );
vk::DebugUtilsObjectNameInfoEXT info {};
info.objectType = vk::ObjectType::eImageView;
info.pObjectName = str.c_str();
info.setObjectHandle( reinterpret_cast< std::uint64_t >( static_cast< VkImageView >( *m_image_view ) ) );
Device::getInstance().setDebugUtilsObjectName( info );
}
vk::ImageView ImageView::getVkView()
{
return *m_image_view;
@@ -62,11 +80,6 @@ namespace fgl::engine
return m_resource->extent();
}
void ImageView::setName( const std::string& str )
{
m_resource->setName( str );
}
bool ImageView::ready()
{
return m_resource->ready();

View File

@@ -21,11 +21,12 @@ namespace fgl::engine
vk::raii::ImageView m_image_view;
Sampler m_sampler;
std::string m_name;
[[nodiscard]] static vk::raii::ImageView createImageView( const std::shared_ptr< ImageHandle >& img );
public:
void setName( const std::string& str );
//! Returns true if the resource has been staged
bool ready();
@@ -39,8 +40,6 @@ namespace fgl::engine
ImageView( ImageView&& other ) = default;
ImageView& operator=( ImageView&& other ) = default;
[[nodiscard]] static vk::raii::ImageView createImageView( const std::shared_ptr< ImageHandle >& img );
[[nodiscard]] vk::Extent2D getExtent() const;
[[nodiscard]] vk::ImageView getVkView();
@@ -49,10 +48,16 @@ namespace fgl::engine
[[nodiscard]] VkImage getVkImage() { return m_resource->getVkImage(); }
void setSampler( Sampler&& sampler ) { m_sampler = std::forward< Sampler >( sampler ); }
[[nodiscard]] Sampler& getSampler() { return m_sampler; };
vk::DescriptorImageInfo descriptorInfo( vk::Sampler sampler, vk::ImageLayout layout ) const;
vk::DescriptorImageInfo descriptorInfo( vk::ImageLayout layout ) const;
~ImageView();
void setName( std::string str );
};
} // namespace fgl::engine

View File

@@ -12,12 +12,12 @@ namespace fgl::engine
{
vk::raii::Sampler createSampler(
vk::Filter min_filter,
vk::Filter mag_filter,
vk::SamplerMipmapMode mipmode,
vk::SamplerAddressMode sampler_wrap_u,
vk::SamplerAddressMode sampler_wrap_v,
vk::SamplerAddressMode sampler_wrap_w )
const vk::Filter min_filter,
const vk::Filter mag_filter,
const vk::SamplerMipmapMode mipmode,
const vk::SamplerAddressMode sampler_wrap_u,
const vk::SamplerAddressMode sampler_wrap_v,
const vk::SamplerAddressMode sampler_wrap_w )
{
vk::SamplerCreateInfo info;
@@ -95,7 +95,7 @@ namespace fgl::engine
* @param wraps x wrap
* @param wrapt y wrap
*/
Sampler::Sampler( int min_filter, int mag_filter, int wraps, int wrapt ) :
Sampler::Sampler( const int min_filter, const int mag_filter, const int wraps, const int wrapt ) :
Sampler(
gl::filterToVk( min_filter ),
gl::filterToVk( mag_filter ),

View File

@@ -15,7 +15,7 @@ namespace fgl::engine
class Sampler
{
vk::raii::Sampler m_sampler { VK_NULL_HANDLE };
vk::raii::Sampler m_sampler;
public:

View File

@@ -43,8 +43,11 @@ namespace fgl::engine
// {location, binding, format, offset}
// attribute_descriptions.emplace_back( 0, 0, vk::Format::eR32G32B32Sfloat, offsetof( ModelVertex, m_position ) );
// attribute_descriptions.emplace_back( 1, 0, vk::Format::eR32G32B32Sfloat, offsetof( ModelVertex, m_color ) );
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
attribute_descriptions.emplace_back( 2, 0, vk::Format::eR32G32B32Sfloat, offsetof( ModelVertex, m_normal ) );
attribute_descriptions.emplace_back( 3, 0, vk::Format::eR32G32Sfloat, offsetof( ModelVertex, m_uv ) );
#pragma GCC diagnostic pop
//Normal Matrix
attribute_descriptions.emplace_back( 4, 1, vk::Format::eR32G32B32A32Sfloat, 0 );

View File

@@ -3,7 +3,11 @@
//
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include <vector>
@@ -11,7 +15,7 @@ namespace vk
{
struct VertexInputAttributeDescription;
struct VertexInputBindingDescription;
}
} // namespace vk
namespace fgl::engine
{
@@ -28,5 +32,4 @@ namespace fgl::engine
static std::vector< vk::VertexInputAttributeDescription > getAttributeDescriptions();
};
}
} // namespace fgl::engine

View File

@@ -100,54 +100,66 @@ namespace fgl::engine
// If the type is a smaller scalar then we want can still copy the data.
log::warn( "Attempting to copy data of size {} into type of size {}", byte_count, T_SIZE );
switch ( byte_count )
if constexpr ( std::is_scalar_v< T > )
{
default:
throw std::runtime_error( "Unknown size" );
case 1:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint8_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset + ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 2:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint16_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset + ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 4:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint32_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset + ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 8:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint64_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset + ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
switch ( byte_count )
{
default:
throw std::runtime_error( "Unknown size" );
case 1:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint8_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset
+ ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 2:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint16_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset
+ ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 4:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint32_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset
+ ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
case 8:
for ( std::size_t i = 0; i < accessor.count; ++i )
{
std::uint64_t tmp {};
std::memcpy(
&tmp,
buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset
+ ( i * byte_count ),
byte_count );
data.emplace_back( static_cast< T >( tmp ) );
}
return data;
}
}
else
{
throw std::runtime_error(
std::format( "Tried extracting data of size {} into type of size {}", byte_count, T_SIZE ) );
}
}
else

View File

@@ -58,7 +58,7 @@ namespace fgl::engine
descriptors::DescriptorSet& Camera::getDescriptor( const FrameIndex index )
{
assert( index < m_camera_info_descriptors.size() );
return m_camera_info_descriptors[ index ];
return *m_camera_info_descriptors[ index ];
}
void Camera::setFOV( const float fov_y )
@@ -331,10 +331,10 @@ namespace fgl::engine
for ( std::uint8_t i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
{
descriptors::DescriptorSet set { CameraDescriptorSet::createLayout() };
set.setMaxIDX( 0 );
set.bindUniformBuffer( 0, m_camera_frame_info[ i ] );
set.update();
auto set { camera_descriptor_set.create() };
set->setMaxIDX( 0 );
set->bindUniformBuffer( 0, m_camera_frame_info[ i ] );
set->update();
m_camera_info_descriptors.emplace_back( std::move( set ) );
}

View File

@@ -73,7 +73,7 @@ namespace fgl::engine
PerFrameSuballocation< HostSingleT< CameraInfo > > m_camera_frame_info;
// Camera info is expected at binding 0
std::vector< descriptors::DescriptorSet > m_camera_info_descriptors {};
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_camera_info_descriptors {};
// TODO: Remove this old swapchain and instead do a proper deffered cleanup of it.
std::shared_ptr< CameraSwapchain > m_old_swapchain { nullptr };

View File

@@ -7,8 +7,10 @@
namespace fgl::engine
{
using CameraDescriptor =
descriptors::Descriptor< 0, vk::DescriptorType::eUniformBuffer, vk::ShaderStageFlagBits::eAllGraphics >;
constexpr descriptors::Descriptor camera_descriptor { 0,
vk::DescriptorType::eUniformBuffer,
vk::ShaderStageFlagBits::eAllGraphics };
inline static descriptors::DescriptorSetLayout camera_descriptor_set { 1, camera_descriptor };
using CameraDescriptorSet = descriptors::DescriptorSetLayout< 1, CameraDescriptor >;
} // namespace fgl::engine

View File

@@ -16,7 +16,8 @@ namespace fgl::engine
for ( PresentIndex i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
{
auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
//auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
auto set { gbuffer_set.create() };
set->setMaxIDX( 2 );

View File

@@ -1,32 +0,0 @@
//
// Created by kj16609 on 1/1/24.
//
#pragma once
#include "is_empty_descriptor.hpp"
#include "is_layout_descriptor.hpp"
namespace fgl::engine
{
template < typename T >
concept is_image_descriptor =
is_layout_descriptor< T > && ( T::m_descriptor_type == vk::DescriptorType::eSampledImage );
template < typename T >
concept is_attachment_descriptor =
is_layout_descriptor< T > && ( T::m_descriptor_type == vk::DescriptorType::eInputAttachment );
template < typename T >
concept is_uniform_buffer_desciptor =
is_layout_descriptor< T > && ( T::m_descriptor_type == vk::DescriptorType::eUniformBuffer );
template < typename T >
concept is_storage_buffer_descriptor =
is_layout_descriptor< T > && ( T::m_descriptor_type == vk::DescriptorType::eStorageBuffer );
template < typename T >
concept is_buffer_descriptor = is_uniform_buffer_desciptor< T > || is_storage_buffer_descriptor< T >;
template < typename T > concept is_descriptor = is_empty_descriptor< T > || is_layout_descriptor< T >;
} // namespace fgl::engine

View File

@@ -1,24 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_raii.hpp>
#include <concepts>
#include <cstdint>
namespace fgl::engine
{
template < typename T >
concept is_descriptor_set = requires( std::remove_reference_t< T > t ) {
{
t.descriptor_count
} -> std::same_as< const std::uint16_t& >;
{
T::createLayout()
} -> std::same_as< vk::raii::DescriptorSetLayout >;
};
} // namespace fgl::engine

View File

@@ -1,21 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include <concepts>
#include <cstdint>
namespace fgl::engine
{
template < typename T >
concept is_descriptor_set_collection = requires( T t ) {
typename T::DescriptorSetTuple;
{
t.DescriptorSetCount
} -> std::same_as< const std::uint64_t& >;
};
} // namespace fgl::engine

View File

@@ -1,24 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
namespace fgl::engine
{
/**
* Descriptor must have a `static constexpr bool is_empty` member with the value `true`
* Descriptor must also be valid in `is_descriptor`
* @tparam T
*/
template < typename T >
concept is_empty_descriptor = requires( T t ) {
{
t.m_binding_idx
} -> std::same_as< const std::uint16_t& >;
{
t.is_empty
} -> std::same_as< const bool& >;
} && T::is_empty;
} // namespace fgl::engine

View File

@@ -1,16 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include "is_descriptor_set.hpp"
#include "is_empty_descriptor.hpp"
namespace fgl::engine
{
template < typename T >
concept is_empty_descriptor_set = is_descriptor_set< T > && ( T::descriptor_count == 1 )
&& is_empty_descriptor< typename T::template Binding< 0 > >;
}

View File

@@ -1,21 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
namespace fgl::engine
{
template < typename T >
concept is_layout_descriptor = requires( T t ) {
{
t.m_binding_idx
} -> std::same_as< const std::uint16_t& >;
{
t.m_layout_binding
} -> std::same_as< const vk::DescriptorSetLayoutBinding& >;
{
t.m_descriptor_type
} -> std::same_as< const vk::DescriptorType& >;
};
}

View File

@@ -1,13 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include "is_constant_range.hpp"
#include "is_descriptor_set.hpp"
namespace fgl::engine
{
template < typename T > concept is_valid_pipeline_input = is_constant_range< T > || is_descriptor_set< T >;
}

View File

@@ -14,7 +14,7 @@ namespace fgl::engine::debug
void drawLine( const LineSegment< CoordinateSpace::World >& line, const glm::vec3 color )
{
drawLine( line.getStart(), line.getEnd() );
drawLine( line.getStart(), line.getEnd(), color );
}
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box, const glm::vec3 color )

View File

@@ -4,8 +4,12 @@
#include "glm.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp>
#pragma GCC diagnostic pop
std::format_context::iterator std::formatter< glm::qua< float > >::format( const glm::quat& quat, format_context& ctx )
const

View File

@@ -4,7 +4,11 @@
#include "matrix.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/glm.hpp>
#pragma GCC diagnostic pop
std::format_context::iterator std::formatter< glm::vec4 >::format( const glm::vec4& vec, format_context& ctx ) const
{

View File

@@ -7,85 +7,81 @@
#include <cstdint>
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/concepts/is_descriptor.hpp"
namespace fgl::engine::descriptors
{
/**
*
* @tparam binding_idx Index of the descriptor
* @tparam descriptor_type Descriptor flags
* @tparam stage_flags
* @tparam binding_count Number of descriptors to have
* @tparam binding_flags Flags to bind with
*/
template <
std::uint16_t binding_idx,
vk::DescriptorType descriptor_type,
vk::ShaderStageFlags stage_flags = vk::ShaderStageFlagBits::eAll,
std::uint16_t binding_count = 1,
vk::DescriptorBindingFlags binding_flags = static_cast< vk::DescriptorBindingFlags >( 0 ) >
struct Descriptor
{
static constexpr std::uint16_t m_binding_idx { binding_idx };
static constexpr std::uint16_t m_count { binding_count };
std::uint16_t m_index;
vk::DescriptorType m_type;
vk::ShaderStageFlags m_stage_flags;
std::uint16_t m_count;
vk::DescriptorBindingFlags m_binding_flags;
static constexpr vk::DescriptorType m_descriptor_type { descriptor_type };
consteval Descriptor() = delete;
static constexpr auto m_binding_flags { binding_flags };
constexpr Descriptor(
const std::uint16_t binding_idx,
const vk::DescriptorType type,
const vk::ShaderStageFlags stage_flags,
const std::uint16_t count = 1,
const vk::DescriptorBindingFlags binding_flags = static_cast< vk::DescriptorBindingFlags >( 0 ) ) :
m_index( binding_idx ),
m_type( type ),
m_stage_flags( stage_flags ),
m_count( count ),
m_binding_flags( binding_flags )
{}
consteval static vk::DescriptorSetLayoutBinding generateLayoutBinding()
constexpr vk::DescriptorSetLayoutBinding generateLayoutBinding()
{
vk::DescriptorSetLayoutBinding layout_binding {};
layout_binding.binding = binding_idx;
layout_binding.descriptorType = descriptor_type;
layout_binding.descriptorCount = binding_count;
layout_binding.stageFlags = stage_flags;
vk::DescriptorSetLayoutBinding layout_binding;
layout_binding.binding = m_index;
layout_binding.descriptorType = m_type;
layout_binding.descriptorCount = m_count;
layout_binding.stageFlags = m_stage_flags;
layout_binding.pImmutableSamplers = VK_NULL_HANDLE;
return layout_binding;
}
/**
* The layout binding is used during pipeline creation to provide information to the pipeline about the descriptor set layout.
* This is used to construct the actual layout and can be done at compiletime.
*/
static constexpr vk::DescriptorSetLayoutBinding m_layout_binding { generateLayoutBinding() };
vk::DescriptorSetLayoutBinding m_layout_binding { generateLayoutBinding() };
};
template < std::uint16_t binding_idx, vk::ShaderStageFlags stage_flags >
using ImageDescriptor = Descriptor< binding_idx, vk::DescriptorType::eSampledImage, stage_flags >;
template < std::uint16_t binding_idx, vk::ShaderStageFlags stage_flags >
using AttachmentDescriptor = Descriptor< binding_idx, vk::DescriptorType::eInputAttachment, stage_flags >;
template < std::uint16_t binding_idx, vk::ShaderStageFlags stage_flags >
using StorageDescriptor = Descriptor< binding_idx, vk::DescriptorType::eStorageBuffer, stage_flags >;
template < std::uint16_t binding_idx, vk::ShaderStageFlags stage_flags >
using UniformDescriptor = Descriptor< binding_idx, vk::DescriptorType::eUniformBuffer, stage_flags >;
template < std::uint16_t idx >
struct EmptyDescriptor
struct ImageDescriptor : Descriptor
{
static constexpr std::uint16_t m_binding_idx { idx };
static constexpr bool is_empty { true };
ImageDescriptor() = delete;
constexpr ImageDescriptor( std::uint16_t idx, vk::ShaderStageFlags stage_flags ) :
Descriptor( idx, vk::DescriptorType::eSampledImage, stage_flags )
{}
};
static_assert( is_empty_descriptor< EmptyDescriptor< 0 > > );
//! Returns the maximum binding index for a list of given descriptors
template < is_descriptor Current, is_descriptor... Bindings >
consteval std::uint16_t getMaxDescriptorIDX()
struct AttachmentDescriptor : Descriptor
{
if constexpr ( sizeof...( Bindings ) == 0 )
{
return Current::m_binding_idx;
}
else
{
return std::max( Current::m_binding_idx, getMaxDescriptorIDX< Bindings... >() );
}
}
AttachmentDescriptor() = delete;
constexpr AttachmentDescriptor( std::uint16_t idx, vk::ShaderStageFlags stage_flags ) :
Descriptor( idx, vk::DescriptorType::eInputAttachment, stage_flags )
{}
};
struct StorageDescriptor : Descriptor
{
StorageDescriptor() = delete;
StorageDescriptor( std::uint16_t idx, vk::ShaderStageFlags stage_flags ) :
Descriptor( idx, vk::DescriptorType::eStorageBuffer, stage_flags )
{}
};
struct UniformDescriptor : Descriptor
{
UniformDescriptor() = delete;
UniformDescriptor( const std::uint16_t idx, vk::ShaderStageFlags stage_flags ) :
Descriptor( idx, vk::DescriptorType::eUniformBuffer, stage_flags )
{}
};
} // namespace fgl::engine::descriptors

View File

@@ -30,7 +30,7 @@ namespace fgl::engine::descriptors
DescriptorPool::DescriptorPool( std::uint32_t set_count ) : m_pool( createPool( set_count ) )
{}
[[nodiscard]] vk::raii::DescriptorSet DescriptorPool::allocateSet( vk::raii::DescriptorSetLayout& layout )
[[nodiscard]] vk::raii::DescriptorSet DescriptorPool::allocateSet( const vk::raii::DescriptorSetLayout& layout )
{
vk::DescriptorSetAllocateInfo alloc_info {};
alloc_info.setDescriptorPool( m_pool );

View File

@@ -41,7 +41,7 @@ namespace fgl::engine::descriptors
static DescriptorPool& init();
[[nodiscard]] static DescriptorPool& getInstance();
[[nodiscard]] vk::raii::DescriptorSet allocateSet( vk::raii::DescriptorSetLayout& layout );
[[nodiscard]] vk::raii::DescriptorSet allocateSet( const vk::raii::DescriptorSetLayout& layout );
};
} // namespace fgl::engine::descriptors

View File

@@ -10,24 +10,24 @@
#include <queue>
#include "DescriptorPool.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/assets/image/ImageView.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/texture/Texture.hpp"
namespace fgl::engine::descriptors
{
DescriptorSet::DescriptorSet( vk::raii::DescriptorSetLayout&& layout ) :
m_layout( std::forward< vk::raii::DescriptorSetLayout >( layout ) ),
m_set( DescriptorPool::getInstance().allocateSet( m_layout ) )
DescriptorSet::DescriptorSet( const vk::raii::DescriptorSetLayout& layout, std::uint16_t idx ) :
m_set_idx( idx ),
m_set( DescriptorPool::getInstance().allocateSet( layout ) )
{}
DescriptorSet::DescriptorSet( DescriptorSet&& other ) noexcept :
m_set_idx( other.m_set_idx ),
m_infos( std::move( other.m_infos ) ),
descriptor_writes( std::move( other.descriptor_writes ) ),
m_resources( std::move( other.m_resources ) ),
m_layout( std::move( other.m_layout ) ),
m_set( std::move( other.m_set ) ),
m_max_idx( other.m_max_idx )
{
@@ -36,10 +36,10 @@ namespace fgl::engine::descriptors
DescriptorSet& DescriptorSet::operator=( DescriptorSet&& other ) noexcept
{
m_set_idx = other.m_set_idx;
m_infos = std::move( other.m_infos );
descriptor_writes = std::move( other.descriptor_writes );
m_resources = std::move( other.m_resources );
m_layout = std::move( other.m_layout );
m_set = std::move( other.m_set );
other.m_set = VK_NULL_HANDLE;
m_max_idx = other.m_max_idx;

View File

@@ -28,6 +28,7 @@ namespace fgl::engine::descriptors
class DescriptorSet
{
std::uint16_t m_set_idx;
//TODO: Maybe redo this to not be a monostate variant?
std::vector< std::variant< std::monostate, vk::DescriptorImageInfo, vk::DescriptorBufferInfo > > m_infos {};
std::vector< vk::WriteDescriptorSet > descriptor_writes {};
@@ -35,7 +36,6 @@ namespace fgl::engine::descriptors
std::vector< std::variant< std::shared_ptr< ImageView >, std::shared_ptr< memory::BufferSuballocation > > >
m_resources {};
vk::raii::DescriptorSetLayout m_layout;
vk::raii::DescriptorSet m_set;
std::uint32_t m_max_idx { 0 };
@@ -52,8 +52,10 @@ namespace fgl::engine::descriptors
VkDescriptorSet getVkDescriptorSet() const { return *m_set; }
inline std::uint16_t setIDX() const { return m_set_idx; }
DescriptorSet() = delete;
DescriptorSet( vk::raii::DescriptorSetLayout&& layout );
DescriptorSet( const vk::raii::DescriptorSetLayout& layout, const std::uint16_t idx );
//Copy
DescriptorSet( const DescriptorSet& other ) = delete;

View File

@@ -1,105 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include "engine/concepts/is_empty_descriptor_set.hpp"
#include "engine/concepts/is_valid_pipeline_input.hpp"
#include "engine/descriptors/createDescriptorSets.hpp"
namespace fgl::engine::descriptors
{
template < is_descriptor_set Current, is_valid_pipeline_input... Sets >
consteval std::uint16_t getMaxBindingSetIDX()
{
if constexpr ( sizeof...( Sets ) == 0 )
return Current::m_set_idx;
else
{
constexpr auto current_idx { Current::m_set_idx };
constexpr auto next_idx { getMaxBindingSetIDX< Sets... >() };
return std::max( current_idx, next_idx );
}
}
template < is_constant_range Current, is_valid_pipeline_input... Sets >
consteval std::uint16_t getMaxBindingSetIDX()
{
if constexpr ( sizeof...( Sets ) == 0 )
return 0;
else
return getMaxBindingSetIDX< Sets... >();
}
template < is_valid_pipeline_input... DescriptorSets >
struct DescriptorSetCollection
{
using DescriptorSetTuple = std::tuple< DescriptorSets... >;
static constexpr auto SIZE { sizeof...( DescriptorSets ) };
static constexpr std::uint64_t DescriptorSetCount { sizeof...( DescriptorSets ) };
//If the first descriptor set is a constant range, then the pipeline has a constant range
static constexpr bool has_constant_range {
is_constant_range< std::tuple_element_t< 0, std::tuple< DescriptorSets... > > >
};
static constexpr std::uint16_t binding_sets { ( is_descriptor_set< DescriptorSets > + ... ) };
static constexpr std::uint16_t max_binding_set { getMaxBindingSetIDX< DescriptorSets... >() };
static constexpr std::uint16_t set_count { ( is_descriptor_set< DescriptorSets > + ... ) };
static constexpr std::uint16_t empty_sets { ( is_empty_descriptor_set< DescriptorSets > + ... ) };
static std::vector< vk::raii::DescriptorSetLayout > createDescriptorSets()
{
std::vector< vk::raii::DescriptorSetLayout > layouts {};
layouts.reserve( binding_sets );
createDescriptorSetsT< DescriptorSets... >( layouts );
assert( layouts.size() > 0 );
assert( layouts.size() == binding_sets );
return layouts;
}
template < std::uint64_t IDX >
requires( IDX < DescriptorSetCount )
using DescriptorSet = std::tuple_element_t< IDX, DescriptorSetTuple >;
template < std::uint64_t BindingIDX >
using BindingSet = DescriptorSet< BindingIDX + ( has_constant_range ? 1 : 0 ) >;
using PushConstantT = BindingSet< 0 >;
};
template <>
struct DescriptorSetCollection<>
{
using DescriptorSetTuple = std::tuple< void >;
static constexpr auto SIZE { 0 };
static constexpr std::uint64_t DescriptorSetCount { 0 };
//If the first descriptor set is a constant range, then the pipeline has a constant range
static constexpr bool has_constant_range { false };
static constexpr std::uint16_t binding_sets { 0 };
static constexpr std::uint16_t max_binding_set { 0 };
static constexpr std::uint16_t set_count { 0 };
static constexpr std::uint16_t empty_sets { 0 };
template < std::uint64_t BindingIDX >
using BindingSet = void;
static std::vector< vk::raii::DescriptorSetLayout > createDescriptorSets() { return {}; }
};
} // namespace fgl::engine::descriptors

View File

@@ -0,0 +1,66 @@
//
// Created by kj16609 on 10/9/24.
//
#include "DescriptorSetLayout.hpp"
#include "DescriptorSet.hpp"
#include "engine/debug/logging/logging.hpp"
namespace fgl::engine::descriptors
{
DescriptorSetLayout::DescriptorSetLayout(
const std::uint16_t set_idx, const std::vector< std::reference_wrapper< const Descriptor > >& descriptors ) :
m_set_idx( set_idx )
{
FGL_ASSERT( descriptors.size() > 0, "Must have more then 1 descriptor set" );
for ( const auto& descriptor_w : descriptors )
{
const auto& descriptor { descriptor_w.get() };
vk::DescriptorSetLayoutBinding binding {};
binding.binding = descriptor.m_index;
binding.descriptorType = descriptor.m_type;
binding.descriptorCount = descriptor.m_count;
binding.stageFlags = descriptor.m_stage_flags;
binding.pImmutableSamplers = VK_NULL_HANDLE;
bindings.emplace_back( binding );
flags.emplace_back( descriptor.m_binding_flags );
}
}
DescriptorSetLayout::DescriptorSetLayout() : m_set_idx( std::numeric_limits< std::uint16_t >::max() )
{}
std::unique_ptr< DescriptorSet > DescriptorSetLayout::create()
{
if ( !m_layout.has_value() ) m_layout = createLayout();
return std::make_unique< DescriptorSet >( *m_layout, m_set_idx );
}
vk::raii::DescriptorSetLayout DescriptorSetLayout::createLayout() const
{
vk::DescriptorSetLayoutBindingFlagsCreateInfo flags_info {};
flags_info.setBindingFlags( flags );
vk::DescriptorSetLayoutCreateInfo info {};
info.setFlags( vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool );
info.setBindings( bindings );
info.setPNext( &flags_info );
log::debug( "Created layout with as set = {} and {} bindings", m_set_idx, bindings.size() );
return Device::getInstance()->createDescriptorSetLayout( info );
}
vk::raii::DescriptorSetLayout& DescriptorSetLayout::layout()
{
if ( !m_layout.has_value() ) m_layout = createLayout();
return *m_layout;
}
} // namespace fgl::engine::descriptors

View File

@@ -5,185 +5,49 @@
#pragma once
#include "Descriptor.hpp"
#include "DescriptorPool.hpp"
#include "engine/concepts/is_descriptor.hpp"
#include "engine/concepts/is_descriptor_set.hpp"
#include "engine/concepts/is_empty_descriptor_set.hpp"
#include "engine/rendering/devices/Device.hpp"
#include "DescriptorSet.hpp"
namespace fgl::engine
{
class PipelineBuilder;
}
namespace fgl::engine::descriptors
{
class DescriptorSet;
struct Descriptor;
template < std::uint16_t set_idx, is_descriptor... Descriptors >
struct DescriptorSetLayout
class DescriptorSetLayout
{
static_assert( sizeof...( Descriptors ) > 0, "Binding set must have at least one binding" );
std::vector< vk::DescriptorSetLayoutBinding > bindings {};
std::vector< vk::DescriptorBindingFlags > flags {};
static constexpr std::uint16_t m_set_idx { set_idx };
std::optional< vk::raii::DescriptorSetLayout > m_layout { std::nullopt };
//! The number of bindings in this set
static constexpr std::uint16_t descriptor_count { sizeof...( Descriptors ) };
std::uint16_t m_set_idx;
//! Number of non-empty descriptors
static constexpr std::uint32_t used_descriptor_count { ( is_layout_descriptor< Descriptors > + ... ) };
DescriptorSetLayout(
std::uint16_t set_idx, const std::vector< std::reference_wrapper< const Descriptor > >& descriptors );
//! The max binding index in this set
static constexpr std::uint16_t max_binding_idx { getMaxDescriptorIDX< Descriptors... >() };
static_assert(
descriptor_count == max_binding_idx + 1,
"Binding count must equal max binding index. (Use EmptyDescriptor for spaces)" );
static_assert(
max_binding_idx + 1 == sizeof...( Descriptors ),
"Binding count must equal max binding index. No spaces allowed." );
template < std::uint16_t local_idx >
using Binding = std::tuple_element_t< local_idx, std::tuple< Descriptors... > >;
/**
* @tparam current_idx Current index to extract
* @tparam offset Number to subtract from the current_idx for the array. (Empty bindings are skipped and do not show up in the array)
* @return
*/
template < std::uint16_t current_idx, std::uint16_t offset >
static consteval std::array< vk::DescriptorSetLayoutBinding, used_descriptor_count > extractBinding()
{
if constexpr ( current_idx == descriptor_count )
{
std::array< vk::DescriptorSetLayoutBinding, used_descriptor_count > data {};
for ( std::uint16_t i = 0; i < used_descriptor_count; ++i )
{
data[ i ] = vk::DescriptorSetLayoutBinding(
std::numeric_limits< std::uint32_t >::max(),
vk::DescriptorType::eUniformBuffer,
1,
vk::ShaderStageFlagBits::eAll,
nullptr );
}
return data;
}
else
{
using Current = Binding< current_idx >;
if constexpr ( is_empty_descriptor< Current > )
{
return extractBinding< current_idx + 1, offset + 1 >();
}
else
{
static_assert( is_layout_descriptor< Current >, "Binding is not a layout descriptor" );
std::array< vk::DescriptorSetLayoutBinding, used_descriptor_count > data {
extractBinding< current_idx + 1, offset >()
};
data[ current_idx - offset ] = Current::m_layout_binding;
return data;
}
}
}
template < std::uint16_t current_idx, std::uint16_t offset >
static consteval std::array< vk::DescriptorBindingFlags, used_descriptor_count > extractBindingFlags()
{
if constexpr ( current_idx == descriptor_count )
{
std::array< vk::DescriptorBindingFlags, used_descriptor_count > data;
for ( std::uint16_t i = 0; i < used_descriptor_count; ++i )
{
data[ i ] = {};
}
return data;
}
else
{
using Current = Binding< current_idx >;
if constexpr ( is_empty_descriptor< Current > )
{
return extractBindingFlags< current_idx + 1, offset + 1 >();
}
else
{
static_assert( is_layout_descriptor< Current >, "Binding is not a layout descriptor" );
std::array< vk::DescriptorBindingFlags, used_descriptor_count > data {
extractBindingFlags< current_idx + 1, offset >()
};
data[ current_idx - offset ] = Current::m_binding_flags;
return data;
}
}
}
static consteval std::array< vk::DescriptorSetLayoutBinding, used_descriptor_count > getLayoutBindings()
{
return extractBinding< 0, 0 >();
}
static consteval std::array< vk::DescriptorBindingFlags, used_descriptor_count > getLayoutBindingFlags()
{
return extractBindingFlags< 0, 0 >();
}
static vk::raii::DescriptorSetLayout createDescriptorSetLayout()
{
static constinit std::array< vk::DescriptorSetLayoutBinding, used_descriptor_count > bindings {
getLayoutBindings()
};
static constinit std::array< vk::DescriptorBindingFlags, used_descriptor_count > flags {
getLayoutBindingFlags()
};
static_assert( bindings.size() == flags.size(), "Binding did not match it's flags" );
static vk::DescriptorSetLayoutBindingFlagsCreateInfo flags_info {};
flags_info.pBindingFlags = flags.data();
flags_info.bindingCount = bindings.size();
static vk::DescriptorSetLayoutCreateInfo layout_info {};
layout_info.pNext = VK_NULL_HANDLE;
layout_info.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool;
layout_info.bindingCount = static_cast< std::uint32_t >( bindings.size() );
layout_info.pBindings = bindings.data();
layout_info.pNext = &flags_info;
return Device::getInstance()->createDescriptorSetLayout( layout_info );
}
DescriptorSetLayout();
public:
DescriptorSetLayout() = delete;
//! Used to make creating an empty set VERY EXPLICIT
inline static DescriptorSetLayout createEmptySet() { return {}; }
static vk::raii::DescriptorSetLayout createLayout() { return createDescriptorSetLayout(); }
friend class ::fgl::engine::PipelineBuilder;
template < typename... Args >
DescriptorSetLayout( const std::uint16_t set_idx, const Args&... descriptors ) :
DescriptorSetLayout( set_idx, std::vector< std::reference_wrapper< const Descriptor > > { descriptors... } )
{}
std::size_t count() const { return bindings.size(); }
std::unique_ptr< DescriptorSet > create();
vk::raii::DescriptorSetLayout createLayout() const;
vk::raii::DescriptorSetLayout& layout();
};
template < std::uint16_t set_idx >
using EmptyDescriptorSet = DescriptorSetLayout< set_idx, EmptyDescriptor< 0 > >;
namespace internal
{
using TestSet = DescriptorSetLayout<
0,
ImageDescriptor< 0, vk::ShaderStageFlagBits::eAll >,
EmptyDescriptor< 1 >,
AttachmentDescriptor< 2, vk::ShaderStageFlagBits::eAll >,
UniformDescriptor< 3, vk::ShaderStageFlagBits::eAll >,
EmptyDescriptor< 4 >,
UniformDescriptor< 5, vk::ShaderStageFlagBits::eAll | vk::ShaderStageFlagBits::eVertex >,
UniformDescriptor< 6, vk::ShaderStageFlagBits::eAll > >;
static_assert( TestSet::descriptor_count == 7 );
} // namespace internal
static_assert( is_descriptor_set< EmptyDescriptorSet< 0 > > && is_empty_descriptor_set< EmptyDescriptorSet< 0 > > );
static_assert( is_descriptor_set< internal::TestSet > && !is_empty_descriptor_set< internal::TestSet > );
} // namespace fgl::engine::descriptors

View File

@@ -1,36 +0,0 @@
//
// Created by kj16609 on 3/13/24.
//
#pragma once
#include "engine/FGL_DEFINES.hpp"
#include "engine/concepts/is_valid_pipeline_input.hpp"
namespace fgl::engine::descriptors
{
template < is_valid_pipeline_input CurrentSet, is_valid_pipeline_input... Sets >
FGL_FORCE_INLINE inline void createDescriptorSetsT( std::vector< vk::raii::DescriptorSetLayout >& out )
{
if constexpr ( is_descriptor_set< CurrentSet > )
{
vk::raii::DescriptorSetLayout layout { CurrentSet::createDescriptorSetLayout() };
out.emplace_back( std::move( layout ) );
}
else if constexpr ( is_constant_range< CurrentSet > )
{
//noop
}
else
{
static_assert( false, "Invalid input" );
}
if constexpr ( sizeof...( Sets ) > 0 )
{
return createDescriptorSetsT< Sets... >( out );
}
}
} // namespace fgl::engine::descriptors

View File

@@ -4,7 +4,11 @@
#include "drawers.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <imgui.h>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -4,7 +4,11 @@
#include "ComponentEditorInterface.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <imgui.h>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -4,7 +4,11 @@
#include "GameObjectComponent.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <imgui.h>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -41,7 +41,7 @@ namespace fgl::engine
return q;
}
Rotation::Rotation( const float x, const float y, const float z ) : glm::quat( toQuat( x, y, z ) )
Rotation::Rotation( const float x_i, const float y_i, const float z_i ) : glm::quat( toQuat( x_i, y_i, z_i ) )
{}
Rotation::Rotation( const float value ) : Rotation( value, value, value )

View File

@@ -20,14 +20,14 @@ namespace fgl::engine
using glm::vec3::y;
using glm::vec3::z;
Scale( const glm::vec3 value ) : glm::vec3( value )
Scale( const glm::vec3 val ) : glm::vec3( val )
{
assert( !std::isnan( x ) );
assert( !std::isnan( y ) );
assert( !std::isnan( z ) );
}
Scale( const float value ) : glm::vec3( value ) {}
Scale( const float val ) : glm::vec3( val ) {}
Scale( const float x_i, const float y_i, const float z_i ) : glm::vec3( x_i, y_i, z_i ) {}
};

View File

@@ -42,8 +42,8 @@ namespace fgl::engine
};
OrientedBoundingBox() :
m_transform( Coordinate< CType >( constants::DEFAULT_VEC3 ) ),
transform_mode( TransformMode::Transform )
transform_mode( TransformMode::Transform ),
m_transform( Coordinate< CType >( constants::DEFAULT_VEC3 ) )
{}
OrientedBoundingBox( const Coordinate< CType > pos, const glm::vec3 inital_scale ) :
@@ -76,6 +76,7 @@ namespace fgl::engine
case TransformMode::Matrix:
return Coordinate< CType >( m_matrix * glm::vec4( -1.0f, -1.0f, -1.0f, 1.0f ) );
}
FGL_UNREACHABLE();
}
//! Returns the bottom right (x, y, z) coordinate
@@ -88,6 +89,7 @@ namespace fgl::engine
case TransformMode::Matrix:
return Coordinate< CType >( m_matrix * glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
}
FGL_UNREACHABLE();
}
// 6 sides, 2 triangles each, 3 verts per triangle

View File

@@ -39,7 +39,7 @@ namespace fgl::engine
glm::vec3( i_x, i_y, i_z )
{}
constexpr explicit Coordinate( const float value ) : glm::vec3( value ) {}
constexpr explicit Coordinate( const float val ) : glm::vec3( val ) {}
explicit Coordinate( const Vector& vector );

View File

@@ -36,7 +36,7 @@ namespace fgl::engine
constexpr Vector() : glm::vec3( constants::DEFAULT_VEC3 ) {}
constexpr explicit Vector( const float value ) : glm::vec3( value ) {}
constexpr explicit Vector( const float val ) : glm::vec3( val ) {}
constexpr explicit Vector( const glm::vec3 i_vec ) : glm::vec3( i_vec ) {}
@@ -72,7 +72,6 @@ namespace fgl::engine
{
return coord - *this;
}
};
inline Vector operator-( const Vector vec )

View File

@@ -64,7 +64,8 @@ namespace fgl::engine
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto set { std::make_unique< descriptors::DescriptorSet >( GuiInputDescriptorSet::createLayout() ) };
auto set { gui_descriptor_set.create() };
//auto set { std::make_unique< descriptors::DescriptorSet >( GuiInputDescriptorSet::createLayout() ) };
set->setMaxIDX( 0 );

View File

@@ -47,12 +47,18 @@ namespace fgl::engine
throw std::runtime_error( "drawIndirectFirstInstance not supported by device" );
}
if ( available_features.wideLines != VK_TRUE )
{
throw std::runtime_error( "wideLines not supported by device" );
}
//Set enabled features
vk::PhysicalDeviceFeatures deviceFeatures = {};
deviceFeatures.samplerAnisotropy = VK_TRUE;
deviceFeatures.multiDrawIndirect = VK_TRUE;
deviceFeatures.tessellationShader = VK_TRUE;
deviceFeatures.drawIndirectFirstInstance = VK_TRUE;
deviceFeatures.wideLines = VK_TRUE;
return deviceFeatures;
}

View File

@@ -13,7 +13,7 @@ namespace fgl::engine::internal
{
vk::raii::Pipeline Pipeline::createGraphicsPipeline(
std::vector< std::unique_ptr< ShaderHandle > >& shaders,
std::vector< std::unique_ptr< Shader > >& shaders,
const PipelineConfigInfo& info,
const vk::raii::PipelineLayout& layout )
{
@@ -66,7 +66,7 @@ namespace fgl::engine::internal
Device& device,
vk::raii::PipelineLayout layout,
PipelineConfigInfo info,
std::vector< std::unique_ptr< ShaderHandle > > shaders ) :
std::vector< std::unique_ptr< Shader > > shaders ) :
m_device( device ),
m_layout( std::move( layout ) ),
m_vk_pipeline( createGraphicsPipeline( shaders, info, m_layout ) )

View File

@@ -12,7 +12,7 @@
namespace fgl::engine
{
class Device;
struct ShaderHandle;
struct Shader;
}
namespace fgl::engine::internal
@@ -29,7 +29,7 @@ namespace fgl::engine::internal
vk::ShaderModule m_frag_shader { VK_NULL_HANDLE };
vk::raii::Pipeline createGraphicsPipeline(
std::vector< std::unique_ptr< ShaderHandle > >& shaders,
std::vector< std::unique_ptr< Shader > >& shaders,
const PipelineConfigInfo& info,
const vk::raii::PipelineLayout& layout );
@@ -39,7 +39,7 @@ namespace fgl::engine::internal
Device& device,
vk::raii::PipelineLayout layout,
PipelineConfigInfo info,
std::vector< std::unique_ptr< ShaderHandle > > shaders );
std::vector< std::unique_ptr< Shader > > shaders );
Pipeline( const Pipeline& other ) = delete;
Pipeline& operator=( const Pipeline& ) = delete;

View File

@@ -1,140 +0,0 @@
//
// Created by kj16609 on 12/7/23.
//
#pragma once
#include "Pipeline.hpp"
#include "Shader.hpp"
#include "engine/concepts/is_descriptor_set_collection.hpp"
#include "engine/concepts/is_empty_descriptor_set.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
template < is_shader_collection ShaderCollection, is_descriptor_set_collection DescriptorSetCollection >
class PipelineT : public internal::Pipeline
{
//If the first descriptor set is a constant range, then the pipeline has a constant range
constexpr static bool has_constant_range { DescriptorSetCollection::has_constant_range };
constexpr static std::uint16_t binding_sets { DescriptorSetCollection::binding_sets };
constexpr static bool has_binding_sets { binding_sets != 0 };
constexpr static std::uint16_t max_binding_set { DescriptorSetCollection::max_binding_set };
constexpr static std::uint16_t set_count { DescriptorSetCollection::set_count };
constexpr static std::uint16_t empty_sets { DescriptorSetCollection::empty_sets };
//! Returns the binding type assocaited with the index
template < std::uint16_t binding_set_idx >
using BindingSet = typename DescriptorSetCollection::template BindingSet< binding_set_idx >;
static_assert(
set_count == 0 || ( set_count == ( max_binding_set + 1 ) ),
"Binding sets must not have any spaces (Use EmptySet<idx>)" );
template < std::uint16_t idx >
consteval static std::uint16_t emptyBindingsAfterIDX()
{
if constexpr ( idx == max_binding_set )
return 0;
else
{
return ( is_empty_descriptor_set< BindingSet< idx > > ? 1 : 0 ) + emptyBindingsAfterIDX< idx + 1 >();
}
}
const vk::PushConstantRange* getRange()
{
if constexpr ( has_constant_range )
{
return &DescriptorSetCollection::template DescriptorSet< 0 >::m_range;
}
else
{
return VK_NULL_HANDLE;
}
}
template < std::uint16_t start_idx >
consteval static std::uint16_t getConcurrentSetCount()
{
if constexpr ( start_idx > max_binding_set )
return 0;
else
{
if constexpr ( !is_empty_descriptor_set< BindingSet< start_idx > > )
return 1 + getConcurrentSetCount< start_idx + 1 >();
else
return 0;
}
}
template < std::uint16_t start_idx >
static consteval std::uint16_t emptySetsBeforeIDX()
{
if constexpr ( start_idx == 0 )
return 0;
else
return emptySetsBeforeIDX< start_idx - 1 >() + is_empty_descriptor_set< BindingSet< start_idx > >;
}
vk::raii::PipelineLayout createLayout( [[maybe_unused]] Device& device )
{
const auto layouts { DescriptorSetCollection::createDescriptorSets() };
std::vector< vk::DescriptorSetLayout > vk_layouts {};
vk_layouts.reserve( layouts.size() );
for ( const vk::raii::DescriptorSetLayout& layout : layouts )
{
vk_layouts.emplace_back( *layout );
}
vk::PipelineLayoutCreateInfo pipeline_layout_info {};
pipeline_layout_info.setLayoutCount = has_binding_sets ? static_cast< uint32_t >( vk_layouts.size() ) : 0;
pipeline_layout_info.pSetLayouts = has_binding_sets ? vk_layouts.data() : VK_NULL_HANDLE;
pipeline_layout_info.pushConstantRangeCount = has_constant_range ? 1 : 0;
pipeline_layout_info.pPushConstantRanges = has_constant_range ? getRange() : VK_NULL_HANDLE;
return Device::getInstance()->createPipelineLayout( pipeline_layout_info );
}
public:
void bindDescriptor(
vk::raii::CommandBuffer& cmd_buffer, std::uint16_t set_idx, descriptors::DescriptorSet& descriptor )
{
const std::vector< vk::DescriptorSet > sets { *descriptor };
constexpr std::vector< std::uint32_t > dynamic_offsets {};
cmd_buffer.bindDescriptorSets( vk::PipelineBindPoint::eGraphics, m_layout, set_idx, sets, dynamic_offsets );
}
template < typename TPushData >
void pushConstant( vk::raii::CommandBuffer& cmd_buffer, TPushData& data )
{
if constexpr ( has_constant_range )
{
using PushConstantType = typename DescriptorSetCollection::PushConstantT;
static_assert(
std::same_as< TPushData, typename PushConstantType::DataType >,
"Push constant data type mismatch" );
PushConstantType::push( cmd_buffer, m_layout, data );
}
else
assert( "Attempted to push constant to pipeline without push constant range" );
}
PipelineT( Device& device, PipelineConfigInfo&& info ) :
Pipeline(
device,
createLayout( device ),
std::forward< PipelineConfigInfo >( info ),
ShaderCollection::loadShaders() )
{}
};
} // namespace fgl::engine

View File

@@ -11,7 +11,7 @@
namespace fgl::engine
{
std::vector< std::byte > ShaderHandle::loadData( const std::filesystem::path& path )
std::vector< std::byte > Shader::loadData( const std::filesystem::path& path )
{
if ( auto ifs = std::ifstream( path, std::ios::binary | std::ios::ate ); ifs )
{
@@ -34,7 +34,7 @@ namespace fgl::engine
}
}
vk::ShaderModuleCreateInfo ShaderHandle::createModuleInfo() const
vk::ShaderModuleCreateInfo Shader::createModuleInfo() const
{
vk::ShaderModuleCreateInfo module_info {};
module_info.flags = {};
@@ -44,7 +44,7 @@ namespace fgl::engine
return module_info;
}
ShaderHandle::ShaderHandle( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info ) :
Shader::Shader( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info ) :
shader_data( loadData( path ) ),
module_create_info( createModuleInfo() ),
stage_info( info ),
@@ -53,4 +53,20 @@ namespace fgl::engine
stage_info.module = shader_module;
}
std::shared_ptr< Shader > Shader::
loadShader( std::filesystem::path path, const vk::ShaderStageFlagBits stage_flags )
{
std::filesystem::path full_path { std::filesystem::current_path() / path };
vk::PipelineShaderStageCreateInfo stage_info {};
stage_info.stage = stage_flags;
stage_info.flags = {};
stage_info.pName = "main";
stage_info.pSpecializationInfo = VK_NULL_HANDLE;
auto shader { std::make_shared< Shader >( path, stage_info ) };
return shader;
}
} // namespace fgl::engine

View File

@@ -12,25 +12,7 @@
namespace fgl::engine
{
template < std::size_t N >
requires( N > 0 )
struct TString
{
using Character = std::string::value_type;
Character str[ N ];
constexpr TString( const char ( &literal )[ N ] ) { std::ranges::copy( literal, str ); }
consteval operator std::string_view() const noexcept { return std::string_view( str, N - 1 ); }
operator std::filesystem::path() const noexcept
{
return std::filesystem::path( std::string_view( str, N - 1 ) );
}
};
struct ShaderHandle
struct Shader
{
std::vector< std::byte > shader_data;
vk::ShaderModuleCreateInfo module_create_info;
@@ -41,89 +23,27 @@ namespace fgl::engine
static std::vector< std::byte > loadData( const std::filesystem::path& );
vk::ShaderModuleCreateInfo createModuleInfo() const;
ShaderHandle( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info );
Shader( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info );
ShaderHandle( const ShaderHandle& other ) = delete;
Shader( const Shader& other ) = delete;
ShaderHandle& operator=( const ShaderHandle& other ) = delete;
Shader& operator=( const Shader& other ) = delete;
ShaderHandle( ShaderHandle&& other ) = delete;
Shader( Shader&& other ) = delete;
ShaderHandle& operator=( ShaderHandle&& other ) = delete;
};
Shader& operator=( Shader&& other ) = delete;
vk::ShaderModule loadShaderModule( const std::string_view path );
static std::shared_ptr< Shader > loadShader( std::filesystem::path path, vk::ShaderStageFlagBits stage_flags );
template < TString filepath, vk::ShaderStageFlagBits stage_flags >
struct Shader
{
consteval static vk::PipelineShaderStageCreateInfo defaultShaderInfo()
inline static std::shared_ptr< Shader > loadVertex( std::filesystem::path path )
{
vk::PipelineShaderStageCreateInfo info {};
info.flags = {};
info.stage = stage_flags;
info.pName = "main";
info.pSpecializationInfo = nullptr;
return info;
return loadShader( path, vk::ShaderStageFlagBits::eVertex );
}
static std::unique_ptr< ShaderHandle > load()
inline static std::shared_ptr< Shader > loadFragment( std::filesystem::path path )
{
return std::make_unique< ShaderHandle >( filepath, defaultShaderInfo() );
return loadShader( path, vk::ShaderStageFlagBits::eFragment );
}
virtual ~Shader() = default;
};
template < TString filepath >
using VertexShaderT = Shader< filepath, vk::ShaderStageFlagBits::eVertex >;
template < TString filepath >
using FragmentShaderT = Shader< filepath, vk::ShaderStageFlagBits::eFragment >;
template < TString filepath >
using TesselationControlShaderT = Shader< filepath, vk::ShaderStageFlagBits::eTessellationControl >;
template < TString filepath >
using TesselationEvaluationShaderT = Shader< filepath, vk::ShaderStageFlagBits::eTessellationEvaluation >;
template < typename T >
concept is_shader = requires( T t ) {
{
t.defaultShaderInfo()
} -> std::same_as< vk::PipelineShaderStageCreateInfo >;
};
template < is_shader... Shaders >
struct ShaderCollection
{
using ShaderTuple = std::tuple< Shaders... >;
constexpr static std::uint64_t ShaderCount { sizeof...( Shaders ) };
template < std::uint64_t IDX >
requires( IDX < ShaderCount )
using Shader = std::tuple_element_t< IDX, ShaderTuple >;
static_assert( ShaderCount >= 1, "Shader count must be two, Missing vertex or fragment?" );
static std::vector< std::unique_ptr< ShaderHandle > > loadShaders()
{
std::vector< std::unique_ptr< ShaderHandle > > shaders;
( ( shaders.push_back( Shaders::load() ) ), ... );
return shaders;
}
};
template < typename T >
concept is_shader_collection = requires( T t ) {
typename T::ShaderTuple;
{
t.ShaderCount
} -> std::same_as< const std::uint64_t& >;
};
} // namespace fgl::engine

View File

@@ -0,0 +1,18 @@
//
// Created by kj16609 on 10/10/24.
//
#include "AttachmentPresets.hpp"
namespace fgl::engine::AttachmentPresets
{
void configureForPresent( AttachmentBuilder& builder )
{
}
} // namespace fgl::engine::AttachmentPresets

View File

@@ -0,0 +1,15 @@
//
// Created by kj16609 on 10/10/24.
//
namespace fgl::engine
{
class AttachmentBuilder;
}
namespace fgl::engine::AttachmentPresets
{
void configureForPresent( AttachmentBuilder& builder );
}

View File

@@ -129,9 +129,6 @@ namespace fgl::engine
const auto preprocessed_source { getInstance().PreprocessGlsl(
reinterpret_cast< const char* >( input.data() ), input.size(), kind, input_name.data(), options ) };
log::info(
"Preprocessed source:\n{}", std::string_view( preprocessed_source.begin(), preprocessed_source.end() ) );
const auto result { getInstance().CompileGlslToSpv(
reinterpret_cast< const char* >( input.data() ), input.size(), kind, input_name.data(), options ) };

View File

@@ -0,0 +1,42 @@
//
// Created by kj16609 on 10/10/24.
//
#include "AttachmentBuilder.hpp"
#include "PipelineBuilder.hpp"
namespace fgl::engine
{
AttachmentBuilder::AttachmentBuilder( PipelineBuilder& source ) : parent( source )
{
// Default
color_blend_config.blendEnable = VK_FALSE;
color_blend_config.srcColorBlendFactor = vk::BlendFactor::eOne;
color_blend_config.dstColorBlendFactor = vk::BlendFactor::eZero;
color_blend_config.colorBlendOp = vk::BlendOp::eAdd;
color_blend_config.srcAlphaBlendFactor = vk::BlendFactor::eOne;
color_blend_config.dstAlphaBlendFactor = vk::BlendFactor::eZero;
color_blend_config.alphaBlendOp = vk::BlendOp::eAdd;
color_blend_config.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG
| vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
}
AttachmentBuilder& AttachmentBuilder::enableBlend()
{
color_blend_config.blendEnable = VK_TRUE;
return *this;
}
void AttachmentBuilder::finish()
{
parent.config.color_blend_attachment.emplace_back( color_blend_config );
m_finished = true;
}
AttachmentBuilder::~AttachmentBuilder()
{
FGL_ASSERT( m_finished, "Attachemnt builder not finished!" );
}
} // namespace fgl::engine

View File

@@ -0,0 +1,32 @@
//
// Created by kj16609 on 10/10/24.
//
#include "engine/rendering/pipelines/Attachment.hpp"
namespace fgl::engine
{
class PipelineBuilder;
class AttachmentBuilder
{
PipelineBuilder& parent;
bool m_finished { false };
AttachmentBuilder( PipelineBuilder& source );
AttachmentBuilder() = delete;
friend class PipelineBuilder;
public:
vk::PipelineColorBlendAttachmentState color_blend_config {};
void finish();
AttachmentBuilder& enableBlend();
~AttachmentBuilder();
};
} // namespace fgl::engine

View File

@@ -0,0 +1,46 @@
//
// Created by kj16609 on 10/9/24.
//
#include "Pipeline.hpp"
#include "PipelineBuilder.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
Pipeline::Pipeline( vk::raii::Pipeline&& pipeline_in, vk::raii::PipelineLayout&& layout ) :
m_pipeline( std::move( pipeline_in ) ),
m_layout( std::move( layout ) )
{}
void Pipeline::bind( vk::raii::CommandBuffer& cmd_buffer )
{
cmd_buffer.bindPipeline( vk::PipelineBindPoint::eGraphics, m_pipeline );
}
void Pipeline::bindDescriptor(
vk::raii::CommandBuffer& command_buffer, std::size_t descriptor_idx, descriptors::DescriptorSet& set )
{
const std::vector< vk::DescriptorSet > sets { *set };
constexpr std::vector< std::uint32_t > offsets {};
command_buffer.bindDescriptorSets( vk::PipelineBindPoint::eGraphics, m_layout, descriptor_idx, sets, offsets );
}
void Pipeline::bindDescriptor( vk::raii::CommandBuffer& comd_buffer, descriptors::DescriptorSet& set )
{
bindDescriptor( comd_buffer, set.setIDX(), set );
}
void Pipeline::setDebugName( const char* str )
{
vk::DebugUtilsObjectNameInfoEXT info {};
info.objectType = vk::ObjectType::ePipeline;
info.pObjectName = str;
info.objectHandle = reinterpret_cast< std::uint64_t >( static_cast< VkPipeline >( *this->m_pipeline ) );
Device::getInstance().setDebugUtilsObjectName( info );
}
} // namespace fgl::engine

View File

@@ -0,0 +1,32 @@
//
// Created by kj16609 on 10/9/24.
//
#include <memory>
#include "engine/assets/model/Primitive.hpp"
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
class Pipeline
{
vk::raii::Pipeline m_pipeline;
vk::raii::PipelineLayout m_layout;
public:
Pipeline() = delete;
Pipeline( vk::raii::Pipeline&& pipeline, vk::raii::PipelineLayout&& layout );
void bind( vk::raii::CommandBuffer& );
void bindDescriptor( vk::raii::CommandBuffer&, std::size_t descriptor_idx, descriptors::DescriptorSet& set );
void bindDescriptor( vk::raii::CommandBuffer& comd_buffer, descriptors::DescriptorSet& set );
void setDebugName( const char* str );
};
} // namespace fgl::engine

View File

@@ -0,0 +1,264 @@
//
// Created by kj16609 on 10/10/24.
//
#include "PipelineBuilder.hpp"
#include "AttachmentBuilder.hpp"
#include "Pipeline.hpp"
#include "engine/descriptors/DescriptorSetLayout.hpp"
namespace fgl::engine
{
PipelineBuilder::PipelineBuilder( vk::raii::RenderPass& renderpass, std::size_t subpass_stage ) :
m_render_pass( renderpass ),
subpass_idx( subpass_stage )
{
addDynamicState( vk::DynamicState::eViewport );
addDynamicState( vk::DynamicState::eScissor );
}
descriptors::DescriptorSetLayout empty_set_layout { descriptors::DescriptorSetLayout::createEmptySet() };
vk::raii::PipelineLayout PipelineBuilder::createLayout()
{
vk::PipelineLayoutCreateInfo info {};
std::vector< vk::DescriptorSetLayout > set_layouts {};
set_layouts.reserve( descriptor_set_layouts.size() );
SetID max_set_idx { 0 };
for ( const auto& [ set_idx, _ ] : descriptor_set_layouts )
{
max_set_idx = std::max( max_set_idx, set_idx );
}
// Any sets not used, Should be set to VK_NULL_HANDLE
set_layouts.resize( max_set_idx + 1 );
for ( std::size_t i = 0; i < set_layouts.size(); ++i )
{
auto itter { descriptor_set_layouts.find( i ) };
if ( itter == descriptor_set_layouts.end() )
{
// Could not find it. Empty
set_layouts[ i ] = empty_set_layout.layout();
continue;
}
else
{
set_layouts[ i ] = itter->second;
continue;
}
}
for ( const auto& [ set_idx, layout ] : descriptor_set_layouts )
{
log::debug( "{} populated", set_idx );
set_layouts[ set_idx ] = layout;
}
info.setSetLayouts( set_layouts );
return Device::getInstance()->createPipelineLayout( info );
}
void PipelineBuilder::
addDescriptorSet( const SetID idx, const vk::raii::DescriptorSetLayout& descriptor_set_layout )
{
FGL_ASSERT( !descriptor_set_layouts.contains( idx ), "Descriptor already set!" );
log::debug( "Setting descriptor layout for set idx {}", idx );
descriptor_set_layouts.insert( std::make_pair( idx, *descriptor_set_layout ) );
}
void PipelineBuilder::addDescriptorSet( descriptors::DescriptorSetLayout& descriptor )
{
return addDescriptorSet( descriptor.m_set_idx, descriptor.layout() );
}
void PipelineBuilder::addDynamicState( vk::DynamicState dynamic_state )
{
m_dynamic_state.emplace_back( dynamic_state );
}
[[nodiscard]] vk::PipelineColorBlendAttachmentState& PipelineBuilder::Config::addColorAttachment()
{
color_blend_attachment.emplace_back();
color_blend_info.setAttachments( color_blend_attachment );
return color_blend_attachment.back();
}
PipelineBuilder::Config::Config()
{
viewport_info.viewportCount = 1;
viewport_info.pViewports = nullptr;
viewport_info.scissorCount = 1;
viewport_info.pScissors = nullptr;
assembly_info.topology = vk::PrimitiveTopology::eTriangleList;
assembly_info.primitiveRestartEnable = VK_FALSE;
rasterization_info.depthClampEnable = VK_FALSE;
rasterization_info.rasterizerDiscardEnable = VK_FALSE;
rasterization_info.polygonMode = vk::PolygonMode::eFill;
rasterization_info.cullMode = vk::CullModeFlagBits::eBack;
rasterization_info.frontFace = vk::FrontFace::eClockwise;
rasterization_info.depthBiasEnable = VK_FALSE;
rasterization_info.depthBiasConstantFactor = 0.0f;
rasterization_info.depthBiasClamp = 0.0f;
rasterization_info.depthBiasSlopeFactor = 0.0f;
rasterization_info.lineWidth = 1.0f;
multisample_info.rasterizationSamples = vk::SampleCountFlagBits::e1;
multisample_info.sampleShadingEnable = VK_FALSE;
multisample_info.minSampleShading = 1.0f;
multisample_info.pSampleMask = nullptr;
multisample_info.alphaToCoverageEnable = VK_FALSE;
multisample_info.alphaToOneEnable = VK_FALSE;
color_blend_info.logicOpEnable = VK_FALSE;
color_blend_info.logicOp = vk::LogicOp::eCopy;
color_blend_info.attachmentCount = 0;
color_blend_info.pAttachments = nullptr;
color_blend_info.blendConstants[ 0 ] = 0.0f;
color_blend_info.blendConstants[ 1 ] = 0.0f;
color_blend_info.blendConstants[ 2 ] = 0.0f;
color_blend_info.blendConstants[ 3 ] = 0.0f;
depth_stencil_info.depthTestEnable = VK_TRUE;
depth_stencil_info.depthWriteEnable = VK_TRUE;
depth_stencil_info.depthCompareOp = vk::CompareOp::eLess;
depth_stencil_info.depthBoundsTestEnable = VK_FALSE;
depth_stencil_info.stencilTestEnable = VK_FALSE;
//depth_stencil_info.front = {};
//depth_stencil_info.back = {};
depth_stencil_info.minDepthBounds = 0.0f;
depth_stencil_info.maxDepthBounds = 1.0f;
dynamic_state_enables = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
dynamic_state_info.setDynamicStates( dynamic_state_enables );
//info.dynamic_state_info.flags = 0;
}
void PipelineBuilder::setTopology( vk::PrimitiveTopology primitive_topology )
{
config.assembly_info.topology = primitive_topology;
}
void PipelineBuilder::disableVertexInput()
{
vertex_input_descriptions.bindings = {};
vertex_input_descriptions.attributes = {};
}
void PipelineBuilder::disableCulling()
{
config.rasterization_info.cullMode = vk::CullModeFlagBits::eNone;
}
AttachmentBuilder PipelineBuilder::addAttachment()
{
return { *this };
}
AttachmentBuilder PipelineBuilder::addColorAttachment()
{
AttachmentBuilder builder { addAttachment() };
return builder;
}
void PipelineBuilder::setBindingDescriptions( const std::vector< vk::VertexInputBindingDescription >& descriptions )
{
vertex_input_descriptions.bindings = descriptions;
}
void PipelineBuilder::setAttributeDescriptions( const std::vector< vk::VertexInputAttributeDescription >&
descriptions )
{
vertex_input_descriptions.attributes = descriptions;
}
std::unique_ptr< Pipeline > PipelineBuilder::create()
{
// Precheck
{
FGL_ASSERT( shaders.fragment, "Pipeline requires fragment shader" );
FGL_ASSERT( shaders.vertex, "Pipeline requires vertex shader" );
}
vk::raii::PipelineLayout layout { createLayout() };
vk::GraphicsPipelineCreateInfo info {};
info.pNext = VK_NULL_HANDLE;
info.flags = {};
m_stages.clear();
if ( shaders.vertex ) m_stages.emplace_back( shaders.vertex->stage_info );
if ( shaders.fragment ) m_stages.emplace_back( shaders.fragment->stage_info );
info.setStages( m_stages );
vk::PipelineVertexInputStateCreateInfo vertex_input_info {};
vertex_input_info.pNext = VK_NULL_HANDLE;
vertex_input_info.flags = {};
vertex_input_info.setVertexBindingDescriptions( vertex_input_descriptions.bindings );
vertex_input_info.setVertexAttributeDescriptions( vertex_input_descriptions.attributes );
info.setPVertexInputState( &vertex_input_info );
info.pInputAssemblyState = &config.assembly_info;
info.pTessellationState = &config.tesselation_state_info;
info.pViewportState = &config.viewport_info;
info.pRasterizationState = &config.rasterization_info;
info.pMultisampleState = &config.multisample_info;
info.pDepthStencilState = &config.depth_stencil_info;
config.color_blend_info.setAttachments( config.color_blend_attachment );
info.pColorBlendState = &config.color_blend_info;
info.pDynamicState = &config.dynamic_state_info;
info.layout = layout;
info.renderPass = m_render_pass;
info.subpass = subpass_idx;
//TODO: Figure out what these do
info.basePipelineHandle = VK_NULL_HANDLE;
info.basePipelineIndex = -1;
vk::PipelineDynamicStateCreateInfo dynamic_state_create_info {};
dynamic_state_create_info.setDynamicStates( m_dynamic_state );
if ( m_dynamic_state.size() > 0 ) info.setPDynamicState( &dynamic_state_create_info );
vk::raii::Pipeline pipeline { Device::getInstance()->createGraphicsPipeline( VK_NULL_HANDLE, info ) };
return std::make_unique< Pipeline >( std::move( pipeline ), std::move( layout ) );
}
void setGBufferOutputAttachments( PipelineBuilder::Config& config )
{
// In order for the pipeline to output, We need to ensure that we have enough attachments for the entire gbuffer (3)
FGL_ASSERT( config.color_blend_attachment.size() == 0, "GBuffer output expected there to be no other outputs" );
for ( int i = 0; i < 3; ++i )
{
auto& color_config { config.addColorAttachment() };
color_config.blendEnable = VK_FALSE;
color_config.srcColorBlendFactor = vk::BlendFactor::eOne;
color_config.dstColorBlendFactor = vk::BlendFactor::eZero;
color_config.colorBlendOp = vk::BlendOp::eAdd;
color_config.srcAlphaBlendFactor = vk::BlendFactor::eOne;
color_config.dstAlphaBlendFactor = vk::BlendFactor::eZero;
color_config.alphaBlendOp = vk::BlendOp::eAdd;
color_config.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG
| vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
}
}
} // namespace fgl::engine

View File

@@ -0,0 +1,111 @@
//
// Created by kj16609 on 10/10/24.
//
#include <vulkan/vulkan_raii.hpp>
#include <cstdint>
#include <unordered_map>
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
namespace descriptors
{
class DescriptorSetLayout;
class DescriptorSetCollection;
} // namespace descriptors
class AttachmentBuilder;
class Pipeline;
class PipelineBuilder
{
vk::raii::RenderPass& m_render_pass;
std::size_t subpass_idx;
struct
{
std::vector< vk::VertexInputBindingDescription > bindings;
std::vector< vk::VertexInputAttributeDescription > attributes;
} vertex_input_descriptions;
struct
{
std::shared_ptr< Shader > vertex { nullptr };
std::shared_ptr< Shader > fragment { nullptr };
} shaders {};
std::vector< vk::PipelineShaderStageCreateInfo > m_stages {};
std::vector< vk::DynamicState > m_dynamic_state {};
using SetID = std::uint32_t;
std::unordered_map< SetID, vk::DescriptorSetLayout > descriptor_set_layouts {};
vk::raii::PipelineLayout createLayout();
public:
void addDescriptorSet( SetID idx, const vk::raii::DescriptorSetLayout& descriptor_set_layout );
void addDescriptorSet( descriptors::DescriptorSetLayout& descriptor );
void addDynamicState( vk::DynamicState dynamic_state );
PipelineBuilder() = delete;
struct Config
{
vk::PipelineViewportStateCreateInfo viewport_info {};
vk::PipelineInputAssemblyStateCreateInfo assembly_info {};
vk::PipelineTessellationStateCreateInfo tesselation_state_info {};
vk::PipelineTessellationDomainOriginStateCreateInfo tesselation_domain_info {};
vk::PipelineRasterizationStateCreateInfo rasterization_info {};
vk::PipelineMultisampleStateCreateInfo multisample_info {};
std::vector< vk::PipelineColorBlendAttachmentState > color_blend_attachment {};
vk::PipelineColorBlendAttachmentState& addColorAttachment();
vk::PipelineColorBlendStateCreateInfo color_blend_info {};
vk::PipelineDepthStencilStateCreateInfo depth_stencil_info {};
std::vector< vk::DynamicState > dynamic_state_enables {};
vk::PipelineDynamicStateCreateInfo dynamic_state_info {};
// Default config
Config();
} config;
void setTopology( vk::PrimitiveTopology primitive_topology );
void disableVertexInput();
void disableCulling();
[[nodiscard]] AttachmentBuilder addAttachment();
[[nodiscard]] AttachmentBuilder addColorAttachment();
vk::PipelineLayoutCreateInfo layout_info {};
void setBindingDescriptions( const std::vector< vk::VertexInputBindingDescription >& descriptions );
void setAttributeDescriptions( const std::vector< vk::VertexInputAttributeDescription >& descriptions );
PipelineBuilder( vk::raii::RenderPass& renderpass, std::size_t subpass_stage );
void setVertexShader( std::shared_ptr< Shader >&& shader )
{
shaders.vertex = std::forward< std::shared_ptr< Shader > >( shader );
}
void setFragmentShader( std::shared_ptr< Shader >&& shader )
{
shaders.fragment = std::forward< std::shared_ptr< Shader > >( shader );
}
std::unique_ptr< Pipeline > create();
};
//! Adds the GBuffer output attachments to the config for the given pipeline
void setGBufferOutputAttachments( PipelineBuilder::Config& config );
} // namespace fgl::engine

View File

@@ -6,19 +6,42 @@
#include <engine/texture/Texture.hpp>
#include "engine/rendering/pipelines/attachments/AttachmentPresets.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
namespace fgl::engine
{
CompositionSystem::CompositionSystem( [[maybe_unused]] Device& device, vk::raii::RenderPass& render_pass )
{
/*
PipelineConfigInfo composition_info { render_pass };
PipelineConfigInfo::addColorAttachmentConfig( composition_info );
PipelineConfigInfo::disableVertexInput( composition_info );
PipelineConfigInfo::disableCulling( composition_info );
composition_info.subpass = 1;
*/
constexpr std::size_t SUBPASS { 1 };
PipelineBuilder builder { render_pass, SUBPASS };
FGL_ASSERT( gbuffer_set.count() == 3, "Aaaa" );
builder.addDescriptorSet( gbuffer_set );
builder.addColorAttachment().finish();
builder.setVertexShader( Shader::loadVertex( "shaders/fullscreen.vert" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/composition.frag" ) );
builder.disableCulling();
builder.disableVertexInput();
m_composite_pipeline = builder.create();
m_composite_pipeline =
std::make_unique< CompositionPipeline >( Device::getInstance(), std::move( composition_info ) );
m_composite_pipeline->setDebugName( "Composition pipeline" );
}
@@ -30,8 +53,7 @@ namespace fgl::engine
m_composite_pipeline->bind( command_buffer );
m_composite_pipeline
->bindDescriptor( command_buffer, GBufferDescriptorSet::m_set_idx, info.getGBufferDescriptor() );
m_composite_pipeline->bindDescriptor( command_buffer, info.getGBufferDescriptor() );
return info.command_buffer;
}

View File

@@ -6,25 +6,16 @@
#include "concepts.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
class Pipeline;
class CompositionSystem
{
using DescriptorSets = descriptors::DescriptorSetCollection< GBufferDescriptorSet >;
using VertexShader = VertexShaderT< "shaders/fullscreen.vert" >;
using FragmentShader = FragmentShaderT< "shaders/composition.frag" >;
using Shaders = ShaderCollection< VertexShader, FragmentShader >;
using CompositionPipeline = PipelineT< Shaders, DescriptorSets >;
std::unique_ptr< CompositionPipeline > m_composite_pipeline { nullptr };
std::unique_ptr< Pipeline > m_composite_pipeline { nullptr };
vk::raii::CommandBuffer& setupSystem( FrameInfo& info );

View File

@@ -10,6 +10,9 @@
#include "DrawPair.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/debug/profiling/counters.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
#include "engine/tree/octtree/OctTreeNode.hpp"
namespace fgl::engine
@@ -17,25 +20,57 @@ namespace fgl::engine
EntityRendererSystem::EntityRendererSystem( Device& device, vk::raii::RenderPass& render_pass ) : m_device( device )
{
ZoneScoped;
{
PipelineConfigInfo standard_info { render_pass };
PipelineConfigInfo::addGBufferAttachmentsConfig( standard_info );
standard_info.subpass = 0;
m_standard_pipeline = std::make_unique< StandardPipeline >( m_device, std::move( standard_info ) );
{
// PipelineConfigInfo standard_info { render_pass };
// PipelineConfigInfo::addGBufferAttachmentsConfig( standard_info );
PipelineBuilder builder { render_pass, 0 };
builder.addDescriptorSet( camera_descriptor_set );
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.setFragmentShader( Shader::loadFragment( "shaders/textureless-gbuffer.frag" ) );
builder.setVertexShader( Shader::loadVertex( "shaders/textureless-gbuffer.vert" ) );
builder.setAttributeDescriptions( ModelVertex::getAttributeDescriptions() );
builder.setBindingDescriptions( ModelVertex::getBindingDescriptions() );
m_standard_pipeline = builder.create();
m_standard_pipeline->setDebugName( "Standard entity pipeline" );
}
{
PipelineConfigInfo textured_info { render_pass };
PipelineConfigInfo::addGBufferAttachmentsConfig( textured_info );
// PipelineConfigInfo textured_info { render_pass };
// PipelineConfigInfo::addGBufferAttachmentsConfig( textured_info );
textured_info.subpass = 0;
m_textured_pipeline = std::make_unique< TexturedPipeline >( m_device, std::move( textured_info ) );
PipelineBuilder builder { render_pass, 0 };
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.addDescriptorSet( camera_descriptor_set );
builder.addDescriptorSet( texture_descriptor_set );
builder.setFragmentShader( Shader::loadFragment( "shaders/textured-gbuffer.frag" ) );
builder.setVertexShader( Shader::loadVertex( "shaders/textured-gbuffer.vert" ) );
builder.setAttributeDescriptions( ModelVertex::getAttributeDescriptions() );
builder.setBindingDescriptions( ModelVertex::getBindingDescriptions() );
m_textured_pipeline = builder.create();
m_textured_pipeline->setDebugName( "Textured entity pipeline" );
}
}
EntityRendererSystem::~EntityRendererSystem()
{}
vk::raii::CommandBuffer& EntityRendererSystem::setupSystem( const FrameInfo& info )
{
auto& command_buffer { info.command_buffer };
@@ -70,8 +105,7 @@ namespace fgl::engine
//Bind pipeline
m_standard_pipeline->bind( command_buffer );
m_standard_pipeline
->bindDescriptor( command_buffer, CameraDescriptorSet::m_set_idx, info.getCameraDescriptor() );
m_standard_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() );
//Get all commands for drawing anything without a texture
auto [ draw_commands, model_matricies ] = getDrawCallsFromTree(
@@ -116,8 +150,8 @@ namespace fgl::engine
// m_textured_pipeline
// ->bindDescriptor( command_buffer, CameraDescriptorSet::m_set_idx, info.global_descriptor_set );
m_textured_pipeline
->bindDescriptor( command_buffer, TextureDescriptorSet::m_set_idx, Texture::getTextureDescriptorSet() );
m_standard_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() );
m_textured_pipeline->bindDescriptor( command_buffer, Texture::getTextureDescriptorSet() );
auto [ draw_commands, model_matricies ] =
getDrawCallsFromTree( info.game_objects, info.camera->getFrustumBounds(), IS_VISIBLE | IS_ENTITY );

View File

@@ -9,12 +9,12 @@
#include "engine/assets/model/Model.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/systems/modelRendering/StandardPipeline.hpp"
#include "engine/systems/modelRendering/TexturedPipeline.hpp"
namespace fgl::engine
{
class Pipeline;
class Device;
namespace memory
@@ -29,10 +29,10 @@ namespace fgl::engine
Device& m_device;
//! Standard pipeline for textureless models
std::unique_ptr< StandardPipeline > m_standard_pipeline {};
std::unique_ptr< Pipeline > m_standard_pipeline {};
//! Pipeline for basic textured models (Single texture)
std::unique_ptr< TexturedPipeline > m_textured_pipeline {};
std::unique_ptr< Pipeline > m_textured_pipeline {};
using DrawParameterBufferSuballocation = HostVector< vk::DrawIndexedIndirectCommand >;
@@ -55,7 +55,7 @@ namespace fgl::engine
void texturedPass( const FrameInfo& info );
EntityRendererSystem( Device& device, vk::raii::RenderPass& render_pass );
~EntityRendererSystem() = default;
~EntityRendererSystem();
EntityRendererSystem( EntityRendererSystem&& other ) = delete;
EntityRendererSystem( const EntityRendererSystem& other ) = delete;
EntityRendererSystem& operator=( const EntityRendererSystem& other ) = delete;

View File

@@ -5,6 +5,9 @@
#include "GuiSystem.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
namespace fgl::engine
{
@@ -17,7 +20,21 @@ namespace fgl::engine
PipelineConfigInfo::disableCulling( info );
info.subpass = 0;
m_pipeline = std::make_unique< Pipeline >( device, std::move( info ) );
//descriptors::DescriptorSetCollection descriptors { gui_descriptor_set };
PipelineBuilder builder { render_pass, 0 };
builder.addDescriptorSet( gui_descriptor_set );
builder.setAttributeDescriptions( SimpleVertex::getAttributeDescriptions() );
builder.setBindingDescriptions( SimpleVertex::getBindingDescriptions() );
builder.setVertexShader( Shader::loadVertex( "shaders/fullscreen.vert" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/gui-compose.frag" ) );
builder.addColorAttachment().finish();
m_pipeline = builder.create();
m_pipeline->setDebugName( "Gui Pipeline" );
}

View File

@@ -4,13 +4,12 @@
#pragma once
#include "engine/FrameInfo.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/descriptors/DescriptorSetLayout.hpp"
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
class Pipeline;
struct FrameInfo;
/**
@@ -18,16 +17,8 @@ namespace fgl::engine
*/
class GuiSystem
{
// Attachment 0 will be the composited image
using CompositeDescriptorSets = descriptors::DescriptorSetCollection< GuiInputDescriptorSet >;
using VertexShader = VertexShaderT< "shaders/fullscreen.vert" >;
using FragmentShader = FragmentShaderT< "shaders/gui-compose.frag" >;
using Shaders = ShaderCollection< VertexShader, FragmentShader >;
using Pipeline = PipelineT< Shaders, CompositeDescriptorSets >;
std::unique_ptr< Pipeline > m_pipeline { nullptr };
std::unique_ptr< Pipeline > m_pipeline;
//Setup isn't needed for this. So we can just never define this safely.
[[maybe_unused]] vk::raii::CommandBuffer& setupSystem( FrameInfo& info );

View File

@@ -11,6 +11,8 @@
#include "engine/debug/drawers.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/primitives/points/Coordinate.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
namespace fgl::engine
{
@@ -25,13 +27,25 @@ namespace fgl::engine
LineDrawer::LineDrawer( Device& device, vk::raii::RenderPass& render_pass )
{
PipelineConfigInfo config { render_pass };
PipelineBuilder builder { render_pass, 0 };
PipelineConfigInfo::addGBufferAttachmentsConfig( config );
PipelineConfigInfo::setVertexInputType( config, Simple );
PipelineConfigInfo::setLineTopo( config );
builder.addDescriptorSet( camera_descriptor_set );
m_pipeline = std::make_unique< LinePipeline >( device, std::move( config ) );
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.addColorAttachment().finish();
builder.setAttributeDescriptions( SimpleVertex::getAttributeDescriptions() );
builder.setBindingDescriptions( SimpleVertex::getBindingDescriptions() );
builder.setTopology( vk::PrimitiveTopology::eLineList );
builder.setVertexShader( Shader::loadVertex( "shaders/line.vert" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/line.frag" ) );
builder.addDynamicState( vk::DynamicState::eLineWidth );
m_pipeline = builder.create();
}
LineDrawer::~LineDrawer()
@@ -42,7 +56,7 @@ namespace fgl::engine
auto& command_buffer { info.command_buffer };
m_pipeline->bind( command_buffer );
m_pipeline->bindDescriptor( command_buffer, CameraDescriptorSet::m_set_idx, info.getCameraDescriptor() );
m_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() );
return command_buffer;
}

View File

@@ -3,12 +3,11 @@
//
#pragma once
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/camera/CameraDescriptor.hpp"
#include "engine/descriptors/Descriptor.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
namespace fgl::engine
{
@@ -18,6 +17,8 @@ namespace fgl::engine
class LineDrawer
{
/*
using VertexShader = VertexShaderT< "shaders/line.vert" >;
using FragmentShader = FragmentShaderT< "shaders/line.frag" >;
@@ -25,7 +26,10 @@ namespace fgl::engine
ShaderCollection< VertexShader, FragmentShader >,
descriptors::DescriptorSetCollection< descriptors::EmptyDescriptorSet< 0 >, CameraDescriptorSet > >;
std::unique_ptr< LinePipeline > m_pipeline {};
*/
std::unique_ptr< Pipeline > m_pipeline {};
PerFrameArray< std::unique_ptr< HostVector< VertexLine > > > m_line_vertex_buffer {};

View File

@@ -4,12 +4,10 @@
#pragma once
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "concepts.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/assets/model/Model.hpp"
#include "engine/rendering/SwapChain.hpp"

View File

@@ -5,13 +5,12 @@
#pragma once
#include "engine/FrameInfo.hpp"
#include "engine/camera/CameraDescriptor.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
/*
using StandardPipelineVertexShader = VertexShaderT< "shaders/textureless-gbuffer.vert" >;
using StandardPipelineFragShader = FragmentShaderT< "shaders/textureless-gbuffer.frag" >;
using StandardPipelineShaders = ShaderCollection< StandardPipelineVertexShader, StandardPipelineFragShader >;
@@ -22,5 +21,6 @@ namespace fgl::engine
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
using StandardPipeline = PipelineT< StandardPipelineShaders, StandardPipelineDescriptorSets >;
*/
} // namespace fgl::engine

View File

@@ -4,13 +4,12 @@
#pragma once
#include "engine/FrameInfo.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/rendering/pipelines/PipelineT.hpp"
#include "engine/rendering/pipelines/Shader.hpp"
namespace fgl::engine
{
/*
using TexturedPipelineVertexShader = VertexShaderT< "shaders/textured-gbuffer.vert" >;
using TexturedPipelineFragShader = FragmentShaderT< "shaders/textured-gbuffer.frag" >;
using TexturedPipelineShaders = ShaderCollection< TexturedPipelineVertexShader, TexturedPipelineFragShader >;
@@ -22,5 +21,6 @@ namespace fgl::engine
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
using TexturedPipeline = PipelineT< TexturedPipelineShaders, TexturedPipelineDescriptorSets >;
*/
} // namespace fgl::engine

View File

@@ -7,11 +7,11 @@
#include <initializer_list>
#include "engine/FrameInfo.hpp"
#include "engine/assets/transfer/TransferManager.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/assets/image/Image.hpp"
#include "engine/assets/image/ImageView.hpp"
#include "engine/assets/transfer/TransferManager.hpp"
#include "engine/debug/logging/logging.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/math/noise/perlin/generator.hpp"
#pragma GCC diagnostic push
@@ -90,7 +90,7 @@ namespace fgl::engine
const ImVec2 imgui_size { static_cast< float >( extent.width ), static_cast< float >( extent.height ) };
ImGui::Image( static_cast< ImTextureID >( getImGuiDescriptorSet() ), imgui_size );
ImGui::Image( getImGuiDescriptorSet(), imgui_size );
}
bool Texture::drawImGuiButton( vk::Extent2D extent )
@@ -113,7 +113,7 @@ namespace fgl::engine
const ImVec2 imgui_size { static_cast< float >( extent.width ), static_cast< float >( extent.height ) };
return ImGui::ImageButton( static_cast< ImTextureID >( getImGuiDescriptorSet() ), imgui_size );
return ImGui::ImageButton( m_name.c_str(), getImGuiDescriptorSet(), imgui_size );
}
Texture::Texture( std::tuple< std::vector< std::byte >, int, int, vk::Format > tuple ) :
@@ -230,23 +230,19 @@ namespace fgl::engine
void Texture::setName( const std::string& str )
{
this->getImageView().setName( str );
m_image->setName( str + " Image" );
m_image_view->setName( str + " ImageView" );
}
descriptors::DescriptorSet& Texture::getTextureDescriptorSet()
{
static std::unique_ptr< descriptors::DescriptorSet > set { nullptr };
static std::optional< vk::raii::DescriptorSetLayout > set_layout { std::nullopt };
if ( set )
return *set;
else
{
set_layout = TextureDescriptorSet::createLayout();
if ( !set_layout.has_value() ) throw std::runtime_error( "No set layout made" );
set = std::make_unique< descriptors::DescriptorSet >( std::move( set_layout.value() ) );
set = texture_descriptor_set.create();
set->setMaxIDX( 1 );
set->setName( "Texture descriptor set" );
return *set;

View File

@@ -11,8 +11,8 @@
#include "engine/assets/AssetManager.hpp"
#include "engine/assets/image/ImageView.hpp"
#include "engine/assets/image/Sampler.hpp"
#include "engine/types.hpp"
#include "engine/constants.hpp"
#include "engine/types.hpp"
namespace fgl::engine
{
@@ -37,8 +37,6 @@ namespace fgl::engine
using TextureStore = AssetStore< Texture >;
//TODO: Implement texture handle map to avoid loading the same texture multiple times
class Texture final : public AssetInterface< Texture >
{
@@ -61,6 +59,8 @@ namespace fgl::engine
//! Descriptor set used for displaying the texture in ImGui
vk::DescriptorSet m_imgui_set { VK_NULL_HANDLE };
std::string m_name;
[[nodiscard]] Texture( std::tuple< std::vector< std::byte >, int, int, vk::Format > );
//! Construct texture with a specific extent and data
@@ -101,6 +101,8 @@ namespace fgl::engine
[[nodiscard]] TextureID getID() const;
void setName( const std::string& str );
const std::string& getName() const { return m_name; }
[[nodiscard]] vk::DescriptorImageInfo getDescriptor() const;
[[nodiscard]] vk::DescriptorSet& getImGuiDescriptorSet();