Implementing struct chaining

This commit is contained in:
2025-05-18 08:49:22 +02:00
parent 56ec1aa97a
commit a398ca65fc
4 changed files with 94 additions and 129 deletions
+4 -1
View File
@@ -29,5 +29,8 @@
"res/shaders/lib" "res/shaders/lib"
], ],
"slang.slangdLocation": "C:\\Users\\Dynamitos\\slang\\build\\Release\\bin\\slangd.exe", "slang.slangdLocation": "C:\\Users\\Dynamitos\\slang\\build\\Release\\bin\\slangd.exe",
"slang.searchInAllWorkspaceDirectories": false "slang.searchInAllWorkspaceDirectories": false,
"files.associations": {
"type_traits": "cpp"
}
} }
+1 -4
View File
@@ -5,7 +5,6 @@
#include "MeshData.h" #include "MeshData.h"
#include "MinimalEngine.h" #include "MinimalEngine.h"
namespace Seele { namespace Seele {
struct GraphicsInitializer { struct GraphicsInitializer {
const char* applicationName; const char* applicationName;
@@ -21,9 +20,7 @@ struct GraphicsInitializer {
Array<const char*> deviceExtensions; Array<const char*> deviceExtensions;
void* windowHandle; void* windowHandle;
GraphicsInitializer() GraphicsInitializer() : applicationName("SeeleEngine"), engineName("SeeleEngine"), windowLayoutFile(nullptr), windowHandle(nullptr) {}
: applicationName("SeeleEngine"), engineName("SeeleEngine"), windowLayoutFile(nullptr), layers{},
instanceExtensions{}, deviceExtensions{"VK_KHR_swapchain"}, windowHandle(nullptr) {}
}; };
struct WindowCreateInfo { struct WindowCreateInfo {
int32 width; int32 width;
+18 -93
View File
@@ -172,7 +172,7 @@ Gfx::OViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreate
return new Viewport(owner, viewportInfo); return new Viewport(owner, viewportInfo);
} }
Gfx::ORenderPass Graphics::createRenderPass(Gfx::RenderTargetLayout layout, Array<Gfx::SubPassDependency> dependencies, URect renderArea, Gfx::ORenderPass Graphics::createRenderPass(Gfx::RenderTargetLayout layout, Array<Gfx::SubPassDependency> dependencies, URect,
std::string name, Array<uint32> viewMasks, Array<uint32> correlationMasks) { std::string name, Array<uint32> viewMasks, Array<uint32> correlationMasks) {
// todo: re-introduce render area to renderpass // todo: re-introduce render area to renderpass
return new RenderPass(this, std::move(layout), std::move(dependencies), name, std::move(viewMasks), std::move(correlationMasks)); return new RenderPass(this, std::move(layout), std::move(dependencies), name, std::move(viewMasks), std::move(correlationMasks));
@@ -553,7 +553,7 @@ void Graphics::buildBottomLevelAccelerationStructures(Array<Gfx::PBottomLevelAS>
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };
scratchBuffers[i] = new BufferAllocation(this, "ScratchBuffer", scratchInfo, scratchAllocInfo, Gfx::QueueType::GRAPHICS, scratchBuffers[i] = new BufferAllocation(this, "ScratchBuffer", scratchInfo, scratchAllocInfo, Gfx::QueueType::GRAPHICS,
accelerationProperties.minAccelerationStructureScratchOffsetAlignment); props.get<VkPhysicalDeviceAccelerationStructurePropertiesKHR>().minAccelerationStructureScratchOffsetAlignment);
buildGeometries[i].dstAccelerationStructure = blas->handle; buildGeometries[i].dstAccelerationStructure = blas->handle;
buildGeometries[i].scratchData.deviceAddress = scratchBuffers[i]->deviceAddress; buildGeometries[i].scratchData.deviceAddress = scratchBuffers[i]->deviceAddress;
@@ -685,7 +685,7 @@ void Graphics::initInstance(GraphicsInitializer initInfo) {
.applicationVersion = VK_MAKE_VERSION(0, 0, 1), .applicationVersion = VK_MAKE_VERSION(0, 0, 1),
.pEngineName = initInfo.engineName, .pEngineName = initInfo.engineName,
.engineVersion = VK_MAKE_VERSION(0, 0, 1), .engineVersion = VK_MAKE_VERSION(0, 0, 1),
.apiVersion = VK_API_VERSION_1_3, .apiVersion = VK_API_VERSION_1_4,
}; };
Array<const char*> extensions = getRequiredExtensions(); Array<const char*> extensions = getRequiredExtensions();
@@ -733,101 +733,35 @@ void Graphics::pickPhysicalDevice() {
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
VkPhysicalDevice bestDevice = VK_NULL_HANDLE; VkPhysicalDevice bestDevice = VK_NULL_HANDLE;
uint32 deviceRating = 0; uint32 deviceRating = 0;
props = VkPhysicalDeviceProperties2{ props.get<VkPhysicalDeviceProperties2>() = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
.pNext = &accelerationProperties,
}; };
accelerationProperties = VkPhysicalDeviceAccelerationStructurePropertiesKHR{ props.get<VkPhysicalDeviceAccelerationStructurePropertiesKHR>() = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR,
.pNext = &rayTracingProperties,
}; };
rayTracingProperties = VkPhysicalDeviceRayTracingPipelinePropertiesKHR{ props.get<VkPhysicalDeviceRayTracingPipelinePropertiesKHR>() = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR,
.pNext = nullptr,
}; };
for (auto dev : physicalDevices) { for (auto dev : physicalDevices) {
uint32 currentRating = 0; uint32 currentRating = 0;
vkGetPhysicalDeviceProperties2(dev, &props); vkGetPhysicalDeviceProperties2(dev, &props.get());
if (props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { if (props.get().properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
std::cout << "found dedicated gpu " << props.properties.deviceName << std::endl; std::cout << "found dedicated gpu " << props.get().properties.deviceName << std::endl;
currentRating += 100; currentRating += 100;
} else if (props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) { } else if (props.get().properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
std::cout << "found integrated gpu " << props.properties.deviceName << std::endl; std::cout << "found integrated gpu " << props.get().properties.deviceName << std::endl;
currentRating += 10; currentRating += 10;
} }
if (currentRating > deviceRating) { if (currentRating > deviceRating) {
deviceRating = currentRating; deviceRating = currentRating;
bestDevice = dev; bestDevice = dev;
std::cout << "bestDevice: " << props.properties.deviceName << std::endl; std::cout << "bestDevice: " << props.get().properties.deviceName << std::endl;
} }
} }
physicalDevice = bestDevice; physicalDevice = bestDevice;
vkGetPhysicalDeviceProperties2(physicalDevice, &props); vkGetPhysicalDeviceProperties2(physicalDevice, &props.get());
bufferDeviceAddressFeatures = { vkGetPhysicalDeviceFeatures2(physicalDevice, &features.get());
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES,
.pNext = nullptr,
.bufferDeviceAddress = true,
};
rayTracingFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR,
.pNext = &bufferDeviceAddressFeatures,
.rayTracingPipeline = true,
};
accelerationFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR,
.pNext = &rayTracingFeatures,
.accelerationStructure = true,
};
meshShaderFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
.taskShader = true,
.meshShader = true,
.multiviewMeshShader = true,
.primitiveFragmentShadingRateMeshShader = false,
.meshShaderQueries = true,
};
features12 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.storageBuffer8BitAccess = true,
.uniformAndStorageBuffer8BitAccess = true,
.shaderBufferInt64Atomics = true,
.shaderFloat16 = true,
.shaderInt8 = true,
.shaderUniformBufferArrayNonUniformIndexing = true,
.shaderSampledImageArrayNonUniformIndexing = true,
.shaderStorageBufferArrayNonUniformIndexing = true,
.descriptorBindingUniformBufferUpdateAfterBind = true,
.descriptorBindingSampledImageUpdateAfterBind = true,
.descriptorBindingStorageBufferUpdateAfterBind = true,
.descriptorBindingPartiallyBound = true,
.runtimeDescriptorArray = true,
.bufferDeviceAddress = true,
};
features11 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
.pNext = &features12,
.storageBuffer16BitAccess = true,
.uniformAndStorageBuffer16BitAccess = true,
.multiview = true,
};
features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &features11,
.features =
{
//.robustBufferAccess = true,
.geometryShader = true,
.fillModeNonSolid = true,
.wideLines = true,
.samplerAnisotropy = true,
.pipelineStatisticsQuery = true,
.fragmentStoresAndAtomics = true,
.shaderInt64 = true,
.shaderInt16 = true,
.inheritedQueries = true,
},
};
bool rayTracingPipelineSupport = false; bool rayTracingPipelineSupport = false;
bool accelerationStructureSupport = false; bool accelerationStructureSupport = false;
bool hostOperationsSupport = false; bool hostOperationsSupport = false;
@@ -867,18 +801,8 @@ void Graphics::pickPhysicalDevice() {
shaderFloatControls = true; shaderFloatControls = true;
} }
} }
rayTracingEnabled = rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport && rayTracingEnabled = false && rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport &&
descriptorIndexingSupport && spirv14Support && shaderFloatControls; descriptorIndexingSupport && spirv14Support && shaderFloatControls;
if (meshShadingEnabled) {
features12.pNext = &meshShaderFeatures;
}
if (rayTracingEnabled) {
if (meshShadingEnabled) {
meshShaderFeatures.pNext = &accelerationFeatures;
} else {
features12.pNext = &accelerationFeatures;
}
}
} }
void Graphics::createDevice(GraphicsInitializer initializer) { void Graphics::createDevice(GraphicsInitializer initializer) {
@@ -945,9 +869,10 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
currQueue.pQueuePriorities = currentPriority; currQueue.pQueuePriorities = currentPriority;
for (int32_t queueIndex = 0; queueIndex < (int32_t)currQueue.queueCount; ++queueIndex) { for (int32_t queueIndex = 0; queueIndex < (int32_t)currQueue.queueCount; ++queueIndex) {
*currentPriority++ = 1.0f; *currentPriority++ = 0.0f;
} }
} }
initializer.deviceExtensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
if (supportMeshShading()) { if (supportMeshShading()) {
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
} }
@@ -970,7 +895,7 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
#endif #endif
VkDeviceCreateInfo deviceInfo = { VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features, .pNext = &features.get(),
.queueCreateInfoCount = (uint32)queueInfos.size(), .queueCreateInfoCount = (uint32)queueInfos.size(),
.pQueueCreateInfos = queueInfos.data(), .pQueueCreateInfos = queueInfos.data(),
.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(), .enabledExtensionCount = (uint32)initializer.deviceExtensions.size(),
+71 -31
View File
@@ -11,31 +11,63 @@ DECLARE_REF(PipelineCache)
DECLARE_REF(Framebuffer) DECLARE_REF(Framebuffer)
template <typename T> template <typename T>
concept chainable_struct = requires(T t) { t.pNext; }; concept chainable_struct = requires(T t) {
template <chainable_struct... T> struct StructChain; t.pNext;
template <> struct StructChain<> { t.sType;
}; };
template<chainable_struct Base> struct StructChain<Base> : StructChain<> { template <chainable_struct T, VkStructureType struct_type> struct Helper {};
StructChain(Base b):b(b) {}
StructChain(const StructChain<>&, Base b) : b(b) {} template <typename...> struct is_unique : std::true_type {};
template <chainable_struct Next> StructChain<Next, Base> append(Next next) { return StructChain<Next, Base>(*this, next); }
template <typename T, typename... Rest>
struct is_unique<T, Rest...> : std::bool_constant<(!std::same_as<T, Rest> && ... && is_unique<Rest...>::value)> {};
template <typename... T>
concept unique_chainable_structs = (chainable_struct<T> && ...) && is_unique<T...>::value;
template <typename... T> struct StructChain;
template <chainable_struct Base, VkStructureType struct_type> struct StructChain<Helper<Base, struct_type>> {
StructChain() {
b.sType = struct_type;
b.pNext = nullptr;
}
Base b; Base b;
Base& operator*(){ template <chainable_struct Query>
Query& get()
requires std::same_as<Query, Base>
{
return b; return b;
} }
}; template <chainable_struct Query>
template <chainable_struct This, chainable_struct... Right> struct StructChain<This, Right...> : StructChain<Right...> { const Query& get() const
StructChain(const StructChain<Right...>& parent, This t) : StructChain<Right...>(parent), t(t) {} requires std::same_as<Query, Base>
template <chainable_struct Next> StructChain<Next, This, Right...> append(Next next) { {
return StructChain<Next, This, Right...>(*this, next); return b;
} }
auto& operator*() { Base& get() { return b; }
auto& base = StructChain<Right...>::operator*(); const Base& get() const { return b; }
t.pNext = base.pNext; };
base.pNext = &t; template <chainable_struct This, VkStructureType struct_type, typename... Right>
return base; struct StructChain<Helper<This, struct_type>, Right...> : StructChain<Right...> {
StructChain() {
t.sType = struct_type;
t.pNext = &StructChain<Right...>::template get();
} }
This t; This t;
template <chainable_struct Query> Query& get() {
if constexpr (std::same_as<Query, This>)
return t;
else
return StructChain<Right...>::template get<Query>();
}
template <chainable_struct Query> const Query& get() const {
if constexpr (std::same_as<Query, This>)
return t;
else
return StructChain<Right...>::template get<Query>();
}
This& get() { return t; }
const This& get() const { return t; }
}; };
class Graphics : public Gfx::Graphics { class Graphics : public Gfx::Graphics {
@@ -45,9 +77,13 @@ class Graphics : public Gfx::Graphics {
constexpr VkInstance getInstance() const { return instance; } constexpr VkInstance getInstance() const { return instance; }
constexpr VkDevice getDevice() const { return handle; } constexpr VkDevice getDevice() const { return handle; }
constexpr VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; } constexpr VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; }
constexpr VkPhysicalDeviceAccelerationStructurePropertiesKHR getAccelerationProperties() const { return accelerationProperties; } constexpr VkPhysicalDeviceAccelerationStructurePropertiesKHR getAccelerationProperties() const {
constexpr VkPhysicalDeviceRayTracingPipelinePropertiesKHR getRayTracingProperties() const { return rayTracingProperties; } return props.get<VkPhysicalDeviceAccelerationStructurePropertiesKHR>();
constexpr float getTimestampPeriod() const { return props.properties.limits.timestampPeriod; } }
constexpr VkPhysicalDeviceRayTracingPipelinePropertiesKHR getRayTracingProperties() const {
return props.get<VkPhysicalDeviceRayTracingPipelinePropertiesKHR>();
}
constexpr float getTimestampPeriod() const { return props.get<VkPhysicalDeviceProperties2>().properties.limits.timestampPeriod; }
constexpr uint64 getTimestampValidBits() const { return graphicsProps.timestampValidBits; } constexpr uint64 getTimestampValidBits() const { return graphicsProps.timestampValidBits; }
PCommandPool getQueueCommands(Gfx::QueueType queueType); PCommandPool getQueueCommands(Gfx::QueueType queueType);
@@ -149,17 +185,21 @@ class Graphics : public Gfx::Graphics {
VkQueueFamilyProperties graphicsProps; VkQueueFamilyProperties graphicsProps;
VkPhysicalDeviceProperties2 props; StructChain<
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingProperties; Helper<VkPhysicalDeviceProperties2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2>,
VkPhysicalDeviceAccelerationStructurePropertiesKHR accelerationProperties; Helper<VkPhysicalDeviceRayTracingPipelinePropertiesKHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR>,
Helper<VkPhysicalDeviceAccelerationStructurePropertiesKHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR>>
props;
StructChain<
Helper<VkPhysicalDeviceFeatures2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2>,
Helper<VkPhysicalDeviceVulkan11Features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES>,
Helper<VkPhysicalDeviceVulkan12Features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES>,
Helper<VkPhysicalDeviceMeshShaderFeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT>,
Helper<VkPhysicalDeviceAccelerationStructureFeaturesKHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR>,
Helper<VkPhysicalDeviceRayTracingPipelineFeaturesKHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR>>
features;
VkPhysicalDeviceFeatures2 features;
VkPhysicalDeviceVulkan11Features features11;
VkPhysicalDeviceVulkan12Features features12;
VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures;
VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddressFeatures;
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationFeatures;
VkPhysicalDeviceRayTracingPipelineFeaturesKHR rayTracingFeatures;
VkDebugUtilsMessengerEXT callback; VkDebugUtilsMessengerEXT callback;
Map<uint32, OFramebuffer> allocatedFramebuffers; Map<uint32, OFramebuffer> allocatedFramebuffers;
VmaAllocator allocator; VmaAllocator allocator;