586 lines
23 KiB
C++
586 lines
23 KiB
C++
// =============================================
|
|
// Aster: model_render.cpp
|
|
// Copyright (c) 2020-2024 Anish Bhobe
|
|
// =============================================
|
|
|
|
#include "buffer.h"
|
|
#include "constants.h"
|
|
#include "context.h"
|
|
#include "device.h"
|
|
#include "global.h"
|
|
#include "image.h"
|
|
#include "physical_device.h"
|
|
#include "pipeline.h"
|
|
#include "swapchain.h"
|
|
#include "window.h"
|
|
|
|
#include "frame.h"
|
|
#include "helpers.h"
|
|
#include "light_manager.h"
|
|
|
|
#include "gpu_resource_manager.h"
|
|
#include "gui.h"
|
|
#include "model_loader.h"
|
|
#include "pipeline_utils.h"
|
|
|
|
#include <EASTL/array.h>
|
|
#include <stb_image.h>
|
|
#include <tiny_gltf.h>
|
|
#include <filesystem>
|
|
|
|
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
|
constexpr auto MODEL_FILE = "model/DamagedHelmet.glb";
|
|
|
|
struct Camera
|
|
{
|
|
mat4 m_View;
|
|
mat4 m_Perspective;
|
|
vec4 m_Position;
|
|
};
|
|
|
|
struct CameraController
|
|
{
|
|
constexpr static vec3 UP = vec3(0.0f, 1.0f, 0.0f);
|
|
|
|
f32 m_Fov;
|
|
f32 m_Pitch;
|
|
f32 m_Yaw;
|
|
f32 m_AspectRatio;
|
|
|
|
Camera m_Camera;
|
|
|
|
CameraController(const vec3 &position, const vec3 &target, const f32 vFov, const f32 aspectRatio)
|
|
: m_Fov(vFov)
|
|
, m_Pitch{0.0f}
|
|
, m_Yaw{0.0f}
|
|
, m_AspectRatio{aspectRatio}
|
|
, m_Camera{
|
|
.m_View = lookAt(position, target, UP),
|
|
.m_Perspective = glm::perspective(vFov, aspectRatio, 0.1f, 100.0f),
|
|
.m_Position = vec4{0.0f, 2.0f, 2.0f, 1.0f},
|
|
}
|
|
{
|
|
}
|
|
|
|
void
|
|
SetAspectRatio(const f32 aspectRatio)
|
|
{
|
|
m_AspectRatio = aspectRatio;
|
|
m_Camera.m_Perspective = glm::perspective(m_Fov, aspectRatio, 0.1f, 100.0f);
|
|
}
|
|
|
|
void
|
|
SetPosition(const vec3 &position)
|
|
{
|
|
m_Camera.m_Position = vec4(position, 1.0f);
|
|
|
|
f32 cosPitch = cos(m_Pitch);
|
|
const vec3 target = vec3(sin(m_Yaw) * cosPitch, sin(m_Pitch), -cos(m_Yaw) * cosPitch);
|
|
m_Camera.m_View = lookAt(position, position + target, UP);
|
|
}
|
|
|
|
void
|
|
SetPitchYaw(f32 pitch, f32 yaw)
|
|
{
|
|
m_Pitch = pitch;
|
|
m_Yaw = yaw;
|
|
|
|
f32 cosPitch = cos(m_Pitch);
|
|
const vec3 target = vec3(sin(m_Yaw) * cosPitch, sin(m_Pitch), -cos(m_Yaw) * cosPitch);
|
|
const vec3 position = vec3{m_Camera.m_Position};
|
|
m_Camera.m_View = lookAt(position, position + target, UP);
|
|
}
|
|
};
|
|
|
|
int
|
|
main(int, char **)
|
|
{
|
|
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
|
|
|
Context context = {"ModelRender [WIP]", VERSION};
|
|
Window window = {"ModelRender [WIP] (Aster)", &context, {640, 480}};
|
|
|
|
PhysicalDevices physicalDevices = {&window, &context};
|
|
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
|
|
|
|
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
|
|
|
Features enabledDeviceFeatures = {
|
|
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
|
.m_Vulkan12Features =
|
|
{
|
|
.descriptorIndexing = true,
|
|
.shaderSampledImageArrayNonUniformIndexing = true,
|
|
.shaderStorageBufferArrayNonUniformIndexing = true,
|
|
.shaderStorageImageArrayNonUniformIndexing = true,
|
|
.descriptorBindingUniformBufferUpdateAfterBind = true, // Not related to Bindless
|
|
.descriptorBindingSampledImageUpdateAfterBind = true,
|
|
.descriptorBindingStorageImageUpdateAfterBind = true,
|
|
.descriptorBindingStorageBufferUpdateAfterBind = true,
|
|
.descriptorBindingPartiallyBound = true,
|
|
.runtimeDescriptorArray = true,
|
|
},
|
|
.m_Vulkan13Features =
|
|
{
|
|
.synchronization2 = true,
|
|
.dynamicRendering = true,
|
|
},
|
|
};
|
|
|
|
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
|
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
|
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
|
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
|
GpuResourceManager resourceManager = {&device, 1000};
|
|
|
|
ModelLoader modelLoader = {&resourceManager, commandQueue, queueAllocation.m_Family, queueAllocation.m_Family};
|
|
LightManager lightManager = LightManager{&resourceManager};
|
|
|
|
Model model = modelLoader.LoadModel(MODEL_FILE);
|
|
|
|
vk::Format attachmentFormat = vk::Format::eR8G8B8A8Srgb;
|
|
Pipeline pipeline = CreatePipeline(&device, attachmentFormat, &resourceManager);
|
|
|
|
//lightManager.AddDirectional(vec3(0.0f, -1.0f, 0.0f), {0.0f, 0.7f, 0.0f});
|
|
//lightManager.AddPoint(vec3{2.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 15.0f);
|
|
//lightManager.AddPoint(vec3{-2.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 15.0f);
|
|
|
|
lightManager.AddPoint(vec3{-5.0f, -5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f);
|
|
lightManager.AddPoint(vec3{5.0f, -5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f);
|
|
lightManager.AddPoint(vec3{-5.0f, 5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f);
|
|
lightManager.AddPoint(vec3{5.0f, 5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f);
|
|
|
|
lightManager.Update();
|
|
|
|
vk::DescriptorPool descriptorPool;
|
|
vk::DescriptorSet descriptorSet;
|
|
|
|
{
|
|
vk::DescriptorSetLayout descriptorSetLayout = pipeline.m_SetLayouts[1];
|
|
eastl::array poolSizes = {
|
|
vk::DescriptorPoolSize{
|
|
.type = vk::DescriptorType::eUniformBuffer,
|
|
.descriptorCount = 1,
|
|
},
|
|
};
|
|
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
|
.maxSets = 1, .poolSizeCount = Cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
|
|
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
|
|
|
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
|
.descriptorPool = descriptorPool,
|
|
.descriptorSetCount = 1,
|
|
.pSetLayouts = &descriptorSetLayout,
|
|
};
|
|
AbortIfFailed(device.m_Device.allocateDescriptorSets(&descriptorSetAllocateInfo, &descriptorSet));
|
|
}
|
|
|
|
vk::Extent2D internalResolution = {1920, 1080};
|
|
|
|
CameraController cameraController = {vec3{0.0f, 2.0f, 2.0f}, vec3{0.0f}, 70_deg,
|
|
Cast<f32>(swapchain.m_Extent.width) / Cast<f32>(swapchain.m_Extent.height)};
|
|
|
|
UniformBuffer ubo;
|
|
ubo.Init(&device, sizeof cameraController.m_Camera, "Camera UBO");
|
|
ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera);
|
|
vk::DescriptorBufferInfo descriptorBufferInfo = {
|
|
.buffer = ubo.m_Buffer,
|
|
.offset = 0,
|
|
.range = ubo.GetSize(),
|
|
};
|
|
eastl::array writeDescriptors = {
|
|
vk::WriteDescriptorSet{
|
|
.dstSet = descriptorSet,
|
|
.dstBinding = 0,
|
|
.dstArrayElement = 0,
|
|
.descriptorCount = 1,
|
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
|
.pBufferInfo = &descriptorBufferInfo,
|
|
},
|
|
};
|
|
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
|
|
|
|
resourceManager.Update();
|
|
|
|
// Persistent variables
|
|
vk::Viewport viewport = {
|
|
.x = 0,
|
|
.y = Cast<f32>(internalResolution.height),
|
|
.width = Cast<f32>(internalResolution.width),
|
|
.height = -Cast<f32>(internalResolution.height),
|
|
.minDepth = 0.0,
|
|
.maxDepth = 1.0,
|
|
};
|
|
|
|
vk::Rect2D scissor = {
|
|
.offset = {0, 0},
|
|
.extent = internalResolution,
|
|
};
|
|
|
|
vk::ImageSubresourceRange subresourceRange = {
|
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
.baseMipLevel = 0,
|
|
.levelCount = 1,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 1,
|
|
};
|
|
|
|
vk::ImageMemoryBarrier2 preRenderBarrier = {
|
|
.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe,
|
|
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
|
.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
|
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
|
.oldLayout = vk::ImageLayout::eUndefined,
|
|
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
.subresourceRange = subresourceRange,
|
|
};
|
|
vk::DependencyInfo preRenderDependencies = {
|
|
.imageMemoryBarrierCount = 1,
|
|
.pImageMemoryBarriers = &preRenderBarrier,
|
|
};
|
|
|
|
vk::ImageMemoryBarrier2 renderToBlitBarrier = {
|
|
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
|
.srcAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllTransfer,
|
|
.dstAccessMask = vk::AccessFlagBits2::eTransferRead,
|
|
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
|
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
.subresourceRange = subresourceRange,
|
|
};
|
|
vk::ImageMemoryBarrier2 acquireToTransferDstBarrier = {
|
|
.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe,
|
|
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllTransfer,
|
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
|
.oldLayout = vk::ImageLayout::eUndefined,
|
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
.subresourceRange = subresourceRange,
|
|
};
|
|
eastl::array postRenderBarriers = {
|
|
renderToBlitBarrier,
|
|
acquireToTransferDstBarrier,
|
|
};
|
|
vk::DependencyInfo postRenderDependencies = {
|
|
.imageMemoryBarrierCount = Cast<u32>(postRenderBarriers.size()),
|
|
.pImageMemoryBarriers = postRenderBarriers.data(),
|
|
};
|
|
|
|
vk::ImageMemoryBarrier2 transferDstToGuiRenderBarrier = {
|
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllTransfer,
|
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
|
.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
|
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
|
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
.subresourceRange = subresourceRange,
|
|
};
|
|
vk::DependencyInfo preGuiDependencies = {
|
|
.imageMemoryBarrierCount = 1,
|
|
.pImageMemoryBarriers = &transferDstToGuiRenderBarrier,
|
|
};
|
|
|
|
vk::ImageMemoryBarrier2 prePresentBarrier = {
|
|
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
|
.srcAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
|
.dstStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe,
|
|
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
|
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
|
.subresourceRange = subresourceRange,
|
|
};
|
|
vk::DependencyInfo prePresentDependencies = {
|
|
.imageMemoryBarrierCount = 1,
|
|
.pImageMemoryBarriers = &prePresentBarrier,
|
|
};
|
|
|
|
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
|
|
eastl::fixed_vector<DepthImage, MAX_FRAMES_IN_FLIGHT> depthImages(frameManager.m_FramesInFlight);
|
|
eastl::fixed_vector<AttachmentImage, MAX_FRAMES_IN_FLIGHT> attachmentImages(frameManager.m_FramesInFlight);
|
|
{
|
|
auto depthIter = depthImages.begin();
|
|
auto attachmentIter = attachmentImages.begin();
|
|
for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index)
|
|
{
|
|
auto name = fmt::format("Depth Frame{}", index);
|
|
depthIter->Init(&device, internalResolution, name.c_str());
|
|
|
|
name = fmt::format("Attachment0 Frame{}", index);
|
|
attachmentIter->Init(&device, internalResolution, attachmentFormat, name.c_str());
|
|
|
|
++depthIter;
|
|
++attachmentIter;
|
|
}
|
|
}
|
|
|
|
gui::Init(&context, &device, &window, swapchain.m_Format, Cast<u32>(swapchain.m_ImageViews.size()),
|
|
queueAllocation.m_Family, commandQueue);
|
|
bool rotating = false;
|
|
bool lockToScreen = true;
|
|
i32 height = Cast<i32>(internalResolution.height);
|
|
vec2 camPitchYaw = vec2(0.0f);
|
|
vec3 camPosition = cameraController.m_Camera.m_Position;
|
|
vk::Extent2D inputResolution = internalResolution;
|
|
|
|
swapchain.RegisterResizeCallback([&cameraController](vk::Extent2D extent) {
|
|
cameraController.SetAspectRatio(Cast<f32>(extent.width) / Cast<f32>(extent.height));
|
|
});
|
|
|
|
Time::Init();
|
|
|
|
INFO("Starting loop");
|
|
while (window.Poll())
|
|
{
|
|
Time::Update();
|
|
|
|
gui::StartBuild();
|
|
|
|
gui::Begin("Settings");
|
|
gui::Text("Window Resolution: %ux%u", swapchain.m_Extent.width, swapchain.m_Extent.height);
|
|
gui::Text("FrameBuffer Resolution %ux%u", internalResolution.width, internalResolution.height);
|
|
gui::Checkbox("Lock Resolution to Window", &lockToScreen);
|
|
if (!lockToScreen)
|
|
{
|
|
if (gui::InputInt("FrameBuffer Height", &height, 1, 10))
|
|
{
|
|
height = eastl::clamp(height, 64, 4320);
|
|
}
|
|
|
|
inputResolution.height = height;
|
|
inputResolution.width = Cast<i32>(cameraController.m_AspectRatio * Cast<f32>(inputResolution.height));
|
|
|
|
if (gui::Button("Change Resolution"))
|
|
{
|
|
if (inputResolution.width != internalResolution.width ||
|
|
inputResolution.height != internalResolution.height)
|
|
{
|
|
internalResolution = inputResolution;
|
|
viewport.width = Cast<f32>(internalResolution.width);
|
|
viewport.height = -Cast<f32>(internalResolution.height);
|
|
viewport.y = Cast<f32>(internalResolution.height);
|
|
scissor.extent = internalResolution;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (swapchain.m_Extent.width != internalResolution.width ||
|
|
swapchain.m_Extent.height != internalResolution.height)
|
|
{
|
|
internalResolution = swapchain.m_Extent;
|
|
viewport.width = Cast<f32>(internalResolution.width);
|
|
viewport.height = -Cast<f32>(internalResolution.height);
|
|
viewport.y = Cast<f32>(internalResolution.height);
|
|
scissor.extent = internalResolution;
|
|
}
|
|
}
|
|
gui::Separator();
|
|
gui::Text("Delta: %0.6f ms", 1000.0f * Time::m_Delta);
|
|
gui::Text("FPS: %0.6f", 1.0f / Time::m_Delta);
|
|
gui::Separator();
|
|
if (gui::DragFloat2("Camera Orientation", Recast<f32 *>(&camPitchYaw)))
|
|
{
|
|
cameraController.SetPitchYaw(glm::radians(camPitchYaw.x), glm::radians(camPitchYaw.y));
|
|
}
|
|
if (gui::InputFloat3("Camera Position", Recast<f32 *>(&camPosition)))
|
|
{
|
|
cameraController.SetPosition(camPosition);
|
|
}
|
|
gui::Checkbox("Rotate", &rotating);
|
|
if (gui::Button("Exit"))
|
|
{
|
|
window.RequestExit();
|
|
}
|
|
gui::End();
|
|
|
|
gui::EndBuild();
|
|
|
|
if (rotating)
|
|
{
|
|
model.SetModelTransform(
|
|
rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
|
|
}
|
|
model.Update();
|
|
ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera);
|
|
|
|
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window);
|
|
|
|
u32 imageIndex = currentFrame->m_ImageIdx;
|
|
vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex];
|
|
vk::ImageView currentSwapchainImageView = swapchain.m_ImageViews[imageIndex];
|
|
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
|
|
|
DepthImage *currentDepthImage = &depthImages[currentFrame->m_FrameIdx];
|
|
AttachmentImage *currentAttachment = &attachmentImages[currentFrame->m_FrameIdx];
|
|
|
|
if (currentAttachment->m_Extent.width != internalResolution.width ||
|
|
currentAttachment->m_Extent.height != internalResolution.height)
|
|
{
|
|
auto name = fmt::format("Depth Frame{}", currentFrame->m_FrameIdx);
|
|
currentDepthImage->Destroy(&device);
|
|
currentDepthImage->Init(&device, internalResolution, name.c_str());
|
|
|
|
name = fmt::format("Attachment0 Frame{}", currentFrame->m_FrameIdx);
|
|
currentAttachment->Destroy(&device);
|
|
currentAttachment->Init(&device, internalResolution, attachmentFormat, name.c_str());
|
|
}
|
|
|
|
vk::ImageView currentDepthImageView = currentDepthImage->m_View;
|
|
vk::Image currentImage = currentAttachment->m_Image;
|
|
vk::ImageView currentImageView = currentAttachment->m_View;
|
|
|
|
preRenderBarrier.image = currentImage;
|
|
postRenderBarriers[0].image = currentImage;
|
|
postRenderBarriers[1].image = currentSwapchainImage;
|
|
transferDstToGuiRenderBarrier.image = currentSwapchainImage;
|
|
prePresentBarrier.image = currentSwapchainImage;
|
|
|
|
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
|
AbortIfFailed(cmd.begin(&beginInfo));
|
|
|
|
cmd.pipelineBarrier2(&preRenderDependencies);
|
|
|
|
// Render
|
|
eastl::array attachmentInfos = {
|
|
vk::RenderingAttachmentInfo{
|
|
.imageView = currentImageView,
|
|
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
|
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
|
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 1.0f},
|
|
},
|
|
};
|
|
|
|
vk::RenderingAttachmentInfo depthAttachment = {
|
|
.imageView = currentDepthImageView,
|
|
.imageLayout = vk::ImageLayout::eDepthAttachmentOptimal,
|
|
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
|
.storeOp = vk::AttachmentStoreOp::eDontCare,
|
|
.clearValue = vk::ClearDepthStencilValue{.depth = 1.0f, .stencil = 0},
|
|
};
|
|
|
|
vk::RenderingInfo renderingInfo = {
|
|
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
|
|
.layerCount = 1,
|
|
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
|
|
.pColorAttachments = attachmentInfos.data(),
|
|
.pDepthAttachment = &depthAttachment,
|
|
};
|
|
|
|
cmd.beginRendering(&renderingInfo);
|
|
|
|
cmd.setViewport(0, 1, &viewport);
|
|
cmd.setScissor(0, 1, &scissor);
|
|
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1,
|
|
&resourceManager.m_DescriptorSet, 0, nullptr);
|
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr);
|
|
|
|
cmd.bindIndexBuffer(model.m_IndexBuffer.m_Buffer, 0, vk::IndexType::eUint32);
|
|
|
|
u32 pcbOffset = 0;
|
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof model.m_Handles,
|
|
&model.m_Handles);
|
|
pcbOffset += sizeof model.m_Handles;
|
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, pcbOffset, sizeof lightManager.m_MetaInfo,
|
|
&lightManager.m_MetaInfo);
|
|
pcbOffset += sizeof lightManager.m_MetaInfo;
|
|
|
|
for (auto &prim : model.m_MeshPrimitives)
|
|
{
|
|
u32 innerPcbOffset = pcbOffset;
|
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
|
sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
|
|
innerPcbOffset += sizeof prim.m_MaterialIdx;
|
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
|
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
|
innerPcbOffset += sizeof prim.m_TransformIdx;
|
|
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
|
|
}
|
|
|
|
cmd.endRendering();
|
|
|
|
cmd.pipelineBarrier2(&postRenderDependencies);
|
|
|
|
vk::ImageBlit blitRegion = {
|
|
.srcSubresource =
|
|
{
|
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
.mipLevel = 0,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 1,
|
|
},
|
|
.srcOffsets =
|
|
std::array{
|
|
vk::Offset3D{0, 0, 0},
|
|
ToOffset3D(currentAttachment->m_Extent),
|
|
},
|
|
.dstSubresource =
|
|
{
|
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
.mipLevel = 0,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = 1,
|
|
},
|
|
.dstOffsets =
|
|
std::array{
|
|
vk::Offset3D{0, 0, 0},
|
|
vk::Offset3D{Cast<i32>(swapchain.m_Extent.width), Cast<i32>(swapchain.m_Extent.height), 1},
|
|
},
|
|
};
|
|
cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage,
|
|
postRenderBarriers[1].newLayout, 1, &blitRegion, vk::Filter::eLinear);
|
|
|
|
cmd.pipelineBarrier2(&preGuiDependencies);
|
|
|
|
gui::Draw(cmd, swapchain.m_Extent, currentSwapchainImageView);
|
|
|
|
cmd.pipelineBarrier2(&prePresentDependencies);
|
|
|
|
AbortIfFailed(cmd.end());
|
|
|
|
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
|
vk::SubmitInfo submitInfo = {
|
|
.waitSemaphoreCount = 1,
|
|
.pWaitSemaphores = ¤tFrame->m_ImageAcquireSem,
|
|
.pWaitDstStageMask = &waitDstStage,
|
|
.commandBufferCount = 1,
|
|
.pCommandBuffers = &cmd,
|
|
.signalSemaphoreCount = 1,
|
|
.pSignalSemaphores = ¤tFrame->m_RenderFinishSem,
|
|
};
|
|
AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
|
|
|
|
currentFrame->Present(commandQueue, &swapchain, &window);
|
|
}
|
|
|
|
AbortIfFailed(device.m_Device.waitIdle());
|
|
|
|
gui::Destroy(&device);
|
|
|
|
for (auto &depthImage : depthImages)
|
|
{
|
|
depthImage.Destroy(&device);
|
|
}
|
|
for (auto &attachmentImage : attachmentImages)
|
|
{
|
|
attachmentImage.Destroy(&device);
|
|
}
|
|
ubo.Destroy(&device);
|
|
device.m_Device.destroy(descriptorPool, nullptr);
|
|
|
|
return 0;
|
|
}
|