xref: /aosp_15_r20/external/swiftshader/tests/VulkanWrapper/DrawTester.hpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright 2021 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef DRAW_TESTER_HPP_
16 #define DRAW_TESTER_HPP_
17 
18 #include "Framebuffer.hpp"
19 #include "Image.hpp"
20 #include "Swapchain.hpp"
21 #include "Util.hpp"
22 #include "VulkanTester.hpp"
23 #include "Window.hpp"
24 
25 #include <functional>
26 #include <memory>
27 
28 enum class Multisample
29 {
30 	False,
31 	True
32 };
33 
34 class DrawTester : public VulkanTester
35 {
36 public:
37 	using ThisType = DrawTester;
38 
39 	DrawTester(Multisample multisample = Multisample::False);
40 	~DrawTester();
41 
42 	void initialize();
43 	void renderFrame();
44 	void show();
45 
46 	/////////////////////////
47 	// Hooks
48 	/////////////////////////
49 
50 	// Called from prepareVertices.
51 	// Callback may call tester.addVertexBuffer() from this function.
52 	void onCreateVertexBuffers(std::function<void(ThisType &tester)> callback);
53 
54 	// Called from createGraphicsPipeline.
55 	// Callback must return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout
56 	// will be created and stored in this->descriptorSetLayout.
57 	void onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback);
58 
59 	// Called from createGraphicsPipeline.
60 	// Callback should call tester.createShaderModule() and return the result.
61 	void onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
62 
63 	// Called from createGraphicsPipeline.
64 	// Callback should call tester.createShaderModule() and return the result.
65 	void onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
66 
67 	// Called from createCommandBuffers.
68 	// Callback may create resources (tester.addImage, tester.addSampler, etc.), and make sure to
69 	// call tester.device().updateDescriptorSets.
70 	void onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback);
71 
72 	/////////////////////////
73 	// Resource Management
74 	/////////////////////////
75 
76 	// Call from doCreateFragmentShader()
77 	vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage);
78 
79 	// Call from doCreateVertexBuffers()
80 	template<typename VertexType>
addVertexBuffer(VertexType * vertexBufferData,size_t vertexBufferDataSize,std::vector<vk::VertexInputAttributeDescription> inputAttributes)81 	void addVertexBuffer(VertexType *vertexBufferData, size_t vertexBufferDataSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
82 	{
83 		addVertexBuffer(vertexBufferData, vertexBufferDataSize, sizeof(VertexType), std::move(inputAttributes));
84 	}
85 
86 	template<typename T>
87 	struct Resource
88 	{
89 		size_t id;
90 		T &obj;
91 	};
92 
93 	template<typename... Args>
addImage(Args &&...args)94 	Resource<Image> addImage(Args &&...args)
95 	{
96 		images.emplace_back(std::make_unique<Image>(std::forward<Args>(args)...));
97 		return { images.size() - 1, *images.back() };
98 	}
99 
getImageById(size_t id)100 	Image &getImageById(size_t id)
101 	{
102 		return *images[id].get();
103 	}
104 
addSampler(const vk::SamplerCreateInfo & samplerCreateInfo)105 	Resource<vk::Sampler> addSampler(const vk::SamplerCreateInfo &samplerCreateInfo)
106 	{
107 		auto sampler = device.createSampler(samplerCreateInfo);
108 		samplers.push_back(sampler);
109 		return { samplers.size() - 1, samplers.back() };
110 	}
111 
getSamplerById(size_t id)112 	vk::Sampler &getSamplerById(size_t id)
113 	{
114 		return samplers[id];
115 	}
116 
117 private:
118 	void createSynchronizationPrimitives();
119 	void createCommandBuffers(vk::RenderPass renderPass);
120 	void prepareVertices();
121 	void createFramebuffers(vk::RenderPass renderPass);
122 	vk::RenderPass createRenderPass(vk::Format colorFormat);
123 	vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
124 	void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
125 
126 	struct Hook
127 	{
__anone820d3f80102DrawTester::Hook128 		std::function<void(ThisType &tester)> createVertexBuffers = [](auto &) {};
__anone820d3f80202DrawTester::Hook129 		std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> createDescriptorSetLayout = [](auto &) { return std::vector<vk::DescriptorSetLayoutBinding>{}; };
__anone820d3f80302DrawTester::Hook130 		std::function<vk::ShaderModule(ThisType &tester)> createVertexShader = [](auto &) { return vk::ShaderModule{}; };
__anone820d3f80402DrawTester::Hook131 		std::function<vk::ShaderModule(ThisType &tester)> createFragmentShader = [](auto &) { return vk::ShaderModule{}; };
__anone820d3f80502DrawTester::Hook132 		std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> updateDescriptorSet = [](auto &, auto &, auto &) {};
133 	} hooks;
134 
135 	const vk::Extent2D windowSize = { 1280, 720 };
136 	const bool multisample;
137 
138 	std::unique_ptr<Window> window;
139 	std::unique_ptr<Swapchain> swapchain;
140 
141 	vk::RenderPass renderPass;  // Owning handle
142 	std::vector<std::unique_ptr<Framebuffer>> framebuffers;
143 	uint32_t currentFrameBuffer = 0;
144 
145 	struct VertexBuffer
146 	{
147 		vk::Buffer buffer;        // Owning handle
148 		vk::DeviceMemory memory;  // Owning handle
149 
150 		vk::VertexInputBindingDescription inputBinding;
151 		std::vector<vk::VertexInputAttributeDescription> inputAttributes;
152 		vk::PipelineVertexInputStateCreateInfo inputState;
153 
154 		uint32_t numVertices = 0;
155 	} vertices;
156 
157 	vk::DescriptorSetLayout descriptorSetLayout;  // Owning handle
158 	vk::PipelineLayout pipelineLayout;            // Owning handle
159 	vk::Pipeline pipeline;                        // Owning handle
160 
161 	vk::Semaphore presentCompleteSemaphore;  // Owning handle
162 	vk::Semaphore renderCompleteSemaphore;   // Owning handle
163 	std::vector<vk::Fence> waitFences;       // Owning handles
164 
165 	vk::CommandPool commandPool;        // Owning handle
166 	vk::DescriptorPool descriptorPool;  // Owning handle
167 
168 	// Resources
169 	std::vector<std::unique_ptr<Image>> images;
170 	std::vector<vk::Sampler> samplers;  // Owning handles
171 
172 	std::vector<vk::CommandBuffer> commandBuffers;  // Owning handles
173 };
174 
onCreateVertexBuffers(std::function<void (ThisType & tester)> callback)175 inline void DrawTester::onCreateVertexBuffers(std::function<void(ThisType &tester)> callback)
176 {
177 	hooks.createVertexBuffers = std::move(callback);
178 }
179 
onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding> (ThisType & tester)> callback)180 inline void DrawTester::onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback)
181 {
182 	hooks.createDescriptorSetLayout = std::move(callback);
183 }
184 
onCreateVertexShader(std::function<vk::ShaderModule (ThisType & tester)> callback)185 inline void DrawTester::onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
186 {
187 	hooks.createVertexShader = std::move(callback);
188 }
189 
onCreateFragmentShader(std::function<vk::ShaderModule (ThisType & tester)> callback)190 inline void DrawTester::onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
191 {
192 	hooks.createFragmentShader = std::move(callback);
193 }
194 
onUpdateDescriptorSet(std::function<void (ThisType & tester,vk::CommandPool & commandPool,vk::DescriptorSet & descriptorSet)> callback)195 inline void DrawTester::onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback)
196 {
197 	hooks.updateDescriptorSet = std::move(callback);
198 }
199 
200 #endif  // DRAW_TESTER_HPP_
201