Make sure that function constant members are fixup'd when patching

* We also add some extra debug asserts after the fixup path to ensure that all
  pointers are in the correct array (if we miss passing the old/new function for
  a value fixup like this, it could point to the old function and be silently
  ignored since that's conditional).
* A unit test harness is added too for convenience of iterating on a single
  shader's annotation.
This commit is contained in:
baldurk
2021-11-01 13:53:28 +00:00
parent 72af2abd7d
commit 20b1257411
2 changed files with 77 additions and 1 deletions
@@ -1235,3 +1235,55 @@ void D3D12Replay::ClearFeedbackCache()
{
m_BindlessFeedback.Usage.clear();
}
#if ENABLED(ENABLE_UNIT_TESTS) && 0
#include "catch/catch.hpp"
TEST_CASE("DO NOT COMMIT - convenience test", "[dxbc]")
{
// this test loads a file from disk and does a no-op edit pass on it then an annotation pass on
// it. Useful for when you are iterating on a shader and don't want to have to load a whole
// capture.
bytebuf buf;
FileIO::ReadAll("/path/to/container_file.dxbc", buf);
bytebuf editedBlob;
{
DXBC::DXBCContainer dxbc(buf, rdcstr(), GraphicsAPI::D3D12, ~0U, ~0U);
DXIL::ProgramEditor editor(&dxbc, 1234, editedBlob);
}
{
DXBC::DXBCContainer container(editedBlob, rdcstr(), GraphicsAPI::D3D12, ~0U, ~0U);
rdcstr disasm = container.GetDisassembly();
RDCLOG("no edits - %s", disasm.c_str());
}
{
WrappedID3D12Device device(NULL, D3D12InitParams(), false);
D3D12_SHADER_BYTECODE desc;
desc.BytecodeLength = buf.size();
desc.pShaderBytecode = buf.data();
WrappedID3D12PipelineState::ShaderEntry shad(desc, &device);
std::map<D3D12FeedbackKey, D3D12FeedbackSlot> slots;
uint32_t numSlots = 4;
AddArraySlots(&shad, 123456, 1000000, slots, numSlots, editedBlob, desc);
}
{
DXBC::DXBCContainer container(editedBlob, rdcstr(), GraphicsAPI::D3D12, ~0U, ~0U);
rdcstr disasm = container.GetDisassembly();
RDCLOG("annotated - %s", disasm.c_str());
}
}
#endif
@@ -215,6 +215,10 @@ void ProgramEditor::Fixup(Function *&f)
}
}
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(m_Functions, f));
#endif
}
void ProgramEditor::Fixup(Type *&t)
@@ -229,6 +233,10 @@ void ProgramEditor::Fixup(Type *&t)
if(result)
t = result;
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(m_Types, t));
#endif
}
void ProgramEditor::Fixup(Block *&b, Function *oldf, Function *newf)
@@ -240,6 +248,10 @@ void ProgramEditor::Fixup(Block *&b, Function *oldf, Function *newf)
if(result)
b = result;
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(newf->blocks, b));
#endif
}
// this variant fixes up the pointer itself only, but doesn't recurse. We don't recurse because we
@@ -264,6 +276,10 @@ void ProgramEditor::Fixup(Instruction *&i, Function *oldf, Function *newf)
if(result)
i = result;
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(newf->args, i) || IN_ARRAY(newf->instructions, i));
#endif
}
void ProgramEditor::Fixup(Constant *&c, Function *oldf, Function *newf)
@@ -286,6 +302,10 @@ void ProgramEditor::Fixup(Constant *&c, Function *oldf, Function *newf)
if(result)
c = result;
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(m_Constants, c) || (newf && IN_ARRAY(newf->constants, c)));
#endif
}
void ProgramEditor::Fixup(Metadata *&m, Function *oldf, Function *newf)
@@ -308,6 +328,10 @@ void ProgramEditor::Fixup(Metadata *&m, Function *oldf, Function *newf)
if(result)
m = result;
}
#if ENABLED(RDOC_DEVEL)
RDCASSERT(IN_ARRAY(m_Metadata, m) || (newf && IN_ARRAY(newf->metadata, m)));
#endif
}
ProgramEditor::~ProgramEditor()
@@ -407,7 +431,7 @@ ProgramEditor::~ProgramEditor()
Fixup(c.type);
Fixup(c.inner);
for(size_t i = 0; i < c.members.size(); i++)
Fixup(c.members[i]);
Fixup(c.members[i], &oldf, &f);
}
for(Value &v : f.values)