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:
baldurk
2018-02-15 10:21:52 +00:00
parent a1c104f6f8
commit 64406b47a3
9 changed files with 109 additions and 71 deletions
+2 -2
View File
@@ -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;
+50 -46
View File
@@ -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
+22
View File
@@ -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)
{
+1 -1
View File
@@ -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;
+1
View File
@@ -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>
+8 -5
View File
@@ -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;
+1
View File
@@ -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)
{
+21 -5
View File
@@ -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>()