1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2021 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "Util.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "SPIRV/GlslangToSpv.h"
17*03ce13f7SAndroid Build Coastguard Worker #include "glslang/Public/ResourceLimits.h"
18*03ce13f7SAndroid Build Coastguard Worker
19*03ce13f7SAndroid Build Coastguard Worker #include <memory>
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard Worker namespace Util {
22*03ce13f7SAndroid Build Coastguard Worker
getMemoryTypeIndex(vk::PhysicalDevice physicalDevice,uint32_t typeBits,vk::MemoryPropertyFlags properties)23*03ce13f7SAndroid Build Coastguard Worker uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties)
24*03ce13f7SAndroid Build Coastguard Worker {
25*03ce13f7SAndroid Build Coastguard Worker vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties();
26*03ce13f7SAndroid Build Coastguard Worker for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
27*03ce13f7SAndroid Build Coastguard Worker {
28*03ce13f7SAndroid Build Coastguard Worker if((typeBits & 1) == 1)
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker if((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
31*03ce13f7SAndroid Build Coastguard Worker {
32*03ce13f7SAndroid Build Coastguard Worker return i;
33*03ce13f7SAndroid Build Coastguard Worker }
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker typeBits >>= 1;
36*03ce13f7SAndroid Build Coastguard Worker }
37*03ce13f7SAndroid Build Coastguard Worker
38*03ce13f7SAndroid Build Coastguard Worker assert(false);
39*03ce13f7SAndroid Build Coastguard Worker return -1;
40*03ce13f7SAndroid Build Coastguard Worker }
41*03ce13f7SAndroid Build Coastguard Worker
beginSingleTimeCommands(vk::Device device,vk::CommandPool commandPool)42*03ce13f7SAndroid Build Coastguard Worker vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool)
43*03ce13f7SAndroid Build Coastguard Worker {
44*03ce13f7SAndroid Build Coastguard Worker vk::CommandBufferAllocateInfo allocInfo{};
45*03ce13f7SAndroid Build Coastguard Worker allocInfo.level = vk::CommandBufferLevel::ePrimary;
46*03ce13f7SAndroid Build Coastguard Worker allocInfo.commandPool = commandPool;
47*03ce13f7SAndroid Build Coastguard Worker allocInfo.commandBufferCount = 1;
48*03ce13f7SAndroid Build Coastguard Worker
49*03ce13f7SAndroid Build Coastguard Worker auto commandBuffer = device.allocateCommandBuffers(allocInfo);
50*03ce13f7SAndroid Build Coastguard Worker
51*03ce13f7SAndroid Build Coastguard Worker vk::CommandBufferBeginInfo beginInfo{};
52*03ce13f7SAndroid Build Coastguard Worker beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker commandBuffer[0].begin(beginInfo);
55*03ce13f7SAndroid Build Coastguard Worker
56*03ce13f7SAndroid Build Coastguard Worker return commandBuffer[0];
57*03ce13f7SAndroid Build Coastguard Worker }
58*03ce13f7SAndroid Build Coastguard Worker
endSingleTimeCommands(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::CommandBuffer commandBuffer)59*03ce13f7SAndroid Build Coastguard Worker void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer)
60*03ce13f7SAndroid Build Coastguard Worker {
61*03ce13f7SAndroid Build Coastguard Worker commandBuffer.end();
62*03ce13f7SAndroid Build Coastguard Worker
63*03ce13f7SAndroid Build Coastguard Worker vk::SubmitInfo submitInfo{};
64*03ce13f7SAndroid Build Coastguard Worker submitInfo.commandBufferCount = 1;
65*03ce13f7SAndroid Build Coastguard Worker submitInfo.pCommandBuffers = &commandBuffer;
66*03ce13f7SAndroid Build Coastguard Worker
67*03ce13f7SAndroid Build Coastguard Worker vk::Fence fence = {}; // TODO: pass in fence?
68*03ce13f7SAndroid Build Coastguard Worker queue.submit(1, &submitInfo, fence);
69*03ce13f7SAndroid Build Coastguard Worker queue.waitIdle();
70*03ce13f7SAndroid Build Coastguard Worker
71*03ce13f7SAndroid Build Coastguard Worker device.freeCommandBuffers(commandPool, 1, &commandBuffer);
72*03ce13f7SAndroid Build Coastguard Worker }
73*03ce13f7SAndroid Build Coastguard Worker
transitionImageLayout(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::Image image,vk::Format format,vk::ImageLayout oldLayout,vk::ImageLayout newLayout)74*03ce13f7SAndroid Build Coastguard Worker void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
75*03ce13f7SAndroid Build Coastguard Worker {
76*03ce13f7SAndroid Build Coastguard Worker vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
77*03ce13f7SAndroid Build Coastguard Worker
78*03ce13f7SAndroid Build Coastguard Worker vk::ImageMemoryBarrier barrier{};
79*03ce13f7SAndroid Build Coastguard Worker barrier.oldLayout = oldLayout;
80*03ce13f7SAndroid Build Coastguard Worker barrier.newLayout = newLayout;
81*03ce13f7SAndroid Build Coastguard Worker barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
82*03ce13f7SAndroid Build Coastguard Worker barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
83*03ce13f7SAndroid Build Coastguard Worker barrier.image = image;
84*03ce13f7SAndroid Build Coastguard Worker barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
85*03ce13f7SAndroid Build Coastguard Worker barrier.subresourceRange.baseMipLevel = 0;
86*03ce13f7SAndroid Build Coastguard Worker barrier.subresourceRange.levelCount = 1;
87*03ce13f7SAndroid Build Coastguard Worker barrier.subresourceRange.baseArrayLayer = 0;
88*03ce13f7SAndroid Build Coastguard Worker barrier.subresourceRange.layerCount = 1;
89*03ce13f7SAndroid Build Coastguard Worker
90*03ce13f7SAndroid Build Coastguard Worker vk::PipelineStageFlags sourceStage;
91*03ce13f7SAndroid Build Coastguard Worker vk::PipelineStageFlags destinationStage;
92*03ce13f7SAndroid Build Coastguard Worker
93*03ce13f7SAndroid Build Coastguard Worker if(oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
94*03ce13f7SAndroid Build Coastguard Worker {
95*03ce13f7SAndroid Build Coastguard Worker barrier.srcAccessMask = {};
96*03ce13f7SAndroid Build Coastguard Worker barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
97*03ce13f7SAndroid Build Coastguard Worker
98*03ce13f7SAndroid Build Coastguard Worker sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
99*03ce13f7SAndroid Build Coastguard Worker destinationStage = vk::PipelineStageFlagBits::eTransfer;
100*03ce13f7SAndroid Build Coastguard Worker }
101*03ce13f7SAndroid Build Coastguard Worker else if(oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
102*03ce13f7SAndroid Build Coastguard Worker {
103*03ce13f7SAndroid Build Coastguard Worker barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
104*03ce13f7SAndroid Build Coastguard Worker barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
105*03ce13f7SAndroid Build Coastguard Worker
106*03ce13f7SAndroid Build Coastguard Worker sourceStage = vk::PipelineStageFlagBits::eTransfer;
107*03ce13f7SAndroid Build Coastguard Worker destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker else
110*03ce13f7SAndroid Build Coastguard Worker {
111*03ce13f7SAndroid Build Coastguard Worker assert(false && "unsupported layout transition!");
112*03ce13f7SAndroid Build Coastguard Worker }
113*03ce13f7SAndroid Build Coastguard Worker
114*03ce13f7SAndroid Build Coastguard Worker commandBuffer.pipelineBarrier(sourceStage, destinationStage, vk::DependencyFlags{}, 0, nullptr, 0, nullptr, 1, &barrier);
115*03ce13f7SAndroid Build Coastguard Worker
116*03ce13f7SAndroid Build Coastguard Worker endSingleTimeCommands(device, commandPool, queue, commandBuffer);
117*03ce13f7SAndroid Build Coastguard Worker }
118*03ce13f7SAndroid Build Coastguard Worker
copyBufferToImage(vk::Device device,vk::CommandPool commandPool,vk::Queue queue,vk::Buffer buffer,vk::Image image,uint32_t width,uint32_t height)119*03ce13f7SAndroid Build Coastguard Worker void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height)
120*03ce13f7SAndroid Build Coastguard Worker {
121*03ce13f7SAndroid Build Coastguard Worker vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
122*03ce13f7SAndroid Build Coastguard Worker
123*03ce13f7SAndroid Build Coastguard Worker vk::BufferImageCopy region{};
124*03ce13f7SAndroid Build Coastguard Worker region.bufferOffset = 0;
125*03ce13f7SAndroid Build Coastguard Worker region.bufferRowLength = 0;
126*03ce13f7SAndroid Build Coastguard Worker region.bufferImageHeight = 0;
127*03ce13f7SAndroid Build Coastguard Worker region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
128*03ce13f7SAndroid Build Coastguard Worker region.imageSubresource.mipLevel = 0;
129*03ce13f7SAndroid Build Coastguard Worker region.imageSubresource.baseArrayLayer = 0;
130*03ce13f7SAndroid Build Coastguard Worker region.imageSubresource.layerCount = 1;
131*03ce13f7SAndroid Build Coastguard Worker region.imageOffset = vk::Offset3D{ 0, 0, 0 };
132*03ce13f7SAndroid Build Coastguard Worker region.imageExtent = vk::Extent3D{ width, height, 1 };
133*03ce13f7SAndroid Build Coastguard Worker
134*03ce13f7SAndroid Build Coastguard Worker commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
135*03ce13f7SAndroid Build Coastguard Worker
136*03ce13f7SAndroid Build Coastguard Worker endSingleTimeCommands(device, commandPool, queue, commandBuffer);
137*03ce13f7SAndroid Build Coastguard Worker }
138*03ce13f7SAndroid Build Coastguard Worker
compileGLSLtoSPIRV(const char * glslSource,EShLanguage glslLanguage)139*03ce13f7SAndroid Build Coastguard Worker std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage)
140*03ce13f7SAndroid Build Coastguard Worker {
141*03ce13f7SAndroid Build Coastguard Worker // glslang requires one-time initialization.
142*03ce13f7SAndroid Build Coastguard Worker const struct GlslangProcessInitialiser
143*03ce13f7SAndroid Build Coastguard Worker {
144*03ce13f7SAndroid Build Coastguard Worker GlslangProcessInitialiser() { glslang::InitializeProcess(); }
145*03ce13f7SAndroid Build Coastguard Worker ~GlslangProcessInitialiser() { glslang::FinalizeProcess(); }
146*03ce13f7SAndroid Build Coastguard Worker } glslangInitialiser;
147*03ce13f7SAndroid Build Coastguard Worker
148*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<glslang::TShader> glslangShader = std::make_unique<glslang::TShader>(glslLanguage);
149*03ce13f7SAndroid Build Coastguard Worker
150*03ce13f7SAndroid Build Coastguard Worker glslangShader->setStrings(&glslSource, 1);
151*03ce13f7SAndroid Build Coastguard Worker glslangShader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
152*03ce13f7SAndroid Build Coastguard Worker glslangShader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
153*03ce13f7SAndroid Build Coastguard Worker
154*03ce13f7SAndroid Build Coastguard Worker const int defaultVersion = 100;
155*03ce13f7SAndroid Build Coastguard Worker EShMessages messages = static_cast<EShMessages>(EShMessages::EShMsgDefault | EShMessages::EShMsgSpvRules | EShMessages::EShMsgVulkanRules);
156*03ce13f7SAndroid Build Coastguard Worker bool parseResult = glslangShader->parse(GetDefaultResources(), defaultVersion, false, messages);
157*03ce13f7SAndroid Build Coastguard Worker
158*03ce13f7SAndroid Build Coastguard Worker if(!parseResult)
159*03ce13f7SAndroid Build Coastguard Worker {
160*03ce13f7SAndroid Build Coastguard Worker std::string debugLog = glslangShader->getInfoDebugLog();
161*03ce13f7SAndroid Build Coastguard Worker std::string infoLog = glslangShader->getInfoLog();
162*03ce13f7SAndroid Build Coastguard Worker assert(false && "Failed to parse shader");
163*03ce13f7SAndroid Build Coastguard Worker }
164*03ce13f7SAndroid Build Coastguard Worker
165*03ce13f7SAndroid Build Coastguard Worker glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
166*03ce13f7SAndroid Build Coastguard Worker assert(intermediateRepresentation);
167*03ce13f7SAndroid Build Coastguard Worker
168*03ce13f7SAndroid Build Coastguard Worker std::vector<uint32_t> spirv;
169*03ce13f7SAndroid Build Coastguard Worker glslang::SpvOptions options;
170*03ce13f7SAndroid Build Coastguard Worker glslang::GlslangToSpv(*intermediateRepresentation, spirv, &options);
171*03ce13f7SAndroid Build Coastguard Worker assert(spirv.size() != 0);
172*03ce13f7SAndroid Build Coastguard Worker
173*03ce13f7SAndroid Build Coastguard Worker return spirv;
174*03ce13f7SAndroid Build Coastguard Worker }
175*03ce13f7SAndroid Build Coastguard Worker
176*03ce13f7SAndroid Build Coastguard Worker } // namespace Util
177