mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Finally get something to show on screen
This commit is contained in:
parent
4d57244151
commit
92ff208c35
@ -45,10 +45,15 @@ namespace engine {
|
|||||||
// submit command lists and draw to the screen
|
// submit command lists and draw to the screen
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
|
void createPipeline(const char* vertShaderPath, const char* fragShaderPath);
|
||||||
|
|
||||||
bool createBuffer(const gfx::BufferDesc& desc, const void* data, gfx::BufferHandle* out);
|
bool createBuffer(const gfx::BufferDesc& desc, const void* data, gfx::BufferHandle* out);
|
||||||
|
|
||||||
|
// waits for the gpu to stop doing stuff to allow for a safe cleanup
|
||||||
|
void waitIdle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> pimpl;
|
std::unique_ptr<Impl> pimpl;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "window.hpp"
|
#include "window.hpp"
|
||||||
#include "gfx_device.hpp"
|
#include "gfx_device.hpp"
|
||||||
|
#include "resource_manager.hpp"
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
@ -9,6 +10,10 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
m_win = std::make_unique<Window>(appName, false);
|
m_win = std::make_unique<Window>(appName, false);
|
||||||
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle());
|
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle());
|
||||||
|
|
||||||
|
engine::ResourceManager resMan{};
|
||||||
|
|
||||||
|
m_gfx->createPipeline(resMan.getFilePath("shader.vert.spv").string().c_str(), resMan.getFilePath("shader.frag.spv").string().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
@ -19,7 +24,7 @@ namespace engine {
|
|||||||
void Application::gameLoop()
|
void Application::gameLoop()
|
||||||
{
|
{
|
||||||
uint64_t lastTick = m_win->getNanos();
|
uint64_t lastTick = m_win->getNanos();
|
||||||
constexpr int TICKFREQ = 20; // in hz
|
constexpr int TICKFREQ = 1; // in hz
|
||||||
|
|
||||||
// single-threaded game loop
|
// single-threaded game loop
|
||||||
while (m_win->isRunning()) {
|
while (m_win->isRunning()) {
|
||||||
@ -30,6 +35,7 @@ namespace engine {
|
|||||||
lastTick = m_win->getLastFrameStamp();
|
lastTick = m_win->getLastFrameStamp();
|
||||||
|
|
||||||
// do tick stuff here
|
// do tick stuff here
|
||||||
|
m_win->setTitle("frame time: " + std::to_string(m_win->dt() * 1000.0f) + " ms");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +53,8 @@ namespace engine {
|
|||||||
m_win->getInputAndEvents();
|
m_win->getInputAndEvents();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_gfx->waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
// structures
|
// structures and enums
|
||||||
|
|
||||||
struct LayerInfo {
|
struct LayerInfo {
|
||||||
std::vector<VkLayerProperties> layersAvailable{};
|
std::vector<VkLayerProperties> layersAvailable{};
|
||||||
@ -61,12 +63,14 @@ namespace engine {
|
|||||||
|
|
||||||
VkRenderPass renderpass;
|
VkRenderPass renderpass;
|
||||||
|
|
||||||
uint32_t swapchainImageIndex = 0;
|
VkSemaphore acquireSemaphore = VK_NULL_HANDLE; // waits until the image is available
|
||||||
VkSemaphore acquireSemaphore = VK_NULL_HANDLE;
|
VkSemaphore releaseSemaphore = VK_NULL_HANDLE; // waits until rendering finishes
|
||||||
VkSemaphore releaseSemaphore = VK_NULL_HANDLE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// enums
|
struct Pipeline {
|
||||||
|
VkPipelineLayout layout = VK_NULL_HANDLE;
|
||||||
|
VkPipeline handle = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
enum class QueueFlags : uint32_t {
|
enum class QueueFlags : uint32_t {
|
||||||
GRAPHICS = (1 << 0),
|
GRAPHICS = (1 << 0),
|
||||||
@ -74,8 +78,23 @@ namespace engine {
|
|||||||
COMPUTE = (1 << 2),
|
COMPUTE = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
|
|
||||||
|
static std::vector<char> readFile(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
||||||
|
if (file.is_open() == false) {
|
||||||
|
throw std::runtime_error("Unable to open file " + filename);
|
||||||
|
}
|
||||||
|
std::vector<char> buffer(file.tellg());
|
||||||
|
file.seekg(0);
|
||||||
|
file.read(buffer.data(), buffer.size());
|
||||||
|
file.close();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<const char*> getRequiredVulkanExtensions(SDL_Window* window)
|
static std::vector<const char*> getRequiredVulkanExtensions(SDL_Window* window)
|
||||||
{
|
{
|
||||||
SDL_bool res;
|
SDL_bool res;
|
||||||
@ -251,7 +270,7 @@ namespace engine {
|
|||||||
|
|
||||||
for (const auto& presMode : supportDetails.presentModes) {
|
for (const auto& presMode : supportDetails.presentModes) {
|
||||||
if (presMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
if (presMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
swapchain->presentMode = presMode; // this mode allows uncapped FPS while also avoiding screen tearing
|
//swapchain->presentMode = presMode; // this mode allows uncapped FPS while also avoiding screen tearing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +367,14 @@ namespace engine {
|
|||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &colorAttachmentRef;
|
subpass.pColorAttachments = &colorAttachmentRef;
|
||||||
|
|
||||||
|
VkSubpassDependency dependency{};
|
||||||
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
dependency.dstSubpass = 0;
|
||||||
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.srcAccessMask = 0;
|
||||||
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
VkRenderPassCreateInfo createInfo{};
|
VkRenderPassCreateInfo createInfo{};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
createInfo.attachmentCount = 1;
|
createInfo.attachmentCount = 1;
|
||||||
@ -355,6 +382,9 @@ namespace engine {
|
|||||||
createInfo.subpassCount = 1;
|
createInfo.subpassCount = 1;
|
||||||
createInfo.pSubpasses = &subpass;
|
createInfo.pSubpasses = &subpass;
|
||||||
|
|
||||||
|
createInfo.dependencyCount = 1;
|
||||||
|
createInfo.pDependencies = &dependency;
|
||||||
|
|
||||||
//if (swapchain->renderpass != VK_NULL_HANDLE) {
|
//if (swapchain->renderpass != VK_NULL_HANDLE) {
|
||||||
// vkDestroyRenderPass(device, swapchain->renderpass, nullptr);
|
// vkDestroyRenderPass(device, swapchain->renderpass, nullptr);
|
||||||
// swapchain->renderpass = VK_NULL_HANDLE;
|
// swapchain->renderpass = VK_NULL_HANDLE;
|
||||||
@ -420,6 +450,25 @@ namespace engine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkShaderModule createShaderModule(VkDevice device, const std::vector<char>& code)
|
||||||
|
{
|
||||||
|
VkShaderModuleCreateInfo createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
|
createInfo.codeSize = code.size();
|
||||||
|
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
|
||||||
|
|
||||||
|
VkShaderModule shaderModule;
|
||||||
|
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create shader module!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return shaderModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// class definitions
|
||||||
|
|
||||||
struct GFXDevice::Impl {
|
struct GFXDevice::Impl {
|
||||||
|
|
||||||
VkInstance instance = VK_NULL_HANDLE;
|
VkInstance instance = VK_NULL_HANDLE;
|
||||||
@ -432,6 +481,7 @@ namespace engine {
|
|||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
|
|
||||||
std::vector<Queue> queues{};
|
std::vector<Queue> queues{};
|
||||||
|
Queue gfxQueue;
|
||||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
||||||
|
|
||||||
@ -439,6 +489,10 @@ namespace engine {
|
|||||||
|
|
||||||
Swapchain swapchain{};
|
Swapchain swapchain{};
|
||||||
|
|
||||||
|
VkFence inFlightFence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
Pipeline pipeline{};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window)
|
GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window)
|
||||||
@ -543,7 +597,7 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// load the instance functions
|
// load the instance functions
|
||||||
volkLoadInstanceOnly(pimpl->instance);
|
volkLoadInstanceOnly(pimpl->instance);
|
||||||
@ -792,12 +846,12 @@ namespace engine {
|
|||||||
vkGetDeviceQueue(pimpl->device, q.familyIndex, q.queueIndex, &q.handle);
|
vkGetDeviceQueue(pimpl->device, q.familyIndex, q.queueIndex, &q.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Queue gfxQueue = getQueueSupporting(pimpl->queues, QueueFlags::GRAPHICS);
|
pimpl->gfxQueue = getQueueSupporting(pimpl->queues, QueueFlags::GRAPHICS);
|
||||||
|
|
||||||
VkCommandPoolCreateInfo gfxCmdPoolInfo{
|
VkCommandPoolCreateInfo gfxCmdPoolInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||||
.queueFamilyIndex = gfxQueue.familyIndex,
|
.queueFamilyIndex = pimpl->gfxQueue.familyIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
res = vkCreateCommandPool(pimpl->device, &gfxCmdPoolInfo, nullptr, &pimpl->commandPool);
|
res = vkCreateCommandPool(pimpl->device, &gfxCmdPoolInfo, nullptr, &pimpl->commandPool);
|
||||||
@ -865,17 +919,33 @@ namespace engine {
|
|||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Now make the swapchain
|
// Now make the swapchain
|
||||||
createSwapchain(pimpl->device, pimpl->queues, window, pimpl->surface, pimpl->swapchainSupportDetails, &pimpl->swapchain);
|
createSwapchain(pimpl->device, pimpl->queues, window, pimpl->surface, pimpl->swapchainSupportDetails, &pimpl->swapchain);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for testing purposes, create a pipeline with a simple shader
|
||||||
|
VkFenceCreateInfo fenceInfo{};
|
||||||
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
fenceInfo.pNext = nullptr;
|
||||||
|
res = vkCreateFence(pimpl->device, &fenceInfo, nullptr, &pimpl->inFlightFence);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXDevice::~GFXDevice()
|
GFXDevice::~GFXDevice()
|
||||||
{
|
{
|
||||||
TRACE("Destroying GFXDevice...");
|
TRACE("Destroying GFXDevice...");
|
||||||
|
|
||||||
|
if (pimpl->pipeline.handle != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipeline(pimpl->device, pimpl->pipeline.handle, nullptr);
|
||||||
|
vkDestroyPipelineLayout(pimpl->device, pimpl->pipeline.layout, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDestroyFence(pimpl->device, pimpl->inFlightFence, nullptr);
|
||||||
|
|
||||||
vkDestroySemaphore(pimpl->device, pimpl->swapchain.releaseSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device, pimpl->swapchain.releaseSemaphore, nullptr);
|
||||||
vkDestroySemaphore(pimpl->device, pimpl->swapchain.acquireSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device, pimpl->swapchain.acquireSemaphore, nullptr);
|
||||||
for (VkImageView view : pimpl->swapchain.imageViews) {
|
for (VkImageView view : pimpl->swapchain.imageViews) {
|
||||||
@ -898,7 +968,238 @@ namespace engine {
|
|||||||
|
|
||||||
void GFXDevice::draw()
|
void GFXDevice::draw()
|
||||||
{
|
{
|
||||||
|
VkResult res;
|
||||||
|
|
||||||
|
res = vkWaitForFences(pimpl->device, 1, &pimpl->inFlightFence, VK_TRUE, UINT64_MAX);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
res = vkResetFences(pimpl->device, 1, &pimpl->inFlightFence);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
uint32_t imageIndex;
|
||||||
|
vkAcquireNextImageKHR(pimpl->device, pimpl->swapchain.swapchain, UINT64_MAX, pimpl->swapchain.acquireSemaphore, VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
|
vkResetCommandBuffer(pimpl->commandBuffer, 0);
|
||||||
|
|
||||||
|
// now record command buffer
|
||||||
|
{
|
||||||
|
VkCommandBufferBeginInfo beginInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||||
|
beginInfo.flags = 0;
|
||||||
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
res = vkBeginCommandBuffer(pimpl->commandBuffer, &beginInfo);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
VkRenderPassBeginInfo renderPassInfo{ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
|
||||||
|
renderPassInfo.renderPass = pimpl->swapchain.renderpass;
|
||||||
|
renderPassInfo.framebuffer = pimpl->swapchain.framebuffers[imageIndex];
|
||||||
|
renderPassInfo.renderArea.offset = { 0, 0 };
|
||||||
|
renderPassInfo.renderArea.extent = pimpl->swapchain.extent;
|
||||||
|
|
||||||
|
VkClearValue clearColor{ {0.0f, 0.0f, 0.0f, 0.0f} };
|
||||||
|
renderPassInfo.clearValueCount = 1;
|
||||||
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
|
|
||||||
|
vkCmdBeginRenderPass(pimpl->commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
vkCmdBindPipeline(pimpl->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pimpl->pipeline.handle);
|
||||||
|
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = (float)pimpl->swapchain.extent.width;
|
||||||
|
viewport.height = (float)pimpl->swapchain.extent.height;
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
vkCmdSetViewport(pimpl->commandBuffer, 0, 1, &viewport);
|
||||||
|
|
||||||
|
VkRect2D scissor{};
|
||||||
|
scissor.offset = { 0, 0 };
|
||||||
|
scissor.extent = pimpl->swapchain.extent;
|
||||||
|
vkCmdSetScissor(pimpl->commandBuffer, 0, 1, &scissor);
|
||||||
|
|
||||||
|
vkCmdDraw(pimpl->commandBuffer, 3, 1, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRenderPass(pimpl->commandBuffer);
|
||||||
|
|
||||||
|
res = vkEndCommandBuffer(pimpl->commandBuffer);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||||
|
|
||||||
|
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
|
||||||
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
|
submitInfo.pWaitSemaphores = &pimpl->swapchain.acquireSemaphore;
|
||||||
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &pimpl->commandBuffer;
|
||||||
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
|
submitInfo.pSignalSemaphores = &pimpl->swapchain.releaseSemaphore;
|
||||||
|
|
||||||
|
res = vkQueueSubmit(pimpl->gfxQueue.handle, 1, &submitInfo, pimpl->inFlightFence);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
VkPresentInfoKHR presentInfo{ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
|
||||||
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
|
presentInfo.pWaitSemaphores = &pimpl->swapchain.releaseSemaphore;
|
||||||
|
|
||||||
|
VkSwapchainKHR swapchains[] = { pimpl->swapchain.swapchain };
|
||||||
|
presentInfo.swapchainCount = 1;
|
||||||
|
presentInfo.pSwapchains = swapchains;
|
||||||
|
presentInfo.pImageIndices = &imageIndex;
|
||||||
|
presentInfo.pResults = nullptr;
|
||||||
|
|
||||||
|
res = vkQueuePresentKHR(pimpl->gfxQueue.handle, &presentInfo);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath)
|
||||||
|
{
|
||||||
|
|
||||||
|
VkResult res;
|
||||||
|
|
||||||
|
auto vertShaderCode = readFile(vertShaderPath);
|
||||||
|
auto fragShaderCode = readFile(fragShaderPath);
|
||||||
|
INFO("Opened shader: {}", std::filesystem::path(vertShaderPath).filename().string());
|
||||||
|
|
||||||
|
VkShaderModule vertShaderModule = createShaderModule(pimpl->device, vertShaderCode);
|
||||||
|
VkShaderModule fragShaderModule = createShaderModule(pimpl->device, fragShaderCode);
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo vertShaderStageInfo{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
|
||||||
|
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
vertShaderStageInfo.module = vertShaderModule;
|
||||||
|
vertShaderStageInfo.pName = "main";
|
||||||
|
vertShaderStageInfo.pSpecializationInfo = nullptr;
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo fragShaderStageInfo{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
|
||||||
|
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
fragShaderStageInfo.module = fragShaderModule;
|
||||||
|
fragShaderStageInfo.pName = "main";
|
||||||
|
fragShaderStageInfo.pSpecializationInfo = nullptr;
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo shaderStages[2] = { vertShaderStageInfo, fragShaderStageInfo };
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
||||||
|
vertexInputInfo.pVertexBindingDescriptions = nullptr;
|
||||||
|
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
||||||
|
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||||
|
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
inputAssembly.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = (float)pimpl->swapchain.extent.width;
|
||||||
|
viewport.height = (float)pimpl->swapchain.extent.height;
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
|
VkRect2D scissor{};
|
||||||
|
scissor.offset = { 0, 0 };
|
||||||
|
scissor.extent = pimpl->swapchain.extent;
|
||||||
|
|
||||||
|
std::vector<VkDynamicState> dynamicStates = {
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicState{};
|
||||||
|
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
dynamicState.dynamicStateCount = dynamicStates.size();
|
||||||
|
dynamicState.pDynamicStates = dynamicStates.data();
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewportState{};
|
||||||
|
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewportState.viewportCount = 1;
|
||||||
|
viewportState.pViewports = &viewport;
|
||||||
|
viewportState.scissorCount = 1;
|
||||||
|
viewportState.pScissors = &scissor;
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
||||||
|
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
rasterizer.depthClampEnable = VK_FALSE;
|
||||||
|
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||||
|
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
|
rasterizer.lineWidth = 1.0f;
|
||||||
|
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
|
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
|
rasterizer.depthBiasEnable = VK_FALSE;
|
||||||
|
rasterizer.depthBiasConstantFactor = 0.0f; // ignored
|
||||||
|
rasterizer.depthBiasClamp = 0.0f; // ignored
|
||||||
|
rasterizer.depthBiasSlopeFactor = 0.0f; // ignored
|
||||||
|
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampling{};
|
||||||
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
|
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
multisampling.minSampleShading = 1.0f; // ignored
|
||||||
|
multisampling.pSampleMask = nullptr; // ignored
|
||||||
|
multisampling.alphaToCoverageEnable = VK_FALSE; // ignored
|
||||||
|
multisampling.alphaToOneEnable = VK_FALSE; // ignored
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
||||||
|
colorBlendAttachment.colorWriteMask =
|
||||||
|
VK_COLOR_COMPONENT_R_BIT |
|
||||||
|
VK_COLOR_COMPONENT_G_BIT |
|
||||||
|
VK_COLOR_COMPONENT_B_BIT |
|
||||||
|
VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
colorBlendAttachment.blendEnable = VK_FALSE;
|
||||||
|
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // ignored
|
||||||
|
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // ignored
|
||||||
|
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; // ignored
|
||||||
|
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // ignored
|
||||||
|
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // ignored
|
||||||
|
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // ignored
|
||||||
|
|
||||||
|
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
||||||
|
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
|
colorBlending.logicOpEnable = VK_FALSE;
|
||||||
|
colorBlending.logicOp = VK_LOGIC_OP_COPY; // ignored
|
||||||
|
colorBlending.attachmentCount = 1;
|
||||||
|
colorBlending.pAttachments = &colorBlendAttachment;
|
||||||
|
colorBlending.blendConstants[0] = 0.0f; // ignored
|
||||||
|
colorBlending.blendConstants[1] = 0.0f; // ignored
|
||||||
|
colorBlending.blendConstants[2] = 0.0f; // ignored
|
||||||
|
colorBlending.blendConstants[3] = 0.0f; // ignored
|
||||||
|
|
||||||
|
VkPipelineLayoutCreateInfo layoutInfo{};
|
||||||
|
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
// everything is 0 because we're not using uniforms
|
||||||
|
layoutInfo.setLayoutCount = 0;
|
||||||
|
layoutInfo.pSetLayouts = nullptr;
|
||||||
|
layoutInfo.pushConstantRangeCount = 0;
|
||||||
|
layoutInfo.pPushConstantRanges = nullptr;
|
||||||
|
|
||||||
|
res = vkCreatePipelineLayout(pimpl->device, &layoutInfo, nullptr, &pimpl->pipeline.layout);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
createInfo.stageCount = 2;
|
||||||
|
createInfo.pStages = shaderStages;
|
||||||
|
createInfo.pVertexInputState = &vertexInputInfo;
|
||||||
|
createInfo.pInputAssemblyState = &inputAssembly;
|
||||||
|
createInfo.pViewportState = &viewportState;
|
||||||
|
createInfo.pRasterizationState = &rasterizer;
|
||||||
|
createInfo.pMultisampleState = &multisampling;
|
||||||
|
createInfo.pDepthStencilState = nullptr;
|
||||||
|
createInfo.pColorBlendState = &colorBlending;
|
||||||
|
createInfo.pDynamicState = &dynamicState;
|
||||||
|
createInfo.layout = pimpl->pipeline.layout;
|
||||||
|
createInfo.renderPass = pimpl->swapchain.renderpass;
|
||||||
|
createInfo.subpass = 0;
|
||||||
|
createInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
createInfo.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
res = vkCreateGraphicsPipelines(pimpl->device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pimpl->pipeline.handle);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
vkDestroyShaderModule(pimpl->device, fragShaderModule, nullptr);
|
||||||
|
vkDestroyShaderModule(pimpl->device, vertShaderModule, nullptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GFXDevice::createBuffer(const gfx::BufferDesc& desc, const void* data, gfx::BufferHandle* out)
|
bool GFXDevice::createBuffer(const gfx::BufferDesc& desc, const void* data, gfx::BufferHandle* out)
|
||||||
@ -906,6 +1207,11 @@ namespace engine {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GFXDevice::waitIdle()
|
||||||
|
{
|
||||||
|
vkDeviceWaitIdle(pimpl->device);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user