mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add GL support for annotations
This commit is contained in:
@@ -622,8 +622,30 @@ typedef union RENDERDOC_AnnotationValue
|
||||
void *apiObject;
|
||||
} RENDERDOC_AnnotationValue;
|
||||
|
||||
// simple C++ helper to avoid the need for a temporary object to pass a simple value via the function
|
||||
// a struct for specifying a GL object, as we don't have pointers we can use so instead we specify a
|
||||
// pointer to this struct giving both the type and the name
|
||||
typedef struct RENDERDOC_GLResourceReference
|
||||
{
|
||||
// this is the same GLenum identifier as passed to glObjectLabel
|
||||
uint32_t identifier;
|
||||
uint32_t name;
|
||||
} GLResourceReference;
|
||||
|
||||
// simple C++ helpers to avoid the need for a temporary objects for value passing and GL object specification
|
||||
#ifdef __cplusplus
|
||||
struct RDGLObjectHelper
|
||||
{
|
||||
RENDERDOC_GLResourceReference gl;
|
||||
|
||||
RDGLObjectHelper(uint32_t identifier, uint32_t name)
|
||||
{
|
||||
gl.identifier = identifier;
|
||||
gl.name = name;
|
||||
}
|
||||
|
||||
operator RENDERDOC_GLResourceReference *() { return ≷ }
|
||||
};
|
||||
|
||||
struct RDAnnotationHelper
|
||||
{
|
||||
RENDERDOC_AnnotationValue val;
|
||||
|
||||
@@ -1266,6 +1266,10 @@ bool GLInitParams::IsSupportedVersion(uint64_t ver)
|
||||
if(ver == 0x22)
|
||||
return true;
|
||||
|
||||
// 0x23 -> 0x24 - added serialised annotations
|
||||
if(ver == 0x23)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2249,6 +2249,8 @@ enum class GLChunk : uint32_t
|
||||
glFlushMappedBufferRangeEXT,
|
||||
glClipControlEXT,
|
||||
|
||||
SetCommandAnnotation,
|
||||
|
||||
Max,
|
||||
};
|
||||
|
||||
|
||||
@@ -947,6 +947,17 @@ WrappedOpenGL::~WrappedOpenGL()
|
||||
if(m_IndirectBuffer)
|
||||
GL.glDeleteBuffers(1, &m_IndirectBuffer);
|
||||
|
||||
// Clean up annotation data
|
||||
for(auto it = m_Annotations.begin(); it != m_Annotations.end(); ++it)
|
||||
delete it->second;
|
||||
m_Annotations.clear();
|
||||
|
||||
SAFE_DELETE(m_RootAnnotation);
|
||||
|
||||
for(SDObject *obj : m_EventAnnotations)
|
||||
delete obj;
|
||||
m_EventAnnotations.clear();
|
||||
|
||||
m_ArrayMS.Destroy();
|
||||
|
||||
SAFE_DELETE(m_FrameReader);
|
||||
@@ -3120,6 +3131,35 @@ bool WrappedOpenGL::Serialise_BeginCaptureFrame(SerialiserType &ser)
|
||||
|
||||
SERIALISE_ELEMENT(state).Unimportant();
|
||||
|
||||
// Serialize object annotations
|
||||
if(ser.VersionAtLeast(0x24))
|
||||
{
|
||||
SCOPED_LOCK(m_AnnotationsLock);
|
||||
|
||||
SERIALISE_ELEMENT_LOCAL(numAnnotations, uint32_t(m_Annotations.size()));
|
||||
|
||||
auto it = m_Annotations.begin();
|
||||
for(uint32_t i = 0; i < numAnnotations; i++)
|
||||
{
|
||||
SERIALISE_ELEMENT_LOCAL(id, it->first);
|
||||
SDObject *annotation = it->second;
|
||||
if(ser.IsReading())
|
||||
annotation = new SDObject(""_lit, ""_lit); // will be overwritten below
|
||||
ser.Serialise("annotation"_lit, *annotation);
|
||||
|
||||
if(ser.IsReading() && IsLoading(m_State))
|
||||
{
|
||||
m_Annotations[id] = annotation;
|
||||
GetReplay()->GetResourceDesc(id).annotations = annotation;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
if(numAnnotations > 0)
|
||||
GetReplay()->WriteFrameRecord().frameInfo.containsAnnotations = true;
|
||||
}
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
@@ -4747,6 +4787,10 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
|
||||
return Serialise_BeginCaptureFrame(ser);
|
||||
}
|
||||
|
||||
case GLChunk::SetCommandAnnotation:
|
||||
return Serialise_SetCommandAnnotation(ser, rdcstr(), eRENDERDOC_AnnotationMax, 0,
|
||||
RENDERDOC_AnnotationValue());
|
||||
|
||||
case GLChunk::ContextConfiguration: return Serialise_ContextConfiguration(ser, NULL);
|
||||
|
||||
case GLChunk::glIndirectSubCommand:
|
||||
@@ -5294,7 +5338,10 @@ RDResult WrappedOpenGL::ContextReplayLog(CaptureState readType, uint32_t startEv
|
||||
break;
|
||||
|
||||
m_LastChunk = chunktype;
|
||||
m_CurEventID++;
|
||||
|
||||
// annotations do not produce events
|
||||
if(chunktype != GLChunk::SetCommandAnnotation)
|
||||
m_CurEventID++;
|
||||
}
|
||||
|
||||
// swap the structure back now that we've accumulated the frame as well.
|
||||
@@ -5400,7 +5447,8 @@ bool WrappedOpenGL::ContextProcessChunk(ReadSerialiser &ser, GLChunk chunk)
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(!m_AddedAction)
|
||||
// annotations don't add events
|
||||
if(!m_AddedAction && chunk != GLChunk::SetCommandAnnotation)
|
||||
AddEvent();
|
||||
}
|
||||
|
||||
@@ -5757,6 +5805,13 @@ void WrappedOpenGL::AddEvent()
|
||||
|
||||
apievent.chunkIndex = uint32_t(m_StructuredFile->chunks.size() - 1);
|
||||
|
||||
// Apply current annotation state to this event
|
||||
if(m_RootAnnotation)
|
||||
{
|
||||
apievent.annotations = m_RootAnnotation->Duplicate();
|
||||
m_EventAnnotations.push_back(apievent.annotations);
|
||||
}
|
||||
|
||||
m_CurEvents.push_back(apievent);
|
||||
|
||||
if(IsLoading(m_State))
|
||||
|
||||
@@ -59,7 +59,7 @@ struct GLInitParams
|
||||
rdcstr renderer, version;
|
||||
|
||||
// check if a frame capture section version is supported
|
||||
static const uint64_t CurrentVersion = 0x23;
|
||||
static const uint64_t CurrentVersion = 0x24;
|
||||
static bool IsSupportedVersion(uint64_t ver);
|
||||
};
|
||||
|
||||
@@ -186,6 +186,12 @@ private:
|
||||
void *m_LastCtx;
|
||||
int m_ImplicitThreadSwitches = 0;
|
||||
|
||||
// Object and command annotation support
|
||||
Threading::CriticalSection m_AnnotationsLock;
|
||||
std::unordered_map<ResourceId, SDObject *> m_Annotations; // Object annotations by ResourceId
|
||||
SDObject *m_RootAnnotation = NULL; // Root for event annotation state
|
||||
rdcarray<SDObject *> m_EventAnnotations; // Track allocations for cleanup
|
||||
|
||||
GLContextTLSData m_EmptyTLSData;
|
||||
uint64_t m_CurCtxDataTLS;
|
||||
rdcarray<GLContextTLSData *> m_CtxDataVector;
|
||||
@@ -574,6 +580,12 @@ private:
|
||||
rdcarray<QueuedResource> m_QueuedInitialFetches;
|
||||
rdcarray<QueuedResource> m_QueuedReleases;
|
||||
|
||||
void RemoveAnnotations(ResourceId id)
|
||||
{
|
||||
SCOPED_LOCK(m_AnnotationsLock);
|
||||
m_Annotations.erase(id);
|
||||
}
|
||||
|
||||
void QueuePrepareInitialState(GLResource res);
|
||||
void QueueResourceRelease(GLResource res);
|
||||
void CheckQueuedInitialFetches(void *ctx);
|
||||
@@ -705,17 +717,17 @@ public:
|
||||
void StartFrameCapture(DeviceOwnedWindow devWnd);
|
||||
bool EndFrameCapture(DeviceOwnedWindow devWnd);
|
||||
bool DiscardFrameCapture(DeviceOwnedWindow devWnd);
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool Serialise_SetCommandAnnotation(SerialiserType &ser, rdcstr key,
|
||||
RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||
RENDERDOC_AnnotationValue value);
|
||||
|
||||
uint32_t SetObjectAnnotation(void *object, const char *key, RENDERDOC_AnnotationType valueType,
|
||||
uint32_t valueVectorWidth, const RENDERDOC_AnnotationValue *value)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
uint32_t valueVectorWidth, const RENDERDOC_AnnotationValue *value);
|
||||
uint32_t SetCommandAnnotation(void *queueOrCommandBuffer, const char *key,
|
||||
RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||
const RENDERDOC_AnnotationValue *value)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
const RENDERDOC_AnnotationValue *value);
|
||||
|
||||
// map with key being mip level, value being stored data
|
||||
typedef std::map<int, bytebuf> CompressedDataStore;
|
||||
|
||||
@@ -32,6 +32,28 @@ GLResourceManager::GLResourceManager(CaptureState &state, WrappedOpenGL *driver)
|
||||
{
|
||||
}
|
||||
|
||||
void GLResourceManager::UnregisterResource(GLResource res)
|
||||
{
|
||||
auto it = m_Resources.find(res);
|
||||
if(it != m_Resources.end())
|
||||
{
|
||||
ResourceId id = it->second.first;
|
||||
m_Names.erase(id);
|
||||
|
||||
ReleaseResource(id);
|
||||
m_Resources.erase(res);
|
||||
|
||||
auto fboit = m_FBOAttachmentsCache.find(id);
|
||||
if(fboit != m_FBOAttachmentsCache.end())
|
||||
{
|
||||
delete fboit->second;
|
||||
m_FBOAttachmentsCache.erase(fboit);
|
||||
}
|
||||
|
||||
m_Driver->RemoveAnnotations(id);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLResourceManager::IsResourceTrackedForPersistency(const GLResource &res)
|
||||
{
|
||||
return res.Namespace == eResTexture || res.Namespace == eResBuffer;
|
||||
|
||||
@@ -165,25 +165,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnregisterResource(GLResource res)
|
||||
{
|
||||
auto it = m_Resources.find(res);
|
||||
if(it != m_Resources.end())
|
||||
{
|
||||
ResourceId id = it->second.first;
|
||||
m_Names.erase(id);
|
||||
|
||||
ReleaseResource(id);
|
||||
m_Resources.erase(res);
|
||||
|
||||
auto fboit = m_FBOAttachmentsCache.find(id);
|
||||
if(fboit != m_FBOAttachmentsCache.end())
|
||||
{
|
||||
delete fboit->second;
|
||||
m_FBOAttachmentsCache.erase(fboit);
|
||||
}
|
||||
}
|
||||
}
|
||||
void UnregisterResource(GLResource res);
|
||||
|
||||
ResourceId GetResID(GLResource res)
|
||||
{
|
||||
|
||||
@@ -54,6 +54,8 @@ rdcstr DoStringise(const GLChunk &el)
|
||||
STRINGISE_ENUM_CLASS(eglSwapBuffersWithDamageEXT);
|
||||
STRINGISE_ENUM_CLASS(eglSwapBuffersWithDamageKHR);
|
||||
|
||||
STRINGISE_ENUM_CLASS_NAMED(SetCommandAnnotation, "Internal::SetCommandAnnotation");
|
||||
|
||||
STRINGISE_ENUM_CLASS_NAMED(ImplicitThreadSwitch, "Internal::Implicit thread context-switch");
|
||||
|
||||
// re-use list of GL functions as chunks. Many of these will be aliased. This may not appear in the
|
||||
|
||||
@@ -235,6 +235,131 @@ void WrappedOpenGL::glObjectPtrLabel(const void *ptr, GLsizei length, const GLch
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedOpenGL::Serialise_SetCommandAnnotation(SerialiserType &ser, rdcstr key,
|
||||
RENDERDOC_AnnotationType valueType,
|
||||
uint32_t valueVectorWidth,
|
||||
RENDERDOC_AnnotationValue value)
|
||||
{
|
||||
SERIALISE_ELEMENT(key);
|
||||
SERIALISE_ELEMENT(valueType);
|
||||
ser.SetStructArg(valueType);
|
||||
SERIALISE_ELEMENT(valueVectorWidth);
|
||||
SERIALISE_ELEMENT(value);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
if(!m_RootAnnotation)
|
||||
m_RootAnnotation = new SDObject("Event Annotations"_lit, "Event Annotations"_lit);
|
||||
|
||||
SDObject *root = m_RootAnnotation;
|
||||
|
||||
if(valueType == eRENDERDOC_Empty)
|
||||
{
|
||||
root->EraseChildByKeyPath(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteAnnotation(root->CreateChildByKeyPath(key), valueType, valueVectorWidth, value);
|
||||
}
|
||||
|
||||
GetReplay()->WriteFrameRecord().frameInfo.containsAnnotations = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t WrappedOpenGL::SetCommandAnnotation(void *queueOrCommandBuffer, const char *key,
|
||||
RENDERDOC_AnnotationType valueType,
|
||||
uint32_t valueVectorWidth,
|
||||
const RENDERDOC_AnnotationValue *value)
|
||||
{
|
||||
if(queueOrCommandBuffer != NULL)
|
||||
return 2;
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
SERIALISE_TIME_CALL();
|
||||
|
||||
if(IsActiveCapturing(m_State))
|
||||
{
|
||||
USE_SCRATCH_SERIALISER();
|
||||
GET_SERIALISER.SetActionChunk();
|
||||
SCOPED_SERIALISE_CHUNK(GLChunk::SetCommandAnnotation);
|
||||
|
||||
RENDERDOC_AnnotationValue val = value ? *value : RENDERDOC_AnnotationValue();
|
||||
|
||||
if(valueType == eRENDERDOC_APIObject && val.apiObject)
|
||||
{
|
||||
RENDERDOC_GLResourceReference *reference = (RENDERDOC_GLResourceReference *)val.apiObject;
|
||||
ResourceId id = GetResourceManager()->GetResID(
|
||||
GetResource((GLenum)reference->identifier, reference->name));
|
||||
RDCCOMPILE_ASSERT(sizeof(val.uint64) == sizeof(id), "ResourceId isn't 64-bit!");
|
||||
memcpy(&val.uint64, &id, sizeof(id));
|
||||
}
|
||||
|
||||
Serialise_SetCommandAnnotation(GET_SERIALISER, key, valueType, valueVectorWidth, val);
|
||||
|
||||
m_ContextRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t WrappedOpenGL::SetObjectAnnotation(void *object, const char *key,
|
||||
RENDERDOC_AnnotationType valueType,
|
||||
uint32_t valueVectorWidth,
|
||||
const RENDERDOC_AnnotationValue *value)
|
||||
{
|
||||
RENDERDOC_GLResourceReference *reference = (RENDERDOC_GLResourceReference *)object;
|
||||
ResourceId id =
|
||||
GetResourceManager()->GetResID(GetResource((GLenum)reference->identifier, reference->name));
|
||||
|
||||
if(id != ResourceId())
|
||||
{
|
||||
RENDERDOC_AnnotationValue val = value ? *value : RENDERDOC_AnnotationValue();
|
||||
|
||||
// Convert API object references to ResourceId
|
||||
if(valueType == eRENDERDOC_APIObject && val.apiObject)
|
||||
{
|
||||
reference = (RENDERDOC_GLResourceReference *)val.apiObject;
|
||||
ResourceId valId =
|
||||
GetResourceManager()->GetResID(GetResource((GLenum)reference->identifier, reference->name));
|
||||
RDCCOMPILE_ASSERT(sizeof(val.uint64) == sizeof(valId), "ResourceId isn't 64-bit!");
|
||||
memcpy(&val.uint64, &valId, sizeof(valId));
|
||||
}
|
||||
|
||||
SDObject *root = NULL;
|
||||
{
|
||||
SCOPED_LOCK(m_AnnotationsLock);
|
||||
root = m_Annotations[id];
|
||||
if(!root)
|
||||
root = m_Annotations[id] = new SDObject("Object Annotations"_lit, "Object Annotations"_lit);
|
||||
}
|
||||
|
||||
if(valueType == eRENDERDOC_Empty)
|
||||
{
|
||||
root->EraseChildByKeyPath(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteAnnotation(root->CreateChildByKeyPath(key), valueType, valueVectorWidth, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
void WrappedOpenGL::glDebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
|
||||
{
|
||||
GetCtxData().m_RealDebugFunc = callback;
|
||||
@@ -600,3 +725,6 @@ INSTANTIATE_FUNCTION_SERIALISED(void, glInsertEventMarkerEXT, GLsizei length, co
|
||||
INSTANTIATE_FUNCTION_SERIALISED(void, glPushDebugGroup, GLenum source, GLuint id, GLsizei length,
|
||||
const GLchar *message);
|
||||
INSTANTIATE_FUNCTION_SERIALISED(void, glPopDebugGroup);
|
||||
INSTANTIATE_FUNCTION_SERIALISED(void, SetCommandAnnotation, rdcstr key,
|
||||
RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||
RENDERDOC_AnnotationValue value);
|
||||
|
||||
Reference in New Issue
Block a user