Start building up code generation
- Introduce (perhaps poorly named) SpirvRoutine type for
routine-emit-time state (reactor objects).
- Add SpirvShader::emitEarly (intended for definitions that are needed
in shader preamble) and SpirvShader::emit (intended for general actual
code generation) passes.
- Wire up new passes to VertexProgram/VertexRoutine
Change-Id: Iac42eae7dc04adfd4163fd74ba407b613551d14e
Bug: b/120799499
Reviewed-on: https://swiftshader-review.googlesource.com/c/24375
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index ae76ff8..36227b9 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -517,4 +517,47 @@
assert(getType(insn.word(1)).definition.opcode() == spv::OpTypeInt);
return insn.word(3);
}
+
+ // emit-time
+
+ void SpirvShader::emitEarly(SpirvRoutine *routine) const
+ {
+ for (auto insn : *this)
+ {
+ switch (insn.opcode())
+ {
+ case spv::OpVariable:
+ {
+ auto &object = getObject(insn.word(2));
+ // Want to exclude: location-oriented interface variables; special things that consume zero slots.
+ // TODO: what to do about zero-slot objects?
+ if (object.kind != Object::Kind::InterfaceVariable && object.sizeInComponents > 0)
+ {
+ // any variable not in a location-oriented interface
+ routine->lvalues.emplace(insn.word(2), std::unique_ptr<Array<Float4>>(
+ new Array<Float4>(object.sizeInComponents)));
+ }
+ break;
+ }
+ default:
+ printf("emitEarly: ignoring opcode %d\n", insn.opcode());
+ break;
+ }
+ }
+ }
+
+ void SpirvShader::emit(SpirvRoutine *routine) const
+ {
+ (void) routine;
+
+ for (auto insn : *this)
+ {
+ switch (insn.opcode())
+ {
+ default:
+ printf("emit: ignoring opcode %d\n", insn.opcode());
+ break;
+ }
+ }
+ }
}
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 52e9143..e6bc13c 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -17,16 +17,24 @@
#include "System/Types.hpp"
#include "Vulkan/VkDebug.hpp"
+#include "ShaderCore.hpp"
#include <string>
#include <vector>
#include <unordered_map>
#include <cstdint>
#include <type_traits>
+#include <memory>
#include <spirv/unified1/spirv.hpp>
namespace sw
{
+ class SpirvRoutine
+ {
+ public:
+ std::unordered_map<uint32_t, std::unique_ptr<Array<Float4>>> lvalues;
+ };
+
class SpirvShader
{
public:
@@ -212,12 +220,9 @@
std::vector<InterfaceComponent> inputs;
std::vector<InterfaceComponent> outputs;
- private:
- const int serialID;
- static volatile int serialCounter;
- Modes modes;
- std::unordered_map<uint32_t, Object> types;
- std::unordered_map<uint32_t, Object> defs;
+ void emitEarly(SpirvRoutine *routine) const;
+
+ void emit(SpirvRoutine *routine) const;
using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>;
std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> inputBuiltins;
@@ -230,12 +235,20 @@
return it->second;
}
- Object const &getObject(uint32_t id) const {
+ Object const &getObject(uint32_t id) const
+ {
auto it = defs.find(id);
assert(it != defs.end());
return it->second;
}
+ private:
+ const int serialID;
+ static volatile int serialCounter;
+ Modes modes;
+ std::unordered_map<uint32_t, Object> types;
+ std::unordered_map<uint32_t, Object> defs;
+
void ProcessExecutionMode(InsnIterator it);
uint32_t ComputeTypeSize(InsnIterator insn);
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index fc75f13..1e0e162 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -64,7 +64,7 @@
// }
//}
- // Actually emit code here
+ spirvShader->emit(&routine);
if(currentLabel != -1)
{
diff --git a/src/Pipeline/VertexRoutine.cpp b/src/Pipeline/VertexRoutine.cpp
index 7d76dbe..636351f 100644
--- a/src/Pipeline/VertexRoutine.cpp
+++ b/src/Pipeline/VertexRoutine.cpp
@@ -19,6 +19,7 @@
#include "Device/Renderer.hpp"
#include "System/Half.hpp"
#include "Vulkan/VkDebug.hpp"
+#include "SpirvShader.hpp"
namespace sw
{
@@ -28,6 +29,7 @@
state(state),
spirvShader(spirvShader)
{
+ spirvShader->emitEarly(&routine);
}
VertexRoutine::~VertexRoutine()
diff --git a/src/Pipeline/VertexRoutine.hpp b/src/Pipeline/VertexRoutine.hpp
index cb2b0fd..7b73b76 100644
--- a/src/Pipeline/VertexRoutine.hpp
+++ b/src/Pipeline/VertexRoutine.hpp
@@ -50,6 +50,7 @@
RegisterArray<MAX_VERTEX_INPUTS> v; // Input registers
RegisterArray<MAX_VERTEX_OUTPUTS> o; // Output registers
+ SpirvRoutine routine;
const VertexProcessor::State &state;
SpirvShader const * const spirvShader;