From 3e736725382272f9001d98218255127a85179695 Mon Sep 17 00:00:00 2001 From: GeorgH93 Date: Thu, 4 Jul 2024 17:00:46 +0200 Subject: [PATCH] Texture implementation basics --- .../ExampleApps/TexturedCubeExampleApp.cpp | 12 ++++---- openVulkanoCpp/Scene/Shader/Shader.hpp | 2 +- openVulkanoCpp/Scene/Textrue.cpp | 30 +++++++++++++++++++ openVulkanoCpp/Scene/Texture.hpp | 20 ++++++++++--- openVulkanoCpp/Scene/UpdateFrequency.hpp | 2 ++ openVulkanoCpp/Vulkan/Image.cpp | 25 ++++++---------- .../Vulkan/Resources/ResourceManager.cpp | 20 +++++++++++-- .../Vulkan/Resources/ResourceManager.hpp | 1 + openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp | 29 +++++++++++++----- 9 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 openVulkanoCpp/Scene/Textrue.cpp diff --git a/examples/ExampleApps/TexturedCubeExampleApp.cpp b/examples/ExampleApps/TexturedCubeExampleApp.cpp index f63e958..39c6906 100644 --- a/examples/ExampleApps/TexturedCubeExampleApp.cpp +++ b/examples/ExampleApps/TexturedCubeExampleApp.cpp @@ -35,7 +35,6 @@ namespace OpenVulkano Shader shader; SimpleDrawable drawable; Node node; - Vector3f_SIMD position = {0, 0, -10}; OpenVulkano::Scene::UI::SimpleUi m_ui; std::shared_ptr m_perfInfo; @@ -43,14 +42,15 @@ namespace OpenVulkano public: void Init() override { - std::srand(1); // Fix seed for random numbers scene.Init(); cam.Init(70, 16, 9, 0.1f, 100); scene.SetCamera(&cam); shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/basic"); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic"); + shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basicTexture"); shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - Geometry* geo = GeometryFactory::MakeCube(1, 1, 1, Vector4f((std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, 1)); + shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); + Geometry* geo = GeometryFactory::MakeCube(); + mat.texture = &Texture::PLACEHOLDER; drawable.Init(&shader, geo, &mat); node.Init(); scene.GetRoot()->AddChild(&node); @@ -60,10 +60,10 @@ namespace OpenVulkano GetGraphicsAppManager()->GetRenderer()->SetScene(&scene); camController.Init(&cam); - camController.SetDefaultKeybindings(); + //camController.SetDefaultKeybindings(); camController.SetPosition({0, 0, 2}); - std::shared_ptr m_perfInfo = std::make_shared(); + m_perfInfo = std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } diff --git a/openVulkanoCpp/Scene/Shader/Shader.hpp b/openVulkanoCpp/Scene/Shader/Shader.hpp index 00f4d26..b7632c2 100644 --- a/openVulkanoCpp/Scene/Shader/Shader.hpp +++ b/openVulkanoCpp/Scene/Shader/Shader.hpp @@ -127,7 +127,7 @@ namespace OpenVulkano::Scene { CheckShaderInitState(); if (setId < 0) setId = static_cast(descriptorSets.size() + 2); - if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1!"); + if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1! They are used for node and camera!"); setId -= 2; while (setId >= static_cast(descriptorSets.size())) { diff --git a/openVulkanoCpp/Scene/Textrue.cpp b/openVulkanoCpp/Scene/Textrue.cpp new file mode 100644 index 0000000..afa5dcd --- /dev/null +++ b/openVulkanoCpp/Scene/Textrue.cpp @@ -0,0 +1,30 @@ +/* + * 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 "Texture.hpp" + +namespace OpenVulkano::Scene +{ + Texture Texture::PLACEHOLDER = Texture(true); + + void Texture::MakePlaceholder(uint32_t width, uint32_t height, Math::Vector4uc color1, Math::Vector4uc color2) + { + if (textureBuffer) throw std::runtime_error("Texture data already initialized"); + Math::Vector4uc* imageMemory = new Math::Vector4uc[width * height](); + for (uint32_t row = 0; row < height; row++) + { + for (uint32_t col = 0; col < width; col++) + { + imageMemory[row * width + col] = (((row & 0x10) == 0) ^ ((col & 0x10) == 0 )) ? color2 : color1; + } + } + textureBuffer = imageMemory; + resolution = {width, height, 1}; + size = sizeof(Math::Vector4uc) * width * height; + format = DataFormat::B8G8R8A8_UNORM; + + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/Texture.hpp b/openVulkanoCpp/Scene/Texture.hpp index 7833b33..205f26c 100644 --- a/openVulkanoCpp/Scene/Texture.hpp +++ b/openVulkanoCpp/Scene/Texture.hpp @@ -9,18 +9,30 @@ #include "UpdateFrequency.hpp" #include "Base/ICloseable.hpp" #include "Math/Math.hpp" +#include "DataFormat.hpp" +#include "Scene/Shader/DescriptorInputDescription.hpp" namespace OpenVulkano::Scene { class Texture { public: + static Texture PLACEHOLDER; + static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_COMBINED_IMAGE_SAMPLER, 1, ShaderProgramType::ALL_GRAPHICS }; + + Texture(bool placeholder = false) { if (placeholder) MakePlaceholder(); } + ICloseable* renderTexture = nullptr; - void* textureBuffer; - Math::Vector3ui resolution; - size_t size; + void* textureBuffer = nullptr; + Math::Vector3ui resolution = {0,0,0}; + size_t size = 0; + DataFormat format = DataFormat::B8G8R8A8_UNORM; bool updated = true; UpdateFrequency updateFrequency = UpdateFrequency::Never; - ICloseable* vulkanTexture = nullptr; + + + + void MakePlaceholder(uint32_t width = 128, uint32_t height = 128, + Math::Vector4uc color1 = {255, 135, 255, 255}, Math::Vector4uc color2 = {255, 225, 255, 255}); }; } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/UpdateFrequency.hpp b/openVulkanoCpp/Scene/UpdateFrequency.hpp index 71a91ea..a7bfeda 100644 --- a/openVulkanoCpp/Scene/UpdateFrequency.hpp +++ b/openVulkanoCpp/Scene/UpdateFrequency.hpp @@ -6,6 +6,8 @@ #pragma once +#include + namespace OpenVulkano::Scene { enum class UpdateFrequency : uint8_t diff --git a/openVulkanoCpp/Vulkan/Image.cpp b/openVulkanoCpp/Vulkan/Image.cpp index 29ab8b9..e1616c2 100644 --- a/openVulkanoCpp/Vulkan/Image.cpp +++ b/openVulkanoCpp/Vulkan/Image.cpp @@ -16,6 +16,7 @@ namespace OpenVulkano::Vulkan format = imageCreateInfo.format; extent = imageCreateInfo.extent; + // TODO allocate from resource manager const vk::MemoryRequirements memRequirements = device->device.getImageMemoryRequirements(image); size = allocSize = memRequirements.size; const vk::MemoryAllocateInfo memAllocInfo = { allocSize, device->GetMemoryType(memRequirements.memoryTypeBits, memoryPropertyFlags) }; @@ -38,27 +39,19 @@ namespace OpenVulkano::Vulkan { 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::ImageCreateInfo imgCreateInfo { {}, vk::ImageType::e2D, vk::Format::eB8G8R8A8Unorm, resolution, 1, 1 }; - vk::ImageViewCreateInfo imgViewCreateInfo; - imgViewCreateInfo.image = image; - imgViewCreateInfo.format = imgCreateInfo.format; - imgViewCreateInfo.viewType = vk::ImageViewType::e2D; + imgCreateInfo.usage = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled; + imgCreateInfo.tiling = vk::ImageTiling::eOptimal; + imgCreateInfo.sharingMode = vk::SharingMode::eExclusive; + imgCreateInfo.initialLayout = vk::ImageLayout::eUndefined; + + vk::ImageViewCreateInfo imgViewCreateInfo { {}, image, vk::ImageViewType::e2D, imgCreateInfo.format }; imgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; imgViewCreateInfo.subresourceRange.baseMipLevel = 0; imgViewCreateInfo.subresourceRange.levelCount = 1; imgViewCreateInfo.subresourceRange.baseArrayLayer = 0; - imgViewCreateInfo.subresourceRange.levelCount = 1; + imgViewCreateInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; Init(device, imgCreateInfo, imgViewCreateInfo); CreateSampler(); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 2e54ebc..9870af3 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -148,7 +148,7 @@ namespace OpenVulkano::Vulkan const std::unique_lock lock(mutex); if (material->texture && !material->texture->renderTexture) { - material->texture->renderTexture = PrepareTexture(material->texture); + PrepareTexture(material->texture); } } @@ -291,6 +291,21 @@ namespace OpenVulkano::Vulkan 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); + vk::ImageMemoryBarrier barrier {}; + barrier.oldLayout = vk::ImageLayout::eUndefined; + barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; + barrier.image = image->image; + barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.setSrcAccessMask({}); + barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite); + + // TODO set access masks for mip and array layers + cmdBuffers[currentBuffer].pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier ); + FreeBuffer(uploadBuffer); } @@ -365,8 +380,7 @@ namespace OpenVulkano::Vulkan { VulkanTexture* vkTexture = new VulkanTexture(); - vkTexture->Init(this, texture); - //vkTexture-> + vkTexture->Init(this, texture, GetDescriptorLayoutSet(Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING, 2); return vkTexture; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 7c73dcf..1b7ce9d 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -40,6 +40,7 @@ namespace OpenVulkano class ResourceManager : public ICloseable, public IShaderOwner { friend UniformBuffer; + friend VulkanTexture; Context* context; vk::Device device = nullptr; diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp index ec39cce..52c7ff8 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp @@ -10,6 +10,7 @@ #include "Vulkan/Image.hpp" #include "Vulkan/Context.hpp" #include "Vulkan/Resources/ResourceManager.hpp" +#include "Vulkan/Scene/VulkanShader.hpp" #include "Scene/Texture.hpp" namespace OpenVulkano::Vulkan @@ -18,22 +19,36 @@ namespace OpenVulkano::Vulkan { public: Scene::Texture* m_texture = nullptr; + vk::DescriptorSet m_descriptorSet; + uint32_t m_setId; - virtual void Init(ResourceManager* resManager, Scene::Texture* texture) + virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId) { - this->m_texture = texture; + m_texture = texture; + m_setId = setId; 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; + + // Setup Descriptor set + const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout }; + m_descriptorSet = resManager->GetContext()->device->device.allocateDescriptorSets(descSetAllocInfo)[0]; + vk::DescriptorImageInfo imageInfo = { sampler, view, vk::ImageLayout::eShaderReadOnlyOptimal }; + vk::WriteDescriptorSet writeDescriptorSet = { m_descriptorSet, binding.bindingId, 0, 1 }; + writeDescriptorSet.descriptorType = static_cast(binding.descriptorType); + writeDescriptorSet.pImageInfo = &imageInfo; + resManager->GetContext()->device->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr); + + texture->renderTexture = this; } void Record(VulkanDrawContext* context) override { - //cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, ) + context->commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, context->GetShader()->pipelineLayout, m_setId, 1, &m_descriptorSet, 0, nullptr); } }; - class VulkanTextureDynamic : VulkanTexture + /*class VulkanTextureDynamic : VulkanTexture { public: uint32_t lastUpdate = -1; @@ -48,13 +63,13 @@ namespace OpenVulkano::Vulkan void Record(VulkanDrawContext* context) override { - /*if(bufferId != lastUpdate && m_texture->updated) + 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);*/ + VulkanTexture::Record(cmdBuffer, bufferId); } - }; + };*/ } \ No newline at end of file