Archived
1
Fork 0

Fix compile issues on Vulkan, make render targets work in editor

This commit is contained in:
redstrate 2021-02-17 00:47:05 -05:00
parent 9b0404dff7
commit 1f98e19819
11 changed files with 120 additions and 94 deletions

View file

@ -758,7 +758,7 @@ void Engine::render(const int index) {
_imgui->render(0);
}
GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer();
GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer(true);
_app->render(commandbuffer);

View file

@ -360,7 +360,7 @@ public:
// misc operations
virtual GFXSize get_alignment(const GFXSize size) { return size; }
virtual GFXCommandBuffer* acquire_command_buffer() { return nullptr; }
virtual GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use = false) { return nullptr; }
virtual void submit([[maybe_unused]] GFXCommandBuffer* command_buffer,
[[maybe_unused]] const int window = -1) {}

View file

@ -4,7 +4,8 @@ set(HEADERS
src/gfx_vulkan_pipeline.hpp
src/gfx_vulkan_texture.hpp
src/gfx_vulkan_framebuffer.hpp
src/gfx_vulkan_renderpass.hpp)
src/gfx_vulkan_renderpass.hpp
src/gfx_vulkan_commandbuffer.hpp)
find_package(Vulkan REQUIRED)

View file

@ -57,7 +57,7 @@ public:
// misc operations
GFXSize get_alignment(const GFXSize size) override;
GFXCommandBuffer* acquire_command_buffer() override;
GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use = false) override;
void submit(GFXCommandBuffer* command_buffer, const int identifier) override;

View file

@ -16,6 +16,7 @@
#include "file.hpp"
#include "log.hpp"
#include "utility.hpp"
#include "gfx_vulkan_commandbuffer.hpp"
void* windowNativeHandle;
@ -709,13 +710,13 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
VkShaderModule vertex_module = VK_NULL_HANDLE, fragment_module = VK_NULL_HANDLE;
const bool has_vertex_stage = !info.shaders.vertex_path.empty() || !info.shaders.vertex_src.empty();
const bool has_fragment_stage = !info.shaders.fragment_path.empty() || !info.shaders.fragment_src.empty();
const bool has_vertex_stage = !info.shaders.vertex_src.empty();
const bool has_fragment_stage = !info.shaders.fragment_src.empty();
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
if (has_vertex_stage) {
const bool vertex_use_shader_source = info.shaders.vertex_path.empty();
const bool vertex_use_shader_source = !info.shaders.vertex_src.is_path();
if (vertex_use_shader_source) {
auto vertex_shader_vector = info.shaders.vertex_src.as_bytecode();
@ -723,13 +724,14 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
vertex_module = createShaderModule(vertex_shader_vector.data(), vertex_shader_vector.size() * sizeof(uint32_t));
}
else {
auto vertex_shader = file::open(file::internal_domain / (std::string(info.shaders.vertex_path) + ".spv"), true);
auto vertex_shader = file::open(file::internal_domain / (info.shaders.vertex_src.as_path().string() + ".spv"), true);
vertex_shader->read_all();
vertex_module = createShaderModule(vertex_shader->cast_data<uint32_t>(), vertex_shader->size());
}
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_path);
if(!vertex_use_shader_source)
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_src.as_path().string());
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@ -741,7 +743,7 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
}
if (has_fragment_stage) {
const bool fragment_use_shader_source = info.shaders.fragment_path.empty();
const bool fragment_use_shader_source = !info.shaders.fragment_src.is_path();
if (fragment_use_shader_source) {
auto fragment_shader_vector = info.shaders.fragment_src.as_bytecode();
@ -749,13 +751,14 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
fragment_module = createShaderModule(fragment_shader_vector.data(), fragment_shader_vector.size() * sizeof(uint32_t));
}
else {
auto fragment_shader = file::open(file::internal_domain / (std::string(info.shaders.fragment_path) + ".spv"), true);
auto fragment_shader = file::open(file::internal_domain / (info.shaders.fragment_src.as_path().string() + ".spv"), true);
fragment_shader->read_all();
fragment_module = createShaderModule(fragment_shader->cast_data<uint32_t>(), fragment_shader->size());
}
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)fragment_module, info.shaders.fragment_path);
if(!fragment_use_shader_source)
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)fragment_module, info.shaders.fragment_src.as_path().string());
VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@ -979,10 +982,7 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->handle);
if (info.label.empty())
pipeline->label = std::string(info.shaders.vertex_path) + std::string(info.shaders.fragment_path);
else
pipeline->label = info.label;
pipeline->label = info.label;
name_object(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipeline->handle, pipeline->label);
name_object(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)pipeline->layout, pipeline->label);
@ -998,19 +998,39 @@ GFXSize GFXVulkan::get_alignment(GFXSize size) {
return (size + minUboAlignment / 2) & ~int(minUboAlignment - 1);
}
GFXCommandBuffer* GFXVulkan::acquire_command_buffer() {
return new GFXCommandBuffer();
GFXCommandBuffer* GFXVulkan::acquire_command_buffer(bool for_presentation_use) {
GFXVulkanCommandBuffer* cmdbuf = new GFXVulkanCommandBuffer();
if(!for_presentation_use) {
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = commandPool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
vkAllocateCommandBuffers(device, &info, &cmdbuf->handle);
}
return cmdbuf;
}
void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
uint32_t imageIndex = 0;
if(identifier != -1) {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
uint32_t imageIndex = 0;
VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
return;
VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
return;
}
VkCommandBuffer cmd = VK_NULL_HANDLE;
VkCommandBuffer& cmd = commandBuffers[currentFrame];
GFXVulkanCommandBuffer* cmdbuf = (GFXVulkanCommandBuffer*)command_buffer;
if(cmdbuf->handle != VK_NULL_HANDLE)
cmd = cmdbuf->handle;
else
cmd = commandBuffers[currentFrame];
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -1240,41 +1260,50 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
vkEndCommandBuffer(cmd);
// submit
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if(identifier == -1) {
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmd;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmd;
VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &inFlightFences[currentFrame]);
if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS)
return;
// present
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = { swapchain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(presentQueue, &presentInfo);
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
} else {
// submit
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmd;
VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &inFlightFences[currentFrame]);
if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS)
return;
// present
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = { swapchain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(presentQueue, &presentInfo);
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
}
const char* GFXVulkan::get_name() {

View file

@ -0,0 +1,10 @@
#pragma once
#include <vulkan/vulkan.h>
#include "gfx_commandbuffer.hpp"
class GFXVulkanCommandBuffer : public GFXCommandBuffer {
public:
VkCommandBuffer handle = VK_NULL_HANDLE;
};

View file

@ -3,6 +3,7 @@
#include <string_view>
#include <vector>
#include <cmath>
#include <functional>
#include "pass.hpp"
#include "matrix.hpp"
@ -63,7 +64,7 @@ public:
void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, int index);
void render_screen(GFXCommandBuffer* commandBuffer, ui::Screen* screen, prism::Extent extent, ControllerContinuity& continuity, RenderScreenOptions options = RenderScreenOptions());
void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, ControllerContinuity& continuity);
void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, RenderTarget& target, ControllerContinuity& continuity);
void create_mesh_pipeline(Material& material);
@ -121,7 +122,6 @@ public:
private:
void createDummyTexture();
void create_render_target_resources(RenderTarget& target);
void createMeshPipeline();
void createPostPipeline();
void createFontPipeline();
void createSkyPipeline();
@ -134,10 +134,7 @@ private:
std::vector<std::unique_ptr<RenderTarget>> render_targets;
ui::Screen* current_screen = nullptr;
// mesh
GFXBuffer* sceneBuffer = nullptr;
// sky
GFXPipeline* skyPipeline = nullptr;

View file

@ -5,6 +5,7 @@
class GFXTexture;
class GFXFramebuffer;
class GFXBuffer;
class RenderTarget {
public:
@ -20,7 +21,10 @@ public:
GFXTexture* offscreenDepthTexture = nullptr;
GFXFramebuffer* offscreenFramebuffer = nullptr;
// mesh
GFXBuffer* sceneBuffer = nullptr;
// smaa
GFXTexture* edge_texture = nullptr;
GFXTexture* blend_texture = nullptr;

View file

@ -112,7 +112,6 @@ Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
offscreenRenderPass = gfx->create_render_pass(renderPassInfo);
createMeshPipeline();
createFontPipeline();
createSkyPipeline();
}
@ -251,28 +250,25 @@ void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->set_render_pass(beginInfo);
const auto& cameras = scene->get_all<Camera>();
for(auto& [obj, camera] : cameras) {
const int actual_width = render_extent.width / cameras.size();
for(auto& [obj, camera] : cameras) {
const bool requires_limited_perspective = render_options.enable_depth_of_field;
if(requires_limited_perspective) {
camera.perspective = transform::perspective(radians(camera.fov), static_cast<float>(actual_width) / static_cast<float>(render_extent.height), camera.near, 100.0f);
camera.perspective = transform::perspective(radians(camera.fov), static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height), camera.near, 100.0f);
} else {
camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast<float>(actual_width) / static_cast<float>(render_extent.height), camera.near);
camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height), camera.near);
}
camera.view = inverse(scene->get<Transform>(obj).model);
Viewport viewport = {};
viewport.x = (actual_width * 0);
viewport.width = actual_width;
viewport.width = render_extent.width;
viewport.height = render_extent.height;
commandbuffer->set_viewport(viewport);
commandbuffer->push_group("render camera");
render_camera(commandbuffer, *scene, obj, camera, render_extent, continuity);
render_camera(commandbuffer, *scene, obj, camera, render_extent, target, continuity);
commandbuffer->pop_group();
}
@ -377,7 +373,7 @@ void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->pop_group();
}
void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, ControllerContinuity& continuity) {
void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, RenderTarget& target, ControllerContinuity& continuity) {
// frustum test
const auto frustum = normalize_frustum(camera_extract_frustum(scene, camera_object));
@ -467,7 +463,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->set_graphics_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline);
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_shader_buffer(target.sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_texture(scene.depthTexture, 2);
command_buffer->bind_texture(scene.pointLightArray, 3);
@ -525,7 +521,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
pass->render_scene(scene, command_buffer);
}
gfx->copy_buffer(sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
gfx->copy_buffer(target.sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
}
void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen, prism::Extent extent, ControllerContinuity& continuity, RenderScreenOptions options) {
@ -809,10 +805,8 @@ void Renderer::create_render_target_resources(RenderTarget& target) {
renderToViewportPipeline = gfx->create_graphics_pipeline(pipelineInfo);
}
}
void Renderer::createMeshPipeline() {
sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage);
target.sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage);
}
void Renderer::createPostPipeline() {

View file

@ -956,6 +956,8 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca
auto renderer = engine->get_renderer();
RenderTarget* target = renderer->allocate_render_target({thumbnail_resolution, thumbnail_resolution});
renderer->shadow_pass->create_scene_resources(scene);
renderer->scene_capture->create_scene_resources(scene);
@ -1011,7 +1013,7 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca
command_buffer->set_render_pass(begin_info);
Renderer::ControllerContinuity continuity;
renderer->render_camera(command_buffer, scene, camera, scene.get<Camera>(camera), begin_info.render_area.extent, continuity);
renderer->render_camera(command_buffer, scene, camera, scene.get<Camera>(camera), begin_info.render_area.extent, *target, continuity);
// render post
begin_info.framebuffer = final_framebuffer;

View file

@ -18,8 +18,6 @@ PositionKeyFrame* currentFrame = nullptr;
std::string currentPath;
std::unique_ptr<Renderer> renderer;
void app_main(Engine* engine) {
CommonEditor* editor = (CommonEditor*)engine->get_app();
@ -33,13 +31,6 @@ void app_main(Engine* engine) {
CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {}
void CutsceneEditor::drawUI() {
if(!renderer) {
renderer = std::make_unique<Renderer>(engine->get_gfx(), false);
renderer->viewport_mode = true;
renderer->resize_viewport({static_cast<uint32_t>(viewport_width), static_cast<uint32_t>(viewport_height)});
}
createDockArea();
const ImGuiID editor_dockspace = ImGui::GetID("dockspace");
@ -430,7 +421,7 @@ void CutsceneEditor::drawUI() {
ImGui::End();
if(ImGui::Begin("Viewport")) {
drawViewport(*renderer);
drawViewport(engine->get_scene());
}
ImGui::End();
@ -440,6 +431,4 @@ void CutsceneEditor::drawUI() {
if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
engine->current_cutscene_time += 1.0f;
renderer->render(engine->get_scene(), -1);
}