mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
add beginnings of a class to organise SPIR-V editing capabilities
This commit is contained in:
@@ -91,6 +91,8 @@ endif()
|
||||
set(sources
|
||||
spirv_common.cpp
|
||||
spirv_common.h
|
||||
spirv_editor.h
|
||||
spirv_editor.cpp
|
||||
spirv_compile.cpp
|
||||
spirv_disassemble.cpp
|
||||
spirv_stringise.cpp
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||
<ForcedIncludeFiles>precompiled.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<ClCompile Include="spirv_editor.cpp" />
|
||||
<ClCompile Include="spirv_stringise.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -218,6 +219,7 @@
|
||||
<ClInclude Include="..\..\..\3rdparty\glslang\SPIRV\spvIR.h" />
|
||||
<ClInclude Include="precompiled.h" />
|
||||
<ClInclude Include="spirv_common.h" />
|
||||
<ClInclude Include="spirv_editor.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
<Filter>PCH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="spirv_stringise.cpp" />
|
||||
<ClCompile Include="spirv_editor.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\3rdparty\glslang\OGLCompilersDLL\InitializeDll.h">
|
||||
@@ -301,5 +302,6 @@
|
||||
<ClInclude Include="precompiled.h">
|
||||
<Filter>PCH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="spirv_editor.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "spirv_editor.h"
|
||||
#include "common/common.h"
|
||||
|
||||
SPIRVEditor::SPIRVEditor(std::vector<uint32_t> &spirvWords) : spirv(spirvWords)
|
||||
{
|
||||
if(spirvWords.size() < 5 || spirvWords[0] != spv::MagicNumber)
|
||||
{
|
||||
RDCERR("Empty or invalid SPIR-V module");
|
||||
return;
|
||||
}
|
||||
|
||||
moduleVersion.major = uint8_t((spirvWords[1] & 0x00ff0000) >> 16);
|
||||
moduleVersion.minor = uint8_t((spirvWords[1] & 0x0000ff00) >> 8);
|
||||
generator = spirvWords[2];
|
||||
idBound = SPIRVIterator(spirvWords, 3);
|
||||
|
||||
// [4] is reserved
|
||||
RDCASSERT(spirv[4] == 0);
|
||||
|
||||
SPIRVIterator it(spirvWords, 5);
|
||||
|
||||
while(it)
|
||||
{
|
||||
spv::Op opcode = it.opcode();
|
||||
|
||||
if(opcode == spv::OpEntryPoint)
|
||||
{
|
||||
SPIRVEntry entry;
|
||||
entry.iter = it;
|
||||
entry.id = it.word(2);
|
||||
entry.name = (const char *)&it.word(3);
|
||||
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SPIRVEditor::MakeId()
|
||||
{
|
||||
if(!idBound)
|
||||
return 0;
|
||||
|
||||
uint32_t ret = *idBound;
|
||||
(*idBound)++;
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "3rdparty/glslang/SPIRV/spirv.hpp"
|
||||
|
||||
class SPIRVOperation;
|
||||
|
||||
class SPIRVIterator
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
SPIRVIterator() = default;
|
||||
SPIRVIterator(std::vector<uint32_t> &w, size_t o) : words(&w), offset(o) {}
|
||||
// increment to the next op
|
||||
SPIRVIterator &operator++(int) { return operator++(); }
|
||||
SPIRVIterator &operator++()
|
||||
{
|
||||
offset += cur() >> spv::WordCountShift;
|
||||
return *this;
|
||||
}
|
||||
// utility functions
|
||||
std::vector<uint32_t>::iterator it() { return words->begin() + offset; }
|
||||
operator bool() const { return words != NULL && offset < words->size(); }
|
||||
uint32_t &operator*() { return cur(); }
|
||||
const uint32_t &operator*() const { return cur(); }
|
||||
spv::Op opcode() { return spv::Op(cur() & spv::OpCodeMask); }
|
||||
uint32_t &word(size_t idx) { return words->at(offset + idx); }
|
||||
const uint32_t &word(size_t idx) const { return words->at(offset + idx); }
|
||||
size_t size() const { return cur() >> spv::WordCountShift; }
|
||||
private:
|
||||
inline uint32_t &cur() { return words->at(offset); }
|
||||
inline const uint32_t &cur() const { return words->at(offset); }
|
||||
// we make this a friend so it can poke directly into words when it wants to edit
|
||||
friend class SPIRVOperation;
|
||||
|
||||
std::vector<uint32_t> *words = NULL;
|
||||
size_t offset = 0;
|
||||
};
|
||||
|
||||
class SPIRVOperation
|
||||
{
|
||||
public:
|
||||
// constructor of a synthetic operation, from an operation & subsequent words, calculates the
|
||||
// length then constructs the first word with opcode + length.
|
||||
template <typename WordContainer>
|
||||
SPIRVOperation(spv::Op op, const WordContainer &data)
|
||||
{
|
||||
auto a = std::begin(data);
|
||||
auto b = std::end(data);
|
||||
size_t count = 1 + (b - a);
|
||||
words.resize(data.size());
|
||||
words[0] = MakeHeader(op, data.size());
|
||||
words.insert(words.begin() + 1, a, b);
|
||||
|
||||
iter = SPIRVIterator(words, 0);
|
||||
}
|
||||
|
||||
// constructor that takes existing words from elsewhere and just references it.
|
||||
// Since this is iterator based, normal iteration invalidation rules apply, if you modify earlier
|
||||
// in the SPIR-V this operation will become invalid.
|
||||
SPIRVOperation(SPIRVIterator it) : iter(it) {}
|
||||
uint32_t &operator[](size_t idx) { return iter.word(idx); }
|
||||
const uint32_t &operator[](size_t idx) const { return iter.word(idx); }
|
||||
size_t size() const { return iter.size(); }
|
||||
void push_back(uint32_t word)
|
||||
{
|
||||
spv::Op op = iter.opcode();
|
||||
size_t count = iter.size();
|
||||
iter.words->insert(iter.it() + count, word);
|
||||
|
||||
// since the length is in the high-order bits, we have to extract/increment/insert instead of
|
||||
// just incrementing. Boo!
|
||||
*iter = MakeHeader(op, count + 1);
|
||||
}
|
||||
|
||||
private:
|
||||
inline uint32_t MakeHeader(spv::Op op, size_t WordCount)
|
||||
{
|
||||
return (uint32_t(op) & spv::OpCodeMask) | (uint16_t(WordCount) << spv::WordCountShift);
|
||||
}
|
||||
|
||||
// everything is based around this iterator, which may point into our local storage or to external
|
||||
// storage.
|
||||
SPIRVIterator iter;
|
||||
|
||||
// may not be used, if we refer to an external iterator
|
||||
std::vector<uint32_t> words;
|
||||
};
|
||||
|
||||
struct SPIRVEntry
|
||||
{
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
SPIRVIterator iter;
|
||||
};
|
||||
|
||||
class SPIRVEditor
|
||||
{
|
||||
public:
|
||||
SPIRVEditor(std::vector<uint32_t> &spirvWords);
|
||||
|
||||
std::vector<uint32_t> &GetWords() { return spirv; }
|
||||
uint32_t MakeId();
|
||||
void AddDecoration(const SPIRVOperation &op);
|
||||
void AddType(const SPIRVOperation &op);
|
||||
void AddVariable(const SPIRVOperation &op);
|
||||
void AddFunction(const SPIRVOperation *ops, size_t count);
|
||||
|
||||
// simple properties that are public.
|
||||
struct
|
||||
{
|
||||
uint8_t major = 1, minor = 0;
|
||||
} moduleVersion;
|
||||
uint32_t generator = 0;
|
||||
|
||||
spv::SourceLanguage sourceLang = spv::SourceLanguageUnknown;
|
||||
uint32_t sourceVer = 0;
|
||||
|
||||
const std::vector<SPIRVEntry> &GetEntries() { return entries; }
|
||||
private:
|
||||
SPIRVIterator idBound;
|
||||
|
||||
struct
|
||||
{
|
||||
SPIRVIterator decoration;
|
||||
SPIRVIterator typeVar;
|
||||
SPIRVIterator function;
|
||||
} globaliters;
|
||||
|
||||
std::vector<SPIRVEntry> entries;
|
||||
|
||||
std::vector<uint32_t> &spirv;
|
||||
};
|
||||
Reference in New Issue
Block a user