Shader: Improve SpirvPrinter output

This commit is contained in:
Jérôme Leclercq 2021-03-13 16:09:18 +01:00
parent 593d80c80e
commit a318b28cd6
1 changed files with 133 additions and 108 deletions

View File

@ -4,9 +4,10 @@
#include <Nazara/Shader/SpirvPrinter.hpp> #include <Nazara/Shader/SpirvPrinter.hpp>
#include <Nazara/Core/CallOnExit.hpp> #include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Shader/SpirvData.hpp> #include <Nazara/Shader/SpirvData.hpp>
#include <SpirV/spirv.h>
#include <cassert> #include <cassert>
#include <iomanip>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Shader/Debug.hpp> #include <Nazara/Shader/Debug.hpp>
@ -21,6 +22,7 @@ namespace Nz
} }
const UInt32* codepoints; const UInt32* codepoints;
std::size_t resultOffset;
std::size_t index = 0; std::size_t index = 0;
std::size_t count; std::size_t count;
std::ostringstream stream; std::ostringstream stream;
@ -37,14 +39,14 @@ namespace Nz
CallOnExit resetOnExit([&] { m_currentState = nullptr; }); CallOnExit resetOnExit([&] { m_currentState = nullptr; });
UInt32 magicNumber = ReadWord(); UInt32 magicNumber = ReadWord();
if (magicNumber != SpvMagicNumber) if (magicNumber != SpirvMagicNumber)
throw std::runtime_error("invalid Spir-V: magic number didn't match"); throw std::runtime_error("invalid Spir-V: magic number didn't match");
if (m_currentState->settings.printHeader) if (m_currentState->settings.printHeader)
m_currentState->stream << "Spir-V module\n"; m_currentState->stream << "Spir-V module\n";
UInt32 versionNumber = ReadWord(); UInt32 versionNumber = ReadWord();
if (versionNumber > SpvVersion) if (versionNumber > SpirvVersion)
throw std::runtime_error("Spir-V is more recent than printer, dismissing"); throw std::runtime_error("Spir-V is more recent than printer, dismissing");
UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF; UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF;
@ -54,6 +56,8 @@ namespace Nz
UInt32 bound = ReadWord(); UInt32 bound = ReadWord();
UInt32 schema = ReadWord(); UInt32 schema = ReadWord();
state.resultOffset = std::snprintf(nullptr, 0, "%%%u = ", bound);
if (m_currentState->settings.printHeader) if (m_currentState->settings.printHeader)
{ {
m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n"; m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n";
@ -81,20 +85,33 @@ namespace Nz
if (!inst) if (!inst)
throw std::runtime_error("invalid instruction"); throw std::runtime_error("invalid instruction");
m_currentState->stream << inst->name;
if (m_currentState->settings.printParameters) if (m_currentState->settings.printParameters)
{ {
std::ostringstream instructionStream;
instructionStream << inst->name;
UInt32 resultId = 0;
std::size_t currentOperand = 0; std::size_t currentOperand = 0;
std::size_t instructionEnd = startIndex + wordCount; std::size_t instructionEnd = startIndex + wordCount;
while (m_currentState->index < instructionEnd) while (m_currentState->index < instructionEnd)
{ {
const SpirvInstruction::Operand* operand = &inst->operands[currentOperand]; const SpirvInstruction::Operand* operand = &inst->operands[currentOperand];
m_currentState->stream << " " << operand->name << "("; if (operand->kind != SpirvOperandKind::IdResult)
{
switch (operand->kind) switch (operand->kind)
{ {
case SpirvOperandKind::IdRef:
case SpirvOperandKind::IdResultType:
case SpirvOperandKind::IdMemorySemantics:
case SpirvOperandKind::IdScope:
{
UInt32 value = ReadWord();
instructionStream << " %" << value;
break;
}
case SpirvOperandKind::ImageOperands: case SpirvOperandKind::ImageOperands:
case SpirvOperandKind::FPFastMathMode: case SpirvOperandKind::FPFastMathMode:
case SpirvOperandKind::SelectionControl: case SpirvOperandKind::SelectionControl:
@ -129,25 +146,20 @@ namespace Nz
case SpirvOperandKind::RayQueryIntersection: case SpirvOperandKind::RayQueryIntersection:
case SpirvOperandKind::RayQueryCommittedIntersectionType: case SpirvOperandKind::RayQueryCommittedIntersectionType:
case SpirvOperandKind::RayQueryCandidateIntersectionType: case SpirvOperandKind::RayQueryCandidateIntersectionType:
case SpirvOperandKind::IdResultType:
case SpirvOperandKind::IdResult:
case SpirvOperandKind::IdMemorySemantics:
case SpirvOperandKind::IdScope:
case SpirvOperandKind::IdRef:
case SpirvOperandKind::LiteralInteger: case SpirvOperandKind::LiteralInteger:
case SpirvOperandKind::LiteralExtInstInteger: case SpirvOperandKind::LiteralExtInstInteger:
case SpirvOperandKind::LiteralSpecConstantOpInteger: case SpirvOperandKind::LiteralSpecConstantOpInteger:
case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME
{ {
UInt32 value = ReadWord(); UInt32 value = ReadWord();
m_currentState->stream << value; instructionStream << " " << operand->name << "(" << value << ")";
break; break;
} }
case SpirvOperandKind::LiteralString: case SpirvOperandKind::LiteralString:
{ {
std::string str = ReadString(); std::string str = ReadString();
m_currentState->stream << "\"" << str << "\""; instructionStream << " \"" << str << "\"";
/* /*
std::size_t offset = GetOutputOffset(); std::size_t offset = GetOutputOffset();
@ -200,15 +212,28 @@ namespace Nz
break; break;
} }
}
m_currentState->stream << ")"; else
resultId = ReadWord();
if (currentOperand < inst->minOperandCount - 1) if (currentOperand < inst->minOperandCount - 1)
currentOperand++; currentOperand++;
} }
if (resultId != 0)
{
std::string resultInfo = "%" + std::to_string(resultId) + " = ";
m_currentState->stream << std::setw(m_currentState->resultOffset) << resultInfo;
}
else
m_currentState->stream << std::string(m_currentState->resultOffset, ' ');
m_currentState->stream << instructionStream.str();
} }
else else
{ {
m_currentState->stream << inst->name;
m_currentState->index += wordCount - 1; m_currentState->index += wordCount - 1;
if (m_currentState->index > m_currentState->count) if (m_currentState->index > m_currentState->count)
throw std::runtime_error("unexpected end of stream"); throw std::runtime_error("unexpected end of stream");