Refactor SPIR-V binary storage This change introduces sw::SpirvBinary, which represents a raw SPIR-V binary as a vector of 32-bit words. Additional utility methods are expected to be moved from sw::SpirvShader into this class. Bug: b/197982536 Change-Id: Ibe3b4c16f7b5c2f56c9e0a7557bedab716cfe704 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/57128 Reviewed-by: Alexis Hétu <sugoi@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/BUILD.gn b/src/Pipeline/BUILD.gn index d579689..d88e255 100644 --- a/src/Pipeline/BUILD.gn +++ b/src/Pipeline/BUILD.gn
@@ -23,6 +23,7 @@ "SamplerCore.hpp", "SetupRoutine.hpp", "ShaderCore.hpp", + "SpirvBinary.hpp", "SpirvShader.hpp", "SpirvShaderDebug.hpp", "VertexProgram.hpp",
diff --git a/src/Pipeline/CMakeLists.txt b/src/Pipeline/CMakeLists.txt index ba8c1f2..4daf9e1 100644 --- a/src/Pipeline/CMakeLists.txt +++ b/src/Pipeline/CMakeLists.txt
@@ -32,6 +32,7 @@ SetupRoutine.hpp ShaderCore.cpp ShaderCore.hpp + SpirvBinary.hpp SpirvID.hpp SpirvShader.cpp SpirvShader.hpp
diff --git a/src/Pipeline/SpirvBinary.hpp b/src/Pipeline/SpirvBinary.hpp new file mode 100644 index 0000000..b4766bb --- /dev/null +++ b/src/Pipeline/SpirvBinary.hpp
@@ -0,0 +1,36 @@ +// Copyright 2018 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. + +#ifndef sw_SpirvBinary_hpp +#define sw_SpirvBinary_hpp + +#include <cstdint> +#include <vector> + +namespace sw { + +class SpirvBinary : public std::vector<uint32_t> +{ +public: + SpirvBinary() = default; + + SpirvBinary(const uint32_t *binary, uint32_t wordCount) + : std::vector<uint32_t>(binary, binary + wordCount) + { + } +}; + +} // namespace sw + +#endif // sw_SpirvBinary_hpp
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index 37ccbb3..4718c3c 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp
@@ -29,7 +29,7 @@ uint32_t codeSerialID, VkShaderStageFlagBits pipelineStage, const char *entryPointName, - InsnStore const &insns, + SpirvBinary const &insns, const vk::RenderPass *renderPass, uint32_t subpassIndex, bool robustBufferAccess,
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp index 62b885b..45bb576 100644 --- a/src/Pipeline/SpirvShader.hpp +++ b/src/Pipeline/SpirvShader.hpp
@@ -17,6 +17,7 @@ #include "SamplerCore.hpp" #include "ShaderCore.hpp" +#include "SpirvBinary.hpp" #include "SpirvID.hpp" #include "Device/Config.hpp" #include "Device/Sampler.hpp" @@ -152,8 +153,7 @@ class SpirvShader { public: - using InsnStore = std::vector<uint32_t>; - InsnStore insns; + SpirvBinary insns; using ImageSampler = void(void *texture, void *uvsIn, void *texelOut, void *constants); @@ -173,7 +173,7 @@ InsnIterator() = default; - explicit InsnIterator(InsnStore::const_iterator iter) + explicit InsnIterator(SpirvBinary::const_iterator iter) : iter{ iter } { } @@ -282,7 +282,7 @@ } private: - InsnStore::const_iterator iter; + SpirvBinary::const_iterator iter; }; /* range-based-for interface */ @@ -565,7 +565,7 @@ SpirvShader(uint32_t codeSerialID, VkShaderStageFlagBits stage, const char *entryPointName, - InsnStore const &insns, + SpirvBinary const &insns, const vk::RenderPass *renderPass, uint32_t subpassIndex, bool robustBufferAccess,
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp index 3901672..8ab06d9 100644 --- a/src/Vulkan/VkPipeline.cpp +++ b/src/Vulkan/VkPipeline.cpp
@@ -33,8 +33,8 @@ namespace { // preprocessSpirv applies and freezes specializations into constants, and inlines all functions. -std::vector<uint32_t> preprocessSpirv( - std::vector<uint32_t> const &code, +sw::SpirvBinary preprocessSpirv( + sw::SpirvBinary const &code, VkSpecializationInfo const *specializationInfo, bool optimize) { @@ -57,14 +57,17 @@ if(specializationInfo) { std::unordered_map<uint32_t, std::vector<uint32_t>> specializations; - for(auto i = 0u; i < specializationInfo->mapEntryCount; ++i) + const uint8_t *specializationData = static_cast<const uint8_t *>(specializationInfo->pData); + + for(uint32_t i = 0; i < specializationInfo->mapEntryCount; i++) { - auto const &e = specializationInfo->pMapEntries[i]; - auto value_ptr = - static_cast<uint32_t const *>(specializationInfo->pData) + e.offset / sizeof(uint32_t); - specializations.emplace(e.constantID, - std::vector<uint32_t>{ value_ptr, value_ptr + e.size / sizeof(uint32_t) }); + const VkSpecializationMapEntry &entry = specializationInfo->pMapEntries[i]; + const uint8_t *value_ptr = specializationData + entry.offset; + std::vector<uint32_t> value(reinterpret_cast<const uint32_t *>(value_ptr), + reinterpret_cast<const uint32_t *>(value_ptr + entry.size)); + specializations.emplace(entry.constantID, std::move(value)); } + opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations)); } @@ -85,7 +88,7 @@ optimizerOptions.set_validator_options(validatorOptions); #endif - std::vector<uint32_t> optimized; + sw::SpirvBinary optimized; opt.Run(code.data(), code.size(), &optimized, optimizerOptions); if(false)
diff --git a/src/Vulkan/VkPipelineCache.cpp b/src/Vulkan/VkPipelineCache.cpp index 375334f..0aa72d6 100644 --- a/src/Vulkan/VkPipelineCache.cpp +++ b/src/Vulkan/VkPipelineCache.cpp
@@ -13,13 +13,14 @@ // limitations under the License. #include "VkPipelineCache.hpp" + #include <cstring> namespace vk { PipelineCache::SpirvShaderKey::SpirvShaderKey(const VkShaderStageFlagBits pipelineStage, const std::string &entryPointName, - const std::vector<uint32_t> &insns, + const sw::SpirvBinary &insns, const vk::RenderPass *renderPass, const uint32_t subpassIndex, const vk::SpecializationInfo &specializationInfo)
diff --git a/src/Vulkan/VkPipelineCache.hpp b/src/Vulkan/VkPipelineCache.hpp index 83664b6..933bfbf 100644 --- a/src/Vulkan/VkPipelineCache.hpp +++ b/src/Vulkan/VkPipelineCache.hpp
@@ -17,6 +17,7 @@ #include "VkObject.hpp" #include "VkSpecializationInfo.hpp" +#include "Pipeline/SpirvBinary.hpp" #include "marl/mutex.h" #include "marl/tsa.h" @@ -56,7 +57,7 @@ { SpirvShaderKey(const VkShaderStageFlagBits pipelineStage, const std::string &entryPointName, - const std::vector<uint32_t> &insns, + const sw::SpirvBinary &insns, const vk::RenderPass *renderPass, const uint32_t subpassIndex, const vk::SpecializationInfo &specializationInfo); @@ -65,7 +66,7 @@ const VkShaderStageFlagBits &getPipelineStage() const { return pipelineStage; } const std::string &getEntryPointName() const { return entryPointName; } - const std::vector<uint32_t> &getInsns() const { return insns; } + const sw::SpirvBinary &getInsns() const { return insns; } const vk::RenderPass *getRenderPass() const { return renderPass; } uint32_t getSubpassIndex() const { return subpassIndex; } const VkSpecializationInfo *getSpecializationInfo() const { return specializationInfo.get(); } @@ -73,7 +74,7 @@ private: const VkShaderStageFlagBits pipelineStage; const std::string entryPointName; - const std::vector<uint32_t> insns; + const sw::SpirvBinary insns; const vk::RenderPass *renderPass; const uint32_t subpassIndex; const vk::SpecializationInfo specializationInfo;
diff --git a/src/Vulkan/VkShaderModule.hpp b/src/Vulkan/VkShaderModule.hpp index 19dc131..2081f07 100644 --- a/src/Vulkan/VkShaderModule.hpp +++ b/src/Vulkan/VkShaderModule.hpp
@@ -16,6 +16,7 @@ #define VK_SHADER_MODULE_HPP_ #include "VkObject.hpp" +#include "Pipeline/SpirvBinary.hpp" #include <atomic> #include <vector> @@ -35,7 +36,7 @@ static size_t ComputeRequiredAllocationSize(const VkShaderModuleCreateInfo *pCreateInfo); // TODO: reconsider boundary of ShaderModule class; try to avoid 'expose the // guts' operations, and this copy. - std::vector<uint32_t> getCode() const { return std::vector<uint32_t>{ code, code + wordCount }; } + sw::SpirvBinary getCode() const { return sw::SpirvBinary(code, wordCount); } uint32_t getSerialID() const { return serialID; } static uint32_t nextSerialID() { return serialCounter++; }