mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-17 09:39:19 +00:00
Add helpers for managing annotations in structured data
This commit is contained in:
5 files changed
+329
-11
No files matched your search
@@ -669,6 +669,13 @@ typically it is one parent to many derived.
|
||||
)");
|
||||
rdcarray<ResourceId> parentResources;
|
||||
|
||||
DOCUMENT(R"(An optional set of annotations associated with this resource, may be ``None`` if
|
||||
annotations are not used.
|
||||
|
||||
:type: SDObject
|
||||
)");
|
||||
SDObject *annotations = NULL;
|
||||
|
||||
DOCUMENT(R"(Utility function for setting up a custom name to overwrite the auto-generated one.
|
||||
|
||||
:param str givenName: The custom name to use.
|
||||
@@ -964,6 +971,13 @@ markers added to the capture after load.
|
||||
)");
|
||||
uint64_t fileOffset = 0;
|
||||
|
||||
DOCUMENT(R"(An optional set of annotations associated with this event, may be ``None`` if
|
||||
annotations are not used.
|
||||
|
||||
:type: SDObject
|
||||
)");
|
||||
SDObject *annotations = NULL;
|
||||
|
||||
static const uint32_t NoChunk = ~0U;
|
||||
};
|
||||
|
||||
@@ -1855,6 +1869,12 @@ this counts the frame number when the capture was made.
|
||||
)");
|
||||
rdcarray<DebugMessage> debugMessages;
|
||||
|
||||
DOCUMENT(R"(Whether or not the capture contains any annotations.
|
||||
|
||||
:type: bool
|
||||
)");
|
||||
bool containsAnnotations = false;
|
||||
|
||||
static const uint32_t NoFrameNumber = ~0U;
|
||||
};
|
||||
|
||||
|
||||
@@ -619,9 +619,9 @@ struct SDObject
|
||||
PopulateAllChildren();
|
||||
}
|
||||
|
||||
ret->data.children.resize(data.children.size());
|
||||
ret->data.children.reserve(data.children.size());
|
||||
for(size_t i = 0; i < data.children.size(); i++)
|
||||
ret->data.children[i] = data.children[i]->Duplicate();
|
||||
ret->AddAndOwnChild(data.children[i]->Duplicate());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -691,8 +691,7 @@ recursively through children.
|
||||
// fully owned children. This shouldn't happen, but just in case we'll evaluate the lazy array
|
||||
// here.
|
||||
PopulateAllChildren();
|
||||
data.children.push_back(child->Duplicate());
|
||||
data.children.back()->m_Parent = this;
|
||||
AddAndOwnChild(child->Duplicate());
|
||||
}
|
||||
DOCUMENT(R"(Find a child object by a given name. If no matching child is found, ``None`` is
|
||||
returned.
|
||||
@@ -734,6 +733,127 @@ The order of the search is not guaranteed, so care should be taken when the name
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DOCUMENT(R"(Create a child object by a key path. Children will be created as necessary to ensure
|
||||
that the key path exists, but if they already exist then the existing object will be returned.
|
||||
|
||||
Key paths are dotted recursive references, e.g. ``foo.bar`` is the member ``bar`` in parent ``foo``.
|
||||
|
||||
Arrays are represented by simple numeric entries e.g. ``foo.0.bar``, ``foo.1.bar``.
|
||||
|
||||
Empty entries are ignored so ``foo..bar`` and ``foo.bar`` refer to the same object.
|
||||
|
||||
Key paths must not be empty and must not begin with a dot.
|
||||
|
||||
If any path element is not unique in any child the behaviour is undefined, so objects should only be
|
||||
manipulated by key path exclusively or not at all.
|
||||
|
||||
:param str keyPath: The key path to search for and return.
|
||||
:return: A reference to the object at the relative key path
|
||||
:rtype: SDObject
|
||||
)");
|
||||
inline SDObject *CreateChildByKeyPath(const rdcstr &keyPath)
|
||||
{
|
||||
if(keyPath.empty() || keyPath[0] == '.')
|
||||
return this;
|
||||
|
||||
int dotIdx = keyPath.indexOf('.');
|
||||
rdcstr element = keyPath.substr(0, dotIdx);
|
||||
|
||||
SDObject *child = NULL;
|
||||
for(size_t i = 0; i < data.children.size(); i++)
|
||||
if(GetChild(i)->name == element)
|
||||
child = GetChild(i);
|
||||
|
||||
if(!child)
|
||||
child = AddAndOwnChild(new SDObject(element, ""_lit));
|
||||
|
||||
while(dotIdx >= 0 && keyPath[dotIdx] == '.')
|
||||
dotIdx++;
|
||||
|
||||
if(dotIdx >= 0 && dotIdx < keyPath.count())
|
||||
return child->CreateChildByKeyPath(keyPath.substr(dotIdx));
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
DOCUMENT(R"(Find if a child object if it exists by a key path. Children will not be created
|
||||
if any element of the path doesn't exist and instead ``None`` will be returned.
|
||||
|
||||
Key paths are dotted recursive references, e.g. ``foo.bar`` is the member ``bar`` in parent ``foo``.
|
||||
|
||||
Arrays are represented by simple numeric entries e.g. ``foo.0.bar``, ``foo.1.bar``.
|
||||
|
||||
Empty entries are ignored so ``foo..bar`` and ``foo.bar`` refer to the same object.
|
||||
|
||||
Key paths must not be empty and must not begin with a dot.
|
||||
|
||||
If any path element is not unique in any child the behaviour is undefined, so objects should only be
|
||||
manipulated by key path exclusively or not at all.
|
||||
|
||||
:param str keyPath: The key path to search for and return.
|
||||
:return: Whether or not a child exists at the given key path
|
||||
:rtype: SDObject
|
||||
)");
|
||||
inline const SDObject *FindChildByKeyPath(const rdcstr &keyPath) const
|
||||
{
|
||||
if(keyPath.empty() || keyPath[0] == '.')
|
||||
return this;
|
||||
|
||||
int dotIdx = keyPath.indexOf('.');
|
||||
rdcstr element = keyPath.substr(0, dotIdx);
|
||||
|
||||
const SDObject *child = NULL;
|
||||
for(size_t i = 0; i < data.children.size(); i++)
|
||||
if(GetChild(i)->name == element)
|
||||
child = GetChild(i);
|
||||
|
||||
if(!child)
|
||||
return NULL;
|
||||
|
||||
while(dotIdx >= 0 && keyPath[dotIdx] == '.')
|
||||
dotIdx++;
|
||||
|
||||
if(dotIdx >= 0 && dotIdx < keyPath.count())
|
||||
return child->FindChildByKeyPath(keyPath.substr(dotIdx));
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
DOCUMENT(R"(Delete a child object by a key path. All children of the resulting path will be deleted
|
||||
as well. If no such path exists, nothing will be changed.
|
||||
|
||||
If any path element is not unique in any child the behaviour is undefined, so objects should only be
|
||||
manipulated by key path exclusively or not at all.
|
||||
|
||||
:param str keyPath: The key path to search for and delete.
|
||||
)");
|
||||
inline void EraseChildByKeyPath(const rdcstr &keyPath)
|
||||
{
|
||||
// shouldn't happen since we delete the found child (if it exists) from the parent, but return to be fault-tolerant
|
||||
if(keyPath.empty() || keyPath[0] == '.')
|
||||
return;
|
||||
|
||||
int dotIdx = keyPath.indexOf('.');
|
||||
rdcstr element = keyPath.substr(0, dotIdx);
|
||||
|
||||
int childIdx = -1;
|
||||
for(int i = 0; i < data.children.count(); i++)
|
||||
if(GetChild(i)->name == element)
|
||||
childIdx = i;
|
||||
|
||||
// if the child doesn't exist we can stop now
|
||||
if(childIdx < 0)
|
||||
return;
|
||||
|
||||
while(dotIdx >= 0 && keyPath[dotIdx] == '.')
|
||||
dotIdx++;
|
||||
|
||||
if(dotIdx >= 0 && dotIdx < keyPath.count())
|
||||
return GetChild(childIdx)->EraseChildByKeyPath(keyPath.substr(dotIdx));
|
||||
|
||||
RemoveChild(childIdx);
|
||||
}
|
||||
|
||||
DOCUMENT(R"(Find a child object by a given index. If the index is out of bounds, ``None`` is
|
||||
returned.
|
||||
|
||||
@@ -1500,12 +1620,11 @@ struct SDChunk : public SDObject
|
||||
ret->data.basic = data.basic;
|
||||
ret->data.str = data.str;
|
||||
|
||||
ret->data.children.resize(data.children.size());
|
||||
|
||||
PopulateAllChildren();
|
||||
|
||||
ret->data.children.reserve(data.children.size());
|
||||
for(size_t i = 0; i < data.children.size(); i++)
|
||||
ret->data.children[i] = data.children[i]->Duplicate();
|
||||
ret->AddAndOwnChild(data.children[i]->Duplicate());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,179 @@ RDOC_CONFIG(rdcarray<rdcstr>, Replay_Shader_LimitedSearchDirPaths, {},
|
||||
"Companion array to DXBC.Debug.SearchDirPaths - listing paths which should not be "
|
||||
"searched exhaustively but only used for simple lookups.");
|
||||
|
||||
void WriteAnnotation(SDObject *obj, RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||
RENDERDOC_AnnotationValue value)
|
||||
{
|
||||
if(valueType == eRENDERDOC_Empty)
|
||||
{
|
||||
RDCERR("Invalid type of annotation to write");
|
||||
return;
|
||||
}
|
||||
|
||||
const rdcinflexiblestr types[eRENDERDOC_APIObject + 1][4] = {
|
||||
// eRENDERDOC_Empty,
|
||||
{""_lit, ""_lit, ""_lit, ""_lit},
|
||||
// eRENDERDOC_Bool,
|
||||
{"bool"_lit, "bool2"_lit, "bool3"_lit, "bool4"_lit},
|
||||
// eRENDERDOC_Int32,
|
||||
{"int"_lit, "int2"_lit, "int3"_lit, "int4"_lit},
|
||||
// eRENDERDOC_UInt32,
|
||||
{"uint"_lit, "uint2"_lit, "uint3"_lit, "uint4"_lit},
|
||||
// eRENDERDOC_Int64,
|
||||
{"long"_lit, "long2"_lit, "long3"_lit, "long4"_lit},
|
||||
// eRENDERDOC_UInt64,
|
||||
{"ulong"_lit, "ulong2"_lit, "ulong3"_lit, "ulong4"_lit},
|
||||
// eRENDERDOC_Float,
|
||||
{"float"_lit, "float2"_lit, "float3"_lit, "float4"_lit},
|
||||
// eRENDERDOC_Double,
|
||||
{"double"_lit, "double2"_lit, "double3"_lit, "double4"_lit},
|
||||
// eRENDERDOC_String,
|
||||
{"string"_lit, ""_lit, ""_lit, ""_lit},
|
||||
// eRENDERDOC_APIObject,
|
||||
{"ResourceId"_lit, ""_lit, ""_lit, ""_lit},
|
||||
};
|
||||
|
||||
const uint32_t byteSize[eRENDERDOC_APIObject + 1] = {
|
||||
// eRENDERDOC_Empty,
|
||||
0,
|
||||
// eRENDERDOC_Bool,
|
||||
1,
|
||||
// eRENDERDOC_Int32,
|
||||
4,
|
||||
// eRENDERDOC_UInt32,
|
||||
4,
|
||||
// eRENDERDOC_Int64,
|
||||
8,
|
||||
// eRENDERDOC_UInt64,
|
||||
8,
|
||||
// eRENDERDOC_Float,
|
||||
4,
|
||||
// eRENDERDOC_Double,
|
||||
8,
|
||||
// eRENDERDOC_String,
|
||||
0,
|
||||
// eRENDERDOC_APIObject,
|
||||
8,
|
||||
};
|
||||
|
||||
const SDBasic basetype[eRENDERDOC_APIObject + 1] = {
|
||||
// eRENDERDOC_Empty,
|
||||
SDBasic::Null,
|
||||
// eRENDERDOC_Bool,
|
||||
SDBasic::Boolean,
|
||||
// eRENDERDOC_Int32,
|
||||
SDBasic::SignedInteger,
|
||||
// eRENDERDOC_UInt32,
|
||||
SDBasic::UnsignedInteger,
|
||||
// eRENDERDOC_Int64,
|
||||
SDBasic::SignedInteger,
|
||||
// eRENDERDOC_UInt64,
|
||||
SDBasic::UnsignedInteger,
|
||||
// eRENDERDOC_Float,
|
||||
SDBasic::Float,
|
||||
// eRENDERDOC_Double,
|
||||
SDBasic::Float,
|
||||
// eRENDERDOC_String,
|
||||
SDBasic::String,
|
||||
// eRENDERDOC_APIObject,
|
||||
SDBasic::Resource,
|
||||
};
|
||||
|
||||
if(valueVectorWidth > 1)
|
||||
{
|
||||
if(valueType == eRENDERDOC_APIObject)
|
||||
{
|
||||
RDCERR("Invalid vector width for API object");
|
||||
return;
|
||||
}
|
||||
else if(valueType == eRENDERDOC_String)
|
||||
{
|
||||
RDCERR("Invalid vector width for string");
|
||||
return;
|
||||
}
|
||||
|
||||
const rdcinflexiblestr comps[] = {"x"_lit, "y"_lit, "z"_lit, "w"_lit};
|
||||
|
||||
obj->type.basetype = SDBasic::Struct;
|
||||
obj->type.name = types[valueType][valueVectorWidth - 1];
|
||||
|
||||
RENDERDOC_AnnotationValue tmp = {};
|
||||
for(uint32_t i = 0; i < valueVectorWidth; i++)
|
||||
{
|
||||
SDObject *child = obj->CreateChildByKeyPath(comps[i]);
|
||||
|
||||
if(byteSize[valueType] == 1)
|
||||
memcpy(&tmp.boolean, &value.vector.boolean[i], sizeof(tmp.boolean));
|
||||
if(byteSize[valueType] == 4)
|
||||
memcpy(&tmp.uint32, &value.vector.uint32[i], sizeof(tmp.uint32));
|
||||
if(byteSize[valueType] == 8)
|
||||
memcpy(&tmp.uint64, &value.vector.uint64[i], sizeof(tmp.uint64));
|
||||
|
||||
WriteAnnotation(child, valueType, 0, tmp);
|
||||
if(i == 0)
|
||||
obj->type.byteSize = child->type.byteSize * valueVectorWidth;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
obj->type.name = types[valueType][0];
|
||||
obj->type.basetype = basetype[valueType];
|
||||
obj->type.byteSize = byteSize[valueType];
|
||||
|
||||
switch(valueType)
|
||||
{
|
||||
case eRENDERDOC_Empty:
|
||||
case eRENDERDOC_AnnotationMax: RDCERR("Invalid annotation type"); return;
|
||||
case eRENDERDOC_Bool:
|
||||
{
|
||||
obj->data.basic.b = value.boolean;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_Int32:
|
||||
{
|
||||
obj->data.basic.i = value.int32;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_UInt32:
|
||||
{
|
||||
obj->data.basic.u = value.uint32;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_Int64:
|
||||
{
|
||||
obj->data.basic.u = value.int64;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_UInt64:
|
||||
{
|
||||
obj->data.basic.u = value.uint64;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_Float:
|
||||
{
|
||||
obj->data.basic.d = value.float32;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_Double:
|
||||
{
|
||||
obj->data.basic.d = value.float64;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_String:
|
||||
{
|
||||
obj->type.byteSize = strlen(value.string);
|
||||
obj->data.str = value.string;
|
||||
break;
|
||||
}
|
||||
case eRENDERDOC_APIObject:
|
||||
{
|
||||
memcpy(&obj->data.basic.id, &value.uint64, sizeof(ResourceId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LogReplayOptions(const ReplayOptions &opts)
|
||||
{
|
||||
RDCLOG("%s API validation during replay", (opts.apiValidation ? "Enabling" : "Not enabling"));
|
||||
|
||||
@@ -44,6 +44,9 @@ struct RDCThumb;
|
||||
struct ReplayOptions;
|
||||
struct SDObject;
|
||||
|
||||
void WriteAnnotation(SDObject *obj, RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth,
|
||||
RENDERDOC_AnnotationValue value);
|
||||
|
||||
// not provided by tinyexr, just do by hand
|
||||
bool is_exr_file(const byte *headerBuffer, size_t size);
|
||||
void LogReplayOptions(const ReplayOptions &opts);
|
||||
|
||||
@@ -442,8 +442,9 @@ void DoSerialise(SerialiserType &ser, ResourceDescription &el)
|
||||
SERIALISE_MEMBER(initialisationChunks);
|
||||
SERIALISE_MEMBER(derivedResources);
|
||||
SERIALISE_MEMBER(parentResources);
|
||||
// SERIALISE_MEMBER(annotations);
|
||||
|
||||
SIZE_CHECK(112);
|
||||
SIZE_CHECK(120);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
@@ -539,8 +540,9 @@ void DoSerialise(SerialiserType &ser, APIEvent &el)
|
||||
SERIALISE_MEMBER(eventId);
|
||||
SERIALISE_MEMBER(chunkIndex);
|
||||
SERIALISE_MEMBER(fileOffset);
|
||||
// SERIALISE_MEMBER(annotations);
|
||||
|
||||
SIZE_CHECK(16);
|
||||
SIZE_CHECK(24);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
@@ -773,8 +775,9 @@ void DoSerialise(SerialiserType &ser, FrameDescription &el)
|
||||
SERIALISE_MEMBER(captureTime);
|
||||
SERIALISE_MEMBER(stats);
|
||||
SERIALISE_MEMBER(debugMessages);
|
||||
SERIALISE_MEMBER(containsAnnotations);
|
||||
|
||||
SIZE_CHECK(504);
|
||||
SIZE_CHECK(512);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
@@ -783,7 +786,7 @@ void DoSerialise(SerialiserType &ser, FrameRecord &el)
|
||||
SERIALISE_MEMBER(frameInfo);
|
||||
SERIALISE_MEMBER(actionList);
|
||||
|
||||
SIZE_CHECK(528);
|
||||
SIZE_CHECK(536);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
|
||||
Reference in new issue
Block a user