Skip to content

Integrate validation and dxc option updates #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2104,6 +2104,11 @@ The set of validation rules that are known to hold for a DXIL program is identif
Rule Code Description
===================================== =======================================================================================================================================================================================================================================================================================================
BITCODE.VALID TODO - Module must be bitcode-valid
CONTAINER.PARTINVALID DXIL Container must not contain unknown parts
CONTAINER.PARTMATCHES DXIL Container Parts must match Module
CONTAINER.PARTMISSING DXIL Container requires certain parts, corresponding to module
CONTAINER.PARTREPEATED DXIL Container must have only one of each part type
CONTAINER.ROOTSIGNATUREINCOMPATIBLE Root Signature in DXIL Container must be compatible with shader
DECL.DXILFNEXTERN External function must be a DXIL function
DECL.DXILNSRESERVED The DXIL reserved prefixes must only be used by built-in functions and types
DECL.FNFLATTENPARAM Function parameters must not use struct types
Expand Down Expand Up @@ -2236,7 +2241,7 @@ SM.GSOUTPUTVERTEXCOUNTRANGE GS output vertex count must be [0..%0]. %
SM.GSTOTALOUTPUTVERTEXDATARANGE Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2. This value cannot be greater than %3
SM.GSVALIDINPUTPRIMITIVE GS input primitive unrecognized
SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY GS output primitive topology unrecognized
SM.HSINPUTCONTROLPOINTCOUNTRANGE HS input control point count must be [1..%0]. %1 specified
SM.HSINPUTCONTROLPOINTCOUNTRANGE HS input control point count must be [0..%0]. %1 specified
SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH For pass thru hull shader, input control point count must match output control point count
SM.INSIDETESSFACTORSIZEMATCHDOMAIN InsideTessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column.
SM.INVALIDRESOURCECOMPTYPE Invalid resource return type
Expand Down Expand Up @@ -2272,6 +2277,7 @@ SM.THREADGROUPCHANNELRANGE Declared Thread Group %0 size %1 outside v
SM.TRIOUTPUTPRIMITIVEMISMATCH Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
SM.UNDEFINEDOUTPUT Not all elements of output %0 were written
SM.VALIDDOMAIN Invalid Tessellator Domain specified. Must be isoline, tri or quad
SM.ZEROHSINPUTCONTROLPOINTWITHINPUT When HS input control point count is 0, no input signature should exist
TYPES.DEFINED Type must be defined based on DXIL primitives
TYPES.I8 I8 can only used as immediate value for intrinsic
TYPES.INTWIDTH Int type must be of valid width
Expand Down
27 changes: 25 additions & 2 deletions include/dxc/HLSL/DxilContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@

#include <stdint.h>
#include <iterator>
#include <functional>
#include "dxc/HLSL/DxilConstants.h"

struct IDxcContainerReflection;
namespace llvm { class Module; }

namespace hlsl {

class AbstractMemoryStream;
class RootSignatureHandle;
class DxilModule;

#pragma pack(push, 1)

static const size_t DxilContainerHashSize = 16;
Expand Down Expand Up @@ -368,8 +373,26 @@ inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major,
return ((unsigned)shaderType << 16) | (major << 4) | minor;
}

class AbstractMemoryStream;
void SerializeDxilContainerForModule(llvm::Module *pModule,
class DxilPartWriter {
public:
virtual uint32_t size() const = 0;
virtual void write(AbstractMemoryStream *pStream) = 0;
};

DxilPartWriter *NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind);
DxilPartWriter *NewRootSignatureWriter(const RootSignatureHandle &S);
DxilPartWriter *NewFeatureInfoWriter(const DxilModule &M);
DxilPartWriter *NewPSVWriter(const DxilModule &M);

class DxilContainerWriter : public DxilPartWriter {
public:
typedef std::function<void(AbstractMemoryStream*)> WriteFn;
virtual void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) = 0;
};

DxilContainerWriter *NewDxilContainerWriter();

void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
AbstractMemoryStream *pModuleBitcode,
AbstractMemoryStream *pStream);
void CreateDxcContainerReflection(IDxcContainerReflection **ppResult);
Expand Down
8 changes: 5 additions & 3 deletions include/dxc/HLSL/DxilMetadataHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class DxilMDHelper {
// Entry points.
static const char kDxilEntryPointsMDName[];

// Root Signature, for intermediate use, not valid in final DXIL module.
static const char kDxilRootSignatureMDName[];

static const unsigned kDxilEntryPointNumFields = 5;
static const unsigned kDxilEntryPointFunction = 0; // Entry point function symbol.
static const unsigned kDxilEntryPointName = 1; // Entry point unmangled name.
Expand Down Expand Up @@ -181,7 +184,6 @@ class DxilMDHelper {
static const unsigned kDxilDSStateTag = 2;
static const unsigned kDxilHSStateTag = 3;
static const unsigned kDxilNumThreadsTag = 4;
static const unsigned kDxilRootSignatureTag = 5;

// GSState.
static const unsigned kDxilGSStateNumFields = 5;
Expand Down Expand Up @@ -261,11 +263,11 @@ class DxilMDHelper {
void LoadDxilSignatures(const llvm::MDOperand &MDO, DxilSignature &InputSig,
DxilSignature &OutputSig, DxilSignature &PCSig);
llvm::MDTuple *EmitSignatureMetadata(const DxilSignature &Sig);
llvm::Metadata *EmitRootSignature(RootSignatureHandle &RootSig);
void EmitRootSignature(RootSignatureHandle &RootSig);
void LoadSignatureMetadata(const llvm::MDOperand &MDO, DxilSignature &Sig);
llvm::MDTuple *EmitSignatureElement(const DxilSignatureElement &SE);
void LoadSignatureElement(const llvm::MDOperand &MDO, DxilSignatureElement &SE);
void LoadRootSignature(const llvm::MDOperand &MDO, RootSignatureHandle &RootSig);
void LoadRootSignature(RootSignatureHandle &RootSig);

// Resources.
llvm::MDTuple *EmitDxilResourceTuple(llvm::MDTuple *pSRVs, llvm::MDTuple *pUAVs,
Expand Down
6 changes: 6 additions & 0 deletions include/dxc/HLSL/DxilModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class DxilModule {
const DxilSignature &GetPatchConstantSignature() const;
const RootSignatureHandle &GetRootSignature() const;

// Remove Root Signature from module metadata
void StripRootSignatureFromMetadata();

// DXIL type system.
DxilTypeSystem &GetTypeSystem();

Expand All @@ -121,6 +124,9 @@ class DxilModule {

void StripDebugRelatedCode();
llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();

static DxilModule *TryGetDxilModule(llvm::Module *pModule);

public:
// Shader properties.
class ShaderFlags {
Expand Down
99 changes: 51 additions & 48 deletions include/dxc/HLSL/DxilPipelineStateValidation.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#ifndef __DXIL_PIPELINE_STATE_VALIDATION__H__
#define __DXIL_PIPELINE_STATE_VALIDATION__H__

#include <stdint.h>
#include <string.h>

// Versioning is additive and based on size
struct PSVRuntimeInfo0
{
Expand All @@ -20,29 +23,29 @@ struct PSVRuntimeInfo0
char OutputPositionPresent;
} VS;
struct HSInfo {
UINT InputControlPointCount; // max control points == 32
UINT OutputControlPointCount; // max control points == 32
UINT TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
UINT TessellatorOutputPrimitive; // hlsl::DXIL::TessellatorOutputPrimitive/D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE
uint32_t InputControlPointCount; // max control points == 32
uint32_t OutputControlPointCount; // max control points == 32
uint32_t TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
uint32_t TessellatorOutputPrimitive; // hlsl::DXIL::TessellatorOutputPrimitive/D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE
} HS;
struct DSInfo {
UINT InputControlPointCount; // max control points == 32
uint32_t InputControlPointCount; // max control points == 32
char OutputPositionPresent;
UINT TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
uint32_t TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN
} DS;
struct GSInfo {
UINT InputPrimitive; // hlsl::DXIL::InputPrimitive/D3D10_SB_PRIMITIVE
UINT OutputTopology; // hlsl::DXIL::PrimitiveTopology/D3D10_SB_PRIMITIVE_TOPOLOGY
UINT OutputStreamMask; // max streams == 4
uint32_t InputPrimitive; // hlsl::DXIL::InputPrimitive/D3D10_SB_PRIMITIVE
uint32_t OutputTopology; // hlsl::DXIL::PrimitiveTopology/D3D10_SB_PRIMITIVE_TOPOLOGY
uint32_t OutputStreamMask; // max streams == 4
char OutputPositionPresent;
} GS;
struct PSInfo {
char DepthOutput;
char SampleFrequency;
} PS;
};
UINT MinimumExpectedWaveLaneCount; // minimum lane count required, 0 if unused
UINT MaximumExpectedWaveLaneCount; // maximum lane count required, 0xffffffff if unused
uint32_t MinimumExpectedWaveLaneCount; // minimum lane count required, 0 if unused
uint32_t MaximumExpectedWaveLaneCount; // maximum lane count required, 0xffffffff if unused
};
// PSVRuntimeInfo1 would derive and extend

Expand All @@ -66,21 +69,21 @@ enum class PSVResourceType
// Versioning is additive and based on size
struct PSVResourceBindInfo0
{
UINT ResType; // PSVResourceType
UINT Space;
UINT LowerBound;
UINT UpperBound;
uint32_t ResType; // PSVResourceType
uint32_t Space;
uint32_t LowerBound;
uint32_t UpperBound;
};
// PSVResourceBindInfo1 would derive and extend

class DxilPipelineStateValidation
{
UINT m_uPSVRuntimeInfoSize;
uint32_t m_uPSVRuntimeInfoSize;
PSVRuntimeInfo0* m_pPSVRuntimeInfo0;
UINT m_uResourceCount;
UINT m_uPSVResourceBindInfoSize;
uint32_t m_uResourceCount;
uint32_t m_uPSVResourceBindInfoSize;
void* m_pPSVResourceBindInfo;
UINT m_uSize;
uint32_t m_uSize;

public:
DxilPipelineStateValidation() :
Expand All @@ -93,70 +96,70 @@ class DxilPipelineStateValidation
}

// Init() from PSV0 blob part that looks like:
// UINT PSVRuntimeInfo_size
// uint32_t PSVRuntimeInfo_size
// { PSVRuntimeInfoN structure }
// UINT ResourceCount
// uint32_t ResourceCount
// --- end of blob if ResourceCount == 0 ---
// UINT PSVResourceBindInfo_size
// uint32_t PSVResourceBindInfo_size
// { PSVResourceBindInfoN structure } * ResourceCount
// returns true if no errors occurred.
bool InitFromPSV0(const void* pBits, UINT size) {
bool InitFromPSV0(const void* pBits, uint32_t size) {
if(!(pBits != nullptr)) return false;
const BYTE* pCurBits = (BYTE*)pBits;
UINT minsize = sizeof(PSVRuntimeInfo0) + sizeof(UINT) * 2;
const uint8_t* pCurBits = (uint8_t*)pBits;
uint32_t minsize = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2;
if(!(size >= minsize)) return false;
m_uPSVRuntimeInfoSize = *((const UINT*)pCurBits);
m_uPSVRuntimeInfoSize = *((const uint32_t*)pCurBits);
if(!(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo0))) return false;
pCurBits += sizeof(UINT);
minsize = m_uPSVRuntimeInfoSize + sizeof(UINT) * 2;
pCurBits += sizeof(uint32_t);
minsize = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2;
if(!(size >= minsize)) return false;
m_pPSVRuntimeInfo0 = const_cast<PSVRuntimeInfo0*>((const PSVRuntimeInfo0*)pCurBits);
pCurBits += m_uPSVRuntimeInfoSize;
m_uResourceCount = *(const UINT*)pCurBits;
pCurBits += sizeof(UINT);
m_uResourceCount = *(const uint32_t*)pCurBits;
pCurBits += sizeof(uint32_t);
if (m_uResourceCount > 0) {
minsize += sizeof(UINT);
minsize += sizeof(uint32_t);
if(!(size >= minsize)) return false;
m_uPSVResourceBindInfoSize = *(const UINT*)pCurBits;
pCurBits += sizeof(UINT);
m_uPSVResourceBindInfoSize = *(const uint32_t*)pCurBits;
pCurBits += sizeof(uint32_t);
minsize += m_uPSVResourceBindInfoSize * m_uResourceCount;
if(!(m_uPSVResourceBindInfoSize >= sizeof(PSVResourceBindInfo0))) return false;
if(!(size >= minsize)) return false;
m_pPSVResourceBindInfo = static_cast<void*>(const_cast<BYTE*>(pCurBits));
m_pPSVResourceBindInfo = static_cast<void*>(const_cast<uint8_t*>(pCurBits));
}
return true;
}

// Initialize a new buffer
// call with null pBuffer to get required size
bool InitNew(UINT ResourceCount, void *pBuffer, UINT *pSize) {
bool InitNew(uint32_t ResourceCount, void *pBuffer, uint32_t *pSize) {
if(!(pSize)) return false;
UINT size = sizeof(PSVRuntimeInfo0) + sizeof(UINT) * 2;
uint32_t size = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2;
if (ResourceCount) {
size += sizeof(UINT) + (sizeof(PSVResourceBindInfo0) * ResourceCount);
size += sizeof(uint32_t) + (sizeof(PSVResourceBindInfo0) * ResourceCount);
}
if (pBuffer) {
if(!(*pSize >= size)) return false;
} else {
*pSize = size;
return true;
}
::ZeroMemory(pBuffer, size);
memset(pBuffer, 0, size);
m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
BYTE* pCurBits = (BYTE*)pBuffer;
*(UINT*)pCurBits = sizeof(PSVRuntimeInfo0);
pCurBits += sizeof(UINT);
uint8_t* pCurBits = (uint8_t*)pBuffer;
*(uint32_t*)pCurBits = sizeof(PSVRuntimeInfo0);
pCurBits += sizeof(uint32_t);
m_pPSVRuntimeInfo0 = (PSVRuntimeInfo0*)pCurBits;
pCurBits += sizeof(PSVRuntimeInfo0);

// Set resource info:
m_uResourceCount = ResourceCount;
*(UINT*)pCurBits = ResourceCount;
pCurBits += sizeof(UINT);
*(uint32_t*)pCurBits = ResourceCount;
pCurBits += sizeof(uint32_t);
if (ResourceCount > 0) {
m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
*(UINT*)pCurBits = m_uPSVResourceBindInfoSize;
pCurBits += sizeof(UINT);
*(uint32_t*)pCurBits = m_uPSVResourceBindInfoSize;
pCurBits += sizeof(uint32_t);
m_pPSVResourceBindInfo = pCurBits;
}
return true;
Expand All @@ -166,14 +169,14 @@ class DxilPipelineStateValidation
return m_pPSVRuntimeInfo0;
}

UINT GetBindCount() const {
uint32_t GetBindCount() const {
return m_uResourceCount;
}

PSVResourceBindInfo0* GetPSVResourceBindInfo0(UINT index) {
PSVResourceBindInfo0* GetPSVResourceBindInfo0(uint32_t index) {
if (index < m_uResourceCount && m_pPSVResourceBindInfo &&
sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize) {
return (PSVResourceBindInfo0*)((BYTE*)m_pPSVResourceBindInfo +
return (PSVResourceBindInfo0*)((uint8_t*)m_pPSVResourceBindInfo +
(index * m_uPSVResourceBindInfoSize));
}
return nullptr;
Expand Down
28 changes: 23 additions & 5 deletions include/dxc/HLSL/DxilRootSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
struct IDxcBlob;
struct IDxcBlobEncoding;

namespace llvm {
class raw_ostream;
}

namespace hlsl {

// Forward declarations.
Expand Down Expand Up @@ -318,13 +322,17 @@ class RootSignatureHandle {
bool IsEmpty() const {
return m_pDesc == nullptr && m_pSerialized == nullptr;
}
IDxcBlob *GetSerialized() const { return m_pSerialized; }
const uint8_t *GetSerializedBytes() const;
unsigned GetSerializedSize() const;

void Assign(const DxilVersionedRootSignatureDesc *pDesc, IDxcBlob *pSerialized);
void Clear();
void LoadSerialized(const uint8_t *pData, unsigned length);
void LoadSerialized(const uint8_t *pData, uint32_t length);
void EnsureSerializedAvailable();
void Deserialize();

const DxilVersionedRootSignatureDesc *GetDesc() const { return m_pDesc; }
};

void DeleteRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature);
Expand All @@ -334,10 +342,20 @@ void ConvertRootSignature(const DxilVersionedRootSignatureDesc* pRootSignatureIn
DxilRootSignatureVersion RootSignatureVersionOut,
const DxilVersionedRootSignatureDesc ** ppRootSignatureOut);

void SerializeRootSignature(
const DxilVersionedRootSignatureDesc *pRootSignature,
_Outptr_ IDxcBlob **ppBlob, _Outptr_ IDxcBlobEncoding **ppErrorBlob,
bool bAllowReservedRegisterSpace);
void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
_Outptr_ IDxcBlob **ppBlob, _Outptr_ IDxcBlobEncoding **ppErrorBlob,
bool bAllowReservedRegisterSpace);

void DeserializeRootSignature(__in_bcount(SrcDataSizeInBytes) const void *pSrcData,
__in uint32_t SrcDataSizeInBytes,
__out const DxilVersionedRootSignatureDesc **ppRootSignature);

// Takes PSV - pipeline state validation data, not shader container.
bool VerifyRootSignatureWithShaderPSV(__in const DxilVersionedRootSignatureDesc *pDesc,
__in DXIL::ShaderKind ShaderKind,
_In_reads_bytes_(PSVSize) const void *pPSVData,
__in uint32_t PSVSize,
__in llvm::raw_ostream &DiagStream);

} // namespace hlsl

Expand Down
Loading