• 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 #include "Buffer.hpp"
16 #include "DrawTester.hpp"
17 #include "benchmark/benchmark.h"
18 
19 #include <cassert>
20 #include <vector>
21 
22 template<typename T>
RunBenchmark(benchmark::State & state,T & tester)23 static void RunBenchmark(benchmark::State &state, T &tester)
24 {
25 	tester.initialize();
26 
27 	if(false) tester.show();  // Enable for visual verification.
28 
29 	// Warmup
30 	tester.renderFrame();
31 
32 	for(auto _ : state)
33 	{
34 		tester.renderFrame();
35 	}
36 }
37 
TriangleSolidColor(benchmark::State & state,Multisample multisample)38 static void TriangleSolidColor(benchmark::State &state, Multisample multisample)
39 {
40 	DrawTester tester(multisample);
41 
42 	tester.onCreateVertexBuffers([](DrawTester &tester) {
43 		struct Vertex
44 		{
45 			float position[3];
46 		};
47 
48 		Vertex vertexBufferData[] = {
49 			{ { 1.0f, 1.0f, 0.5f } },
50 			{ { -1.0f, 1.0f, 0.5f } },
51 			{ { 0.0f, -1.0f, 0.5f } }
52 		};
53 
54 		std::vector<vk::VertexInputAttributeDescription> inputAttributes;
55 		inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
56 
57 		tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
58 	});
59 
60 	tester.onCreateVertexShader([](DrawTester &tester) {
61 		const char *vertexShader = R"(#version 310 es
62 			layout(location = 0) in vec3 inPos;
63 
64 			void main()
65 			{
66 				gl_Position = vec4(inPos.xyz, 1.0);
67 			})";
68 
69 		return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
70 	});
71 
72 	tester.onCreateFragmentShader([](DrawTester &tester) {
73 		const char *fragmentShader = R"(#version 310 es
74 			precision highp float;
75 
76 			layout(location = 0) out vec4 outColor;
77 
78 			void main()
79 			{
80 				outColor = vec4(1.0, 1.0, 1.0, 1.0);
81 			})";
82 
83 		return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
84 	});
85 
86 	RunBenchmark(state, tester);
87 }
88 
TriangleInterpolateColor(benchmark::State & state,Multisample multisample)89 static void TriangleInterpolateColor(benchmark::State &state, Multisample multisample)
90 {
91 	DrawTester tester(multisample);
92 
93 	tester.onCreateVertexBuffers([](DrawTester &tester) {
94 		struct Vertex
95 		{
96 			float position[3];
97 			float color[3];
98 		};
99 
100 		Vertex vertexBufferData[] = {
101 			{ { 1.0f, 1.0f, 0.05f }, { 1.0f, 0.0f, 0.0f } },
102 			{ { -1.0f, 1.0f, 0.5f }, { 0.0f, 1.0f, 0.0f } },
103 			{ { 0.0f, -1.0f, 0.5f }, { 0.0f, 0.0f, 1.0f } }
104 		};
105 
106 		std::vector<vk::VertexInputAttributeDescription> inputAttributes;
107 		inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
108 		inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color)));
109 
110 		tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
111 	});
112 
113 	tester.onCreateVertexShader([](DrawTester &tester) {
114 		const char *vertexShader = R"(#version 310 es
115 			layout(location = 0) in vec3 inPos;
116 			layout(location = 1) in vec3 inColor;
117 
118 			layout(location = 0) out vec3 outColor;
119 
120 			void main()
121 			{
122 				outColor = inColor;
123 				gl_Position = vec4(inPos.xyz, 1.0);
124 			})";
125 
126 		return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
127 	});
128 
129 	tester.onCreateFragmentShader([](DrawTester &tester) {
130 		const char *fragmentShader = R"(#version 310 es
131 			precision highp float;
132 
133 			layout(location = 0) in vec3 inColor;
134 
135 			layout(location = 0) out vec4 outColor;
136 
137 			void main()
138 			{
139 				outColor = vec4(inColor, 1.0);
140 			})";
141 
142 		return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
143 	});
144 
145 	RunBenchmark(state, tester);
146 }
147 
TriangleSampleTexture(benchmark::State & state,Multisample multisample)148 static void TriangleSampleTexture(benchmark::State &state, Multisample multisample)
149 {
150 	DrawTester tester(multisample);
151 
152 	tester.onCreateVertexBuffers([](DrawTester &tester) {
153 		struct Vertex
154 		{
155 			float position[3];
156 			float texCoord[2];
157 		};
158 
159 		Vertex vertexBufferData[] = {
160 			{ { 1.0f, 1.0f, 0.5f }, { 1.0f, 0.0f } },
161 			{ { -1.0f, 1.0f, 0.5f }, { 0.0f, 1.0f } },
162 			{ { 0.0f, -1.0f, 0.5f }, { 0.0f, 0.0f } }
163 		};
164 
165 		std::vector<vk::VertexInputAttributeDescription> inputAttributes;
166 		inputAttributes.push_back(vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)));
167 		inputAttributes.push_back(vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, texCoord)));
168 
169 		tester.addVertexBuffer(vertexBufferData, sizeof(vertexBufferData), std::move(inputAttributes));
170 	});
171 
172 	tester.onCreateVertexShader([](DrawTester &tester) {
173 		const char *vertexShader = R"(#version 310 es
174 			layout(location = 0) in vec3 inPos;
175 			layout(location = 1) in vec2 inTexCoord;
176 			layout(location = 0) out vec2 outTexCoord;
177 
178 			void main()
179 			{
180 				gl_Position = vec4(inPos.xyz, 1.0);
181 				outTexCoord = inTexCoord;
182 			})";
183 
184 		return tester.createShaderModule(vertexShader, EShLanguage::EShLangVertex);
185 	});
186 
187 	tester.onCreateFragmentShader([](DrawTester &tester) {
188 		const char *fragmentShader = R"(#version 310 es
189 			precision highp float;
190 
191 			layout(location = 0) in vec2 inTexCoord;
192 			layout(location = 0) out vec4 outColor;
193 			layout(binding = 0) uniform sampler2D texSampler;
194 
195 			void main()
196 			{
197 				outColor = texture(texSampler, inTexCoord);
198 			})";
199 
200 		return tester.createShaderModule(fragmentShader, EShLanguage::EShLangFragment);
201 	});
202 
203 	tester.onCreateDescriptorSetLayouts([](DrawTester &tester) -> std::vector<vk::DescriptorSetLayoutBinding> {
204 		vk::DescriptorSetLayoutBinding samplerLayoutBinding;
205 		samplerLayoutBinding.binding = 1;
206 		samplerLayoutBinding.descriptorCount = 1;
207 		samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
208 		samplerLayoutBinding.pImmutableSamplers = nullptr;
209 		samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
210 
211 		return { samplerLayoutBinding };
212 	});
213 
214 	tester.onUpdateDescriptorSet([](DrawTester &tester, vk::CommandPool &commandPool, vk::DescriptorSet &descriptorSet) {
215 		auto &device = tester.getDevice();
216 		auto &physicalDevice = tester.getPhysicalDevice();
217 		auto &queue = tester.getQueue();
218 
219 		auto &texture = tester.addImage(device, physicalDevice, 16, 16, vk::Format::eR8G8B8A8Unorm).obj;
220 
221 		// Fill texture with colorful checkerboard
222 		std::array<uint32_t, 3> rgb = { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF };
223 		int colorIndex = 0;
224 		vk::DeviceSize bufferSize = 16 * 16 * 4;
225 		Buffer buffer(device, bufferSize, vk::BufferUsageFlagBits::eTransferSrc);
226 		uint32_t *data = static_cast<uint32_t *>(buffer.mapMemory());
227 
228 		for(int i = 0; i < 16; i++)
229 		{
230 			for(int j = 0; j < 16; j++)
231 			{
232 				if(((i ^ j) & 1) == 0)
233 				{
234 					data[i + 16 * j] = rgb[colorIndex++ % rgb.size()];
235 				}
236 				else
237 				{
238 					data[i + 16 * j] = 0;
239 				}
240 			}
241 		}
242 
243 		buffer.unmapMemory();
244 
245 		Util::transitionImageLayout(device, commandPool, queue, texture.getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
246 		Util::copyBufferToImage(device, commandPool, queue, buffer.getBuffer(), texture.getImage(), 16, 16);
247 		Util::transitionImageLayout(device, commandPool, queue, texture.getImage(), vk::Format::eR8G8B8A8Unorm, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
248 
249 		vk::SamplerCreateInfo samplerInfo;
250 		samplerInfo.magFilter = vk::Filter::eLinear;
251 		samplerInfo.minFilter = vk::Filter::eLinear;
252 		samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
253 		samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
254 		samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
255 		samplerInfo.anisotropyEnable = VK_FALSE;
256 		samplerInfo.unnormalizedCoordinates = VK_FALSE;
257 		samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
258 		samplerInfo.mipLodBias = 0.0f;
259 		samplerInfo.minLod = 0.0f;
260 		samplerInfo.maxLod = 0.0f;
261 
262 		auto sampler = tester.addSampler(samplerInfo);
263 
264 		vk::DescriptorImageInfo imageInfo;
265 		imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
266 		imageInfo.imageView = texture.getImageView();
267 		imageInfo.sampler = sampler.obj;
268 
269 		std::array<vk::WriteDescriptorSet, 1> descriptorWrites = {};
270 
271 		descriptorWrites[0].dstSet = descriptorSet;
272 		descriptorWrites[0].dstBinding = 1;
273 		descriptorWrites[0].dstArrayElement = 0;
274 		descriptorWrites[0].descriptorType = vk::DescriptorType::eCombinedImageSampler;
275 		descriptorWrites[0].descriptorCount = 1;
276 		descriptorWrites[0].pImageInfo = &imageInfo;
277 
278 		device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
279 	});
280 
281 	RunBenchmark(state, tester);
282 }
283 
284 BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
285 BENCHMARK_CAPTURE(TriangleInterpolateColor, TriangleInterpolateColor, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
286 BENCHMARK_CAPTURE(TriangleSampleTexture, TriangleSampleTexture, Multisample::False)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
287 BENCHMARK_CAPTURE(TriangleSolidColor, TriangleSolidColor_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
288 BENCHMARK_CAPTURE(TriangleInterpolateColor, TriangleInterpolateColor_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
289 BENCHMARK_CAPTURE(TriangleSampleTexture, TriangleSampleTexture_Multisample, Multisample::True)->Unit(benchmark::kMillisecond)->MeasureProcessCPUTime();
290