Skip to content

Commit f090e10

Browse files
committed
Add overdraw counter image
1 parent 598ae5a commit f090e10

8 files changed

Lines changed: 172 additions & 22 deletions

File tree

engine/assets/shaders/shared.slangh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ struct PushConstants
44
float4x4 proj;
55
};
66

7+
struct UniformBuffer
8+
{
9+
float2 viewport;
10+
};
11+
712
struct VertexOutput
813
{
914
float4 position : SV_Position;

engine/assets/shaders/test.frag.slang

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@
33
[[vk::binding(1, 0)]]
44
Sampler2D textures[];
55

6+
[[vk::binding(5, 1)]]
7+
RWTexture2D<uint> overdraw;
8+
9+
10+
[[vk::binding(3, 0)]]
11+
ConstantBuffer<UniformBuffer> ubo;
12+
613
[shader("fragment")]
7-
float3 main(VertexOutput input) : SV_Target
14+
float3 main(VertexOutput input, float4 pos : SV_Position) : SV_Target
815
{
916
float3 color = input.color;
1017

@@ -16,5 +23,7 @@ float3 main(VertexOutput input) : SV_Target
1623

1724
color *= max(0.3, cosTheta);
1825

26+
InterlockedAdd(overdraw[uint2(pos.xy)], 1);
27+
1928
return color;
2029
}

engine/src/render/vk_device.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ void VulkanDevice::CreateDevice()
8282
enabled_features13_ = {};
8383

8484
enabled_features_.features.multiDrawIndirect = available_features_.features.multiDrawIndirect;
85+
enabled_features_.features.fragmentStoresAndAtomics = available_features_.features.fragmentStoresAndAtomics;
8586

8687
enabled_features11_.shaderDrawParameters = available_features11_.shaderDrawParameters;
8788

engine/src/render/vk_frame.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,15 @@ void VulkanFrame::RecreateFrameImages(const uint32_t width, const uint32_t heigh
101101
.aspect_flags = vk::ImageAspectFlagBits::eColor,
102102
};
103103
render_image_ = std::make_unique<VulkanImage>(render_image_info, allocator_->get());
104+
105+
overdraw_image_ = nullptr;
106+
const ImageInfo overdraw_image_info{
107+
.width = width,
108+
.height = height,
109+
.format = vk::Format::eR32Uint,
110+
.usage =
111+
vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
112+
.aspect_flags = vk::ImageAspectFlagBits::eColor,
113+
};
114+
overdraw_image_ = std::make_unique<VulkanImage>(overdraw_image_info, allocator_->get());
104115
}

engine/src/render/vk_frame.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class VulkanFrame
3434

3535
[[nodiscard]] VulkanBuffer* DrawCount() const { return draw_count_.get(); }
3636

37+
[[nodiscard]] VulkanImage* Overdraw() const { return overdraw_image_.get(); }
38+
3739
[[nodiscard]] VulkanBuffer* DebugLineVertexBuffer() const { return debug_line_vertex_buffer_.get(); }
3840

3941
[[nodiscard]] vk::Semaphore ImageAvailable() const { return image_available_.get(); }
@@ -52,6 +54,7 @@ class VulkanFrame
5254

5355
std::unique_ptr<VulkanImage> depth_image_;
5456
std::unique_ptr<VulkanImage> render_image_;
57+
std::unique_ptr<VulkanImage> overdraw_image_;
5558

5659
std::unique_ptr<VulkanBuffer> object_buffer_;
5760
std::unique_ptr<VulkanBuffer> indirect_buffer_;

engine/src/render/vk_image.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,37 @@ void VulkanImage::TransitionImageLayout(const vk::Image image, const vk::Command
4747
barrier.dstAccessMask = vk::AccessFlagBits2::eTransferWrite;
4848
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe;
4949
barrier.dstStageMask = vk::PipelineStageFlagBits2::eTransfer;
50+
} else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eGeneral)
51+
{
52+
barrier.srcAccessMask = vk::AccessFlagBits2::eNone;
53+
barrier.dstAccessMask = vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite;
54+
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe;
55+
barrier.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader;
5056
} else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eTransferSrcOptimal)
5157
{
5258
barrier.srcAccessMask = vk::AccessFlagBits2::eNone;
5359
barrier.dstAccessMask = vk::AccessFlagBits2::eTransferRead;
5460
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe;
5561
barrier.dstStageMask = vk::PipelineStageFlagBits2::eTransfer;
62+
} else if (old_layout == vk::ImageLayout::eTransferDstOptimal && new_layout == vk::ImageLayout::eGeneral)
63+
{
64+
barrier.srcAccessMask = vk::AccessFlagBits2::eTransferWrite;
65+
barrier.dstAccessMask = vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite;
66+
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTransfer;
67+
barrier.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader;
68+
} else if (old_layout == vk::ImageLayout::eGeneral && new_layout == vk::ImageLayout::eTransferDstOptimal)
69+
{
70+
barrier.srcAccessMask = vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eShaderWrite;
71+
barrier.dstAccessMask = vk::AccessFlagBits2::eTransferWrite;
72+
barrier.srcStageMask = vk::PipelineStageFlagBits2::eFragmentShader;
73+
barrier.dstStageMask = vk::PipelineStageFlagBits2::eTransfer;
74+
} else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eDepthAttachmentOptimal)
75+
{
76+
barrier.srcAccessMask = vk::AccessFlagBits2::eNone;
77+
barrier.dstAccessMask =
78+
vk::AccessFlagBits2::eDepthStencilAttachmentRead | vk::AccessFlagBits2::eDepthStencilAttachmentWrite;
79+
barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe;
80+
barrier.dstStageMask = vk::PipelineStageFlagBits2::eEarlyFragmentTests;
5681
} else if (old_layout == vk::ImageLayout::eTransferDstOptimal &&
5782
new_layout == vk::ImageLayout::eShaderReadOnlyOptimal)
5883
{

engine/src/render/vk_renderer.cpp

Lines changed: 110 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ constexpr uint32_t kStorageBufferCount = 20;
4242
constexpr uint32_t kStorageImageCount = 20;
4343
constexpr uint32_t kCombinedImageSamplerCount = 20;
4444
constexpr uint32_t kMaxTextures = 20;
45+
constexpr uint32_t kUniformBufferCount = 20;
4546

4647
VulkanRenderer::VulkanRenderer(Window* window, ResourceManager& resource_manager, EventManager& event_manager) :
4748
window_(window), event_manager_(&event_manager)
@@ -125,7 +126,8 @@ VulkanRenderer::VulkanRenderer(Window* window, ResourceManager& resource_manager
125126
descriptor_pool_info.pool_sizes = {
126127
{.type = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = kCombinedImageSamplerCount},
127128
{.type = vk::DescriptorType::eStorageBuffer, .descriptorCount = kStorageBufferCount},
128-
{.type = vk::DescriptorType::eStorageImage, .descriptorCount = kStorageImageCount}};
129+
{.type = vk::DescriptorType::eStorageImage, .descriptorCount = kStorageImageCount},
130+
{.type = vk::DescriptorType::eUniformBuffer, .descriptorCount = kUniformBufferCount}};
129131

130132
descriptor_pool_ = std::make_unique<VulkanDescriptorPool>(device_->get(), descriptor_pool_info);
131133

@@ -159,27 +161,35 @@ VulkanRenderer::VulkanRenderer(Window* window, ResourceManager& resource_manager
159161
.binding = 4,
160162
.descriptorType = vk::DescriptorType::eStorageImage,
161163
.descriptorCount = 1,
162-
.stageFlags = vk::ShaderStageFlagBits::eCompute}},
164+
.stageFlags = vk::ShaderStageFlagBits::eCompute},
165+
vk::DescriptorSetLayoutBinding{// Overdraw
166+
.binding = 5,
167+
.descriptorType = vk::DescriptorType::eStorageImage,
168+
.descriptorCount = 1,
169+
.stageFlags = vk::ShaderStageFlagBits::eFragment}},
163170
std::vector<vk::DescriptorBindingFlags>{}, vk::DescriptorSetLayoutCreateFlags{});
164171

165172
static_descriptor_set_layout_ = std::make_unique<VulkanDescriptorSetLayout>(
166173
device_->get(),
167-
std::vector{
168-
vk::DescriptorSetLayoutBinding{
169-
// Mesh infos
170-
.binding = 0,
171-
.descriptorType = vk::DescriptorType::eStorageBuffer,
172-
.descriptorCount = 1,
173-
.stageFlags = vk::ShaderStageFlagBits::eCompute | vk::ShaderStageFlagBits::eVertex},
174-
vk::DescriptorSetLayoutBinding{
175-
// Textures
176-
.binding = 1,
177-
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
178-
.descriptorCount = kMaxTextures,
179-
.stageFlags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute},
180-
},
181-
std::vector<vk::DescriptorBindingFlags>{vk::DescriptorBindingFlags{},
182-
vk::DescriptorBindingFlagBits::ePartiallyBound},
174+
std::vector{vk::DescriptorSetLayoutBinding{
175+
// Mesh infos
176+
.binding = 0,
177+
.descriptorType = vk::DescriptorType::eStorageBuffer,
178+
.descriptorCount = 1,
179+
.stageFlags = vk::ShaderStageFlagBits::eCompute | vk::ShaderStageFlagBits::eVertex},
180+
vk::DescriptorSetLayoutBinding{
181+
// Textures
182+
.binding = 1,
183+
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
184+
.descriptorCount = kMaxTextures,
185+
.stageFlags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute},
186+
vk::DescriptorSetLayoutBinding{// ubo
187+
.binding = 3,
188+
.descriptorType = vk::DescriptorType::eUniformBuffer,
189+
.descriptorCount = 1,
190+
.stageFlags = vk::ShaderStageFlagBits::eFragment}},
191+
std::vector<vk::DescriptorBindingFlags>{
192+
vk::DescriptorBindingFlags{}, vk::DescriptorBindingFlagBits::ePartiallyBound, vk::DescriptorBindingFlags{}},
183193
vk::DescriptorSetLayoutCreateFlags{});
184194

185195
static_descriptor_set_ = descriptor_pool_->allocate(static_descriptor_set_layout_->get());
@@ -580,6 +590,20 @@ void VulkanRenderer::run(glm::mat4 world, float fov)
580590
constexpr vk::DebugUtilsLabelEXT label_info2{.pLabelName = "MeshPass"};
581591
cmd.beginDebugUtilsLabelEXT(label_info2, instance_->getDynamicLoader());
582592

593+
VulkanImage::TransitionImageLayout(frame->Overdraw()->get(), cmd, vk::ImageLayout::eGeneral,
594+
vk::ImageLayout::eTransferDstOptimal);
595+
596+
vk::ImageSubresourceRange range{.aspectMask = vk::ImageAspectFlagBits::eColor,
597+
.baseMipLevel = 0,
598+
.levelCount = 1,
599+
.baseArrayLayer = 0,
600+
.layerCount = 1};
601+
vk::ClearColorValue clearValue{std::array<float, 4>{0.f, 0.f, 0.f, 0.f}};
602+
cmd.clearColorImage(frame->Overdraw()->get(), vk::ImageLayout::eTransferDstOptimal, clearValue, range);
603+
604+
VulkanImage::TransitionImageLayout(frame->Overdraw()->get(), cmd, vk::ImageLayout::eTransferDstOptimal,
605+
vk::ImageLayout::eGeneral);
606+
583607
VulkanImage::TransitionImageLayout(frame->RenderImage()->get(), cmd, vk::ImageLayout::eTransferSrcOptimal,
584608
vk::ImageLayout::eColorAttachmentOptimal);
585609

@@ -1049,10 +1073,77 @@ void VulkanRenderer::RecreateSwapChain()
10491073
aspect_ratio_ = static_cast<float>(width) / static_cast<float>(height);
10501074
}
10511075

1052-
void VulkanRenderer::RecreateFrameImages(const uint32_t width, const uint32_t height) const
1076+
void VulkanRenderer::RecreateFrameImages(const uint32_t width, const uint32_t height)
10531077
{
1078+
std::vector<vk::WriteDescriptorSet> writes;
1079+
std::vector<vk::DescriptorImageInfo> image_infos;
1080+
1081+
image_infos.reserve(frames_.size());
1082+
1083+
vk::DescriptorBufferInfo ubo_buffer_info{.buffer = nullptr, .offset = 0, .range = vk::WholeSize};
1084+
1085+
if (!uniform_buffer_)
1086+
{
1087+
constexpr BufferInfo info{.size = sizeof(UniformBuffer),
1088+
.usage = vk::BufferUsageFlagBits::eUniformBuffer,
1089+
.memoryUsage = VMA_MEMORY_USAGE_CPU_TO_GPU,
1090+
.memoryFlags = VMA_ALLOCATION_CREATE_MAPPED_BIT};
1091+
uniform_buffer_ = std::make_unique<VulkanBuffer>(info, allocator_->get(), device_.get());
1092+
1093+
ubo_buffer_info.buffer = uniform_buffer_->get();
1094+
const vk::WriteDescriptorSet ubo_write{.dstSet = static_descriptor_set_,
1095+
.dstBinding = 3,
1096+
.dstArrayElement = 0,
1097+
.descriptorCount = 1,
1098+
.descriptorType = vk::DescriptorType::eUniformBuffer,
1099+
.pBufferInfo = &ubo_buffer_info};
1100+
writes.reserve(frames_.size() * 2);
1101+
1102+
writes.push_back(ubo_write);
1103+
} else
1104+
{
1105+
writes.reserve(frames_.size());
1106+
}
1107+
1108+
uniform_buffer_->map();
1109+
auto* ubo = uniform_buffer_->GetMappedDataAs<UniformBuffer>();
1110+
ubo->viewport.x = static_cast<float>(width);
1111+
ubo->viewport.y = static_cast<float>(height);
1112+
uniform_buffer_->unmap();
1113+
10541114
for (const auto& frame: frames_)
10551115
{
10561116
frame->RecreateFrameImages(width, height);
1117+
1118+
image_infos.push_back(
1119+
{.sampler = nullptr, .imageView = frame->Overdraw()->view(), .imageLayout = vk::ImageLayout::eGeneral});
1120+
1121+
const vk::WriteDescriptorSet write{.dstSet = frame->DescriptorSet(),
1122+
.dstBinding = 5,
1123+
.dstArrayElement = 0,
1124+
.descriptorCount = 1,
1125+
.descriptorType = vk::DescriptorType::eStorageImage,
1126+
.pImageInfo = &image_infos.back()};
1127+
1128+
writes.push_back(write);
1129+
}
1130+
1131+
device_->get().updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
1132+
1133+
auto cmd = util::BeginSingleTimeCommandBuffer(*graphics_pool_);
1134+
for (const auto& image: swap_chain_->images())
1135+
{
1136+
VulkanImage::TransitionImageLayout(image, cmd, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR);
1137+
}
1138+
1139+
for (const auto& frame: frames_)
1140+
{
1141+
VulkanImage::TransitionImageLayout(frame->RenderImage()->get(), cmd, vk::ImageLayout::eUndefined,
1142+
vk::ImageLayout::eTransferSrcOptimal);
1143+
VulkanImage::TransitionImageLayout(frame->DepthImage()->get(), cmd, vk::ImageLayout::eUndefined,
1144+
vk::ImageLayout::eDepthAttachmentOptimal);
1145+
VulkanImage::TransitionImageLayout(frame->Overdraw()->get(), cmd, vk::ImageLayout::eUndefined,
1146+
vk::ImageLayout::eGeneral);
10571147
}
1148+
util::EndSingleTimeCommandBuffer(cmd, device_->GraphicsQueue(), *graphics_pool_);
10581149
}

engine/src/render/vk_renderer.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ struct ComputePushConstant
5555
uint32_t render_object_count;
5656
};
5757

58+
struct UniformBuffer
59+
{
60+
glm::vec2 viewport;
61+
};
62+
5863
struct Vertex
5964
{
6065
glm::vec3 position;
@@ -109,7 +114,7 @@ class VulkanRenderer
109114
void EndFrame(uint32_t image_index);
110115

111116
void RecreateSwapChain();
112-
void RecreateFrameImages(uint32_t width, uint32_t height) const;
117+
void RecreateFrameImages(uint32_t width, uint32_t height);
113118

114119
static constexpr uint32_t max_frames_in_flight_ = 2;
115120

@@ -165,7 +170,7 @@ class VulkanRenderer
165170
std::vector<TextureInfo> texture_infos_;
166171
std::vector<std::unique_ptr<VulkanImage>> texture_images_;
167172
vk::UniqueSampler texture_sampler_;
168-
173+
std::unique_ptr<VulkanBuffer> uniform_buffer_;
169174

170175
Window *window_ = nullptr;
171176
EventManager *event_manager_ = nullptr;

0 commit comments

Comments
 (0)