diff --git a/qrenderdoc/Code/Interface/CommonPipelineState.h b/qrenderdoc/Code/Interface/CommonPipelineState.h index e740e5d38..d942e82a6 100644 --- a/qrenderdoc/Code/Interface/CommonPipelineState.h +++ b/qrenderdoc/Code/Interface/CommonPipelineState.h @@ -32,6 +32,7 @@ struct ICaptureContext; DOCUMENT("Information about a single resource bound to a slot in an API-specific way."); struct BoundResource { + DOCUMENT(""); BoundResource() { Id = ResourceId(); @@ -47,6 +48,23 @@ struct BoundResource typeHint = CompType::Typeless; } + bool operator==(const BoundResource &o) const + { + return Id == o.Id && HighestMip == o.HighestMip && FirstSlice == o.FirstSlice && + typeHint == o.typeHint; + } + bool operator<(const BoundResource &o) const + { + if(Id != o.Id) + return Id < o.Id; + if(HighestMip != o.HighestMip) + return HighestMip < o.HighestMip; + if(FirstSlice != o.FirstSlice) + return FirstSlice < o.FirstSlice; + if(typeHint != o.typeHint) + return typeHint < o.typeHint; + return false; + } DOCUMENT("A :class:`~renderdoc.ResourceId` identifying the bound resource."); ResourceId Id; DOCUMENT("For textures, the highest mip level available on this binding, or -1 for all mips"); @@ -66,6 +84,7 @@ support resource arrays, there will only be one bound resource. )"); struct BoundResourceArray { + DOCUMENT(""); BoundResourceArray() = default; BoundResourceArray(BindpointMap b) : BindPoint(b) {} BoundResourceArray(BindpointMap b, const rdcarray &r) : BindPoint(b), Resources(r) @@ -88,6 +107,21 @@ DECLARE_REFLECTION_STRUCT(BoundResourceArray); DOCUMENT("Information about a single vertex or index buffer binding."); struct BoundBuffer { + DOCUMENT(""); + bool operator==(const BoundBuffer &o) const + { + return Buffer == o.Buffer && ByteOffset == o.ByteOffset && ByteStride == o.ByteStride; + } + bool operator<(const BoundBuffer &o) const + { + if(Buffer != o.Buffer) + return Buffer < o.Buffer; + if(ByteOffset != o.ByteOffset) + return ByteOffset < o.ByteOffset; + if(ByteStride != o.ByteStride) + return ByteStride < o.ByteStride; + return false; + } DOCUMENT("A :class:`~renderdoc.ResourceId` identifying the buffer."); ResourceId Buffer; DOCUMENT("The offset in bytes from the start of the buffer to the data."); @@ -114,6 +148,38 @@ DECLARE_REFLECTION_STRUCT(BoundCBuffer); DOCUMENT("Information about a vertex input attribute feeding the vertex shader."); struct VertexInputAttribute { + DOCUMENT(""); + bool operator==(const VertexInputAttribute &o) const + { + return Name == o.Name && VertexBuffer == o.VertexBuffer && + RelativeByteOffset == o.RelativeByteOffset && PerInstance == o.PerInstance && + InstanceRate == o.InstanceRate && Format == o.Format && + !memcmp(&GenericValue, &o.GenericValue, sizeof(GenericValue)) && + GenericEnabled == o.GenericEnabled && Used == o.Used; + } + bool operator<(const VertexInputAttribute &o) const + { + if(Name != o.Name) + return Name < o.Name; + if(VertexBuffer != o.VertexBuffer) + return VertexBuffer < o.VertexBuffer; + if(RelativeByteOffset != o.RelativeByteOffset) + return RelativeByteOffset < o.RelativeByteOffset; + if(PerInstance != o.PerInstance) + return PerInstance < o.PerInstance; + if(InstanceRate != o.InstanceRate) + return InstanceRate < o.InstanceRate; + if(Format != o.Format) + return Format < o.Format; + if(memcmp(&GenericValue, &o.GenericValue, sizeof(GenericValue)) < 0) + return true; + if(GenericEnabled != o.GenericEnabled) + return GenericEnabled < o.GenericEnabled; + if(Used != o.Used) + return Used < o.Used; + return false; + } + DOCUMENT("The name of this input. This may be a variable name or a semantic name."); rdcstr Name; DOCUMENT("The index of the vertex buffer used to provide this attribute."); diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h index bbc0dc5e5..e6134301e 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.h +++ b/qrenderdoc/Code/Interface/PersistantConfig.h @@ -31,8 +31,23 @@ DOCUMENT("Describes an external program that can be used to disassemble SPIR-V."); struct SPIRVDisassembler { + DOCUMENT(""); SPIRVDisassembler() {} VARIANT_CAST(SPIRVDisassembler); + bool operator==(const SPIRVDisassembler &o) const + { + return name == o.name && executable == o.executable && args == o.args; + } + bool operator<(const SPIRVDisassembler &o) const + { + if(name != o.name) + return name < o.name; + if(executable != o.executable) + return executable < o.executable; + if(args != o.args) + return args < o.args; + return false; + } DOCUMENT("The human-readable name of the program."); rdcstr name; diff --git a/renderdoc/api/replay/basic_types.h b/renderdoc/api/replay/basic_types.h index 9f52b4674..eacde46bb 100644 --- a/renderdoc/api/replay/basic_types.h +++ b/renderdoc/api/replay/basic_types.h @@ -58,6 +58,13 @@ struct rdcpair A first; B second; + bool operator==(const rdcpair &o) const { return first == o.first && second == o.second; } + bool operator<(const rdcpair &o) const + { + if(first != o.first) + return first < o.first; + return second < o.second; + } operator std::tuple() { return std::tie(first, second); } }; @@ -97,12 +104,35 @@ struct ItemHelper for(int32_t i = 0; i < count; i++) new(first + i) T(); } + + static bool equalRange(T *a, T *b, int32_t count) + { + for(int32_t i = 0; i < count; i++) + if(!(a[i] == b[i])) + return false; + + return true; + } + + static bool lessthanRange(T *a, T *b, int32_t count) + { + for(int32_t i = 0; i < count; i++) + if(a[i] < b[i]) + return true; + + return false; + } }; template struct ItemHelper { static void initRange(T *first, int32_t itemCount) { memset(first, 0, itemCount * sizeof(T)); } + static bool equalRange(T *a, T *b, int32_t count) { return !memcmp(a, b, count * sizeof(T)); } + static bool lessthanRange(T *a, T *b, int32_t count) + { + return memcmp(a, b, count * sizeof(T)) < 0; + } }; template @@ -156,6 +186,16 @@ public: // simple accessors T &operator[](size_t i) { return elems[i]; } const T &operator[](size_t i) const { return elems[i]; } + bool operator==(const rdcarray &o) const + { + return usedCount == o.usedCount && ItemHelper::equalRange(elems, o.elems, usedCount); + } + bool operator<(const rdcarray &o) const + { + if(usedCount != o.usedCount) + return usedCount < o.usedCount; + return ItemHelper::lessthanRange(elems, o.elems, usedCount); + } T *data() { return elems; } const T *data() const { return elems; } T *begin() { return elems ? elems : end(); } diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index e41f96f9f..1ced21c17 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -482,6 +482,23 @@ struct EnvironmentModification : mod(m), sep(s), name(n), value(v) { } + DOCUMENT(""); + bool operator==(const EnvironmentModification &o) const + { + return mod == o.mod && sep == o.sep && name == o.name && value == o.value; + } + bool operator<(const EnvironmentModification &o) const + { + if(!(mod == o.mod)) + return mod < o.mod; + if(!(sep == o.sep)) + return sep < o.sep; + if(!(name == o.name)) + return name < o.name; + if(!(value == o.value)) + return value < o.value; + return false; + } DOCUMENT("The :class:`modification ` to use."); EnvMod mod; DOCUMENT("The :class:`separator ` to use if needed."); @@ -497,6 +514,24 @@ DECLARE_REFLECTION_STRUCT(EnvironmentModification); DOCUMENT("The format for a capture file either supported to read from, or export to"); struct CaptureFileFormat { + DOCUMENT(""); + bool operator==(const CaptureFileFormat &o) const + { + return name == o.name && description == o.description && openSupported == o.openSupported && + convertSupported == o.convertSupported; + } + bool operator<(const CaptureFileFormat &o) const + { + if(!(name == o.name)) + return name < o.name; + if(!(description == o.description)) + return description < o.description; + if(!(openSupported == o.openSupported)) + return openSupported < o.openSupported; + if(!(convertSupported == o.convertSupported)) + return convertSupported < o.convertSupported; + return false; + } DOCUMENT("The name of the format as a single minimal string, e.g. ``rdc``."); rdcstr name; diff --git a/renderdoc/api/replay/d3d11_pipestate.h b/renderdoc/api/replay/d3d11_pipestate.h index 3cd8ba92b..cf12daace 100644 --- a/renderdoc/api/replay/d3d11_pipestate.h +++ b/renderdoc/api/replay/d3d11_pipestate.h @@ -37,6 +37,31 @@ DOCUMENT(R"(Describes a single D3D11 input layout element for one vertex input. )"); struct Layout { + DOCUMENT(""); + bool operator==(const Layout &o) const + { + return SemanticName == o.SemanticName && SemanticIndex == o.SemanticIndex && + Format == o.Format && InputSlot == o.InputSlot && ByteOffset == o.ByteOffset && + PerInstance == o.PerInstance && InstanceDataStepRate == o.InstanceDataStepRate; + } + bool operator<(const Layout &o) const + { + if(!(SemanticName == o.SemanticName)) + return SemanticName < o.SemanticName; + if(!(SemanticIndex == o.SemanticIndex)) + return SemanticIndex < o.SemanticIndex; + if(!(Format == o.Format)) + return Format < o.Format; + if(!(InputSlot == o.InputSlot)) + return InputSlot < o.InputSlot; + if(!(ByteOffset == o.ByteOffset)) + return ByteOffset < o.ByteOffset; + if(!(PerInstance == o.PerInstance)) + return PerInstance < o.PerInstance; + if(!(InstanceDataStepRate == o.InstanceDataStepRate)) + return InstanceDataStepRate < o.InstanceDataStepRate; + return false; + } DOCUMENT("The semantic name for this input."); rdcstr SemanticName; @@ -75,6 +100,21 @@ with the next instance data. DOCUMENT("Describes a single D3D11 vertex buffer binding.") struct VB { + DOCUMENT(""); + bool operator==(const VB &o) const + { + return Buffer == o.Buffer && Stride == o.Stride && Offset == o.Offset; + } + bool operator<(const VB &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Stride == o.Stride)) + return Stride < o.Stride; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer bound to this slot."); ResourceId Buffer; @@ -117,6 +157,48 @@ struct IA DOCUMENT("Describes the details of a D3D11 resource view - any one of UAV, SRV, RTV or DSV."); struct View { + DOCUMENT(""); + bool operator==(const View &o) const + { + return Object == o.Object && Resource == o.Resource && Type == o.Type && Format == o.Format && + Structured == o.Structured && BufferStructCount == o.BufferStructCount && + ElementSize == o.ElementSize && FirstElement == o.FirstElement && + NumElements == o.NumElements && Flags == o.Flags && HighestMip == o.HighestMip && + NumMipLevels == o.NumMipLevels && ArraySize == o.ArraySize && + FirstArraySlice == o.FirstArraySlice; + } + bool operator<(const View &o) const + { + if(!(Object == o.Object)) + return Object < o.Object; + if(!(Resource == o.Resource)) + return Resource < o.Resource; + if(!(Type == o.Type)) + return Type < o.Type; + if(!(Format == o.Format)) + return Format < o.Format; + if(!(Structured == o.Structured)) + return Structured < o.Structured; + if(!(BufferStructCount == o.BufferStructCount)) + return BufferStructCount < o.BufferStructCount; + if(!(ElementSize == o.ElementSize)) + return ElementSize < o.ElementSize; + if(!(FirstElement == o.FirstElement)) + return FirstElement < o.FirstElement; + if(!(NumElements == o.NumElements)) + return NumElements < o.NumElements; + if(!(Flags == o.Flags)) + return Flags < o.Flags; + if(!(HighestMip == o.HighestMip)) + return HighestMip < o.HighestMip; + if(!(NumMipLevels == o.NumMipLevels)) + return NumMipLevels < o.NumMipLevels; + if(!(ArraySize == o.ArraySize)) + return ArraySize < o.ArraySize; + if(!(FirstArraySlice == o.FirstArraySlice)) + return FirstArraySlice < o.FirstArraySlice; + return false; + } DOCUMENT("The :class:`ResourceId` of the view itself."); ResourceId Object; @@ -162,6 +244,48 @@ or the structured buffer element size, as appropriate. DOCUMENT("Describes a sampler state object."); struct Sampler { + DOCUMENT(""); + bool operator==(const Sampler &o) const + { + return Samp == o.Samp && AddressU == o.AddressU && AddressV == o.AddressV && + AddressW == o.AddressW && BorderColor[0] == o.BorderColor[0] && + BorderColor[1] == o.BorderColor[1] && BorderColor[2] == o.BorderColor[2] && + BorderColor[3] == o.BorderColor[3] && Comparison == o.Comparison && Filter == o.Filter && + MaxAniso == o.MaxAniso && MaxLOD == o.MaxLOD && MinLOD == o.MinLOD && + MipLODBias == o.MipLODBias; + } + bool operator<(const Sampler &o) const + { + if(!(Samp == o.Samp)) + return Samp < o.Samp; + if(!(AddressU == o.AddressU)) + return AddressU < o.AddressU; + if(!(AddressV == o.AddressV)) + return AddressV < o.AddressV; + if(!(AddressW == o.AddressW)) + return AddressW < o.AddressW; + if(!(BorderColor[0] == o.BorderColor[0])) + return BorderColor[0] < o.BorderColor[0]; + if(!(BorderColor[1] == o.BorderColor[1])) + return BorderColor[1] < o.BorderColor[1]; + if(!(BorderColor[2] == o.BorderColor[2])) + return BorderColor[2] < o.BorderColor[2]; + if(!(BorderColor[3] == o.BorderColor[3])) + return BorderColor[3] < o.BorderColor[3]; + if(!(Comparison == o.Comparison)) + return Comparison < o.Comparison; + if(!(Filter == o.Filter)) + return Filter < o.Filter; + if(!(MaxAniso == o.MaxAniso)) + return MaxAniso < o.MaxAniso; + if(!(MaxLOD == o.MaxLOD)) + return MaxLOD < o.MaxLOD; + if(!(MinLOD == o.MinLOD)) + return MinLOD < o.MinLOD; + if(!(MipLODBias == o.MipLODBias)) + return MipLODBias < o.MipLODBias; + return false; + } DOCUMENT("The :class:`ResourceId` of the sampler state object."); ResourceId Samp; DOCUMENT("The :class:`AddressMode` in the U direction."); @@ -200,6 +324,21 @@ struct Sampler DOCUMENT("Describes a constant buffer binding."); struct CBuffer { + DOCUMENT(""); + bool operator==(const CBuffer &o) const + { + return Buffer == o.Buffer && VecOffset == o.VecOffset && VecCount == o.VecCount; + } + bool operator<(const CBuffer &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(VecOffset == o.VecOffset)) + return VecOffset < o.VecOffset; + if(!(VecCount == o.VecCount)) + return VecCount < o.VecCount; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer."); ResourceId Buffer; @@ -251,6 +390,16 @@ mapping data. DOCUMENT("Describes a binding on the D3D11 stream-out stage."); struct SOBind { + DOCUMENT(""); + bool operator==(const SOBind &o) const { return Buffer == o.Buffer && Offset == o.Offset; } + bool operator<(const SOBind &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer."); ResourceId Buffer; @@ -268,6 +417,28 @@ struct SO DOCUMENT("Describes a single D3D11 viewport."); struct Viewport { + DOCUMENT(""); + bool operator==(const Viewport &o) const + { + return X == o.X && Y == o.Y && Width == o.Width && Height == o.Height && + MinDepth == o.MinDepth && MaxDepth == o.MaxDepth; + } + bool operator<(const Viewport &o) const + { + if(!(X == o.X)) + return X < o.X; + if(!(Y == o.Y)) + return Y < o.Y; + if(!(Width == o.Width)) + return Width < o.Width; + if(!(Height == o.Height)) + return Height < o.Height; + if(!(MinDepth == o.MinDepth)) + return MinDepth < o.MinDepth; + if(!(MaxDepth == o.MaxDepth)) + return MaxDepth < o.MaxDepth; + return false; + } Viewport() = default; Viewport(float TX, float TY, float W, float H, float MN, float MX, bool en) : X(TX), Y(TY), Width(W), Height(H), MinDepth(MN), MaxDepth(MX), Enabled(en) @@ -293,6 +464,26 @@ struct Viewport DOCUMENT("Describes a single D3D11 scissor rect."); struct Scissor { + DOCUMENT(""); + bool operator==(const Scissor &o) const + { + return left == o.left && top == o.top && right == o.right && bottom == o.bottom && + Enabled == o.Enabled; + } + bool operator<(const Scissor &o) const + { + if(!(left == o.left)) + return left < o.left; + if(!(top == o.top)) + return top < o.top; + if(!(right == o.right)) + return right < o.right; + if(!(bottom == o.bottom)) + return bottom < o.bottom; + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + return false; + } Scissor() = default; Scissor(int l, int t, int r, int b, bool en) : left(l), top(t), right(r), bottom(b), Enabled(en) { @@ -404,6 +595,21 @@ struct DepthStencilState DOCUMENT("Describes the details of a D3D11 blend operation."); struct BlendEquation { + DOCUMENT(""); + bool operator==(const BlendEquation &o) const + { + return Source == o.Source && Destination == o.Destination && Operation == o.Operation; + } + bool operator<(const BlendEquation &o) const + { + if(!(Source == o.Source)) + return Source < o.Source; + if(!(Destination == o.Destination)) + return Destination < o.Destination; + if(!(Operation == o.Operation)) + return Operation < o.Operation; + return false; + } DOCUMENT("The :class:`BlendMultiplier` for the source blend value."); BlendMultiplier Source = BlendMultiplier::One; DOCUMENT("The :class:`BlendMultiplier` for the destination blend value."); @@ -415,6 +621,29 @@ struct BlendEquation DOCUMENT("Describes the blend configuration for a given D3D11 target."); struct Blend { + DOCUMENT(""); + bool operator==(const Blend &o) const + { + return Enabled == o.Enabled && LogicEnabled == o.LogicEnabled && m_Blend == o.m_Blend && + m_AlphaBlend == o.m_AlphaBlend && Logic == o.Logic && WriteMask == o.WriteMask; + } + bool operator<(const Blend &o) const + { + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + if(!(LogicEnabled == o.LogicEnabled)) + return LogicEnabled < o.LogicEnabled; + if(!(m_Blend == o.m_Blend)) + return m_Blend < o.m_Blend; + if(!(m_AlphaBlend == o.m_AlphaBlend)) + return m_AlphaBlend < o.m_AlphaBlend; + if(!(Logic == o.Logic)) + return Logic < o.Logic; + if(!(WriteMask == o.WriteMask)) + return WriteMask < o.WriteMask; + return false; + } + DOCUMENT("A :class:`D3D11_BlendEquation` describing the blending for colour values."); BlendEquation m_Blend; DOCUMENT("A :class:`D3D11_BlendEquation` describing the blending for alpha values."); diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index bb3630a85..48c296570 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -36,6 +36,31 @@ DOCUMENT(R"(Describes a single D3D12 input layout element for one vertex input. )"); struct Layout { + DOCUMENT(""); + bool operator==(const Layout &o) const + { + return SemanticName == o.SemanticName && SemanticIndex == o.SemanticIndex && + Format == o.Format && InputSlot == o.InputSlot && ByteOffset == o.ByteOffset && + PerInstance == o.PerInstance && InstanceDataStepRate == o.InstanceDataStepRate; + } + bool operator<(const Layout &o) const + { + if(!(SemanticName == o.SemanticName)) + return SemanticName < o.SemanticName; + if(!(SemanticIndex == o.SemanticIndex)) + return SemanticIndex < o.SemanticIndex; + if(!(Format == o.Format)) + return Format < o.Format; + if(!(InputSlot == o.InputSlot)) + return InputSlot < o.InputSlot; + if(!(ByteOffset == o.ByteOffset)) + return ByteOffset < o.ByteOffset; + if(!(PerInstance == o.PerInstance)) + return PerInstance < o.PerInstance; + if(!(InstanceDataStepRate == o.InstanceDataStepRate)) + return InstanceDataStepRate < o.InstanceDataStepRate; + return false; + } DOCUMENT("The semantic name for this input."); rdcstr SemanticName; @@ -74,6 +99,23 @@ with the next instance data. DOCUMENT("Describes a single D3D12 vertex buffer binding.") struct VB { + DOCUMENT(""); + bool operator==(const VB &o) const + { + return Buffer == o.Buffer && Stride == o.Stride && Size == o.Size && Offset == o.Offset; + } + bool operator<(const VB &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Stride == o.Stride)) + return Stride < o.Stride; + if(!(Size == o.Size)) + return Size < o.Size; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer bound to this slot."); ResourceId Buffer; @@ -124,6 +166,58 @@ If the value is 0, strip cutting is disabled. DOCUMENT("Describes the details of a D3D12 resource view - any one of UAV, SRV, RTV or DSV."); struct View { + DOCUMENT(""); + bool operator==(const View &o) const + { + return Resource == o.Resource && Type == o.Type && Format == o.Format && + swizzle[0] == o.swizzle[0] && swizzle[1] == o.swizzle[1] && swizzle[2] == o.swizzle[2] && + swizzle[3] == o.swizzle[3] && BufferFlags == o.BufferFlags && + BufferStructCount == o.BufferStructCount && ElementSize == o.ElementSize && + FirstElement == o.FirstElement && NumElements == o.NumElements && + CounterResource == o.CounterResource && CounterByteOffset == o.CounterByteOffset && + HighestMip == o.HighestMip && NumMipLevels == o.NumMipLevels && + ArraySize == o.ArraySize && FirstArraySlice == o.FirstArraySlice; + } + bool operator<(const View &o) const + { + if(!(Resource == o.Resource)) + return Resource < o.Resource; + if(!(Type == o.Type)) + return Type < o.Type; + if(!(Format == o.Format)) + return Format < o.Format; + if(!(swizzle[0] == o.swizzle[0])) + return swizzle[0] < o.swizzle[0]; + if(!(swizzle[1] == o.swizzle[1])) + return swizzle[1] < o.swizzle[1]; + if(!(swizzle[2] == o.swizzle[2])) + return swizzle[2] < o.swizzle[2]; + if(!(swizzle[3] == o.swizzle[3])) + return swizzle[3] < o.swizzle[3]; + if(!(BufferFlags == o.BufferFlags)) + return BufferFlags < o.BufferFlags; + if(!(BufferStructCount == o.BufferStructCount)) + return BufferStructCount < o.BufferStructCount; + if(!(ElementSize == o.ElementSize)) + return ElementSize < o.ElementSize; + if(!(FirstElement == o.FirstElement)) + return FirstElement < o.FirstElement; + if(!(NumElements == o.NumElements)) + return NumElements < o.NumElements; + if(!(CounterResource == o.CounterResource)) + return CounterResource < o.CounterResource; + if(!(CounterByteOffset == o.CounterByteOffset)) + return CounterByteOffset < o.CounterByteOffset; + if(!(HighestMip == o.HighestMip)) + return HighestMip < o.HighestMip; + if(!(NumMipLevels == o.NumMipLevels)) + return NumMipLevels < o.NumMipLevels; + if(!(ArraySize == o.ArraySize)) + return ArraySize < o.ArraySize; + if(!(FirstArraySlice == o.FirstArraySlice)) + return FirstArraySlice < o.FirstArraySlice; + return false; + } DOCUMENT("``True`` if this view is a root parameter (i.e. not in a table)."); bool Immediate = false; DOCUMENT("The index in the original root signature that this descriptor came from."); @@ -176,6 +270,52 @@ or the structured buffer element size, as appropriate. DOCUMENT("Describes the details of a sampler descriptor."); struct Sampler { + DOCUMENT(""); + bool operator==(const Sampler &o) const + { + return Immediate == o.Immediate && RootElement == o.RootElement && TableIndex == o.TableIndex && + AddressU == o.AddressU && AddressV == o.AddressV && AddressW == o.AddressW && + BorderColor[0] == o.BorderColor[0] && BorderColor[1] == o.BorderColor[1] && + BorderColor[2] == o.BorderColor[2] && BorderColor[3] == o.BorderColor[3] && + Comparison == o.Comparison && Filter == o.Filter && MaxAniso == o.MaxAniso && + MaxLOD == o.MaxLOD && MinLOD == o.MinLOD && MipLODBias == o.MipLODBias; + } + bool operator<(const Sampler &o) const + { + if(!(Immediate == o.Immediate)) + return Immediate < o.Immediate; + if(!(RootElement == o.RootElement)) + return RootElement < o.RootElement; + if(!(TableIndex == o.TableIndex)) + return TableIndex < o.TableIndex; + if(!(AddressU == o.AddressU)) + return AddressU < o.AddressU; + if(!(AddressV == o.AddressV)) + return AddressV < o.AddressV; + if(!(AddressW == o.AddressW)) + return AddressW < o.AddressW; + if(!(BorderColor[0] == o.BorderColor[0])) + return BorderColor[0] < o.BorderColor[0]; + if(!(BorderColor[1] == o.BorderColor[1])) + return BorderColor[1] < o.BorderColor[1]; + if(!(BorderColor[2] == o.BorderColor[2])) + return BorderColor[2] < o.BorderColor[2]; + if(!(BorderColor[3] == o.BorderColor[3])) + return BorderColor[3] < o.BorderColor[3]; + if(!(Comparison == o.Comparison)) + return Comparison < o.Comparison; + if(!(Filter == o.Filter)) + return Filter < o.Filter; + if(!(MaxAniso == o.MaxAniso)) + return MaxAniso < o.MaxAniso; + if(!(MaxLOD == o.MaxLOD)) + return MaxLOD < o.MaxLOD; + if(!(MinLOD == o.MinLOD)) + return MinLOD < o.MinLOD; + if(!(MipLODBias == o.MipLODBias)) + return MipLODBias < o.MipLODBias; + return false; + } DOCUMENT("``True`` if this view is a static sampler (i.e. not in a table)."); bool Immediate = 0; DOCUMENT("The index in the original root signature that this descriptor came from."); @@ -219,6 +359,31 @@ struct Sampler DOCUMENT("Describes the details of a constant buffer view descriptor."); struct CBuffer { + DOCUMENT(""); + bool operator==(const CBuffer &o) const + { + return Immediate == o.Immediate && RootElement == o.RootElement && TableIndex == o.TableIndex && + Buffer == o.Buffer && Offset == o.Offset && ByteSize == o.ByteSize && + RootValues == o.RootValues; + } + bool operator<(const CBuffer &o) const + { + if(!(Immediate == o.Immediate)) + return Immediate < o.Immediate; + if(!(RootElement == o.RootElement)) + return RootElement < o.RootElement; + if(!(TableIndex == o.TableIndex)) + return TableIndex < o.TableIndex; + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + if(!(ByteSize == o.ByteSize)) + return ByteSize < o.ByteSize; + if(!(RootValues == o.RootValues)) + return RootValues < o.RootValues; + return false; + } DOCUMENT("``True`` if this view is a root constant (i.e. not in a table)."); bool Immediate = false; DOCUMENT("The index in the original root signature that this descriptor came from."); @@ -242,6 +407,24 @@ struct CBuffer DOCUMENT("Contains all of the registers in a single register space mapped to by a root signature."); struct RegisterSpace { + DOCUMENT(""); + bool operator==(const RegisterSpace &o) const + { + return ConstantBuffers == o.ConstantBuffers && Samplers == o.Samplers && SRVs == o.SRVs && + UAVs == o.UAVs; + } + bool operator<(const RegisterSpace &o) const + { + if(!(ConstantBuffers == o.ConstantBuffers)) + return ConstantBuffers < o.ConstantBuffers; + if(!(Samplers == o.Samplers)) + return Samplers < o.Samplers; + if(!(SRVs == o.SRVs)) + return SRVs < o.SRVs; + if(!(UAVs == o.UAVs)) + return UAVs < o.UAVs; + return false; + } DOCUMENT("List of :class:`D3D12_CBuffer` containing the constant buffers."); rdcarray ConstantBuffers; DOCUMENT("List of :class:`D3D12_Sampler` containing the samplers."); @@ -275,6 +458,26 @@ mapping data. DOCUMENT("Describes a binding on the D3D12 stream-out stage."); struct SOBind { + DOCUMENT(""); + bool operator==(const SOBind &o) const + { + return Buffer == o.Buffer && Offset == o.Offset && Size == o.Size && + WrittenCountBuffer == o.WrittenCountBuffer && WrittenCountOffset == o.WrittenCountOffset; + } + bool operator<(const SOBind &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + if(!(Size == o.Size)) + return Size < o.Size; + if(!(WrittenCountBuffer == o.WrittenCountBuffer)) + return WrittenCountBuffer < o.WrittenCountBuffer; + if(!(WrittenCountOffset == o.WrittenCountOffset)) + return WrittenCountOffset < o.WrittenCountOffset; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer."); ResourceId Buffer; DOCUMENT( @@ -300,6 +503,28 @@ struct Streamout DOCUMENT("Describes a single D3D12 viewport."); struct Viewport { + DOCUMENT(""); + bool operator==(const Viewport &o) const + { + return X == o.X && Y == o.Y && Width == o.Width && Height == o.Height && + MinDepth == o.MinDepth && MaxDepth == o.MaxDepth; + } + bool operator<(const Viewport &o) const + { + if(!(X == o.X)) + return X < o.X; + if(!(Y == o.Y)) + return Y < o.Y; + if(!(Width == o.Width)) + return Width < o.Width; + if(!(Height == o.Height)) + return Height < o.Height; + if(!(MinDepth == o.MinDepth)) + return MinDepth < o.MinDepth; + if(!(MaxDepth == o.MaxDepth)) + return MaxDepth < o.MaxDepth; + return false; + } Viewport() = default; Viewport(float TX, float TY, float W, float H, float MN, float MX) : X(TX), Y(TY), Width(W), Height(H), MinDepth(MN), MaxDepth(MX) @@ -323,6 +548,23 @@ struct Viewport DOCUMENT("Describes a single D3D12 scissor rect."); struct Scissor { + DOCUMENT(""); + bool operator==(const Scissor &o) const + { + return left == o.left && top == o.top && right == o.right && bottom == o.bottom; + } + bool operator<(const Scissor &o) const + { + if(!(left == o.left)) + return left < o.left; + if(!(top == o.top)) + return top < o.top; + if(!(right == o.right)) + return right < o.right; + if(!(bottom == o.bottom)) + return bottom < o.bottom; + return false; + } Scissor() = default; Scissor(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} DOCUMENT("Top-left X co-ordinate of the viewport."); @@ -427,6 +669,21 @@ struct DepthStencilState DOCUMENT("Describes the details of a D3D12 blend operation."); struct BlendEquation { + DOCUMENT(""); + bool operator==(const BlendEquation &o) const + { + return Source == o.Source && Destination == o.Destination && Operation == o.Operation; + } + bool operator<(const BlendEquation &o) const + { + if(!(Source == o.Source)) + return Source < o.Source; + if(!(Destination == o.Destination)) + return Destination < o.Destination; + if(!(Operation == o.Operation)) + return Operation < o.Operation; + return false; + } DOCUMENT("The :class:`BlendMultiplier` for the source blend value."); BlendMultiplier Source = BlendMultiplier::One; DOCUMENT("The :class:`BlendMultiplier` for the destination blend value."); @@ -438,6 +695,28 @@ struct BlendEquation DOCUMENT("Describes the blend configuration for a given D3D12 target."); struct Blend { + DOCUMENT(""); + bool operator==(const Blend &o) const + { + return Enabled == o.Enabled && LogicEnabled == o.LogicEnabled && m_Blend == o.m_Blend && + m_AlphaBlend == o.m_AlphaBlend && Logic == o.Logic && WriteMask == o.WriteMask; + } + bool operator<(const Blend &o) const + { + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + if(!(LogicEnabled == o.LogicEnabled)) + return LogicEnabled < o.LogicEnabled; + if(!(m_Blend == o.m_Blend)) + return m_Blend < o.m_Blend; + if(!(m_AlphaBlend == o.m_AlphaBlend)) + return m_AlphaBlend < o.m_AlphaBlend; + if(!(Logic == o.Logic)) + return Logic < o.Logic; + if(!(WriteMask == o.WriteMask)) + return WriteMask < o.WriteMask; + return false; + } DOCUMENT("A :class:`D3D12_BlendEquation` describing the blending for colour values."); BlendEquation m_Blend; DOCUMENT("A :class:`D3D12_BlendEquation` describing the blending for alpha values."); @@ -500,6 +779,14 @@ struct OM DOCUMENT("Describes the current state that a sub-resource is in."); struct ResourceState { + DOCUMENT(""); + bool operator==(const ResourceState &o) const { return name == o.name; } + bool operator<(const ResourceState &o) const + { + if(!(name == o.name)) + return name < o.name; + return false; + } DOCUMENT("A human-readable name for the current state."); rdcstr name; }; @@ -507,6 +794,16 @@ struct ResourceState DOCUMENT("Contains the current state of a given resource."); struct ResourceData { + DOCUMENT(""); + bool operator==(const ResourceData &o) const { return id == o.id && states == o.states; } + bool operator<(const ResourceData &o) const + { + if(!(id == o.id)) + return id < o.id; + if(!(states == o.states)) + return states < o.states; + return false; + } DOCUMENT("The :class:`ResourceId` of the resource."); ResourceId id; diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index 8e7a9bbc0..6426d6d9a 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -52,8 +52,25 @@ DECLARE_REFLECTION_STRUCT(FloatVector); DOCUMENT("Properties of a path on a remote filesystem."); struct PathEntry { + DOCUMENT(""); PathEntry() : flags(PathProperty::NoFlags), lastmod(0), size(0) {} PathEntry(const char *fn, PathProperty f) : filename(fn), flags(f), lastmod(0), size(0) {} + bool operator==(const PathEntry &o) const + { + return filename == o.filename && flags == o.flags && lastmod == o.lastmod && size == o.size; + } + bool operator<(const PathEntry &o) const + { + if(!(filename == o.filename)) + return filename < o.filename; + if(!(flags == o.flags)) + return flags < o.flags; + if(!(lastmod == o.lastmod)) + return lastmod < o.lastmod; + if(!(size == o.size)) + return size < o.size; + return false; + } DOCUMENT("The filename of this path. This contains only the filename, not the full path."); rdcstr filename; @@ -102,6 +119,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_ResourceFormatName(const Re DOCUMENT("Description of the format of a resource or element."); struct ResourceFormat { + DOCUMENT(""); ResourceFormat() { type = ResourceFormatType::Undefined; @@ -113,14 +131,28 @@ struct ResourceFormat srgbCorrected = false; } - DOCUMENT("Compares two ``ResourceFormat`` objects for equality."); bool operator==(const ResourceFormat &r) const { return type == r.type && compCount == r.compCount && compByteWidth == r.compByteWidth && compType == r.compType && bgraOrder == r.bgraOrder && srgbCorrected == r.srgbCorrected; } + bool operator<(const ResourceFormat &r) const + { + if(type != r.type) + return type < r.type; + if(compCount != r.compCount) + return compCount < r.compCount; + if(compByteWidth != r.compByteWidth) + return compByteWidth < r.compByteWidth; + if(compType != r.compType) + return compType < r.compType; + if(bgraOrder != r.bgraOrder) + return bgraOrder < r.bgraOrder; + if(srgbCorrected != r.srgbCorrected) + return srgbCorrected < r.srgbCorrected; + return false; + } - DOCUMENT("Compares two ``ResourceFormat`` objects for inequality."); bool operator!=(const ResourceFormat &r) const { return !(*this == r); } DOCUMENT(R"(:return: The name of the format. :rtype: str @@ -159,6 +191,23 @@ DECLARE_REFLECTION_STRUCT(ResourceFormat); DOCUMENT("The details of a texture filter in a sampler."); struct TextureFilter { + DOCUMENT(""); + bool operator==(const TextureFilter &o) const + { + return minify == o.magnify && minify == o.magnify && mip == o.mip && func == o.func; + } + bool operator<(const TextureFilter &o) const + { + if(!(minify == o.magnify)) + return minify < o.magnify; + if(!(minify == o.magnify)) + return minify < o.magnify; + if(!(mip == o.mip)) + return mip < o.mip; + if(!(func == o.func)) + return func < o.func; + return false; + } DOCUMENT("The :class:`FilterMode` to use when minifying the texture."); FilterMode minify = FilterMode::NoFilter; DOCUMENT("The :class:`FilterMode` to use when magnifying the texture."); @@ -174,6 +223,9 @@ DECLARE_REFLECTION_STRUCT(TextureFilter); DOCUMENT("A description of any type of resource."); struct ResourceDescription { + DOCUMENT(""); + bool operator==(const ResourceDescription &o) const { return ID == o.ID; } + bool operator<(const ResourceDescription &o) const { return ID < o.ID; } DOCUMENT("The unique :class:`ResourceId` that identifies this resource."); ResourceId ID; @@ -225,6 +277,21 @@ DECLARE_REFLECTION_STRUCT(ResourceDescription); DOCUMENT("A description of a buffer resource."); struct BufferDescription { + DOCUMENT(""); + bool operator==(const BufferDescription &o) const + { + return ID == o.ID && creationFlags == o.creationFlags && length == o.length; + } + bool operator<(const BufferDescription &o) const + { + if(!(ID == o.ID)) + return ID < o.ID; + if(!(creationFlags == o.creationFlags)) + return creationFlags < o.creationFlags; + if(!(length == o.length)) + return length < o.length; + return false; + } DOCUMENT("The unique :class:`ResourceId` that identifies this buffer."); ResourceId ID; @@ -240,6 +307,47 @@ DECLARE_REFLECTION_STRUCT(BufferDescription); DOCUMENT("A description of a texture resource."); struct TextureDescription { + DOCUMENT(""); + bool operator==(const TextureDescription &o) const + { + return format == o.format && dimension == o.dimension && resType == o.resType && + width == o.width && height == o.height && depth == o.depth && ID == o.ID && + cubemap == o.cubemap && mips == o.mips && arraysize == o.arraysize && + creationFlags == o.creationFlags && msQual == o.msQual && msSamp == o.msSamp && + byteSize == o.byteSize; + } + bool operator<(const TextureDescription &o) const + { + if(!(format == o.format)) + return format < o.format; + if(!(dimension == o.dimension)) + return dimension < o.dimension; + if(!(resType == o.resType)) + return resType < o.resType; + if(!(width == o.width)) + return width < o.width; + if(!(height == o.height)) + return height < o.height; + if(!(depth == o.depth)) + return depth < o.depth; + if(!(ID == o.ID)) + return ID < o.ID; + if(!(cubemap == o.cubemap)) + return cubemap < o.cubemap; + if(!(mips == o.mips)) + return mips < o.mips; + if(!(arraysize == o.arraysize)) + return arraysize < o.arraysize; + if(!(creationFlags == o.creationFlags)) + return creationFlags < o.creationFlags; + if(!(msQual == o.msQual)) + return msQual < o.msQual; + if(!(msSamp == o.msSamp)) + return msSamp < o.msSamp; + if(!(byteSize == o.byteSize)) + return byteSize < o.byteSize; + return false; + } DOCUMENT("The :class:`ResourceFormat` that describes the format of each pixel in the texture."); ResourceFormat format; @@ -288,6 +396,9 @@ DECLARE_REFLECTION_STRUCT(TextureDescription); DOCUMENT("An individual API-level event, generally corresponds one-to-one with an API call."); struct APIEvent { + DOCUMENT(""); + bool operator==(const APIEvent &o) const { return eventID == o.eventID; } + bool operator<(const APIEvent &o) const { return eventID < o.eventID; } DOCUMENT(R"(The API event's Event ID (EID). This is a 1-based count of API events in the capture. The EID is used as a reference point in @@ -323,6 +434,28 @@ DECLARE_REFLECTION_STRUCT(APIEvent); DOCUMENT("A debugging message from the API validation or internal analysis and error detection."); struct DebugMessage { + DOCUMENT(""); + bool operator==(const DebugMessage &o) const + { + return eventID == o.eventID && category == o.category && severity == o.severity && + source == o.source && messageID == o.messageID && description == o.description; + } + bool operator<(const DebugMessage &o) const + { + if(!(eventID == o.eventID)) + return eventID < o.eventID; + if(!(category == o.category)) + return category < o.category; + if(!(severity == o.severity)) + return severity < o.severity; + if(!(source == o.source)) + return source < o.source; + if(!(messageID == o.messageID)) + return messageID < o.messageID; + if(!(description == o.description)) + return description < o.description; + return false; + } DOCUMENT("The :data:`EID ` where this debug message was found."); uint32_t eventID; @@ -774,18 +907,17 @@ DECLARE_REFLECTION_STRUCT(FrameDescription); DOCUMENT("Describes a particular use of a resource at a specific :data:`EID `."); struct EventUsage { + DOCUMENT(""); EventUsage() : eventID(0), usage(ResourceUsage::Unused) {} EventUsage(uint32_t e, ResourceUsage u) : eventID(e), usage(u) {} EventUsage(uint32_t e, ResourceUsage u, ResourceId v) : eventID(e), usage(u), view(v) {} - DOCUMENT("Compares two ``EventUsage`` objects for less-than."); bool operator<(const EventUsage &o) const { - if(eventID != o.eventID) + if(!(eventID == o.eventID)) return eventID < o.eventID; return usage < o.usage; } - DOCUMENT("Compares two ``EventUsage`` objects for equality."); bool operator==(const EventUsage &o) const { return eventID == o.eventID && usage == o.usage; } DOCUMENT("The :data:`EID ` where this usage happened."); uint32_t eventID; @@ -834,7 +966,9 @@ struct DrawcallDescription outputs[i] = ResourceId(); depthOut = ResourceId(); } - + DOCUMENT(""); + bool operator==(const DrawcallDescription &o) const { return eventID == o.eventID; } + bool operator<(const DrawcallDescription &o) const { return eventID < o.eventID; } DOCUMENT("The :data:`EID ` that actually produced the drawcall."); uint32_t eventID; DOCUMENT("A 1-based index of this drawcall relative to other drawcalls."); @@ -1061,9 +1195,9 @@ struct CounterResult DOCUMENT("Compares two ``CounterResult`` objects for less-than."); bool operator<(const CounterResult &o) const { - if(eventID != o.eventID) + if(!(eventID == o.eventID)) return eventID < o.eventID; - if(counterID != o.counterID) + if(!(counterID == o.counterID)) return counterID < o.counterID; // don't compare values, just consider equal @@ -1107,6 +1241,21 @@ DECLARE_REFLECTION_STRUCT(PixelValue); DOCUMENT("The value of pixel output at a particular event."); struct ModificationValue { + DOCUMENT(""); + bool operator==(const ModificationValue &o) const + { + return !memcmp(&col, &o.col, sizeof(col)) && depth == o.depth && stencil == o.stencil; + } + bool operator<(const ModificationValue &o) const + { + if(memcmp(&col, &o.col, sizeof(col)) < 0) + return true; + if(!(depth == o.depth)) + return depth < o.depth; + if(!(stencil == o.stencil)) + return stencil < o.stencil; + return false; + } DOCUMENT("The colour value."); PixelValue col; @@ -1122,6 +1271,53 @@ DECLARE_REFLECTION_STRUCT(ModificationValue); DOCUMENT("An attempt to modify a pixel by a particular event."); struct PixelModification { + DOCUMENT(""); + bool operator==(const PixelModification &o) const + { + return eventID == o.eventID && directShaderWrite == o.directShaderWrite && + unboundPS == o.unboundPS && fragIndex == o.fragIndex && primitiveID == o.primitiveID && + preMod == o.preMod && shaderOut == o.shaderOut && postMod == o.postMod && + sampleMasked == o.sampleMasked && backfaceCulled == o.backfaceCulled && + depthClipped == o.depthClipped && viewClipped == o.viewClipped && + scissorClipped == o.scissorClipped && shaderDiscarded == o.shaderDiscarded && + depthTestFailed == o.depthTestFailed && stencilTestFailed == o.stencilTestFailed; + } + bool operator<(const PixelModification &o) const + { + if(!(eventID == o.eventID)) + return eventID < o.eventID; + if(!(directShaderWrite == o.directShaderWrite)) + return directShaderWrite < o.directShaderWrite; + if(!(unboundPS == o.unboundPS)) + return unboundPS < o.unboundPS; + if(!(fragIndex == o.fragIndex)) + return fragIndex < o.fragIndex; + if(!(primitiveID == o.primitiveID)) + return primitiveID < o.primitiveID; + if(!(preMod == o.preMod)) + return preMod < o.preMod; + if(!(shaderOut == o.shaderOut)) + return shaderOut < o.shaderOut; + if(!(postMod == o.postMod)) + return postMod < o.postMod; + if(!(sampleMasked == o.sampleMasked)) + return sampleMasked < o.sampleMasked; + if(!(backfaceCulled == o.backfaceCulled)) + return backfaceCulled < o.backfaceCulled; + if(!(depthClipped == o.depthClipped)) + return depthClipped < o.depthClipped; + if(!(viewClipped == o.viewClipped)) + return viewClipped < o.viewClipped; + if(!(scissorClipped == o.scissorClipped)) + return scissorClipped < o.scissorClipped; + if(!(shaderDiscarded == o.shaderDiscarded)) + return shaderDiscarded < o.shaderDiscarded; + if(!(depthTestFailed == o.depthTestFailed)) + return depthTestFailed < o.depthTestFailed; + if(!(stencilTestFailed == o.stencilTestFailed)) + return stencilTestFailed < o.stencilTestFailed; + return false; + } DOCUMENT("The :data:`EID ` where the modification happened."); uint32_t eventID; diff --git a/renderdoc/api/replay/gl_pipestate.h b/renderdoc/api/replay/gl_pipestate.h index 46fa1381b..4ac8bd362 100644 --- a/renderdoc/api/replay/gl_pipestate.h +++ b/renderdoc/api/replay/gl_pipestate.h @@ -36,6 +36,27 @@ DOCUMENT(R"(Describes the configuration for a single vertex attribute. )"); struct VertexAttribute { + DOCUMENT(""); + bool operator==(const VertexAttribute &o) const + { + return Enabled == o.Enabled && Format == o.Format && + !memcmp(&GenericValue, &o.GenericValue, sizeof(GenericValue)) && + BufferSlot == o.BufferSlot && RelativeOffset == o.RelativeOffset; + } + bool operator<(const VertexAttribute &o) const + { + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + if(!(Format == o.Format)) + return Format < o.Format; + if(memcmp(&GenericValue, &o.GenericValue, sizeof(GenericValue)) < 0) + return true; + if(!(BufferSlot == o.BufferSlot)) + return BufferSlot < o.BufferSlot; + if(!(RelativeOffset == o.RelativeOffset)) + return RelativeOffset < o.RelativeOffset; + return false; + } DOCUMENT("``True`` if this vertex attribute is enabled."); bool Enabled = false; DOCUMENT("The :class:`ResourceFormat` of the vertex attribute."); @@ -55,6 +76,23 @@ struct VertexAttribute DOCUMENT("Describes a single OpenGL vertex buffer binding.") struct VB { + DOCUMENT(""); + bool operator==(const VB &o) const + { + return Buffer == o.Buffer && Stride == o.Stride && Offset == o.Offset && Divisor == o.Divisor; + } + bool operator<(const VB &o) const + { + if(!(Buffer == o.Buffer)) + return Buffer < o.Buffer; + if(!(Stride == o.Stride)) + return Stride < o.Stride; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + if(!(Divisor == o.Divisor)) + return Divisor < o.Divisor; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer bound to this slot."); ResourceId Buffer; @@ -145,6 +183,36 @@ struct FixedVertexProcessing DOCUMENT("Describes the details of a texture."); struct Texture { + DOCUMENT(""); + bool operator==(const Texture &o) const + { + return Resource == o.Resource && FirstSlice == o.FirstSlice && HighestMip == o.HighestMip && + ResType == o.ResType && Swizzle[0] == o.Swizzle[0] && Swizzle[1] == o.Swizzle[1] && + Swizzle[2] == o.Swizzle[2] && Swizzle[3] == o.Swizzle[3] && + DepthReadChannel == o.DepthReadChannel; + } + bool operator<(const Texture &o) const + { + if(!(Resource == o.Resource)) + return Resource < o.Resource; + if(!(FirstSlice == o.FirstSlice)) + return FirstSlice < o.FirstSlice; + if(!(HighestMip == o.HighestMip)) + return HighestMip < o.HighestMip; + if(!(ResType == o.ResType)) + return ResType < o.ResType; + if(!(Swizzle[0] == o.Swizzle[0])) + return Swizzle[0] < o.Swizzle[0]; + if(!(Swizzle[1] == o.Swizzle[1])) + return Swizzle[1] < o.Swizzle[1]; + if(!(Swizzle[2] == o.Swizzle[2])) + return Swizzle[2] < o.Swizzle[2]; + if(!(Swizzle[3] == o.Swizzle[3])) + return Swizzle[3] < o.Swizzle[3]; + if(!(DepthReadChannel == o.DepthReadChannel)) + return DepthReadChannel < o.DepthReadChannel; + return false; + } DOCUMENT("The :class:`ResourceId` of the underlying resource the view refers to."); ResourceId Resource; DOCUMENT("Valid for texture arrays or 3D textures - the first slice available."); @@ -171,6 +239,50 @@ struct Texture DOCUMENT("Describes the sampler properties of a texture."); struct Sampler { + DOCUMENT(""); + bool operator==(const Sampler &o) const + { + return Samp == o.Samp && AddressS == o.AddressS && AddressT == o.AddressT && + AddressR == o.AddressR && BorderColor[0] == o.BorderColor[0] && + BorderColor[1] == o.BorderColor[1] && BorderColor[2] == o.BorderColor[2] && + BorderColor[3] == o.BorderColor[3] && Comparison == o.Comparison && Filter == o.Filter && + SeamlessCube == o.SeamlessCube && MaxAniso == o.MaxAniso && MaxLOD == o.MaxLOD && + MinLOD == o.MinLOD && MipLODBias == o.MipLODBias; + } + bool operator<(const Sampler &o) const + { + if(!(Samp == o.Samp)) + return Samp < o.Samp; + if(!(AddressS == o.AddressS)) + return AddressS < o.AddressS; + if(!(AddressT == o.AddressT)) + return AddressT < o.AddressT; + if(!(AddressR == o.AddressR)) + return AddressR < o.AddressR; + if(!(BorderColor[0] == o.BorderColor[0])) + return BorderColor[0] < o.BorderColor[0]; + if(!(BorderColor[1] == o.BorderColor[1])) + return BorderColor[1] < o.BorderColor[1]; + if(!(BorderColor[2] == o.BorderColor[2])) + return BorderColor[2] < o.BorderColor[2]; + if(!(BorderColor[3] == o.BorderColor[3])) + return BorderColor[3] < o.BorderColor[3]; + if(!(Comparison == o.Comparison)) + return Comparison < o.Comparison; + if(!(Filter == o.Filter)) + return Filter < o.Filter; + if(!(SeamlessCube == o.SeamlessCube)) + return SeamlessCube < o.SeamlessCube; + if(!(MaxAniso == o.MaxAniso)) + return MaxAniso < o.MaxAniso; + if(!(MaxLOD == o.MaxLOD)) + return MaxLOD < o.MaxLOD; + if(!(MinLOD == o.MinLOD)) + return MinLOD < o.MinLOD; + if(!(MipLODBias == o.MipLODBias)) + return MipLODBias < o.MipLODBias; + return false; + } DOCUMENT("The :class:`ResourceId` of the sampler object, if a separate one is set."); ResourceId Samp; DOCUMENT("The :class:`AddressMode` in the S direction."); @@ -211,6 +323,21 @@ struct Sampler DOCUMENT("Describes the properties of a buffer."); struct Buffer { + DOCUMENT(""); + bool operator==(const Buffer &o) const + { + return Resource == o.Resource && Offset == o.Offset && Size == o.Size; + } + bool operator<(const Buffer &o) const + { + if(!(Resource == o.Resource)) + return Resource < o.Resource; + if(!(Offset == o.Offset)) + return Offset < o.Offset; + if(!(Size == o.Size)) + return Size < o.Size; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer object."); ResourceId Resource; DOCUMENT("The byte offset from the start of the buffer."); @@ -222,6 +349,33 @@ struct Buffer DOCUMENT("Describes the properties of a load/store image."); struct ImageLoadStore { + DOCUMENT(""); + bool operator==(const ImageLoadStore &o) const + { + return Resource == o.Resource && Level == o.Level && Layered == o.Layered && Layer == o.Layer && + ResType == o.ResType && readAllowed == o.readAllowed && writeAllowed == o.writeAllowed && + Format == o.Format; + } + bool operator<(const ImageLoadStore &o) const + { + if(!(Resource == o.Resource)) + return Resource < o.Resource; + if(!(Level == o.Level)) + return Level < o.Level; + if(!(Layered == o.Layered)) + return Layered < o.Layered; + if(!(Layer == o.Layer)) + return Layer < o.Layer; + if(!(ResType == o.ResType)) + return ResType < o.ResType; + if(!(readAllowed == o.readAllowed)) + return readAllowed < o.readAllowed; + if(!(writeAllowed == o.writeAllowed)) + return writeAllowed < o.writeAllowed; + if(!(Format == o.Format)) + return Format < o.Format; + return false; + } DOCUMENT("The :class:`ResourceId` of the texture object."); ResourceId Resource; DOCUMENT("The mip of the texture that's used in the attachment."); @@ -262,6 +416,28 @@ struct Feedback DOCUMENT("Describes a single OpenGL viewport."); struct Viewport { + DOCUMENT(""); + bool operator==(const Viewport &o) const + { + return Left == o.Left && Bottom == o.Bottom && Width == o.Width && Height == o.Height && + MinDepth == o.MinDepth && MaxDepth == o.MaxDepth; + } + bool operator<(const Viewport &o) const + { + if(!(Left == o.Left)) + return Left < o.Left; + if(!(Bottom == o.Bottom)) + return Bottom < o.Bottom; + if(!(Width == o.Width)) + return Width < o.Width; + if(!(Height == o.Height)) + return Height < o.Height; + if(!(MinDepth == o.MinDepth)) + return MinDepth < o.MinDepth; + if(!(MaxDepth == o.MaxDepth)) + return MaxDepth < o.MaxDepth; + return false; + } DOCUMENT("The X co-ordinate of the left side of the viewport."); float Left = 0.0f; DOCUMENT("The Y co-ordinate of the bottom side of the viewport."); @@ -279,6 +455,26 @@ struct Viewport DOCUMENT("Describes a single OpenGL scissor region."); struct Scissor { + DOCUMENT(""); + bool operator==(const Scissor &o) const + { + return Left == o.Left && Bottom == o.Bottom && Width == o.Width && Height == o.Height && + Enabled == o.Enabled; + } + bool operator<(const Scissor &o) const + { + if(!(Left == o.Left)) + return Left < o.Left; + if(!(Bottom == o.Bottom)) + return Bottom < o.Bottom; + if(!(Width == o.Width)) + return Width < o.Width; + if(!(Height == o.Height)) + return Height < o.Height; + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + return false; + } DOCUMENT("The X co-ordinate of the left side of the scissor region."); int32_t Left = 0; DOCUMENT("The Y co-ordinate of the bottom side of the scissor region."); @@ -416,6 +612,30 @@ struct StencilState DOCUMENT("Describes the state of a framebuffer attachment."); struct Attachment { + DOCUMENT(""); + bool operator==(const Attachment &o) const + { + return Obj == o.Obj && Layer == o.Layer && Mip == o.Mip && Swizzle[0] == o.Swizzle[0] && + Swizzle[1] == o.Swizzle[1] && Swizzle[2] == o.Swizzle[2] && Swizzle[3] == o.Swizzle[3]; + } + bool operator<(const Attachment &o) const + { + if(!(Obj == o.Obj)) + return Obj < o.Obj; + if(!(Layer == o.Layer)) + return Layer < o.Layer; + if(!(Mip == o.Mip)) + return Mip < o.Mip; + if(!(Swizzle[0] == o.Swizzle[0])) + return Swizzle[0] < o.Swizzle[0]; + if(!(Swizzle[1] == o.Swizzle[1])) + return Swizzle[1] < o.Swizzle[1]; + if(!(Swizzle[2] == o.Swizzle[2])) + return Swizzle[2] < o.Swizzle[2]; + if(!(Swizzle[3] == o.Swizzle[3])) + return Swizzle[3] < o.Swizzle[3]; + return false; + } DOCUMENT("The :class:`ResourceId` of the texture bound to this attachment."); ResourceId Obj; DOCUMENT("The slice of the texture that's used in the attachment."); @@ -448,6 +668,21 @@ struct FBO DOCUMENT("Describes the details of an OpenGL blend operation."); struct BlendEquation { + DOCUMENT(""); + bool operator==(const BlendEquation &o) const + { + return Source == o.Source && Destination == o.Destination && Operation == o.Operation; + } + bool operator<(const BlendEquation &o) const + { + if(!(Source == o.Source)) + return Source < o.Source; + if(!(Destination == o.Destination)) + return Destination < o.Destination; + if(!(Operation == o.Operation)) + return Operation < o.Operation; + return false; + } DOCUMENT("The :class:`BlendMultiplier` for the source blend value."); BlendMultiplier Source = BlendMultiplier::One; DOCUMENT("The :class:`BlendMultiplier` for the destination blend value."); @@ -459,6 +694,26 @@ struct BlendEquation DOCUMENT("Describes the blend configuration for a given OpenGL attachment."); struct Blend { + DOCUMENT(""); + bool operator==(const Blend &o) const + { + return Enabled == o.Enabled && m_Blend == o.m_Blend && m_AlphaBlend == o.m_AlphaBlend && + Logic == o.Logic && WriteMask == o.WriteMask; + } + bool operator<(const Blend &o) const + { + if(!(Enabled == o.Enabled)) + return Enabled < o.Enabled; + if(!(m_Blend == o.m_Blend)) + return m_Blend < o.m_Blend; + if(!(m_AlphaBlend == o.m_AlphaBlend)) + return m_AlphaBlend < o.m_AlphaBlend; + if(!(Logic == o.Logic)) + return Logic < o.Logic; + if(!(WriteMask == o.WriteMask)) + return WriteMask < o.WriteMask; + return false; + } DOCUMENT("A :class:`GL_BlendEquation` describing the blending for colour values."); BlendEquation m_Blend; DOCUMENT("A :class:`GL_BlendEquation` describing the blending for alpha values."); diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index b9ef26928..712cf1f0a 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -114,6 +114,7 @@ data bytes when they are specified to be column-major in the API/shader metadata )"); struct ShaderVariable { + DOCUMENT(""); ShaderVariable() { name = ""; @@ -165,6 +166,32 @@ struct ShaderVariable value.u.z = z; value.u.w = w; } + bool operator==(const ShaderVariable &o) const + { + return rows == o.rows && columns == o.columns && name == o.name && type == o.type && + displayAsHex == o.displayAsHex && !memcmp(&value, &o.value, sizeof(value)) && + isStruct == o.isStruct && members == o.members; + } + bool operator<(const ShaderVariable &o) const + { + if(!(rows == o.rows)) + return rows < o.rows; + if(!(columns == o.columns)) + return columns < o.columns; + if(!(name == o.name)) + return name < o.name; + if(!(type == o.type)) + return type < o.type; + if(!(displayAsHex == o.displayAsHex)) + return displayAsHex < o.displayAsHex; + if(memcmp(&value, &o.value, sizeof(value)) < 0) + return true; + if(!(isStruct == o.isStruct)) + return isStruct < o.isStruct; + if(!(members == o.members)) + return members < o.members; + return false; + } DOCUMENT("The number of rows in this matrix."); uint32_t rows; @@ -196,6 +223,26 @@ with all mutable variable contents. )"); struct ShaderDebugState { + DOCUMENT(""); + bool operator==(const ShaderDebugState &o) const + { + return registers == o.registers && outputs == o.outputs && indexableTemps == o.indexableTemps && + nextInstruction == o.nextInstruction && flags == o.flags; + } + bool operator<(const ShaderDebugState &o) const + { + if(!(registers == o.registers)) + return registers < o.registers; + if(!(outputs == o.outputs)) + return outputs < o.outputs; + if(!(indexableTemps == o.indexableTemps)) + return indexableTemps < o.indexableTemps; + if(!(nextInstruction == o.nextInstruction)) + return nextInstruction < o.nextInstruction; + if(!(flags == o.flags)) + return flags < o.flags; + return false; + } DOCUMENT("The temporary variables for this shader as a list of :class:`ShaderValue`."); rdcarray registers; DOCUMENT("The output variables for this shader as a list of :class:`ShaderValue`."); @@ -247,18 +294,45 @@ between shader stages. )"); struct SigParameter { - SigParameter() - : semanticIndex(0), - needSemanticIndex(false), - regIndex(0), - systemValue(ShaderBuiltin::Undefined), - compType(CompType::Float), - regChannelMask(0), - channelUsedMask(0), - compCount(0), - stream(0), - arrayIndex(~0U) + DOCUMENT(""); + bool operator==(const SigParameter &o) const { + return varName == o.varName && semanticName == o.semanticName && + semanticIdxName == o.semanticIdxName && semanticIndex == o.semanticIndex && + regIndex == o.regIndex && systemValue == o.systemValue && compType == o.compType && + regChannelMask == o.regChannelMask && channelUsedMask == o.channelUsedMask && + needSemanticIndex == o.needSemanticIndex && compCount == o.compCount && + stream == o.stream && arrayIndex == o.arrayIndex; + } + bool operator<(const SigParameter &o) const + { + if(!(varName == o.varName)) + return varName < o.varName; + if(!(semanticName == o.semanticName)) + return semanticName < o.semanticName; + if(!(semanticIdxName == o.semanticIdxName)) + return semanticIdxName < o.semanticIdxName; + if(!(semanticIndex == o.semanticIndex)) + return semanticIndex < o.semanticIndex; + if(!(regIndex == o.regIndex)) + return regIndex < o.regIndex; + if(!(systemValue == o.systemValue)) + return systemValue < o.systemValue; + if(!(compType == o.compType)) + return compType < o.compType; + if(!(regChannelMask == o.regChannelMask)) + return regChannelMask < o.regChannelMask; + if(!(channelUsedMask == o.channelUsedMask)) + return channelUsedMask < o.channelUsedMask; + if(!(needSemanticIndex == o.needSemanticIndex)) + return needSemanticIndex < o.needSemanticIndex; + if(!(compCount == o.compCount)) + return compCount < o.compCount; + if(!(stream == o.stream)) + return stream < o.stream; + if(!(arrayIndex == o.arrayIndex)) + return arrayIndex < o.arrayIndex; + return false; } DOCUMENT("The name of this variable - may not be present in the metadata for all APIs."); @@ -268,40 +342,40 @@ struct SigParameter DOCUMENT("The combined semantic name and index."); rdcstr semanticIdxName; DOCUMENT("The semantic index of this variable - see :data:`semanticName`."); - uint32_t semanticIndex; + uint32_t semanticIndex = 0; DOCUMENT(R"(The index of the shader register/binding used to store this signature element. This may be :data:`NoIndex` if the element is system-generated and not consumed by another shader stage. See :data:`systemValue`. )"); - uint32_t regIndex; + uint32_t regIndex = 0; DOCUMENT("The :class:`ShaderBuiltin` value that this element contains."); - ShaderBuiltin systemValue; + ShaderBuiltin systemValue = ShaderBuiltin::Undefined; DOCUMENT("The :class:`component type ` of data that this element stores."); - CompType compType; + CompType compType = CompType::Float; DOCUMENT(R"(A bitmask indicating which components in the shader register are stored, for APIs that pack signatures together. )"); - uint8_t regChannelMask; + uint8_t regChannelMask = 0; DOCUMENT(R"(A bitmask indicating which components in the shader register are actually used by the shader itself, for APIs that pack signatures together. )"); - uint8_t channelUsedMask; + uint8_t channelUsedMask = 0; DOCUMENT("A convenience flag - ``True`` if the semantic name is unique and no index is needed."); - bool needSemanticIndex; + bool needSemanticIndex = false; DOCUMENT("The number of components used to store this element. See :data:`compType`."); - uint32_t compCount; + uint32_t compCount = 0; DOCUMENT( "Selects a stream for APIs that provide multiple output streams for the same named output."); - uint32_t stream; + uint32_t stream = 0; DOCUMENT("If this element is part of an array, indicates the index, or :data:`NoIndex` if not."); - uint32_t arrayIndex; + uint32_t arrayIndex = ~0U; static const uint32_t NoIndex = ~0U; }; @@ -313,6 +387,31 @@ struct ShaderConstant; DOCUMENT("Describes the storage characteristics for a basic :class:`ShaderConstant` in memory."); struct ShaderVariableDescriptor { + DOCUMENT(""); + bool operator==(const ShaderVariableDescriptor &o) const + { + return type == o.type && rows == o.rows && cols == o.cols && + rowMajorStorage == o.rowMajorStorage && elements == o.elements && + arrayStride == o.arrayStride && name == o.name; + } + bool operator<(const ShaderVariableDescriptor &o) const + { + if(!(type == o.type)) + return type < o.type; + if(!(rows == o.rows)) + return rows < o.rows; + if(!(cols == o.cols)) + return cols < o.cols; + if(!(rowMajorStorage == o.rowMajorStorage)) + return rowMajorStorage < o.rowMajorStorage; + if(!(elements == o.elements)) + return elements < o.elements; + if(!(arrayStride == o.arrayStride)) + return arrayStride < o.arrayStride; + if(!(name == o.name)) + return name < o.name; + return false; + } DOCUMENT("The :class:`VarType` that this basic constant stores."); VarType type; DOCUMENT("The number of rows in this matrix."); @@ -334,6 +433,19 @@ DECLARE_REFLECTION_STRUCT(ShaderVariableDescriptor); DOCUMENT("Describes the type and members of a :class:`ShaderConstant`."); struct ShaderVariableType { + DOCUMENT(""); + bool operator==(const ShaderVariableType &o) const + { + return descriptor == o.descriptor && members == o.members; + } + bool operator<(const ShaderVariableType &o) const + { + if(!(descriptor == o.descriptor)) + return descriptor < o.descriptor; + if(!(members == o.members)) + return members < o.members; + return false; + } DOCUMENT("The :class:`ShaderVariableDescriptor` that describes the current constant."); ShaderVariableDescriptor descriptor; @@ -346,6 +458,16 @@ DECLARE_REFLECTION_STRUCT(ShaderVariableType); DOCUMENT("Describes the offset of a constant in memory in terms of 16 byte vectors."); struct ShaderRegister { + DOCUMENT(""); + bool operator==(const ShaderRegister &o) const { return vec == o.vec && comp == o.comp; } + bool operator<(const ShaderRegister &o) const + { + if(!(vec == o.vec)) + return vec < o.vec; + if(!(comp == o.comp)) + return comp < o.comp; + return false; + } DOCUMENT("The index of the 16 byte vector where this register begins"); uint32_t vec; DOCUMENT("The 4 byte component within that vector where this register begins"); @@ -357,6 +479,23 @@ DECLARE_REFLECTION_STRUCT(ShaderRegister); DOCUMENT("Contains the detail of a constant within a :class:`ConstantBlock` in memory."); struct ShaderConstant { + DOCUMENT(""); + bool operator==(const ShaderConstant &o) const + { + return name == o.name && reg == o.reg && defaultValue == o.defaultValue && type == o.type; + } + bool operator<(const ShaderConstant &o) const + { + if(!(name == o.name)) + return name < o.name; + if(!(reg == o.reg)) + return reg < o.reg; + if(!(defaultValue == o.defaultValue)) + return defaultValue < o.defaultValue; + if(!(type == o.type)) + return type < o.type; + return false; + } DOCUMENT("The name of this constant"); rdcstr name; DOCUMENT( @@ -378,6 +517,26 @@ information. )"); struct ConstantBlock { + DOCUMENT(""); + bool operator==(const ConstantBlock &o) const + { + return name == o.name && variables == o.variables && bindPoint == o.bindPoint && + byteSize == o.byteSize && bufferBacked == o.bufferBacked; + } + bool operator<(const ConstantBlock &o) const + { + if(!(name == o.name)) + return name < o.name; + if(!(variables == o.variables)) + return variables < o.variables; + if(!(bindPoint == o.bindPoint)) + return bindPoint < o.bindPoint; + if(!(byteSize == o.byteSize)) + return byteSize < o.byteSize; + if(!(bufferBacked == o.bufferBacked)) + return bufferBacked < o.bufferBacked; + return false; + } DOCUMENT("The name of this constant block, may be empty on some APIs."); rdcstr name; DOCUMENT("The constants contained within this block as a list of :class:`ShaderConstant`."); @@ -405,6 +564,19 @@ relevant. )"); struct ShaderSampler { + DOCUMENT(""); + bool operator==(const ShaderSampler &o) const + { + return name == o.name && bindPoint == o.bindPoint; + } + bool operator<(const ShaderSampler &o) const + { + if(!(name == o.name)) + return name < o.name; + if(!(bindPoint == o.bindPoint)) + return bindPoint < o.bindPoint; + return false; + } DOCUMENT("The name of this sampler."); rdcstr name; @@ -424,6 +596,28 @@ directly by means of the API resource binding system. )"); struct ShaderResource { + DOCUMENT(""); + bool operator==(const ShaderResource &o) const + { + return resType == o.resType && name == o.name && variableType == o.variableType && + bindPoint == o.bindPoint && IsTexture == o.IsTexture && IsReadOnly == o.IsReadOnly; + } + bool operator<(const ShaderResource &o) const + { + if(!(resType == o.resType)) + return resType < o.resType; + if(!(name == o.name)) + return name < o.name; + if(!(variableType == o.variableType)) + return variableType < o.variableType; + if(!(bindPoint == o.bindPoint)) + return bindPoint < o.bindPoint; + if(!(IsTexture == o.IsTexture)) + return IsTexture < o.IsTexture; + if(!(IsReadOnly == o.IsReadOnly)) + return IsReadOnly < o.IsReadOnly; + return false; + } DOCUMENT("The :class:`TextureDim` that describes the type of this resource."); TextureDim resType; @@ -454,6 +648,16 @@ DECLARE_REFLECTION_STRUCT(ShaderResource); DOCUMENT("Describes an entry point in a shader."); struct ShaderEntryPoint { + DOCUMENT(""); + bool operator==(const ShaderEntryPoint &o) const { return name == o.name && stage == o.stage; } + bool operator<(const ShaderEntryPoint &o) const + { + if(!(name == o.name)) + return name < o.name; + if(!(stage == o.stage)) + return stage < o.stage; + return false; + } DOCUMENT("The name of the entry point."); rdcstr name; @@ -466,6 +670,16 @@ DECLARE_REFLECTION_STRUCT(ShaderEntryPoint); DOCUMENT("Contains a single flag used at compile-time on a shader."); struct ShaderCompileFlag { + DOCUMENT(""); + bool operator==(const ShaderCompileFlag &o) const { return Name == o.Name && Value == o.Value; } + bool operator<(const ShaderCompileFlag &o) const + { + if(!(Name == o.Name)) + return Name < o.Name; + if(!(Value == o.Value)) + return Value < o.Value; + return false; + } DOCUMENT("The name of the compile flag."); rdcstr Name; @@ -490,6 +704,19 @@ DECLARE_REFLECTION_STRUCT(ShaderCompileFlags); DOCUMENT("Contains a source file available in a debug-compiled shader."); struct ShaderSourceFile { + DOCUMENT(""); + bool operator==(const ShaderSourceFile &o) const + { + return Filename == o.Filename && Contents == o.Contents; + } + bool operator<(const ShaderSourceFile &o) const + { + if(!(Filename == o.Filename)) + return Filename < o.Filename; + if(!(Contents == o.Contents)) + return Contents < o.Contents; + return false; + } DOCUMENT("The filename of this source file."); rdcstr Filename; @@ -576,6 +803,7 @@ See :class:`ShaderBindpointMapping` for how this mapping works in detail. )"); struct BindpointMap { + DOCUMENT(""); BindpointMap() { bindset = 0; @@ -594,7 +822,7 @@ struct BindpointMap bool operator<(const BindpointMap &o) const { - if(bindset != o.bindset) + if(!(bindset == o.bindset)) return bindset < o.bindset; return bind < o.bind; } diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index ff8800bf2..d5be71fa2 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -29,6 +29,84 @@ namespace VKPipe DOCUMENT("The contents of a single binding element within a descriptor set, possibly in an array."); struct BindingElement { + DOCUMENT(""); + bool operator==(const BindingElement &o) const + { + return view == o.view && res == o.res && sampler == o.sampler && + immutableSampler == o.immutableSampler && viewfmt == o.viewfmt && + swizzle[0] == o.swizzle[0] && swizzle[1] == o.swizzle[1] && swizzle[2] == o.swizzle[2] && + swizzle[3] == o.swizzle[3] && baseMip == o.baseMip && baseLayer == o.baseLayer && + numMip == o.numMip && numLayer == o.numLayer && offset == o.offset && size == o.size && + Filter == o.Filter && AddressU == o.AddressU && AddressV == o.AddressV && + AddressW == o.AddressW && mipBias == o.mipBias && maxAniso == o.maxAniso && + comparison == o.comparison && minlod == o.minlod && maxlod == o.maxlod && + BorderColor[0] == o.BorderColor[0] && BorderColor[1] == o.BorderColor[1] && + BorderColor[2] == o.BorderColor[2] && BorderColor[3] == o.BorderColor[3] && + unnormalized == o.unnormalized; + } + bool operator<(const BindingElement &o) const + { + if(!(view == o.view)) + return view < o.view; + if(!(res == o.res)) + return res < o.res; + if(!(sampler == o.sampler)) + return sampler < o.sampler; + if(!(immutableSampler == o.immutableSampler)) + return immutableSampler < o.immutableSampler; + if(!(viewfmt == o.viewfmt)) + return viewfmt < o.viewfmt; + if(!(swizzle[0] == o.swizzle[0])) + return swizzle[0] < o.swizzle[0]; + if(!(swizzle[1] == o.swizzle[1])) + return swizzle[1] < o.swizzle[1]; + if(!(swizzle[2] == o.swizzle[2])) + return swizzle[2] < o.swizzle[2]; + if(!(swizzle[3] == o.swizzle[3])) + return swizzle[3] < o.swizzle[3]; + if(!(baseMip == o.baseMip)) + return baseMip < o.baseMip; + if(!(baseLayer == o.baseLayer)) + return baseLayer < o.baseLayer; + if(!(numMip == o.numMip)) + return numMip < o.numMip; + if(!(numLayer == o.numLayer)) + return numLayer < o.numLayer; + if(!(offset == o.offset)) + return offset < o.offset; + if(!(size == o.size)) + return size < o.size; + if(!(Filter == o.Filter)) + return Filter < o.Filter; + if(!(AddressU == o.AddressU)) + return AddressU < o.AddressU; + if(!(AddressV == o.AddressV)) + return AddressV < o.AddressV; + if(!(AddressW == o.AddressW)) + return AddressW < o.AddressW; + if(!(mipBias == o.mipBias)) + return mipBias < o.mipBias; + if(!(maxAniso == o.maxAniso)) + return maxAniso < o.maxAniso; + if(!(comparison == o.comparison)) + return comparison < o.comparison; + if(!(minlod == o.minlod)) + return minlod < o.minlod; + if(!(maxlod == o.maxlod)) + return maxlod < o.maxlod; + if(!(BorderColor[0] == o.BorderColor[0])) + return BorderColor[0] < o.BorderColor[0]; + if(!(BorderColor[1] == o.BorderColor[1])) + return BorderColor[1] < o.BorderColor[1]; + if(!(BorderColor[2] == o.BorderColor[2])) + return BorderColor[2] < o.BorderColor[2]; + if(!(BorderColor[3] == o.BorderColor[3])) + return BorderColor[3] < o.BorderColor[3]; + if(!(unnormalized == o.unnormalized)) + return unnormalized < o.unnormalized; + return false; + } + DOCUMENT("The :class:`ResourceId` of the current view object, if one is in use."); ResourceId view; // bufferview, imageview, attachmentview DOCUMENT("The :class:`ResourceId` of the current underlying buffer or image object."); @@ -95,6 +173,24 @@ struct BindingElement DOCUMENT("The contents of a single binding within a descriptor set, either arrayed or not."); struct DescriptorBinding { + DOCUMENT(""); + bool operator==(const DescriptorBinding &o) const + { + return descriptorCount == o.descriptorCount && type == o.type && stageFlags == o.stageFlags && + binds == o.binds; + } + bool operator<(const DescriptorBinding &o) const + { + if(!(descriptorCount == o.descriptorCount)) + return descriptorCount < o.descriptorCount; + if(!(type == o.type)) + return type < o.type; + if(!(stageFlags == o.stageFlags)) + return stageFlags < o.stageFlags; + if(!(binds == o.binds)) + return binds < o.binds; + return false; + } DOCUMENT(R"(How many descriptors are in this binding array. If this binding is empty/non-existant this value will be ``0``. )"); @@ -113,6 +209,21 @@ If :data:`descriptorCount` is 1 then this isn't an array, and this list has only DOCUMENT("The contents of a descriptor set."); struct DescriptorSet { + DOCUMENT(""); + bool operator==(const DescriptorSet &o) const + { + return layout == o.layout && descset == o.descset && bindings == o.bindings; + } + bool operator<(const DescriptorSet &o) const + { + if(!(layout == o.layout)) + return layout < o.layout; + if(!(descset == o.descset)) + return descset < o.descset; + if(!(bindings == o.bindings)) + return bindings < o.bindings; + return false; + } DOCUMENT("The :class:`ResourceId` of the descriptor set layout that matches this set."); ResourceId layout; DOCUMENT("The :class:`ResourceId` of the descriptor set object."); @@ -159,6 +270,24 @@ struct InputAssembly DOCUMENT("Describes the configuration of a single vertex attribute."); struct VertexAttribute { + DOCUMENT(""); + bool operator==(const VertexAttribute &o) const + { + return location == o.location && binding == o.binding && format == o.format && + byteoffset == o.byteoffset; + } + bool operator<(const VertexAttribute &o) const + { + if(!(location == o.location)) + return location < o.location; + if(!(binding == o.binding)) + return binding < o.binding; + if(!(format == o.format)) + return format < o.format; + if(!(byteoffset == o.byteoffset)) + return byteoffset < o.byteoffset; + return false; + } DOCUMENT("The location in the shader that is bound to this attribute."); uint32_t location = 0; DOCUMENT("The vertex binding where data will be sourced from."); @@ -174,6 +303,22 @@ struct VertexAttribute DOCUMENT("Describes a vertex binding."); struct VertexBinding { + DOCUMENT(""); + bool operator==(const VertexBinding &o) const + { + return vbufferBinding == o.vbufferBinding && bytestride == o.bytestride && + perInstance == o.perInstance; + } + bool operator<(const VertexBinding &o) const + { + if(!(vbufferBinding == o.vbufferBinding)) + return vbufferBinding < o.vbufferBinding; + if(!(bytestride == o.bytestride)) + return bytestride < o.bytestride; + if(!(perInstance == o.perInstance)) + return perInstance < o.perInstance; + return false; + } DOCUMENT("The vertex binding where data will be sourced from."); uint32_t vbufferBinding = 0; DOCUMENT("The byte stride between the start of one set of vertex data and the next."); @@ -185,6 +330,16 @@ struct VertexBinding DOCUMENT("Describes a single Vulkan vertex buffer binding.") struct VB { + DOCUMENT(""); + bool operator==(const VB &o) const { return buffer == o.buffer && offset == o.offset; } + bool operator<(const VB &o) const + { + if(!(buffer == o.buffer)) + return buffer < o.buffer; + if(!(offset == o.offset)) + return offset < o.offset; + return false; + } DOCUMENT("The :class:`ResourceId` of the buffer bound to this slot."); ResourceId buffer; DOCUMENT("The byte offset from the start of the buffer to the beginning of the vertex data."); @@ -205,6 +360,16 @@ struct VertexInput DOCUMENT("The provided value for a specialization constant."); struct SpecInfo { + DOCUMENT(""); + bool operator==(const SpecInfo &o) const { return specID == o.specID && data == o.data; } + bool operator<(const SpecInfo &o) const + { + if(!(specID == o.specID)) + return specID < o.specID; + if(!(data == o.data)) + return data < o.data; + return false; + } DOCUMENT("The specialization ID"); uint32_t specID = 0; DOCUMENT("A ``bytes`` with the contents of the constant."); @@ -243,6 +408,28 @@ struct Tessellation DOCUMENT("Describes a single Vulkan viewport."); struct Viewport { + DOCUMENT(""); + bool operator==(const Viewport &o) const + { + return x == o.x && y == o.y && width == o.width && height == o.height && + minDepth == o.minDepth && maxDepth == o.maxDepth; + } + bool operator<(const Viewport &o) const + { + if(!(x == o.x)) + return x < o.x; + if(!(y == o.y)) + return y < o.y; + if(!(width == o.width)) + return width < o.width; + if(!(height == o.height)) + return height < o.height; + if(!(minDepth == o.minDepth)) + return minDepth < o.minDepth; + if(!(maxDepth == o.maxDepth)) + return maxDepth < o.maxDepth; + return false; + } DOCUMENT("The X co-ordinate of the viewport."); float x = 0.0f; DOCUMENT("The Y co-ordinate of the viewport."); @@ -260,6 +447,23 @@ struct Viewport DOCUMENT("Describes a single Vulkan scissor region."); struct Scissor { + DOCUMENT(""); + bool operator==(const Scissor &o) const + { + return x == o.x && y == o.y && width == o.width && height == o.height; + } + bool operator<(const Scissor &o) const + { + if(!(x == o.x)) + return x < o.x; + if(!(y == o.y)) + return y < o.y; + if(!(width == o.width)) + return width < o.width; + if(!(height == o.height)) + return height < o.height; + return false; + } DOCUMENT("The X co-ordinate of the scissor region."); int32_t x = 0; DOCUMENT("The Y co-ordinate of the scissor region."); @@ -273,6 +477,9 @@ struct Scissor DOCUMENT("Describes a combined viewport and scissor region."); struct ViewportScissor { + DOCUMENT(""); + bool operator==(const ViewportScissor &o) const { return vp == o.vp && scissor == o.scissor; } + bool operator<(const ViewportScissor &o) const { return vp == o.vp && scissor == o.scissor; } DOCUMENT("The :class:`VK_Viewport`."); Viewport vp; DOCUMENT("The :class:`VK_Scissor`."); @@ -332,6 +539,21 @@ struct MultiSample DOCUMENT("Describes the details of a Vulkan blend operation."); struct BlendEquation { + DOCUMENT(""); + bool operator==(const BlendEquation &o) const + { + return Source == o.Source && Destination == o.Destination && Operation == o.Operation; + } + bool operator<(const BlendEquation &o) const + { + if(!(Source == o.Source)) + return Source < o.Source; + if(!(Destination == o.Destination)) + return Destination < o.Destination; + if(!(Operation == o.Operation)) + return Operation < o.Operation; + return false; + } DOCUMENT("The :class:`BlendMultiplier` for the source blend value."); BlendMultiplier Source = BlendMultiplier::One; DOCUMENT("The :class:`BlendMultiplier` for the destination blend value."); @@ -343,14 +565,32 @@ struct BlendEquation DOCUMENT("Describes the blend configuration for a given Vulkan attachment."); struct Blend { - DOCUMENT("``True`` if blending is enabled for this attachment."); - bool blendEnable = false; + DOCUMENT(""); + bool operator==(const Blend &o) const + { + return blendEnable == o.blendEnable && blend == o.blend && alphaBlend == o.alphaBlend && + writeMask == o.writeMask; + } + bool operator<(const Blend &o) const + { + if(!(blendEnable == o.blendEnable)) + return blendEnable < o.blendEnable; + if(!(blend == o.blend)) + return blend < o.blend; + if(!(alphaBlend == o.alphaBlend)) + return alphaBlend < o.alphaBlend; + if(!(writeMask == o.writeMask)) + return writeMask < o.writeMask; + return false; + } DOCUMENT("A :class:`VK_BlendEquation` describing the blending for colour values."); BlendEquation blend; DOCUMENT("A :class:`VK_BlendEquation` describing the blending for alpha values."); BlendEquation alphaBlend; + DOCUMENT("``True`` if blending is enabled for this attachment."); + bool blendEnable = false; DOCUMENT("The mask for writes to the attachment."); uint8_t writeMask = 0; }; @@ -447,6 +687,40 @@ If there is no depth-stencil attachment, this index is ``-1``. DOCUMENT("Describes a single attachment in a framebuffer object."); struct Attachment { + DOCUMENT(""); + bool operator==(const Attachment &o) const + { + return view == o.view && img == o.img && viewfmt == o.viewfmt && swizzle[0] == o.swizzle[0] && + swizzle[1] == o.swizzle[1] && swizzle[2] == o.swizzle[2] && swizzle[3] == o.swizzle[3] && + baseMip == o.baseMip && baseLayer == o.baseLayer && numMip == o.numMip && + numLayer == o.numLayer; + } + bool operator<(const Attachment &o) const + { + if(!(view == o.view)) + return view < o.view; + if(!(img == o.img)) + return img < o.img; + if(!(viewfmt == o.viewfmt)) + return viewfmt < o.viewfmt; + if(!(swizzle[0] == o.swizzle[0])) + return swizzle[0] < o.swizzle[0]; + if(!(swizzle[1] == o.swizzle[1])) + return swizzle[1] < o.swizzle[1]; + if(!(swizzle[2] == o.swizzle[2])) + return swizzle[2] < o.swizzle[2]; + if(!(swizzle[3] == o.swizzle[3])) + return swizzle[3] < o.swizzle[3]; + if(!(baseMip == o.baseMip)) + return baseMip < o.baseMip; + if(!(baseLayer == o.baseLayer)) + return baseLayer < o.baseLayer; + if(!(numMip == o.numMip)) + return numMip < o.numMip; + if(!(numLayer == o.numLayer)) + return numLayer < o.numLayer; + return false; + } DOCUMENT("The :class:`ResourceId` of the image view itself."); ResourceId view; DOCUMENT("The :class:`ResourceId` of the underlying image that the view refers to."); @@ -511,6 +785,26 @@ struct CurrentPass DOCUMENT("Contains the layout of a range of subresources in an image."); struct ImageLayout { + DOCUMENT(""); + bool operator==(const ImageLayout &o) const + { + return baseMip == o.baseMip && baseLayer == o.baseLayer && numMip == o.numMip && + numLayer == o.numLayer && name == o.name; + } + bool operator<(const ImageLayout &o) const + { + if(!(baseMip == o.baseMip)) + return baseMip < o.baseMip; + if(!(baseLayer == o.baseLayer)) + return baseLayer < o.baseLayer; + if(!(numMip == o.numMip)) + return numMip < o.numMip; + if(!(numLayer == o.numLayer)) + return numLayer < o.numLayer; + if(!(name == o.name)) + return name < o.name; + return false; + } DOCUMENT("The first mip level used in the range."); uint32_t baseMip = 0; DOCUMENT("For 3D textures and texture arrays, the first slice used in the range."); @@ -526,6 +820,14 @@ struct ImageLayout DOCUMENT("Contains the current layout of all subresources in the image."); struct ImageData { + DOCUMENT(""); + bool operator==(const ImageData &o) const { return image == o.image; } + bool operator<(const ImageData &o) const + { + if(!(image == o.image)) + return image < o.image; + return false; + } DOCUMENT("The :class:`ResourceId` of the image."); ResourceId image; diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index f021e5dde..206e8aae1 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -2034,7 +2034,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::Blend &el) SERIALISE_MEMBER(alphaBlend); SERIALISE_MEMBER(writeMask); - SIZE_CHECK(32); + SIZE_CHECK(28); } template