Skip to content

Commit

Permalink
[UIX] Added assembler and source traceback for IL
Browse files Browse the repository at this point in the history
- Added IL representation
- Added IL assembler, used for source traceback
- Added validation object support to IL content view

[DX12, Vulkan]
- IL requests now feed a json serialized form of the program
- Added source traceback from code offsets, provides basic block id and instruction index
- Fixed Vulkan SpvOpVariable type, fetched from wrong map
  • Loading branch information
miguel-petersen committed Aug 21, 2023
1 parent 8b897da commit 8cfe7cc
Show file tree
Hide file tree
Showing 61 changed files with 4,544 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class DXBCModule final : public IDXModule {
GlobalUID GetInstrumentationGUID() override;
bool Compile(const DXCompileJob& job, DXStream& out) override;
IDXDebugModule *GetDebug() override;
DXCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset) override;
const char* GetLanguage() override;

private:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

// Std
#include <Backend/IL/ID.h>

struct DXCodeOffsetTraceback {
/// Originating basic block
IL::ID basicBlockID{IL::InvalidID};

/// Instruction index in basic block
uint32_t instructionIndex{~0u};
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <Backends/DX12/Compiler/DXIL/LLVM/LLVMRecordStringView.h>
#include <Backends/DX12/Compiler/DXIL/Blocks/DXILPhysicalBlockSection.h>
#include <Backends/DX12/Compiler/DXIL/DXILHeader.h>
#include <Backends/DX12/Compiler/DXCodeOffsetTraceback.h>

// Common
#include <Common/Containers/TrivialStackVector.h>
Expand All @@ -43,7 +44,7 @@ struct DXILValueReader;

/// Function block
struct DXILPhysicalBlockFunction : public DXILPhysicalBlockSection {
using DXILPhysicalBlockSection::DXILPhysicalBlockSection;
DXILPhysicalBlockFunction(const Allocators &allocators, Backend::IL::Program &program, DXILPhysicalBlockTable &table);

/// Copy this block
/// \param out destination block
Expand All @@ -67,6 +68,11 @@ struct DXILPhysicalBlockFunction : public DXILPhysicalBlockSection {
/// Get the declaration associated with an index
const DXILFunctionDeclaration* GetFunctionDeclarationFromIndex(uint32_t index);

/// Get a source traceback
/// \param codeOffset given offset, must originate from the same function
/// \return traceback
DXCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset);

public:
/// Compile a function
/// \param block block
Expand Down Expand Up @@ -296,6 +302,10 @@ struct DXILPhysicalBlockFunction : public DXILPhysicalBlockSection {
/// All function blocks
TrivialStackVector<FunctionBlock, 4> functionBlocks;

private:
/// Source traceback lookup
Vector<DXCodeOffsetTraceback> sourceTraceback;

private:
/// Function visitation counters
uint32_t stitchFunctionIndex{0};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class DXILModule final : public IDXModule {
GlobalUID GetInstrumentationGUID() override;
bool Compile(const DXCompileJob& job, DXStream& out) override;
IDXDebugModule *GetDebug() override;
DXCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset) override;
const char* GetLanguage() override;

/// Get the binding info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

// Layer
#include <Backends/DX12/DX12.h>
#include <Backends/DX12/Compiler/DXCodeOffsetTraceback.h>

// Common
#include <Common/GlobalUID.h>
Expand Down Expand Up @@ -69,6 +70,11 @@ class IDXModule {
/// \return debug interface
virtual IDXDebugModule* GetDebug() = 0;

/// Get a source traceback
/// \param codeOffset given offset, must originate from the same module
/// \return traceback
virtual DXCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset) = 0;

/// Get the guid
/// \return
virtual GlobalUID GetInstrumentationGUID() = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ class ShaderSGUIDHost final : public IShaderSGUIDHost {
void Commit(IBridge* bridge);

/// Overrides
ShaderSGUID Bind(const IL::Program &program, const IL::ConstOpaqueInstructionRef& instruction) override;
ShaderSGUID Bind(const IL::Program &program, const IL::BasicBlock::ConstIterator& instruction) override;
ShaderSourceMapping GetMapping(ShaderSGUID sguid) override;
std::string_view GetSource(ShaderSGUID sguid) override;
std::string_view GetSource(const ShaderSourceMapping &mapping) override;

private:
/// Cached entry maps
struct ShaderEntry {
std::unordered_map<ShaderSourceMapping::TSortKey, ShaderSourceMapping> mappings;
std::unordered_map<ShaderSourceMapping, ShaderSourceMapping> mappings;
};

private:
Expand Down
11 changes: 11 additions & 0 deletions Source/Backends/DX12/Layer/Source/Compiler/DXBC/DXBCModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <Backends/DX12/Compiler/DXBC/DXBCUtils.h>
#include <Backends/DX12/Compiler/DXBC/DXBCConverter.h>
#include <Backends/DX12/Layer.h>
#include <Backends/DX12/Compiler/DXIL/DXILModule.h>

// Common
#include <Common/FileSystem.h>
Expand Down Expand Up @@ -161,6 +162,16 @@ IDXDebugModule *DXBCModule::GetDebug() {
return table.debugModule;
}

DXCodeOffsetTraceback DXBCModule::GetCodeOffsetTraceback(uint32_t codeOffset) {
// Check if DXIL
if (table.dxilModule) {
return table.dxilModule->GetCodeOffsetTraceback(codeOffset);
}

// No native DXBC traceback
return {};
}

const char * DXBCModule::GetLanguage() {
// Special case, converted at runtime
if (conversionBlob.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
* https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/Bitcode/Writer/BitcodeWriter.cpp
*/

DXILPhysicalBlockFunction::DXILPhysicalBlockFunction(const Allocators &allocators, Backend::IL::Program &program, DXILPhysicalBlockTable &table):
DXILPhysicalBlockSection(allocators, program, table),
sourceTraceback(allocators) {
/* */
}

void DXILPhysicalBlockFunction::ParseFunction(struct LLVMBlock *block) {
// Definition order is linear to the internally linked functions
uint32_t linkedIndex = internalLinkedFunctions[program.GetFunctionList().GetCount()];
Expand Down Expand Up @@ -117,12 +123,24 @@ void DXILPhysicalBlockFunction::ParseFunction(struct LLVMBlock *block) {
// Reserve forward allocations
table.idMap.ReserveForward(block->records.size());

// Reserve source traceback
sourceTraceback.resize(block->records.size());

// Visit function records
for (uint32_t recordIdx = 0; recordIdx < static_cast<uint32_t>(block->records.size()); recordIdx++) {
LLVMRecord &record = block->records[recordIdx];

// Setup reader
DXILValueReader reader(table, record);

// Provide traceback
if (basicBlock != nullptr) {
sourceTraceback[recordIdx] = DXCodeOffsetTraceback {
.basicBlockID = basicBlock->GetID(),
.instructionIndex = basicBlock->GetCount()
};
}

// Get the current id anchor
// LLVM id references are encoded relative to the current record
uint32_t anchor = table.idMap.GetAnchor();
Expand Down Expand Up @@ -1228,6 +1246,10 @@ const DXILFunctionDeclaration * DXILPhysicalBlockFunction::GetFunctionDeclaratio
return functions[index];
}

DXCodeOffsetTraceback DXILPhysicalBlockFunction::GetCodeOffsetTraceback(uint32_t codeOffset) {
return sourceTraceback.at(codeOffset);
}

bool DXILPhysicalBlockFunction::TryParseIntrinsic(IL::BasicBlock *basicBlock, uint32_t recordIdx, DXILValueReader &reader, uint32_t anchor, uint32_t called, uint32_t result, const DXILFunctionDeclaration *declaration) {
LLVMRecordStringView view = table.symbol.GetValueString(called);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ IDXDebugModule *DXILModule::GetDebug() {
return nullptr;
}

DXCodeOffsetTraceback DXILModule::GetCodeOffsetTraceback(uint32_t codeOffset) {
return table.function.GetCodeOffsetTraceback(codeOffset);
}

const char * DXILModule::GetLanguage() {
return "DXIL";
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ void MetadataController::OnMessage(const GetShaderILMessage& message) {

// Pretty print to stream
std::stringstream ilStream;
IL::PrettyPrint(*shader->module->GetProgram(), ilStream);
IL::PrettyPrintProgramJson(*shader->module->GetProgram(), ilStream);

// Add native file
auto&& file = view.Add<ShaderILMessage>(ShaderILMessage::AllocationInfo { .codeLength = static_cast<size_t>(ilStream.tellp()) });
auto&& file = view.Add<ShaderILMessage>(ShaderILMessage::AllocationInfo { .programLength = static_cast<size_t>(ilStream.tellp()) });
file->shaderUID = message.shaderUID;
file->found = true;
file->code.Set(ilStream.str());
file->program.Set(ilStream.str());
}

void MetadataController::OnMessage(const GetShaderBlockGraphMessage& message) {
Expand Down Expand Up @@ -364,6 +364,8 @@ void MetadataController::OnMessage(const struct GetShaderSourceMappingMessage& m
response->fileUID = mapping.fileUID;
response->line = mapping.line;
response->column = mapping.column;
response->basicBlockId = mapping.basicBlockId;
response->instructionIndex = mapping.instructionIndex;

// Fill contents
response->contents.Set(sourceContents);
Expand Down
45 changes: 27 additions & 18 deletions Source/Backends/DX12/Layer/Source/Symbolizer/ShaderSGUIDHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <Backends/DX12/States/ShaderState.h>
#include <Backends/DX12/Compiler/IDXModule.h>
#include <Backends/DX12/Compiler/IDXDebugModule.h>
#include <Backends/DX12/Compiler/DXCodeOffsetTraceback.h>

// Backend
#include <Backend/IL/Program.h>
Expand Down Expand Up @@ -82,6 +83,8 @@ void ShaderSGUIDHost::Commit(IBridge *bridge) {
message->fileUID = mapping.fileUID;
message->line = mapping.line;
message->column = mapping.column;
message->basicBlockId = mapping.basicBlockId;
message->instructionIndex = mapping.instructionIndex;

// Fill contents
message->contents.Set(sourceContents);
Expand All @@ -94,7 +97,7 @@ void ShaderSGUIDHost::Commit(IBridge *bridge) {
pendingSubmissions.clear();
}

ShaderSGUID ShaderSGUIDHost::Bind(const IL::Program &program, const IL::ConstOpaqueInstructionRef& instruction) {
ShaderSGUID ShaderSGUIDHost::Bind(const IL::Program &program, const IL::BasicBlock::ConstIterator& instruction) {
// Get instruction pointer
const IL::Instruction* ptr = IL::ConstInstructionRef<>(instruction).Get();

Expand All @@ -109,33 +112,39 @@ ShaderSGUID ShaderSGUIDHost::Bind(const IL::Program &program, const IL::ConstOpa
return InvalidShaderSGUID;
}

// Debug modules are optional
IDXDebugModule* debugModule = shaderState->module->GetDebug();
if (!debugModule) {
return InvalidShaderSGUID;
}

// Try to get the association
DXSourceAssociation sourceAssociation = debugModule->GetSourceAssociation(ptr->source.codeOffset);
if (!sourceAssociation) {
return InvalidShaderSGUID;
}
// Get traceback
DXCodeOffsetTraceback traceback = shaderState->module->GetCodeOffsetTraceback(ptr->source.codeOffset);

// Create mapping
// Default mapping
ShaderSourceMapping mapping{};
mapping.fileUID = sourceAssociation.fileUID;
mapping.line = sourceAssociation.line;
mapping.column = sourceAssociation.column;
mapping.shaderGUID = program.GetShaderGUID();

// Mapping il association
mapping.basicBlockId = traceback.basicBlockID;
mapping.instructionIndex = traceback.instructionIndex;

// Debug modules are optional
if (IDXDebugModule* debugModule = shaderState->module->GetDebug()) {
// Try to get the association
DXSourceAssociation sourceAssociation = debugModule->GetSourceAssociation(ptr->source.codeOffset);
if (!sourceAssociation) {
return InvalidShaderSGUID;
}

// Mapping source association
mapping.fileUID = sourceAssociation.fileUID;
mapping.line = sourceAssociation.line;
mapping.column = sourceAssociation.column;
}

// Serial
std::lock_guard guard(mutex);

// Get entry
ShaderEntry& shaderEntry = shaderEntries[mapping.shaderGUID];

// Find mapping
auto ssmIt = shaderEntry.mappings.find(mapping.GetInlineSortKey());
auto ssmIt = shaderEntry.mappings.find(mapping);
if (ssmIt == shaderEntry.mappings.end()) {
// Free indices?
if (!freeIndices.empty()) {
Expand All @@ -157,7 +166,7 @@ ShaderSGUID ShaderSGUIDHost::Bind(const IL::Program &program, const IL::ConstOpa
pendingSubmissions.push_back(mapping.sguid);

// Insert mappings
shaderEntry.mappings[mapping.GetInlineSortKey()] = mapping;
shaderEntry.mappings[mapping] = mapping;
sguidLookup.at(mapping.sguid) = mapping;
return mapping.sguid;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

// Layer
#include <Backends/Vulkan/Compiler/Blocks/SpvPhysicalBlockSection.h>
#include <Backends/Vulkan/Compiler/SpvCodeOffsetTraceback.h>

// Backend
#include <Backend/IL/Source.h>
Expand Down Expand Up @@ -87,6 +88,11 @@ struct SpvPhysicalBlockFunction : public SpvPhysicalBlockSection {
/// \param out destination function
void CopyTo(SpvPhysicalBlockTable& remote, SpvPhysicalBlockFunction& out);

/// Get the code offset traceback
/// \param codeOffset code offset, must originate from same function
/// \return traceback
SpvCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset);

private:
/// Patch all loop continues
/// \param fn function
Expand Down Expand Up @@ -172,6 +178,10 @@ struct SpvPhysicalBlockFunction : public SpvPhysicalBlockSection {
/// All metadata
std::vector<IdentifierMetadata> identifierMetadata;

private:
/// All traceback information
std::unordered_map<uint32_t, SpvCodeOffsetTraceback> sourceTraceback;

private:
struct LoopContinueBlock {
IL::InstructionRef<> instruction;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

// Std
#include <Backend/IL/ID.h>

struct SpvCodeOffsetTraceback {
/// Originating basic block id
IL::ID basicBlockID{IL::InvalidID};

/// Linear instruction index in basic block
uint32_t instructionIndex{~0u};
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <Backends/Vulkan/Compiler/SpvJob.h>
#include <Backends/Vulkan/States/ShaderModuleInstrumentationKey.h>
#include <Backends/Vulkan/Config.h>
#include <Backends/Vulkan/Compiler/SpvCodeOffsetTraceback.h>

// Forward declarations
struct SpvDebugMap;
Expand Down Expand Up @@ -74,6 +75,11 @@ class SpvModule {
/// \return success state
bool Recompile(const uint32_t* code, uint32_t wordCount, const SpvJob& job);

/// Get code offset traceback
/// \param codeOffset code offset, must originate from this module
/// \return traceback
SpvCodeOffsetTraceback GetCodeOffsetTraceback(uint32_t codeOffset);

/// Get the produced program
/// \return
const IL::Program* GetProgram() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ class ShaderSGUIDHost final : public IShaderSGUIDHost {
void Commit(IBridge* bridge);

/// Overrides
ShaderSGUID Bind(const IL::Program &program, const IL::ConstOpaqueInstructionRef& instruction) override;
ShaderSGUID Bind(const IL::Program &program, const IL::BasicBlock::ConstIterator& instruction) override;
ShaderSourceMapping GetMapping(ShaderSGUID sguid) override;
std::string_view GetSource(ShaderSGUID sguid) override;
std::string_view GetSource(const ShaderSourceMapping &mapping) override;

private:
struct ShaderEntry {
std::unordered_map<ShaderSourceMapping::TSortKey, ShaderSourceMapping> mappings;
std::unordered_map<ShaderSourceMapping, ShaderSourceMapping> mappings;
};

/// Get the source map from a guid
Expand Down
Loading

0 comments on commit 8cfe7cc

Please sign in to comment.