| /*------------------------------------------------------------------------- |
| * Vulkan CTS Framework |
| * -------------------- |
| * |
| * Copyright (c) 2021 The Khronos Group Inc. |
| * |
| * 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 "vksServices.hpp" |
| #include "vksJson.hpp" |
| #include "vksCacheBuilder.hpp" |
| #include "vksStore.hpp" |
| |
| #include <map> |
| #include <mutex> |
| #include <fstream> |
| #include <iostream> |
| |
| #include "deUniquePtr.hpp" |
| #include "vkPrograms.hpp" |
| #include "vkPlatform.hpp" |
| #include "vkDeviceUtil.hpp" |
| #include "vktTestCase.hpp" |
| #include "tcuCommandLine.hpp" |
| #include "tcuPlatform.hpp" |
| #include "tcuTestContext.hpp" |
| #include "tcuResource.hpp" |
| #include "tcuTestLog.hpp" |
| |
| tcu::Platform* createPlatform (void); |
| |
| struct VkscServer |
| { |
| const vk::PlatformInterface& vkp; |
| vk::VkInstance instance; |
| const vk::InstanceInterface& vki; |
| vk::VkPhysicalDevice physicalDevice; |
| deUint32 queueIndex; |
| const vk::VkPhysicalDeviceFeatures2& enabledFeatures; |
| }; |
| |
| VkscServer* createServerVKSC(const std::string& logFile); |
| std::unique_ptr<VkscServer> vkscServer; |
| |
| namespace vksc_server |
| { |
| |
| using namespace json; |
| |
| Store ServiceStore; |
| |
| bool LoadPhysicalFile (const string& path, vector<u8>& content) |
| { |
| std::ifstream file(path, std::ios::binary); |
| if (!file) return false; |
| |
| content.assign((std::istreambuf_iterator<char>(file)), |
| std::istreambuf_iterator<char>()); |
| |
| return true; |
| } |
| |
| bool StoreFile (const string& uniqueFilename, const vector<u8>& content) |
| { |
| return ServiceStore.Set(uniqueFilename, content); |
| } |
| |
| bool GetFile (const string& path, vector<u8>& content, bool removeAfter) |
| { |
| return ServiceStore.Get(path, content, removeAfter) || LoadPhysicalFile(path, content); |
| } |
| |
| bool AppendFile (const string& path, const vector<u8>& content, bool clear) |
| { |
| auto mode = clear ? std::ios::binary : std::ios::binary | std::ios::app; |
| |
| std::ofstream file(path, mode); |
| if (!file) return false; |
| |
| std::copy(content.begin(), content.end(), std::ostream_iterator<u8>{file}); |
| |
| return true; |
| } |
| |
| void CreateVulkanSCCache (const VulkanPipelineCacheInput& input, int caseFraction, vector<u8>& binary, const CmdLineParams& cmdLineParams, const std::string& logFile) |
| { |
| if (!cmdLineParams.compilerPath.empty()) |
| { |
| std::stringstream prefix; |
| if (caseFraction >= 0) |
| prefix << "sub_" << caseFraction << "_"; |
| else |
| prefix << ""; |
| |
| binary = vksc_server::buildOfflinePipelineCache(input, |
| cmdLineParams.compilerPath, |
| cmdLineParams.compilerDataDir, |
| cmdLineParams.compilerArgs, |
| cmdLineParams.compilerPipelineCacheFile, |
| cmdLineParams.compilerLogFile, |
| prefix.str()); |
| } |
| else |
| { |
| if (vkscServer.get() == DE_NULL) |
| vkscServer.reset(createServerVKSC(logFile)); |
| |
| binary = buildPipelineCache(input, |
| vkscServer->vkp, |
| vkscServer->instance, |
| vkscServer->vki, |
| vkscServer->physicalDevice, |
| vkscServer->queueIndex); |
| } |
| } |
| |
| bool CompileShader (const SourceVariant& source, const string& commandLine, vector<u8>& binary) |
| { |
| glu::ShaderProgramInfo programInfo; |
| vk::SpirVProgramInfo programInfoSpirv; |
| tcu::CommandLine cmd(commandLine); |
| |
| std::unique_ptr<vk::ProgramBinary> programBinary; |
| |
| if (source.active == "glsl") programBinary.reset( vk::buildProgram(source.glsl, &programInfo, cmd) ); |
| else if (source.active == "hlsl") programBinary.reset( vk::buildProgram(source.hlsl, &programInfo, cmd) ); |
| else if (source.active == "spirv") programBinary.reset( vk::assembleProgram(source.spirv, &programInfoSpirv, cmd) ); |
| else return false; |
| |
| if (!programBinary || programBinary->getBinary() == nullptr) |
| { |
| return false; |
| } |
| |
| if (programBinary->getFormat() != vk::PROGRAM_FORMAT_SPIRV) |
| { |
| throw std::runtime_error("CompileShader supports only PROGRAM_FORMAT_SPIRV binary output"); |
| } |
| |
| binary.assign( programBinary->getBinary(), |
| programBinary->getBinary() + programBinary->getSize() ); |
| |
| return true; |
| } |
| |
| } // vksc_server |
| |
| VkscServer* createServerVKSC(const std::string& logFile) |
| { |
| tcu::CommandLine cmdLine {"--deqp-vk-device-id=0"}; |
| tcu::DirArchive archive {""}; |
| tcu::TestLog log { logFile.c_str() }; log.supressLogging(true); |
| tcu::Platform* platform {createPlatform()}; |
| vk::Library* library {platform->getVulkanPlatform().createLibrary()}; |
| tcu::TestContext* tcx = new tcu::TestContext{*platform, archive, log, cmdLine, nullptr}; |
| vk::ResourceInterface* resource = new vk::ResourceInterfaceStandard{*tcx}; |
| vk::BinaryCollection* collection = new vk::BinaryCollection{}; |
| vkt::Context* context = new vkt::Context(*tcx, library->getPlatformInterface(), *collection, de::SharedPtr<vk::ResourceInterface>{resource}); |
| |
| VkscServer* result = new VkscServer |
| { |
| library->getPlatformInterface(), |
| context->getInstance(), |
| context->getInstanceInterface(), |
| context->getPhysicalDevice(), |
| context->getUniversalQueueFamilyIndex(), |
| context->getDeviceFeatures2() |
| }; |
| |
| return result; |
| } |