From 76bae46dbc167838531eaae85b0d41aab5e0741f Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 21 Sep 2022 12:36:12 -0400 Subject: [PATCH] self define descriptors --- engine/xe_input.cpp | 0 engine/xe_input.hpp | 15 ++++ engine/xe_render_system.cpp | 172 +++++++++++++++++------------------- engine/xe_render_system.hpp | 66 +++++++++++--- src/simple_renderer.cpp | 24 +++-- src/simple_renderer.hpp | 2 +- 6 files changed, 166 insertions(+), 113 deletions(-) create mode 100644 engine/xe_input.cpp create mode 100644 engine/xe_input.hpp diff --git a/engine/xe_input.cpp b/engine/xe_input.cpp new file mode 100644 index 0000000..e69de29 diff --git a/engine/xe_input.hpp b/engine/xe_input.hpp new file mode 100644 index 0000000..53d9f03 --- /dev/null +++ b/engine/xe_input.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "xe_window.hpp" + +namespace xe { + +class XeInput { + + private: + + XeWindow &xeWindow; + +}; + +} \ No newline at end of file diff --git a/engine/xe_render_system.cpp b/engine/xe_render_system.cpp index 6cfb183..0158e34 100644 --- a/engine/xe_render_system.cpp +++ b/engine/xe_render_system.cpp @@ -19,19 +19,20 @@ namespace xe { XeRenderSystem::XeRenderSystem( XeEngine &xeEngine, std::string vert, - std::string frag, - uint32_t pushCunstantDataSize, - uint32_t uniformBufferDataSize, - XeImage *image + std::string frag, + std::map uniformBindings, + std::map imageBindings, + uint32_t pushCunstantDataSize ) : xeDevice{xeEngine.xeDevice}, xeRenderer{xeEngine.xeRenderer}, xeDescriptorPool{xeEngine.xeDescriptorPool}, pushCunstantDataSize{pushCunstantDataSize}, - uniformBufferDataSize{uniformBufferDataSize}, - textureSamplerBinding{image != nullptr} { + uniformBindings{uniformBindings}, + imageBindings{imageBindings} { + createTextureSampler(); createDescriptorSetLayout(); createUniformBuffers(); - createDescriptorSets(image); + createDescriptorSets(); createPipelineLayout(); createPipeline(xeRenderer.getSwapChainRenderPass(), vert, frag); } @@ -39,99 +40,96 @@ XeRenderSystem::XeRenderSystem( XeRenderSystem::~XeRenderSystem() { vkDestroyPipelineLayout(xeDevice.device(), pipelineLayout, nullptr); - if ( textureSamplerBinding ) { - vkDestroySampler(xeDevice.device(), textureSampler, nullptr); - } + vkDestroySampler(xeDevice.device(), textureSampler, nullptr); }; +void XeRenderSystem::createTextureSampler() { + VkSamplerCreateInfo samplerInfo{}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 0.0f; + + if (vkCreateSampler(xeDevice.device(), &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) { + throw std::runtime_error("failed to create texture sampler!"); + } +} + void XeRenderSystem::createDescriptorSetLayout() { XeDescriptorSetLayout::Builder builder{xeDevice}; - int binding = 0; - - if (uniformBufferDataSize > 0) { + + for ( const auto &[binding, size]: uniformBindings) { builder.addBinding(binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, nullptr); - binding += 1; } - if (textureSamplerBinding) { - - VkSamplerCreateInfo samplerInfo{}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.anisotropyEnable = VK_FALSE; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 0.0f; - - if (vkCreateSampler(xeDevice.device(), &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) { - throw std::runtime_error("failed to create texture sampler!"); - } + for ( const auto &[binding, image]: imageBindings) { builder.addBinding(binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &textureSampler); - binding += 1; } xeDescriptorSetLayout = builder.build(); } void XeRenderSystem::createUniformBuffers() { - if(uniformBufferDataSize == 0) return; - - uboBuffers = std::vector>(XeSwapChain::MAX_FRAMES_IN_FLIGHT); - for (int i = 0; i < uboBuffers.size(); i++) { - uboBuffers[i] = std::make_unique( - xeDevice, - uniformBufferDataSize, - XeSwapChain::MAX_FRAMES_IN_FLIGHT, - - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - uboBuffers[i]->map(); + for ( const auto &[binding, bufferSize]: uniformBindings) { + uboBuffers[binding] = std::vector>(XeSwapChain::MAX_FRAMES_IN_FLIGHT); + for (int i = 0; i < uboBuffers[binding].size(); i++) { + uboBuffers[binding][i] = std::make_unique( + xeDevice, + bufferSize, + XeSwapChain::MAX_FRAMES_IN_FLIGHT, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + uboBuffers[binding][i]->map(); + } } - } -void XeRenderSystem::createDescriptorSets(XeImage *image) { +void XeRenderSystem::createDescriptorSets() { descriptorSets = std::vector(XeSwapChain::MAX_FRAMES_IN_FLIGHT); for (int i = 0; i < descriptorSets.size(); i++) { - updateDescriptorSet(image, i, true); + updateDescriptorSet(i, true); } } -void XeRenderSystem::updateDescriptorSet(XeImage *image, int frameIndex, bool allocate) { - auto bufferInfo = uboBuffers[frameIndex]->descriptorInfo(); - XeDescriptorWriter writer{*xeDescriptorSetLayout, *xeDescriptorPool}; - - int binding = 0; +void XeRenderSystem::updateDescriptorSet(int frameIndex, bool allocate) { - if (uniformBufferDataSize > 0) { - writer.writeBuffer(binding, &bufferInfo); - binding += 1; - } - - if (textureSamplerBinding) { - VkDescriptorImageInfo imageInfo{}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = image->textureImageView; - imageInfo.sampler = textureSampler; - writer.writeImage(binding, &imageInfo); - binding += 1; - } - if (allocate) { - writer.build(descriptorSets[frameIndex]); - } else { - writer.overwrite(descriptorSets[frameIndex]); - } + XeDescriptorWriter writer{*xeDescriptorSetLayout, *xeDescriptorPool}; + + std::vector bufferInfos{}; + + int i = 0; + for ( const auto &[binding, size]: uniformBindings) { + bufferInfos.push_back(uboBuffers[binding][frameIndex]->descriptorInfo()); + writer.writeBuffer(binding, &bufferInfos[i]); + i++; + } + + for ( const auto &[binding, image]: imageBindings) { + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.imageView = image->textureImageView; + imageInfo.sampler = textureSampler; + writer.writeImage(binding, &imageInfo); + } + + if (allocate) { + writer.build(descriptorSets[frameIndex]); + } else { + writer.overwrite(descriptorSets[frameIndex]); + } } @@ -143,8 +141,12 @@ void XeRenderSystem::createPipelineLayout() { pushConstantRange.offset = 0; pushConstantRange.size = pushCunstantDataSize; + std::vector descriptorSetLayouts{xeDescriptorSetLayout->getDescriptorSetLayout()}; + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); + pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); if (pushCunstantDataSize > 0) { pipelineLayoutInfo.pushConstantRangeCount = 1; @@ -154,17 +156,6 @@ void XeRenderSystem::createPipelineLayout() { pipelineLayoutInfo.pPushConstantRanges = nullptr; } - std::vector descriptorSetLayouts{xeDescriptorSetLayout->getDescriptorSetLayout()}; - - if (uniformBufferDataSize > 0) { - pipelineLayoutInfo.setLayoutCount = static_cast(descriptorSetLayouts.size()); - pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data(); - } else { - - pipelineLayoutInfo.setLayoutCount = 0; - pipelineLayoutInfo.pSetLayouts = nullptr; - } - if(vkCreatePipelineLayout(xeDevice.device(), &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { std::runtime_error("failed to create pipeline layout!"); } @@ -215,12 +206,13 @@ void XeRenderSystem::loadPushConstant(void *pushConstantData) { pushConstantData); } -void XeRenderSystem::loadUniformObject(void *uniformBufferData) { - uboBuffers[xeRenderer.getFrameIndex()]->writeToBuffer(uniformBufferData); +void XeRenderSystem::loadUniformObject(uint32_t binding, void *uniformBufferData) { + uboBuffers[binding][xeRenderer.getFrameIndex()]->writeToBuffer(uniformBufferData); } -void XeRenderSystem::loadTexture(XeImage *image) { - updateDescriptorSet(image, xeRenderer.getFrameIndex(), false); +void XeRenderSystem::loadTexture(uint32_t binding, XeImage *image) { + imageBindings[binding] = image; + updateDescriptorSet(xeRenderer.getFrameIndex(), false); } void XeRenderSystem::render(XeGameObject &gameObject) { diff --git a/engine/xe_render_system.hpp b/engine/xe_render_system.hpp index d6b24b5..ae68f53 100644 --- a/engine/xe_render_system.hpp +++ b/engine/xe_render_system.hpp @@ -10,19 +10,55 @@ #include "xe_image.hpp" #include +#include namespace xe { class XeRenderSystem { public: + class Builder { + public: + Builder(XeEngine &xeEngine, std::string vert, std::string frag) : xeEngine{xeEngine}, vert{vert}, frag{frag} {} + + Builder& addPushConstant(uint32_t size) { + pushCunstantDataSize = size; + return *this; + } + + Builder& addUniformBinding(uint32_t binding, uint32_t size) { + uniformBindings[binding] = size; + return *this; + } + + Builder& addTextureBinding(uint32_t binding, XeImage* image) { + imageBindings[binding] = image; + return *this; + } + + std::unique_ptr build() { + return std::make_unique(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize)); + } + + private: + + std::map uniformBindings{}; + std::map imageBindings{}; + uint32_t pushCunstantDataSize{0}; + + std::string vert; + std::string frag; + + XeEngine &xeEngine; + }; + XeRenderSystem( XeEngine &xeEngine, std::string vert, - std::string frag, - uint32_t pushCunstantDataSize, - uint32_t uniformBufferDataSize, - XeImage *image + std::string frag, + std::map uniformBindings, + std::map imageBindings, + uint32_t pushCunstantDataSize ); ~XeRenderSystem(); @@ -32,37 +68,39 @@ class XeRenderSystem { void start(); void loadPushConstant(void *pushConstantData); - void loadUniformObject(void *uniformBufferData); - void loadTexture(XeImage *image); + void loadUniformObject(uint32_t binding, void *uniformBufferData); + void loadTexture(uint32_t binding, XeImage *image); void render(XeGameObject &gameObject); void stop(); private: + void createTextureSampler(); void createDescriptorSetLayout(); void createUniformBuffers(); - void createDescriptorSets(XeImage *image); - void updateDescriptorSet(XeImage *image, int frameIndex, bool allocate); + void createDescriptorSets(); + void updateDescriptorSet(int frameIndex, bool allocate); void createPipelineLayout(); void createPipeline(VkRenderPass renderPass, std::string vert, std::string frag); bool boundPipeline{false}; bool boundDescriptor{false}; - uint32_t uniformBufferDataSize; - uint32_t pushCunstantDataSize; - bool textureSamplerBinding; - + XeDevice& xeDevice; XeRenderer& xeRenderer; - std::unique_ptr xePipeline; - std::vector> uboBuffers; + std::map>> uboBuffers{}; + std::map uniformBindings; + std::map imageBindings; std::vector descriptorSets; + uint32_t pushCunstantDataSize; + VkSampler textureSampler; VkPipelineLayout pipelineLayout; + std::unique_ptr xePipeline; std::unique_ptr &xeDescriptorPool; std::unique_ptr xeDescriptorSetLayout; diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp index a7016f9..82c2e38 100644 --- a/src/simple_renderer.cpp +++ b/src/simple_renderer.cpp @@ -1,29 +1,37 @@ #include "simple_renderer.hpp" +#include "xe_render_system.hpp" + +#include namespace app { -SimpleRenderer::SimpleRenderer(xe::XeEngine &xeEngine, xe::XeImage *xeImage) - : xeRenderSystem{xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv", sizeof(PushConstant), sizeof(UniformBuffer), xeImage} {}; +SimpleRenderer::SimpleRenderer(xe::XeEngine &xeEngine, xe::XeImage *xeImage) { + xeRenderSystem = xe::XeRenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv") + .addPushConstant(sizeof(PushConstant)) + .addUniformBinding(0, sizeof(UniformBuffer)) + .addTextureBinding(1, xeImage) + .build(); +} void SimpleRenderer::render(std::vector &gameObjects, xe::XeCamera &xeCamera, xe::XeImage *xeImage) { - xeRenderSystem.loadTexture(xeImage); + xeRenderSystem->loadTexture(1, xeImage); - xeRenderSystem.start(); + xeRenderSystem->start(); UniformBuffer ubo{}; ubo.projectionView = xeCamera.getProjection() * xeCamera.getView(); - xeRenderSystem.loadUniformObject(&ubo); + xeRenderSystem->loadUniformObject(0, &ubo); for(auto &obj : gameObjects) { PushConstant pc{}; pc.modelMatrix = obj.transform.mat4(); pc.normalMatrix = obj.transform.normalMatrix(); - xeRenderSystem.loadPushConstant(&pc); - xeRenderSystem.render(obj); + xeRenderSystem->loadPushConstant(&pc); + xeRenderSystem->render(obj); } - xeRenderSystem.stop(); + xeRenderSystem->stop(); } diff --git a/src/simple_renderer.hpp b/src/simple_renderer.hpp index 20e3997..d9be7b2 100644 --- a/src/simple_renderer.hpp +++ b/src/simple_renderer.hpp @@ -29,7 +29,7 @@ class SimpleRenderer { void render(std::vector &gameObjects, xe::XeCamera &xeCamera, xe::XeImage *xeImage); private: - xe::XeRenderSystem xeRenderSystem; + std::unique_ptr xeRenderSystem; };