Shader/SpirvPrinter: Add settings

This commit is contained in:
Jérôme Leclercq 2020-08-24 16:49:14 +02:00
parent 77b66620c9
commit ba777ebbca
2 changed files with 146 additions and 123 deletions

View File

@ -16,16 +16,24 @@ namespace Nz
class NAZARA_SHADER_API SpirvPrinter class NAZARA_SHADER_API SpirvPrinter
{ {
public: public:
struct Settings;
inline SpirvPrinter(); inline SpirvPrinter();
SpirvPrinter(const SpirvPrinter&) = default; SpirvPrinter(const SpirvPrinter&) = default;
SpirvPrinter(SpirvPrinter&&) = default; SpirvPrinter(SpirvPrinter&&) = default;
~SpirvPrinter() = default; ~SpirvPrinter() = default;
std::string Print(const UInt32* codepoints, std::size_t count); std::string Print(const UInt32* codepoints, std::size_t count, const Settings& settings = Settings());
SpirvPrinter& operator=(const SpirvPrinter&) = default; SpirvPrinter& operator=(const SpirvPrinter&) = default;
SpirvPrinter& operator=(SpirvPrinter&&) = default; SpirvPrinter& operator=(SpirvPrinter&&) = default;
struct Settings
{
bool printHeader = true;
bool printParameters = true;
};
private: private:
void AppendInstruction(); void AppendInstruction();
std::string ReadString(); std::string ReadString();

View File

@ -19,13 +19,18 @@ namespace Nz
std::size_t index = 0; std::size_t index = 0;
std::size_t count; std::size_t count;
std::ostringstream stream; std::ostringstream stream;
const Settings& settings;
}; };
std::string SpirvPrinter::Print(const UInt32* codepoints, std::size_t count) std::string SpirvPrinter::Print(const UInt32* codepoints, std::size_t count, const Settings& settings)
{ {
State state; State state = {
state.codepoints = codepoints; codepoints,
state.count = count; 0,
count,
{},
settings
};
m_currentState = &state; m_currentState = &state;
CallOnExit resetOnExit([&] { m_currentState = nullptr; }); CallOnExit resetOnExit([&] { m_currentState = nullptr; });
@ -34,7 +39,8 @@ namespace Nz
if (magicNumber != SpvMagicNumber) if (magicNumber != SpvMagicNumber)
throw std::runtime_error("invalid Spir-V: magic number didn't match"); throw std::runtime_error("invalid Spir-V: magic number didn't match");
m_currentState->stream << "Spir-V module\n"; if (m_currentState->settings.printHeader)
m_currentState->stream << "Spir-V module\n";
UInt32 versionNumber = ReadWord(); UInt32 versionNumber = ReadWord();
if (versionNumber > SpvVersion) if (versionNumber > SpvVersion)
@ -43,17 +49,17 @@ namespace Nz
UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF; UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF;
UInt8 minorVersion = ((versionNumber) >> 8) & 0xFF; UInt8 minorVersion = ((versionNumber) >> 8) & 0xFF;
m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n";
UInt32 generatorId = ReadWord(); UInt32 generatorId = ReadWord();
m_currentState->stream << "Generator: " << std::to_string(generatorId) << "\n";
UInt32 bound = ReadWord(); UInt32 bound = ReadWord();
m_currentState->stream << "Bound: " << std::to_string(bound) << "\n";
UInt32 schema = ReadWord(); UInt32 schema = ReadWord();
m_currentState->stream << "Schema: " << std::to_string(schema) << "\n";
if (m_currentState->settings.printHeader)
{
m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n";
m_currentState->stream << "Generator: " << std::to_string(generatorId) << "\n";
m_currentState->stream << "Bound: " << std::to_string(bound) << "\n";
m_currentState->stream << "Schema: " << std::to_string(schema) << "\n";
}
while (m_currentState->index < m_currentState->count) while (m_currentState->index < m_currentState->count)
AppendInstruction(); AppendInstruction();
@ -76,126 +82,135 @@ namespace Nz
m_currentState->stream << inst->name; m_currentState->stream << inst->name;
std::size_t currentOperand = 0; if (m_currentState->settings.printParameters)
std::size_t instructionEnd = startIndex + wordCount;
while (m_currentState->index < instructionEnd)
{ {
const SpirvInstruction::Operand* operand = &inst->operands[currentOperand]; std::size_t currentOperand = 0;
std::size_t instructionEnd = startIndex + wordCount;
m_currentState->stream << " " << operand->name << "("; while (m_currentState->index < instructionEnd)
switch (operand->kind)
{ {
case SpirvOperandKind::ImageOperands: const SpirvInstruction::Operand* operand = &inst->operands[currentOperand];
case SpirvOperandKind::FPFastMathMode:
case SpirvOperandKind::SelectionControl: m_currentState->stream << " " << operand->name << "(";
case SpirvOperandKind::LoopControl:
case SpirvOperandKind::FunctionControl: switch (operand->kind)
case SpirvOperandKind::MemorySemantics:
case SpirvOperandKind::MemoryAccess:
case SpirvOperandKind::KernelProfilingInfo:
case SpirvOperandKind::RayFlags:
case SpirvOperandKind::SourceLanguage:
case SpirvOperandKind::ExecutionModel:
case SpirvOperandKind::AddressingModel:
case SpirvOperandKind::MemoryModel:
case SpirvOperandKind::ExecutionMode:
case SpirvOperandKind::StorageClass:
case SpirvOperandKind::Dim:
case SpirvOperandKind::SamplerAddressingMode:
case SpirvOperandKind::SamplerFilterMode:
case SpirvOperandKind::ImageFormat:
case SpirvOperandKind::ImageChannelOrder:
case SpirvOperandKind::ImageChannelDataType:
case SpirvOperandKind::FPRoundingMode:
case SpirvOperandKind::LinkageType:
case SpirvOperandKind::AccessQualifier:
case SpirvOperandKind::FunctionParameterAttribute:
case SpirvOperandKind::Decoration:
case SpirvOperandKind::BuiltIn:
case SpirvOperandKind::Scope:
case SpirvOperandKind::GroupOperation:
case SpirvOperandKind::KernelEnqueueFlags:
case SpirvOperandKind::Capability:
case SpirvOperandKind::RayQueryIntersection:
case SpirvOperandKind::RayQueryCommittedIntersectionType:
case SpirvOperandKind::RayQueryCandidateIntersectionType:
case SpirvOperandKind::IdResultType:
case SpirvOperandKind::IdResult:
case SpirvOperandKind::IdMemorySemantics:
case SpirvOperandKind::IdScope:
case SpirvOperandKind::IdRef:
case SpirvOperandKind::LiteralInteger:
case SpirvOperandKind::LiteralExtInstInteger:
case SpirvOperandKind::LiteralSpecConstantOpInteger:
case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME
{ {
UInt32 value = ReadWord(); case SpirvOperandKind::ImageOperands:
m_currentState->stream << value; case SpirvOperandKind::FPFastMathMode:
break; case SpirvOperandKind::SelectionControl:
} case SpirvOperandKind::LoopControl:
case SpirvOperandKind::FunctionControl:
case SpirvOperandKind::LiteralString: case SpirvOperandKind::MemorySemantics:
{ case SpirvOperandKind::MemoryAccess:
std::string str = ReadString(); case SpirvOperandKind::KernelProfilingInfo:
m_currentState->stream << "\"" << str << "\""; case SpirvOperandKind::RayFlags:
case SpirvOperandKind::SourceLanguage:
/* case SpirvOperandKind::ExecutionModel:
std::size_t offset = GetOutputOffset(); case SpirvOperandKind::AddressingModel:
case SpirvOperandKind::MemoryModel:
std::size_t size4 = CountWord(str); case SpirvOperandKind::ExecutionMode:
for (std::size_t i = 0; i < size4; ++i) case SpirvOperandKind::StorageClass:
case SpirvOperandKind::Dim:
case SpirvOperandKind::SamplerAddressingMode:
case SpirvOperandKind::SamplerFilterMode:
case SpirvOperandKind::ImageFormat:
case SpirvOperandKind::ImageChannelOrder:
case SpirvOperandKind::ImageChannelDataType:
case SpirvOperandKind::FPRoundingMode:
case SpirvOperandKind::LinkageType:
case SpirvOperandKind::AccessQualifier:
case SpirvOperandKind::FunctionParameterAttribute:
case SpirvOperandKind::Decoration:
case SpirvOperandKind::BuiltIn:
case SpirvOperandKind::Scope:
case SpirvOperandKind::GroupOperation:
case SpirvOperandKind::KernelEnqueueFlags:
case SpirvOperandKind::Capability:
case SpirvOperandKind::RayQueryIntersection:
case SpirvOperandKind::RayQueryCommittedIntersectionType:
case SpirvOperandKind::RayQueryCandidateIntersectionType:
case SpirvOperandKind::IdResultType:
case SpirvOperandKind::IdResult:
case SpirvOperandKind::IdMemorySemantics:
case SpirvOperandKind::IdScope:
case SpirvOperandKind::IdRef:
case SpirvOperandKind::LiteralInteger:
case SpirvOperandKind::LiteralExtInstInteger:
case SpirvOperandKind::LiteralSpecConstantOpInteger:
case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME
{ {
UInt32 codepoint = 0; UInt32 value = ReadWord();
for (std::size_t j = 0; j < 4; ++j) m_currentState->stream << value;
{ break;
std::size_t pos = i * 4 + j; }
if (pos < str.size())
codepoint |= UInt32(str[pos]) << (j * 8); case SpirvOperandKind::LiteralString:
} {
std::string str = ReadString();
Append(codepoint); m_currentState->stream << "\"" << str << "\"";
/*
std::size_t offset = GetOutputOffset();
std::size_t size4 = CountWord(str);
for (std::size_t i = 0; i < size4; ++i)
{
UInt32 codepoint = 0;
for (std::size_t j = 0; j < 4; ++j)
{
std::size_t pos = i * 4 + j;
if (pos < str.size())
codepoint |= UInt32(str[pos]) << (j * 8);
}
Append(codepoint);
}
*/
break;
} }
*/
break;
}
case SpirvOperandKind::PairLiteralIntegerIdRef: case SpirvOperandKind::PairLiteralIntegerIdRef:
{ {
ReadWord(); ReadWord();
ReadWord(); ReadWord();
break; break;
}
case SpirvOperandKind::PairIdRefLiteralInteger:
{
ReadWord();
ReadWord();
break;
}
case SpirvOperandKind::PairIdRefIdRef:
{
ReadWord();
ReadWord();
break;
}
/*case SpirvOperandKind::LiteralContextDependentNumber:
{
throw std::runtime_error("not yet implemented");
}*/
default:
break;
} }
case SpirvOperandKind::PairIdRefLiteralInteger: m_currentState->stream << ")";
{
ReadWord();
ReadWord();
break;
}
case SpirvOperandKind::PairIdRefIdRef:
{
ReadWord();
ReadWord();
break;
}
/*case SpirvOperandKind::LiteralContextDependentNumber:
{
throw std::runtime_error("not yet implemented");
}*/
default:
break;
if (currentOperand < inst->minOperandCount - 1)
currentOperand++;
} }
}
m_currentState->stream << ")"; else
{
if (currentOperand < inst->minOperandCount - 1) m_currentState->index += wordCount - 1;
currentOperand++; if (m_currentState->index > m_currentState->count)
throw std::runtime_error("unexpected end of stream");
} }
m_currentState->stream << "\n"; m_currentState->stream << "\n";