mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-13 19:17:12 +00:00
Add an SDBasic type for ResourceId.
* This type is core enum and used globally (not API specific) that it merits becoming a specific structured data type
This commit is contained in:
@@ -682,8 +682,7 @@ void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &
|
||||
// that for the best raw structured data representation instead of flattening those out to just
|
||||
// "ResourceId", and we also don't want to store two types ('fake' and 'real'), so instead we
|
||||
// check the custom string.
|
||||
if((obj->type.flags & SDTypeFlags::HasCustomString) &&
|
||||
!strncmp(obj->data.str.c_str(), "ResourceId", 10))
|
||||
if(obj->type.basetype == SDBasic::ResourceId)
|
||||
{
|
||||
ResourceId id;
|
||||
static_assert(sizeof(id) == sizeof(obj->data.basic.u), "ResourceId is no longer uint64_t!");
|
||||
@@ -715,6 +714,7 @@ void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList &
|
||||
case SDBasic::Null: param = lit("NULL"); break;
|
||||
case SDBasic::Buffer: param = lit("(%1 bytes)").arg(obj->type.byteSize); break;
|
||||
case SDBasic::String: param = obj->data.str; break;
|
||||
case SDBasic::ResourceId:
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: param = Formatter::Format(obj->data.basic.u); break;
|
||||
case SDBasic::SignedInteger: param = Formatter::Format(obj->data.basic.i); break;
|
||||
|
||||
@@ -251,6 +251,54 @@ inline enum_name operator++(enum_name &a) \
|
||||
|
||||
#define ENUM_ARRAY_SIZE(enum_name) size_t(enum_name::Count)
|
||||
|
||||
// declare ResourceId extremely early so that it can be referenced in structured_data.h
|
||||
|
||||
#ifdef RENDERDOC_EXPORTS
|
||||
struct ResourceId;
|
||||
|
||||
namespace ResourceIDGen
|
||||
{
|
||||
// the only function allowed access to ResourceId internals, for allocating a new ID
|
||||
ResourceId GetNewUniqueID();
|
||||
};
|
||||
#endif
|
||||
|
||||
// We give every resource a globally unique ID so that we can differentiate
|
||||
// between two textures allocated in the same memory (after the first is freed)
|
||||
//
|
||||
// it's a struct around a uint64_t to aid in template selection
|
||||
DOCUMENT(R"(This is an opaque identifier that uniquely locates a resource.
|
||||
|
||||
.. note::
|
||||
These IDs do not overlap ever - textures, buffers, shaders and samplers will all have unique IDs
|
||||
and do not reuse the namespace. Likewise the IDs assigned for resources during capture are not
|
||||
re-used on replay - the corresponding resources created on replay to stand-in for capture-time
|
||||
resources are given unique IDs and a mapping is stored to between the capture-time resource and
|
||||
the replay-time one.
|
||||
)");
|
||||
struct ResourceId
|
||||
{
|
||||
ResourceId() : id() {}
|
||||
DOCUMENT("A helper function that explicitly creates an empty/invalid/null :class:`ResourceId`.");
|
||||
inline static ResourceId Null() { return ResourceId(); }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for equality.");
|
||||
bool operator==(const ResourceId u) const { return id == u.id; }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for inequality.");
|
||||
bool operator!=(const ResourceId u) const { return id != u.id; }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for less-than.");
|
||||
bool operator<(const ResourceId u) const { return id < u.id; }
|
||||
#if defined(RENDERDOC_QT_COMPAT)
|
||||
operator QVariant() const { return QVariant::fromValue(*this); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint64_t id;
|
||||
|
||||
#ifdef RENDERDOC_EXPORTS
|
||||
friend ResourceId ResourceIDGen::GetNewUniqueID();
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "basic_types.h"
|
||||
#include "stringise.h"
|
||||
#include "structured_data.h"
|
||||
@@ -422,52 +470,8 @@ struct GlobalEnvironment
|
||||
Display *xlibDisplay = NULL;
|
||||
};
|
||||
|
||||
#ifdef RENDERDOC_EXPORTS
|
||||
struct ResourceId;
|
||||
|
||||
namespace ResourceIDGen
|
||||
{
|
||||
// the only function allowed access to ResourceId internals, for allocating a new ID
|
||||
ResourceId GetNewUniqueID();
|
||||
};
|
||||
#endif
|
||||
|
||||
// We give every resource a globally unique ID so that we can differentiate
|
||||
// between two textures allocated in the same memory (after the first is freed)
|
||||
//
|
||||
// it's a struct around a uint64_t to aid in template selection
|
||||
DOCUMENT(R"(This is an opaque identifier that uniquely locates a resource.
|
||||
|
||||
.. note::
|
||||
These IDs do not overlap ever - textures, buffers, shaders and samplers will all have unique IDs
|
||||
and do not reuse the namespace. Likewise the IDs assigned for resources during capture are not
|
||||
re-used on replay - the corresponding resources created on replay to stand-in for capture-time
|
||||
resources are given unique IDs and a mapping is stored to between the capture-time resource and
|
||||
the replay-time one.
|
||||
)");
|
||||
struct ResourceId
|
||||
{
|
||||
ResourceId() : id() {}
|
||||
DOCUMENT("A helper function that explicitly creates an empty/invalid/null :class:`ResourceId`.");
|
||||
inline static ResourceId Null() { return ResourceId(); }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for equality.");
|
||||
bool operator==(const ResourceId u) const { return id == u.id; }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for inequality.");
|
||||
bool operator!=(const ResourceId u) const { return id != u.id; }
|
||||
DOCUMENT("Compares two ``ResourceId`` objects for less-than.");
|
||||
bool operator<(const ResourceId u) const { return id < u.id; }
|
||||
#if defined(RENDERDOC_QT_COMPAT)
|
||||
operator QVariant() const { return QVariant::fromValue(*this); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint64_t id;
|
||||
|
||||
#ifdef RENDERDOC_EXPORTS
|
||||
friend ResourceId ResourceIDGen::GetNewUniqueID();
|
||||
#endif
|
||||
};
|
||||
|
||||
// declare metatype/reflection for ResourceId here as the struct itself is declared before including
|
||||
// all relevant headers above
|
||||
#if defined(RENDERDOC_QT_COMPAT)
|
||||
Q_DECLARE_METATYPE(ResourceId);
|
||||
#endif
|
||||
|
||||
@@ -81,6 +81,11 @@ DOCUMENT(R"(The basic irreducible type of an object. Every other more complex ty
|
||||
|
||||
A single byte character. Wide/multi-byte characters are not supported (these would be stored as a
|
||||
string with 1 character and multiple bytes in UTF-8).
|
||||
|
||||
.. data:: ResourceId
|
||||
|
||||
A ResourceId. Equivalent to (and stored as) an 8-byte unsigned integer, but specifically contains
|
||||
the unique Id of a resource in a capture.
|
||||
)");
|
||||
enum class SDBasic : uint32_t
|
||||
{
|
||||
@@ -96,6 +101,7 @@ enum class SDBasic : uint32_t
|
||||
Float,
|
||||
Boolean,
|
||||
Character,
|
||||
ResourceId,
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_ENUM(SDBasic);
|
||||
@@ -251,9 +257,14 @@ union SDObjectPODData
|
||||
DOCUMENT("The value as a single byte character.");
|
||||
char c;
|
||||
|
||||
DOCUMENT("The value as a :class:`ResourceId`.");
|
||||
ResourceId id;
|
||||
|
||||
// mostly here just for debugging
|
||||
DOCUMENT("A useful alias of :data:`u` - the number of children when a struct/array.");
|
||||
uint64_t numChildren;
|
||||
|
||||
SDObjectPODData() : u(0) {}
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(SDObjectPODData);
|
||||
@@ -378,6 +389,7 @@ struct SDObject
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: return QVariant(qulonglong(data.basic.u));
|
||||
case SDBasic::SignedInteger: return QVariant(qlonglong(data.basic.i));
|
||||
case SDBasic::ResourceId: return (QVariant)data.basic.id;
|
||||
case SDBasic::Float: return data.basic.d;
|
||||
case SDBasic::Boolean: return data.basic.b;
|
||||
case SDBasic::Character: return data.basic.c;
|
||||
@@ -523,6 +535,16 @@ inline SDObject *makeSDObject(const char *name, const char *val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DOCUMENT("Make a structured object out of a ResourceId");
|
||||
inline SDObject *makeSDObject(const char *name, ResourceId val)
|
||||
{
|
||||
SDObject *ret = new SDObject(name, "ResourceId");
|
||||
ret->type.basetype = SDBasic::ResourceId;
|
||||
ret->type.byteSize = 8;
|
||||
ret->data.basic.id = val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DOCUMENT("Make an array-type structured object out of a string");
|
||||
inline SDObject *makeSDArray(const char *name)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ std::string DoStringise(const ResourceId &el)
|
||||
return StringFormat::Fmt("ResourceId::%llu", el);
|
||||
}
|
||||
|
||||
BASIC_TYPE_SERIALISE_STRINGIFY(ResourceId, (uint64_t &)el, SDBasic::UnsignedInteger, 8);
|
||||
BASIC_TYPE_SERIALISE_STRINGIFY(ResourceId, (uint64_t &)el, SDBasic::ResourceId, 8);
|
||||
|
||||
INSTANTIATE_SERIALISE_TYPE(ResourceId);
|
||||
|
||||
|
||||
@@ -3761,10 +3761,7 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in
|
||||
buf->type.basetype = SDBasic::Struct;
|
||||
buf->type.byteSize = sizeof(D3D12BufferLocation);
|
||||
|
||||
uint64_t bufid;
|
||||
memcpy(&bufid, &id, sizeof(bufid));
|
||||
|
||||
buf->AddChild(makeSDObject("Buffer", bufid));
|
||||
buf->AddChild(makeSDObject("Buffer", id));
|
||||
buf->AddChild(makeSDObject("Offset", offs));
|
||||
|
||||
buf->data.children[0]->type.flags |= SDTypeFlags::HasCustomString;
|
||||
@@ -3810,10 +3807,7 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in
|
||||
buf->type.basetype = SDBasic::Struct;
|
||||
buf->type.byteSize = sizeof(D3D12BufferLocation);
|
||||
|
||||
uint64_t bufid;
|
||||
memcpy(&bufid, &id, sizeof(bufid));
|
||||
|
||||
buf->AddChild(makeSDObject("Buffer", bufid));
|
||||
buf->AddChild(makeSDObject("Buffer", id));
|
||||
buf->AddChild(makeSDObject("Offset", offs));
|
||||
|
||||
buf->data.children[0]->type.flags |= SDTypeFlags::HasCustomString;
|
||||
@@ -3866,10 +3860,7 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in
|
||||
buf->type.basetype = SDBasic::Struct;
|
||||
buf->type.byteSize = sizeof(D3D12BufferLocation);
|
||||
|
||||
uint64_t bufid;
|
||||
memcpy(&bufid, &id, sizeof(bufid));
|
||||
|
||||
buf->AddChild(makeSDObject("Buffer", bufid));
|
||||
buf->AddChild(makeSDObject("Buffer", id));
|
||||
buf->AddChild(makeSDObject("Offset", offs));
|
||||
|
||||
buf->data.children[0]->type.flags |= SDTypeFlags::HasCustomString;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<DisplayString Condition="type.basetype == SDBasic::Float">{name} = {data.basic.d}</DisplayString>
|
||||
<DisplayString Condition="type.basetype == SDBasic::Boolean">{name} = {data.basic.b}</DisplayString>
|
||||
<DisplayString Condition="type.basetype == SDBasic::Character">{name} = {data.basic.c}</DisplayString>
|
||||
<DisplayString Condition="type.basetype == SDBasic::ResourceId">{name} = {data.basic.id}</DisplayString>
|
||||
<DisplayString Condition="type.basetype == SDBasic::Array">{name} = {type.name}[]</DisplayString>
|
||||
<DisplayString>SDObject: {type.name} {name}</DisplayString>
|
||||
<Expand>
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include "3rdparty/pugixml/pugixml.hpp"
|
||||
|
||||
static const char *typeNames[] = {
|
||||
"chunk", "struct", "array", "null", "buffer", "string",
|
||||
"enum", "uint", "int", "float", "bool", "char",
|
||||
"chunk", "struct", "array", "null", "buffer", "string", "enum",
|
||||
"uint", "int", "float", "bool", "char", "ResourceId",
|
||||
};
|
||||
|
||||
template <typename inttype>
|
||||
@@ -190,7 +190,8 @@ static void Obj2XML(pugi::xml_node &parent, SDObject &child)
|
||||
obj.append_attribute("typename") = child.type.name.c_str();
|
||||
|
||||
if(child.type.basetype == SDBasic::UnsignedInteger ||
|
||||
child.type.basetype == SDBasic::SignedInteger || child.type.basetype == SDBasic::Float)
|
||||
child.type.basetype == SDBasic::SignedInteger || child.type.basetype == SDBasic::Float ||
|
||||
child.type.basetype == SDBasic::ResourceId)
|
||||
{
|
||||
obj.append_attribute("width") = child.type.byteSize;
|
||||
}
|
||||
@@ -240,6 +241,7 @@ static void Obj2XML(pugi::xml_node &parent, SDObject &child)
|
||||
|
||||
switch(child.type.basetype)
|
||||
{
|
||||
case SDBasic::ResourceId:
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: obj.text() = child.data.basic.u; break;
|
||||
case SDBasic::SignedInteger: obj.text() = child.data.basic.i; break;
|
||||
@@ -404,8 +406,8 @@ static SDObject *XML2Obj(pugi::xml_node &obj)
|
||||
}
|
||||
}
|
||||
|
||||
if(ret->type.basetype == SDBasic::UnsignedInteger ||
|
||||
ret->type.basetype == SDBasic::SignedInteger || ret->type.basetype == SDBasic::Float)
|
||||
if(ret->type.basetype == SDBasic::UnsignedInteger || ret->type.basetype == SDBasic::SignedInteger ||
|
||||
ret->type.basetype == SDBasic::Float || ret->type.basetype == SDBasic::ResourceId)
|
||||
{
|
||||
ret->type.byteSize = obj.attribute("width").as_uint();
|
||||
}
|
||||
@@ -460,6 +462,7 @@ static SDObject *XML2Obj(pugi::xml_node &obj)
|
||||
|
||||
switch(ret->type.basetype)
|
||||
{
|
||||
case SDBasic::ResourceId:
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: ret->data.basic.u = obj.text().as_ullong(); break;
|
||||
case SDBasic::SignedInteger: ret->data.basic.i = obj.text().as_llong(); break;
|
||||
|
||||
@@ -668,6 +668,7 @@ void DoSerialise(SerialiserType &ser, SDObject *el)
|
||||
}
|
||||
case SDBasic::Boolean: ser.Serialise("", el->data.basic.b); break;
|
||||
case SDBasic::Character: ser.Serialise("", el->data.basic.c); break;
|
||||
case SDBasic::ResourceId: ser.Serialise("", el->data.basic.id); break;
|
||||
case SDBasic::UnsignedInteger:
|
||||
if(el->type.byteSize == 1)
|
||||
{
|
||||
|
||||
@@ -1338,6 +1338,7 @@ public:
|
||||
case SDBasic::Null: RDCFATAL("Cannot call SerialiseValue for type %d!", type); break;
|
||||
case SDBasic::String: RDCFATAL("eString should be specialised!"); break;
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::ResourceId:
|
||||
case SDBasic::UnsignedInteger:
|
||||
if(byteSize == 1)
|
||||
current.data.basic.u = (uint64_t)(uint8_t)el;
|
||||
@@ -1634,12 +1635,27 @@ BASIC_TYPE_SERIALISE(bool, el, SDBasic::Boolean, 1);
|
||||
|
||||
BASIC_TYPE_SERIALISE(char, el, SDBasic::Character, 1);
|
||||
|
||||
BASIC_TYPE_SERIALISE(char *, el, SDBasic::String, 0);
|
||||
BASIC_TYPE_SERIALISE(const char *, el, SDBasic::String, 0);
|
||||
template <>
|
||||
inline const char *TypeName<char *>()
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
template <class SerialiserType>
|
||||
void DoSerialise(SerialiserType &ser, char *&el)
|
||||
{
|
||||
ser.SerialiseValue(SDBasic::String, 0, el);
|
||||
}
|
||||
|
||||
// these are special because we give them a typename of 'string' for both:
|
||||
// BASIC_TYPE_SERIALISE(rdcstr, el, SDBasic::String, 0);
|
||||
// BASIC_TYPE_SERIALISE(std::string, el, SDBasic::String, 0);
|
||||
template <>
|
||||
inline const char *TypeName<const char *>()
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
template <class SerialiserType>
|
||||
void DoSerialise(SerialiserType &ser, const char *&el)
|
||||
{
|
||||
ser.SerialiseValue(SDBasic::String, 0, el);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const char *TypeName<std::string>()
|
||||
|
||||
Reference in New Issue
Block a user