diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index d0853253c..f0b483e51 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -437,13 +437,15 @@ public: void WriteThroughPointer(ShaderVariable &ptr, const ShaderVariable &val); ShaderVariable MakeCompositePointer(const ShaderVariable &base, Id id, rdcarray &indices); - DebugAPIWrapper *GetAPIWrapper() { return apiWrapper; } + DebugAPIWrapper *GetAPIWrapper(); uint32_t GetNumInstructions() { return (uint32_t)instructionOffsets.size(); } GlobalState GetGlobal() { return global; } const rdcarray &GetLiveGlobals() { return liveGlobals; } ThreadState &GetActiveLane() { return workgroup[activeLaneIndex]; } const ThreadState &GetActiveLane() const { return workgroup[activeLaneIndex]; } uint32_t GetSubgroupSize() const { return subgroupSize; } + uint64_t GetDeviceThreadID() const { return deviceThreadID; } + bool IsDeviceThread() const { return Threading::GetCurrentID() == GetDeviceThreadID(); } private: virtual void PreParse(uint32_t maxId); virtual void PostParse(); @@ -558,6 +560,8 @@ private: rdcshaders::ControlFlow controlFlow; const ScopeData *GetScope(size_t offset) const; + + uint64_t deviceThreadID; }; // this does a 'safe' value assignment, by doing parallel depth-first iteration of both variables diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index 1586af5f2..e5aee9edf 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -24,6 +24,7 @@ #include "spirv_debug.h" #include "common/formatting.h" +#include "common/threading.h" #include "core/settings.h" #include "replay/common/var_dispatch_helpers.h" #include "spirv_op_helpers.h" @@ -307,7 +308,17 @@ void AssignValue(ShaderVariable &dst, const ShaderVariable &src) AssignValue(dst.members[i], src.members[i]); } -Debugger::Debugger() +#if defined(RELEASE) +#define CHECK_DEBUGGER_THREAD() \ + do \ + { \ + } while((void)0, 0) +#else +#define CHECK_DEBUGGER_THREAD() \ + RDCASSERTMSG("Debugger function called from non-device thread!", IsDeviceThread()); +#endif // #if defined(RELEASE) + +Debugger::Debugger() : deviceThreadID(Threading::GetCurrentID()) { } @@ -3179,6 +3190,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const std::function pointerReadCallback; if(IsPhysicalPointer(ptr)) { + CHECK_DEBUGGER_THREAD(); if(checkPointerFlags(ptr, PointerFlags::DereferencedPhysical)) typeId = getBufferTypeId(ptr); else @@ -3209,6 +3221,7 @@ ShaderVariable Debugger::ReadFromPointer(const ShaderVariable &ptr) const const ShaderVariable *inner = getPointer(ptr); if(inner->type == VarType::ReadWriteResource && checkPointerFlags(*inner, PointerFlags::SSBO)) { + CHECK_DEBUGGER_THREAD(); typeId = getBufferTypeId(ptr); byteOffset = getByteOffset(ptr); bind = inner->GetBindIndex(); @@ -3496,6 +3509,7 @@ void Debugger::WriteThroughPointer(ShaderVariable &ptr, const ShaderVariable &va if(pointerWriteCallback) { + CHECK_DEBUGGER_THREAD(); auto writeCallback = [pointerWriteCallback](const ShaderVariable &var, const Decorations &dec, const DataType &type, uint64_t offset, const rdcstr &) { @@ -4500,6 +4514,12 @@ void Debugger::RegisterOp(Iter it) } } +// Must be called from the replay manager thread (the debugger thread) +DebugAPIWrapper *Debugger::GetAPIWrapper() +{ + CHECK_DEBUGGER_THREAD(); + return apiWrapper; +} }; // namespace rdcspv #if ENABLED(ENABLE_UNIT_TESTS)