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, ®ion);
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