1252 lines · cpp
1//===- DXContainerTest.cpp - Tests for DXContainerFile --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Object/DXContainer.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/BinaryFormat/Magic.h"12#include "llvm/ObjectYAML/DXContainerYAML.h"13#include "llvm/ObjectYAML/yaml2obj.h"14#include "llvm/Support/Error.h"15#include "llvm/Support/MemoryBufferRef.h"16#include "llvm/Testing/Support/Error.h"17#include "gtest/gtest.h"18 19using namespace llvm;20using namespace llvm::object;21 22template <std::size_t X> MemoryBufferRef getMemoryBuffer(uint8_t Data[X]) {23 StringRef Obj(reinterpret_cast<char *>(&Data[0]), X);24 return MemoryBufferRef(Obj, "");25}26 27TEST(DXCFile, IdentifyMagic) {28 {29 StringRef Buffer("DXBC");30 EXPECT_EQ(identify_magic(Buffer), file_magic::dxcontainer_object);31 }32 {33 StringRef Buffer("DXBCBlahBlahBlah");34 EXPECT_EQ(identify_magic(Buffer), file_magic::dxcontainer_object);35 }36}37 38TEST(DXCFile, ParseHeaderErrors) {39 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43};40 EXPECT_THAT_EXPECTED(41 DXContainer::create(getMemoryBuffer<4>(Buffer)),42 FailedWithMessage("Reading structure out of file bounds"));43}44 45TEST(DXCFile, EmptyFile) {46 EXPECT_THAT_EXPECTED(47 DXContainer::create(MemoryBufferRef(StringRef("", 0), "")),48 FailedWithMessage("Reading structure out of file bounds"));49}50 51TEST(DXCFile, ParseHeader) {52 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,54 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,55 0x70, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};56 DXContainer C =57 llvm::cantFail(DXContainer::create(getMemoryBuffer<32>(Buffer)));58 EXPECT_TRUE(memcmp(C.getHeader().Magic, "DXBC", 4) == 0);59 EXPECT_TRUE(memcmp(C.getHeader().FileHash.Digest,60 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0);61 EXPECT_EQ(C.getHeader().Version.Major, 1u);62 EXPECT_EQ(C.getHeader().Version.Minor, 0u);63}64 65TEST(DXCFile, ParsePartMissingOffsets) {66 uint8_t Buffer[] = {67 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,69 0x00, 0x00, 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,70 };71 EXPECT_THAT_EXPECTED(72 DXContainer::create(getMemoryBuffer<32>(Buffer)),73 FailedWithMessage("Reading structure out of file bounds"));74}75 76TEST(DXCFile, ParsePartInvalidOffsets) {77 // This test covers a case where the part offset is beyond the buffer size.78 uint8_t Buffer[] = {79 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,81 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,82 };83 EXPECT_THAT_EXPECTED(84 DXContainer::create(getMemoryBuffer<36>(Buffer)),85 FailedWithMessage("Part offset points beyond boundary of the file"));86}87 88TEST(DXCFile, ParsePartTooSmallBuffer) {89 // This test covers a case where there is insufficent space to read a full90 // part name, but the offset for the part is inside the buffer.91 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,93 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,94 0x26, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,95 0x24, 0x00, 0x00, 0x00, 0x46, 0x4B};96 EXPECT_THAT_EXPECTED(97 DXContainer::create(getMemoryBuffer<38>(Buffer)),98 FailedWithMessage("File not large enough to read part name"));99}100 101TEST(DXCFile, ParsePartNoSize) {102 // This test covers a case where the part's header is readable, but the size103 // the part extends beyond the boundaries of the file.104 uint8_t Buffer[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,106 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00,107 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,108 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00};109 EXPECT_THAT_EXPECTED(110 DXContainer::create(getMemoryBuffer<42>(Buffer)),111 FailedWithMessage("Reading part size out of file bounds"));112}113 114TEST(DXCFile, ParseOverlappingParts) {115 // This test covers a case where a part's offset is inside the size range116 // covered by the previous part.117 uint8_t Buffer[] = {118 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,120 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,121 0x2C, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x30, 0x08, 0x00, 0x00, 0x00,122 0x46, 0x4B, 0x45, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,123 };124 EXPECT_THAT_EXPECTED(125 DXContainer::create(getMemoryBuffer<60>(Buffer)),126 FailedWithMessage(127 "Part offset for part 1 begins before the previous part ends"));128}129 130TEST(DXCFile, ParseEmptyParts) {131 uint8_t Buffer[] = {132 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,134 0x70, 0x0D, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00,135 0x44, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,136 0x5C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,137 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x31,138 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x32, 0x00, 0x00, 0x00, 0x00,139 0x46, 0x4B, 0x45, 0x33, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x34,140 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x35, 0x00, 0x00, 0x00, 0x00,141 0x46, 0x4B, 0x45, 0x36, 0x00, 0x00, 0x00, 0x00,142 };143 DXContainer C =144 llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer)));145 EXPECT_EQ(C.getHeader().PartCount, 7u);146 147 // All the part sizes are 0, which makes a nice test of the range based for148 int ElementsVisited = 0;149 for (auto Part : C) {150 EXPECT_EQ(Part.Part.Size, 0u);151 EXPECT_EQ(Part.Data.size(), 0u);152 ++ElementsVisited;153 }154 EXPECT_EQ(ElementsVisited, 7);155 156 {157 // These are all intended to be fake part names so that the parser doesn't158 // try to parse the part data.159 auto It = C.begin();160 EXPECT_TRUE(memcmp(It->Part.Name, "FKE0", 4) == 0);161 ++It;162 EXPECT_TRUE(memcmp(It->Part.Name, "FKE1", 4) == 0);163 ++It;164 EXPECT_TRUE(memcmp(It->Part.Name, "FKE2", 4) == 0);165 ++It;166 EXPECT_TRUE(memcmp(It->Part.Name, "FKE3", 4) == 0);167 ++It;168 EXPECT_TRUE(memcmp(It->Part.Name, "FKE4", 4) == 0);169 ++It;170 EXPECT_TRUE(memcmp(It->Part.Name, "FKE5", 4) == 0);171 ++It;172 EXPECT_TRUE(memcmp(It->Part.Name, "FKE6", 4) == 0);173 ++It; // Don't increment past the end174 EXPECT_TRUE(memcmp(It->Part.Name, "FKE6", 4) == 0);175 }176}177 178// This test verify DXIL part are correctly parsed.179// This test is based on the binary output constructed from this yaml.180// --- !dxcontainer181// Header:182// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,183// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]184// Version:185// Major: 1186// Minor: 0187// PartCount: 1188// Parts:189// - Name: DXIL190// Size: 28191// Program:192// MajorVersion: 6193// MinorVersion: 5194// ShaderKind: 5195// Size: 8196// DXILMajorVersion: 1197// DXILMinorVersion: 5198// DXILSize: 4199// DXIL: [ 0x42, 0x43, 0xC0, 0xDE, ]200// ...201TEST(DXCFile, ParseDXILPart) {202 uint8_t Buffer[] = {203 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,205 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,206 0x44, 0x58, 0x49, 0x4c, 0x1c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x05, 0x00,207 0x08, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x05, 0x01, 0x00, 0x00,208 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde};209 DXContainer C =210 llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer)));211 EXPECT_EQ(C.getHeader().PartCount, 1u);212 const std::optional<object::DXContainer::DXILData> &DXIL = C.getDXIL();213 EXPECT_TRUE(DXIL.has_value());214 dxbc::ProgramHeader Header = DXIL->first;215 EXPECT_EQ(Header.getMajorVersion(), 6u);216 EXPECT_EQ(Header.getMinorVersion(), 5u);217 EXPECT_EQ(Header.ShaderKind, 5u);218 EXPECT_EQ(Header.Size, 8u);219 EXPECT_EQ(Header.Bitcode.MajorVersion, 1u);220 EXPECT_EQ(Header.Bitcode.MinorVersion, 5u);221}222 223static Expected<DXContainer>224generateDXContainer(StringRef Yaml, SmallVectorImpl<char> &BinaryData) {225 DXContainerYAML::Object Obj;226 SMDiagnostic GenerateDiag;227 yaml::Input YIn(228 Yaml, /*Ctxt=*/nullptr,229 [](const SMDiagnostic &Diag, void *DiagContext) {230 *static_cast<SMDiagnostic *>(DiagContext) = Diag;231 },232 &GenerateDiag);233 234 YIn >> Obj;235 if (YIn.error())236 return createStringError(YIn.error(), GenerateDiag.getMessage());237 238 raw_svector_ostream OS(BinaryData);239 std::string ErrorMsg;240 if (!yaml::yaml2dxcontainer(241 Obj, OS, [&ErrorMsg](const Twine &Msg) { ErrorMsg = Msg.str(); }))242 return createStringError(YIn.error(), ErrorMsg);243 244 MemoryBufferRef BinaryDataRef = MemoryBufferRef(OS.str(), "");245 246 return DXContainer::create(BinaryDataRef);247}248 249TEST(DXCFile, PSVResourceIterators) {250 const char *Yaml = R"(251--- !dxcontainer252Header:253 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 254 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]255 Version:256 Major: 1257 Minor: 0258 PartCount: 2259Parts:260 - Name: PSV0261 Size: 144262 PSVInfo:263 Version: 0264 ShaderStage: 14265 PayloadSizeInBytes: 4092266 MinimumWaveLaneCount: 0267 MaximumWaveLaneCount: 4294967295268 ResourceStride: 16269 Resources:270 - Type: Sampler271 Space: 1272 LowerBound: 1273 UpperBound: 1274 - Type: CBV275 Space: 2276 LowerBound: 2277 UpperBound: 2278 - Type: SRVTyped279 Space: 3280 LowerBound: 3281 UpperBound: 3282 - Name: DXIL283 Size: 24284 Program:285 MajorVersion: 6286 MinorVersion: 0287 ShaderKind: 14288 Size: 6289 DXILMajorVersion: 1290 DXILMinorVersion: 0291 DXILSize: 0292...293)";294 295 SmallVector<char, 256> BinaryData;296 auto C = generateDXContainer(Yaml, BinaryData);297 298 ASSERT_THAT_EXPECTED(C, Succeeded());299 300 const auto &PSVInfo = C->getPSVInfo();301 ASSERT_TRUE(PSVInfo.has_value());302 303 EXPECT_EQ(PSVInfo->getResourceCount(), 3u);304 305 auto It = PSVInfo->getResources().begin();306 307 EXPECT_TRUE(It == PSVInfo->getResources().begin());308 309 dxbc::PSV::v2::ResourceBindInfo Binding;310 311 Binding = *It;312 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);313 EXPECT_EQ(Binding.Flags, 0u);314 315 ++It;316 Binding = *It;317 318 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::CBV);319 EXPECT_EQ(Binding.Flags, 0u);320 321 --It;322 Binding = *It;323 324 EXPECT_TRUE(It == PSVInfo->getResources().begin());325 326 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);327 EXPECT_EQ(Binding.Flags, 0u);328 329 --It;330 Binding = *It;331 332 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);333 EXPECT_EQ(Binding.Flags, 0u);334 335 ++It;336 Binding = *It;337 338 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::CBV);339 EXPECT_EQ(Binding.Flags, 0u);340 341 ++It;342 Binding = *It;343 344 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVTyped);345 EXPECT_EQ(Binding.Flags, 0u);346 347 EXPECT_FALSE(It == PSVInfo->getResources().end());348 349 ++It;350 Binding = *It;351 352 EXPECT_TRUE(It == PSVInfo->getResources().end());353 EXPECT_FALSE(It != PSVInfo->getResources().end());354 355 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid);356 EXPECT_EQ(Binding.Flags, 0u);357 358 {359 auto Old = It++;360 Binding = *Old;361 362 EXPECT_TRUE(Old == PSVInfo->getResources().end());363 EXPECT_FALSE(Old != PSVInfo->getResources().end());364 365 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid);366 EXPECT_EQ(Binding.Flags, 0u);367 }368 369 Binding = *It;370 371 EXPECT_TRUE(It == PSVInfo->getResources().end());372 373 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid);374 EXPECT_EQ(Binding.Flags, 0u);375 376 {377 auto Old = It--;378 Binding = *Old;379 EXPECT_TRUE(Old == PSVInfo->getResources().end());380 381 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid);382 EXPECT_EQ(Binding.Flags, 0u);383 }384 385 Binding = *It;386 387 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVTyped);388 EXPECT_EQ(Binding.Flags, 0u);389}390 391// The malicious file bits in these tests are mutations of the binary produced392// by the following YAML:393//394// --- !dxcontainer395// Header:396// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,397// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]398// Version:399// Major: 1400// Minor: 0401// PartCount: 3402// Parts:403// - Name: DXIL404// Size: 24405// Program:406// MajorVersion: 6407// MinorVersion: 0408// ShaderKind: 14409// Size: 6410// DXILMajorVersion: 1411// DXILMinorVersion: 0412// DXILSize: 0413// - Name: PSV0414// Size: 36415// PSVInfo:416// Version: 0417// ShaderStage: 5418// MinimumWaveLaneCount: 0419// MaximumWaveLaneCount: 0420// ResourceStride: 16421// Resources: []422// - Name: BLEH423// Size: 16424// ...425 426TEST(DXCFile, MaliciousFiles) {427 428 // In this file blob, the file size is specified as 96 bytes (0x60), and the429 // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of430 // the file.431 {432 uint8_t Buffer[] = {433 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,435 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,436 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,437 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,438 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,439 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,441 };442 EXPECT_THAT_EXPECTED(443 DXContainer::create(getMemoryBuffer<96>(Buffer)),444 FailedWithMessage(445 "Pipeline state data extends beyond the bounds of the part"));446 }447 448 // PSV extends beyond part, but in file range. In this blob the file size is449 // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is450 // 40 bytes (0x40).451 {452 uint8_t Buffer[] = {453 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,455 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,456 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,457 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,458 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,459 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,460 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,463 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,465 };466 EXPECT_THAT_EXPECTED(467 DXContainer::create(getMemoryBuffer<144>(Buffer)),468 FailedWithMessage(469 "Pipeline state data extends beyond the bounds of the part"));470 }471 472 // In this file blob, the file is 116 bytes (0x74). The file structure is473 // valid except that it specifies 1 16 byte resource binding which would474 // extend beyond the range of the part and file.475 {476 uint8_t Buffer[] = {477 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,479 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,480 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,481 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,482 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,483 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,486 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,487 };488 EXPECT_THAT_EXPECTED(489 DXContainer::create(getMemoryBuffer<116>(Buffer)),490 FailedWithMessage(491 "Resource binding data extends beyond the bounds of the part"));492 }493 494 // In this file blob, the file is 116 bytes (0x74). The file structure is495 // valid except that it specifies 1 16 byte resource binding which would496 // extend beyond the range of the part and into the `BLEH` part.497 {498 uint8_t Buffer[] = {499 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,501 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,502 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,503 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,504 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,505 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,506 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,508 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,509 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,511 };512 EXPECT_THAT_EXPECTED(513 DXContainer::create(getMemoryBuffer<144>(Buffer)),514 FailedWithMessage(515 "Resource binding data extends beyond the bounds of the part"));516 }517}518 519// This test verifies that the resource iterator follows the stride even if the520// stride doesn't match an expected or known value. In this test, the resource521// data is structured validly, with 32 bytes per resource. This test is based on522// editing the binary output constructed from this yaml.523//524// --- !dxcontainer525// Header:526// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,527// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]528// Version:529// Major: 1530// Minor: 0531// PartCount: 2532// Parts:533// - Name: DXIL534// Size: 24535// Program:536// MajorVersion: 6537// MinorVersion: 0538// ShaderKind: 14539// Size: 6540// DXILMajorVersion: 1541// DXILMinorVersion: 0542// DXILSize: 0543// - Name: PSV0544// Size: 100545// PSVInfo:546// Version: 0547// ShaderStage: 5548// MinimumWaveLaneCount: 0549// MaximumWaveLaneCount: 0550// ResourceStride: 16551// Resources:552// - Type: 1553// Space: 2554// LowerBound: 3555// UpperBound: 4556// - Type: 5557// Space: 6558// LowerBound: 7559// UpperBound: 8560// ...561TEST(DXCFile, PSVResourceIteratorsStride) {562 uint8_t Buffer[] = {563 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,564 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 565 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,566 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00,567 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00,568 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,570 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,571 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,572 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,573 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,574 0x00, 0x00, 0x00, 0x00,575 }; 576 DXContainer C =577 llvm::cantFail(DXContainer::create(getMemoryBuffer<180>(Buffer)));578 579 const auto &PSVInfo = C.getPSVInfo();580 ASSERT_TRUE(PSVInfo.has_value());581 582 ASSERT_EQ(PSVInfo->getResourceCount(), 2u);583 584 auto It = PSVInfo->getResources().begin();585 586 EXPECT_TRUE(It == PSVInfo->getResources().begin());587 588 dxbc::PSV::v2::ResourceBindInfo Binding;589 590 Binding = *It;591 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);592 EXPECT_EQ(Binding.Space, 2u);593 EXPECT_EQ(Binding.LowerBound, 3u);594 EXPECT_EQ(Binding.UpperBound, 4u);595 596 ++It;597 Binding = *It;598 599 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVStructured);600 EXPECT_EQ(Binding.Space, 6u);601 EXPECT_EQ(Binding.LowerBound, 7u);602 EXPECT_EQ(Binding.UpperBound, 8u);603 604 --It;605 Binding = *It;606 607 EXPECT_TRUE(It == PSVInfo->getResources().begin());608 609 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);610 EXPECT_EQ(Binding.Space, 2u);611 EXPECT_EQ(Binding.LowerBound, 3u);612 EXPECT_EQ(Binding.UpperBound, 4u);613 614 --It;615 Binding = *It;616 617 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Sampler);618 EXPECT_EQ(Binding.Space, 2u);619 EXPECT_EQ(Binding.LowerBound, 3u);620 EXPECT_EQ(Binding.UpperBound, 4u);621 622 ++It;623 Binding = *It;624 625 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVStructured);626 EXPECT_EQ(Binding.Space, 6u);627 EXPECT_EQ(Binding.LowerBound, 7u);628 EXPECT_EQ(Binding.UpperBound, 8u);;629 630 631 EXPECT_FALSE(It == PSVInfo->getResources().end());632 633 ++It;634 Binding = *It;635 636 EXPECT_TRUE(It == PSVInfo->getResources().end());637 EXPECT_FALSE(It != PSVInfo->getResources().end());638 639 EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::Invalid);640 EXPECT_EQ(Binding.Flags, 0u);641}642 643// This test binary is created using mutations of the yaml in the SigElements644// test found under test/ObjectYAML/DXContainer/SigElements.yaml.645 646TEST(DXCFile, MisalignedStringTable) {647 uint8_t Buffer[] = {648 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,650 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,651 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00,652 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,653 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,654 0x50, 0x53, 0x56, 0x30, 0x68, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,657 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40,658 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,659 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};662 EXPECT_THAT_EXPECTED(DXContainer::create(getMemoryBuffer<168>(Buffer)),663 FailedWithMessage("String table misaligned"));664}665 666// This test binary is created using mutations of the yaml in the SigElements667// test found under test/ObjectYAML/DXContainer/SigElements.yaml.668TEST(DXCFile, SigElementsExtendBeyondPart) {669 uint8_t Buffer[] = {670 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,672 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,673 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00,674 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,675 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,676 0x50, 0x53, 0x56, 0x30, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,679 0x05, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40,680 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x00,681 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,682 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,683 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x03, 0x00};684 EXPECT_THAT_EXPECTED(685 DXContainer::create(getMemoryBuffer<164>(Buffer)),686 FailedWithMessage(687 "Signature elements extend beyond the size of the part"));688}689 690TEST(DXCFile, MalformedSignature) {691 /*692 The tests here exercise the DXContainer Signature section parser. These tests693 are based on modifying the binary described by the following yaml:694 695 --- !dxcontainer696 Header:697 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,698 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]699 Version:700 Major: 1701 Minor: 0702 FileSize: 128703 PartCount: 1704 PartOffsets: [ 64 ]705 Parts:706 - Name: ISG1707 Size: 52708 Signature:709 Parameters:710 - Stream: 0711 Name: AAA712 Index: 0713 SystemValue: Undefined714 CompType: Float32715 Register: 0716 Mask: 7717 ExclusiveMask: 2718 MinPrecision: Default719 ...720 721 The unmodified hex sequence is:722 723 uint8_t Buffer[] = {724 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80,726 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,729 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08,730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,732 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00,733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00734 };735 736 */737 738 {739 740 // This binary says the signature has 10 parameters, but the part data is741 // only big enough for 1.742 uint8_t Buffer[] = {743 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,745 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,748 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,749 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,750 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,751 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,752 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,753 0x00, 0x00, 0x00, 0x00};754 EXPECT_THAT_EXPECTED(755 DXContainer::create(getMemoryBuffer<164>(Buffer)),756 FailedWithMessage(757 "Signature parameters extend beyond the part boundary"));758 }759 760 {761 762 // This binary only has one parameter, but the start offset is beyond the763 // size of the part.764 uint8_t Buffer[] = {765 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,767 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,770 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,771 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,772 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,773 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,774 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,775 0x00, 0x00, 0x00, 0x00};776 EXPECT_THAT_EXPECTED(777 DXContainer::create(getMemoryBuffer<164>(Buffer)),778 FailedWithMessage(779 "Signature parameters extend beyond the part boundary"));780 }781 782 {783 784 // This parameter has a name offset of 3, which is before the start of the785 // string table.786 uint8_t Buffer[] = {787 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,789 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,792 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,793 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,794 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,795 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,796 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,797 0x00, 0x00, 0x00, 0x00};798 EXPECT_THAT_EXPECTED(799 DXContainer::create(getMemoryBuffer<164>(Buffer)),800 FailedWithMessage("Invalid parameter name offset: name starts before "801 "the first name offset"));802 }803 804 {805 // This parameter has a name offset of 255, which is after the end of the806 // part.807 uint8_t Buffer[] = {808 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,810 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,813 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,814 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,815 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,816 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,817 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,818 0x00, 0x00, 0x00, 0x00};819 EXPECT_THAT_EXPECTED(820 DXContainer::create(getMemoryBuffer<164>(Buffer)),821 FailedWithMessage("Invalid parameter name offset: name starts after "822 "the end of the part data"));823 }824}825 826TEST(RootSignature, RootParameters) {827 {828 // Root Parameters offset has changed to 36, additional padding was added,829 // as well as fixing the parameter offset.830 uint8_t Buffer[] = {831 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,832 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,833 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,834 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,835 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,836 0x2c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,838 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,839 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,843 0x00};844 845 DXContainer C =846 llvm::cantFail(DXContainer::create(getMemoryBuffer<144>(Buffer)));847 848 auto MaybeRS = C.getRootSignature();849 ASSERT_TRUE(MaybeRS.has_value());850 const auto &RS = MaybeRS.value();851 ASSERT_EQ(RS.getVersion(), 2u);852 ASSERT_EQ(RS.getNumParameters(), 1u);853 ASSERT_EQ(RS.getRootParametersOffset(), 36u);854 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);855 ASSERT_EQ(RS.getStaticSamplersOffset(), 44u);856 ASSERT_EQ(RS.getFlags(), 17u);857 858 auto RootParam = *RS.param_headers().begin();859 ASSERT_EQ((unsigned)RootParam.ParameterType, 1u);860 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 2u);861 auto ParamView = RS.getParameter(RootParam);862 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());863 864 DirectX::RootConstantView *RootConstantsView =865 dyn_cast<DirectX::RootConstantView>(&*ParamView);866 ASSERT_TRUE(RootConstantsView != nullptr);867 auto Constants = RootConstantsView->read();868 869 ASSERT_THAT_ERROR(Constants.takeError(), Succeeded());870 871 ASSERT_EQ(Constants->ShaderRegister, 15u);872 ASSERT_EQ(Constants->RegisterSpace, 14u);873 ASSERT_EQ(Constants->Num32BitValues, 16u);874 }875}876 877TEST(RootSignature, ParseRootFlags) {878 {879 uint8_t Buffer[] = {880 0x44, 0x58, 0x42, 0x43, 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F,881 0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00, 0x00, 0x00,882 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,883 0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,884 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,885 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,886 };887 DXContainer C =888 llvm::cantFail(DXContainer::create(getMemoryBuffer<68>(Buffer)));889 890 const auto &RS = C.getRootSignature();891 ASSERT_TRUE(RS.has_value());892 ASSERT_EQ(RS->getVersion(), 2u);893 ASSERT_EQ(RS->getNumParameters(), 0u);894 ASSERT_EQ(RS->getRootParametersOffset(), 24u);895 ASSERT_EQ(RS->getNumStaticSamplers(), 0u);896 ASSERT_EQ(RS->getStaticSamplersOffset(), 0u);897 ASSERT_EQ(RS->getFlags(), 0x01u);898 }899 {900 // this parameter has the root signature definition missing some values.901 uint8_t Buffer[] = {902 0x44, 0x58, 0x42, 0x43, 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35,903 0x6F, 0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00,904 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24,905 0x00, 0x00, 0x00, 0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00,906 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,908 };909 EXPECT_THAT_EXPECTED(910 DXContainer::create(getMemoryBuffer<64>(Buffer)),911 FailedWithMessage(912 "Invalid root signature, insufficient space for header."));913 }914}915 916TEST(RootSignature, ParseRootConstant) {917 {918 uint8_t Buffer[] = {919 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,920 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,921 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,922 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,923 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,924 0x2c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,925 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,926 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,927 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,928 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,930 0x00};931 DXContainer C =932 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));933 934 auto MaybeRS = C.getRootSignature();935 ASSERT_TRUE(MaybeRS.has_value());936 const auto &RS = MaybeRS.value();937 ASSERT_EQ(RS.getVersion(), 2u);938 ASSERT_EQ(RS.getNumParameters(), 1u);939 ASSERT_EQ(RS.getRootParametersOffset(), 24u);940 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);941 ASSERT_EQ(RS.getStaticSamplersOffset(), 44u);942 ASSERT_EQ(RS.getFlags(), 17u);943 944 auto RootParam = *RS.param_headers().begin();945 ASSERT_EQ((unsigned)RootParam.ParameterType, 1u);946 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 2u);947 auto ParamView = RS.getParameter(RootParam);948 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());949 950 DirectX::RootConstantView *RootConstantsView =951 dyn_cast<DirectX::RootConstantView>(&*ParamView);952 ASSERT_TRUE(RootConstantsView != nullptr);953 auto Constants = RootConstantsView->read();954 955 ASSERT_THAT_ERROR(Constants.takeError(), Succeeded());956 957 ASSERT_EQ(Constants->ShaderRegister, 15u);958 ASSERT_EQ(Constants->RegisterSpace, 14u);959 ASSERT_EQ(Constants->Num32BitValues, 16u);960 }961}962 963TEST(RootSignature, ParseRootDescriptor) {964 {965 uint8_t Buffer[] = {966 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,967 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,968 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,969 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,970 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,971 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,972 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,973 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,975 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,976 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,977 0x00};978 DXContainer C =979 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));980 981 auto MaybeRS = C.getRootSignature();982 ASSERT_TRUE(MaybeRS.has_value());983 const auto &RS = MaybeRS.value();984 ASSERT_EQ(RS.getVersion(), 1u);985 ASSERT_EQ(RS.getNumParameters(), 1u);986 ASSERT_EQ(RS.getRootParametersOffset(), 24u);987 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);988 ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);989 ASSERT_EQ(RS.getFlags(), 17u);990 991 auto RootParam = *RS.param_headers().begin();992 ASSERT_EQ((unsigned)RootParam.ParameterType, 2u);993 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);994 auto ParamView = RS.getParameter(RootParam);995 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());996 997 DirectX::RootDescriptorView *RootDescriptorView =998 dyn_cast<DirectX::RootDescriptorView>(&*ParamView);999 ASSERT_TRUE(RootDescriptorView != nullptr);1000 auto Descriptor = RootDescriptorView->read(RS.getVersion());1001 1002 ASSERT_THAT_ERROR(Descriptor.takeError(), Succeeded());1003 1004 ASSERT_EQ(Descriptor->ShaderRegister, 31u);1005 ASSERT_EQ(Descriptor->RegisterSpace, 32u);1006 }1007 1008 {1009 uint8_t Buffer[] = {1010 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,1011 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,1012 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,1013 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,1014 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1015 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,1016 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,1017 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1021 0x00};1022 DXContainer C =1023 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));1024 1025 auto MaybeRS = C.getRootSignature();1026 ASSERT_TRUE(MaybeRS.has_value());1027 const auto &RS = MaybeRS.value();1028 ASSERT_EQ(RS.getVersion(), 2u);1029 ASSERT_EQ(RS.getNumParameters(), 1u);1030 ASSERT_EQ(RS.getRootParametersOffset(), 24u);1031 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);1032 ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);1033 ASSERT_EQ(RS.getFlags(), 17u);1034 1035 auto RootParam = *RS.param_headers().begin();1036 ASSERT_EQ((unsigned)RootParam.ParameterType, 2u);1037 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);1038 auto ParamView = RS.getParameter(RootParam);1039 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());1040 1041 DirectX::RootDescriptorView *RootDescriptorView =1042 dyn_cast<DirectX::RootDescriptorView>(&*ParamView);1043 ASSERT_TRUE(RootDescriptorView != nullptr);1044 auto Descriptor = RootDescriptorView->read(RS.getVersion());1045 1046 ASSERT_THAT_ERROR(Descriptor.takeError(), Succeeded());1047 1048 ASSERT_EQ(Descriptor->ShaderRegister, 31u);1049 ASSERT_EQ(Descriptor->RegisterSpace, 32u);1050 ASSERT_EQ(Descriptor->Flags, 4u);1051 }1052}1053 1054TEST(RootSignature, ParseDescriptorTable) {1055 {1056 uint8_t Buffer[] = {1057 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,1058 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,1059 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,1060 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,1061 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1062 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1063 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1064 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,1065 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,1066 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1068 0x00};1069 DXContainer C =1070 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));1071 1072 auto MaybeRS = C.getRootSignature();1073 ASSERT_TRUE(MaybeRS.has_value());1074 const auto &RS = MaybeRS.value();1075 ASSERT_EQ(RS.getVersion(), 2u);1076 ASSERT_EQ(RS.getNumParameters(), 1u);1077 ASSERT_EQ(RS.getRootParametersOffset(), 24u);1078 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);1079 ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);1080 ASSERT_EQ(RS.getFlags(), 17u);1081 1082 auto RootParam = *RS.param_headers().begin();1083 ASSERT_EQ((unsigned)RootParam.ParameterType, 0u);1084 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);1085 auto ParamView = RS.getParameter(RootParam);1086 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());1087 1088 auto *DescriptorTableView =1089 dyn_cast<DirectX::DescriptorTableView>(&*ParamView);1090 ASSERT_TRUE(DescriptorTableView != nullptr);1091 auto Table = DescriptorTableView->read<dxbc::RTS0::v2::DescriptorRange>();1092 1093 ASSERT_THAT_ERROR(Table.takeError(), Succeeded());1094 1095 ASSERT_EQ(Table->NumRanges, 1u);1096 1097 auto Range = *Table->begin();1098 1099 ASSERT_EQ(Range.RangeType, 0u);1100 ASSERT_EQ(Range.NumDescriptors, -1u);1101 ASSERT_EQ(Range.BaseShaderRegister, 42u);1102 ASSERT_EQ(Range.RegisterSpace, 43u);1103 ASSERT_EQ(Range.OffsetInDescriptorsFromTableStart, 41u);1104 ASSERT_EQ(Range.Flags, 65536u);1105 }1106 1107 {1108 uint8_t Buffer[] = {1109 0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,1110 0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,1111 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,1112 0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1113 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1114 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1115 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1116 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,1117 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,1118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1120 0x00};1121 DXContainer C =1122 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));1123 1124 auto MaybeRS = C.getRootSignature();1125 ASSERT_TRUE(MaybeRS.has_value());1126 const auto &RS = MaybeRS.value();1127 ASSERT_EQ(RS.getVersion(), 1u);1128 ASSERT_EQ(RS.getNumParameters(), 1u);1129 ASSERT_EQ(RS.getRootParametersOffset(), 24u);1130 ASSERT_EQ(RS.getNumStaticSamplers(), 0u);1131 ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);1132 ASSERT_EQ(RS.getFlags(), 17u);1133 1134 auto RootParam = *RS.param_headers().begin();1135 ASSERT_EQ((unsigned)RootParam.ParameterType, 0u);1136 ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);1137 auto ParamView = RS.getParameter(RootParam);1138 ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());1139 1140 auto *DescriptorTableView =1141 dyn_cast<DirectX::DescriptorTableView>(&*ParamView);1142 ASSERT_TRUE(DescriptorTableView != nullptr);1143 auto Table = DescriptorTableView->read<dxbc::RTS0::v1::DescriptorRange>();1144 1145 ASSERT_THAT_ERROR(Table.takeError(), Succeeded());1146 1147 ASSERT_EQ(Table->NumRanges, 1u);1148 1149 auto Range = *Table->begin();1150 1151 ASSERT_EQ(Range.RangeType, 0u);1152 ASSERT_EQ(Range.NumDescriptors, -1u);1153 ASSERT_EQ(Range.BaseShaderRegister, 42u);1154 ASSERT_EQ(Range.RegisterSpace, 43u);1155 ASSERT_EQ(Range.OffsetInDescriptorsFromTableStart, 41u);1156 }1157}1158 1159TEST(RootSignature, ParseStaticSamplers) {1160 {1161 uint8_t Buffer[] = {1162 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1164 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1167 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,1168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1169 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,1170 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,1171 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,1172 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,1173 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00};1174 DXContainer C =1175 llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));1176 1177 auto MaybeRS = C.getRootSignature();1178 ASSERT_TRUE(MaybeRS.has_value());1179 const auto &RS = MaybeRS.value();1180 ASSERT_EQ(RS.getVersion(), 2u);1181 ASSERT_EQ(RS.getNumParameters(), 0u);1182 ASSERT_EQ(RS.getRootParametersOffset(), 0u);1183 ASSERT_EQ(RS.getNumStaticSamplers(), 1u);1184 ASSERT_EQ(RS.getStaticSamplersOffset(), 24u);1185 ASSERT_EQ(RS.getFlags(), 17u);1186 1187 auto Sampler = *RS.samplers().begin();1188 1189 ASSERT_EQ(Sampler.Filter, 10u);1190 ASSERT_EQ(Sampler.AddressU, 1u);1191 ASSERT_EQ(Sampler.AddressV, 2u);1192 ASSERT_EQ(Sampler.AddressW, 5u);1193 ASSERT_FLOAT_EQ(Sampler.MipLODBias, 1.23f);1194 ASSERT_EQ(Sampler.MaxAnisotropy, 20u);1195 ASSERT_EQ(Sampler.ComparisonFunc, 4u);1196 ASSERT_EQ(Sampler.BorderColor, 0u);1197 ASSERT_FLOAT_EQ(Sampler.MinLOD, 4.56f);1198 ASSERT_FLOAT_EQ(Sampler.MaxLOD, 8.9f);1199 ASSERT_EQ(Sampler.ShaderRegister, 31u);1200 ASSERT_EQ(Sampler.RegisterSpace, 32u);1201 ASSERT_EQ(Sampler.ShaderVisibility, 7u);1202 }1203 {1204 // this is testing static sampler parsing for root signature version 1.2,1205 // it changes: the version number, the size of root signature being emitted1206 // and the values for flag fields.1207 uint8_t Buffer[] = {1208 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1210 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,1213 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,1215 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,1216 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,1217 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,1218 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,1219 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,1220 0x01, 0x00, 0x00, 0x00};1221 DXContainer C =1222 llvm::cantFail(DXContainer::create(getMemoryBuffer<148>(Buffer)));1223 1224 auto MaybeRS = C.getRootSignature();1225 ASSERT_TRUE(MaybeRS.has_value());1226 const auto &RS = MaybeRS.value();1227 ASSERT_EQ(RS.getVersion(), 3U);1228 ASSERT_EQ(RS.getNumParameters(), 0U);1229 ASSERT_EQ(RS.getRootParametersOffset(), 0U);1230 ASSERT_EQ(RS.getNumStaticSamplers(), 1U);1231 ASSERT_EQ(RS.getStaticSamplersOffset(), 24U);1232 ASSERT_EQ(RS.getFlags(), 17U);1233 1234 auto Sampler = *RS.samplers().begin();1235 1236 ASSERT_EQ(Sampler.Filter, 10U);1237 ASSERT_EQ(Sampler.AddressU, 1U);1238 ASSERT_EQ(Sampler.AddressV, 2U);1239 ASSERT_EQ(Sampler.AddressW, 5U);1240 ASSERT_FLOAT_EQ(Sampler.MipLODBias, 1.23F);1241 ASSERT_EQ(Sampler.MaxAnisotropy, 20U);1242 ASSERT_EQ(Sampler.ComparisonFunc, 4U);1243 ASSERT_EQ(Sampler.BorderColor, 0U);1244 ASSERT_FLOAT_EQ(Sampler.MinLOD, 4.56F);1245 ASSERT_FLOAT_EQ(Sampler.MaxLOD, 8.9F);1246 ASSERT_EQ(Sampler.ShaderRegister, 31U);1247 ASSERT_EQ(Sampler.RegisterSpace, 32U);1248 ASSERT_EQ(Sampler.ShaderVisibility, 7U);1249 ASSERT_EQ(Sampler.Flags, 1U);1250 }1251}1252