removed render triangle test
This commit is contained in:
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace sophia {
|
|
||||||
|
|
||||||
void runRenderTriangleTest(const std::string& vertShaderPath,
|
|
||||||
const std::string& fragShaderPath);
|
|
||||||
|
|
||||||
} // namespace sophia
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <limits>
|
|
||||||
#include <sophia/render_triangle_test.hpp>
|
|
||||||
#include <sophia/util/logger.hpp>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
#include <vulkan/vulkan.hpp>
|
|
||||||
|
|
||||||
#define GLM_FORCE_RADIANS
|
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include "buffer.hpp"
|
|
||||||
#include "device.hpp"
|
|
||||||
#include "image.hpp"
|
|
||||||
#include "pipelines/graphics_pipeline.hpp"
|
|
||||||
#include "shader.hpp"
|
|
||||||
#include "swapchain.hpp"
|
|
||||||
|
|
||||||
namespace sophia {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct Vertex {
|
|
||||||
glm::vec2 position;
|
|
||||||
glm::vec3 color;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PushConstants {
|
|
||||||
glm::mat4 transform;
|
|
||||||
glm::vec4 color;
|
|
||||||
glm::vec4 data;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void runRenderTriangleTest(const std::string& vertShaderPath,
|
|
||||||
const std::string& fragShaderPath) {
|
|
||||||
std::unique_ptr<sophia::Window> window =
|
|
||||||
std::make_unique<Window>(750, 1000, "Render Triangle Test");
|
|
||||||
std::unique_ptr<sophia::Device> device =
|
|
||||||
Device::Builder().withWindow(*window).build();
|
|
||||||
|
|
||||||
log::info("Running Render Triangle Test...");
|
|
||||||
|
|
||||||
std::unique_ptr<Swapchain> swapchain =
|
|
||||||
std::make_unique<Swapchain>(*device, window->getExtent());
|
|
||||||
|
|
||||||
auto vertexShader = Shader::Builder()
|
|
||||||
.fromGLSL(vertShaderPath)
|
|
||||||
.setStage(ShaderStage::VERTEX)
|
|
||||||
.build();
|
|
||||||
auto fragmentShader = Shader::Builder()
|
|
||||||
.fromGLSL(fragShaderPath)
|
|
||||||
.setStage(ShaderStage::FRAGMENT)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
vk::PushConstantRange pushConstantRange{};
|
|
||||||
pushConstantRange.stageFlags =
|
|
||||||
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment;
|
|
||||||
pushConstantRange.offset = 0;
|
|
||||||
pushConstantRange.size = sizeof(PushConstants);
|
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutInfo{};
|
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
|
||||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
|
|
||||||
|
|
||||||
vk::UniquePipelineLayout pipelineLayout =
|
|
||||||
device->get()->createPipelineLayoutUnique(pipelineLayoutInfo);
|
|
||||||
|
|
||||||
std::vector<vk::VertexInputBindingDescription> bindingDescriptions{
|
|
||||||
{0, sizeof(Vertex), vk::VertexInputRate::eVertex}};
|
|
||||||
std::vector<vk::VertexInputAttributeDescription> attributeDescriptions{
|
|
||||||
{0, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, position)},
|
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)}};
|
|
||||||
|
|
||||||
std::unique_ptr<sophia::GraphicsPipeline> graphicsPipeline =
|
|
||||||
GraphicsPipeline::Builder(*device)
|
|
||||||
.setVertexShader(*vertexShader)
|
|
||||||
.setFragmentShader(*fragmentShader)
|
|
||||||
.setPipelineLayout(pipelineLayout.get())
|
|
||||||
.setColorAttachmentFormats({swapchain->getImageFormat()})
|
|
||||||
.setVertexInput(bindingDescriptions, attributeDescriptions)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Oversized triangle covering the full screen so the fragment shader runs
|
|
||||||
// for every pixel.
|
|
||||||
std::vector<Vertex> vertices{
|
|
||||||
{{-1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}},
|
|
||||||
{{3.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
|
|
||||||
{{-1.0f, 3.0f}, {0.0f, 0.0f, 1.0f}},
|
|
||||||
};
|
|
||||||
|
|
||||||
Buffer vertexBuffer{*device, sizeof(Vertex),
|
|
||||||
static_cast<u32>(vertices.size()),
|
|
||||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
|
||||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
|
||||||
vk::MemoryPropertyFlagBits::eHostCoherent};
|
|
||||||
vertexBuffer.map();
|
|
||||||
vertexBuffer.writeToBuffer(vertices.data(), sizeof(Vertex) * vertices.size());
|
|
||||||
vertexBuffer.unmap();
|
|
||||||
|
|
||||||
vk::UniqueSemaphore imageAvailableSemaphore =
|
|
||||||
device->get()->createSemaphoreUnique({});
|
|
||||||
|
|
||||||
std::vector<vk::UniqueSemaphore> renderFinishedSemaphores;
|
|
||||||
for (size_t i = 0; i < swapchain->imageCount(); i++) {
|
|
||||||
renderFinishedSemaphores.push_back(
|
|
||||||
device->get()->createSemaphoreUnique({}));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto recreateSwapchain = [&]() {
|
|
||||||
vk::Extent2D extent = window->getExtent();
|
|
||||||
while (extent.width == 0 || extent.height == 0) {
|
|
||||||
extent = window->getExtent();
|
|
||||||
glfwWaitEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
device->waitIdle();
|
|
||||||
|
|
||||||
std::shared_ptr<Swapchain> oldSwapchain = std::move(swapchain);
|
|
||||||
swapchain = std::make_unique<Swapchain>(*device, extent, oldSwapchain);
|
|
||||||
|
|
||||||
if (!oldSwapchain->compareSwapchainFormats(*swapchain)) {
|
|
||||||
log::fatal("swapchain image format changed on recreation");
|
|
||||||
throw std::runtime_error("swapchain image format changed on recreation");
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFinishedSemaphores.clear();
|
|
||||||
for (size_t i = 0; i < swapchain->imageCount(); i++) {
|
|
||||||
renderFinishedSemaphores.push_back(
|
|
||||||
device->get()->createSemaphoreUnique({}));
|
|
||||||
}
|
|
||||||
|
|
||||||
log::trace("recreated swapchain");
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::UniqueFence inFlightFence =
|
|
||||||
device->get()->createFenceUnique({vk::FenceCreateFlagBits::eSignaled});
|
|
||||||
|
|
||||||
vk::CommandBufferAllocateInfo commandBufferAllocInfo{
|
|
||||||
device->getCommandPool(), vk::CommandBufferLevel::ePrimary, 1};
|
|
||||||
vk::CommandBuffer commandBuffer =
|
|
||||||
device->get()->allocateCommandBuffers(commandBufferAllocInfo)[0];
|
|
||||||
|
|
||||||
auto startTime = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
while (!window->shouldClose()) {
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
double elapsedTime =
|
|
||||||
std::chrono::duration<double>(
|
|
||||||
std::chrono::high_resolution_clock::now() - startTime)
|
|
||||||
.count();
|
|
||||||
|
|
||||||
vk::Fence inFlightFenceHandle = inFlightFence.get();
|
|
||||||
(void)device->get()->waitForFences(inFlightFenceHandle, vk::True,
|
|
||||||
std::numeric_limits<u64>::max());
|
|
||||||
|
|
||||||
vk::Semaphore imageAvailableSemaphoreHandle = imageAvailableSemaphore.get();
|
|
||||||
u32 imageIndex = 0;
|
|
||||||
vk::Result acquireResult =
|
|
||||||
swapchain->acquireNextImage(imageAvailableSemaphoreHandle, imageIndex);
|
|
||||||
if (acquireResult == vk::Result::eErrorOutOfDateKHR) {
|
|
||||||
recreateSwapchain();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (acquireResult != vk::Result::eSuccess &&
|
|
||||||
acquireResult != vk::Result::eSuboptimalKHR) {
|
|
||||||
log::fatal("failed to acquire swapchain image");
|
|
||||||
throw std::runtime_error("failed to acquire swapchain image");
|
|
||||||
}
|
|
||||||
|
|
||||||
device->get()->resetFences(inFlightFenceHandle);
|
|
||||||
|
|
||||||
commandBuffer.reset();
|
|
||||||
commandBuffer.begin(vk::CommandBufferBeginInfo{});
|
|
||||||
|
|
||||||
Image& image = swapchain->getImage(static_cast<int>(imageIndex));
|
|
||||||
image.transitionLayout(commandBuffer,
|
|
||||||
vk::ImageLayout::eColorAttachmentOptimal);
|
|
||||||
|
|
||||||
vk::ClearValue clearValue{};
|
|
||||||
clearValue.color =
|
|
||||||
vk::ClearColorValue{std::array<float, 4>{0.01f, 0.01f, 0.02f, 1.0f}};
|
|
||||||
|
|
||||||
vk::RenderingAttachmentInfo colorAttachment{};
|
|
||||||
colorAttachment.imageView = image.getView();
|
|
||||||
colorAttachment.imageLayout = vk::ImageLayout::eColorAttachmentOptimal;
|
|
||||||
colorAttachment.loadOp = vk::AttachmentLoadOp::eClear;
|
|
||||||
colorAttachment.storeOp = vk::AttachmentStoreOp::eStore;
|
|
||||||
colorAttachment.clearValue = clearValue;
|
|
||||||
|
|
||||||
vk::RenderingInfo renderingInfo{};
|
|
||||||
renderingInfo.renderArea = vk::Rect2D{{0, 0}, swapchain->getExtent()};
|
|
||||||
renderingInfo.layerCount = 1;
|
|
||||||
renderingInfo.colorAttachmentCount = 1;
|
|
||||||
renderingInfo.pColorAttachments = &colorAttachment;
|
|
||||||
|
|
||||||
commandBuffer.beginRendering(renderingInfo);
|
|
||||||
|
|
||||||
vk::Extent2D extent = swapchain->getExtent();
|
|
||||||
vk::Viewport viewport{0.0f,
|
|
||||||
0.0f,
|
|
||||||
static_cast<float>(extent.width),
|
|
||||||
static_cast<float>(extent.height),
|
|
||||||
0.0f,
|
|
||||||
1.0f};
|
|
||||||
vk::Rect2D scissor{{0, 0}, extent};
|
|
||||||
commandBuffer.setViewport(0, viewport);
|
|
||||||
commandBuffer.setScissor(0, scissor);
|
|
||||||
|
|
||||||
graphicsPipeline->bind(commandBuffer);
|
|
||||||
|
|
||||||
vk::Buffer vertexBuffers[] = {vertexBuffer.getBuffer()};
|
|
||||||
vk::DeviceSize offsets[] = {0};
|
|
||||||
commandBuffer.bindVertexBuffers(0, vertexBuffers, offsets);
|
|
||||||
|
|
||||||
PushConstants push{};
|
|
||||||
push.transform = glm::mat4(1.0f);
|
|
||||||
push.color = glm::vec4(1.0f);
|
|
||||||
push.data = glm::vec4(static_cast<float>(extent.width),
|
|
||||||
static_cast<float>(extent.height),
|
|
||||||
static_cast<float>(elapsedTime), 0.0f);
|
|
||||||
commandBuffer.pushConstants(
|
|
||||||
pipelineLayout.get(),
|
|
||||||
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
|
||||||
0, sizeof(push), &push);
|
|
||||||
|
|
||||||
commandBuffer.draw(static_cast<u32>(vertices.size()), 1, 0, 0);
|
|
||||||
|
|
||||||
commandBuffer.endRendering();
|
|
||||||
|
|
||||||
image.transitionLayout(commandBuffer, vk::ImageLayout::ePresentSrcKHR);
|
|
||||||
|
|
||||||
commandBuffer.end();
|
|
||||||
|
|
||||||
vk::Semaphore renderFinishedSemaphoreHandle =
|
|
||||||
renderFinishedSemaphores.at(imageIndex).get();
|
|
||||||
vk::PipelineStageFlags waitStage =
|
|
||||||
vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
|
||||||
|
|
||||||
vk::SubmitInfo submitInfo{};
|
|
||||||
submitInfo.waitSemaphoreCount = 1;
|
|
||||||
submitInfo.pWaitSemaphores = &imageAvailableSemaphoreHandle;
|
|
||||||
submitInfo.pWaitDstStageMask = &waitStage;
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
submitInfo.pCommandBuffers = &commandBuffer;
|
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
|
||||||
submitInfo.pSignalSemaphores = &renderFinishedSemaphoreHandle;
|
|
||||||
|
|
||||||
device->getGraphicsQueue().submit(submitInfo, inFlightFenceHandle);
|
|
||||||
|
|
||||||
vk::Result presentResult = swapchain->present(
|
|
||||||
device->getPresentQueue(), imageIndex, renderFinishedSemaphoreHandle);
|
|
||||||
if (presentResult == vk::Result::eErrorOutOfDateKHR ||
|
|
||||||
presentResult == vk::Result::eSuboptimalKHR || window->wasResized()) {
|
|
||||||
window->resetResizedFlag();
|
|
||||||
recreateSwapchain();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (presentResult != vk::Result::eSuccess) {
|
|
||||||
log::fatal("failed to present swapchain image");
|
|
||||||
throw std::runtime_error("failed to present swapchain image");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
device->waitIdle();
|
|
||||||
|
|
||||||
auto endTime = std::chrono::high_resolution_clock::now();
|
|
||||||
double totalRuntime =
|
|
||||||
std::chrono::duration<double>(endTime - startTime).count();
|
|
||||||
log::info("Application ran for", totalRuntime, "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sophia
|
|
||||||
Reference in New Issue
Block a user