Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_RENDERER_BACKEND_VULKAN_SHADERPROGRAM
19 : #define INCLUDED_RENDERER_BACKEND_VULKAN_SHADERPROGRAM
20 :
21 : #include "renderer/backend/IShaderProgram.h"
22 : #include "renderer/backend/vulkan/Texture.h"
23 :
24 : #include <array>
25 : #include <cstddef>
26 : #include <glad/vulkan.h>
27 : #include <memory>
28 : #include <unordered_map>
29 : #include <vector>
30 :
31 : class CShaderDefines;
32 : class CStr;
33 :
34 : namespace Renderer
35 : {
36 :
37 : namespace Backend
38 : {
39 :
40 : namespace Vulkan
41 : {
42 :
43 : class CDevice;
44 :
45 : class CVertexInputLayout : public IVertexInputLayout
46 : {
47 : public:
48 0 : CVertexInputLayout(CDevice* device, const PS::span<const SVertexAttributeFormat> attributes)
49 0 : : m_Device(device), m_Attributes(attributes.begin(), attributes.end())
50 : {
51 : static uint32_t m_LastAvailableUID = 1;
52 0 : m_UID = m_LastAvailableUID++;
53 0 : for (const SVertexAttributeFormat& attribute : m_Attributes)
54 : {
55 0 : ENSURE(attribute.format != Format::UNDEFINED);
56 0 : ENSURE(attribute.stride > 0);
57 : }
58 0 : }
59 :
60 0 : ~CVertexInputLayout() override = default;
61 :
62 : IDevice* GetDevice() override;
63 :
64 0 : const std::vector<SVertexAttributeFormat>& GetAttributes() const noexcept { return m_Attributes; }
65 :
66 : using UID = uint32_t;
67 0 : UID GetUID() const { return m_UID; }
68 :
69 : private:
70 : CDevice* m_Device = nullptr;
71 :
72 : UID m_UID = 0;
73 :
74 : std::vector<SVertexAttributeFormat> m_Attributes;
75 : };
76 :
77 0 : class CShaderProgram final : public IShaderProgram
78 : {
79 : public:
80 : ~CShaderProgram() override;
81 :
82 : IDevice* GetDevice() override;
83 :
84 : int32_t GetBindingSlot(const CStrIntern name) const override;
85 :
86 : std::vector<VfsPath> GetFileDependencies() const override;
87 :
88 : uint32_t GetStreamLocation(const VertexAttributeStream stream) const;
89 :
90 0 : const std::vector<VkPipelineShaderStageCreateInfo>& GetStages() const { return m_Stages; }
91 :
92 : void Bind();
93 : void Unbind();
94 : void PreDraw(VkCommandBuffer commandBuffer);
95 :
96 0 : VkPipelineLayout GetPipelineLayout() const { return m_PipelineLayout; }
97 0 : VkPipelineBindPoint GetPipelineBindPoint() const { return VK_PIPELINE_BIND_POINT_GRAPHICS; }
98 :
99 : void SetUniform(
100 : const int32_t bindingSlot,
101 : const float value);
102 : void SetUniform(
103 : const int32_t bindingSlot,
104 : const float valueX, const float valueY);
105 : void SetUniform(
106 : const int32_t bindingSlot,
107 : const float valueX, const float valueY,
108 : const float valueZ);
109 : void SetUniform(
110 : const int32_t bindingSlot,
111 : const float valueX, const float valueY,
112 : const float valueZ, const float valueW);
113 : void SetUniform(
114 : const int32_t bindingSlot, PS::span<const float> values);
115 : void SetTexture(const int32_t bindingSlot, CTexture* texture);
116 :
117 : // TODO: rename to something related to buffer.
118 0 : bool IsMaterialConstantsDataOutdated() const { return m_MaterialConstantsDataOutdated; }
119 0 : void UpdateMaterialConstantsData() { m_MaterialConstantsDataOutdated = false; }
120 0 : std::byte* GetMaterialConstantsData() const { return m_MaterialConstantsData.get(); }
121 0 : uint32_t GetMaterialConstantsDataSize() const { return m_MaterialConstantsDataSize; }
122 :
123 : private:
124 : friend class CDevice;
125 :
126 : CShaderProgram();
127 :
128 : std::pair<std::byte*, uint32_t> GetUniformData(
129 : const int32_t bindingSlot, const uint32_t dataSize);
130 :
131 : static std::unique_ptr<CShaderProgram> Create(
132 : CDevice* device, const CStr& name, const CShaderDefines& defines);
133 :
134 : void UpdateActiveDescriptorSet(
135 : VkCommandBuffer commandBuffer);
136 :
137 : CDevice* m_Device = nullptr;
138 :
139 : std::vector<VkShaderModule> m_ShaderModules;
140 : std::vector<VkPipelineShaderStageCreateInfo> m_Stages;
141 : VkPipelineLayout m_PipelineLayout = VK_NULL_HANDLE;
142 :
143 : std::vector<VfsPath> m_FileDependencies;
144 :
145 : struct PushConstant
146 : {
147 : CStrIntern name;
148 : uint32_t offset;
149 : uint32_t size;
150 : VkShaderStageFlags stageFlags;
151 : };
152 : struct Uniform
153 : {
154 : CStrIntern name;
155 : uint32_t offset;
156 : uint32_t size;
157 : };
158 : std::unique_ptr<std::byte[]> m_MaterialConstantsData;
159 : uint32_t m_MaterialConstantsDataSize = 0;
160 : bool m_MaterialConstantsDataOutdated = false;
161 : std::array<std::byte, 128> m_PushConstantData;
162 : uint32_t m_PushConstantDataMask = 0;
163 : std::array<VkShaderStageFlags, 32> m_PushConstantDataFlags;
164 : std::vector<PushConstant> m_PushConstants;
165 : std::vector<Uniform> m_Uniforms;
166 : std::unordered_map<CStrIntern, uint32_t> m_UniformMapping;
167 : std::unordered_map<CStrIntern, uint32_t> m_PushConstantMapping;
168 :
169 : uint32_t m_TexturesDescriptorSetSize = 0;
170 : bool m_BoundTexturesOutdated = false;
171 :
172 : VkDescriptorSetLayout m_TexturesDescriptorSetLayout = VK_NULL_HANDLE;
173 : std::vector<CTexture*> m_BoundTextures;
174 : std::vector<CTexture::UID> m_BoundTexturesUID;
175 : VkDescriptorSet m_ActiveTexturesDescriptorSet = VK_NULL_HANDLE;
176 : std::unordered_map<CStrIntern, uint32_t> m_TextureMapping;
177 :
178 : std::unordered_map<VertexAttributeStream, uint32_t> m_StreamLocations;
179 : };
180 :
181 : } // namespace Vulkan
182 :
183 : } // namespace Backend
184 :
185 : } // namespace Renderer
186 :
187 : #endif // INCLUDED_RENDERER_BACKEND_VULKAN_SHADERPROGRAM
|