|
@@ -14,17 +14,25 @@
|
|
|
|
|
|
#include <stdint.h>
|
|
|
#include <string.h>
|
|
|
+#include "assert.h"
|
|
|
+
|
|
|
#ifndef UINT_MAX
|
|
|
#define UINT_MAX 0xffffffff
|
|
|
#endif
|
|
|
// How many dwords are required for mask with one bit per component, 4 components per vector
|
|
|
inline uint32_t PSVComputeMaskDwordsFromVectors(uint32_t Vectors) { return (Vectors + 7) >> 3; }
|
|
|
-inline uint32_t PSVComputeInputOutputTableSize(uint32_t InputVectors, uint32_t OutputVectors) {
|
|
|
- return sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(OutputVectors) * InputVectors * 4;
|
|
|
+inline uint32_t PSVComputeInputOutputTableDwords(uint32_t InputVectors, uint32_t OutputVectors) {
|
|
|
+ return PSVComputeMaskDwordsFromVectors(OutputVectors) * InputVectors * 4;
|
|
|
}
|
|
|
#define PSVALIGN(ptr, alignbits) (((ptr) + ((1 << (alignbits))-1)) & ~((1 << (alignbits))-1))
|
|
|
#define PSVALIGN4(ptr) (((ptr) + 3) & ~3)
|
|
|
|
|
|
+#ifdef DBG
|
|
|
+#define PSV_RETB(exp) do { if(!(exp)) { assert(false && #exp); return false; } } while(0)
|
|
|
+#else // DBG
|
|
|
+#define PSV_RETB(exp) do { if(!(exp)) { return false; } } while(0)
|
|
|
+#endif // DBG
|
|
|
+
|
|
|
struct VSInfo {
|
|
|
char OutputPositionPresent;
|
|
|
};
|
|
@@ -335,230 +343,122 @@ public:
|
|
|
struct PSVInitInfo
|
|
|
{
|
|
|
PSVInitInfo(uint32_t psvVersion)
|
|
|
- : PSVVersion(psvVersion),
|
|
|
- ResourceCount(0),
|
|
|
- ShaderStage(PSVShaderKind::Invalid),
|
|
|
- StringTable(),
|
|
|
- SemanticIndexTable(),
|
|
|
- UsesViewID(0),
|
|
|
- SigInputElements(0),
|
|
|
- SigOutputElements(0),
|
|
|
- SigPatchConstOrPrimElements(0),
|
|
|
- SigInputVectors(0),
|
|
|
- SigPatchConstOrPrimVectors(0)
|
|
|
+ : PSVVersion(psvVersion)
|
|
|
{}
|
|
|
- uint32_t PSVVersion;
|
|
|
- uint32_t ResourceCount;
|
|
|
- PSVShaderKind ShaderStage;
|
|
|
+ uint32_t PSVVersion = 0;
|
|
|
+ uint32_t ResourceCount = 0;
|
|
|
+ PSVShaderKind ShaderStage = PSVShaderKind::Invalid;
|
|
|
PSVStringTable StringTable;
|
|
|
PSVSemanticIndexTable SemanticIndexTable;
|
|
|
- uint8_t UsesViewID;
|
|
|
- uint8_t SigInputElements;
|
|
|
- uint8_t SigOutputElements;
|
|
|
- uint8_t SigPatchConstOrPrimElements;
|
|
|
- uint8_t SigInputVectors;
|
|
|
- uint8_t SigPatchConstOrPrimVectors;
|
|
|
+ uint8_t UsesViewID = 0;
|
|
|
+ uint8_t SigInputElements = 0;
|
|
|
+ uint8_t SigOutputElements = 0;
|
|
|
+ uint8_t SigPatchConstOrPrimElements = 0;
|
|
|
+ uint8_t SigInputVectors = 0;
|
|
|
+ uint8_t SigPatchConstOrPrimVectors = 0;
|
|
|
uint8_t SigOutputVectors[4] = {0, 0, 0, 0};
|
|
|
+
|
|
|
+ static_assert(MAX_PSV_VERSION == 1, "otherwise this needs updating.");
|
|
|
+ uint32_t RuntimeInfoSize() const {
|
|
|
+ if (PSVVersion < 1)
|
|
|
+ return sizeof(PSVRuntimeInfo0);
|
|
|
+ return sizeof(PSVRuntimeInfo1);
|
|
|
+ }
|
|
|
+ uint32_t ResourceBindInfoSize() const {
|
|
|
+ return sizeof(PSVResourceBindInfo0);
|
|
|
+ }
|
|
|
+ uint32_t SignatureElementSize() const {
|
|
|
+ return sizeof(PSVSignatureElement0);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
class DxilPipelineStateValidation
|
|
|
{
|
|
|
- uint32_t m_uPSVRuntimeInfoSize;
|
|
|
- PSVRuntimeInfo0* m_pPSVRuntimeInfo0;
|
|
|
- PSVRuntimeInfo1* m_pPSVRuntimeInfo1;
|
|
|
- uint32_t m_uResourceCount;
|
|
|
- uint32_t m_uPSVResourceBindInfoSize;
|
|
|
- void* m_pPSVResourceBindInfo;
|
|
|
+ uint32_t m_uPSVRuntimeInfoSize = 0;
|
|
|
+ PSVRuntimeInfo0* m_pPSVRuntimeInfo0 = nullptr;
|
|
|
+ PSVRuntimeInfo1 *m_pPSVRuntimeInfo1 = nullptr;
|
|
|
+ uint32_t m_uResourceCount = 0;
|
|
|
+ uint32_t m_uPSVResourceBindInfoSize = 0;
|
|
|
+ void *m_pPSVResourceBindInfo = nullptr;
|
|
|
PSVStringTable m_StringTable;
|
|
|
PSVSemanticIndexTable m_SemanticIndexTable;
|
|
|
- uint32_t m_uPSVSignatureElementSize;
|
|
|
- void* m_pSigInputElements;
|
|
|
- void* m_pSigOutputElements;
|
|
|
- void* m_pSigPatchConstOrPrimElements;
|
|
|
- uint32_t* m_pViewIDOutputMask;
|
|
|
- uint32_t* m_pViewIDPCOrPrimOutputMask;
|
|
|
- uint32_t* m_pInputToOutputTable;
|
|
|
- uint32_t* m_pInputToPCOutputTable;
|
|
|
- uint32_t* m_pPCInputToOutputTable;
|
|
|
+ uint32_t m_uPSVSignatureElementSize = 0;
|
|
|
+ void *m_pSigInputElements = nullptr;
|
|
|
+ void *m_pSigOutputElements = nullptr;
|
|
|
+ void *m_pSigPatchConstOrPrimElements = nullptr;
|
|
|
+ uint32_t *m_pViewIDOutputMask = nullptr;
|
|
|
+ uint32_t *m_pViewIDPCOrPrimOutputMask = nullptr;
|
|
|
+ uint32_t *m_pInputToOutputTable = nullptr;
|
|
|
+ uint32_t *m_pInputToPCOutputTable = nullptr;
|
|
|
+ uint32_t *m_pPCInputToOutputTable = nullptr;
|
|
|
|
|
|
public:
|
|
|
- DxilPipelineStateValidation() :
|
|
|
- m_uPSVRuntimeInfoSize(0),
|
|
|
- m_pPSVRuntimeInfo0(nullptr),
|
|
|
- m_pPSVRuntimeInfo1(nullptr),
|
|
|
- m_uResourceCount(0),
|
|
|
- m_uPSVResourceBindInfoSize(0),
|
|
|
- m_pPSVResourceBindInfo(nullptr),
|
|
|
- m_StringTable(),
|
|
|
- m_SemanticIndexTable(),
|
|
|
- m_uPSVSignatureElementSize(0),
|
|
|
- m_pSigInputElements(nullptr),
|
|
|
- m_pSigOutputElements(nullptr),
|
|
|
- m_pSigPatchConstOrPrimElements(nullptr),
|
|
|
- m_pViewIDOutputMask(nullptr),
|
|
|
- m_pViewIDPCOrPrimOutputMask(nullptr),
|
|
|
- m_pInputToOutputTable(nullptr),
|
|
|
- m_pInputToPCOutputTable(nullptr),
|
|
|
- m_pPCInputToOutputTable(nullptr)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- // Init() from PSV0 blob part that looks like:
|
|
|
- // uint32_t PSVRuntimeInfo_size
|
|
|
- // { PSVRuntimeInfoN structure }
|
|
|
- // uint32_t ResourceCount
|
|
|
- // If ResourceCount > 0:
|
|
|
- // uint32_t PSVResourceBindInfo_size
|
|
|
- // { PSVResourceBindInfoN structure } * ResourceCount
|
|
|
- // If PSVRuntimeInfo1:
|
|
|
- // uint32_t StringTableSize (dword aligned)
|
|
|
- // If StringTableSize:
|
|
|
- // { StringTableSize bytes, null terminated }
|
|
|
- // uint32_t SemanticIndexTableEntries (number of dwords)
|
|
|
- // If SemanticIndexTableEntries:
|
|
|
- // { semantic index } * SemanticIndexTableEntries
|
|
|
- // If SigInputElements || SigOutputElements || SigPatchConstOrPrimElements:
|
|
|
- // uint32_t PSVSignatureElement_size
|
|
|
- // { PSVSignatureElementN structure } * SigInputElements
|
|
|
- // { PSVSignatureElementN structure } * SigOutputElements
|
|
|
- // { PSVSignatureElementN structure } * SigPatchConstOrPrimElements
|
|
|
- // If (UsesViewID):
|
|
|
- // For (i : each stream index 0-3):
|
|
|
- // If (SigOutputVectors[i] non-zero):
|
|
|
- // { uint32_t * PSVComputeMaskDwordsFromVectors(SigOutputVectors[i]) }
|
|
|
- // - Outputs affected by ViewID as a bitmask
|
|
|
- // If (HS and SigPatchConstOrPrimVectors non-zero):
|
|
|
- // { uint32_t * PSVComputeMaskDwordsFromVectors(SigPatchConstOrPrimVectors) }
|
|
|
- // - PCOutputs affected by ViewID as a bitmask
|
|
|
- // For (i : each stream index 0-3):
|
|
|
- // If (SigInputVectors and SigOutputVectors[i] non-zero):
|
|
|
- // { PSVComputeInputOutputTableSize(SigInputVectors, SigOutputVectors[i]) }
|
|
|
- // - Outputs affected by inputs as a table of bitmasks
|
|
|
- // If (HS and SigPatchConstOrPrimVectors and SigInputVectors non-zero):
|
|
|
- // { PSVComputeInputOutputTableSize(SigInputVectors, SigPatchConstOrPrimVectors) }
|
|
|
- // - Patch constant outputs affected by inputs as a table of bitmasks
|
|
|
- // If (DS and SigOutputVectors[0] and SigPatchConstOrPrimVectors non-zero):
|
|
|
- // { PSVComputeInputOutputTableSize(SigPatchConstOrPrimVectors, SigOutputVectors[0]) }
|
|
|
- // - Outputs affected by patch constant inputs as a table of bitmasks
|
|
|
- // returns true if no errors occurred.
|
|
|
- bool InitFromPSV0(const void* pBits, uint32_t size) {
|
|
|
- if(!(pBits != nullptr)) return false;
|
|
|
- uint8_t* pCurBits = (uint8_t*)const_cast<void*>(pBits);
|
|
|
- uint32_t minsize = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2;
|
|
|
- if(!(size >= minsize)) return false;
|
|
|
- m_uPSVRuntimeInfoSize = *((const uint32_t*)pCurBits);
|
|
|
- if(!(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo0))) return false;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- minsize = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2;
|
|
|
- if(!(size >= minsize)) return false;
|
|
|
- m_pPSVRuntimeInfo0 = const_cast<PSVRuntimeInfo0*>((const PSVRuntimeInfo0*)pCurBits);
|
|
|
- if(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo1))
|
|
|
- m_pPSVRuntimeInfo1 = const_cast<PSVRuntimeInfo1*>((const PSVRuntimeInfo1*)pCurBits);
|
|
|
- pCurBits += m_uPSVRuntimeInfoSize;
|
|
|
- m_uResourceCount = *(const uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- if (m_uResourceCount > 0) {
|
|
|
- minsize += sizeof(uint32_t);
|
|
|
- if(!(size >= minsize)) return false;
|
|
|
- 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<uint8_t*>(pCurBits));
|
|
|
- }
|
|
|
- pCurBits += m_uPSVResourceBindInfoSize * m_uResourceCount;
|
|
|
-
|
|
|
- if (m_pPSVRuntimeInfo1) {
|
|
|
- minsize += sizeof(uint32_t) * 2; // m_StringTable.Size and m_SemanticIndexTable.Entries
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_StringTable.Size = PSVALIGN4(*(uint32_t*)pCurBits);
|
|
|
- if (m_StringTable.Size != *(uint32_t*)pCurBits)
|
|
|
- return false; // Illegal: Size not aligned
|
|
|
- minsize += m_StringTable.Size;
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- m_StringTable.Table = (const char *)pCurBits;
|
|
|
- pCurBits += m_StringTable.Size;
|
|
|
-
|
|
|
- m_SemanticIndexTable.Entries = *(uint32_t*)pCurBits;
|
|
|
- minsize += sizeof(uint32_t) * m_SemanticIndexTable.Entries;
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- m_SemanticIndexTable.Table = (uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * m_SemanticIndexTable.Entries;
|
|
|
-
|
|
|
- // Dxil Signature Elements
|
|
|
- if (m_pPSVRuntimeInfo1->SigInputElements || m_pPSVRuntimeInfo1->SigOutputElements || m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
- minsize += sizeof(uint32_t);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_uPSVSignatureElementSize = *(uint32_t*)pCurBits;
|
|
|
- if (m_uPSVSignatureElementSize < sizeof(PSVSignatureElement0))
|
|
|
- return false; // Illegal: Size smaller than first version
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- minsize += m_uPSVSignatureElementSize * (m_pPSVRuntimeInfo1->SigInputElements + m_pPSVRuntimeInfo1->SigOutputElements + m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigInputElements) {
|
|
|
- m_pSigInputElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigInputElements;
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigOutputElements) {
|
|
|
- m_pSigOutputElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigOutputElements;
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
- m_pSigPatchConstOrPrimElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements;
|
|
|
- }
|
|
|
+ DxilPipelineStateValidation() {}
|
|
|
|
|
|
- // ViewID dependencies
|
|
|
- if (m_pPSVRuntimeInfo1->UsesViewID) {
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- if (m_pPSVRuntimeInfo1->SigOutputVectors[i]) {
|
|
|
- minsize += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_pViewIDOutputMask = (uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- }
|
|
|
- if (!IsGS())
|
|
|
- break;
|
|
|
- }
|
|
|
- if ((IsHS() || IsMS()) && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors) {
|
|
|
- minsize += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_pViewIDPCOrPrimOutputMask = (uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- }
|
|
|
+ enum class RWMode {
|
|
|
+ Read,
|
|
|
+ CalcSize,
|
|
|
+ Write,
|
|
|
+ };
|
|
|
|
|
|
- // Input to Output dependencies
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- if (!IsMS() && m_pPSVRuntimeInfo1->SigOutputVectors[i] > 0 && m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
- minsize += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_pInputToOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- }
|
|
|
- if (!IsGS())
|
|
|
- break;
|
|
|
- }
|
|
|
- if ((IsHS() || IsMS()) && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0 && m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
- minsize += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_pInputToPCOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- if (IsDS() && m_pPSVRuntimeInfo1->SigOutputVectors[0] > 0 && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0) {
|
|
|
- minsize += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors, m_pPSVRuntimeInfo1->SigOutputVectors[0]);
|
|
|
- if (!(size >= minsize)) return false;
|
|
|
- m_pPCInputToOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors, m_pPSVRuntimeInfo1->SigOutputVectors[0]);
|
|
|
- }
|
|
|
- }
|
|
|
+ class CheckedReaderWriter {
|
|
|
+ private:
|
|
|
+ char *Ptr;
|
|
|
+ uint32_t Size;
|
|
|
+ uint32_t Offset;
|
|
|
+ RWMode Mode;
|
|
|
+
|
|
|
+ public:
|
|
|
+ CheckedReaderWriter(const void *ptr, uint32_t size, RWMode mode)
|
|
|
+ : Ptr(reinterpret_cast<char*>(const_cast<void*>(ptr))),
|
|
|
+ Size(mode == RWMode::CalcSize ? 0 : size), Offset(0), Mode(mode) {}
|
|
|
+
|
|
|
+ uint32_t GetSize() { return Size; }
|
|
|
+ RWMode GetMode() { return Mode; }
|
|
|
+
|
|
|
+ // Return true if size fits in remaing buffer.
|
|
|
+ bool CheckBounds(size_t size);
|
|
|
+ // Increment Offset by size. Return false on error.
|
|
|
+ bool IncrementPos(size_t size);
|
|
|
+
|
|
|
+ // Cast and return true if it fits.
|
|
|
+ template <typename _T> bool Cast(_T **ppPtr, size_t size);
|
|
|
+ template <typename _T> bool Cast(_T **ppPtr);
|
|
|
+
|
|
|
+ // Map* methods increment Offset.
|
|
|
+
|
|
|
+ // Assign pointer, increment Offset, and return true if size fits.
|
|
|
+ template<typename _T> bool MapPtr(_T **ppPtr, size_t size = 0);
|
|
|
+ // Read value, increment Offset, and return true if value fits.
|
|
|
+ template <typename _T> bool MapValue(_T *pValue, const _T init = {});
|
|
|
+ // Assign pointer, increment Offset, and return true if array fits.
|
|
|
+ template <typename _T>
|
|
|
+ bool MapArray(_T **ppPtr, size_t count, size_t eltSize);
|
|
|
+ //template <> bool MapArray<void>(void **ppPtr, size_t count, size_t eltSize);
|
|
|
+ // Assign pointer, increment Offset, and return true if array fits.
|
|
|
+ template <typename _T> bool MapArray(_T **ppPtr, size_t count = 1);
|
|
|
+
|
|
|
+ void Clear();
|
|
|
+ };
|
|
|
+
|
|
|
+ // Assigned derived ptr to base if size large enough.
|
|
|
+ template<typename _Base, typename _T>
|
|
|
+ bool AssignDerived(_T** ppDerived, _Base* pBase, uint32_t size) {
|
|
|
+ if ((size_t)size < sizeof(_T))
|
|
|
+ return false; // size not large enough for type
|
|
|
+ *ppDerived = reinterpret_cast<_T *>(pBase);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+private:
|
|
|
+ bool ReadOrWrite(const void *pBits, uint32_t *pSize, RWMode mode,
|
|
|
+ const PSVInitInfo &initInfo = PSVInitInfo(MAX_PSV_VERSION));
|
|
|
+
|
|
|
+public:
|
|
|
+ bool InitFromPSV0(const void* pBits, uint32_t size) {
|
|
|
+ return ReadOrWrite(pBits, &size, RWMode::Read);
|
|
|
+ }
|
|
|
+
|
|
|
// Initialize a new buffer
|
|
|
// call with null pBuffer to get required size
|
|
|
|
|
@@ -569,174 +469,8 @@ public:
|
|
|
}
|
|
|
|
|
|
bool InitNew(const PSVInitInfo &initInfo, void *pBuffer, uint32_t *pSize) {
|
|
|
- if(!(pSize)) return false;
|
|
|
- if (initInfo.PSVVersion > MAX_PSV_VERSION) return false;
|
|
|
-
|
|
|
- // Versioned structure sizes
|
|
|
- m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0);
|
|
|
- m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0);
|
|
|
- m_uPSVSignatureElementSize = sizeof(PSVSignatureElement0);
|
|
|
- if (initInfo.PSVVersion > 0) {
|
|
|
- m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo1);
|
|
|
- }
|
|
|
-
|
|
|
- // PSVVersion 0
|
|
|
- uint32_t size = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2;
|
|
|
- if (initInfo.ResourceCount) {
|
|
|
- size += sizeof(uint32_t) + (m_uPSVResourceBindInfoSize * initInfo.ResourceCount);
|
|
|
- }
|
|
|
-
|
|
|
- // PSVVersion 1
|
|
|
- if (initInfo.PSVVersion > 0) {
|
|
|
- size += sizeof(uint32_t) + PSVALIGN4(initInfo.StringTable.Size);
|
|
|
- size += sizeof(uint32_t) + sizeof(uint32_t) * initInfo.SemanticIndexTable.Entries;
|
|
|
- if (initInfo.SigInputElements || initInfo.SigOutputElements || initInfo.SigPatchConstOrPrimElements) {
|
|
|
- size += sizeof(uint32_t); // PSVSignatureElement_size
|
|
|
- }
|
|
|
- size += m_uPSVSignatureElementSize * initInfo.SigInputElements;
|
|
|
- size += m_uPSVSignatureElementSize * initInfo.SigOutputElements;
|
|
|
- size += m_uPSVSignatureElementSize * initInfo.SigPatchConstOrPrimElements;
|
|
|
-
|
|
|
- if (initInfo.UsesViewID) {
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- size += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(initInfo.SigOutputVectors[i]);
|
|
|
- if (initInfo.ShaderStage != PSVShaderKind::Geometry)
|
|
|
- break;
|
|
|
- }
|
|
|
- if (initInfo.ShaderStage == PSVShaderKind::Hull || initInfo.ShaderStage == PSVShaderKind::Mesh)
|
|
|
- size += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(initInfo.SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- if (initInfo.SigInputVectors > 0) {
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- if (initInfo.SigOutputVectors[i] > 0) {
|
|
|
- size += PSVComputeInputOutputTableSize(initInfo.SigInputVectors, initInfo.SigOutputVectors[i]);
|
|
|
- if (initInfo.ShaderStage != PSVShaderKind::Geometry)
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (initInfo.ShaderStage == PSVShaderKind::Hull && initInfo.SigPatchConstOrPrimVectors > 0 && initInfo.SigInputVectors > 0) {
|
|
|
- size += PSVComputeInputOutputTableSize(initInfo.SigInputVectors, initInfo.SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- }
|
|
|
- if (initInfo.ShaderStage == PSVShaderKind::Domain && initInfo.SigOutputVectors[0] > 0 && initInfo.SigPatchConstOrPrimVectors > 0) {
|
|
|
- size += PSVComputeInputOutputTableSize(initInfo.SigPatchConstOrPrimVectors, initInfo.SigOutputVectors[0]);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Validate or return required size
|
|
|
- if (pBuffer) {
|
|
|
- if(!(*pSize >= size)) return false;
|
|
|
- } else {
|
|
|
- *pSize = size;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // PSVVersion 0
|
|
|
- memset(pBuffer, 0, size);
|
|
|
- uint8_t* pCurBits = (uint8_t*)pBuffer;
|
|
|
- *(uint32_t*)pCurBits = m_uPSVRuntimeInfoSize;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- m_pPSVRuntimeInfo0 = (PSVRuntimeInfo0*)pCurBits;
|
|
|
- if (initInfo.PSVVersion > 0) {
|
|
|
- m_pPSVRuntimeInfo1 = (PSVRuntimeInfo1*)pCurBits;
|
|
|
- }
|
|
|
- pCurBits += m_uPSVRuntimeInfoSize;
|
|
|
-
|
|
|
- // Set resource info:
|
|
|
- m_uResourceCount = initInfo.ResourceCount;
|
|
|
- *(uint32_t*)pCurBits = m_uResourceCount;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- if (m_uResourceCount > 0) {
|
|
|
- *(uint32_t*)pCurBits = m_uPSVResourceBindInfoSize;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- m_pPSVResourceBindInfo = pCurBits;
|
|
|
- }
|
|
|
- pCurBits += m_uPSVResourceBindInfoSize * m_uResourceCount;
|
|
|
-
|
|
|
- // PSVVersion 1
|
|
|
- if (initInfo.PSVVersion) {
|
|
|
- m_pPSVRuntimeInfo1->ShaderStage = (uint8_t)initInfo.ShaderStage;
|
|
|
- m_pPSVRuntimeInfo1->UsesViewID = initInfo.UsesViewID;
|
|
|
- m_pPSVRuntimeInfo1->SigInputElements = initInfo.SigInputElements;
|
|
|
- m_pPSVRuntimeInfo1->SigOutputElements = initInfo.SigOutputElements;
|
|
|
- m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements = initInfo.SigPatchConstOrPrimElements;
|
|
|
- m_pPSVRuntimeInfo1->SigInputVectors = initInfo.SigInputVectors;
|
|
|
- memcpy(m_pPSVRuntimeInfo1->SigOutputVectors, initInfo.SigOutputVectors, 4);
|
|
|
- if (IsHS() || IsDS() || IsMS()) {
|
|
|
- m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors = initInfo.SigPatchConstOrPrimVectors;
|
|
|
- }
|
|
|
-
|
|
|
- // Note: if original size was unaligned, padding has already been zero initialized
|
|
|
- m_StringTable.Size = PSVALIGN4(initInfo.StringTable.Size);
|
|
|
- *(uint32_t*)pCurBits = m_StringTable.Size;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- memcpy(pCurBits, initInfo.StringTable.Table, initInfo.StringTable.Size);
|
|
|
- m_StringTable.Table = (const char *)pCurBits;
|
|
|
- pCurBits += m_StringTable.Size;
|
|
|
-
|
|
|
- m_SemanticIndexTable.Entries = initInfo.SemanticIndexTable.Entries;
|
|
|
- *(uint32_t*)pCurBits = m_SemanticIndexTable.Entries;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- memcpy(pCurBits, initInfo.SemanticIndexTable.Table, sizeof(uint32_t) * initInfo.SemanticIndexTable.Entries);
|
|
|
- m_SemanticIndexTable.Table = (const uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * m_SemanticIndexTable.Entries;
|
|
|
-
|
|
|
- // Dxil Signature Elements
|
|
|
- if (m_pPSVRuntimeInfo1->SigInputElements || m_pPSVRuntimeInfo1->SigOutputElements || m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
- *(uint32_t*)pCurBits = m_uPSVSignatureElementSize;
|
|
|
- pCurBits += sizeof(uint32_t);
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigInputElements) {
|
|
|
- m_pSigInputElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigInputElements;
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigOutputElements) {
|
|
|
- m_pSigOutputElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigOutputElements;
|
|
|
- }
|
|
|
- if (m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
- m_pSigPatchConstOrPrimElements = (PSVSignatureElement0*)pCurBits;
|
|
|
- pCurBits += m_uPSVSignatureElementSize * m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements;
|
|
|
- }
|
|
|
-
|
|
|
- // ViewID dependencies
|
|
|
- if (m_pPSVRuntimeInfo1->UsesViewID) {
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- if (m_pPSVRuntimeInfo1->SigOutputVectors[i]) {
|
|
|
- m_pViewIDOutputMask = (uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- }
|
|
|
- if (!IsGS())
|
|
|
- break;
|
|
|
- }
|
|
|
- if ((IsHS() || IsMS()) && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors) {
|
|
|
- m_pViewIDPCOrPrimOutputMask = (uint32_t*)pCurBits;
|
|
|
- pCurBits += sizeof(uint32_t) * PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Input to Output dependencies
|
|
|
- if (m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
- for (unsigned i = 0; i < 4; i++) {
|
|
|
- if (m_pPSVRuntimeInfo1->SigOutputVectors[i] > 0) {
|
|
|
- m_pInputToOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigOutputVectors[i]);
|
|
|
- }
|
|
|
- if (!IsGS())
|
|
|
- break;
|
|
|
- }
|
|
|
- if (IsHS() && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0 && m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
- m_pInputToPCOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
- }
|
|
|
- }
|
|
|
- if (IsDS() && m_pPSVRuntimeInfo1->SigOutputVectors[0] > 0 && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0) {
|
|
|
- m_pPCInputToOutputTable = (uint32_t*)pCurBits;
|
|
|
- pCurBits += PSVComputeInputOutputTableSize(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors, m_pPSVRuntimeInfo1->SigOutputVectors[0]);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
+ RWMode Mode = nullptr != pBuffer ? RWMode::Write : RWMode::CalcSize;
|
|
|
+ return ReadOrWrite(pBuffer, pSize, Mode, initInfo);
|
|
|
}
|
|
|
|
|
|
PSVRuntimeInfo0* GetPSVRuntimeInfo0() const {
|
|
@@ -751,15 +485,23 @@ public:
|
|
|
return m_uResourceCount;
|
|
|
}
|
|
|
|
|
|
- PSVResourceBindInfo0* GetPSVResourceBindInfo0(uint32_t index) const {
|
|
|
- if (index < m_uResourceCount && m_pPSVResourceBindInfo &&
|
|
|
- sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize) {
|
|
|
- return (PSVResourceBindInfo0*)((uint8_t*)m_pPSVResourceBindInfo +
|
|
|
- (index * m_uPSVResourceBindInfoSize));
|
|
|
+ template <typename _T>
|
|
|
+ _T *GetRecord(void *pRecords, uint32_t recordSize, uint32_t numRecords,
|
|
|
+ uint32_t index) const {
|
|
|
+ if (pRecords && index < numRecords && sizeof(_T) <= recordSize) {
|
|
|
+ __analysis_assume((size_t)index * (size_t)recordSize <= UINT_MAX);
|
|
|
+ return reinterpret_cast<_T *>(reinterpret_cast<uint8_t *>(pRecords) +
|
|
|
+ (index * recordSize));
|
|
|
}
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
+ PSVResourceBindInfo0* GetPSVResourceBindInfo0(uint32_t index) const {
|
|
|
+ return GetRecord<PSVResourceBindInfo0>(m_pPSVResourceBindInfo,
|
|
|
+ m_uPSVResourceBindInfoSize,
|
|
|
+ m_uResourceCount, index);
|
|
|
+ }
|
|
|
+
|
|
|
const PSVStringTable &GetStringTable() const { return m_StringTable; }
|
|
|
const PSVSemanticIndexTable &GetSemanticIndexTable() const { return m_SemanticIndexTable; }
|
|
|
|
|
@@ -780,31 +522,19 @@ public:
|
|
|
return 0;
|
|
|
}
|
|
|
PSVSignatureElement0* GetInputElement0(uint32_t index) const {
|
|
|
- if (m_pPSVRuntimeInfo1 && m_pSigInputElements &&
|
|
|
- index < m_pPSVRuntimeInfo1->SigInputElements &&
|
|
|
- sizeof(PSVSignatureElement0) <= m_uPSVSignatureElementSize) {
|
|
|
- return (PSVSignatureElement0*)((uint8_t*)m_pSigInputElements +
|
|
|
- (index * m_uPSVSignatureElementSize));
|
|
|
- }
|
|
|
- return nullptr;
|
|
|
+ return GetRecord<PSVSignatureElement0>(
|
|
|
+ m_pSigInputElements, m_uPSVSignatureElementSize,
|
|
|
+ m_pPSVRuntimeInfo1 ? m_pPSVRuntimeInfo1->SigInputElements : 0, index);
|
|
|
}
|
|
|
PSVSignatureElement0* GetOutputElement0(uint32_t index) const {
|
|
|
- if (m_pPSVRuntimeInfo1 && m_pSigOutputElements &&
|
|
|
- index < m_pPSVRuntimeInfo1->SigOutputElements &&
|
|
|
- sizeof(PSVSignatureElement0) <= m_uPSVSignatureElementSize) {
|
|
|
- return (PSVSignatureElement0*)((uint8_t*)m_pSigOutputElements +
|
|
|
- (index * m_uPSVSignatureElementSize));
|
|
|
- }
|
|
|
- return nullptr;
|
|
|
+ return GetRecord<PSVSignatureElement0>(
|
|
|
+ m_pSigOutputElements, m_uPSVSignatureElementSize,
|
|
|
+ m_pPSVRuntimeInfo1 ? m_pPSVRuntimeInfo1->SigOutputElements : 0, index);
|
|
|
}
|
|
|
PSVSignatureElement0* GetPatchConstOrPrimElement0(uint32_t index) const {
|
|
|
- if (m_pPSVRuntimeInfo1 && m_pSigPatchConstOrPrimElements &&
|
|
|
- index < m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements &&
|
|
|
- sizeof(PSVSignatureElement0) <= m_uPSVSignatureElementSize) {
|
|
|
- return (PSVSignatureElement0*)((uint8_t*)m_pSigPatchConstOrPrimElements +
|
|
|
- (index * m_uPSVSignatureElementSize));
|
|
|
- }
|
|
|
- return nullptr;
|
|
|
+ return GetRecord<PSVSignatureElement0>(
|
|
|
+ m_pSigPatchConstOrPrimElements, m_uPSVSignatureElementSize,
|
|
|
+ m_pPSVRuntimeInfo1 ? m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements : 0, index);
|
|
|
}
|
|
|
// More convenient wrapper:
|
|
|
PSVSignatureElement GetSignatureElement(PSVSignatureElement0* pElement0) const {
|
|
@@ -845,7 +575,7 @@ public:
|
|
|
return PSVDependencyTable();
|
|
|
}
|
|
|
PSVDependencyTable GetInputToPCOutputTable() const {
|
|
|
- if ((IsHS() || IsMS()) && m_pInputToPCOutputTable && m_pPSVRuntimeInfo1) {
|
|
|
+ if (IsHS() && m_pInputToPCOutputTable && m_pPSVRuntimeInfo1) {
|
|
|
return PSVDependencyTable(m_pInputToPCOutputTable, m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors);
|
|
|
}
|
|
|
return PSVDependencyTable();
|
|
@@ -858,6 +588,249 @@ public:
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// Return true if size fits in remaing buffer.
|
|
|
+inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::CheckBounds(size_t size) {
|
|
|
+ if (Mode != RWMode::CalcSize) {
|
|
|
+ PSV_RETB(size <= UINT_MAX);
|
|
|
+ PSV_RETB(Offset <= Size);
|
|
|
+ return (uint32_t)size <= Size - Offset;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+// Increment Offset by size. Return false on error.
|
|
|
+inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::IncrementPos(size_t size) {
|
|
|
+ PSV_RETB(size <= UINT_MAX);
|
|
|
+ uint32_t uSize = size;
|
|
|
+ if (Mode == RWMode::CalcSize) {
|
|
|
+ PSV_RETB(uSize <= Size + uSize);
|
|
|
+ Size += uSize;
|
|
|
+ }
|
|
|
+ PSV_RETB(CheckBounds(size));
|
|
|
+ Offset += size;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+// Cast and return true if it fits.
|
|
|
+template <typename _T> inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::Cast(_T **ppPtr, size_t size) {
|
|
|
+ PSV_RETB(CheckBounds(size));
|
|
|
+ *ppPtr = reinterpret_cast<_T*>(Ptr + Offset);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+template <typename _T>
|
|
|
+inline bool DxilPipelineStateValidation::CheckedReaderWriter::Cast(_T **ppPtr) {
|
|
|
+ return Cast(ppPtr, sizeof(_T));
|
|
|
+}
|
|
|
+
|
|
|
+// Map* methods increment Offset.
|
|
|
+
|
|
|
+// Assign pointer, increment Offset, and return true if size fits.
|
|
|
+template<typename _T>
|
|
|
+inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::MapPtr(_T **ppPtr, size_t size) {
|
|
|
+ PSV_RETB(Cast(ppPtr, size));
|
|
|
+ PSV_RETB(IncrementPos(size));
|
|
|
+ return true;
|
|
|
+}
|
|
|
+// Read value, increment Offset, and return true if value fits.
|
|
|
+template <typename _T>
|
|
|
+inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::MapValue(_T *pValue, const _T init) {
|
|
|
+ _T *pPtr = nullptr;
|
|
|
+ PSV_RETB(MapPtr(&pPtr, sizeof(_T)));
|
|
|
+ switch (Mode) {
|
|
|
+ case RWMode::Read: *pValue = *pPtr; break;
|
|
|
+ case RWMode::CalcSize: *pValue = init; break;
|
|
|
+ case RWMode::Write: *pPtr = *pValue = init; break;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+// Assign pointer, increment Offset, and return true if array fits.
|
|
|
+template <typename _T>
|
|
|
+inline bool DxilPipelineStateValidation::CheckedReaderWriter::MapArray(
|
|
|
+ _T **ppPtr, size_t count, size_t eltSize) {
|
|
|
+ PSV_RETB(count <= UINT_MAX && eltSize <= UINT_MAX && eltSize >= sizeof(_T));
|
|
|
+ return count ? MapPtr(ppPtr, eltSize * count) : true;
|
|
|
+}
|
|
|
+//template <> bool MapArray<void>(void **ppPtr, size_t count, size_t eltSize);
|
|
|
+template <>
|
|
|
+inline bool DxilPipelineStateValidation::CheckedReaderWriter::MapArray<void>(
|
|
|
+ void **ppPtr, size_t count, size_t eltSize) {
|
|
|
+ PSV_RETB(count <= UINT_MAX && eltSize <= UINT_MAX && eltSize > 0);
|
|
|
+ return count ? MapPtr(ppPtr, eltSize * count) : true;
|
|
|
+}
|
|
|
+
|
|
|
+// Assign pointer, increment Offset, and return true if array fits.
|
|
|
+template <typename _T>
|
|
|
+inline bool
|
|
|
+DxilPipelineStateValidation::CheckedReaderWriter::MapArray(_T **ppPtr, size_t count) {
|
|
|
+ return count ? MapArray(ppPtr, count, sizeof(_T)) : true;
|
|
|
+}
|
|
|
+
|
|
|
+inline void DxilPipelineStateValidation::CheckedReaderWriter::Clear() {
|
|
|
+ if (Mode == RWMode::Write) {
|
|
|
+ memset(Ptr, 0, Size);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// PSV0 blob part looks like:
|
|
|
+// uint32_t PSVRuntimeInfo_size
|
|
|
+// { PSVRuntimeInfoN structure }
|
|
|
+// uint32_t ResourceCount
|
|
|
+// If ResourceCount > 0:
|
|
|
+// uint32_t PSVResourceBindInfo_size
|
|
|
+// { PSVResourceBindInfoN structure } * ResourceCount
|
|
|
+// If PSVRuntimeInfo1:
|
|
|
+// uint32_t StringTableSize (dword aligned)
|
|
|
+// If StringTableSize:
|
|
|
+// { StringTableSize bytes, null terminated }
|
|
|
+// uint32_t SemanticIndexTableEntries (number of dwords)
|
|
|
+// If SemanticIndexTableEntries:
|
|
|
+// { semantic index } * SemanticIndexTableEntries
|
|
|
+// If SigInputElements || SigOutputElements || SigPatchConstOrPrimElements:
|
|
|
+// uint32_t PSVSignatureElement_size
|
|
|
+// { PSVSignatureElementN structure } * SigInputElements
|
|
|
+// { PSVSignatureElementN structure } * SigOutputElements
|
|
|
+// { PSVSignatureElementN structure } * SigPatchConstOrPrimElements
|
|
|
+// If (UsesViewID):
|
|
|
+// For (i : each stream index 0-3):
|
|
|
+// If (SigOutputVectors[i] non-zero):
|
|
|
+// { uint32_t * PSVComputeMaskDwordsFromVectors(SigOutputVectors[i]) }
|
|
|
+// - Outputs affected by ViewID as a bitmask
|
|
|
+// If (HS and SigPatchConstOrPrimVectors non-zero):
|
|
|
+// { uint32_t * PSVComputeMaskDwordsFromVectors(SigPatchConstOrPrimVectors) }
|
|
|
+// - PCOutputs affected by ViewID as a bitmask
|
|
|
+// For (i : each stream index 0-3):
|
|
|
+// If (SigInputVectors and SigOutputVectors[i] non-zero):
|
|
|
+// { uint32_t * PSVComputeInputOutputTableDwords(SigInputVectors, SigOutputVectors[i]) }
|
|
|
+// - Outputs affected by inputs as a table of bitmasks
|
|
|
+// If (HS and SigPatchConstOrPrimVectors and SigInputVectors non-zero):
|
|
|
+// { uint32_t * PSVComputeInputOutputTableDwords(SigInputVectors, SigPatchConstOrPrimVectors) }
|
|
|
+// - Patch constant outputs affected by inputs as a table of bitmasks
|
|
|
+// If (DS and SigOutputVectors[0] and SigPatchConstOrPrimVectors non-zero):
|
|
|
+// { uint32_t * PSVComputeInputOutputTableDwords(SigPatchConstOrPrimVectors, SigOutputVectors[0]) }
|
|
|
+// - Outputs affected by patch constant inputs as a table of bitmasks
|
|
|
+// returns true if no errors occurred.
|
|
|
+inline bool DxilPipelineStateValidation::ReadOrWrite(
|
|
|
+ const void *pBits, uint32_t *pSize, RWMode mode,
|
|
|
+ const PSVInitInfo &initInfo) {
|
|
|
+ PSV_RETB(pSize != nullptr);
|
|
|
+ PSV_RETB(pBits != nullptr || mode == RWMode::CalcSize);
|
|
|
+ PSV_RETB(initInfo.PSVVersion <= MAX_PSV_VERSION);
|
|
|
+
|
|
|
+ CheckedReaderWriter rw(pBits, *pSize, mode);
|
|
|
+ rw.Clear();
|
|
|
+
|
|
|
+ PSV_RETB(rw.MapValue(&m_uPSVRuntimeInfoSize, initInfo.RuntimeInfoSize()));
|
|
|
+ PSV_RETB(rw.MapArray(&m_pPSVRuntimeInfo0, 1, m_uPSVRuntimeInfoSize));
|
|
|
+ AssignDerived(&m_pPSVRuntimeInfo1, m_pPSVRuntimeInfo0, m_uPSVRuntimeInfoSize); // failure ok
|
|
|
+
|
|
|
+ // In RWMode::CalcSize, use temp runtime info to hold needed values from initInfo
|
|
|
+ PSVRuntimeInfo1 tempRuntimeInfo = {};
|
|
|
+ if (mode == RWMode::CalcSize && initInfo.PSVVersion > 0) {
|
|
|
+ m_pPSVRuntimeInfo1 = &tempRuntimeInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ PSV_RETB(rw.MapValue(&m_uResourceCount, initInfo.ResourceCount));
|
|
|
+
|
|
|
+ if (m_uResourceCount > 0) {
|
|
|
+ PSV_RETB(rw.MapValue(&m_uPSVResourceBindInfoSize, initInfo.ResourceBindInfoSize()));
|
|
|
+ PSV_RETB(sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize);
|
|
|
+ PSV_RETB(rw.MapArray(&m_pPSVResourceBindInfo, m_uResourceCount, m_uPSVResourceBindInfoSize));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_pPSVRuntimeInfo1) {
|
|
|
+ if (mode != RWMode::Read) {
|
|
|
+ m_pPSVRuntimeInfo1->ShaderStage = (uint8_t)initInfo.ShaderStage;
|
|
|
+ m_pPSVRuntimeInfo1->SigInputElements = initInfo.SigInputElements;
|
|
|
+ m_pPSVRuntimeInfo1->SigOutputElements = initInfo.SigOutputElements;
|
|
|
+ m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements = initInfo.SigPatchConstOrPrimElements;
|
|
|
+ m_pPSVRuntimeInfo1->UsesViewID = initInfo.UsesViewID;
|
|
|
+ for (unsigned i = 0; i < 4; i++) {
|
|
|
+ m_pPSVRuntimeInfo1->SigOutputVectors[i] = initInfo.SigOutputVectors[i];
|
|
|
+ }
|
|
|
+ if (IsHS() || IsDS() || IsMS()) {
|
|
|
+ m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors = initInfo.SigPatchConstOrPrimVectors;
|
|
|
+ }
|
|
|
+ m_pPSVRuntimeInfo1->SigInputVectors = initInfo.SigInputVectors;
|
|
|
+ }
|
|
|
+
|
|
|
+ PSV_RETB(rw.MapValue(&m_StringTable.Size, PSVALIGN4(initInfo.StringTable.Size)));
|
|
|
+ PSV_RETB(PSVALIGN4(m_StringTable.Size) == m_StringTable.Size);
|
|
|
+ if (m_StringTable.Size) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_StringTable.Table, m_StringTable.Size));
|
|
|
+ if (mode == RWMode::Write) {
|
|
|
+ memcpy(const_cast<char*>(m_StringTable.Table), initInfo.StringTable.Table, initInfo.StringTable.Size);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ PSV_RETB(rw.MapValue(&m_SemanticIndexTable.Entries, initInfo.SemanticIndexTable.Entries));
|
|
|
+ if (m_SemanticIndexTable.Entries) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_SemanticIndexTable.Table, m_SemanticIndexTable.Entries));
|
|
|
+ if (mode == RWMode::Write) {
|
|
|
+ memcpy(const_cast<uint32_t*>(m_SemanticIndexTable.Table), initInfo.SemanticIndexTable.Table, sizeof(uint32_t) * initInfo.SemanticIndexTable.Entries);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Dxil Signature Elements
|
|
|
+ if (m_pPSVRuntimeInfo1->SigInputElements || m_pPSVRuntimeInfo1->SigOutputElements || m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
+ PSV_RETB(rw.MapValue(&m_uPSVSignatureElementSize, initInfo.SignatureElementSize()));
|
|
|
+ PSV_RETB(sizeof(PSVSignatureElement0) <= m_uPSVSignatureElementSize);
|
|
|
+ if (m_pPSVRuntimeInfo1->SigInputElements) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pSigInputElements, m_pPSVRuntimeInfo1->SigInputElements, m_uPSVSignatureElementSize));
|
|
|
+ }
|
|
|
+ if (m_pPSVRuntimeInfo1->SigOutputElements) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pSigOutputElements, m_pPSVRuntimeInfo1->SigOutputElements, m_uPSVSignatureElementSize));
|
|
|
+ }
|
|
|
+ if (m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pSigPatchConstOrPrimElements, m_pPSVRuntimeInfo1->SigPatchConstOrPrimElements, m_uPSVSignatureElementSize));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ViewID dependencies
|
|
|
+ if (m_pPSVRuntimeInfo1->UsesViewID) {
|
|
|
+ for (unsigned i = 0; i < 4; i++) {
|
|
|
+ if (m_pPSVRuntimeInfo1->SigOutputVectors[i]) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pViewIDOutputMask,
|
|
|
+ PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigOutputVectors[i])));
|
|
|
+ }
|
|
|
+ if (!IsGS())
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if ((IsHS() || IsMS()) && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pViewIDPCOrPrimOutputMask,
|
|
|
+ PSVComputeMaskDwordsFromVectors(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Input to Output dependencies
|
|
|
+ for (unsigned i = 0; i < 4; i++) {
|
|
|
+ if (!IsMS() && m_pPSVRuntimeInfo1->SigOutputVectors[i] > 0 && m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pInputToOutputTable,
|
|
|
+ PSVComputeInputOutputTableDwords(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigOutputVectors[i])));
|
|
|
+ }
|
|
|
+ if (!IsGS())
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (IsHS() && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0 && m_pPSVRuntimeInfo1->SigInputVectors > 0) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pInputToPCOutputTable,
|
|
|
+ PSVComputeInputOutputTableDwords(m_pPSVRuntimeInfo1->SigInputVectors, m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors)));
|
|
|
+ }
|
|
|
+ if (IsDS() && m_pPSVRuntimeInfo1->SigOutputVectors[0] > 0 && m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors > 0) {
|
|
|
+ PSV_RETB(rw.MapArray(&m_pPCInputToOutputTable,
|
|
|
+ PSVComputeInputOutputTableDwords(m_pPSVRuntimeInfo1->SigPatchConstOrPrimVectors, m_pPSVRuntimeInfo1->SigOutputVectors[0])));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mode == RWMode::CalcSize) {
|
|
|
+ *pSize = rw.GetSize();
|
|
|
+ m_pPSVRuntimeInfo1 = nullptr; // clear ptr to tempRuntimeInfo
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
namespace hlsl {
|
|
|
|
|
|
class ViewIDValidator {
|
|
@@ -885,4 +858,6 @@ namespace hlsl {
|
|
|
|
|
|
}
|
|
|
|
|
|
+#undef PSV_RETB
|
|
|
+
|
|
|
#endif // __DXIL_PIPELINE_STATE_VALIDATION__H__
|