647 lines
20 KiB
C++
647 lines
20 KiB
C++
// =============================================
|
|
// Aster: device.h
|
|
// Copyright (c) 2020-2025 Anish Bhobe
|
|
// =============================================
|
|
|
|
#pragma once
|
|
|
|
#include "context.h"
|
|
#include "pipeline_helpers.h"
|
|
#include "resource.h"
|
|
|
|
#include "aster/aster.h"
|
|
#include "aster/core/buffer.h"
|
|
#include "aster/core/device.h"
|
|
#include "aster/core/image.h"
|
|
#include "aster/core/image_view.h"
|
|
#include "aster/core/instance.h"
|
|
#include "aster/core/physical_device.h"
|
|
#include "aster/core/pipeline.h"
|
|
#include "aster/core/sampler.h"
|
|
#include "aster/core/size.h"
|
|
#include "aster/core/swapchain.h"
|
|
|
|
#include <EASTL/hash_map.h>
|
|
#include <EASTL/optional.h>
|
|
#include <EASTL/variant.h>
|
|
|
|
#include <slang-com-ptr.h>
|
|
#include <slang.h>
|
|
|
|
constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3;
|
|
|
|
struct Window;
|
|
|
|
template <>
|
|
struct eastl::hash<vk::SamplerCreateInfo>
|
|
{
|
|
usize
|
|
operator()(vk::SamplerCreateInfo const &createInfo) const noexcept
|
|
{
|
|
usize hash = HashAny(createInfo.flags);
|
|
hash = HashCombine(hash, HashAny(createInfo.magFilter));
|
|
hash = HashCombine(hash, HashAny(createInfo.minFilter));
|
|
hash = HashCombine(hash, HashAny(createInfo.mipmapMode));
|
|
hash = HashCombine(hash, HashAny(createInfo.addressModeU));
|
|
hash = HashCombine(hash, HashAny(createInfo.addressModeV));
|
|
hash = HashCombine(hash, HashAny(createInfo.addressModeW));
|
|
hash = HashCombine(hash, HashAny(static_cast<usize>(createInfo.mipLodBias * 1000))); // Resolution of 10^-3
|
|
hash = HashCombine(hash, HashAny(createInfo.anisotropyEnable));
|
|
hash = HashCombine(
|
|
hash,
|
|
HashAny(static_cast<usize>(createInfo.maxAnisotropy * 0x20))); // 32:1 Anisotropy is enough resolution
|
|
hash = HashCombine(hash, HashAny(createInfo.compareEnable));
|
|
hash = HashCombine(hash, HashAny(createInfo.compareOp));
|
|
hash = HashCombine(hash, HashAny(static_cast<usize>(createInfo.minLod * 1000))); // 0.001 resolution is enough.
|
|
hash = HashCombine(
|
|
hash,
|
|
HashAny(static_cast<usize>(createInfo.maxLod * 1000))); // 0.001 resolution is enough. (1 == NO Clamp)
|
|
hash = HashCombine(hash, HashAny(createInfo.borderColor));
|
|
hash = HashCombine(hash, HashAny(createInfo.unnormalizedCoordinates));
|
|
|
|
return hash;
|
|
}
|
|
};
|
|
|
|
namespace systems
|
|
{
|
|
|
|
// ====================================================================================================
|
|
#pragma region Creation Structs
|
|
// ====================================================================================================
|
|
|
|
// ----------------------------------------------------------------------------------------------------
|
|
#pragma region Image
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
struct Texture2DCreateInfo
|
|
{
|
|
vk::Format m_Format = vk::Format::eUndefined;
|
|
vk::Extent2D m_Extent = {};
|
|
cstr m_Name = nullptr;
|
|
bool m_IsSampled = true;
|
|
bool m_IsMipMapped = false;
|
|
bool m_IsStorage = false;
|
|
};
|
|
|
|
struct TextureCubeCreateInfo
|
|
{
|
|
vk::Format m_Format = vk::Format::eUndefined;
|
|
u32 m_Side = 0;
|
|
cstr m_Name = nullptr;
|
|
bool m_IsSampled = true;
|
|
bool m_IsMipMapped = false;
|
|
bool m_IsStorage = false;
|
|
};
|
|
|
|
struct AttachmentCreateInfo
|
|
{
|
|
vk::Format m_Format = vk::Format::eUndefined;
|
|
vk::Extent2D m_Extent = {};
|
|
cstr m_Name = nullptr;
|
|
};
|
|
|
|
struct DepthStencilImageCreateInfo
|
|
{
|
|
vk::Extent2D m_Extent = {};
|
|
cstr m_Name = nullptr;
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
// ----------------------------------------------------------------------------------------------------
|
|
#pragma region View
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
template <concepts::AnyImage TImage>
|
|
struct ViewCreateInfo
|
|
{
|
|
using ImageType = TImage;
|
|
|
|
Ref<ImageType> m_Image;
|
|
cstr m_Name;
|
|
vk::ImageViewType m_ViewType = vk::ImageViewType::e2D;
|
|
vk::ComponentMapping m_Components = {};
|
|
vk::ImageAspectFlags m_AspectMask = {};
|
|
eastl::optional<u8> m_MipLevelCount = eastl::nullopt;
|
|
eastl::optional<u8> m_LayerCount = eastl::nullopt;
|
|
u8 m_BaseMipLevel = 0;
|
|
u8 m_BaseLayer = 0;
|
|
|
|
[[nodiscard]] u8
|
|
GetMipLevelCount() const
|
|
{
|
|
return m_MipLevelCount.value_or(m_Image->m_MipLevels - m_BaseMipLevel);
|
|
}
|
|
|
|
[[nodiscard]] u8
|
|
GetLayerCount() const
|
|
{
|
|
return m_LayerCount.value_or(m_Image->m_LayerCount - m_BaseLayer);
|
|
}
|
|
|
|
explicit
|
|
operator vk::ImageViewCreateInfo() const
|
|
{
|
|
return {
|
|
.image = m_Image->m_Image,
|
|
.viewType = m_ViewType,
|
|
.format = m_Image->m_Format,
|
|
.components = m_Components,
|
|
.subresourceRange =
|
|
{
|
|
.aspectMask = m_AspectMask,
|
|
.baseMipLevel = m_BaseMipLevel,
|
|
.levelCount = GetMipLevelCount(),
|
|
.baseArrayLayer = m_BaseLayer,
|
|
.layerCount = GetLayerCount(),
|
|
},
|
|
};
|
|
}
|
|
|
|
explicit
|
|
operator ViewCreateInfo<Image>() const
|
|
{
|
|
return {
|
|
.m_Image = CastImage<Image>(m_Image),
|
|
.m_Name = m_Name,
|
|
.m_ViewType = m_ViewType,
|
|
.m_Components = m_Components,
|
|
.m_AspectMask = m_AspectMask,
|
|
.m_MipLevelCount = m_MipLevelCount,
|
|
.m_LayerCount = m_LayerCount,
|
|
.m_BaseMipLevel = m_BaseMipLevel,
|
|
.m_BaseLayer = m_BaseLayer,
|
|
};
|
|
}
|
|
};
|
|
#pragma endregion
|
|
|
|
// ----------------------------------------------------------------------------------------------------
|
|
#pragma region Sampler
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
struct SamplerCreateInfo
|
|
{
|
|
cstr m_Name = nullptr;
|
|
vk::SamplerCreateFlags m_Flags = {};
|
|
vk::Filter m_MagFilter = vk::Filter::eLinear;
|
|
vk::Filter m_MinFilter = vk::Filter::eLinear;
|
|
vk::SamplerMipmapMode m_MipmapMode = vk::SamplerMipmapMode::eLinear;
|
|
vk::SamplerAddressMode m_AddressModeU = vk::SamplerAddressMode::eRepeat;
|
|
vk::SamplerAddressMode m_AddressModeV = vk::SamplerAddressMode::eRepeat;
|
|
vk::SamplerAddressMode m_AddressModeW = vk::SamplerAddressMode::eRepeat;
|
|
vk::BorderColor m_BorderColor = vk::BorderColor::eFloatOpaqueBlack;
|
|
vk::CompareOp m_CompareOp = vk::CompareOp::eNever;
|
|
f32 m_MipLodBias = 0.0f;
|
|
f32 m_MaxAnisotropy = 16.0f;
|
|
f32 m_MinLod = 0;
|
|
f32 m_MaxLod = VK_LOD_CLAMP_NONE;
|
|
bool m_AnisotropyEnable = true;
|
|
bool m_CompareEnable = false;
|
|
bool m_NormalizedCoordinates = true;
|
|
|
|
explicit
|
|
operator vk::SamplerCreateInfo() const
|
|
{
|
|
return {
|
|
.flags = m_Flags,
|
|
.magFilter = m_MagFilter,
|
|
.minFilter = m_MinFilter,
|
|
.mipmapMode = m_MipmapMode,
|
|
.addressModeU = m_AddressModeU,
|
|
.addressModeV = m_AddressModeV,
|
|
.addressModeW = m_AddressModeW,
|
|
.mipLodBias = m_MipLodBias,
|
|
.anisotropyEnable = m_AnisotropyEnable,
|
|
.maxAnisotropy = m_MaxAnisotropy,
|
|
.compareEnable = m_CompareEnable,
|
|
.compareOp = m_CompareOp,
|
|
.minLod = m_MinLod,
|
|
.maxLod = m_MaxLod,
|
|
.borderColor = m_BorderColor,
|
|
.unnormalizedCoordinates = !m_NormalizedCoordinates,
|
|
};
|
|
}
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
// ----------------------------------------------------------------------------------------------------
|
|
#pragma region Pipeline
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
struct AttributeInfo
|
|
{
|
|
u32 m_Location;
|
|
u32 m_Offset;
|
|
|
|
enum class Format
|
|
{
|
|
eFloat32X4,
|
|
eFloat32X3,
|
|
eFloat32X2,
|
|
eFloat32,
|
|
} m_Format;
|
|
|
|
[[nodiscard]] vk::Format
|
|
GetFormat() const
|
|
{
|
|
switch (m_Format)
|
|
{
|
|
case Format::eFloat32X4:
|
|
return vk::Format::eR32G32B32A32Sfloat;
|
|
case Format::eFloat32X3:
|
|
return vk::Format::eR32G32B32Sfloat;
|
|
case Format::eFloat32X2:
|
|
return vk::Format::eR32G32Sfloat;
|
|
case Format::eFloat32:
|
|
return vk::Format::eR32Sfloat;
|
|
}
|
|
return vk::Format::eUndefined;
|
|
}
|
|
};
|
|
|
|
struct VertexInput
|
|
{
|
|
eastl::vector<AttributeInfo> m_Attribute;
|
|
u32 m_Stride;
|
|
bool m_IsPerInstance;
|
|
};
|
|
|
|
enum class ShaderType
|
|
{
|
|
eInvalid = 0,
|
|
eVertex = VK_SHADER_STAGE_VERTEX_BIT,
|
|
eTesselationControl = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
|
|
eTesselationEvaluation = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
|
eGeometry = VK_SHADER_STAGE_GEOMETRY_BIT,
|
|
eFragment = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
eCompute = VK_SHADER_STAGE_COMPUTE_BIT,
|
|
eTask = VK_SHADER_STAGE_TASK_BIT_EXT,
|
|
eMesh = VK_SHADER_STAGE_MESH_BIT_EXT,
|
|
eMax,
|
|
};
|
|
|
|
constexpr static u32 ShaderTypeCount = 8;
|
|
|
|
static_assert(static_cast<u32>(ShaderType::eMax) == 1 + (1 << (ShaderTypeCount - 1)));
|
|
|
|
struct ShaderInfo
|
|
{
|
|
std::string_view m_ShaderFile;
|
|
eastl::vector<std::string_view> m_EntryPoints;
|
|
};
|
|
|
|
struct GraphicsPipelineCreateInfo
|
|
{
|
|
enum class DepthTest
|
|
{
|
|
eEnabled,
|
|
eReadOnly,
|
|
eDisabled,
|
|
};
|
|
|
|
enum class CompareOp
|
|
{
|
|
eNever = 0x0,
|
|
eLessThan = 0x1,
|
|
eEqualTo = 0x2,
|
|
eGreaterThan = 0x4,
|
|
eLessThanOrEqualTo = eLessThan | eEqualTo,
|
|
eGreaterThanOrEqualTo = eGreaterThan | eEqualTo,
|
|
eNotEqualTo = eLessThan | eGreaterThan,
|
|
eAlways = eLessThan | eEqualTo | eGreaterThan,
|
|
};
|
|
|
|
eastl::fixed_vector<VertexInput, 4, false> m_VertexInputs;
|
|
eastl::fixed_vector<ShaderInfo, 4, false> m_Shaders;
|
|
|
|
DepthTest m_DepthTest = DepthTest::eEnabled;
|
|
CompareOp m_DepthOp = CompareOp::eLessThan;
|
|
|
|
cstr m_Name;
|
|
|
|
private:
|
|
friend Device;
|
|
[[nodiscard]] vk::PipelineDepthStencilStateCreateInfo GetDepthStencilStateCreateInfo() const;
|
|
};
|
|
|
|
struct ComputePipelineCreateInfo
|
|
{
|
|
ShaderInfo m_Shader;
|
|
cstr m_Name;
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
// ----------------------------------------------------------------------------------------------------
|
|
#pragma region Device
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
PhysicalDevice DefaultPhysicalDeviceSelector(PhysicalDevices const &physicalDevices);
|
|
|
|
using PhysicalDeviceSelectorFn = PhysicalDevice (*)(PhysicalDevices const &);
|
|
static_assert(std::convertible_to<decltype(DefaultPhysicalDeviceSelector), PhysicalDeviceSelectorFn>);
|
|
|
|
struct DeviceCreateInfo
|
|
{
|
|
std::reference_wrapper<Window> m_Window;
|
|
Features m_Features;
|
|
cstr m_AppName = "Aster App";
|
|
Version m_AppVersion = {0, 1, 0};
|
|
PhysicalDeviceSelectorFn m_PhysicalDeviceSelector = DefaultPhysicalDeviceSelector;
|
|
std::span<u8> m_PipelineCacheData = {};
|
|
eastl::vector<cstr> m_ShaderSearchPaths;
|
|
bool m_UseBindless = true;
|
|
cstr m_Name = "Primary";
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
#pragma endregion
|
|
|
|
namespace _internal
|
|
{
|
|
class SyncServer;
|
|
}
|
|
|
|
class Receipt
|
|
{
|
|
void *m_Opaque;
|
|
|
|
explicit Receipt(void *opaque)
|
|
: m_Opaque{opaque}
|
|
{
|
|
}
|
|
|
|
friend _internal::SyncServer;
|
|
};
|
|
|
|
struct Frame
|
|
{
|
|
// Persistent
|
|
Device *m_Device;
|
|
|
|
// TODO: ThreadSafe
|
|
_internal::GraphicsContextPool m_PrimaryPool;
|
|
_internal::TransferContextPool m_AsyncTransferPool;
|
|
_internal::ContextPool m_AsyncComputePool;
|
|
|
|
vk::Fence m_FrameAvailableFence;
|
|
vk::Semaphore m_ImageAcquireSem;
|
|
vk::Semaphore m_RenderFinishSem;
|
|
u32 m_FrameIdx;
|
|
|
|
// Transient
|
|
vk::Image m_SwapchainImage;
|
|
vk::ImageView m_SwapchainImageView;
|
|
Size2D m_SwapchainSize;
|
|
u32 m_ImageIdx;
|
|
|
|
void Reset(u32 imageIdx, vk::Image swapchainImage, vk::ImageView swapchainImageView, Size2D swapchainSize);
|
|
GraphicsContext CreateGraphicsContext();
|
|
TransferContext CreateAsyncTransferContext();
|
|
void WaitUntilReady();
|
|
|
|
Frame() = default;
|
|
Frame(Device &device, u32 frameIndex, u32 primaryQueueFamily, u32 asyncTransferQueue, u32 asyncComputeQueue);
|
|
Frame(Frame &&other) noexcept;
|
|
|
|
Frame &operator=(Frame &&other) noexcept;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(Frame);
|
|
|
|
~Frame() = default;
|
|
};
|
|
|
|
class CommitManager;
|
|
|
|
class Device final
|
|
{
|
|
public: // TODO: Temp
|
|
std::reference_wrapper<Window> m_Window;
|
|
Instance m_Instance;
|
|
Surface m_Surface;
|
|
::Device m_Device;
|
|
Swapchain m_Swapchain;
|
|
std::unique_ptr<CommitManager> m_CommitManager;
|
|
|
|
// TODO: This is single-threaded.
|
|
vk::Queue m_PrimaryQueue;
|
|
u32 m_PrimaryQueueFamily;
|
|
|
|
vk::Queue m_TransferQueue;
|
|
u32 m_TransferQueueFamily;
|
|
|
|
vk::Queue m_ComputeQueue;
|
|
u32 m_ComputeQueueFamily;
|
|
|
|
_internal::OrderlessTransferContextPool m_TransferContextPool;
|
|
_internal::OrderlessComputeContextPool m_ComputeContextPool;
|
|
|
|
std::array<Frame, MAX_FRAMES_IN_FLIGHT> m_Frames;
|
|
u32 m_CurrentFrameIdx = 0;
|
|
|
|
public:
|
|
// ====================================================================================================
|
|
// Resource Management
|
|
// ====================================================================================================
|
|
|
|
//
|
|
// Buffer Management
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
[[nodiscard]] Ref<StorageBuffer> CreateStorageBuffer(usize size, cstr name = nullptr);
|
|
[[nodiscard]] Ref<IndexBuffer> CreateIndexBuffer(usize size, cstr name = nullptr);
|
|
[[nodiscard]] Ref<UniformBuffer> CreateUniformBuffer(usize size, cstr name = nullptr);
|
|
[[nodiscard]] Ref<StagingBuffer> CreateStagingBuffer(usize size, cstr name = nullptr);
|
|
[[nodiscard]] Ref<VertexBuffer> CreateVertexBuffer(usize size, cstr name = nullptr);
|
|
|
|
//
|
|
// Image Management
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
template <concepts::ImageInto<Texture> T>
|
|
[[nodiscard]] Ref<T>
|
|
CreateTexture2D(Texture2DCreateInfo const &createInfo)
|
|
{
|
|
return CastImage<T>(CreateTexture2D(createInfo));
|
|
}
|
|
|
|
template <concepts::ImageInto<TextureCube> T>
|
|
[[nodiscard]] Ref<T>
|
|
CreateTextureCube(TextureCubeCreateInfo const &createInfo)
|
|
{
|
|
return CastImage<T>(CreateTextureCube(createInfo));
|
|
}
|
|
|
|
[[nodiscard]] Ref<Image> CreateTexture2D(Texture2DCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<ImageCube> CreateTextureCube(TextureCubeCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<Image> CreateAttachment(AttachmentCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<Image> CreateDepthStencilImage(DepthStencilImageCreateInfo const &createInfo);
|
|
|
|
//
|
|
// View Management
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
template <concepts::View TImageView>
|
|
Ref<TImageView>
|
|
CreateView(ViewCreateInfo<typename TImageView::ImageType> const &createInfo)
|
|
{
|
|
return CastView<TImageView>(CreateView(ViewCreateInfo<Image>(createInfo)));
|
|
}
|
|
|
|
[[nodiscard]] Ref<ImageView> CreateView(ViewCreateInfo<Image> const &createInfo);
|
|
|
|
//
|
|
// Image - View Combined Management
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
template <concepts::ViewTo<Image> T>
|
|
[[nodiscard]] Ref<T>
|
|
CreateTexture2DWithView(Texture2DCreateInfo const &createInfo)
|
|
{
|
|
auto handle = CreateTexture2DWithView(createInfo);
|
|
return CastView<T>(handle);
|
|
}
|
|
|
|
template <concepts::ViewTo<ImageCube> T>
|
|
[[nodiscard]] Ref<T>
|
|
CreateTextureCubeWithView(TextureCubeCreateInfo const &createInfo)
|
|
{
|
|
auto handle = CreateTextureCubeWithView(createInfo);
|
|
return CastView<T>(handle);
|
|
}
|
|
|
|
[[nodiscard]] Ref<TextureView> CreateTexture2DWithView(Texture2DCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<ImageCubeView> CreateTextureCubeWithView(TextureCubeCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<ImageView> CreateAttachmentWithView(AttachmentCreateInfo const &createInfo);
|
|
[[nodiscard]] Ref<ImageView> CreateDepthStencilImageWithView(DepthStencilImageCreateInfo const &createInfo);
|
|
|
|
//
|
|
// Sampler Management
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
private:
|
|
eastl::hash_map<vk::SamplerCreateInfo, WeakRef<Sampler>> m_HashToSamplerIdx;
|
|
|
|
public:
|
|
Ref<Sampler> CreateSampler(SamplerCreateInfo const &createInfo);
|
|
|
|
//
|
|
// Pipeline
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
// TODO: Cache shader modules for reuse. Time to move to `slang`
|
|
private:
|
|
Slang::ComPtr<slang::IGlobalSession> m_GlobalSlangSession;
|
|
Slang::ComPtr<slang::ISession> m_SlangSession;
|
|
|
|
PipelineCreationError
|
|
CreateShaders(eastl::fixed_vector<vk::PipelineShaderStageCreateInfo, ShaderTypeCount, false> &shadersOut,
|
|
Slang::ComPtr<slang::IComponentType> &program, std::span<ShaderInfo const> const &shaders);
|
|
systems::PipelineCreationError
|
|
CreateShader(vk::PipelineShaderStageCreateInfo &shadersOut, Slang::ComPtr<slang::IComponentType> &program,
|
|
ShaderInfo const &shaders);
|
|
PipelineCreationError
|
|
CreatePipelineLayout(vk::PipelineLayout &pipelineLayout, Slang::ComPtr<slang::IComponentType> const &program);
|
|
|
|
public:
|
|
// Pipelines, unlike the other resources, are not ref-counted.
|
|
PipelineCreationError CreatePipeline(Pipeline &pipeline, GraphicsPipelineCreateInfo const &createInfo);
|
|
PipelineCreationError CreateComputePipeline(Pipeline &pipeline, ComputePipelineCreateInfo const &createInfo);
|
|
|
|
//
|
|
// Frames
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
public:
|
|
Frame &GetNextFrame();
|
|
|
|
Size2D
|
|
GetSwapchainSize() const
|
|
{
|
|
return {m_Swapchain.m_Extent.width, m_Swapchain.m_Extent.height};
|
|
}
|
|
|
|
void
|
|
RegisterResizeCallback(Swapchain::FnResizeCallback &&callback)
|
|
{
|
|
m_Swapchain.RegisterResizeCallback(eastl::forward<Swapchain::FnResizeCallback>(callback));
|
|
}
|
|
|
|
void Present(Frame &frame, GraphicsContext &graphicsContext);
|
|
|
|
//
|
|
// Context
|
|
// ----------------------------------------------------------------------------------------------------
|
|
friend Context;
|
|
friend GraphicsContext;
|
|
friend TransferContext;
|
|
|
|
TransferContext CreateTransferContext();
|
|
ComputeContext CreateComputeContext();
|
|
Receipt Submit(Context &context);
|
|
|
|
//
|
|
// Sync
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
std::unique_ptr<_internal::SyncServer> m_SyncServer;
|
|
void WaitOn(Receipt recpt);
|
|
|
|
//
|
|
// Device Methods
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
template <concepts::VkHandle T>
|
|
void
|
|
SetName(T const &object, cstr name) const
|
|
{
|
|
m_Device.SetName(object, name);
|
|
}
|
|
|
|
[[nodiscard]] vk::Queue
|
|
GetQueue(u32 const familyIndex, u32 const queueIndex) const
|
|
{
|
|
return m_Device.GetQueue(familyIndex, queueIndex);
|
|
}
|
|
|
|
[[nodiscard]] eastl::vector<u8>
|
|
DumpPipelineCache() const
|
|
{
|
|
return m_Device.DumpPipelineCache();
|
|
}
|
|
|
|
void
|
|
WaitIdle() const
|
|
{
|
|
m_Device.WaitIdle();
|
|
}
|
|
|
|
// Inner
|
|
// ----------------------------------------------------------------------------------------------------
|
|
|
|
[[nodiscard]] ::Device &
|
|
GetInner()
|
|
{
|
|
return m_Device;
|
|
}
|
|
|
|
[[nodiscard]] vk::Device &
|
|
GetHandle()
|
|
{
|
|
return m_Device.m_Device;
|
|
}
|
|
|
|
// Ctor/Dtor
|
|
// ----------------------------------------------------------------------------------------------------
|
|
explicit Device(DeviceCreateInfo const &createInfo);
|
|
|
|
~Device();
|
|
|
|
PIN_MEMORY(Device);
|
|
};
|
|
|
|
} // namespace systems
|