• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 enum class Multisample
26 {
27 	False,
28 	True
29 };
30 
31 class DrawTester : public VulkanTester
32 {
33 public:
34 	using ThisType = DrawTester;
35 
36 	DrawTester(Multisample multisample = Multisample::False);
37 	~DrawTester();
38 
39 	void initialize();
40 	void renderFrame();
41 	void show();
42 
43 	/////////////////////////
44 	// Hooks
45 	/////////////////////////
46 
47 	// Called from prepareVertices.
48 	// Callback may call tester.addVertexBuffer() from this function.
49 	void onCreateVertexBuffers(std::function<void(ThisType &tester)> callback);
50 
51 	// Called from createGraphicsPipeline.
52 	// Callback must return vector of DescriptorSetLayoutBindings for which a DescriptorSetLayout
53 	// will be created and stored in this->descriptorSetLayout.
54 	void onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback);
55 
56 	// Called from createGraphicsPipeline.
57 	// Callback should call tester.createShaderModule() and return the result.
58 	void onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
59 
60 	// Called from createGraphicsPipeline.
61 	// Callback should call tester.createShaderModule() and return the result.
62 	void onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback);
63 
64 	// Called from createCommandBuffers.
65 	// Callback may create resources (tester.addImage, tester.addSampler, etc.), and make sure to
66 	// call tester.device().updateDescriptorSets.
67 	void onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback);
68 
69 	/////////////////////////
70 	// Resource Management
71 	/////////////////////////
72 
73 	// Call from doCreateFragmentShader()
74 	vk::ShaderModule createShaderModule(const char *glslSource, EShLanguage glslLanguage);
75 
76 	// Call from doCreateVertexBuffers()
77 	template<typename VertexType>
addVertexBuffer(VertexType * vertexBufferData,size_t vertexBufferDataSize,std::vector<vk::VertexInputAttributeDescription> inputAttributes)78 	void addVertexBuffer(VertexType *vertexBufferData, size_t vertexBufferDataSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
79 	{
80 		addVertexBuffer(vertexBufferData, vertexBufferDataSize, sizeof(VertexType), std::move(inputAttributes));
81 	}
82 
83 	template<typename T>
84 	struct Resource
85 	{
86 		size_t id;
87 		T &obj;
88 	};
89 
90 	template<typename... Args>
addImage(Args &&...args)91 	Resource<Image> addImage(Args &&... args)
92 	{
93 		images.emplace_back(std::make_unique<Image>(std::forward<Args>(args)...));
94 		return { images.size() - 1, *images.back() };
95 	}
96 
getImageById(size_t id)97 	Image &getImageById(size_t id)
98 	{
99 		return *images[id].get();
100 	}
101 
addSampler(const vk::SamplerCreateInfo & samplerCreateInfo)102 	Resource<vk::Sampler> addSampler(const vk::SamplerCreateInfo &samplerCreateInfo)
103 	{
104 		auto sampler = device.createSampler(samplerCreateInfo);
105 		samplers.push_back(sampler);
106 		return { samplers.size() - 1, samplers.back() };
107 	}
108 
getSamplerById(size_t id)109 	vk::Sampler &getSamplerById(size_t id)
110 	{
111 		return samplers[id];
112 	}
113 
114 private:
115 	void createSynchronizationPrimitives();
116 	void createCommandBuffers(vk::RenderPass renderPass);
117 	void prepareVertices();
118 	void createFramebuffers(vk::RenderPass renderPass);
119 	vk::RenderPass createRenderPass(vk::Format colorFormat);
120 	vk::Pipeline createGraphicsPipeline(vk::RenderPass renderPass);
121 	void addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes);
122 
123 	struct Hook
124 	{
__anoncf6d42890102DrawTester::Hook125 		std::function<void(ThisType &tester)> createVertexBuffers = [](auto &) {};
__anoncf6d42890202DrawTester::Hook126 		std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> createDescriptorSetLayout = [](auto &) { return std::vector<vk::DescriptorSetLayoutBinding>{}; };
__anoncf6d42890302DrawTester::Hook127 		std::function<vk::ShaderModule(ThisType &tester)> createVertexShader = [](auto &) { return vk::ShaderModule{}; };
__anoncf6d42890402DrawTester::Hook128 		std::function<vk::ShaderModule(ThisType &tester)> createFragmentShader = [](auto &) { return vk::ShaderModule{}; };
__anoncf6d42890502DrawTester::Hook129 		std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> updateDescriptorSet = [](auto &, auto &, auto &) {};
130 	} hooks;
131 
132 	const vk::Extent2D windowSize = { 1280, 720 };
133 	const bool multisample;
134 
135 	std::unique_ptr<Window> window;
136 	std::unique_ptr<Swapchain> swapchain;
137 
138 	vk::RenderPass renderPass;  // Owning handle
139 	std::vector<std::unique_ptr<Framebuffer>> framebuffers;
140 	uint32_t currentFrameBuffer = 0;
141 
142 	struct VertexBuffer
143 	{
144 		vk::Buffer buffer;        // Owning handle
145 		vk::DeviceMemory memory;  // Owning handle
146 
147 		vk::VertexInputBindingDescription inputBinding;
148 		std::vector<vk::VertexInputAttributeDescription> inputAttributes;
149 		vk::PipelineVertexInputStateCreateInfo inputState;
150 
151 		uint32_t numVertices = 0;
152 	} vertices;
153 
154 	vk::DescriptorSetLayout descriptorSetLayout;  // Owning handle
155 	vk::PipelineLayout pipelineLayout;            // Owning handle
156 	vk::Pipeline pipeline;                        // Owning handle
157 
158 	vk::Semaphore presentCompleteSemaphore;  // Owning handle
159 	vk::Semaphore renderCompleteSemaphore;   // Owning handle
160 	std::vector<vk::Fence> waitFences;       // Owning handles
161 
162 	vk::CommandPool commandPool;        // Owning handle
163 	vk::DescriptorPool descriptorPool;  // Owning handle
164 
165 	// Resources
166 	std::vector<std::unique_ptr<Image>> images;
167 	std::vector<vk::Sampler> samplers;  // Owning handles
168 
169 	std::vector<vk::CommandBuffer> commandBuffers;  // Owning handles
170 };
171 
onCreateVertexBuffers(std::function<void (ThisType & tester)> callback)172 inline void DrawTester::onCreateVertexBuffers(std::function<void(ThisType &tester)> callback)
173 {
174 	hooks.createVertexBuffers = std::move(callback);
175 }
176 
onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding> (ThisType & tester)> callback)177 inline void DrawTester::onCreateDescriptorSetLayouts(std::function<std::vector<vk::DescriptorSetLayoutBinding>(ThisType &tester)> callback)
178 {
179 	hooks.createDescriptorSetLayout = std::move(callback);
180 }
181 
onCreateVertexShader(std::function<vk::ShaderModule (ThisType & tester)> callback)182 inline void DrawTester::onCreateVertexShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
183 {
184 	hooks.createVertexShader = std::move(callback);
185 }
186 
onCreateFragmentShader(std::function<vk::ShaderModule (ThisType & tester)> callback)187 inline void DrawTester::onCreateFragmentShader(std::function<vk::ShaderModule(ThisType &tester)> callback)
188 {
189 	hooks.createFragmentShader = std::move(callback);
190 }
191 
onUpdateDescriptorSet(std::function<void (ThisType & tester,vk::CommandPool & commandPool,vk::DescriptorSet & descriptorSet)> callback)192 inline void DrawTester::onUpdateDescriptorSet(std::function<void(ThisType &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet)> callback)
193 {
194 	hooks.updateDescriptorSet = std::move(callback);
195 }
196 
197 #endif  // DRAW_TESTER_HPP_
198