Skip to content

Commit 880e37b

Browse files
committed
common descriptor pool and shadowmapping begin
1 parent 4c998bb commit 880e37b

File tree

7 files changed

+390
-161
lines changed

7 files changed

+390
-161
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ add_library(ReactorLib STATIC
6666
src/vulkan/MeshGenerators.cpp
6767
src/core/ModelIO.hpp
6868
src/core/ModelIO.cpp
69+
src/vulkan/ShadowMapping.hpp
70+
src/vulkan/ShadowMapping.cpp
6971
)
7072

7173
target_compile_definitions(ReactorLib PUBLIC GLM_ENABLE_EXPERIMENTAL)

src/vulkan/DescriptorSet.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
namespace reactor {
1010

11-
DescriptorSet::DescriptorSet(vk::Device device, size_t framesInFlight, const std::vector<vk::DescriptorSetLayoutBinding> &bindings)
12-
: m_device(device)
11+
DescriptorSet::DescriptorSet(vk::Device device, vk::DescriptorPool pool, size_t framesInFlight, const std::vector<vk::DescriptorSetLayoutBinding> &bindings)
12+
: m_device(device), m_pool(pool)
1313
{
1414
// create a descriptor set layout
1515
vk::DescriptorSetLayoutCreateInfo layoutInfo({}, bindings);
@@ -20,13 +20,6 @@ namespace reactor {
2020
poolSizes.push_back({binding.descriptorType, static_cast<uint32_t>(framesInFlight)});
2121
}
2222

23-
vk::DescriptorPoolCreateInfo poolInfo(
24-
vk::DescriptorPoolCreateFlags(),
25-
static_cast<uint32_t>(framesInFlight),
26-
static_cast<uint32_t>(poolSizes.size()), poolSizes.data());
27-
28-
m_pool = device.createDescriptorPool(poolInfo);
29-
3023
// allocate one set per frame
3124
std::vector<vk::DescriptorSetLayout> layouts(framesInFlight, m_layout);
3225
vk::DescriptorSetAllocateInfo allocInfo(m_pool, layouts);
@@ -35,7 +28,6 @@ namespace reactor {
3528
}
3629

3730
DescriptorSet::~DescriptorSet() {
38-
if (m_pool) m_device.destroyDescriptorPool(m_pool);
3931
if (m_layout) m_device.destroyDescriptorSetLayout(m_layout);
4032
}
4133

src/vulkan/DescriptorSet.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace reactor {
1212
public:
1313
DescriptorSet(
1414
vk::Device device,
15+
vk::DescriptorPool pool,
1516
size_t framesInFlight,
1617
const std::vector<vk::DescriptorSetLayoutBinding>& bindings);
1718

src/vulkan/ShadowMapping.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#include "ShadowMapping.hpp"
2+
3+
#include "VulkanRenderer.hpp"
4+
5+
namespace reactor
6+
{
7+
8+
ShadowMapping::ShadowMapping(VulkanRenderer& renderer, uint32_t resolution)
9+
: m_renderer(renderer), m_resolution(resolution), m_shadowMapView(VK_NULL_HANDLE),
10+
m_shadowMapSampler(VK_NULL_HANDLE)
11+
{
12+
createResources();
13+
createDescriptors();
14+
createPipeline();
15+
}
16+
17+
ShadowMapping::~ShadowMapping()
18+
{
19+
// if you own any Vulkan handles directly, clean them up here
20+
21+
auto device = m_renderer.device();
22+
device.destroyImageView(m_shadowMapView);
23+
device.destroySampler(m_shadowMapSampler);
24+
}
25+
26+
void ShadowMapping::createResources()
27+
{
28+
auto device = m_renderer.device();
29+
auto& allocator = m_renderer.allocator();
30+
31+
vk::ImageCreateInfo imageInfo = {};
32+
imageInfo.imageType = vk::ImageType::e2D;
33+
imageInfo.format = vk::Format::eD32Sfloat;
34+
imageInfo.extent = vk::Extent3D{m_resolution, m_resolution, 1};
35+
imageInfo.mipLevels = 1;
36+
imageInfo.arrayLayers = 1;
37+
imageInfo.samples = vk::SampleCountFlagBits::e1;
38+
imageInfo.tiling = vk::ImageTiling::eOptimal;
39+
imageInfo.usage = vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eSampled;
40+
imageInfo.sharingMode = vk::SharingMode::eExclusive;
41+
imageInfo.initialLayout = vk::ImageLayout::eUndefined;
42+
43+
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY;
44+
45+
m_shadowMap = std::make_unique<Image>(allocator, imageInfo, memoryUsage);
46+
47+
// 2. Create image view
48+
vk::ImageViewCreateInfo viewInfo{};
49+
viewInfo.image = m_shadowMap->get();
50+
viewInfo.viewType = vk::ImageViewType::e2D;
51+
viewInfo.format = vk::Format::eD32Sfloat;
52+
viewInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eDepth;
53+
viewInfo.subresourceRange.baseMipLevel = 0;
54+
viewInfo.subresourceRange.levelCount = 1;
55+
viewInfo.subresourceRange.baseArrayLayer = 0;
56+
viewInfo.subresourceRange.layerCount = 1;
57+
58+
m_shadowMapView = device.createImageView(viewInfo);
59+
60+
// 3. Create sampler
61+
vk::SamplerCreateInfo samplerInfo{};
62+
samplerInfo.magFilter = vk::Filter::eLinear;
63+
samplerInfo.minFilter = vk::Filter::eLinear;
64+
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eNearest;
65+
samplerInfo.addressModeU = vk::SamplerAddressMode::eClampToBorder;
66+
samplerInfo.addressModeV = vk::SamplerAddressMode::eClampToBorder;
67+
samplerInfo.addressModeW = vk::SamplerAddressMode::eClampToBorder;
68+
samplerInfo.borderColor = vk::BorderColor::eFloatOpaqueWhite;
69+
samplerInfo.compareEnable = VK_TRUE;
70+
samplerInfo.compareOp = vk::CompareOp::eLessOrEqual;
71+
72+
m_shadowMapSampler = device.createSampler(samplerInfo);
73+
74+
const size_t frameCount = 2;
75+
m_mvpBuffer.clear();
76+
m_mvpBuffer.reserve(frameCount);
77+
for (size_t i = 0; i < frameCount; ++i)
78+
{
79+
m_mvpBuffer.push_back(std::make_unique<Buffer>(m_renderer.allocator(), sizeof(glm::mat4), vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, "MVP Buffer"));
80+
}
81+
}
82+
83+
void ShadowMapping::createPipeline()
84+
{
85+
spdlog::info("Creating shadow mapping pipeline");
86+
87+
auto device = m_renderer.device();
88+
89+
std::vector<vk::DescriptorSetLayout> setLayouts;
90+
if (m_descriptors)
91+
{
92+
setLayouts.push_back(m_descriptors->getLayout());
93+
}
94+
95+
Pipeline::Builder builder(device);
96+
97+
builder
98+
.setVertexShader("../resources/shaders/triangle.vert.spv")
99+
// No fragment shader, we only want depth output
100+
.setVertexInputFromVertex()
101+
.setDepthAttachment(vk::Format::eD32Sfloat, true) // depth test and write enabled
102+
.setDescriptorSetLayouts(setLayouts)
103+
.setMultisample(4)
104+
.setFrontFace(vk::FrontFace::eClockwise) // Match main geometry pipeline
105+
.addPushContantRange(vk::ShaderStageFlagBits::eVertex, 0, sizeof(glm::mat4));
106+
107+
m_depthPassPipeline = builder.build();
108+
}
109+
110+
void ShadowMapping::createDescriptors()
111+
{
112+
spdlog::info("Creating shadow mapping descriptors");
113+
vk::Device device = m_renderer.device();
114+
size_t framesInFlight = 2;
115+
116+
// Descriptor set bindings: UBO for light's MVP
117+
std::vector<vk::DescriptorSetLayoutBinding> bindings = {
118+
{ 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }
119+
// Add more if you want—for example for a sampler or shadow map
120+
};
121+
122+
// Use your DescriptorSet abstraction to handle layout & Vulkan allocation
123+
m_descriptors = std::make_unique<DescriptorSet>(device, m_renderer.descriptorPool(), framesInFlight, bindings);
124+
125+
// Now update each descriptor set with the corresponding per-frame UBO
126+
for (size_t i = 0; i < framesInFlight; ++i)
127+
{
128+
vk::DescriptorBufferInfo uboInfo{};
129+
uboInfo.buffer = m_mvpBuffer[i]->getHandle();
130+
uboInfo.offset = 0;
131+
uboInfo.range = sizeof(glm::mat4);
132+
133+
vk::WriteDescriptorSet writes{};
134+
writes.dstSet = m_descriptors->get(i);
135+
writes.dstBinding = 0;
136+
writes.dstArrayElement = 0;
137+
writes.descriptorType = vk::DescriptorType::eUniformBuffer;
138+
writes.descriptorCount = 1;
139+
writes.pBufferInfo = &uboInfo;
140+
141+
m_descriptors->updateSet({writes});
142+
}
143+
144+
}
145+
146+
} // namespace reactor

src/vulkan/ShadowMapping.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include "Buffer.hpp"
4+
#include "DescriptorSet.hpp"
5+
#include "Image.hpp"
6+
#include "Pipeline.hpp"
7+
#include <memory>
8+
#include <vulkan/vulkan.hpp>
9+
10+
namespace reactor
11+
{
12+
13+
class VulkanRenderer;
14+
15+
class ShadowMapping
16+
{
17+
public:
18+
explicit ShadowMapping(VulkanRenderer& renderer, uint32_t resolution = 2048);
19+
~ShadowMapping();
20+
21+
void recordShadowPass(vk::CommandBuffer cmd, size_t frameIndex);
22+
23+
vk::ImageView shadowMapView() const;
24+
vk::Sampler shadowMapSampler() const;
25+
vk::DescriptorSet shadowMapDescriptorSet(size_t frameIndex) const;
26+
27+
void setLightMatrix(const glm::mat4& lightMVP, size_t frameIndex);
28+
29+
uint32_t resolution() const
30+
{
31+
return m_resolution;
32+
}
33+
34+
private:
35+
void createResources();
36+
void createPipeline();
37+
void createDescriptors();
38+
39+
VulkanRenderer& m_renderer;
40+
uint32_t m_resolution;
41+
42+
// depth image, view, and sampler for shadow map
43+
std::unique_ptr<Image> m_shadowMap;
44+
vk::ImageView m_shadowMapView;
45+
vk::Sampler m_shadowMapSampler;
46+
47+
std::vector<std::unique_ptr<Buffer>> m_mvpBuffer;
48+
49+
std::unique_ptr<DescriptorSet> m_descriptors;
50+
51+
// Pipeline for depth pass
52+
std::unique_ptr<Pipeline> m_depthPassPipeline;
53+
};
54+
} // namespace reactor

0 commit comments

Comments
 (0)