• 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 "Util.hpp"
16 #include "SPIRV/GlslangToSpv.h"
17 #include "StandAlone/ResourceLimits.h"
18 
19 namespace Util {
20 
getMemoryTypeIndex(vk::PhysicalDevice physicalDevice,uint32_t typeBits,vk::MemoryPropertyFlags properties)21 uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties)
22 {
23 	vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties();
24 	for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
25 	{
26 		if((typeBits & 1) == 1)
27 		{
28 			if((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
29 			{
30 				return i;
31 			}
32 		}
33 		typeBits >>= 1;
34 	}
35 
36 	assert(false);
37 	return -1;
38 }
39 
beginSingleTimeCommands(vk::Device device,vk::CommandPool commandPool)40 vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool)
41 {
42 	vk::CommandBufferAllocateInfo allocInfo{};
43 	allocInfo.level = vk::CommandBufferLevel::ePrimary;
44 	allocInfo.commandPool = commandPool;
45 	allocInfo.commandBufferCount = 1;
46 
47 	auto commandBuffer = device.allocateCommandBuffers(allocInfo);
48 
49 	vk::CommandBufferBeginInfo beginInfo{};
50 	beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
51 
52 	commandBuffer[0].begin(beginInfo);
53 
54 	return commandBuffer[0];
55 }
56 
endSingleTimeCommands(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::CommandBuffer commandBuffer)57 void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer)
58 {
59 	commandBuffer.end();
60 
61 	vk::SubmitInfo submitInfo{};
62 	submitInfo.commandBufferCount = 1;
63 	submitInfo.pCommandBuffers = &commandBuffer;
64 
65 	vk::Fence fence = {};  // TODO: pass in fence?
66 	queue.submit(1, &submitInfo, fence);
67 	queue.waitIdle();
68 
69 	device.freeCommandBuffers(commandPool, 1, &commandBuffer);
70 }
71 
transitionImageLayout(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::Image image,vk::Format format,vk::ImageLayout oldLayout,vk::ImageLayout newLayout)72 void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
73 {
74 	vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
75 
76 	vk::ImageMemoryBarrier barrier{};
77 	barrier.oldLayout = oldLayout;
78 	barrier.newLayout = newLayout;
79 	barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
80 	barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
81 	barrier.image = image;
82 	barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
83 	barrier.subresourceRange.baseMipLevel = 0;
84 	barrier.subresourceRange.levelCount = 1;
85 	barrier.subresourceRange.baseArrayLayer = 0;
86 	barrier.subresourceRange.layerCount = 1;
87 
88 	vk::PipelineStageFlags sourceStage;
89 	vk::PipelineStageFlags destinationStage;
90 
91 	if(oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
92 	{
93 		barrier.srcAccessMask = {};
94 		barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
95 
96 		sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
97 		destinationStage = vk::PipelineStageFlagBits::eTransfer;
98 	}
99 	else if(oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
100 	{
101 		barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
102 		barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
103 
104 		sourceStage = vk::PipelineStageFlagBits::eTransfer;
105 		destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
106 	}
107 	else
108 	{
109 		assert(false && "unsupported layout transition!");
110 	}
111 
112 	commandBuffer.pipelineBarrier(sourceStage, destinationStage, vk::DependencyFlags{}, 0, nullptr, 0, nullptr, 1, &barrier);
113 
114 	endSingleTimeCommands(device, commandPool, queue, commandBuffer);
115 }
116 
copyBufferToImage(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::Buffer buffer,vk::Image image,uint32_t width,uint32_t height)117 void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height)
118 {
119 	vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
120 
121 	vk::BufferImageCopy region{};
122 	region.bufferOffset = 0;
123 	region.bufferRowLength = 0;
124 	region.bufferImageHeight = 0;
125 	region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
126 	region.imageSubresource.mipLevel = 0;
127 	region.imageSubresource.baseArrayLayer = 0;
128 	region.imageSubresource.layerCount = 1;
129 	region.imageOffset = vk::Offset3D{ 0, 0, 0 };
130 	region.imageExtent = vk::Extent3D{ width, height, 1 };
131 
132 	commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, &region);
133 
134 	endSingleTimeCommands(device, commandPool, queue, commandBuffer);
135 }
136 
compileGLSLtoSPIRV(const char * glslSource,EShLanguage glslLanguage)137 std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage)
138 {
139 	// glslang requires one-time initialization.
140 	const struct GlslangProcessInitialiser
141 	{
142 		GlslangProcessInitialiser() { glslang::InitializeProcess(); }
143 		~GlslangProcessInitialiser() { glslang::FinalizeProcess(); }
144 	} glslangInitialiser;
145 
146 	std::unique_ptr<glslang::TShader> glslangShader = std::make_unique<glslang::TShader>(glslLanguage);
147 
148 	glslangShader->setStrings(&glslSource, 1);
149 	glslangShader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
150 	glslangShader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
151 
152 	const int defaultVersion = 100;
153 	EShMessages messages = static_cast<EShMessages>(EShMessages::EShMsgDefault | EShMessages::EShMsgSpvRules | EShMessages::EShMsgVulkanRules);
154 	bool parseResult = glslangShader->parse(&glslang::DefaultTBuiltInResource, defaultVersion, false, messages);
155 
156 	if(!parseResult)
157 	{
158 		std::string debugLog = glslangShader->getInfoDebugLog();
159 		std::string infoLog = glslangShader->getInfoLog();
160 		assert(false && "Failed to parse shader");
161 	}
162 
163 	glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
164 	assert(intermediateRepresentation);
165 
166 	std::vector<uint32_t> spirv;
167 	glslang::SpvOptions options;
168 	glslang::GlslangToSpv(*intermediateRepresentation, spirv, &options);
169 	assert(spirv.size() != 0);
170 
171 	return spirv;
172 }
173 
174 }  // namespace Util
175