Added object system using SSBOs

This commit is contained in:
connellpaxton 2024-02-10 17:40:56 -05:00
parent d706da69e9
commit 13fff8cfad
12 changed files with 185 additions and 15 deletions

View File

@ -2,6 +2,7 @@
#include <Renderer/Shader.hpp> #include <Renderer/Shader.hpp>
#include <Renderer/RenderPass.hpp> #include <Renderer/RenderPass.hpp>
#include <Renderer/UniformBuffer.hpp> #include <Renderer/UniformBuffer.hpp>
#include <Renderer/ShaderBuffer.hpp>
#include <Renderer/VertexBuffer.hpp> #include <Renderer/VertexBuffer.hpp>
#include <Resources/Texture.hpp> #include <Resources/Texture.hpp>
@ -191,6 +192,21 @@ void GraphicsPipeline::update(uint32_t binding, const UniformBuffer& uni) {
}, nullptr); }, nullptr);
} }
void GraphicsPipeline::update(uint32_t binding, const ShaderBuffer& ssbo) {
auto buff_info = vk::DescriptorBufferInfo{
.buffer = ssbo,
.offset = 0,
.range = vk::WholeSize,
};
dev.updateDescriptorSets(vk::WriteDescriptorSet {
.dstSet = desc_set,
.dstBinding = binding,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageBuffer,
.pBufferInfo = &buff_info,
}, nullptr);
}
void GraphicsPipeline::update(uint32_t binding, const Texture& tex) { void GraphicsPipeline::update(uint32_t binding, const Texture& tex) {
auto tex_info = vk::DescriptorImageInfo { auto tex_info = vk::DescriptorImageInfo {
.sampler = tex.sampler, .sampler = tex.sampler,

View File

@ -4,6 +4,7 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
struct Shader; struct Shader;
struct ShaderBuffer;
struct UniformBuffer; struct UniformBuffer;
struct VertexBuffer; struct VertexBuffer;
struct RenderPass; struct RenderPass;
@ -27,6 +28,7 @@ struct GraphicsPipeline {
/* create overload for every type of object we need to update */ /* create overload for every type of object we need to update */
void update(uint32_t binding, const UniformBuffer& uni); void update(uint32_t binding, const UniformBuffer& uni);
void update(uint32_t binding, const ShaderBuffer& ssbo);
void update(uint32_t binding, const Texture& tex); void update(uint32_t binding, const Texture& tex);
~GraphicsPipeline(); ~GraphicsPipeline();

View File

@ -191,9 +191,9 @@ Renderer::Renderer(Window& win) : win(win) {
command_buffer = std::make_unique<CommandBuffer>(dev, queue_family); command_buffer = std::make_unique<CommandBuffer>(dev, queue_family);
uniform_buffer = std::make_unique<UniformBuffer>(phys_dev, dev); uniform_buffer = std::make_unique<UniformBuffer>(phys_dev, dev);
shader_buffer = std::make_unique<ShaderBuffer>(phys_dev, dev);
textures = createResources({ textures = createResources({
"assets/textures/oil.jpg",
"assets/textures/eire.png", "assets/textures/eire.png",
}); });
@ -205,13 +205,14 @@ Renderer::Renderer(Window& win) : win(win) {
std::vector<vk::DescriptorSetLayoutBinding> bindings = { std::vector<vk::DescriptorSetLayoutBinding> bindings = {
uniform_buffer->binding(0), uniform_buffer->binding(0),
textures[0].binding(1), textures[0].binding(1),
shader_buffer->binding(2),
}; };
vertex_buffer = std::make_unique<VertexBuffer>(phys_dev, dev, 6); vertex_buffer = std::make_unique<VertexBuffer>(phys_dev, dev, 6);
/* simple quad */ /* simple quad */
vertex_buffer->upload(std::vector<Vertex> { vertex_buffer->upload(std::vector<Vertex> {
{ { -1.0,-1.0 } }, { { -1.0, -1.0 } },
{ { -1.0, 1.0 } }, { { -1.0, 1.0 } },
{ { 1.0, 1.0 } }, { { 1.0, 1.0 } },
{ { 1.0, 1.0 } }, { { 1.0, 1.0 } },
@ -219,10 +220,16 @@ Renderer::Renderer(Window& win) : win(win) {
{ { -1.0,-1.0 } }, { { -1.0,-1.0 } },
}); });
shader_buffer->upload(std::vector<Object> {
{ { 0.0, -10.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0, 0.0 }, 0, Shape::SPHERE },
{ { 0.0, -12.0, 0.0, 0.0 }, { 10.0, 1.0, 10.0, 0.0 }, 1, Shape::BOX },
});
pipeline = std::make_unique<GraphicsPipeline>(dev, shaders, swapchain->extent, *render_pass, bindings, *vertex_buffer); pipeline = std::make_unique<GraphicsPipeline>(dev, shaders, swapchain->extent, *render_pass, bindings, *vertex_buffer);
pipeline->update(0, *uniform_buffer); pipeline->update(0, *uniform_buffer);
pipeline->update(1, textures[1]); pipeline->update(1, textures[0]);
pipeline->update(2, *shader_buffer);
for (auto& shader : shaders) for (auto& shader : shaders)
shader.cleanup(); shader.cleanup();
@ -328,6 +335,7 @@ void Renderer::draw() {
.time = time, .time = time,
.viewport = glm::vec4(viewport.width, viewport.y, 0.0, 0.0), .viewport = glm::vec4(viewport.width, viewport.y, 0.0, 0.0),
.cam_dir = cam.dir(), .cam_dir = cam.dir(),
.n_objects = 2,
}); });
command_buffer->bind(*pipeline); command_buffer->bind(*pipeline);
@ -335,6 +343,7 @@ void Renderer::draw() {
command_buffer->command_buffer.setScissor(0, scissor); command_buffer->command_buffer.setScissor(0, scissor);
command_buffer->bind(pipeline->layout, pipeline->desc_set); command_buffer->bind(pipeline->layout, pipeline->desc_set);
command_buffer->bind(*vertex_buffer); command_buffer->bind(*vertex_buffer);
shader_buffer->objects[0].center.y += glm::sin(time)/10.0;
command_buffer->command_buffer.draw(6, 1, 0, 0); command_buffer->command_buffer.draw(6, 1, 0, 0);
/* draw User Interface stuff */ /* draw User Interface stuff */
@ -346,7 +355,6 @@ void Renderer::draw() {
command_buffer->end(); command_buffer->end();
vk::PipelineStageFlags stage_flags = vk::PipelineStageFlagBits::eColorAttachmentOutput; vk::PipelineStageFlags stage_flags = vk::PipelineStageFlagBits::eColorAttachmentOutput;
/* submit our command buffer to the queue */ /* submit our command buffer to the queue */
@ -386,7 +394,6 @@ void Renderer::present() {
} }
frame++; frame++;
time += 0.0167f * speed * static_cast<float>(running);
} }
Renderer::~Renderer() { Renderer::~Renderer() {
@ -395,6 +402,7 @@ Renderer::~Renderer() {
ui.reset(); ui.reset();
uniform_buffer.reset(); uniform_buffer.reset();
shader_buffer.reset();
vertex_buffer.reset(); vertex_buffer.reset();
pipeline.reset(); pipeline.reset();

View File

@ -8,6 +8,7 @@
#include <Renderer/Swapchain.hpp> #include <Renderer/Swapchain.hpp>
#include <Renderer/CommandBuffer.hpp> #include <Renderer/CommandBuffer.hpp>
#include <Renderer/RenderPass.hpp> #include <Renderer/RenderPass.hpp>
#include <Renderer/ShaderBuffer.hpp>
#include <Scene/Camera.hpp> #include <Scene/Camera.hpp>
@ -48,6 +49,7 @@ struct Renderer {
std::unique_ptr<GraphicsPipeline> pipeline; std::unique_ptr<GraphicsPipeline> pipeline;
/* just holds single quad */ /* just holds single quad */
std::unique_ptr<ShaderBuffer> shader_buffer;
std::unique_ptr<VertexBuffer> vertex_buffer; std::unique_ptr<VertexBuffer> vertex_buffer;
std::unique_ptr<UniformBuffer> uniform_buffer; std::unique_ptr<UniformBuffer> uniform_buffer;

View File

@ -0,0 +1,3 @@
#include <Renderer/ShaderBuffer.hpp>

52
Renderer/ShaderBuffer.hpp Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include <util/glsl_types.hpp>
#include <Scene/Object.hpp>
#include <Memory/Buffer.hpp>
using namespace glsl;
/* Wrapper for SSBO */
struct ShaderBuffer {
ShaderBuffer(vk::PhysicalDevice phys_dev, vk::Device dev, const size_t n_objects = 0x1000) : phys_dev(phys_dev), dev(dev), n_objects(n_objects) {
buffer = std::make_unique<Buffer>(
phys_dev, dev, n_objects * sizeof(Object),
vk::BufferUsageFlagBits::eStorageBuffer,
vk::MemoryPropertyFlagBits::eHostCoherent
| vk::MemoryPropertyFlagBits::eHostVisible
);
objects = reinterpret_cast<Object*>(buffer->p);
}
vk::PhysicalDevice phys_dev;
vk::Device dev;
size_t n_objects;
Object* objects;
std::unique_ptr<Buffer> buffer;
operator vk::Buffer&() const {
return *buffer;
}
inline vk::DescriptorSetLayoutBinding binding(uint32_t binding, vk::ShaderStageFlags stages = vk::ShaderStageFlagBits::eFragment) {
return vk::DescriptorSetLayoutBinding {
.binding = binding,
.descriptorType = vk::DescriptorType::eStorageBuffer,
.descriptorCount = 1,
.stageFlags = stages,
.pImmutableSamplers = nullptr,
};
}
inline void upload(const std::vector<Object>& scene) {
buffer->upload(reinterpret_cast<const uint8_t*>(scene.data()));
}
~ShaderBuffer() {
buffer.reset();
}
};

View File

@ -9,6 +9,10 @@
#include <memory> #include <memory>
#include <util/glsl_types.hpp>
using namespace glsl;
/* Uniform: /* Uniform:
* *
layout (set = 0, binding = 0) uniform Matrices { layout (set = 0, binding = 0) uniform Matrices {
@ -16,14 +20,16 @@ layout (set = 0, binding = 0) uniform Matrices {
float time; float time;
vec4 viewport; vec4 viewport;
vec3 cam_dir; vec3 cam_dir;
uint n_objects;
}; };
*/ */
struct UniformData { struct UniformData {
glm::vec3 cam_pos; vec3 cam_pos;
float time; float time;
glm::vec4 viewport; vec4 viewport;
glm::vec3 cam_dir; vec3 cam_dir;
uint n_objects;
}; };
struct UniformBuffer { struct UniformBuffer {

20
Scene/Object.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <util/glsl_types.hpp>
using namespace glsl;
enum Shape {
SPHERE,
BOX,
};
struct Object {
vec4 center;
vec4 dimensions;
uint id;
Shape shape;
float pad0;
float pad1;
};

View File

@ -5,15 +5,43 @@ layout (set = 0, binding = 0) uniform Matrices {
float time; float time;
vec4 viewport; vec4 viewport;
vec3 cam_dir; vec3 cam_dir;
uint n_objects;
};
/*
enum Shape {
SPHERE,
BOX,
};
*/
#define SPHERE 0
#define BOX 1
struct Object {
vec4 center;
vec4 dimensions;
uint id;
uint shape;
};
layout (set = 0, binding = 2) readonly buffer Objects {
Object objects[];
}; };
layout (location = 0) in vec2 pos; layout (location = 0) in vec2 pos;
layout (location = 0) out vec4 fragColor; layout (location = 0) out vec4 fragColor;
float opUnion(float v1, float v2) { /* joins two parts of a scene */
float op_union(float v1, float v2) {
return min(v1, v2); return min(v1, v2);
} }
/* subtracts sdf from scene */
float op_subtract(float v1, float v2) {
return max(v1, -v2);
}
float box(vec3 p, vec3 c, vec3 r) { float box(vec3 p, vec3 c, vec3 r) {
p -= c; p -= c;
vec3 q = abs(p) - r; vec3 q = abs(p) - r;
@ -24,9 +52,28 @@ float sphere(vec3 p, vec3 c, float r) {
return length(p-c) - r; return length(p-c) - r;
} }
float obj_to_sdf(vec3 p, uint n) {
switch(objects[n].shape) {
case SPHERE:
return sphere(p, objects[n].center.xyz, objects[n].dimensions.x);
break;
case BOX:
return box(p, objects[n].center.xyz, objects[n].dimensions.xyz);
break;
}
}
float sdf(vec3 pos) { float sdf(vec3 pos) {
float d = sphere(pos, vec3(0.0, 0.0, 0.0), 3.0); float d = 100000000.0;
d = opUnion(d, box(pos, vec3(0.0, -10.0, 0.0), vec3(10.0, 1.0, 10.0))); for(uint i = 0; i < n_objects; i++) {
d = op_union(d, obj_to_sdf(pos, i));
}
/*float dsphere = sphere(pos, vec3(0.0, 3.0*sin(time)-10.0, 0.0), 1.0);
float dbox = box(pos, vec3(0.0, -10.0, 0.0), vec3(10.0, 1.0, 10.0));
float dpellet = sphere(pos, vec3(0.0, 10.0*sin(time) - 10.0, 0.0), 0.1);
float d = op_union(op_subtract(dbox, dsphere), dpellet);*/
return d; return d;
} }
@ -57,8 +104,10 @@ void main() {
float d = raycast(dir); float d = raycast(dir);
vec3 point = cam_pos + dir * d; vec3 point = cam_pos + dir * d;
float c = 1.0-(length(point)*0.075);
if(d < 0.0) if(d < 0.0)
fragColor = vec4(0.0); fragColor = vec4(0.1);
else else
fragColor = vec4(mod(point.y, 1.0)); fragColor = vec4(c);
} }

Binary file not shown.

View File

@ -80,9 +80,10 @@ int main(int argc, char* argv[]) {
ren.present(); ren.present();
const auto t = frame_timer.read(); const auto t = frame_timer.read();
ren.ui->info.fps = 1000.0f / t; ren.ui->info.fps = 1000.0f / t;
ren.time += t / 1000.0 * ren.speed * static_cast<float>(ren.running);
while (frame_timer.read() < 16.60) /*while (frame_timer.read() < 16.60)
; ;*/
} }
} catch (const std::string& e) { } catch (const std::string& e) {

11
util/glsl_types.hpp Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <glm/glm.hpp>
namespace glsl {
typedef uint32_t uint;
typedef glm::vec1 vec1;
typedef glm::vec2 vec2;
typedef glm::vec3 vec3;
typedef glm::vec4 vec4;
}