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