[llvm] 5fdf860 - [DX] Fix PSV resource serialization

Chris Bieneman via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 19 16:02:43 PDT 2023


Author: Chris Bieneman
Date: 2023-07-19T18:01:01-05:00
New Revision: 5fdf8605102014825dc79e1859f218228dbcd15f

URL: https://github.com/llvm/llvm-project/commit/5fdf8605102014825dc79e1859f218228dbcd15f
DIFF: https://github.com/llvm/llvm-project/commit/5fdf8605102014825dc79e1859f218228dbcd15f.diff

LOG: [DX] Fix PSV resource serialization

When writing this initially I missed including the resource stride.
This change adds the resources stride to the serialized value.

I've also extended the testing and error reporting around parsing PSV
information. This adds tests to verify that the reader produces
meaningful error messages for malformed DXContainer files, and a test
that verifies the resource stride is respected in the reader even if
the stride isn't an expected or known value (as would happen if the
format changes in the future).

This is part of #59479.

Reviewed By: bogner, bob80905

Differential Revision: https://reviews.llvm.org/D155143

Added: 
    

Modified: 
    llvm/include/llvm/Object/DXContainer.h
    llvm/include/llvm/ObjectYAML/DXContainerYAML.h
    llvm/lib/MC/DXContainerPSVInfo.cpp
    llvm/lib/Object/DXContainer.cpp
    llvm/lib/ObjectYAML/DXContainerYAML.cpp
    llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
    llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
    llvm/tools/obj2yaml/dxcontainer2yaml.cpp
    llvm/unittests/Object/DXContainerTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index 55371d14a36893..ece2dfdd8b2d8c 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -35,16 +35,19 @@ class PSVRuntimeInfo {
   // swaps it as appropriate.
   struct ResourceArray {
     StringRef Data;
-    size_t Stride; // size of each element in the list.
+    uint32_t Stride; // size of each element in the list.
 
     ResourceArray() = default;
     ResourceArray(StringRef D, size_t S) : Data(D), Stride(S) {}
 
     using value_type = dxbc::PSV::v2::ResourceBindInfo;
+    static constexpr uint32_t MaxStride() {
+      return static_cast<uint32_t>(sizeof(value_type));
+    }
 
     struct iterator {
       StringRef Data;
-      size_t Stride; // size of each element in the list.
+      uint32_t Stride; // size of each element in the list.
       const char *Current;
 
       iterator(const ResourceArray &A, const char *C)
@@ -58,7 +61,8 @@ class PSVRuntimeInfo {
         value_type Val = {{0, 0, 0, 0}, 0, 0};
         if (Current >= Data.end())
           return Val;
-        memcpy(static_cast<void *>(&Val), Current, Stride);
+        memcpy(static_cast<void *>(&Val), Current,
+               std::min(Stride, MaxStride()));
         if (sys::IsBigEndianHost)
           Val.swapBytes();
         return Val;
@@ -123,6 +127,8 @@ class PSVRuntimeInfo {
                : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo) ? 1 : 0);
   }
 
+  uint32_t getResourceStride() const { return Resources.Stride; }
+
   const InfoStruct &getInfo() const { return BasicInfo; }
 };
 

diff  --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 299c8bfaaa20ce..5dff8b3db9d012 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -80,6 +80,7 @@ struct PSVInfo {
   uint32_t Version;
 
   dxbc::PSV::v2::RuntimeInfo Info;
+  uint32_t ResourceStride;
   std::vector<ResourceBindInfo> Resources;
 
   void mapInfoForVersion(yaml::IO &IO);

diff  --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp
index a3444d0adb7267..ea12495bad3d68 100644
--- a/llvm/lib/MC/DXContainerPSVInfo.cpp
+++ b/llvm/lib/MC/DXContainerPSVInfo.cpp
@@ -16,16 +16,20 @@ using namespace llvm::dxbc::PSV;
 
 void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
   uint32_t InfoSize;
+  uint32_t BindingSize;
   switch (Version) {
   case 0:
     InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo);
+    BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
     break;
   case 1:
     InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo);
+    BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);
     break;
   case 2:
   default:
     InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);
+    BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);
   }
   uint32_t InfoSizeSwapped = InfoSize;
   if (sys::IsBigEndianHost)
@@ -40,8 +44,7 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
     sys::swapByteOrder(ResourceCount);
   OS.write(reinterpret_cast<const char *>(&ResourceCount), sizeof(uint32_t));
 
-  size_t BindingSize = (Version < 2) ? sizeof(v0::ResourceBindInfo)
-                                     : sizeof(v2::ResourceBindInfo);
+  OS.write(reinterpret_cast<const char *>(&BindingSize), sizeof(uint32_t));
   for (const auto &Res : Resources)
     OS.write(reinterpret_cast<const char *>(&Res), BindingSize);
 }

diff  --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index a0f0698c3c9bc3..48932afea84b88 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -200,6 +200,10 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
 
   StringRef PSVInfoData = Data.substr(sizeof(uint32_t), Size);
 
+  if (PSVInfoData.size() < Size)
+    return parseFailed(
+        "Pipeline state data extends beyond the bounds of the part");
+
   using namespace dxbc::PSV;
 
   const uint32_t PSVVersion = getVersion();
@@ -234,12 +238,20 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
     return Err;
   Current += sizeof(uint32_t);
 
-  Resources.Stride = (PSVVersion < 2) ? sizeof(v0::ResourceBindInfo)
-                                      : sizeof(v2::ResourceBindInfo);
-  size_t BindingDataSize = Resources.Stride * ResourceCount;
-  Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);
+  if (ResourceCount > 0) {
+    if (Error Err = readInteger(Data, Current, Resources.Stride))
+      return Err;
+    Current += sizeof(uint32_t);
+
+    size_t BindingDataSize = Resources.Stride * ResourceCount;
+    Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);
 
-  Current += BindingDataSize;
+    if (Resources.Data.size() < BindingDataSize)
+      return parseFailed(
+          "Resource binding data extends beyond the bounds of the part");
+
+    Current += BindingDataSize;
+  }
 
   return Error::success();
 }

diff  --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 741b0cb47586ff..ed9f39954111cc 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -127,6 +127,7 @@ void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
   IO.mapRequired("ShaderStage", PSV.Info.ShaderStage);
   PSV.mapInfoForVersion(IO);
 
+  IO.mapRequired("ResourceStride", PSV.ResourceStride);
   IO.mapRequired("Resources", PSV.Resources);
 
   // Restore the YAML context.

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml
index 4b9999f389951f..d15bfadda41f07 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-amplification.yaml
@@ -17,6 +17,7 @@ Parts:
       PayloadSizeInBytes: 4092
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -45,6 +46,7 @@ Parts:
 # CHECK-NEXT: PayloadSizeInBytes: 4092
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml
index 84111d0afe9e29..7e9f2fbd8b54de 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-compute.yaml
@@ -16,6 +16,7 @@ Parts:
       ShaderStage:     5
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -43,6 +44,7 @@ Parts:
 # CHECK-NEXT: ShaderStage:     5
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml
index c5ca43a0b4cc15..db2aee954b3466 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-domain.yaml
@@ -19,6 +19,7 @@ Parts:
       TessellatorDomain: 2056
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -49,6 +50,7 @@ Parts:
 # CHECK-NEXT: TessellatorDomain: 2056
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml
index 96e8b2788e443c..5509ac669e2d6b 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-geometry.yaml
@@ -20,6 +20,7 @@ Parts:
       OutputPositionPresent: 1
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -51,6 +52,7 @@ Parts:
 # CHECK-NEXT: OutputPositionPresent: 1
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml
index 811387404d6a1d..cd60f2b192b2e2 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-hull.yaml
@@ -20,6 +20,7 @@ Parts:
       TessellatorOutputPrimitive: 8192
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -51,6 +52,7 @@ Parts:
 # CHECK-NEXT: TessellatorOutputPrimitive: 8192
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml
index 4d8c6d4b423112..07fb656c5b72a7 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-mesh.yaml
@@ -21,6 +21,7 @@ Parts:
       MaxOutputPrimitives: 4092
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -53,6 +54,7 @@ Parts:
 # CHECK-NEXT: MaxOutputPrimitives: 4092
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml
index c05471cb013bb8..c7f956e5740cca 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-pixel.yaml
@@ -18,6 +18,7 @@ Parts:
       SampleFrequency: 96
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -47,6 +48,7 @@ Parts:
 # CHECK-NEXT: SampleFrequency: 96
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml
index fe176add546e17..6df9169b73e2f5 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-vertex.yaml
@@ -17,6 +17,7 @@ Parts:
       OutputPositionPresent: 1
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -45,6 +46,7 @@ Parts:
 # CHECK-NEXT: OutputPositionPresent: 1
 # CHECK-NEXT: MinimumWaveLaneCount: 0
 # CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
index 310df02ed43fa3..94c215c1fffc8f 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
@@ -23,6 +23,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -57,6 +58,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
index d8233a78ea4985..715b28b812c820 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
@@ -22,6 +22,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -55,6 +56,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
index 87826edf03672f..472b5e0a94779e 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
@@ -26,6 +26,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -63,6 +64,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
index a081cde1be65ae..0c0a4ed70a1a22 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
@@ -27,6 +27,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -65,6 +66,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
index 4c5f60de69c9eb..330d24ff8597f8 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
@@ -27,6 +27,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -65,6 +66,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
index c969620e4f3303..51bd6390df15e1 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
@@ -29,6 +29,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -69,6 +70,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
index 279fd098e6ab89..2e49034f4e3fc0 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
@@ -24,6 +24,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -59,6 +60,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
index aa2a17aedd6409..ad8f08200d5072 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
@@ -23,6 +23,7 @@ Parts:
       SigPatchConstOrPrimElements: 32
       SigInputVectors: 64
       SigOutputVectors: [ 8, 16, 32, 64 ]
+      ResourceStride:       16
       Resources:
         - Type:            1
           Space:           2
@@ -57,6 +58,7 @@ Parts:
 # CHECK-NEXT: SigPatchConstOrPrimElements: 32
 # CHECK-NEXT: SigInputVectors: 64
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
+# CHECK-NEXT: ResourceStride: 16
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
index f2b431e522be67..d4fee91294099a 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
@@ -26,6 +26,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -67,6 +68,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
index fd477b3c1df09e..5ee136bf227505 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
@@ -25,6 +25,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -65,6 +66,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
index f339a42789f56f..4ed9f04e9dc4a1 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
@@ -29,6 +29,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -73,6 +74,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
index 09150dd1442049..66def9becdef12 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
@@ -30,6 +30,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -75,6 +76,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
index 9a07346525c973..0a35992c89b804 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
@@ -30,6 +30,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -75,6 +76,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
index d6e8be4dd6c1ca..ec81b60b0d8378 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
@@ -32,6 +32,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -79,6 +80,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
index 841c1e91e1a826..60e53f8fb7b063 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
@@ -27,6 +27,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -69,6 +70,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
index 786cbc76078185..15b227c06fad3d 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
@@ -26,6 +26,7 @@ Parts:
       NumThreadsX:     512
       NumThreadsY:     1024
       NumThreadsZ:     2048
+      ResourceStride:       24
       Resources:
         - Type:            1
           Space:           2
@@ -67,6 +68,7 @@ Parts:
 # CHECK-NEXT: NumThreadsX:     512
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
+# CHECK-NEXT: ResourceStride: 24
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            1
 # CHECK-NEXT: Space:           2

diff  --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index f33f565ecdc505..dd3bea67c75fca 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -89,6 +89,7 @@ dumpDXContainer(MemoryBufferRef Source) {
       else if (const auto *P =
                    std::get_if<dxbc::PSV::v2::RuntimeInfo>(&PSVInfo->getInfo()))
         NewPart.Info = DXContainerYAML::PSVInfo(P);
+      NewPart.Info->ResourceStride = PSVInfo->getResourceStride();
       for (auto Res : PSVInfo->getResources())
         NewPart.Info->Resources.push_back(Res);
       break;

diff  --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index 4d7daaf9f4d098..151fab0ac81c70 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -219,6 +219,7 @@ TEST(DXCFile, PSVResourceIterators) {
       PayloadSizeInBytes: 4092
       MinimumWaveLaneCount: 0
       MaximumWaveLaneCount: 4294967295
+      ResourceStride:  16
       Resources:
         - Type:            1
           Space:           1
@@ -334,9 +335,261 @@ TEST(DXCFile, PSVResourceIterators) {
     EXPECT_EQ(Binding.Type, 0u);
     EXPECT_EQ(Binding.Flags, 0u);
   }
-  
+
   Binding = *It;
 
   EXPECT_EQ(Binding.Type, 3u);
   EXPECT_EQ(Binding.Flags, 0u);
 }
+
+// The malicious file bits in these tests are mutations of the binary produced
+// by the following YAML:
+//
+// --- !dxcontainer
+// Header:
+//   Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+//                      0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+//   Version:
+//     Major:           1
+//     Minor:           0
+//   PartCount:       3
+// Parts:
+//   - Name:            DXIL
+//     Size:            24
+//     Program:
+//       MajorVersion:    6
+//       MinorVersion:    0
+//       ShaderKind:      14
+//       Size:            6
+//       DXILMajorVersion: 0
+//       DXILMinorVersion: 1
+//       DXILSize:        0
+//   - Name:            PSV0
+//     Size:            36
+//     PSVInfo:
+//       Version:         0
+//       ShaderStage:     5
+//       MinimumWaveLaneCount: 0
+//       MaximumWaveLaneCount: 0
+//       ResourceStride:       16
+//       Resources: []
+//   - Name: BLEH
+//     Size: 16
+// ...
+
+TEST(DXCFile, MaliciousFiles) {
+
+  // In this file blob, the file size is specified as 96 bytes (0x60), and the
+  // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of
+  // the file.
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+        0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+        0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+        0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    EXPECT_THAT_EXPECTED(
+        DXContainer::create(getMemoryBuffer<96>(Buffer)),
+        FailedWithMessage(
+            "Pipeline state data extends beyond the bounds of the part"));
+  }
+
+  // PSV extends beyond part, but in file range. In this blob the file size is
+  // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is
+  // 40 bytes (0x40).
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
+        0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+        0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
+        0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
+        0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+        0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    EXPECT_THAT_EXPECTED(
+        DXContainer::create(getMemoryBuffer<144>(Buffer)),
+        FailedWithMessage(
+            "Pipeline state data extends beyond the bounds of the part"));
+  }
+
+  // In this file blob, the file is 116 bytes (0x74). The file structure is
+  // valid except that it specifies 1 16 byte resource binding which would
+  // extend beyond the range of the part and file.
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+        0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+        0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+        0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+    };
+    EXPECT_THAT_EXPECTED(
+        DXContainer::create(getMemoryBuffer<116>(Buffer)),
+        FailedWithMessage(
+            "Resource binding data extends beyond the bounds of the part"));
+  }
+
+  // In this file blob, the file is 116 bytes (0x74). The file structure is
+  // valid except that it specifies 1 16 byte resource binding which would
+  // extend beyond the range of the part and into the `BLEH` part.
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
+        0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
+        0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
+        0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
+        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+        0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    EXPECT_THAT_EXPECTED(
+        DXContainer::create(getMemoryBuffer<144>(Buffer)),
+        FailedWithMessage(
+            "Resource binding data extends beyond the bounds of the part"));
+  }
+}
+
+// This test verifies that the resource iterator follows the stride even if the
+// stride doesn't match an expected or known value. In this test, the resource
+// data is structured validly, with 32 bytes per resource. This test is based on
+// editing the binary output constructed from this yaml.
+//
+// --- !dxcontainer
+// Header:
+//   Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+//                      0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+//   Version:
+//     Major:           1
+//     Minor:           0
+//   PartCount:       2
+// Parts:
+//   - Name:            DXIL
+//     Size:            24
+//     Program:
+//       MajorVersion:    6
+//       MinorVersion:    0
+//       ShaderKind:      14
+//       Size:            6
+//       DXILMajorVersion: 0
+//       DXILMinorVersion: 1
+//       DXILSize:        0
+//   - Name:            PSV0
+//     Size:            100
+//     PSVInfo:
+//       Version:         0
+//       ShaderStage:     5
+//       MinimumWaveLaneCount: 0
+//       MaximumWaveLaneCount: 0
+//       ResourceStride:       16
+//       Resources:
+//         - Type:            1
+//           Space:           2
+//           LowerBound:      3
+//           UpperBound:      4
+//         - Type:            5
+//           Space:           6
+//           LowerBound:      7
+//           UpperBound:      8
+// ...
+TEST(DXCFile, PSVResourceIteratorsStride) {
+  uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+        0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
+        0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00,
+        0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00,
+        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+        0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+    }; 
+    DXContainer C =
+      llvm::cantFail(DXContainer::create(getMemoryBuffer<180>(Buffer)));
+
+  const auto &PSVInfo = C.getPSVInfo();
+  ASSERT_TRUE(PSVInfo.has_value());
+
+  ASSERT_EQ(PSVInfo->getResourceCount(), 2u);
+
+  auto It = PSVInfo->getResources().begin();
+
+  EXPECT_TRUE(It == PSVInfo->getResources().begin());
+
+  dxbc::PSV::v2::ResourceBindInfo Binding;
+
+  Binding = *It;
+  EXPECT_EQ(Binding.Type, 1u);
+  EXPECT_EQ(Binding.Space, 2u);
+  EXPECT_EQ(Binding.LowerBound, 3u);
+  EXPECT_EQ(Binding.UpperBound, 4u);
+
+  ++It;
+  Binding = *It;
+
+  EXPECT_EQ(Binding.Type, 5u);
+  EXPECT_EQ(Binding.Space, 6u);
+  EXPECT_EQ(Binding.LowerBound, 7u);
+  EXPECT_EQ(Binding.UpperBound, 8u);
+
+  --It;
+  Binding = *It;
+
+  EXPECT_TRUE(It == PSVInfo->getResources().begin());
+
+  EXPECT_EQ(Binding.Type, 1u);
+  EXPECT_EQ(Binding.Space, 2u);
+  EXPECT_EQ(Binding.LowerBound, 3u);
+  EXPECT_EQ(Binding.UpperBound, 4u);
+
+  --It;
+  Binding = *It;
+
+  EXPECT_EQ(Binding.Type, 1u);
+  EXPECT_EQ(Binding.Space, 2u);
+  EXPECT_EQ(Binding.LowerBound, 3u);
+  EXPECT_EQ(Binding.UpperBound, 4u);
+
+  ++It;
+  Binding = *It;
+
+  EXPECT_EQ(Binding.Type, 5u);
+  EXPECT_EQ(Binding.Space, 6u);
+  EXPECT_EQ(Binding.LowerBound, 7u);
+  EXPECT_EQ(Binding.UpperBound, 8u);;
+
+
+  EXPECT_FALSE(It == PSVInfo->getResources().end());
+
+  ++It;
+  Binding = *It;
+
+  EXPECT_TRUE(It == PSVInfo->getResources().end());
+  EXPECT_FALSE(It != PSVInfo->getResources().end());
+
+  EXPECT_EQ(Binding.Type, 0u);
+  EXPECT_EQ(Binding.Flags, 0u);
+}


        


More information about the llvm-commits mailing list