diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 8a165adf43561b1204490a12afa00d2a3fabdbf4..c21ee3d60169b538da113e2cde802dfbf54a2bb3 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -203,7 +203,7 @@ namespace vkcv * @return Image-Object */ [[nodiscard]] - Image createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1); + Image createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1, bool supportStorage = false, bool supportColorAttachment = false); /** TODO: * @param setDescriptions @@ -211,7 +211,7 @@ namespace vkcv */ [[nodiscard]] DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings); - void writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites& writes); + void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes); DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const; @@ -259,5 +259,6 @@ namespace vkcv void submitCommandStream(const CommandStreamHandle handle); void prepareSwapchainImageForPresent(const CommandStreamHandle handle); void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image); + void prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image); }; } diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index a1219ce4147ebbb8ae0650da8a87766f8967874b..e1eb78ee02ea9142dcbaaa51ab06e3f3bbfa78e1 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -45,7 +45,7 @@ namespace vkcv { Image(ImageManager* manager, const ImageHandle& handle); - static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth); + static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment); }; diff --git a/projects/cmd_sync_test/resources/shaders/compile.bat b/projects/cmd_sync_test/resources/shaders/compile.bat index 516c2f2f78001e1a5d182356e7c3fe82d66a45ee..9ffc664ad1768265f80c6d532ddd848b59238139 100644 --- a/projects/cmd_sync_test/resources/shaders/compile.bat +++ b/projects/cmd_sync_test/resources/shaders/compile.bat @@ -2,4 +2,6 @@ %VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv %VULKAN_SDK%\Bin32\glslc.exe shadow.vert -o shadow_vert.spv %VULKAN_SDK%\Bin32\glslc.exe shadow.frag -o shadow_frag.spv +%VULKAN_SDK%\Bin32\glslc.exe voxelization.vert -o voxelization_vert.spv +%VULKAN_SDK%\Bin32\glslc.exe voxelization.frag -o voxelization_frag.spv pause \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/voxelization.frag b/projects/cmd_sync_test/resources/shaders/voxelization.frag new file mode 100644 index 0000000000000000000000000000000000000000..91575b037ccf364b54113db2ef22ee9f397af6e5 --- /dev/null +++ b/projects/cmd_sync_test/resources/shaders/voxelization.frag @@ -0,0 +1,27 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 passPos; + +layout(set=0, binding=0, r8) uniform image3D voxelImage; +layout(set=0, binding=1) uniform voxelizationInfo{ + float extent; +} voxelInfo; + +vec3 worldToVoxelCoordinates(vec3 world, float voxelExtent){ + return world / voxelExtent + 0.5f; +} + +ivec3 voxelCoordinatesToUV(vec3 voxelCoordinates, ivec3 voxelImageResolution){ + return ivec3(voxelCoordinates * voxelImageResolution); +} + +void main() { + vec3 voxelCoordinates = worldToVoxelCoordinates(passPos, voxelInfo.extent); + ivec3 voxeImageSize = imageSize(voxelImage); + ivec3 UV = voxelCoordinatesToUV(voxelCoordinates, voxeImageSize); + if(any(lessThan(UV, ivec3(0))) || any(greaterThanEqual(UV, voxeImageSize))){ + //return; + } + imageStore(voxelImage, UV, vec4(1)); +} \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/voxelization.vert b/projects/cmd_sync_test/resources/shaders/voxelization.vert new file mode 100644 index 0000000000000000000000000000000000000000..6914e95122125843bdb84baf51c8cfef4c726da5 --- /dev/null +++ b/projects/cmd_sync_test/resources/shaders/voxelization.vert @@ -0,0 +1,18 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inUV; + +layout(location = 0) out vec3 passPos; + +layout( push_constant ) uniform constants{ + mat4 mvp; + mat4 model; +}; + +void main() { + gl_Position = mvp * vec4(inPosition, 1.0); + passPos = (model * vec4(inPosition, 1)).xyz; +} \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/voxelization_frag.spv b/projects/cmd_sync_test/resources/shaders/voxelization_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..2093865dba17592a0d8ba5d4372e6fdf6f578b85 Binary files /dev/null and b/projects/cmd_sync_test/resources/shaders/voxelization_frag.spv differ diff --git a/projects/cmd_sync_test/resources/shaders/voxelization_vert.spv b/projects/cmd_sync_test/resources/shaders/voxelization_vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..bbccee7abd853e0f78d16fecf37dccefc2a13c00 Binary files /dev/null and b/projects/cmd_sync_test/resources/shaders/voxelization_vert.spv differ diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp index a0fb29fafe24a4ae1279161dc8814c0d8f52765f..c6cde4f4e064a62ef357f04e4fbf888640d6a934 100644 --- a/projects/cmd_sync_test/src/main.cpp +++ b/projects/cmd_sync_test/src/main.cpp @@ -63,16 +63,16 @@ int main(int argc, const char** argv) { indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data); - auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; + auto& vertexAttributes = mesh.vertexGroups[0].vertexBuffer.attributes; - std::sort(attributes.begin(), attributes.end(), [](const vkcv::VertexAttribute& x, const vkcv::VertexAttribute& y) { + std::sort(vertexAttributes.begin(), vertexAttributes.end(), [](const vkcv::VertexAttribute& x, const vkcv::VertexAttribute& y) { return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); }); const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::VertexBufferBinding(attributes[0].offset, vertexBuffer.getVulkanHandle()), - vkcv::VertexBufferBinding(attributes[1].offset, vertexBuffer.getVulkanHandle()), - vkcv::VertexBufferBinding(attributes[2].offset, vertexBuffer.getVulkanHandle()) }; + vkcv::VertexBufferBinding(vertexAttributes[0].offset, vertexBuffer.getVulkanHandle()), + vkcv::VertexBufferBinding(vertexAttributes[1].offset, vertexBuffer.getVulkanHandle()), + vkcv::VertexBufferBinding(vertexAttributes[2].offset, vertexBuffer.getVulkanHandle()) }; const vkcv::Mesh loadedMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices); @@ -116,7 +116,7 @@ int main(int argc, const char** argv) { windowWidth, windowHeight, trianglePass, - attributes, + vertexAttributes, { core.getDescriptorSet(descriptorSet).layout }, true); vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); @@ -147,30 +147,6 @@ int main(int argc, const char** argv) { const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); - const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); - - const std::vector<glm::vec3> instancePositions = { - glm::vec3( 0.f, -2.f, 0.f), - glm::vec3( 3.f, 0.f, 0.f), - glm::vec3(-3.f, 0.f, 0.f), - glm::vec3( 0.f, 2.f, 0.f), - glm::vec3( 0.f, -5.f, 0.f) - }; - - std::vector<glm::mat4> modelMatrices; - std::vector<vkcv::DrawcallInfo> drawcalls; - std::vector<vkcv::DrawcallInfo> shadowDrawcalls; - for (const auto& position : instancePositions) { - modelMatrices.push_back(glm::translate(glm::mat4(1.f), position)); - drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage })); - shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {})); - } - - modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f)); - - std::vector<std::array<glm::mat4, 2>> mainPassMatrices; - std::vector<glm::mat4> mvpLight; - vkcv::ShaderProgram shadowShader; shadowShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow_vert.spv"); shadowShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow_frag.spv"); @@ -191,7 +167,7 @@ int main(int argc, const char** argv) { shadowMapResolution, shadowMapResolution, shadowPass, - attributes, + vertexAttributes, {}, false); const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig); @@ -212,7 +188,79 @@ int main(int argc, const char** argv) { vkcv::SamplerDescriptorWrite(1, sampler), vkcv::SamplerDescriptorWrite(4, shadowSampler) }; setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) }; - core.writeResourceDescription(descriptorSet, 0, setWrites); + core.writeDescriptorSet(descriptorSet, setWrites); + + const uint32_t voxelResolution = 32; + vkcv::Image voxelImage = core.createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true); + + const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; + vkcv::Image voxelizationDummyRenderTarget = core.createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true); + + vkcv::ShaderProgram voxelizationShader; + voxelizationShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/voxelization_vert.spv"); + voxelizationShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/voxelization_frag.spv"); + voxelizationShader.reflectShader(vkcv::ShaderStage::VERTEX); + voxelizationShader.reflectShader(vkcv::ShaderStage::FRAGMENT); + + vkcv::PassConfig voxelizationPassConfig({ + vkcv::AttachmentDescription(vkcv::AttachmentOperation::DONT_CARE, vkcv::AttachmentOperation::DONT_CARE, voxelizationDummyFormat)}); + vkcv::PassHandle voxelizationPass = core.createPass(voxelizationPassConfig); + + std::vector<vkcv::DescriptorBinding> voxelizationDescriptorBindings = { + vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_STORAGE, 1, vkcv::ShaderStage::FRAGMENT), + vkcv::DescriptorBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 1, vkcv::ShaderStage::FRAGMENT)}; + vkcv::DescriptorSetHandle voxelizationDescriptorSet = core.createDescriptorSet(voxelizationDescriptorBindings); + + const vkcv::PipelineConfig voxelizationPipeConfig( + voxelizationShader, + voxelResolution, + voxelResolution, + voxelizationPass, + vertexAttributes, + { core.getDescriptorSet(voxelizationDescriptorSet).layout }, + false); + const vkcv::PipelineHandle voxelizationPipe = core.createGraphicsPipeline(voxelizationPipeConfig); + + struct VoxelizationInfo { + float extent; + }; + vkcv::Buffer voxelizationInfoBuffer = core.createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, sizeof(VoxelizationInfo)); + const float voxelizationExtent = 10.f; + VoxelizationInfo voxelizationInfo; + voxelizationInfo.extent = voxelizationExtent; + voxelizationInfoBuffer.fill({ voxelizationInfo }); + + vkcv::DescriptorWrites voxelizationDescriptorWrites; + voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, voxelImage.getHandle()) }; + voxelizationDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(1, voxelizationInfoBuffer.getHandle()) }; + core.writeDescriptorSet(voxelizationDescriptorSet, voxelizationDescriptorWrites); + + const std::vector<glm::vec3> instancePositions = { + glm::vec3(0.f, -2.f, 0.f), + glm::vec3(3.f, 0.f, 0.f), + glm::vec3(-3.f, 0.f, 0.f), + glm::vec3(0.f, 2.f, 0.f), + glm::vec3(0.f, -5.f, 0.f) + }; + + const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, core.getDescriptorSet(voxelizationDescriptorSet).vulkanHandle); + + std::vector<glm::mat4> modelMatrices; + std::vector<vkcv::DrawcallInfo> drawcalls; + std::vector<vkcv::DrawcallInfo> shadowDrawcalls; + std::vector<vkcv::DrawcallInfo> voxelizationDrawcalls; + for (const auto& position : instancePositions) { + modelMatrices.push_back(glm::translate(glm::mat4(1.f), position)); + drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage })); + shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {})); + voxelizationDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { voxelizationDescriptorUsage })); + } + modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f)); + + std::vector<std::array<glm::mat4, 2>> mainPassMatrices; + std::vector<glm::mat4> mvpLight; + std::vector<std::array<glm::mat4, 2>> voxelizationMatrices; auto start = std::chrono::system_clock::now(); const auto appStartTime = start; @@ -247,7 +295,7 @@ int main(int argc, const char** argv) { shadowProjectionSize, -shadowProjectionSize, shadowProjectionSize); - + glm::mat4 vulkanCorrectionMatrix(1.f); vulkanCorrectionMatrix[2][2] = 0.5; vulkanCorrectionMatrix[3][2] = 0.5; @@ -260,17 +308,29 @@ int main(int argc, const char** argv) { const glm::mat4 viewProjectionCamera = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); + const float voxelizationHalfExtent = 0.5f * voxelizationExtent; + const glm::mat4 voxelizationProjection = vulkanCorrectionMatrix * glm::ortho( + -voxelizationHalfExtent, + voxelizationHalfExtent, + -voxelizationHalfExtent, + voxelizationHalfExtent, + -voxelizationHalfExtent, + voxelizationHalfExtent); + mainPassMatrices.clear(); mvpLight.clear(); + voxelizationMatrices.clear(); for (const auto& m : modelMatrices) { mainPassMatrices.push_back({ viewProjectionCamera * m, m }); mvpLight.push_back(lightInfo.lightMatrix* m); + voxelizationMatrices.push_back({ voxelizationProjection * m, m }); } vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; - vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); + const vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); + const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4)); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); @@ -282,6 +342,15 @@ int main(int argc, const char** argv) { shadowDrawcalls, { shadowMap.getHandle() }); + core.prepareImageForStorage(cmdStream, voxelImage.getHandle()); + core.recordDrawcallsToCmdStream( + cmdStream, + voxelizationPass, + voxelizationPipe, + voxelizationPushConstantData, + voxelizationDrawcalls, + { voxelizationDummyRenderTarget.getHandle() }); + core.prepareImageForSampling(cmdStream, shadowMap.getHandle()); core.recordDrawcallsToCmdStream( diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 599eae46ca0243d7eaacc06ec59c713edd5f1e72..bf2967105f76d8863817eb232611d8a5cdecdb56 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -133,7 +133,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorWrites setWrites; setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) }; setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; - core.writeResourceDescription(descriptorSet, 0, setWrites); + core.writeDescriptorSet(descriptorSet, setWrites); vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index b53a1a2c2db1008e7c69c880ef1c5a608d879021..a0b2e0a390297228723fc880448429216ca936ff 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -275,7 +275,12 @@ namespace vkcv deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); #endif - + + // FIXME: check if device feature is supported + vk::PhysicalDeviceFeatures deviceFeatures; + deviceFeatures.fragmentStoresAndAtomics = true; + deviceCreateInfo.pEnabledFeatures = &deviceFeatures; + // Ablauf // qCreateInfos erstellen --> braucht das Device // device erstellen diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 9ed83d2a224119bd20fcfc81c5720b425de06bb6..b7fc5aa9459436c8d90d968d455d3778f818a5ca 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -217,7 +217,7 @@ namespace vkcv targetHandle = m_ImageManager->getVulkanImageView(handle); const bool isDepthImage = isDepthFormat(m_ImageManager->getImageFormat(handle)); const vk::ImageLayout targetLayout = - isDepthFormat ? vk::ImageLayout::eDepthStencilAttachmentOptimal : vk::ImageLayout::eColorAttachmentOptimal; + isDepthImage ? vk::ImageLayout::eDepthStencilAttachmentOptimal : vk::ImageLayout::eColorAttachmentOptimal; m_ImageManager->recordImageLayoutTransition(handle, targetLayout, cmdBuffer); } attachmentsViews.push_back(targetHandle); @@ -392,9 +392,9 @@ namespace vkcv return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode); } - Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth) + Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment) { - return Image::create(m_ImageManager.get(), format, width, height, depth); + return Image::create(m_ImageManager.get(), format, width, height, depth, supportStorage, supportColorAttachment); } DescriptorSetHandle Core::createDescriptorSet(const std::vector<DescriptorBinding>& bindings) @@ -402,10 +402,9 @@ namespace vkcv return m_DescriptorManager->createDescriptorSet(bindings); } - void Core::writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites &writes) { - m_DescriptorManager->writeResourceDescription( + void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) { + m_DescriptorManager->writeDescriptorSet( handle, - setIndex, writes, *m_ImageManager, *m_BufferManager, @@ -465,4 +464,10 @@ namespace vkcv m_ImageManager->recordImageLayoutTransition(image, vk::ImageLayout::eShaderReadOnlyOptimal, cmdBuffer); }, nullptr); } + + void Core::prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image) { + recordCommandsToStream(cmdStream, [image, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition(image, vk::ImageLayout::eGeneral, cmdBuffer); + }, nullptr); + } } diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index a2efecbe7055122d28a864b7c722a5998be460e4..7d3ebe6a208e1fd1497c0aa596d985a37f49a786 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -90,9 +90,8 @@ namespace vkcv vk::DescriptorType type; }; - void DescriptorManager::writeResourceDescription( + void DescriptorManager::writeDescriptorSet( const DescriptorSetHandle &handle, - size_t setIndex, const DescriptorWrites &writes, const ImageManager &imageManager, const BufferManager &bufferManager, diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp index d8607b9312b25e71c7eb4af009efd92b834b40ec..d18be64f3b069af68cecce68f6fa623c81f8dfa4 100644 --- a/src/vkcv/DescriptorManager.hpp +++ b/src/vkcv/DescriptorManager.hpp @@ -23,9 +23,8 @@ namespace vkcv DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &descriptorBindings); - void writeResourceDescription( + void writeDescriptorSet( const DescriptorSetHandle &handle, - size_t setIndex, const DescriptorWrites &writes, const ImageManager &imageManager, const BufferManager &bufferManager, diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index f861daeb1cd7de9697e2f649de444666b8b0e63c..9f7fdadc7400fd3e63061f1e40cd494db63a7869 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -19,9 +19,9 @@ namespace vkcv{ } } - Image Image::create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth) + Image Image::create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth, bool supportStorage, bool supportColorAttachment) { - return Image(manager, manager->createImage(width, height, depth, format)); + return Image(manager, manager->createImage(width, height, depth, format, supportStorage, supportColorAttachment)); } vk::Format Image::getFormat() const { diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index cdfd32b009a8007b606c86bf087b3f921b2bb89f..8084937538a96255b15e7390b8baddf9683f0ca4 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -80,7 +80,7 @@ namespace vkcv { } } - ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format) + ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format, bool supportStorage, bool supportColorAttachment) { const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice(); @@ -90,6 +90,12 @@ namespace vkcv { vk::ImageUsageFlags imageUsageFlags = ( vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst ); + if (supportStorage) { + imageUsageFlags |= vk::ImageUsageFlagBits::eStorage; + } + if (supportColorAttachment) { + imageUsageFlags |= vk::ImageUsageFlagBits::eColorAttachment; + } const bool isDepthFormat = isDepthImageFormat(format); diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index b9fccb25ec16bc1fd9569ab1a94627bd7ff06b18..316ad2312c0bd26f6ecd06a664042b8b51d946d5 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -67,7 +67,7 @@ namespace vkcv { ImageManager& operator=(ImageManager&& other) = delete; ImageManager& operator=(const ImageManager& other) = delete; - ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format); + ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format, bool supportStorage, bool supportColorAttachment); ImageHandle createSwapchainImage();