You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
6.0 KiB
175 lines
6.0 KiB
// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "Util.hpp"
|
|
#include "SPIRV/GlslangToSpv.h"
|
|
#include "StandAlone/ResourceLimits.h"
|
|
|
|
namespace Util {
|
|
|
|
uint32_t getMemoryTypeIndex(vk::PhysicalDevice physicalDevice, uint32_t typeBits, vk::MemoryPropertyFlags properties)
|
|
{
|
|
vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties();
|
|
for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
|
|
{
|
|
if((typeBits & 1) == 1)
|
|
{
|
|
if((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
typeBits >>= 1;
|
|
}
|
|
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
|
|
vk::CommandBuffer beginSingleTimeCommands(vk::Device device, vk::CommandPool commandPool)
|
|
{
|
|
vk::CommandBufferAllocateInfo allocInfo{};
|
|
allocInfo.level = vk::CommandBufferLevel::ePrimary;
|
|
allocInfo.commandPool = commandPool;
|
|
allocInfo.commandBufferCount = 1;
|
|
|
|
auto commandBuffer = device.allocateCommandBuffers(allocInfo);
|
|
|
|
vk::CommandBufferBeginInfo beginInfo{};
|
|
beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
|
|
|
|
commandBuffer[0].begin(beginInfo);
|
|
|
|
return commandBuffer[0];
|
|
}
|
|
|
|
void endSingleTimeCommands(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::CommandBuffer commandBuffer)
|
|
{
|
|
commandBuffer.end();
|
|
|
|
vk::SubmitInfo submitInfo{};
|
|
submitInfo.commandBufferCount = 1;
|
|
submitInfo.pCommandBuffers = &commandBuffer;
|
|
|
|
vk::Fence fence = {}; // TODO: pass in fence?
|
|
queue.submit(1, &submitInfo, fence);
|
|
queue.waitIdle();
|
|
|
|
device.freeCommandBuffers(commandPool, 1, &commandBuffer);
|
|
}
|
|
|
|
void transitionImageLayout(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
|
|
{
|
|
vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
|
|
|
|
vk::ImageMemoryBarrier barrier{};
|
|
barrier.oldLayout = oldLayout;
|
|
barrier.newLayout = newLayout;
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
barrier.image = image;
|
|
barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
|
|
barrier.subresourceRange.baseMipLevel = 0;
|
|
barrier.subresourceRange.levelCount = 1;
|
|
barrier.subresourceRange.baseArrayLayer = 0;
|
|
barrier.subresourceRange.layerCount = 1;
|
|
|
|
vk::PipelineStageFlags sourceStage;
|
|
vk::PipelineStageFlags destinationStage;
|
|
|
|
if(oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
|
|
{
|
|
barrier.srcAccessMask = {};
|
|
barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
|
|
|
|
sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
|
destinationStage = vk::PipelineStageFlagBits::eTransfer;
|
|
}
|
|
else if(oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
|
|
{
|
|
barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
|
|
barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
|
|
|
|
sourceStage = vk::PipelineStageFlagBits::eTransfer;
|
|
destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
|
|
}
|
|
else
|
|
{
|
|
assert(false && "unsupported layout transition!");
|
|
}
|
|
|
|
commandBuffer.pipelineBarrier(sourceStage, destinationStage, vk::DependencyFlags{}, 0, nullptr, 0, nullptr, 1, &barrier);
|
|
|
|
endSingleTimeCommands(device, commandPool, queue, commandBuffer);
|
|
}
|
|
|
|
void copyBufferToImage(vk::Device device, vk::CommandPool commandPool, vk::Queue queue, vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height)
|
|
{
|
|
vk::CommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
|
|
|
|
vk::BufferImageCopy region{};
|
|
region.bufferOffset = 0;
|
|
region.bufferRowLength = 0;
|
|
region.bufferImageHeight = 0;
|
|
region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
|
|
region.imageSubresource.mipLevel = 0;
|
|
region.imageSubresource.baseArrayLayer = 0;
|
|
region.imageSubresource.layerCount = 1;
|
|
region.imageOffset = vk::Offset3D{ 0, 0, 0 };
|
|
region.imageExtent = vk::Extent3D{ width, height, 1 };
|
|
|
|
commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
|
|
|
|
endSingleTimeCommands(device, commandPool, queue, commandBuffer);
|
|
}
|
|
|
|
std::vector<uint32_t> compileGLSLtoSPIRV(const char *glslSource, EShLanguage glslLanguage)
|
|
{
|
|
// glslang requires one-time initialization.
|
|
const struct GlslangProcessInitialiser
|
|
{
|
|
GlslangProcessInitialiser() { glslang::InitializeProcess(); }
|
|
~GlslangProcessInitialiser() { glslang::FinalizeProcess(); }
|
|
} glslangInitialiser;
|
|
|
|
std::unique_ptr<glslang::TShader> glslangShader = std::make_unique<glslang::TShader>(glslLanguage);
|
|
|
|
glslangShader->setStrings(&glslSource, 1);
|
|
glslangShader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
|
|
glslangShader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
|
|
|
|
const int defaultVersion = 100;
|
|
EShMessages messages = static_cast<EShMessages>(EShMessages::EShMsgDefault | EShMessages::EShMsgSpvRules | EShMessages::EShMsgVulkanRules);
|
|
bool parseResult = glslangShader->parse(&glslang::DefaultTBuiltInResource, defaultVersion, false, messages);
|
|
|
|
if(!parseResult)
|
|
{
|
|
std::string debugLog = glslangShader->getInfoDebugLog();
|
|
std::string infoLog = glslangShader->getInfoLog();
|
|
assert(false && "Failed to parse shader");
|
|
}
|
|
|
|
glslang::TIntermediate *intermediateRepresentation = glslangShader->getIntermediate();
|
|
assert(intermediateRepresentation);
|
|
|
|
std::vector<uint32_t> spirv;
|
|
glslang::SpvOptions options;
|
|
glslang::GlslangToSpv(*intermediateRepresentation, spirv, &options);
|
|
assert(spirv.size() != 0);
|
|
|
|
return spirv;
|
|
}
|
|
|
|
} // namespace Util
|