diff --git a/config/Sources.cmake b/config/Sources.cmake index e7a36ff1eb287bbbc6e3331adaa84ab476916d21..8fc0aa9a2605a629596e26d5eeb0772164e6ec7a 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -70,4 +70,6 @@ set(vkcv_sources ${vkcv_source}/vkcv/SamplerManager.hpp ${vkcv_source}/vkcv/SamplerManager.cpp + + ${vkcv_include}/vkcv/DescriptorWrites.hpp ) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 6451d81ad3afd3f8154d778c9bceb68cdf34ba73..cf75b8e754513da774ec1841c8c4cc700b99ee2d 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -20,6 +20,7 @@ #include "Result.hpp" #include "vkcv/DescriptorConfig.hpp" #include "Sampler.hpp" +#include "DescriptorWrites.hpp" namespace vkcv { @@ -64,21 +65,21 @@ namespace vkcv Context m_Context; - SwapChain m_swapchain; - std::vector<vk::ImageView> m_swapchainImageViews; - const Window& m_window; + SwapChain m_swapchain; + std::vector<vk::ImageView> m_swapchainImageViews; + const Window& m_window; - std::unique_ptr<PassManager> m_PassManager; - std::unique_ptr<PipelineManager> m_PipelineManager; - std::unique_ptr<DescriptorManager> m_DescriptorManager; - std::unique_ptr<BufferManager> m_BufferManager; - std::unique_ptr<SamplerManager> m_SamplerManager; - std::unique_ptr<ImageManager> m_ImageManager; + std::unique_ptr<PassManager> m_PassManager; + std::unique_ptr<PipelineManager> m_PipelineManager; + std::unique_ptr<DescriptorManager> m_DescriptorManager; + std::unique_ptr<BufferManager> m_BufferManager; + std::unique_ptr<SamplerManager> m_SamplerManager; + std::unique_ptr<ImageManager> m_ImageManager; - CommandResources m_CommandResources; - SyncResources m_SyncResources; - uint32_t m_currentSwapchainImageIndex; - std::vector<vk::Framebuffer> m_TemporaryFramebuffers; + CommandResources m_CommandResources; + SyncResources m_SyncResources; + uint32_t m_currentSwapchainImageIndex; + std::vector<vk::Framebuffer> m_TemporaryFramebuffers; /** * recreates the swapchain @@ -212,7 +213,10 @@ namespace vkcv * @return */ [[nodiscard]] - ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> &descriptorSets); + ResourcesHandle createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets); + void writeResourceDescription(ResourcesHandle handle, size_t setIndex, const DescriptorWrites& writes); + + vk::DescriptorSetLayout getDescritorSetLayout(ResourcesHandle handle, size_t setIndex); /** * @brief start recording command buffers and increment frame index @@ -222,9 +226,18 @@ namespace vkcv /** * @brief render a beautiful triangle */ - void renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, - const int width, const int height, const size_t pushConstantSize, const void* pushConstantData, - const std::vector<VertexBufferBinding> & vertexBufferBindings, const BufferHandle indexBuffer, const size_t indexCount); + void renderMesh( + const PassHandle renderpassHandle, + const PipelineHandle pipelineHandle, + const int width, + const int height, + const size_t pushConstantSize, + const void* pushConstantData, + const std::vector<VertexBufferBinding> &vertexBufferBindings, + const BufferHandle indexBuffer, + const size_t indexCount, + const vkcv::ResourcesHandle resourceHandle, + const size_t resourceDescriptorSetIndex); /** * @brief end recording and present image diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp index 8116259757fe623f97a2814991b226ee27efca50..161273db1ec3bd0be290ecdd1042d12d181d303e 100644 --- a/include/vkcv/DescriptorConfig.hpp +++ b/include/vkcv/DescriptorConfig.hpp @@ -11,7 +11,8 @@ namespace vkcv UNIFORM_BUFFER, STORAGE_BUFFER, SAMPLER, - IMAGE + IMAGE_SAMPLED, + IMAGE_STORAGE }; /* @@ -40,10 +41,9 @@ namespace vkcv * @param[in] a number of bindings that were created beforehand * @param[in] the number of (identical) sets that should be created from the attached bindings */ - struct DescriptorSet + struct DescriptorSetConfig { - DescriptorSet() = delete; - explicit DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept; + explicit DescriptorSetConfig(std::vector<DescriptorBinding> bindings) noexcept; std::vector<DescriptorBinding> bindings; }; diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d67e8e3233e184b207d109e652adeca43407d7e0 --- /dev/null +++ b/include/vkcv/DescriptorWrites.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "Handles.hpp" +#include <vector> + +namespace vkcv { + struct SampledImageDescriptorWrite { + inline SampledImageDescriptorWrite(uint32_t binding, ImageHandle image) : binding(binding), image(image) {}; + uint32_t binding; + ImageHandle image; + }; + + struct StorageImageDescriptorWrite { + inline StorageImageDescriptorWrite(uint32_t binding, ImageHandle image) : binding(binding), image(image) {}; + uint32_t binding; + ImageHandle image; + }; + + struct UniformBufferDescriptorWrite { + inline UniformBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {}; + uint32_t binding; + BufferHandle buffer; + }; + + struct StorageBufferDescriptorWrite { + inline StorageBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {}; + uint32_t binding; + BufferHandle buffer; + }; + + struct SamplerDescriptorWrite { + inline SamplerDescriptorWrite(uint32_t binding, SamplerHandle sampler) : binding(binding), sampler(sampler) {}; + uint32_t binding; + SamplerHandle sampler; + }; + + struct DescriptorWrites { + std::vector<SampledImageDescriptorWrite> sampledImageWrites; + std::vector<StorageImageDescriptorWrite> storageImageWrites; + std::vector<UniformBufferDescriptorWrite> uniformBufferWrites; + std::vector<StorageBufferDescriptorWrite> storageBufferWrites; + std::vector<SamplerDescriptorWrite> samplerWrites; + }; +} \ No newline at end of file diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 5050513b6fd612605b7c83d18d2d3beaaef9a8a0..d56fac9c0e442faeff1898443d737df365c9ed45 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -28,6 +28,9 @@ namespace vkcv { [[nodiscard]] vk::ImageLayout getLayout() const; + + [[nodiscard]] + vkcv::ImageHandle getHandle() const; void switchLayout(vk::ImageLayout newLayout); diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/PipelineConfig.hpp index fdf5df7403ed91fd48eef1e593c567c602957937..a8e1334f3ee5d6774b9fed35edd685f19747814d 100644 --- a/include/vkcv/PipelineConfig.hpp +++ b/include/vkcv/PipelineConfig.hpp @@ -24,17 +24,19 @@ namespace vkcv { * @param passHandle handle for Render Pass */ PipelineConfig( - const ShaderProgram& shaderProgram, - uint32_t width, - uint32_t height, - PassHandle &passHandle, - const std::vector<VertexAttribute> &vertexAttributes); + const ShaderProgram& shaderProgram, + uint32_t width, + uint32_t height, + PassHandle &passHandle, + const std::vector<VertexAttribute> &vertexAttributes, + const std::vector<vk::DescriptorSetLayout> &descriptorLayouts); - ShaderProgram m_ShaderProgram; - uint32_t m_Height; - uint32_t m_Width; - PassHandle m_PassHandle; - std::vector<VertexAttribute> m_vertexAttributes; + ShaderProgram m_ShaderProgram; + uint32_t m_Height; + uint32_t m_Width; + PassHandle m_PassHandle; + std::vector<VertexAttribute> m_vertexAttributes; + std::vector<vk::DescriptorSetLayout> m_descriptorLayouts; }; } \ No newline at end of file diff --git a/projects/first_mesh/resources/shaders/frag.spv b/projects/first_mesh/resources/shaders/frag.spv index 50030afba4d1c527a1f9bc59e16cf50a50f72f94..087e4e22fb2fcec27d99b3ff2aa1a705fe755796 100644 Binary files a/projects/first_mesh/resources/shaders/frag.spv and b/projects/first_mesh/resources/shaders/frag.spv differ diff --git a/projects/first_mesh/resources/shaders/shader.frag b/projects/first_mesh/resources/shaders/shader.frag index ce1efbde47b86321fec089f1b2a7b8380b390a2f..71a1de69c57c0d7b7d4665095410e7acaf8dbd62 100644 --- a/projects/first_mesh/resources/shaders/shader.frag +++ b/projects/first_mesh/resources/shaders/shader.frag @@ -6,7 +6,9 @@ layout(location = 1) in vec2 passUV; layout(location = 0) out vec3 outColor; +layout(set=0, binding=0) uniform texture2D meshTexture; +layout(set=0, binding=1) uniform sampler textureSampler; + void main() { - outColor = 0.5 * passNormal + 0.5; - //outColor = vec3(abs(passUV), 0); + outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb; } \ No newline at end of file diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index fbd32539c9a6b698fd95a2806722e915a4fbdaac..107cd432e1bc902692bb5b1fa694120ddf24038b 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -5,7 +5,6 @@ #include <chrono> #include <vkcv/asset/asset_loader.hpp> - int main(int argc, const char** argv) { const char* applicationName = "First Mesh"; @@ -100,7 +99,19 @@ int main(int argc, const char** argv) { return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); }); - const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass, mesh.vertexGroups[0].vertexBuffer.attributes); + vkcv::DescriptorSetConfig setConfig({ + vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT), + vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT) + }); + vkcv::ResourcesHandle set = core.createResourceDescription({ setConfig }); + + const vkcv::PipelineConfig trianglePipelineDefinition( + triangleShaderProgram, + windowWidth, + windowHeight, + trianglePass, + mesh.vertexGroups[0].vertexBuffer.attributes, + { core.getDescritorSetLayout(set, 0) }); vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); if (!trianglePipeline) { @@ -109,15 +120,26 @@ int main(int argc, const char** argv) { } vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, mesh.texture_hack.w, mesh.texture_hack.h); - texture.fill(mesh.texture_hack.img); + vkcv::SamplerHandle sampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { { mesh.vertexGroups[0].vertexBuffer.attributes[0].offset, vertexBuffer.getHandle() }, { mesh.vertexGroups[0].vertexBuffer.attributes[1].offset, vertexBuffer.getHandle() }, { mesh.vertexGroups[0].vertexBuffer.attributes[2].offset, vertexBuffer.getHandle() } }; + vkcv::DescriptorWrites setWrites; + setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) }; + setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; + core.writeResourceDescription(set, 0, setWrites); + auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { core.beginFrame(); @@ -129,15 +151,17 @@ int main(int argc, const char** argv) { const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); core.renderMesh( - trianglePass, - trianglePipeline, - windowWidth, - windowHeight, - sizeof(mvp), - &mvp, - vertexBufferBindings, - indexBuffer.getHandle(), - mesh.vertexGroups[0].numIndices + trianglePass, + trianglePipeline, + windowWidth, + windowHeight, + sizeof(mvp), + &mvp, + vertexBufferBindings, + indexBuffer.getHandle(), + mesh.vertexGroups[0].numIndices, + set, + 0 ); core.endFrame(); diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index d51d60e4788aeb0271d434520fad29edc3804c55..2c071b727f7e41e7eb4dee17a2da3302f615ffa0 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -5,41 +5,41 @@ #include <chrono> int main(int argc, const char** argv) { - const char* applicationName = "First Triangle"; + const char* applicationName = "First Triangle"; const int windowWidth = 800; const int windowHeight = 600; - vkcv::Window window = vkcv::Window::create( + vkcv::Window window = vkcv::Window::create( applicationName, windowWidth, windowHeight, false - ); + ); - vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); - window.initEvents(); + window.initEvents(); vkcv::Core core = vkcv::Core::create( - window, - applicationName, + window, + applicationName, VK_MAKE_VERSION(0, 0, 1), - {vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, + { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, {}, - {"VK_KHR_swapchain"} + { "VK_KHR_swapchain" } ); - const auto &context = core.getContext(); + const auto& context = core.getContext(); const vk::Instance& instance = context.getInstance(); const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); const vk::Device& device = context.getDevice(); - + struct vec3 { float x, y, z; }; - + const size_t n = 5027; - + auto testBuffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); vec3 vec_data[n]; @@ -58,26 +58,26 @@ int main(int argc, const char** argv) { m[1] = { 0, 0, 0 }; m[2] = { 0, 0, 0 }; buffer.unmap();*/ - + vkcv::SamplerHandle sampler = core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - vkcv::SamplerAddressMode::REPEAT + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerMipmapMode::NEAREST, + vkcv::SamplerAddressMode::REPEAT ); std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl; switch (physicalDevice.getProperties().vendorID) { - case 0x1002: std::cout << "Running AMD huh? You like underdogs, are you a Linux user?" << std::endl; break; - case 0x10DE: std::cout << "An NVidia GPU, how predictable..." << std::endl; break; - case 0x8086: std::cout << "Poor child, running on an Intel GPU, probably integrated..." - "or perhaps you are from the future with a dedicated one?" << std::endl; break; - case 0x13B5: std::cout << "ARM? What the hell are you running on, next thing I know you're trying to run Vulkan on a leg..." << std::endl; break; - default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl; + case 0x1002: std::cout << "Running AMD huh? You like underdogs, are you a Linux user?" << std::endl; break; + case 0x10DE: std::cout << "An NVidia GPU, how predictable..." << std::endl; break; + case 0x8086: std::cout << "Poor child, running on an Intel GPU, probably integrated..." + "or perhaps you are from the future with a dedicated one?" << std::endl; break; + case 0x13B5: std::cout << "ARM? What the hell are you running on, next thing I know you're trying to run Vulkan on a leg..." << std::endl; break; + default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl; } - // an example attachment for passes that output to the window + // an example attachment for passes that output to the window const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentLayout::UNDEFINED, vkcv::AttachmentLayout::COLOR_ATTACHMENT, @@ -86,7 +86,7 @@ int main(int argc, const char** argv) { vkcv::AttachmentOperation::CLEAR, core.getSwapchainImageFormat()); - vkcv::PassConfig trianglePassDefinition({present_color_attachment}); + vkcv::PassConfig trianglePassDefinition({ present_color_attachment }); vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition); if (!trianglePass) @@ -99,9 +99,15 @@ int main(int argc, const char** argv) { triangleShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/vert.spv")); triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/frag.spv")); triangleShaderProgram.reflectShader(vkcv::ShaderStage::VERTEX); - triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT); + triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT); - const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass, {}); + const vkcv::PipelineConfig trianglePipelineDefinition( + triangleShaderProgram, + windowWidth, + windowHeight, + trianglePass, + {}, + {}); vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); if (!trianglePipeline) @@ -110,24 +116,6 @@ int main(int argc, const char** argv) { return EXIT_FAILURE; } - //just an example - //creates 20 descriptor sets, each containing bindings for 50 uniform buffers, images, and samplers - std::vector<vkcv::DescriptorSet> sets; - - for (uint32_t i = 0; i < 20; i++) - { - vkcv::DescriptorBinding uniformBufBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 50, vkcv::ShaderStage::VERTEX); - vkcv::DescriptorBinding storageBufBinding(vkcv::DescriptorType::STORAGE_BUFFER, 50, vkcv::ShaderStage::VERTEX); - vkcv::DescriptorBinding imageBinding(vkcv::DescriptorType::IMAGE, 50, vkcv::ShaderStage::VERTEX); - vkcv::DescriptorBinding samplerBinding(vkcv::DescriptorType::SAMPLER, 50, vkcv::ShaderStage::VERTEX); - - vkcv::DescriptorSet set({uniformBufBinding, storageBufBinding, imageBinding, samplerBinding}); - - sets.push_back(set); - auto resourceHandle = core.createResourceDescription(sets); - std::cout << "Resource " << resourceHandle << " created." << std::endl; - } - std::vector<vkcv::VertexBufferBinding> vertexBufferBindings; /* @@ -157,16 +145,17 @@ int main(int argc, const char** argv) { const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); core.renderMesh( - trianglePass, - trianglePipeline, - windowWidth, - windowHeight, - sizeof(mvp), - &mvp, - vertexBufferBindings, - triangleIndexBuffer.getHandle(), - 3 - ); + trianglePass, + trianglePipeline, + windowWidth, + windowHeight, + sizeof(mvp), + &mvp, + vertexBufferBindings, + triangleIndexBuffer.getHandle(), + 3, + vkcv::ResourcesHandle(), + 0); core.endFrame(); } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index d8a67ebd2160a20a2e9b7c9b2cf81e9d6cab6b07..0b0d3a24f0398a5efa17a4c33110adabbb97c15e 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -173,9 +173,19 @@ namespace vkcv return device.createFramebuffer(createInfo); } - void Core::renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, - const int width, const int height, const size_t pushConstantSize, const void *pushConstantData, - const std::vector<VertexBufferBinding>& vertexBufferBindings, const BufferHandle indexBuffer, const size_t indexCount) { + void Core::renderMesh( + const PassHandle renderpassHandle, + const PipelineHandle pipelineHandle, + const int width, + const int height, + const size_t pushConstantSize, + const void *pushConstantData, + const std::vector<VertexBufferBinding>& vertexBufferBindings, + const BufferHandle indexBuffer, + const size_t indexCount, + const vkcv::ResourcesHandle resourceHandle, + const size_t resourceDescriptorSetIndex + ) { if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; @@ -254,6 +264,11 @@ namespace vkcv cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset)); } + if (resourceHandle) { + const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex); + cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr); + } + cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData); cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {}); @@ -332,8 +347,22 @@ namespace vkcv return Image::create(m_ImageManager.get(), format, width, height, depth); } - ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) + ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets) { return m_DescriptorManager->createResourceDescription(descriptorSets); } + + void Core::writeResourceDescription(ResourcesHandle handle, size_t setIndex, const DescriptorWrites &writes) { + m_DescriptorManager->writeResourceDescription( + handle, + setIndex, + writes, + *m_ImageManager, + *m_BufferManager, + *m_SamplerManager); + } + + vk::DescriptorSetLayout Core::getDescritorSetLayout(ResourcesHandle handle, size_t setIndex) { + return m_DescriptorManager->getDescriptorSetLayout(handle, setIndex); + } } diff --git a/src/vkcv/DescriptorConfig.cpp b/src/vkcv/DescriptorConfig.cpp index f437ab6833edca09f58499b6d74307606bba8999..c4f6e326560e91747d206fecc983525a5b7bb6dc 100644 --- a/src/vkcv/DescriptorConfig.cpp +++ b/src/vkcv/DescriptorConfig.cpp @@ -14,7 +14,7 @@ namespace vkcv { shaderStage{shaderStage} {}; - DescriptorSet::DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept : + DescriptorSetConfig::DescriptorSetConfig(std::vector<DescriptorBinding> bindings) noexcept : bindings{std::move(bindings)} {}; } diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index c42db30fb4d8d72e340a9db53afb3fcf6d1058d0..5cb05f7a34a9daa61631690cceb406582bf58863 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -40,7 +40,7 @@ namespace vkcv m_Device.destroy(m_Pool); } - ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) + ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets) { std::vector<vk::DescriptorSet> vk_sets; std::vector<vk::DescriptorSetLayout> vk_setLayouts; @@ -86,6 +86,105 @@ namespace vkcv return ResourcesHandle(m_NextResourceDescriptionID++); } + void DescriptorManager::writeResourceDescription( + ResourcesHandle handle, + size_t setIndex, + const DescriptorWrites &writes, + const ImageManager &imageManager, + const BufferManager &bufferManager, + const SamplerManager &samplerManager) { + + vk::DescriptorSet set = m_ResourceDescriptions[handle.getId()].descriptorSets[setIndex]; + + std::vector<vk::WriteDescriptorSet> vulkanWrites; + + for (const auto& write : writes.sampledImageWrites) { + vk::DescriptorImageInfo imageInfo( + nullptr, + imageManager.getVulkanImageView(write.image), + vk::ImageLayout::eShaderReadOnlyOptimal); + + vk::WriteDescriptorSet vulkanWrite( + set, + write.binding, + (uint32_t)0, + vk::DescriptorType::eSampledImage, + imageInfo); + vulkanWrites.push_back(vulkanWrite); + } + + for (const auto& write : writes.storageImageWrites) { + vk::DescriptorImageInfo imageInfo( + nullptr, + imageManager.getVulkanImageView(write.image), + vk::ImageLayout::eGeneral); + + vk::WriteDescriptorSet vulkanWrite( + set, + write.binding, + (uint32_t)0, + vk::DescriptorType::eStorageImage, + imageInfo); + vulkanWrites.push_back(vulkanWrite); + } + + for (const auto& write : writes.uniformBufferWrites) { + vk::DescriptorBufferInfo bufferInfo( + bufferManager.getBuffer(write.buffer), + (uint32_t)0, + bufferManager.getBufferSize(write.buffer)); + + vk::WriteDescriptorSet vulkanWrite( + set, + write.binding, + (uint32_t)0, + vk::DescriptorType::eUniformBuffer, + nullptr, + bufferInfo); + vulkanWrites.push_back(vulkanWrite); + } + + for (const auto& write : writes.storageBufferWrites) { + vk::DescriptorBufferInfo bufferInfo( + bufferManager.getBuffer(write.buffer), + (uint32_t)0, + bufferManager.getBufferSize(write.buffer)); + + vk::WriteDescriptorSet vulkanWrite( + set, + write.binding, + (uint32_t)0, + vk::DescriptorType::eStorageBuffer, + nullptr, + bufferInfo); + vulkanWrites.push_back(vulkanWrite); + } + + for (const auto& write : writes.samplerWrites) { + vk::DescriptorImageInfo imageInfo( + samplerManager.getVulkanSampler(write.sampler), + nullptr, + vk::ImageLayout::eGeneral); + + vk::WriteDescriptorSet vulkanWrite( + set, + write.binding, + (uint32_t)0, + vk::DescriptorType::eSampler, + imageInfo); + vulkanWrites.push_back(vulkanWrite); + } + m_Device.updateDescriptorSets(vulkanWrites, nullptr); + } + + vk::DescriptorSet DescriptorManager::getDescriptorSet(ResourcesHandle handle, size_t index) { + return m_ResourceDescriptions[handle.getId()].descriptorSets[index]; + } + + vk::DescriptorSetLayout DescriptorManager::getDescriptorSetLayout(ResourcesHandle handle, size_t index) { + return m_ResourceDescriptions[handle.getId()].descriptorSetLayouts[index]; + } + vk::DescriptorType DescriptorManager::convertDescriptorTypeFlag(DescriptorType type) { switch (type) { @@ -95,9 +194,12 @@ namespace vkcv return vk::DescriptorType::eStorageBuffer; case DescriptorType::SAMPLER: return vk::DescriptorType::eSampler; - case DescriptorType::IMAGE: + case DescriptorType::IMAGE_SAMPLED: return vk::DescriptorType::eSampledImage; + case DescriptorType::IMAGE_STORAGE: + return vk::DescriptorType::eStorageImage; default: + std::cerr << "Error: DescriptorManager::convertDescriptorTypeFlag, unknown DescriptorType" << std::endl; return vk::DescriptorType::eUniformBuffer; } } diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp index 744f557051bee3a6524abcf16822c3faa9c78576..937fb278cda241e9153881d5c27662ac929781cd 100644 --- a/src/vkcv/DescriptorManager.hpp +++ b/src/vkcv/DescriptorManager.hpp @@ -2,6 +2,11 @@ #include "vkcv/Handles.hpp" #include "vkcv/DescriptorConfig.hpp" +#include "vkcv/DescriptorWrites.hpp" + +#include "ImageManager.hpp" +#include "vkcv/BufferManager.hpp" +#include "SamplerManager.hpp" namespace vkcv { @@ -18,11 +23,22 @@ namespace vkcv * @param[in] vector of filled vkcv::DescriptorSet structs * @return index into that objects a resource handle */ - ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> & descriptorSets); + ResourcesHandle createResourceDescription(const std::vector<DescriptorSetConfig> & descriptorSets); + + void writeResourceDescription( + ResourcesHandle handle, + size_t setIndex, + const DescriptorWrites& writes, + const ImageManager& imageManager, + const BufferManager& bufferManager, + const SamplerManager& samplerManager); + + vk::DescriptorSet getDescriptorSet(ResourcesHandle handle, size_t index); + vk::DescriptorSetLayout getDescriptorSetLayout(ResourcesHandle handle, size_t index); private: - vk::Device m_Device; - vk::DescriptorPool m_Pool; + vk::Device m_Device; + vk::DescriptorPool m_Pool; /** diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index c4341b4f173028afa5dce98383b2ae34833ee2fa..7104f784231418da4f1c26364459dbf735fdde97 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -38,6 +38,10 @@ namespace vkcv{ m_manager->switchImageLayout(m_handle, m_layout, newLayout); m_layout = newLayout; } + + vkcv::ImageHandle Image::getHandle() const { + return m_handle; + } void Image::fill(void *data, size_t size) { m_manager->fillImage(m_handle, data, size); diff --git a/src/vkcv/PipelineConfig.cpp b/src/vkcv/PipelineConfig.cpp index b5a8e98cea635005c2cb82c22921e6c6b6b3b8ed..d317258470bde76e8b8ba8e1f9bc684ea469b6c0 100644 --- a/src/vkcv/PipelineConfig.cpp +++ b/src/vkcv/PipelineConfig.cpp @@ -9,15 +9,18 @@ namespace vkcv { PipelineConfig::PipelineConfig( - const ShaderProgram& shaderProgram, - uint32_t width, - uint32_t height, - PassHandle &passHandle, - const std::vector<VertexAttribute> &vertexAttributes): + const ShaderProgram& shaderProgram, + uint32_t width, + uint32_t height, + PassHandle &passHandle, + const std::vector<VertexAttribute> &vertexAttributes, + const std::vector<vk::DescriptorSetLayout> &descriptorLayouts) + : m_ShaderProgram(shaderProgram), m_Height(height), m_Width(width), m_PassHandle(passHandle), - m_vertexAttributes(vertexAttributes) + m_vertexAttributes(vertexAttributes), + m_descriptorLayouts(descriptorLayouts) {} } diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp index ca6d44b5019a634681de05c9d7963f7ff68cc315..1b0d665e9011b9c652a69e35c295a701a6029dd2 100644 --- a/src/vkcv/PipelineManager.cpp +++ b/src/vkcv/PipelineManager.cpp @@ -186,7 +186,7 @@ namespace vkcv // pipeline layout vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( {}, - {}, + (config.m_descriptorLayouts), (pushConstantRange)); vk::PipelineLayout vkPipelineLayout{}; if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)