Skip to content

Commit

Permalink
WinPIX: Changes to support bitfields in PIX's shader debugger (micros…
Browse files Browse the repository at this point in the history
…oft#6219)

Two related sets of changes:
1) Modify the value-to-declare pass to tolerate bitfields, which are
detected by their habit of being smaller than the type in which they are
contained. The pass produces dbg.declare statements that map each HLSL
variable to some storage. With bitfields, that mapping becomes
many-to-one, because many bitfields can be stored in the same basic
type. Most of the changes are to preserve the size of the bitfield as
the code descends the type hierarchy into the underlying basic type,
which is what motivates these new "type overrride" parameters to some
functions. Complications to watch out for are min16 types, which may or
may not be their own purpose-made (16-bit) types depending on whether or
not they are enabled.
2) Modify the PIX debug-info API to return enough data to PIX to allow
it to extract (by bit shifting) a bitfield from the underlying type.
This bit is also about preserving knowledge of the field's size as
opposed to its containing type's size, hence the new dxcapi
interface/method.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
jeffnn and github-actions[bot] committed Feb 2, 2024
1 parent 74e3256 commit a23d586
Show file tree
Hide file tree
Showing 7 changed files with 436 additions and 81 deletions.
11 changes: 11 additions & 0 deletions include/dxc/dxcpix.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,23 @@ struct __declspec(uuid("9ba0d9d3-457b-426f-8019-9f3849982aa2")) IDxcPixArrayType
};

struct __declspec(uuid("6c707d08-7995-4a84-bae5-e6d8291f3b78"))
IDxcPixStructField0 : public IUnknown {
virtual STDMETHODIMP GetName(_Outptr_result_z_ BSTR *Name) = 0;

virtual STDMETHODIMP GetType(_COM_Outptr_ IDxcPixType **ppType) = 0;

virtual STDMETHODIMP GetOffsetInBits(_Out_ DWORD *pOffsetInBits) = 0;
};

struct __declspec(uuid("de45597c-5869-4f97-a77b-d6650b9a16cf"))
IDxcPixStructField : public IUnknown {
virtual STDMETHODIMP GetName(_Outptr_result_z_ BSTR *Name) = 0;

virtual STDMETHODIMP GetType(_COM_Outptr_ IDxcPixType **ppType) = 0;

virtual STDMETHODIMP GetOffsetInBits(_Out_ DWORD *pOffsetInBits) = 0;

virtual STDMETHODIMP GetFieldSizeInBits(_Out_ DWORD *pFieldSizeInBits) = 0;
};

struct __declspec(uuid("24c08c44-684b-4b1c-b41b-f8772383d074"))
Expand Down
29 changes: 21 additions & 8 deletions lib/DxilDia/DxcPixEntrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ HRESULT CreateEntrypointWrapper(IMalloc *pMalloc, IUnknown *pReal, REFIID iid,
// Entrypoint is the base class for all entrypoints, providing
// the default QueryInterface implementation, as well as a
// more convenient way of calling SetupAndRun.
template <typename I> class Entrypoint : public I {
template <typename I, typename IParent = I> class Entrypoint : public I {
protected:
using IInterface = I;

Expand All @@ -251,15 +251,16 @@ template <typename I> class Entrypoint : public I {

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **ppvObject) override final {
return SetupAndRun(m_pMalloc,
std::mem_fn(&Entrypoint<IInterface>::QueryInterfaceImpl),
ThisPtr(this), iid, CheckNotNull(OutParam(ppvObject)));
return SetupAndRun(
m_pMalloc,
std::mem_fn(&Entrypoint<IInterface, IParent>::QueryInterfaceImpl),
ThisPtr(this), iid, CheckNotNull(OutParam(ppvObject)));
}

HRESULT STDMETHODCALLTYPE QueryInterfaceImpl(REFIID iid, void **ppvObject) {
// Special-casing so we don't need to create a new wrapper.
if (iid == __uuidof(IInterface) || iid == __uuidof(IUnknown) ||
iid == __uuidof(INoMarshal)) {
if (iid == __uuidof(IInterface) || iid == __uuidof(IParent) ||
iid == __uuidof(IUnknown) || iid == __uuidof(INoMarshal)) {
this->AddRef();
*ppvObject = this;
return S_OK;
Expand All @@ -275,6 +276,11 @@ template <typename I> class Entrypoint : public I {
Name(IMalloc *M, IInterface *pI) : Entrypoint<IInterface>(M, pI) {} \
DXC_MICROCOM_TM_ALLOC(Name)

#define DEFINE_ENTRYPOINT_BOILERPLATE2(Name, ParentIFace) \
Name(IMalloc *M, IInterface *pI) \
: Entrypoint<IInterface, ParentIFace>(M, pI) {} \
DXC_MICROCOM_TM_ALLOC(Name)

struct IUnknownEntrypoint : public Entrypoint<IUnknown> {
DEFINE_ENTRYPOINT_BOILERPLATE(IUnknownEntrypoint);
};
Expand Down Expand Up @@ -390,8 +396,10 @@ struct IDxcPixArrayTypeEntrypoint : public Entrypoint<IDxcPixArrayType> {
};
DEFINE_ENTRYPOINT_WRAPPER_TRAIT(IDxcPixArrayType);

struct IDxcPixStructFieldEntrypoint : public Entrypoint<IDxcPixStructField> {
DEFINE_ENTRYPOINT_BOILERPLATE(IDxcPixStructFieldEntrypoint);
struct IDxcPixStructFieldEntrypoint
: public Entrypoint<IDxcPixStructField, IDxcPixStructField0> {
DEFINE_ENTRYPOINT_BOILERPLATE2(IDxcPixStructFieldEntrypoint,
IDxcPixStructField0);

STDMETHODIMP GetName(BSTR *Name) override {
return InvokeOnReal(&IInterface::GetName, CheckNotNull(OutParam(Name)));
Expand All @@ -401,6 +409,11 @@ struct IDxcPixStructFieldEntrypoint : public Entrypoint<IDxcPixStructField> {
return InvokeOnReal(&IInterface::GetType, CheckNotNull(OutParam(ppType)));
}

STDMETHODIMP GetFieldSizeInBits(DWORD *pFieldSizeInBits) override {
return InvokeOnReal(&IInterface::GetFieldSizeInBits,
CheckNotNull(OutParam(pFieldSizeInBits)));
}

STDMETHODIMP GetOffsetInBits(DWORD *pOffsetInBits) override {
return InvokeOnReal(&IInterface::GetOffsetInBits,
CheckNotNull(OutParam(pOffsetInBits)));
Expand Down
2 changes: 1 addition & 1 deletion lib/DxilDia/DxcPixLiveVariables_FragmentIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ InitialOffsetInBitsFromDIExpression(const llvm::DataLayout &DataLayout,
}

FragmentOffsetInBits = Expression->getBitPieceOffset();
assert(Expression->getBitPieceSize() ==
assert(Expression->getBitPieceSize() <=
DataLayout.getTypeAllocSizeInBits(Alloca->getAllocatedType()));
}

Expand Down
7 changes: 7 additions & 0 deletions lib/DxilDia/DxcPixTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,10 @@ dxil_debug_info::DxcPixStructField::GetOffsetInBits(DWORD *pOffsetInBits) {
*pOffsetInBits = m_pField->getOffsetInBits();
return S_OK;
}

STDMETHODIMP
dxil_debug_info::DxcPixStructField::GetFieldSizeInBits(
DWORD *pFieldSizeInBits) {
*pFieldSizeInBits = m_pField->getSizeInBits();
return S_OK;
}
11 changes: 11 additions & 0 deletions lib/DxilDia/DxcPixTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ class DxcPixStructType : public IDxcPixStructType2 {
STDMETHODIMP GetBaseType(IDxcPixType **ppType) override;
};

struct __declspec(uuid("6c707d08-7995-4a84-bae5-e6d8291f3b78"))
PreviousDxcPixStructField {};

class DxcPixStructField : public IDxcPixStructField {
private:
DXC_MICROCOM_TM_REF_FIELDS()
Expand All @@ -228,6 +231,12 @@ class DxcPixStructField : public IDxcPixStructField {

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **ppvObject) override {
if (IsEqualIID(iid, __uuidof(PreviousDxcPixStructField))) {
*(IDxcPixStructField **)ppvObject = this;
this->AddRef();
return S_OK;
}

return DoBasicQueryInterface<IDxcPixStructField>(this, iid, ppvObject);
}

Expand All @@ -236,5 +245,7 @@ class DxcPixStructField : public IDxcPixStructField {
STDMETHODIMP GetType(IDxcPixType **ppType) override;

STDMETHODIMP GetOffsetInBits(DWORD *pOffsetInBits) override;

STDMETHODIMP GetFieldSizeInBits(DWORD *pFieldSizeInBits) override;
};
} // namespace dxil_debug_info

0 comments on commit a23d586

Please sign in to comment.