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++; }