Skip to content

Commit

Permalink
need to have a think about how to get renderables
Browse files Browse the repository at this point in the history
  • Loading branch information
tadgem committed Jun 30, 2024
1 parent 8aa3206 commit 3347b24
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 235 deletions.
268 changes: 33 additions & 235 deletions examples/pipeline-abstraction/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@
#include "ImGui/lvk_extensions.h"
using namespace lvk;

class Renderable
{
public:
VkDescriptorSet& m_DescriptorSet;
VkPipelineLayout& m_PipelineLayout;

Renderable(VkDescriptorSet& descriptorSet, VkPipelineLayout& pipelineLayout) :
m_DescriptorSet(descriptorSet), m_PipelineLayout(pipelineLayout)
{

}
virtual void RecordGraphicsCommands(VkCommandBuffer& cmd) = 0;
};

class MeshRenderable : public Renderable
{
public:
Expand Down Expand Up @@ -63,7 +49,7 @@ struct Pipeline
Vector<Material> m_PipelineMaterials;
Vector<VkPipelineData> m_PipelineDatas;

Optional<const Framebuffer*> m_OutputFramebuffer;
Optional<Framebuffer*> m_OutputFramebuffer;
Optional<LvkIm3dViewState> m_Im3dState;

Optional<VkRecordCommandCallback> m_CommandCallback;
Expand All @@ -79,7 +65,7 @@ struct Pipeline
m_OutputFramebuffer = &fb;
}

const Framebuffer* GetOutputFramebuffer()
Framebuffer* GetOutputFramebuffer()
{
if (m_OutputFramebuffer.has_value())
{
Expand Down Expand Up @@ -112,23 +98,6 @@ struct Pipeline
};

struct ViewData
{
// most of this can be encapsulated in a view pipeline
Framebuffer m_GBuffer;
Framebuffer m_LightPassFB;
Material m_LightPassMaterial;

VkPipeline m_GBufferPipeline, m_LightPassPipeline;
VkPipelineLayout m_GBufferPipelineLayout, m_LightPassPipelineLayour;

LvkIm3dViewState m_Im3dState;
VkExtent2D m_CurrentResolution{ 1920, 1080 };

Camera m_Camera;
Mesh m_ViewQuad;
};

struct ViewDataV2
{
Pipeline m_Pipeline;
View m_View;
Expand Down Expand Up @@ -315,52 +284,7 @@ Pipeline CreateViewPipeline(VulkanAPI& vk, LvkIm3dState& im3dState, ShaderProgra

ViewData CreateView(VulkanAPI& vk, LvkIm3dState im3dState, ShaderProgram gbufferProg, ShaderProgram lightPassProg)
{
Framebuffer gbuffer{};
gbuffer.AddColourAttachment(vk, ResolutionScale::Full, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
gbuffer.AddColourAttachment(vk, ResolutionScale::Full, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
gbuffer.AddColourAttachment(vk, ResolutionScale::Full, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
gbuffer.AddDepthAttachment(vk, ResolutionScale::Full, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_ASPECT_DEPTH_BIT);
gbuffer.Build(vk);

Framebuffer finalImage{};
finalImage.AddColourAttachment(vk, ResolutionScale::Full, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
finalImage.Build(vk);

Material lightPassMat = Material::Create(vk, lightPassProg);

lightPassMat.SetColourAttachment(vk, "positionBufferSampler", gbuffer, 1);
lightPassMat.SetColourAttachment(vk, "normalBufferSampler", gbuffer, 2);
lightPassMat.SetColourAttachment(vk, "colourBufferSampler", gbuffer, 0);

// create gbuffer pipeline
VkPipelineLayout gbufferPipelineLayout;
VkPipeline gbufferPipeline = vk.CreateRasterizationGraphicsPipeline(
gbufferProg,
Vector<VkVertexInputBindingDescription>{VertexDataPosNormalUv::GetBindingDescription() },
VertexDataPosNormalUv::GetAttributeDescriptions(),
gbuffer.m_RenderPass,
vk.m_SwapChainImageExtent.width, vk.m_SwapChainImageExtent.height,
VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, false,
VK_COMPARE_OP_LESS, gbufferPipelineLayout, 3);

// create present graphics pipeline
// Pipeline stage?
VkPipelineLayout lightPassPipelineLayout;
VkPipeline pipeline = vk.CreateRasterizationGraphicsPipeline(
lightPassProg,
Vector<VkVertexInputBindingDescription>{VertexDataPosUv::GetBindingDescription() },
VertexDataPosUv::GetAttributeDescriptions(),
finalImage.m_RenderPass,
vk.m_SwapChainImageExtent.width, vk.m_SwapChainImageExtent.height,
VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, false,
VK_COMPARE_OP_LESS, lightPassPipelineLayout);

auto im3dViewState = AddIm3dForViewport(vk, im3dState, finalImage.m_RenderPass, false);
Pipeline pipeline = CreateViewPipeline(vk, im3dState, gbufferProg, lightPassProg);

static Vector<VertexDataPosUv> screenQuadVerts = {
{ { -1.0f, -1.0f , 0.0f}, { 0.0f, 0.0f } },
Expand All @@ -383,12 +307,7 @@ ViewData CreateView(VulkanAPI& vk, LvkIm3dState im3dState, ShaderProgram gbuffer

Mesh screenQuad{ vertBuffer, vertAlloc, indexBuffer, indexAlloc, 6 };

return { gbuffer, finalImage, lightPassMat, gbufferPipeline, pipeline, gbufferPipelineLayout, lightPassPipelineLayout, im3dViewState , {1920, 1080}, {}, screenQuad };
}

void FreeView(VulkanAPI& vk, ViewData& view)
{
FreeIm3dViewport(vk, view.m_Im3dState);
return { pipeline, {{}, {1920, 1080}}, screenQuad };
}

static Transform g_Transform;
Expand All @@ -408,23 +327,23 @@ void UpdateRenderItemUniformBuffer(VulkanAPI& vk, Material& renderItemMaterial)

void UpdateViewData(VulkanAPI& vk, ViewData* view, DeferredLightData& lightData)
{
glm::quat qPitch = glm::angleAxis(glm::radians(-view->m_Camera.Rotation.x), glm::vec3(1, 0, 0));
glm::quat qYaw = glm::angleAxis(glm::radians(view->m_Camera.Rotation.y), glm::vec3(0, 1, 0));
glm::quat qPitch = glm::angleAxis(glm::radians(-view->m_View.m_Camera.Rotation.x), glm::vec3(1, 0, 0));
glm::quat qYaw = glm::angleAxis(glm::radians(view->m_View.m_Camera.Rotation.y), glm::vec3(0, 1, 0));
// omit roll
glm::quat Rotation = qPitch * qYaw;
Rotation = glm::normalize(Rotation);
glm::mat4 rotate = glm::mat4_cast(Rotation);
glm::mat4 translate = glm::mat4(1.0f);
translate = glm::translate(translate, -view->m_Camera.Position);
translate = glm::translate(translate, -view->m_View.m_Camera.Position);

view->m_Camera.View = rotate * translate;
view->m_View.m_Camera.View = rotate * translate;
if (vk.m_SwapChainImageExtent.width > 0 || vk.m_SwapChainImageExtent.height)
{
view->m_Camera.Proj = glm::perspective(glm::radians(45.0f),(float) view->m_CurrentResolution.width / (float)view->m_CurrentResolution.height, 0.1f, 10000.0f);
view->m_Camera.Proj[1][1] *= -1;
view->m_View.m_Camera.Proj = glm::perspective(glm::radians(45.0f),(float) view->m_View.m_CurrentResolution.width / (float)view->m_View.m_CurrentResolution.height, 0.1f, 10000.0f);
view->m_View.m_Camera.Proj[1][1] *= -1;
}

view->m_LightPassMaterial.SetBuffer(vk.GetFrameIndex(), 0, 3, lightData);
view->m_Pipeline.m_PipelineMaterials[0].SetBuffer(vk.GetFrameIndex(), 0, 3, lightData);
}

void RecordCommandBuffersV2(VulkanAPI_SDL& vk, Vector<ViewData*> views, RenderModel& model, Mesh& screenQuad, LvkIm3dState& im3dState, DeferredLightData& lightData)
Expand All @@ -435,6 +354,9 @@ void RecordCommandBuffersV2(VulkanAPI_SDL& vk, Vector<ViewData*> views, RenderMo
{ {1.0f, 1.0f, 0.0f}, {1.0, 1.0} },
{ {-1.0f, 1.0f, 0.0f}, {0.0f, 1.0} }
};

Vector<Renderable*> renderables{};

vk.RecordGraphicsCommands([&](VkCommandBuffer& commandBuffer, uint32_t frameIndex) {
{
Array<VkClearValue, 4> clearValues{};
Expand Down Expand Up @@ -476,133 +398,15 @@ void RecordCommandBuffersV2(VulkanAPI_SDL& vk, Vector<ViewData*> views, RenderMo

for (auto& view : views)
{
struct PCViewData
if (view->m_Pipeline.m_CommandCallback.has_value())
{
glm::mat4 view;
glm::mat4 proj;
};


PCViewData pcData{ view->m_Camera.View, view->m_Camera.Proj };
VkExtent2D viewExtent = view->m_CurrentResolution;

// update screen quad
{
auto max = vk.GetMaxFramebufferResolution();
float w = static_cast<float>((float) viewExtent.width / (float) max.width);
float h = static_cast<float>((float) viewExtent.height / (float) max.height);

Vector<VertexDataPosUv> newScreenQuadData = {
{ { -1.0f, -1.0f , 0.0f}, { 0.0f, 0.0f } },
{ {1.0f, -1.0f, 0.0f}, {w, 0.0f} },
{ {1.0f, 1.0f, 0.0f}, {w, h} },
{ {-1.0f, 1.0f, 0.0f}, {0.0f, h} }
};
auto& draw_commands = view->m_Pipeline.m_CommandCallback.value();

vkCmdUpdateBuffer(commandBuffer, view->m_ViewQuad.m_VertexBuffer, 0, 4 * sizeof(VertexDataPosUv), &newScreenQuadData[0]);
//todo: convert meshes to renderables
draw_commands(commandBuffer, frameIndex, view->m_View, view->m_ViewQuad, {});
}

{
Array<VkClearValue, 4> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[1].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[2].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[3].depthStencil = { 1.0f, 0 };

VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = view->m_GBuffer.m_RenderPass;
renderPassInfo.framebuffer = view->m_GBuffer.m_SwapchainFramebuffers[frameIndex];
renderPassInfo.renderArea.offset = { 0,0 };
renderPassInfo.renderArea.extent = viewExtent;

renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();

vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, view->m_GBufferPipeline);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.x = 0.0f;
viewport.width = static_cast<float>(viewExtent.width);
viewport.height = static_cast<float>(viewExtent.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

VkRect2D scissor{};
scissor.offset = { 0,0 };
scissor.extent = VkExtent2D{
static_cast<uint32_t>(viewExtent.width) ,
static_cast<uint32_t>(viewExtent.height)
};

vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdPushConstants(commandBuffer, view->m_GBufferPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PCViewData), &pcData);

for (int i = 0; i < model.m_RenderItems.size(); i++)
{
MeshEx& mesh = model.m_RenderItems[i].m_Mesh;

VkBuffer vertexBuffers[]{ mesh.m_VertexBuffer };
VkDeviceSize sizes[] = { 0 };

vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, sizes);
vkCmdBindIndexBuffer(commandBuffer, mesh.m_IndexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, view->m_GBufferPipelineLayout, 0, 1, &model.m_RenderItems[i].m_Material.m_DescriptorSets[0].m_Sets[frameIndex], 0, nullptr);
vkCmdDrawIndexed(commandBuffer, mesh.m_IndexCount, 1, 0, 0, 0);
}
vkCmdEndRenderPass(commandBuffer);
}

Array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[1].depthStencil = { 1.0f, 0 };

VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = view->m_LightPassFB.m_RenderPass;
renderPassInfo.framebuffer = view->m_LightPassFB.m_SwapchainFramebuffers[frameIndex];
renderPassInfo.renderArea.offset = { 0,0 };
renderPassInfo.renderArea.extent = viewExtent;

renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();

vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, view->m_LightPassPipeline);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.x = 0.0f;
viewport.width = static_cast<float>(viewExtent.width);
viewport.height = static_cast<float>(viewExtent.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

VkRect2D scissor{};
scissor.offset = { 0,0 };
scissor.extent = VkExtent2D{
static_cast<uint32_t>(viewExtent.width) ,
static_cast<uint32_t>(viewExtent.height)
};

// issue with lighting pass is that uvs are just 0,0 -> 1,1
// meaning the entire buffer will be resampled
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdPushConstants(commandBuffer, view->m_LightPassPipelineLayour, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PCViewData), &pcData);
VkDeviceSize sizes[] = { 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &view->m_ViewQuad.m_VertexBuffer, sizes);
vkCmdBindIndexBuffer(commandBuffer, view->m_ViewQuad.m_IndexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, view->m_LightPassPipelineLayour, 0, 1, &view->m_LightPassMaterial.m_DescriptorSets[0].m_Sets[frameIndex], 0, nullptr);
vkCmdDrawIndexed(commandBuffer, view->m_ViewQuad.m_IndexCount, 1, 0, 0, 0);

DrawIm3d(vk, commandBuffer, frameIndex, im3dState, view->m_Im3dState, view->m_Camera.Proj * view->m_Camera.View, viewExtent.width, viewExtent.height);
vkCmdEndRenderPass(commandBuffer);
}
}
);
});
}

RenderModel CreateRenderModelGbuffer(VulkanAPI& vk, const String& modelPath, ShaderProgram& shader)
Expand Down Expand Up @@ -658,28 +462,25 @@ void OnImGui(VulkanAPI& vk, DeferredLightData& lightDataCpu, Vector<ViewData*> v
auto extent = ImGui::GetContentRegionAvail();
auto max = vk.GetMaxFramebufferExtent();
ImVec2 uv1 = { extent.x / max.width, extent.y / max.height };
auto& image = views[0]->m_LightPassFB.m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];

// auto& image = views[0]->m_LightPassFB.m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];
auto& image = views[0]->m_Pipeline.GetOutputFramebuffer()->m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];
ImGuiX::Image(image, extent, { 0,0 }, uv1);
DrawIm3dTextListsImGuiAsChild(Im3d::GetTextDrawLists(), Im3d::GetTextDrawListCount(), (float)views[0]->m_CurrentResolution.width, (float)views[0]->m_CurrentResolution.height, views[0]->m_Camera.Proj * views[0]->m_Camera.View);
views[0]->m_CurrentResolution = { (uint32_t)extent.x, (uint32_t)extent.y };
DrawIm3dTextListsImGuiAsChild(Im3d::GetTextDrawLists(), Im3d::GetTextDrawListCount(), (float)views[0]->m_View.m_CurrentResolution.width, (float)views[0]->m_View.m_CurrentResolution.height, views[0]->m_View.m_Camera.Proj * views[0]->m_View.m_Camera.View);
views[0]->m_View.m_CurrentResolution = { (uint32_t)extent.x, (uint32_t)extent.y };

}
ImGui::End();

if (ImGui::Begin("View 2"))
{
// size needs to be the current resolution
// uv0 will likely always be 0,0
// uv1 needs to be MaxResolution / CurrentResolution;
auto extent = ImGui::GetContentRegionAvail();
auto max = vk.GetMaxFramebufferExtent();
ImVec2 uv1 = { extent.x / max.width, extent.y / max.height };
auto& image = views[1]->m_LightPassFB.m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];

// auto& image = views[0]->m_LightPassFB.m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];
auto& image = views[1]->m_Pipeline.GetOutputFramebuffer()->m_ColourAttachments[0].m_AttachmentSwapchainImages[vk.GetFrameIndex()];
ImGuiX::Image(image, extent, { 0,0 }, uv1);
DrawIm3dTextListsImGuiAsChild(Im3d::GetTextDrawLists(), Im3d::GetTextDrawListCount(), (float)views[1]->m_CurrentResolution.width, (float)views[1]->m_CurrentResolution.height, views[1]->m_Camera.Proj * views[1]->m_Camera.View);
views[1]->m_CurrentResolution = { (uint32_t)extent.x, (uint32_t)extent.y };
DrawIm3dTextListsImGuiAsChild(Im3d::GetTextDrawLists(), Im3d::GetTextDrawListCount(), (float)views[1]->m_View.m_CurrentResolution.width, (float)views[1]->m_View.m_CurrentResolution.height, views[1]->m_View.m_Camera.Proj * views[1]->m_View.m_Camera.View);
views[1]->m_View.m_CurrentResolution = { (uint32_t)extent.x, (uint32_t)extent.y };

}
ImGui::End();
Expand All @@ -694,13 +495,13 @@ void OnImGui(VulkanAPI& vk, DeferredLightData& lightDataCpu, Vector<ViewData*> v

ImGui::Separator();

ImGui::DragFloat3("Cam 1 Position", &views[0]->m_Camera.Position[0]);
ImGui::DragFloat3("Cam 1 Euler Rotation", &views[0]->m_Camera.Rotation[0]);
ImGui::DragFloat3("Cam 1 Position", &views[0]->m_View.m_Camera.Position[0]);
ImGui::DragFloat3("Cam 1 Euler Rotation", &views[0]->m_View.m_Camera.Rotation[0]);

ImGui::Separator();

ImGui::DragFloat3("Cam 2 Position", &views[1]->m_Camera.Position[0]);
ImGui::DragFloat3("Cam 2 Euler Rotation", &views[1]->m_Camera.Rotation[0]);
ImGui::DragFloat3("Cam 2 Position", &views[1]->m_View.m_Camera.Position[0]);
ImGui::DragFloat3("Cam 2 Euler Rotation", &views[1]->m_View.m_Camera.Rotation[0]);
}
ImGui::End();

Expand Down Expand Up @@ -789,9 +590,9 @@ int main() {
ShaderProgram lightPassProg = ShaderProgram::Create(vk, "shaders/lights.vert.spv", "shaders/lights.frag.spv");

ViewData viewA = CreateView(vk, im3dState, gbufferProg, lightPassProg);
viewA.m_Camera.Position = { -40.0, 10.0f, 30.0f };
viewA.m_View.m_Camera.Position = { -40.0, 10.0f, 30.0f };
ViewData viewB = CreateView(vk, im3dState, gbufferProg, lightPassProg);
viewB.m_Camera.Position = { 30.0, 0.0f, -20.0f };
viewB.m_View.m_Camera.Position = { 30.0, 0.0f, -20.0f };

Vector<ViewData*> views{ &viewA, &viewB };

Expand Down Expand Up @@ -829,9 +630,6 @@ int main() {
gbufferProg.Free(vk);
lightPassProg.Free(vk);

FreeView(vk, viewA);
FreeView(vk, viewB);

m.Free(vk);

FreeIm3d(vk, im3dState);
Expand Down
Loading

0 comments on commit 3347b24

Please sign in to comment.