Skip to content

Commit e25d3fb

Browse files
committed
Added cull mode and front face using dynamic mode extension, to avoid additional binding
1 parent 7380d19 commit e25d3fb

19 files changed

Lines changed: 272 additions & 19 deletions

VesperEngine/Backend/device.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
VESPERENGINE_NAMESPACE_BEGIN
1818

19+
PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr;
20+
PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT = nullptr;
21+
1922
// local callback functions
2023
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
2124
VkDebugUtilsMessageSeverityFlagBitsEXT _messageSeverity,
@@ -198,7 +201,12 @@ void Device::CreateLogicalDevice()
198201
VkPhysicalDeviceFeatures deviceFeatures = {};
199202
deviceFeatures.samplerAnisotropy = VK_TRUE;
200203

201-
// EXT features
204+
// EXT features -> Dynamic state
205+
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamicStateFeatures = {};
206+
dynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
207+
dynamicStateFeatures.extendedDynamicState = VK_TRUE;
208+
209+
// EXT features -> Indexing
202210
VkPhysicalDeviceDescriptorIndexingFeaturesEXT indexingFeatures = {};
203211
indexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
204212
indexingFeatures.runtimeDescriptorArray = VK_TRUE;
@@ -212,13 +220,19 @@ void Device::CreateLogicalDevice()
212220
// indexingFeatures.descriptorBindingUniformTexelBufferUpdateAfterBind = VK_TRUE;
213221
// indexingFeatures.descriptorBindingStorageTexelBufferUpdateAfterBind = VK_TRUE;
214222

223+
215224
VkPhysicalDeviceFeatures2 deviceFeatures2 = {};
216225
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
217226
deviceFeatures2.features = deviceFeatures; // Include base features like samplerAnisotropy
218227

219228
if (m_bIsBindlessResourcesSupported)
220229
{
221-
deviceFeatures2.pNext = &indexingFeatures;
230+
dynamicStateFeatures.pNext = &indexingFeatures;
231+
deviceFeatures2.pNext = &dynamicStateFeatures;
232+
}
233+
else
234+
{
235+
dynamicStateFeatures.pNext = &indexingFeatures;
222236
}
223237

224238
VkDeviceCreateInfo createInfo = {};
@@ -243,7 +257,16 @@ void Device::CreateLogicalDevice()
243257

244258
// Use features2 instead of pEnabledFeatures
245259
createInfo.pEnabledFeatures = nullptr;
246-
createInfo.pNext = &deviceFeatures2;
260+
261+
if (m_bIsBindlessResourcesSupported)
262+
{
263+
createInfo.pNext = &deviceFeatures2;
264+
}
265+
else
266+
{
267+
createInfo.pNext = &dynamicStateFeatures;;
268+
}
269+
//
247270

248271
if (vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device) != VK_SUCCESS)
249272
{
@@ -252,6 +275,22 @@ void Device::CreateLogicalDevice()
252275

253276
vkGetDeviceQueue(m_device, indices.GraphicsFamily, 0, &m_graphicsQueue);
254277
vkGetDeviceQueue(m_device, indices.PresentFamily, 0, &m_presentQueue);
278+
279+
if (VK_EXT_extended_dynamic_state2_enabled)
280+
{
281+
// the function name vkCmdSetCullMode does not have EXT vkCmdSetCullModeEXT, because in Vulkan 1.3 they were promoted to Core
282+
vkCmdSetCullModeEXT = reinterpret_cast<PFN_vkCmdSetCullModeEXT>(vkGetDeviceProcAddr(m_device, "vkCmdSetCullMode"));
283+
vkCmdSetFrontFaceEXT = reinterpret_cast<PFN_vkCmdSetFrontFaceEXT>(vkGetDeviceProcAddr(m_device, "vkCmdSetFrontFace"));
284+
285+
if (!vkCmdSetCullModeEXT || !vkCmdSetFrontFaceEXT)
286+
{
287+
throw std::runtime_error("failed to create logical device! Device does not support VK_EXT_extended_dynamic_state2, which is required!");
288+
}
289+
}
290+
else
291+
{
292+
throw std::runtime_error("failed to create logical device! Device does not support VK_EXT_extended_dynamic_state2, which is required!");
293+
}
255294
}
256295

257296
void Device::CreateCommandPool()
@@ -536,6 +575,10 @@ bool Device::CheckDeviceExtensionSupport(VkPhysicalDevice _device)
536575
{
537576
VK_EXT_descriptor_indexing_extension_enabled = true;
538577
}
578+
else if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) == 0)
579+
{
580+
VK_EXT_extended_dynamic_state2_enabled = true;
581+
}
539582

540583
requiredExtensions.erase(extension.extensionName);
541584
}

VesperEngine/Backend/device.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct QueueFamilyIndices
3131
bool IsComplete() { return GraphicsFamilyHasValue && PresentFamilyHasValue; }
3232
};
3333

34+
extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
35+
extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
3436

3537
class VESPERENGINE_API Device final
3638
{
@@ -115,6 +117,7 @@ class VESPERENGINE_API Device final
115117
bool VK_EXT_memory_priority_enabled = false;
116118
bool VK_EXT_debug_utils_enabled = false;
117119
bool VK_EXT_descriptor_indexing_extension_enabled = false;
120+
bool VK_EXT_extended_dynamic_state2_enabled = false;
118121

119122
bool m_bIsBindlessResourcesSupported = false;
120123

@@ -162,7 +165,8 @@ class VESPERENGINE_API Device final
162165
const std::vector<const char*> m_validationLayers = { "VK_LAYER_KHRONOS_validation" };
163166
const std::vector<const char*> m_deviceExtensions = {
164167
VK_KHR_SWAPCHAIN_EXTENSION_NAME, // Swapchain support
165-
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME // Bindless binding support
168+
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, // Bindless binding support
169+
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME // Extended dynamic state 2
166170
};
167171
};
168172

VesperEngine/Backend/model_data.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct MaterialData
7070
BufferComponent UniformBuffer;
7171
int32 Index{ -1 };
7272
bool IsTransparent{ false };
73+
bool IsDoubleSided{ false };
7374
MaterialType Type;
7475
};
7576

@@ -91,6 +92,7 @@ struct ModelData
9192
std::vector<uint32> Indices{};
9293
std::shared_ptr<MaterialData> Material;
9394
bool IsStatic{ false };
95+
bool IsMirrored{ false };
9496
glm::vec4 MorphWeights[2]{ glm::vec4(0.0f), glm::vec4(0.0f) };
9597
uint32 MorphTargetCount{ 0 };
9698
std::vector<MorphAnimation> Animations{};

VesperEngine/Backend/pipeline.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,14 @@ void Pipeline::DefaultPipelineConfiguration(PipelineConfigInfo& _outConfigInfo)
123123
VK_DYNAMIC_STATE_VIEWPORT,
124124

125125
// Scissor is like Viewport, but instead "squash" the result image (Viewport.width/height if changed keep the image but squashed), it will cut it.
126-
// Any pixels outside of the Scissor rectangle (offset + extent) will be discarded.
127-
VK_DYNAMIC_STATE_SCISSOR
126+
// Any pixels outside of the Scissor rectangle (offset + extent) will be discarded.
127+
VK_DYNAMIC_STATE_SCISSOR,
128+
129+
// Allow changing culling mode dynamically
130+
VK_DYNAMIC_STATE_CULL_MODE,
131+
132+
// Allow changing front face dynamically
133+
VK_DYNAMIC_STATE_FRONT_FACE
128134
};
129135
_outConfigInfo.DynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
130136
_outConfigInfo.DynamicStateInfo.pDynamicStates = _outConfigInfo.DynamicStateEnables.data();
@@ -326,6 +332,14 @@ void Pipeline::Bind(VkCommandBuffer _commandBuffer)
326332
{
327333
// VK_PIPELINE_BIND_POINT_GRAPHICS signal is a graphic pipeline (other are compute and ray tracing)
328334
vkCmdBindPipeline(_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicPipeline);
335+
336+
// TODO: This break Skybox!
337+
// fallback, to avoid validation error, since is expecting culling to be dynamic (for now)
338+
// vkCmdSetCullModeEXT(_commandBuffer, VK_CULL_MODE_BACK_BIT);
339+
// vkCmdSetFrontFaceEXT(_commandBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
340+
//vkCmdSetDepthTestEnableEXT(_commandBuffer, VK_TRUE); // if depth test is dynamic
341+
//vkCmdSetDepthWriteEnableEXT(_commandBuffer, VK_TRUE); // if write is dynamic
342+
//vkCmdSetBlendConstants(_commandBuffer, blendConstants); // if blending is dynamic
329343
}
330344

331345
std::vector<int8> Pipeline::ReadFile(const std::string& _filepath)

VesperEngine/Components/graphics_components.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct MaterialComponent
6060
{
6161
using FieldType = int32;
6262
int32 Index{ -1 };
63+
bool IsDoubleSided{ false };
6364

6465
// store the descriptor set bound to the resource per presentation frame (1,2 or 3)
6566
std::vector<VkDescriptorSet> BoundDescriptorSet;

VesperEngine/Components/object_components.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct StaticComponent
3838
struct UpdateComponent
3939
{
4040
glm::mat4 ModelMatrix{ 1 };
41+
bool IsMirrored{ false };
4142
};
4243

4344
// define the struct which each instance has at least to have, if needs to be visible

VesperEngine/Systems/brdf_lut_generation_system.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ void BRDFLUTGenerationSystem::Generate(VkCommandBuffer _commandBuffer, uint32 _w
6161
const PushResolution resolution{{ _width, _height }};
6262
PushConstants(_commandBuffer, 0, &resolution);
6363

64+
//if (vkCmdSetCullModeEXT && vkCmdSetFrontFaceEXT) // no need, we do throw and exception if not supported
65+
{
66+
vkCmdSetCullModeEXT(_commandBuffer, VK_CULL_MODE_NONE);
67+
vkCmdSetFrontFaceEXT(_commandBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
68+
}
69+
6470
Bind(m_quadVertexBufferComponent, _commandBuffer);
6571
Draw(m_quadVertexBufferComponent, _commandBuffer);
6672
}

VesperEngine/Systems/irradiance_convolution_generation_system.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ void IrradianceConvolutionGenerationSystem::Generate(
148148
PushConstant pc{ _viewProj, _deltaPhi, _deltaTheta };
149149
PushConstants(_commandBuffer, 0, &pc);
150150

151+
//if (vkCmdSetCullModeEXT && vkCmdSetFrontFaceEXT) // no need, we do throw and exception if not supported
152+
{
153+
vkCmdSetCullModeEXT(_commandBuffer, VK_CULL_MODE_NONE);
154+
vkCmdSetFrontFaceEXT(_commandBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
155+
}
156+
151157
Bind(m_cubeVertex, _commandBuffer);
152158
Draw(m_cubeVertex, _commandBuffer);
153159
}

VesperEngine/Systems/material_system.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const MaterialSystem::DefaultMaterialType MaterialSystem::DefaultPhongMaterial =
3434
float{0.5f}
3535
},
3636
false,
37+
false,
3738
MaterialType::Phong
3839
};
3940

@@ -49,6 +50,7 @@ std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(
4950
const std::vector<std::string>& _texturePaths,
5051
const std::vector<std::any>& _values,
5152
bool _bIsTransparent,
53+
bool _bIsDoubleSided,
5254
MaterialType _type,
5355
const std::vector<int32>& _uvIndices)
5456
{
@@ -65,6 +67,7 @@ std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(
6567

6668
material->Type = _type;
6769
material->IsTransparent = _bIsTransparent;
70+
material->IsDoubleSided = _bIsDoubleSided;
6871

6972
#ifdef _DEBUG
7073
material->Name = _name;
@@ -206,6 +209,7 @@ std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(
206209
const std::vector<std::shared_ptr<TextureData>>& _textures,
207210
const std::vector<std::any>& _values,
208211
bool _bIsTransparent,
212+
bool _bIsDoubleSided,
209213
MaterialType _type,
210214
const std::vector<int32>& _uvIndices)
211215
{
@@ -222,6 +226,7 @@ std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(
222226

223227
material->Type = _type;
224228
material->IsTransparent = _bIsTransparent;
229+
material->IsDoubleSided = _bIsDoubleSided;
225230

226231
#ifdef _DEBUG
227232
material->Name = _name;
@@ -356,7 +361,7 @@ std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(
356361

357362
std::shared_ptr<MaterialData> MaterialSystem::CreateMaterial(const DefaultMaterialType& _defaultMaterial)
358363
{
359-
return CreateMaterial(_defaultMaterial.Name, _defaultMaterial.Textures, _defaultMaterial.Values, _defaultMaterial.IsTransparent, _defaultMaterial.Type, {});
364+
return CreateMaterial(_defaultMaterial.Name, _defaultMaterial.Textures, _defaultMaterial.Values, _defaultMaterial.IsTransparent, _defaultMaterial.IsDoubleSided, _defaultMaterial.Type, {});
360365
}
361366

362367
void MaterialSystem::Cleanup()

VesperEngine/Systems/material_system.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class VESPERENGINE_API MaterialSystem final
7575
const std::vector<std::string>& Textures;
7676
const std::vector<std::any> Values;
7777
bool IsTransparent;
78+
bool IsDoubleSided;
7879
MaterialType Type;
7980
};
8081

@@ -96,6 +97,7 @@ class VESPERENGINE_API MaterialSystem final
9697
const std::vector<std::string>& _texturePaths,
9798
const std::vector<std::any>& _values,
9899
bool _bIsTransparent,
100+
bool _bIsDoubleSided,
99101
MaterialType _type,
100102
const std::vector<int32>& _uvIndices = {});
101103

@@ -107,6 +109,7 @@ class VESPERENGINE_API MaterialSystem final
107109
const std::vector<std::shared_ptr<TextureData>>& _textures,
108110
const std::vector<std::any>& _values,
109111
bool _bIsTransparent,
112+
bool _bIsDoubleSided,
110113
MaterialType _type,
111114
const std::vector<int32>& _uvIndices = {});
112115

0 commit comments

Comments
 (0)