Move state variables from Spirv to SpirvShader
This makes Spirv a purely SPIR-V binary parsing class, while SpirvShader
also holds the pipeline state which affects SPIR-V code emission at draw
time (which is provided at pipeline creation time).
Bug: b/247020580
Bug: b/253234336
Change-Id: Iaf3933c15981f64f8f5ffc8da72cd2a3b94879d5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/68971
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 69b9922..8099e31 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -30,31 +30,13 @@
Spirv::Spirv(
VkShaderStageFlagBits pipelineStage,
const char *entryPointName,
- const SpirvBinary &insns,
- const vk::RenderPass *renderPass,
- uint32_t subpassIndex,
- bool robustBufferAccess)
+ const SpirvBinary &insns)
: insns{ insns }
, inputs{ MAX_INTERFACE_COMPONENTS }
, outputs{ MAX_INTERFACE_COMPONENTS }
- , robustBufferAccess(robustBufferAccess)
{
ASSERT(insns.size() > 0);
- if(renderPass)
- {
- // capture formats of any input attachments present
- auto subpass = renderPass->getSubpass(subpassIndex);
- inputAttachmentFormats.reserve(subpass.inputAttachmentCount);
- for(auto i = 0u; i < subpass.inputAttachmentCount; i++)
- {
- auto attachmentIndex = subpass.pInputAttachments[i].attachment;
- inputAttachmentFormats.push_back(attachmentIndex != VK_ATTACHMENT_UNUSED
- ? renderPass->getAttachment(attachmentIndex).format
- : VK_FORMAT_UNDEFINED);
- }
- }
-
// The identifiers of all OpVariables that define the entry point's IO variables.
std::unordered_set<Object::ID> interfaceIds;
@@ -1716,7 +1698,7 @@
object.definition = insn;
}
-OutOfBoundsBehavior Spirv::getOutOfBoundsBehavior(Object::ID pointerId, const vk::PipelineLayout *pipelineLayout) const
+OutOfBoundsBehavior SpirvShader::getOutOfBoundsBehavior(Object::ID pointerId, const vk::PipelineLayout *pipelineLayout) const
{
auto it = descriptorDecorations.find(pointerId);
if(it != descriptorDecorations.end())
@@ -1770,7 +1752,7 @@
// emit-time
-void Spirv::emitProlog(SpirvRoutine *routine) const
+void SpirvShader::emitProlog(SpirvRoutine *routine) const
{
for(auto insn : *this)
{
@@ -1815,7 +1797,7 @@
}
}
-void Spirv::emit(SpirvRoutine *routine, const RValue<SIMD::Int> &activeLaneMask, const RValue<SIMD::Int> &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets, unsigned int multiSampleCount) const
+void SpirvShader::emit(SpirvRoutine *routine, const RValue<SIMD::Int> &activeLaneMask, const RValue<SIMD::Int> &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets, unsigned int multiSampleCount) const
{
SpirvEmitter::emit(*this, routine, entryPoint, activeLaneMask, storesAndAtomicsMask, descriptorSets, multiSampleCount);
}
@@ -1826,15 +1808,29 @@
const vk::RenderPass *renderPass,
uint32_t subpassIndex,
bool robustBufferAccess)
- : Spirv(stage, entryPointName, insns, renderPass, subpassIndex, robustBufferAccess)
+ : Spirv(stage, entryPointName, insns)
+ , robustBufferAccess(robustBufferAccess)
{
+ if(renderPass)
+ {
+ // capture formats of any input attachments present
+ auto subpass = renderPass->getSubpass(subpassIndex);
+ inputAttachmentFormats.reserve(subpass.inputAttachmentCount);
+ for(auto i = 0u; i < subpass.inputAttachmentCount; i++)
+ {
+ auto attachmentIndex = subpass.pInputAttachments[i].attachment;
+ inputAttachmentFormats.push_back(attachmentIndex != VK_ATTACHMENT_UNUSED
+ ? renderPass->getAttachment(attachmentIndex).format
+ : VK_FORMAT_UNDEFINED);
+ }
+ }
}
SpirvShader::~SpirvShader()
{
}
-SpirvEmitter::SpirvEmitter(const Spirv &shader,
+SpirvEmitter::SpirvEmitter(const SpirvShader &shader,
SpirvRoutine *routine,
Spirv::Function::ID entryPoint,
RValue<SIMD::Int> activeLaneMask,
@@ -1851,7 +1847,7 @@
{
}
-void SpirvEmitter::emit(const Spirv &shader,
+void SpirvEmitter::emit(const SpirvShader &shader,
SpirvRoutine *routine,
Spirv::Function::ID entryPoint,
RValue<SIMD::Int> activeLaneMask,
@@ -2722,7 +2718,7 @@
return scopeObj.constantValue[0];
}
-void Spirv::emitEpilog(SpirvRoutine *routine) const
+void SpirvShader::emitEpilog(SpirvRoutine *routine) const
{
for(auto insn : *this)
{
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 7555aba..3cd438a 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -146,15 +146,14 @@
#endif // ENABLE_RR_PRINT
};
+// The Spirv class parses a SPIR-V binary and provides utilities for retrieving
+// information about instructions, objects, types, etc.
class Spirv
{
public:
Spirv(VkShaderStageFlagBits stage,
const char *entryPointName,
- const SpirvBinary &insns,
- const vk::RenderPass *renderPass,
- uint32_t subpassIndex,
- bool robustBufferAccess);
+ const SpirvBinary &insns);
~Spirv();
@@ -753,7 +752,6 @@
};
std::unordered_map<Object::ID, DescriptorDecorations> descriptorDecorations;
- std::vector<vk::Format> inputAttachmentFormats;
struct InterfaceComponent
{
@@ -813,25 +811,15 @@
std::vector<InterfaceComponent> inputs;
std::vector<InterfaceComponent> outputs;
- // TODO(b/247020580): Move to SpirvRoutine
- void emitProlog(SpirvRoutine *routine) const;
- void emit(SpirvRoutine *routine, const RValue<SIMD::Int> &activeLaneMask, const RValue<SIMD::Int> &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets, unsigned int multiSampleCount = 0) const;
- void emitEpilog(SpirvRoutine *routine) const;
-
uint32_t getWorkgroupSizeX() const;
uint32_t getWorkgroupSizeY() const;
uint32_t getWorkgroupSizeZ() const;
- bool getRobustBufferAccess() const { return robustBufferAccess; }
-
using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>;
std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> inputBuiltins;
std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> outputBuiltins;
WorkgroupMemory workgroupMemory;
-private:
- const bool robustBufferAccess;
-
Function::ID entryPoint;
spv::ExecutionModel executionModel = spv::ExecutionModelMax; // Invalid prior to OpEntryPoint parsing.
ExecutionModes executionModes = {};
@@ -940,8 +928,6 @@
return it->second;
}
- OutOfBoundsBehavior getOutOfBoundsBehavior(Object::ID pointerId, const vk::PipelineLayout *pipelineLayout) const;
-
// Returns the *component* offset in the literal for the given access chain.
uint32_t WalkLiteralAccessChain(Type::ID id, const Span &indexes) const;
@@ -979,7 +965,8 @@
static bool IsTerminator(spv::Op opcode);
};
-// TODO(b/247020580): Move state from Spirv to SpirvShader
+// The SpirvShader class holds a parsed SPIR-V shader but also the pipeline
+// state which affects code emission when passing it to SpirvEmitter.
class SpirvShader : public Spirv
{
public:
@@ -991,6 +978,21 @@
bool robustBufferAccess);
~SpirvShader();
+
+ // TODO(b/247020580): Move to SpirvRoutine
+ void emitProlog(SpirvRoutine *routine) const;
+ void emit(SpirvRoutine *routine, const RValue<SIMD::Int> &activeLaneMask, const RValue<SIMD::Int> &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets, unsigned int multiSampleCount = 0) const;
+ void emitEpilog(SpirvRoutine *routine) const;
+
+ bool getRobustBufferAccess() const { return robustBufferAccess; }
+ OutOfBoundsBehavior getOutOfBoundsBehavior(Object::ID pointerId, const vk::PipelineLayout *pipelineLayout) const;
+
+ vk::Format getInputAttachmentFormat(int32_t index) const { return inputAttachmentFormats[index]; }
+
+private:
+ const bool robustBufferAccess;
+
+ std::vector<vk::Format> inputAttachmentFormats;
};
// The SpirvEmitter class translates the parsed SPIR-V shader into Reactor code.
@@ -1004,7 +1006,7 @@
using Span = Spirv::Span;
public:
- static void emit(const Spirv &shader,
+ static void emit(const SpirvShader &shader,
SpirvRoutine *routine,
Spirv::Function::ID entryPoint,
RValue<SIMD::Int> activeLaneMask,
@@ -1019,7 +1021,7 @@
};
private:
- SpirvEmitter(const Spirv &shader,
+ SpirvEmitter(const SpirvShader &shader,
SpirvRoutine *routine,
Spirv::Function::ID entryPoint,
RValue<SIMD::Int> activeLaneMask,
@@ -1519,7 +1521,7 @@
static sw::MipmapType convertMipmapMode(const vk::SamplerState *samplerState);
static sw::AddressingMode convertAddressingMode(int coordinateIndex, const vk::SamplerState *samplerState, VkImageViewType imageViewType);
- const Spirv &shader;
+ const SpirvShader &shader;
SpirvRoutine *const routine; // The current routine being built.
Spirv::Function::ID function; // The current function being built.
Block::ID block; // The current block being built.
diff --git a/src/Pipeline/SpirvShaderImage.cpp b/src/Pipeline/SpirvShaderImage.cpp
index ef2d30e..a4b5570 100644
--- a/src/Pipeline/SpirvShaderImage.cpp
+++ b/src/Pipeline/SpirvShaderImage.cpp
@@ -835,7 +835,7 @@
// For subpass data, format in the instruction is spv::ImageFormatUnknown. Get it from
// the renderpass data instead. In all other cases, we can use the format in the instruction.
vk::Format imageFormat = (dim == spv::DimSubpassData)
- ? shader.inputAttachmentFormats[d.InputAttachmentIndex]
+ ? shader.getInputAttachmentFormat(d.InputAttachmentIndex)
: SpirvFormatToVulkanFormat(static_cast<spv::ImageFormat>(instruction.imageFormat));
// Depth+Stencil image attachments select aspect based on the Sampled Type of the