/* * 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 "VulkanShader.hpp" #include "../Context.hpp" #include "../Device.hpp" #include "../../Scene/Vertex.hpp" namespace openVulkanoCpp::Vulkan { namespace { constexpr vk::PrimitiveTopology ToVkTopology(Scene::Topology topology) { switch (topology) { case Scene::Topology::PointList: return vk::PrimitiveTopology::ePointList; case Scene::Topology::LineList: return vk::PrimitiveTopology::eLineList; case Scene::Topology::LineStripe: return vk::PrimitiveTopology::eLineStrip; case Scene::Topology::TriangleList: return vk::PrimitiveTopology::eTriangleList; case Scene::Topology::TriangleStripe: return vk::PrimitiveTopology::eTriangleStrip; default: throw std::runtime_error("Unknown topology!"); } } } void VulkanShader::Init(Context* context, Scene::Shader* shader, IShaderOwner* owner) { this->device = context->device->device; this->shader = shader; this->owner = owner; this->context = context; shaderModuleVertex = context->device->CreateShaderModule(shader->vertexShaderName + ".vert.spv"); shaderModuleFragment = context->device->CreateShaderModule(shader->fragmentShaderName + ".frag.spv"); BuildPipeline(); } void VulkanShader::BuildPipeline() { std::vector shaderStageCreateInfos(2); shaderStageCreateInfos[0] = { {}, vk::ShaderStageFlagBits::eVertex, shaderModuleVertex, "main" }; shaderStageCreateInfos[1] = { {}, vk::ShaderStageFlagBits::eFragment, shaderModuleFragment, "main" }; auto vertexBindDesc = vk::VertexInputBindingDescription(0, sizeof(Vertex), vk::VertexInputRate::eVertex); std::vector attributeDescriptions; attributeDescriptions.emplace_back(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)); attributeDescriptions.emplace_back(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, normal)); attributeDescriptions.emplace_back(2, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, tangent)); attributeDescriptions.emplace_back(3, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, biTangent)); attributeDescriptions.emplace_back(4, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, textureCoordinates)); attributeDescriptions.emplace_back(5, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(Vertex, color)); vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { {}, 1, &context->swapChain.GetFullscreenViewport(), 1, &context->swapChain.GetFullscreenScissor() }; vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = { {}, 1, &vertexBindDesc, static_cast(attributeDescriptions.size()), attributeDescriptions.data() }; vk::PipelineInputAssemblyStateCreateInfo inputAssembly = { {}, ToVkTopology(shader->topology), 0 }; vk::PipelineRasterizationStateCreateInfo rasterizer = {}; rasterizer.cullMode = vk::CullModeFlagBits::eBack; vk::PipelineMultisampleStateCreateInfo msaa = {}; vk::PipelineDepthStencilStateCreateInfo depth = { {}, 1, 1, vk::CompareOp::eLess }; depth.maxDepthBounds = 1; vk::PipelineColorBlendAttachmentState colorBlendAttachment = {}; colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eA | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eR; vk::PipelineColorBlendStateCreateInfo colorInfo = {}; colorInfo.attachmentCount = 1; colorInfo.pAttachments = &colorBlendAttachment; vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { {}, static_cast(shaderStageCreateInfos.size()), shaderStageCreateInfos.data(), &pipelineVertexInputStateCreateInfo, &inputAssembly, nullptr, &viewportStateCreateInfo, &rasterizer, &msaa, &depth, &colorInfo, nullptr, context->pipeline.pipelineLayout, context->swapChainRenderPass.renderPass }; pipeline = this->device.createGraphicsPipeline({}, pipelineCreateInfo).value; } void VulkanShader::Resize() { device.destroyPipeline(pipeline); BuildPipeline(); } void VulkanShader::Record(vk::CommandBuffer& cmdBuffer, uint32_t bufferId) { cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); } void VulkanShader::Close() { owner->RemoveShader(this); shader = nullptr; device.destroyPipeline(pipeline); device.destroyShaderModule(shaderModuleVertex); device.destroyShaderModule(shaderModuleFragment); } }