/* * 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 "IRecordable.hpp" #include "Vulkan/Image.hpp" #include "Vulkan/Context.hpp" #include "Vulkan/Resources/ResourceManager.hpp" #include "Vulkan/Scene/VulkanShader.hpp" #include "Scene/Texture.hpp" #include "Scene/Shader/Shader.hpp" namespace OpenVulkano::Vulkan { class VulkanTexture : public IRenderResource, public IRecordable, public Image { public: vk::Sampler m_sampler; vk::DescriptorSet m_descriptorSet; VulkanTexture() : IRenderResource(nullptr) {} virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) { Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }); resManager->CopyDataToImage(texture->size, texture->textureBuffer, this); texture->updated = false; m_sampler = resManager->CreateSampler(reinterpret_cast(*texture->m_samplerConfig)); SetDescriptorSet(resManager, descriptorSetLayout, binding); UpdateAddress(texture); UpdateRenderResource(GetOwnerResource()); } void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) { Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible); texture->updated = false; texture->textureBuffer = Map(); m_sampler = resManager->CreateSampler(reinterpret_cast(*texture->m_samplerConfig)); SetDescriptorSet(resManager, descriptorSetLayout, binding); UpdateAddress(texture); UpdateRenderResource(GetOwnerResource()); } virtual ~VulkanTexture() override { if (m_sampler) Close(); } void Close() override { ResetRenderResource(GetOwnerResource()); Image::Close(); } void SetDescriptorSet(ResourceManager* resManager, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) { // Setup Descriptor set const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout }; m_descriptorSet = resManager->GetContext()->device->device.allocateDescriptorSets(descSetAllocInfo)[0]; vk::DescriptorImageInfo imageInfo = { m_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); } void Record(VulkanDrawContext* context) override { int setId = -1, i = 0; for (const auto& descriptorSet : context->GetShader()->GetOwner()->descriptorSets) { for (const auto& descriptor : descriptorSet) { if (descriptor.descriptorType < 6) { if (setId != -1) [[unlikely]] { Logger::RENDER->error("Found multiple possible descriptor set for texture! Use 'Record(VulkanDrawContext* context, int setId)' explicitly when using multiple sets containing textures!"); } setId = i; break; } } i++; } if (setId == -1) [[unlikely]] { Logger::RENDER->error("Failed to discover setId for texture binding."); return; } else [[likely]] { Record(context, setId + 2); // Set 0 and 1 are automatically bound special sets for the camera and the node } } virtual void Record(VulkanDrawContext* context, int setId) { context->commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, context->GetShader()->pipelineLayout, setId, 1, &m_descriptorSet, 0, nullptr); } void Release() override { //TODO } }; class VulkanTextureDynamic : public VulkanTexture { public: void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) override { VulkanTexture::Init(resManager, texture, descriptorSetLayout, binding); } void Record(VulkanDrawContext* context) override { if(GetOwner()->updated) { context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this); GetOwner()->updated = false; } VulkanTexture::Record(context); } void Record(VulkanDrawContext* context, int setId) override { if(GetOwner()->updated) { context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this); GetOwner()->updated = false; } VulkanTexture::Record(context, setId); } }; }