diff --git a/openVulkanoCpp/Scene/Geometry.cpp b/openVulkanoCpp/Scene/Geometry.cpp index 9049972..e601b3d 100644 --- a/openVulkanoCpp/Scene/Geometry.cpp +++ b/openVulkanoCpp/Scene/Geometry.cpp @@ -13,7 +13,7 @@ #include #include #include -#define ASSIMP_AVAILABLE +//#define ASSIMP_AVAILABLE #endif #include diff --git a/openVulkanoCpp/Scene/Texture.hpp b/openVulkanoCpp/Scene/Texture.hpp new file mode 100644 index 0000000..e1e427d --- /dev/null +++ b/openVulkanoCpp/Scene/Texture.hpp @@ -0,0 +1,24 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "UpdateFrequency.hpp" +#include "Base/ICloseable.hpp" + +namespace openVulkanoCpp::Scene +{ + struct Texture + { + ICloseable* renderTexture = nullptr; + void* textureBuffer; + Math::Vector3ui resolution; + size_t size; + bool updated = true; + UpdateFrequency updateFrequency = UpdateFrequency::Never; + ICloseable* vulkanTexture = nullptr; + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Image.cpp b/openVulkanoCpp/Vulkan/Image.cpp index ff73710..7567f23 100644 --- a/openVulkanoCpp/Vulkan/Image.cpp +++ b/openVulkanoCpp/Vulkan/Image.cpp @@ -34,6 +34,52 @@ namespace openVulkanoCpp::Vulkan {}, nullptr, nullptr, imgMemBarrier); } + void Image::Init(const Device* device, const vk::Extent3D& resolution) + { + this->device = device->device; + + vk::ImageCreateInfo imgCreateInfo; + imgCreateInfo.imageType = vk::ImageType::e2D; + imgCreateInfo.extent = resolution; + imgCreateInfo.mipLevels = 1; + imgCreateInfo.arrayLayers = 1; + imgCreateInfo.format = vk::Format::eR8G8B8Srgb; + imgCreateInfo.tiling = vk::ImageTiling::eOptimal; + imgCreateInfo.initialLayout = vk::ImageLayout::eUndefined; + imgCreateInfo.usage = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled; + imgCreateInfo.sharingMode = vk::SharingMode::eExclusive; + imgCreateInfo.samples = vk::SampleCountFlagBits::e1; + + vk::ImageViewCreateInfo imgViewCreateInfo; + imgViewCreateInfo.image = image; + imgViewCreateInfo.format = imgCreateInfo.format; + imgViewCreateInfo.viewType = vk::ImageViewType::e2D; + imgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + imgViewCreateInfo.subresourceRange.baseMipLevel = 0; + imgViewCreateInfo.subresourceRange.levelCount = 1; + imgViewCreateInfo.subresourceRange.baseArrayLayer = 0; + imgViewCreateInfo.subresourceRange.levelCount = 1; + + Init(device, imgCreateInfo, imgViewCreateInfo); + CreateSampler(); + } + + void Image::CreateSampler() + { + vk::SamplerCreateInfo samplerCreateInfo; + samplerCreateInfo.magFilter = vk::Filter::eLinear; + samplerCreateInfo.minFilter = vk::Filter::eLinear; + samplerCreateInfo.mipmapMode = vk::SamplerMipmapMode::eLinear; + samplerCreateInfo.addressModeU = vk::SamplerAddressMode::eClampToEdge; + samplerCreateInfo.addressModeV = vk::SamplerAddressMode::eClampToEdge; + samplerCreateInfo.addressModeW = vk::SamplerAddressMode::eClampToEdge; + samplerCreateInfo.borderColor = vk::BorderColor::eFloatTransparentBlack; + samplerCreateInfo.unnormalizedCoordinates = false; + samplerCreateInfo.compareEnable = false; + + sampler = this->device.createSampler(samplerCreateInfo); + } + void Image::Close() { if(sampler) diff --git a/openVulkanoCpp/Vulkan/Image.hpp b/openVulkanoCpp/Vulkan/Image.hpp index 8d2eeee..fb74dc7 100644 --- a/openVulkanoCpp/Vulkan/Image.hpp +++ b/openVulkanoCpp/Vulkan/Image.hpp @@ -38,6 +38,8 @@ namespace openVulkanoCpp::Vulkan */ void Init(const Device* device, const vk::ImageCreateInfo& imageCreateInfo, vk::ImageViewCreateInfo imageViewCreateInfo, const vk::MemoryPropertyFlags& memoryPropertyFlags = vk::MemoryPropertyFlagBits::eDeviceLocal); + void Init(const Device* device, const vk::Extent3D& resolution); + void SetLayout(vk::CommandBuffer& cmdBuffer, vk::ImageSubresourceRange subResourceRange, vk::ImageLayout newLayout, vk::ImageLayout oldLayout = vk::ImageLayout::eUndefined) const; void SetLayout(vk::CommandBuffer& cmdBuffer, vk::ImageAspectFlags aspectMask, vk::ImageLayout newLayout, vk::ImageLayout oldLayout = vk::ImageLayout::eUndefined) const @@ -45,6 +47,8 @@ namespace openVulkanoCpp::Vulkan SetLayout(cmdBuffer, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1), newLayout, oldLayout); } + void CreateSampler(); + void Close() override; operator bool() const { return image.operator bool(); } @@ -53,5 +57,7 @@ namespace openVulkanoCpp::Vulkan vk::Image GetImage() override { return image; } vk::ImageView GetView() override { return view; } + + ~Image() override { Close(); } }; } diff --git a/openVulkanoCpp/Vulkan/Pipeline.hpp b/openVulkanoCpp/Vulkan/Pipeline.hpp index ea64a03..8e3808b 100644 --- a/openVulkanoCpp/Vulkan/Pipeline.hpp +++ b/openVulkanoCpp/Vulkan/Pipeline.hpp @@ -38,6 +38,7 @@ namespace openVulkanoCpp::Vulkan vk::PushConstantRange camPushConstantDescFrag = { vk::ShaderStageFlagBits::eFragment, camPushConstantDesc.size, camPushConstantDesc.size }; std::array camPushConstantDescs = { camPushConstantDesc, camPushConstantDescFrag }; vk::DescriptorSetLayoutBinding nodeLayoutBinding = { 0, vk::DescriptorType::eUniformBufferDynamic, 1, vk::ShaderStageFlagBits::eVertex }; + //vk::DescriptorSetLayoutBinding textureLayoutBinding = { 0, vk::DescriptorType::image }; std::array layoutBindings = { nodeLayoutBinding }; vk::DescriptorSetLayoutCreateInfo dslci = { {}, layoutBindings.size(), layoutBindings.data() }; descriptorSetLayout = device.createDescriptorSetLayout(dslci); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index fa9585d..d4870f3 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -6,10 +6,14 @@ #include "ResourceManager.hpp" #include "Scene/Vertex.hpp" +#include "Scene/Geometry.hpp" +#include "Scene/Material.hpp" #include "Vulkan/Context.hpp" #include "Vulkan/Scene/VulkanShader.hpp" #include "Vulkan/Scene/VulkanGeometry.hpp" #include "Vulkan/Scene/VulkanNode.hpp" +#include "Vulkan/Scene/VulkanTexture.hpp" +#include "Vulkan/Image.hpp" namespace openVulkanoCpp::Vulkan { @@ -115,6 +119,10 @@ namespace openVulkanoCpp::Vulkan { material->shader->renderShader = CreateShader(material->shader); } + if (material->texture && !material->texture->renderTexture) + { + material->texture->renderTexture = PrepareTexture(material->texture); + } } void ResourceManager::PrepareNode(Scene::Node* node) @@ -159,7 +167,7 @@ namespace openVulkanoCpp::Vulkan } } } - ManagedBuffer* buffer = CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent); + ManagedBuffer* buffer = CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/); return buffer; } @@ -196,6 +204,17 @@ namespace openVulkanoCpp::Vulkan toFree[currentBuffer].clear(); } + void ResourceManager::CopyDataToImage(vk::DeviceSize size, void* data, Image* image) + { + ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + uploadBuffer->Copy(data, size, 0); + + vk::BufferImageCopy region(0, 0, 0, { vk::ImageAspectFlagBits::eColor, 0, 0, 1 }, { 0, 0, 0 }, image->extent); + cmdBuffers[currentBuffer].copyBufferToImage(uploadBuffer->buffer, image->image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion); + + FreeBuffer(uploadBuffer); + } + ManagedBuffer* ResourceManager::CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, void* data) { ManagedBuffer* target = CreateBuffer(size, usage | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal); @@ -253,4 +272,14 @@ namespace openVulkanoCpp::Vulkan shaders.push_back(vkShader); return vkShader; } + + VulkanTexture* ResourceManager::PrepareTexture(Scene::Texture* texture) + { + VulkanTexture* vkTexture = new VulkanTexture(); + + vkTexture->Init(this, texture); + //vkTexture-> + + return vkTexture; + } } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index e2f3877..b1b656e 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -10,6 +10,7 @@ #include "Base/ICloseable.hpp" #include "IShaderOwner.hpp" #include "ManagedResource.hpp" +#include "Vulkan/Image.hpp" #include #include @@ -20,11 +21,13 @@ namespace openVulkanoCpp class Node; class Geometry; class Material; + class Texture; } namespace Vulkan { class VulkanGeometry; + class VulkanTexture; class ResourceManager : virtual public ICloseable, virtual public IShaderOwner { @@ -68,12 +71,20 @@ namespace openVulkanoCpp void PrepareNode(Scene::Node* node); + VulkanTexture* PrepareTexture(Scene::Texture* texture); + void RemoveShader(VulkanShader* shader) override; + void CopyDataToImage(vk::DeviceSize size, void* data, openVulkanoCpp::Vulkan::Image* image); + ManagedBuffer* CreateSharedMemoryBuffer(size_t size); void FreeBuffer(ManagedBuffer* buffer); + [[nodiscard]] Context* GetContext() const { return context; } + + [[nodiscard]] vk::Device GetDevice() const { return device; } + protected: // Allocation management void DoFreeBuffer(ManagedBuffer* buffer); diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp new file mode 100644 index 0000000..860e3be --- /dev/null +++ b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp @@ -0,0 +1,56 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "IRecordable.hpp" +#include "Vulkan/Image.hpp" +#include "Vulkan/Context.hpp" +#include "Vulkan/Resources/ResourceManager.hpp" +#include "Scene/Texture.hpp" + +namespace openVulkanoCpp::Vulkan +{ + struct VulkanTexture : IRecordable, Image + { + Scene::Texture* m_texture = nullptr; + + virtual void Init(ResourceManager* resManager, Scene::Texture* texture) + { + this->m_texture = texture; + Image::Init(resManager->GetContext()->device.get(), { texture->resolution.x, texture->resolution.y, texture->resolution.z }); + resManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this); + texture->updated = false; + } + + void Record(vk::CommandBuffer& cmdBuffer, uint32_t bufferId) override + { + //cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, ) + } + }; + + struct VulkanTextureDynamic : VulkanTexture + { + uint32_t lastUpdate = -1; + ResourceManager* resourceManager; + + void Init(ResourceManager* resManager, Scene::Texture* texture) override + { + resourceManager = resManager; + VulkanTexture::Init(resourceManager, texture); + lastUpdate = -1; + } + + void Record(vk::CommandBuffer& cmdBuffer, uint32_t bufferId) override + { + if(bufferId != lastUpdate && m_texture->updated) + { + lastUpdate = bufferId; + resourceManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this); + m_texture->updated = false; + } + VulkanTexture::Record(cmdBuffer, bufferId); + } + }; +} \ No newline at end of file