• 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 "DrawTester.hpp"
16 
17 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
18 
DrawTester(Multisample multisample)19 DrawTester::DrawTester(Multisample multisample)
20     : multisample(multisample == Multisample::True)
21 {
22 }
23 
~DrawTester()24 DrawTester::~DrawTester()
25 {
26 	device.freeCommandBuffers(commandPool, commandBuffers);
27 
28 	device.destroyDescriptorPool(descriptorPool);
29 	for(auto &sampler : samplers)
30 	{
31 		device.destroySampler(sampler, nullptr);
32 	}
33 	images.clear();
34 	device.destroyCommandPool(commandPool, nullptr);
35 
36 	for(auto &fence : waitFences)
37 	{
38 		device.destroyFence(fence, nullptr);
39 	}
40 
41 	device.destroySemaphore(renderCompleteSemaphore, nullptr);
42 	device.destroySemaphore(presentCompleteSemaphore, nullptr);
43 
44 	device.destroyPipeline(pipeline);
45 	device.destroyPipelineLayout(pipelineLayout, nullptr);
46 	device.destroyDescriptorSetLayout(descriptorSetLayout);
47 
48 	device.freeMemory(vertices.memory, nullptr);
49 	device.destroyBuffer(vertices.buffer, nullptr);
50 
51 	for(auto &framebuffer : framebuffers)
52 	{
53 		framebuffer.reset();
54 	}
55 
56 	device.destroyRenderPass(renderPass, nullptr);
57 
58 	swapchain.reset();
59 	window.reset();
60 }
61 
initialize()62 void DrawTester::initialize()
63 {
64 	VulkanTester::initialize();
65 
66 	window.reset(new Window(instance, windowSize));
67 	swapchain.reset(new Swapchain(physicalDevice, device, *window));
68 
69 	renderPass = createRenderPass(swapchain->colorFormat);
70 	createFramebuffers(renderPass);
71 
72 	prepareVertices();
73 
74 	pipeline = createGraphicsPipeline(renderPass);
75 
76 	createSynchronizationPrimitives();
77 
78 	createCommandBuffers(renderPass);
79 }
80 
renderFrame()81 void DrawTester::renderFrame()
82 {
83 	swapchain->acquireNextImage(presentCompleteSemaphore, currentFrameBuffer);
84 
85 	device.waitForFences(1, &waitFences[currentFrameBuffer], VK_TRUE, UINT64_MAX);
86 	device.resetFences(1, &waitFences[currentFrameBuffer]);
87 
88 	vk::PipelineStageFlags waitStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
89 
90 	vk::SubmitInfo submitInfo;
91 	submitInfo.pWaitDstStageMask = &waitStageMask;
92 	submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
93 	submitInfo.waitSemaphoreCount = 1;
94 	submitInfo.pSignalSemaphores = &renderCompleteSemaphore;
95 	submitInfo.signalSemaphoreCount = 1;
96 	submitInfo.pCommandBuffers = &commandBuffers[currentFrameBuffer];
97 	submitInfo.commandBufferCount = 1;
98 
99 	queue.submit(1, &submitInfo, waitFences[currentFrameBuffer]);
100 
101 	swapchain->queuePresent(queue, currentFrameBuffer, renderCompleteSemaphore);
102 }
103 
show()104 void DrawTester::show()
105 {
106 	window->show();
107 }
108 
createRenderPass(vk::Format colorFormat)109 vk::RenderPass DrawTester::createRenderPass(vk::Format colorFormat)
110 {
111 	std::vector<vk::AttachmentDescription> attachments(multisample ? 2 : 1);
112 
113 	if(multisample)
114 	{
115 		// Color attachment
116 		attachments[0].format = colorFormat;
117 		attachments[0].samples = vk::SampleCountFlagBits::e4;
118 		attachments[0].loadOp = vk::AttachmentLoadOp::eClear;
119 		attachments[0].storeOp = vk::AttachmentStoreOp::eStore;
120 		attachments[0].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
121 		attachments[0].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
122 		attachments[0].initialLayout = vk::ImageLayout::eUndefined;
123 		attachments[0].finalLayout = vk::ImageLayout::eColorAttachmentOptimal;
124 
125 		// Resolve attachment
126 		attachments[1].format = colorFormat;
127 		attachments[1].samples = vk::SampleCountFlagBits::e1;
128 		attachments[1].loadOp = vk::AttachmentLoadOp::eDontCare;
129 		attachments[1].storeOp = vk::AttachmentStoreOp::eStore;
130 		attachments[1].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
131 		attachments[1].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
132 		attachments[1].initialLayout = vk::ImageLayout::eUndefined;
133 		attachments[1].finalLayout = vk::ImageLayout::ePresentSrcKHR;
134 	}
135 	else
136 	{
137 		attachments[0].format = colorFormat;
138 		attachments[0].samples = vk::SampleCountFlagBits::e1;
139 		attachments[0].loadOp = vk::AttachmentLoadOp::eDontCare;
140 		attachments[0].storeOp = vk::AttachmentStoreOp::eStore;
141 		attachments[0].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
142 		attachments[0].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
143 		attachments[0].initialLayout = vk::ImageLayout::eUndefined;
144 		attachments[0].finalLayout = vk::ImageLayout::ePresentSrcKHR;
145 	}
146 
147 	vk::AttachmentReference attachment0;
148 	attachment0.attachment = 0;
149 	attachment0.layout = vk::ImageLayout::eColorAttachmentOptimal;
150 
151 	vk::AttachmentReference attachment1;
152 	attachment1.attachment = 1;
153 	attachment1.layout = vk::ImageLayout::eColorAttachmentOptimal;
154 
155 	vk::SubpassDescription subpassDescription;
156 	subpassDescription.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
157 	subpassDescription.colorAttachmentCount = 1;
158 	subpassDescription.pResolveAttachments = multisample ? &attachment1 : nullptr;
159 	subpassDescription.pColorAttachments = &attachment0;
160 
161 	std::array<vk::SubpassDependency, 2> dependencies;
162 
163 	dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
164 	dependencies[0].dstSubpass = 0;
165 	dependencies[0].srcStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
166 	dependencies[0].dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
167 	dependencies[0].srcAccessMask = vk::AccessFlagBits::eMemoryRead;
168 	dependencies[0].dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
169 	dependencies[0].dependencyFlags = vk::DependencyFlagBits::eByRegion;
170 
171 	dependencies[1].srcSubpass = 0;
172 	dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
173 	dependencies[1].srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
174 	dependencies[1].dstStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
175 	dependencies[1].srcAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
176 	dependencies[1].dstAccessMask = vk::AccessFlagBits::eMemoryRead;
177 	dependencies[1].dependencyFlags = vk::DependencyFlagBits::eByRegion;
178 
179 	vk::RenderPassCreateInfo renderPassInfo;
180 	renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
181 	renderPassInfo.pAttachments = attachments.data();
182 	renderPassInfo.subpassCount = 1;
183 	renderPassInfo.pSubpasses = &subpassDescription;
184 	renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
185 	renderPassInfo.pDependencies = dependencies.data();
186 
187 	return device.createRenderPass(renderPassInfo);
188 }
189 
createFramebuffers(vk::RenderPass renderPass)190 void DrawTester::createFramebuffers(vk::RenderPass renderPass)
191 {
192 	framebuffers.resize(swapchain->imageCount());
193 
194 	for(size_t i = 0; i < framebuffers.size(); i++)
195 	{
196 		framebuffers[i].reset(new Framebuffer(device, physicalDevice, swapchain->getImageView(i), swapchain->colorFormat, renderPass, swapchain->getExtent(), multisample));
197 	}
198 }
199 
prepareVertices()200 void DrawTester::prepareVertices()
201 {
202 	hooks.createVertexBuffers(*this);
203 }
204 
createGraphicsPipeline(vk::RenderPass renderPass)205 vk::Pipeline DrawTester::createGraphicsPipeline(vk::RenderPass renderPass)
206 {
207 	auto setLayoutBindings = hooks.createDescriptorSetLayout(*this);
208 
209 	std::vector<vk::DescriptorSetLayout> setLayouts;
210 	if(!setLayoutBindings.empty())
211 	{
212 		vk::DescriptorSetLayoutCreateInfo layoutInfo;
213 		layoutInfo.bindingCount = static_cast<uint32_t>(setLayoutBindings.size());
214 		layoutInfo.pBindings = setLayoutBindings.data();
215 		descriptorSetLayout = device.createDescriptorSetLayout(layoutInfo);
216 
217 		setLayouts.push_back(descriptorSetLayout);
218 	}
219 
220 	vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
221 	pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
222 	pipelineLayoutCreateInfo.pSetLayouts = setLayouts.data();
223 	pipelineLayout = device.createPipelineLayout(pipelineLayoutCreateInfo);
224 
225 	vk::GraphicsPipelineCreateInfo pipelineCreateInfo;
226 	pipelineCreateInfo.layout = pipelineLayout;
227 	pipelineCreateInfo.renderPass = renderPass;
228 
229 	vk::PipelineInputAssemblyStateCreateInfo inputAssemblyState;
230 	inputAssemblyState.topology = vk::PrimitiveTopology::eTriangleList;
231 
232 	vk::PipelineRasterizationStateCreateInfo rasterizationState;
233 	rasterizationState.depthClampEnable = VK_FALSE;
234 	rasterizationState.rasterizerDiscardEnable = VK_FALSE;
235 	rasterizationState.polygonMode = vk::PolygonMode::eFill;
236 	rasterizationState.cullMode = vk::CullModeFlagBits::eNone;
237 	rasterizationState.frontFace = vk::FrontFace::eCounterClockwise;
238 	rasterizationState.depthBiasEnable = VK_FALSE;
239 	rasterizationState.lineWidth = 1.0f;
240 
241 	vk::PipelineColorBlendAttachmentState blendAttachmentState;
242 	blendAttachmentState.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
243 	blendAttachmentState.blendEnable = VK_FALSE;
244 	vk::PipelineColorBlendStateCreateInfo colorBlendState;
245 	colorBlendState.attachmentCount = 1;
246 	colorBlendState.pAttachments = &blendAttachmentState;
247 
248 	vk::PipelineViewportStateCreateInfo viewportState;
249 	viewportState.viewportCount = 1;
250 	viewportState.scissorCount = 1;
251 
252 	std::vector<vk::DynamicState> dynamicStateEnables;
253 	dynamicStateEnables.push_back(vk::DynamicState::eViewport);
254 	dynamicStateEnables.push_back(vk::DynamicState::eScissor);
255 	vk::PipelineDynamicStateCreateInfo dynamicState = {};
256 	dynamicState.pDynamicStates = dynamicStateEnables.data();
257 	dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStateEnables.size());
258 
259 	vk::PipelineDepthStencilStateCreateInfo depthStencilState;
260 	depthStencilState.depthTestEnable = VK_FALSE;
261 	depthStencilState.depthWriteEnable = VK_FALSE;
262 	depthStencilState.depthCompareOp = vk::CompareOp::eLessOrEqual;
263 	depthStencilState.depthBoundsTestEnable = VK_FALSE;
264 	depthStencilState.back.failOp = vk::StencilOp::eKeep;
265 	depthStencilState.back.passOp = vk::StencilOp::eKeep;
266 	depthStencilState.back.compareOp = vk::CompareOp::eAlways;
267 	depthStencilState.stencilTestEnable = VK_FALSE;
268 	depthStencilState.front = depthStencilState.back;
269 
270 	vk::PipelineMultisampleStateCreateInfo multisampleState;
271 	multisampleState.rasterizationSamples = multisample ? vk::SampleCountFlagBits::e4 : vk::SampleCountFlagBits::e1;
272 	multisampleState.pSampleMask = nullptr;
273 
274 	vk::ShaderModule vertexModule = hooks.createVertexShader(*this);
275 	vk::ShaderModule fragmentModule = hooks.createFragmentShader(*this);
276 
277 	assert(vertexModule);    // TODO: if nullptr, use a default
278 	assert(fragmentModule);  // TODO: if nullptr, use a default
279 
280 	std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages;
281 
282 	shaderStages[0].module = vertexModule;
283 	shaderStages[0].stage = vk::ShaderStageFlagBits::eVertex;
284 	shaderStages[0].pName = "main";
285 
286 	shaderStages[1].module = fragmentModule;
287 	shaderStages[1].stage = vk::ShaderStageFlagBits::eFragment;
288 	shaderStages[1].pName = "main";
289 
290 	pipelineCreateInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
291 	pipelineCreateInfo.pStages = shaderStages.data();
292 	pipelineCreateInfo.pVertexInputState = &vertices.inputState;
293 	pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
294 	pipelineCreateInfo.pRasterizationState = &rasterizationState;
295 	pipelineCreateInfo.pColorBlendState = &colorBlendState;
296 	pipelineCreateInfo.pMultisampleState = &multisampleState;
297 	pipelineCreateInfo.pViewportState = &viewportState;
298 	pipelineCreateInfo.pDepthStencilState = &depthStencilState;
299 	pipelineCreateInfo.renderPass = renderPass;
300 	pipelineCreateInfo.pDynamicState = &dynamicState;
301 
302 	auto pipeline = device.createGraphicsPipeline(nullptr, pipelineCreateInfo).value;
303 
304 	device.destroyShaderModule(fragmentModule);
305 	device.destroyShaderModule(vertexModule);
306 
307 	return pipeline;
308 }
309 
createSynchronizationPrimitives()310 void DrawTester::createSynchronizationPrimitives()
311 {
312 	vk::SemaphoreCreateInfo semaphoreCreateInfo;
313 	presentCompleteSemaphore = device.createSemaphore(semaphoreCreateInfo);
314 	renderCompleteSemaphore = device.createSemaphore(semaphoreCreateInfo);
315 
316 	vk::FenceCreateInfo fenceCreateInfo;
317 	fenceCreateInfo.flags = vk::FenceCreateFlagBits::eSignaled;
318 	waitFences.resize(swapchain->imageCount());
319 	for(auto &fence : waitFences)
320 	{
321 		fence = device.createFence(fenceCreateInfo);
322 	}
323 }
324 
createCommandBuffers(vk::RenderPass renderPass)325 void DrawTester::createCommandBuffers(vk::RenderPass renderPass)
326 {
327 	vk::CommandPoolCreateInfo commandPoolCreateInfo;
328 	commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
329 	commandPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
330 	commandPool = device.createCommandPool(commandPoolCreateInfo);
331 
332 	std::vector<vk::DescriptorSet> descriptorSets;
333 	if(descriptorSetLayout)
334 	{
335 		std::array<vk::DescriptorPoolSize, 1> poolSizes = {};
336 		poolSizes[0].type = vk::DescriptorType::eCombinedImageSampler;
337 		poolSizes[0].descriptorCount = 1;
338 
339 		vk::DescriptorPoolCreateInfo poolInfo;
340 		poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
341 		poolInfo.pPoolSizes = poolSizes.data();
342 		poolInfo.maxSets = 1;
343 
344 		descriptorPool = device.createDescriptorPool(poolInfo);
345 
346 		std::vector<vk::DescriptorSetLayout> layouts(1, descriptorSetLayout);
347 		vk::DescriptorSetAllocateInfo allocInfo;
348 		allocInfo.descriptorPool = descriptorPool;
349 		allocInfo.descriptorSetCount = 1;
350 		allocInfo.pSetLayouts = layouts.data();
351 
352 		descriptorSets = device.allocateDescriptorSets(allocInfo);
353 
354 		hooks.updateDescriptorSet(*this, commandPool, descriptorSets[0]);
355 	}
356 
357 	vk::CommandBufferAllocateInfo commandBufferAllocateInfo;
358 	commandBufferAllocateInfo.commandPool = commandPool;
359 	commandBufferAllocateInfo.commandBufferCount = static_cast<uint32_t>(swapchain->imageCount());
360 	commandBufferAllocateInfo.level = vk::CommandBufferLevel::ePrimary;
361 
362 	commandBuffers = device.allocateCommandBuffers(commandBufferAllocateInfo);
363 
364 	for(size_t i = 0; i < commandBuffers.size(); i++)
365 	{
366 		vk::CommandBufferBeginInfo commandBufferBeginInfo;
367 		commandBuffers[i].begin(commandBufferBeginInfo);
368 
369 		vk::ClearValue clearValues[1];
370 		clearValues[0].color = vk::ClearColorValue(std::array<float, 4>{ 0.5f, 0.5f, 0.5f, 1.0f });
371 
372 		vk::RenderPassBeginInfo renderPassBeginInfo;
373 		renderPassBeginInfo.framebuffer = framebuffers[i]->getFramebuffer();
374 		renderPassBeginInfo.renderPass = renderPass;
375 		renderPassBeginInfo.renderArea.offset.x = 0;
376 		renderPassBeginInfo.renderArea.offset.y = 0;
377 		renderPassBeginInfo.renderArea.extent = windowSize;
378 		renderPassBeginInfo.clearValueCount = ARRAY_SIZE(clearValues);
379 		renderPassBeginInfo.pClearValues = clearValues;
380 		commandBuffers[i].beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
381 
382 		// Set dynamic state
383 		vk::Viewport viewport(0.0f, 0.0f, static_cast<float>(windowSize.width), static_cast<float>(windowSize.height), 0.0f, 1.0f);
384 		commandBuffers[i].setViewport(0, 1, &viewport);
385 
386 		vk::Rect2D scissor(vk::Offset2D(0, 0), windowSize);
387 		commandBuffers[i].setScissor(0, 1, &scissor);
388 
389 		if(!descriptorSets.empty())
390 		{
391 			commandBuffers[i].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &descriptorSets[0], 0, nullptr);
392 		}
393 
394 		// Draw
395 		if(vertices.numVertices > 0)
396 		{
397 			commandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
398 			VULKAN_HPP_NAMESPACE::DeviceSize offset = 0;
399 			commandBuffers[i].bindVertexBuffers(0, 1, &vertices.buffer, &offset);
400 			commandBuffers[i].draw(vertices.numVertices, 1, 0, 0);
401 		}
402 
403 		commandBuffers[i].endRenderPass();
404 		commandBuffers[i].end();
405 	}
406 }
407 
addVertexBuffer(void * vertexBufferData,size_t vertexBufferDataSize,size_t vertexSize,std::vector<vk::VertexInputAttributeDescription> inputAttributes)408 void DrawTester::addVertexBuffer(void *vertexBufferData, size_t vertexBufferDataSize, size_t vertexSize, std::vector<vk::VertexInputAttributeDescription> inputAttributes)
409 {
410 	assert(!vertices.buffer);  // For now, only support adding once
411 
412 	vk::BufferCreateInfo vertexBufferInfo;
413 	vertexBufferInfo.size = vertexBufferDataSize;
414 	vertexBufferInfo.usage = vk::BufferUsageFlagBits::eVertexBuffer;
415 	vertices.buffer = device.createBuffer(vertexBufferInfo);
416 
417 	vk::MemoryAllocateInfo memoryAllocateInfo;
418 	vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(vertices.buffer);
419 	memoryAllocateInfo.allocationSize = memoryRequirements.size;
420 	memoryAllocateInfo.memoryTypeIndex = Util::getMemoryTypeIndex(physicalDevice, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
421 	vertices.memory = device.allocateMemory(memoryAllocateInfo);
422 
423 	void *data = device.mapMemory(vertices.memory, 0, VK_WHOLE_SIZE);
424 	memcpy(data, vertexBufferData, vertexBufferDataSize);
425 	device.unmapMemory(vertices.memory);
426 	device.bindBufferMemory(vertices.buffer, vertices.memory, 0);
427 
428 	vertices.inputBinding.binding = 0;
429 	vertices.inputBinding.stride = static_cast<uint32_t>(vertexSize);
430 	vertices.inputBinding.inputRate = vk::VertexInputRate::eVertex;
431 
432 	vertices.inputAttributes = std::move(inputAttributes);
433 
434 	vertices.inputState.vertexBindingDescriptionCount = 1;
435 	vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding;
436 	vertices.inputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertices.inputAttributes.size());
437 	vertices.inputState.pVertexAttributeDescriptions = vertices.inputAttributes.data();
438 
439 	// Note that we assume data is tightly packed
440 	vertices.numVertices = static_cast<uint32_t>(vertexBufferDataSize / vertexSize);
441 }
442 
createShaderModule(const char * glslSource,EShLanguage glslLanguage)443 vk::ShaderModule DrawTester::createShaderModule(const char *glslSource, EShLanguage glslLanguage)
444 {
445 	auto spirv = Util::compileGLSLtoSPIRV(glslSource, glslLanguage);
446 
447 	vk::ShaderModuleCreateInfo moduleCreateInfo;
448 	moduleCreateInfo.codeSize = spirv.size() * sizeof(uint32_t);
449 	moduleCreateInfo.pCode = (uint32_t *)spirv.data();
450 
451 	return device.createShaderModule(moduleCreateInfo);
452 }
453