diff --git a/src/Nazara/Shader/SpirvPrinter.cpp b/src/Nazara/Shader/SpirvPrinter.cpp index 180a54d68..01eb65cb0 100644 --- a/src/Nazara/Shader/SpirvPrinter.cpp +++ b/src/Nazara/Shader/SpirvPrinter.cpp @@ -4,9 +4,10 @@ #include #include +#include #include -#include #include +#include #include #include #include @@ -21,6 +22,7 @@ namespace Nz } const UInt32* codepoints; + std::size_t resultOffset; std::size_t index = 0; std::size_t count; std::ostringstream stream; @@ -37,14 +39,14 @@ namespace Nz CallOnExit resetOnExit([&] { m_currentState = nullptr; }); UInt32 magicNumber = ReadWord(); - if (magicNumber != SpvMagicNumber) + if (magicNumber != SpirvMagicNumber) throw std::runtime_error("invalid Spir-V: magic number didn't match"); if (m_currentState->settings.printHeader) m_currentState->stream << "Spir-V module\n"; UInt32 versionNumber = ReadWord(); - if (versionNumber > SpvVersion) + if (versionNumber > SpirvVersion) throw std::runtime_error("Spir-V is more recent than printer, dismissing"); UInt8 majorVersion = ((versionNumber) >> 16) & 0xFF; @@ -54,6 +56,8 @@ namespace Nz UInt32 bound = ReadWord(); UInt32 schema = ReadWord(); + state.resultOffset = std::snprintf(nullptr, 0, "%%%u = ", bound); + if (m_currentState->settings.printHeader) { m_currentState->stream << "Version " + std::to_string(+majorVersion) << "." << std::to_string(+minorVersion) << "\n"; @@ -81,134 +85,155 @@ namespace Nz if (!inst) throw std::runtime_error("invalid instruction"); - m_currentState->stream << inst->name; - if (m_currentState->settings.printParameters) { + std::ostringstream instructionStream; + instructionStream << inst->name; + + UInt32 resultId = 0; + std::size_t currentOperand = 0; std::size_t instructionEnd = startIndex + wordCount; while (m_currentState->index < instructionEnd) { const SpirvInstruction::Operand* operand = &inst->operands[currentOperand]; - m_currentState->stream << " " << operand->name << "("; - - switch (operand->kind) + if (operand->kind != SpirvOperandKind::IdResult) { - case SpirvOperandKind::ImageOperands: - case SpirvOperandKind::FPFastMathMode: - case SpirvOperandKind::SelectionControl: - case SpirvOperandKind::LoopControl: - case SpirvOperandKind::FunctionControl: - 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 + switch (operand->kind) { - UInt32 value = ReadWord(); - m_currentState->stream << value; - break; - } - - case SpirvOperandKind::LiteralString: - { - std::string str = ReadString(); - m_currentState->stream << "\"" << str << "\""; - - /* - std::size_t offset = GetOutputOffset(); - - std::size_t size4 = CountWord(str); - for (std::size_t i = 0; i < size4; ++i) + case SpirvOperandKind::IdRef: + case SpirvOperandKind::IdResultType: + case SpirvOperandKind::IdMemorySemantics: + case SpirvOperandKind::IdScope: { - 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); + UInt32 value = ReadWord(); + instructionStream << " %" << value; + break; + } + + case SpirvOperandKind::ImageOperands: + case SpirvOperandKind::FPFastMathMode: + case SpirvOperandKind::SelectionControl: + case SpirvOperandKind::LoopControl: + case SpirvOperandKind::FunctionControl: + 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::LiteralInteger: + case SpirvOperandKind::LiteralExtInstInteger: + case SpirvOperandKind::LiteralSpecConstantOpInteger: + case SpirvOperandKind::LiteralContextDependentNumber: //< FIXME + { + UInt32 value = ReadWord(); + instructionStream << " " << operand->name << "(" << value << ")"; + break; + } + + case SpirvOperandKind::LiteralString: + { + std::string str = ReadString(); + instructionStream << " \"" << 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: - { - ReadWord(); - ReadWord(); - break; + case SpirvOperandKind::PairLiteralIntegerIdRef: + { + ReadWord(); + ReadWord(); + 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: - { - ReadWord(); - ReadWord(); - break; - } - - case SpirvOperandKind::PairIdRefIdRef: - { - ReadWord(); - ReadWord(); - break; - } - - /*case SpirvOperandKind::LiteralContextDependentNumber: - { - throw std::runtime_error("not yet implemented"); - }*/ - - default: - break; - } - - m_currentState->stream << ")"; + else + resultId = ReadWord(); if (currentOperand < inst->minOperandCount - 1) 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 { + m_currentState->stream << inst->name; + m_currentState->index += wordCount - 1; if (m_currentState->index > m_currentState->count) throw std::runtime_error("unexpected end of stream");