Default to stripping reflection from DXIL and fix a bunch of fallout.

Two test options, -Qstrip_reflect_from_dxil and -Qkeep_reflect_in_dxil
for making tests work with reflection removed, since many tests are relying
on main module disassembly-reassembly between test phases and reflection
metadata will no longer be present there.  The strip option is for the
few cases where tests don't want the reflection kept in DXIL by default.

Validator no longer requires function annotations for no reason.

Fix places where remove global hook was not being called when functions
were removed manually from the list.

StripReflection now deletes function annotations, unless targeting lib or
old validator that required them.  Preserve global constructor list and
add annotation for 1.4 validator.  The global hook fixes were required
here, otherwise annotations would refer to dead functions during linking.
Struct annotations may not be removed in library case when they still need
translation to legacy types.

Allow missing struct annotation when not necessary to upgrade the layout.

Preserve usage in reflection by upgrading the module, emitting metadata,
cloning for reflection, then restoring validator version and re-emit
metadata.

Fix size for 16-bit type for usage and reflected size.

Make various batch reflection tests require validator 1.5, since these
tests rely on module disassembly->assembly, which will not preserve extra
usage metadata for reflection in 1.4.

Include reflection part in IDxcAssembler, but don't strip from module,
since there are no options to prevent this from breaking a lot of tests.

Don't strip reflection from offline lib target.
This commit is contained in:
Tex Riddell 2019-08-18 20:35:00 -07:00
Родитель 4ac7d8d584
Коммит 892765cc4b
33 изменённых файлов: 332 добавлений и 68 удалений

Просмотреть файл

@ -3075,7 +3075,6 @@ META.DUPLICATESYSVALUE System value may only appear once in s
META.ENTRYFUNCTION entrypoint not found
META.FLAGSUSAGE Flags must match usage
META.FORCECASEONSWITCH Attribute forcecase only works for switch
META.FUNCTIONANNOTATION Cannot find function annotation for %0
META.GLCNOTONAPPENDCONSUME globallycoherent cannot be used with append/consume buffers
META.INTEGERINTERPMODE Interpolation mode on integer must be Constant
META.INTERPMODEINONEROW Interpolation mode must be identical for all elements packed into the same row.

Просмотреть файл

@ -152,7 +152,6 @@ enum class ValidationRule : unsigned {
MetaEntryFunction, // entrypoint not found
MetaFlagsUsage, // Flags must match usage
MetaForceCaseOnSwitch, // Attribute forcecase only works for switch
MetaFunctionAnnotation, // Cannot find function annotation for %0
MetaGlcNotOnAppendConsume, // globallycoherent cannot be used with append/consume buffers
MetaIntegerInterpMode, // Interpolation mode on integer must be Constant
MetaInterpModeInOneRow, // Interpolation mode must be identical for all elements packed into the same row.

Просмотреть файл

@ -154,6 +154,7 @@ public:
bool StripRootSignature = false; // OPT_Qstrip_rootsignature
bool StripPrivate = false; // OPT_Qstrip_priv
bool StripReflection = false; // OPT_Qstrip_reflect
bool KeepReflectionInDxil = false; // OPT_Qkeep_reflect_in_dxil
bool StripReflectionFromDxil = false; // OPT_Qstrip_reflect_from_dxil
bool ExtractRootSignature = false; // OPT_extractrootsignature
bool DisassembleColorCoded = false; // OPT_Cc

Просмотреть файл

@ -353,8 +353,6 @@ def dumpbin : Flag<["-", "/"], "dumpbin">, Flags<[DriverOption]>, Group<hlslutil
HelpText<"Load a binary file rather than compiling">;
def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>,
HelpText<"Strip reflection data from shader bytecode (must be used with /Fo <file>)">;
def Qstrip_reflect_from_dxil : Flag<["-", "/"], "Qstrip_reflect_from_dxil">, Flags<[CoreOption, HelpHidden]>, Group<hlslutil_Group>,
HelpText<"Strip reflection data from shader bytecode (must be used with /Fo <file>)">;
def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[CoreOption, DriverOption]>, Group<hlslutil_Group>,
HelpText<"Strip debug information from 4_0+ shader bytecode (must be used with /Fo <file>)">;
def Qembed_debug : Flag<["-", "/"], "Qembed_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
@ -368,6 +366,14 @@ def extractrootsignature : Flag<["-", "/"], "extractrootsignature">, Flags<[Driv
def verifyrootsignature : JoinedOrSeparate<["-", "/"], "verifyrootsignature">, MetaVarName<"<file>">, Flags<[DriverOption]>, Group<hlslutil_Group>, HelpText<"Verify shader bytecode with root signature">;
def force_rootsig_ver : JoinedOrSeparate<["-", "/"], "force_rootsig_ver">, Flags<[CoreOption]>, MetaVarName<"<profile>">, Group<hlslcomp_Group>, HelpText<"force root signature version (rootsig_1_1 if omitted)">;
// Temporary TEST options, until reflection inside DXIL part can always be stripped
def Qkeep_reflect_in_dxil : Flag<["-", "/"], "Qkeep_reflect_in_dxil">,
Flags<[CoreOption, HelpHidden]>, Group<hlslutil_Group>,
HelpText<"Keep reflection data in shader bytecode">;
def Qstrip_reflect_from_dxil : Flag<["-", "/"], "Qstrip_reflect_from_dxil">,
Flags<[CoreOption, HelpHidden]>, Group<hlslutil_Group>,
HelpText<"Strip reflection data from shader bytecode (must be used with /Fo <file>)">;
/*
def shtemplate : JoinedOrSeparate<["-", "/"], "shtemplate">, MetaVarName<"<file>">, Group<hlslcomp_Group>,
HelpText<"Template shader file for merging/matching resources">;

Просмотреть файл

@ -159,7 +159,7 @@ Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {
delete CGN; // Delete the call graph node for this func
FunctionMap.erase(F); // Remove the call graph node from the map
if (M.HasHLModule()) M.GetHLModule().RemoveFunction(F); // HLSL Change
M.CallRemoveGlobalHook(F); // HLSL Change
M.getFunctionList().remove(F);
return F;

Просмотреть файл

@ -1542,8 +1542,28 @@ StripResourcesReflection(std::vector<std::unique_ptr<TResource>> &vec) {
return bChanged;
}
static bool ResourceTypeRequiresTranslation(const StructType* Ty) {
if (Ty->getName().startswith("class.matrix."))
return true;
for (auto eTy : Ty->elements()) {
if (StructType *structTy = dyn_cast<StructType>(eTy)) {
if (ResourceTypeRequiresTranslation(structTy))
return true;
}
SequentialType *seqTy;
while (seqTy = dyn_cast<SequentialType>(eTy)) {
eTy = seqTy->getElementType();
}
if (eTy->getScalarSizeInBits() < 32) {
return true;
}
}
return false;
}
bool DxilModule::StripReflection() {
bool bChanged = false;
bool bIsLib = GetShaderModel()->IsLib();
// Remove names.
for (Function &F : m_pModule->functions()) {
@ -1560,15 +1580,36 @@ bool DxilModule::StripReflection() {
}
}
}
// Remove struct annotation.
// FunctionAnnotation is used later, so keep it.
if (!m_pTypeSystem->GetStructAnnotationMap().empty()) {
m_pTypeSystem->GetStructAnnotationMap().clear();
bChanged = true;
if (bIsLib && GetUseMinPrecision())
{
// We must preserve struct annotations for resources containing min-precision types,
// since they have not yet been converted for legacy layout.
SmallVector<const StructType*, 4> structsToRemove;
for (auto &item : m_pTypeSystem->GetStructAnnotationMap()) {
if (!ResourceTypeRequiresTranslation(item.first))
structsToRemove.emplace_back(item.first);
}
for (auto Ty : structsToRemove) {
m_pTypeSystem->GetStructAnnotationMap().erase(Ty);
}
} else {
// Remove struct annotations.
if (!m_pTypeSystem->GetStructAnnotationMap().empty()) {
m_pTypeSystem->GetStructAnnotationMap().clear();
bChanged = true;
}
if (DXIL::CompareVersions(m_ValMajor, m_ValMinor, 1, 5) >= 0) {
// Remove function annotations.
if (!m_pTypeSystem->GetFunctionAnnotationMap().empty()) {
m_pTypeSystem->GetFunctionAnnotationMap().clear();
bChanged = true;
}
}
}
// Resource
if (!GetShaderModel()->IsLib()) {
if (!bIsLib) {
bChanged |= StripResourcesReflection(m_CBuffers);
bChanged |= StripResourcesReflection(m_UAVs);
bChanged |= StripResourcesReflection(m_SRVs);
@ -1578,8 +1619,12 @@ bool DxilModule::StripReflection() {
// Unused global.
SmallVector<GlobalVariable *,2> UnusedGlobals;
for (GlobalVariable &GV : m_pModule->globals()) {
if (GV.use_empty())
UnusedGlobals.emplace_back(&GV);
if (GV.use_empty()) {
// Need to preserve this global, otherwise we drop constructors
// for static globals.
if (!bIsLib || GV.getName().compare("llvm.global_ctors") != 0)
UnusedGlobals.emplace_back(&GV);
}
}
bChanged |= !UnusedGlobals.empty();

Просмотреть файл

@ -553,6 +553,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
opts.StripRootSignature = Args.hasFlag(OPT_Qstrip_rootsignature, OPT_INVALID, false);
opts.StripPrivate = Args.hasFlag(OPT_Qstrip_priv, OPT_INVALID, false);
opts.StripReflection = Args.hasFlag(OPT_Qstrip_reflect, OPT_INVALID, false);
opts.KeepReflectionInDxil = Args.hasFlag(OPT_Qkeep_reflect_in_dxil, OPT_INVALID, false);
opts.StripReflectionFromDxil = Args.hasFlag(OPT_Qstrip_reflect_from_dxil, OPT_INVALID, false);
opts.ExtractRootSignature = Args.hasFlag(OPT_extractrootsignature, OPT_INVALID, false);
opts.DisassembleColorCoded = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
@ -700,6 +701,11 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
opts.ValVerMinor = 0;
}
if (opts.KeepReflectionInDxil && opts.StripReflectionFromDxil) {
errors << "-Qstrip_reflect_from_dxil mutually exclusive with -Qkeep_reflect_in_dxil.";
return 1;
}
// SPIRV Change Starts
#ifdef ENABLE_SPIRV_CODEGEN
opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);

Просмотреть файл

@ -1559,8 +1559,6 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
Flags &= ~SerializeDxilFlags::IncludeDebugNamePart;
bool bSupportsShaderHash = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) >= 0;
bool bCompat_1_4 = DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0;
if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0)
Flags &= ~SerializeDxilFlags::IncludeReflectionPart;
bool bEmitReflection = Flags & SerializeDxilFlags::IncludeReflectionPart ||
pReflectionStreamOut;
@ -1679,7 +1677,22 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
// Clone module for reflection, strip function defs
std::unique_ptr<Module> reflectionModule;
if (bEmitReflection) {
if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0) {
// Retain usage information in metadata for reflection by:
// Upgrade validator version, re-emit metadata, then clone module for reflection.
// 0,0 = Not meant to be validated, support latest
pModule->SetValidatorVersion(0, 0);
pModule->ReEmitDxilResources();
}
reflectionModule.reset(llvm::CloneModule(pModule->GetModule()));
if (DXIL::CompareVersions(ValMajor, ValMinor, 1, 5) < 0) {
// Now restore validator version on main module and re-emit metadata.
pModule->SetValidatorVersion(ValMajor, ValMinor);
pModule->ReEmitDxilResources();
}
for (Function &F : reflectionModule->functions()) {
if (!F.isDeclaration()) {
F.deleteBody();

Просмотреть файл

@ -497,8 +497,14 @@ public:
GenerateDxilResourceHandles();
// TODO: Update types earlier for libraries and replace users, to
// avoid having to preserve HL struct annotation.
// Note 1: Needs to happen after legalize
// Note 2: Cannot do this easily/trivially if any functions have
// resource arguments (in offline linking target).
if (DM.GetOP()->UseMinPrecision())
UpdateStructTypeForLegacyLayout();
// Change resource symbol into undef.
UpdateResourceSymbols();
@ -1601,7 +1607,11 @@ StructType *UpdateStructTypeForLegacyLayout(StructType *ST,
unsigned fieldsCount = ST->getNumElements();
std::vector<Type *> fieldTypes(fieldsCount);
DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
DXASSERT(SA, "must have annotation for struct type");
// After reflection is stripped from library, this will be null if no update is required.
if (!SA) {
return ST;
}
if (SA->IsEmptyStruct()) {
return ST;
@ -2139,7 +2149,7 @@ static unsigned GetOffsetForCBExtractValue(ExtractValueInst *EV, bool bMinPrecis
unsigned bits = EV->getType()->getScalarSizeInBits();
if (bits == 64)
typeSize = 8;
else if (bits == 16 && bMinPrecision)
else if (bits == 16 && !bMinPrecision)
typeSize = 2;
return (EV->getIndices().front() * typeSize);
}

Просмотреть файл

@ -871,6 +871,7 @@ HRESULT CShaderReflectionType::Initialize(
//
// Note that DXIL supports some types that don't currently have equivalents
// in the reflection interface, so we try to muddle through here.
bool bMinPrec = M.GetUseMinPrecision();
D3D_SHADER_VARIABLE_TYPE componentType = D3D_SVT_VOID;
switch(typeAnnotation.GetCompType().GetKind())
{
@ -884,12 +885,22 @@ HRESULT CShaderReflectionType::Initialize(
case hlsl::DXIL::ComponentType::I16:
componentType = D3D_SVT_MIN16INT;
m_Name = "min16int";
if (bMinPrec) {
m_Name = "min16int";
} else {
m_Name = "int16_t";
cbCompSize = 2;
}
break;
case hlsl::DXIL::ComponentType::U16:
componentType = D3D_SVT_MIN16UINT;
m_Name = "min16uint";
if (bMinPrec) {
m_Name = "min16uint";
} else {
m_Name = "uint16_t";
cbCompSize = 2;
}
break;
case hlsl::DXIL::ComponentType::I64:
@ -916,7 +927,12 @@ HRESULT CShaderReflectionType::Initialize(
case hlsl::DXIL::ComponentType::SNormF16:
case hlsl::DXIL::ComponentType::UNormF16:
componentType = D3D_SVT_MIN16FLOAT;
m_Name = "min16float";
if (bMinPrec) {
m_Name = "min16float";
} else {
m_Name = "float16_t";
cbCompSize = 2;
}
break;
case hlsl::DXIL::ComponentType::F32:
@ -1529,7 +1545,7 @@ static unsigned GetOffsetForCBExtractValue(ExtractValueInst *EV, bool bMinPrecis
unsigned bits = EV->getType()->getScalarSizeInBits();
if (bits == 64)
typeSize = 8;
else if (bits == 16 && bMinPrecision)
else if (bits == 16 && !bMinPrecision)
typeSize = 2;
return (EV->getIndices().front() * typeSize);
}

Просмотреть файл

@ -352,13 +352,13 @@ public:
bool runOnModule(Module &M) override {
if (M.HasDxilModule()) {
DxilModule &DM = M.GetDxilModule();
unsigned ValMajor = 0;
unsigned ValMinor = 0;
M.GetDxilModule().GetValidatorVersion(ValMajor, ValMinor);
bool IsLib = DM.GetShaderModel()->IsLib();
// Skip validation patch for lib.
if (!IsLib) {
unsigned ValMajor = 0;
unsigned ValMinor = 0;
M.GetDxilModule().GetValidatorVersion(ValMajor, ValMinor);
if (ValMajor == 1 && ValMinor <= 1) {
patchValidation_1_1(M);
}
@ -393,6 +393,11 @@ public:
// Clear intermediate options that shouldn't be in the final DXIL
DM.ClearIntermediateOptions();
if (IsLib && DXIL::CompareVersions(ValMajor, ValMinor, 1, 4) <= 0) {
// 1.4 validator requires function annotations for all functions
AddFunctionAnnotationForInitializers(M, DM);
}
return true;
}
@ -542,6 +547,22 @@ private:
}
}
}
void AddFunctionAnnotationForInitializers(Module &M, DxilModule &DM) {
if (GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors")) {
ConstantArray *init = cast<ConstantArray>(GV->getInitializer());
for (auto V : init->operand_values()) {
if (isa<ConstantAggregateZero>(V))
continue;
ConstantStruct *CS = cast<ConstantStruct>(V);
if (isa<ConstantPointerNull>(CS->getOperand(1)))
continue;
Function *F = cast<Function>(CS->getOperand(1));
if (DM.GetTypeSystem().GetFunctionAnnotation(F) == nullptr)
DM.GetTypeSystem().AddFunctionAnnotation(F);
}
}
}
};
}

Просмотреть файл

@ -103,7 +103,6 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
case hlsl::ValidationRule::MetaTessellatorOutputPrimitive: return "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.";
case hlsl::ValidationRule::MetaMaxTessFactor: return "Hull Shader MaxTessFactor must be [%0..%1]. %2 specified";
case hlsl::ValidationRule::MetaValidSamplerMode: return "Invalid sampler mode on sampler ";
case hlsl::ValidationRule::MetaFunctionAnnotation: return "Cannot find function annotation for %0";
case hlsl::ValidationRule::MetaGlcNotOnAppendConsume: return "globallycoherent cannot be used with append/consume buffers";
case hlsl::ValidationRule::MetaStructBufAlignment: return "structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)";
case hlsl::ValidationRule::MetaStructBufAlignmentOutOfBound: return "structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)";
@ -3592,13 +3591,6 @@ static void ValidateFunction(Function &F, ValidationContext &ValCtx) {
if (isShader && !F.getReturnType()->isVoidTy())
ValCtx.EmitFormatError(ValidationRule::DeclShaderReturnVoid, { F.getName() });
DxilFunctionAnnotation *funcAnnotation =
ValCtx.DxilMod.GetTypeSystem().GetFunctionAnnotation(&F);
if (!funcAnnotation) {
ValCtx.EmitFormatError(ValidationRule::MetaFunctionAnnotation, { F.getName() });
return;
}
auto ArgFormatError = [&](Argument &arg, ValidationRule rule) {
if (arg.hasName())
ValCtx.EmitFormatError(rule, { arg.getName().str(), F.getName() });

Просмотреть файл

@ -25,10 +25,6 @@
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include "llvm/Pass.h"
#include <unordered_map>
#include "dxc/HLSL/HLModule.h" // HLSL Change
#include "dxc/DXIL/DxilModule.h" // HLSL Change
#include "dxc/DXIL/DxilOperations.h" // HLSL Change
#include "dxc/DXIL/DxilInstructions.h" // HLSL Change
using namespace llvm;
#define DEBUG_TYPE "globaldce"
@ -166,14 +162,12 @@ bool GlobalDCE::runOnModule(Module &M) {
I->setAliasee(nullptr);
}
hlsl::HLModule *HLM = M.HasHLModule() ? &M.GetHLModule() : nullptr; // HLSL Change
if (!DeadFunctions.empty()) {
// Now that all interferences have been dropped, delete the actual objects
// themselves.
for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
RemoveUnusedGlobalValue(*DeadFunctions[i]);
if (HLM != nullptr) HLM->RemoveFunction(DeadFunctions[i]); // HLSL Change
M.CallRemoveGlobalHook(DeadFunctions[i]); // HLSL Change
M.getFunctionList().erase(DeadFunctions[i]);
}
NumFunctions += DeadFunctions.size();
@ -183,7 +177,7 @@ bool GlobalDCE::runOnModule(Module &M) {
if (!DeadGlobalVars.empty()) {
for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
if (HLM != nullptr) HLM->RemoveGlobal(DeadGlobalVars[i]); // HLSL Change
M.CallRemoveGlobalHook(DeadGlobalVars[i]); // HLSL Change
M.getGlobalList().erase(DeadGlobalVars[i]);
}
NumVariables += DeadGlobalVars.size();

Просмотреть файл

@ -1,8 +1,7 @@
// RUN: %dxc -E main -T ps_6_0 %s -Qstrip_reflect | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_0 %s -Qstrip_reflect | FileCheck %s
// Make sure only function annotation, no struct annotation.
// CHECK:!dx.typeAnnotations = !{[[FuncAnnot:[^,]+]]}
// CHECK:[[FuncAnnot]] = !{i32 1, void ()* @main,
// Make sure there are no type annotations
// CHECK-NOT: !dx.typeAnnotations
//--------------------------------------------------------------------------------------
// File: BasicHLSL11_PS.hlsl

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -E main -T ps_6_2 -enable-16bit-types -HV 2018 -Qstrip_reflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -E main -T ps_6_2 -enable-16bit-types -HV 2018 -Qstrip_reflect %s | FileCheck %s
struct MyStruct1
@ -76,6 +76,5 @@ float4 main() : SV_Target {
return 1;
}
// Make sure only function annotation, no struct annotation.
// CHECK:!dx.typeAnnotations = !{[[FuncAnnot:[^,]+]]}
// CHECK:[[FuncAnnot]] = !{i32 1, void ()* @main,
// Make sure there are no type annotations
// CHECK-NOT: !dx.typeAnnotations

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -E main -T cs_6_0 -Zi -Od -DDefineA -DDefineB=0 %s | FileCheck %s
// RUN: %dxc -E main -T cs_6_0 -Zi -Od -DDefineA -DDefineB=0 %s -Qstrip_reflect | FileCheck %s
// CHECK: threadId
// CHECK: groupId
@ -22,7 +22,7 @@
// Make sure source info contents exist.
// CHECK: !{!"DefineA=1", !"DefineB=0"}
// CHECK: share_mem_dbg.hlsl"}
// CHECK: !{!"-E", !"main", !"-T", !"cs_6_0", !"-Zi", !"-Od", !"-D", !"DefineA", !"-D", !"DefineB=0"}
// CHECK: !{!"-E", !"main", !"-T", !"cs_6_0", !"-Zi", !"-Od", !"-D", !"DefineA", !"-D", !"DefineB=0", !"-Qstrip_reflect"}
struct S {

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// Verify CB variable sizes align with expectations.
// This also tests some matrix, struct, and array cases that may

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -auto-binding-space 13 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -auto-binding-space 13 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
// Make sure usage flag is set properly for cbuffers used in libraries

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// Make sure nest empty struct works.

Просмотреть файл

@ -0,0 +1,125 @@
// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -enable-16bit-types %s | %D3DReflect %s | FileCheck %s
// Note: validator version 1.5 is required because these tests use
// module disassembly -> reassembly between steps, and type annotations
// compatible with the 1.4 validator does not have usage metadata, so it's lost.
// Make sure CB usage is correct.
#if 0
// CHECK: ID3D12LibraryReflection:
// CHECK-NEXT: D3D12_LIBRARY_DESC:
// CHECK-NEXT: Creator: <nullptr>
// CHECK-NEXT: Flags: 0
// CHECK-NEXT: FunctionCount: 2
// CHECK-NEXT: ID3D12FunctionReflection:
// CHECK-NEXT: D3D12_FUNCTION_DESC: Name: _GLOBAL__sub_I_lib_global.hlsl
// CHECK-NEXT: Shader Version: Library 6.3
// CHECK-NEXT: Creator: <nullptr>
// CHECK-NEXT: Flags: 0
// CHECK-NEXT: ConstantBuffers: 1
// CHECK-NEXT: BoundResources: 1
// CHECK-NEXT: FunctionParameterCount: 0
// CHECK-NEXT: HasReturn: FALSE
// CHECK-NEXT: Constant Buffers:
// CHECK-NEXT: ID3D12ShaderReflectionConstantBuffer:
// CHECK-NEXT: D3D12_SHADER_BUFFER_DESC: Name: X
// CHECK-NEXT: Type: D3D_CT_CBUFFER
// CHECK-NEXT: Size: 16
// CHECK-NEXT: uFlags: 0
// CHECK-NEXT: Num Variables: 2
// CHECK-NEXT: {
// CHECK-NEXT: ID3D12ShaderReflectionVariable:
// CHECK-NEXT: D3D12_SHADER_VARIABLE_DESC: Name: e
// CHECK-NEXT: Size: 2
// CHECK-NEXT: StartOffset: 0
// CHECK-NEXT: uFlags: 0
// CHECK-NEXT: DefaultValue: <nullptr>
// CHECK-NEXT: ID3D12ShaderReflectionType:
// CHECK-NEXT: D3D12_SHADER_TYPE_DESC: Name: float16_t
// CHECK-NEXT: Class: D3D_SVC_SCALAR
// CHECK-NEXT: Type: D3D_SVT_MIN16FLOAT
// CHECK-NEXT: Elements: 0
// CHECK-NEXT: Rows: 1
// CHECK-NEXT: Columns: 1
// CHECK-NEXT: Members: 0
// CHECK-NEXT: Offset: 0
// CHECK-NEXT: CBuffer: X
// CHECK-NEXT: ID3D12ShaderReflectionVariable:
// CHECK-NEXT: D3D12_SHADER_VARIABLE_DESC: Name: f
// CHECK-NEXT: Size: 2
// CHECK-NEXT: StartOffset: 2
// CHECK-NEXT: uFlags: 0x2
// CHECK-NEXT: DefaultValue: <nullptr>
// CHECK-NEXT: ID3D12ShaderReflectionType:
// CHECK-NEXT: D3D12_SHADER_TYPE_DESC: Name: float16_t
// CHECK-NEXT: Class: D3D_SVC_SCALAR
// CHECK-NEXT: Type: D3D_SVT_MIN16FLOAT
// CHECK-NEXT: Elements: 0
// CHECK-NEXT: Rows: 1
// CHECK-NEXT: Columns: 1
// CHECK-NEXT: Members: 0
// CHECK-NEXT: Offset: 0
// CHECK-NEXT: CBuffer: X
// CHECK-NEXT: }
// CHECK-NEXT: Bound Resources:
// CHECK-NEXT: D3D12_SHADER_BUFFER_DESC: Name: X
// CHECK-NEXT: Type: D3D_SIT_CBUFFER
// CHECK-NEXT: uID: 0
// CHECK-NEXT: BindCount: 1
// CHECK-NEXT: BindPoint: 4294967295
// CHECK-NEXT: Space: 4294967295
// CHECK-NEXT: ReturnType: <unknown: 0>
// CHECK-NEXT: Dimension: D3D_SRV_DIMENSION_UNKNOWN
// CHECK-NEXT: NumSamples (or stride): 0
// CHECK-NEXT: uFlags: 0
// CHECK-NEXT: ID3D12FunctionReflection:
// CHECK-NEXT: D3D12_FUNCTION_DESC: Name: test
// CHECK-NEXT: Shader Version: Pixel 6.3
// CHECK-NEXT: Creator: <nullptr>
// CHECK-NEXT: Flags: 0
// CHECK-NEXT: ConstantBuffers: 0
// CHECK-NEXT: BoundResources: 2
// CHECK-NEXT: FunctionParameterCount: 0
// CHECK-NEXT: HasReturn: FALSE
// CHECK-NEXT: Bound Resources:
// CHECK-NEXT: D3D12_SHADER_BUFFER_DESC: Name: g_samLinear
// CHECK-NEXT: Type: D3D_SIT_SAMPLER
// CHECK-NEXT: uID: 0
// CHECK-NEXT: BindCount: 1
// CHECK-NEXT: BindPoint: 4294967295
// CHECK-NEXT: Space: 4294967295
// CHECK-NEXT: ReturnType: <unknown: 0>
// CHECK-NEXT: Dimension: D3D_SRV_DIMENSION_UNKNOWN
// CHECK-NEXT: NumSamples (or stride): 0
// CHECK-NEXT: uFlags: 0
// CHECK-NEXT: D3D12_SHADER_BUFFER_DESC: Name: g_txDiffuse
// CHECK-NEXT: Type: D3D_SIT_TEXTURE
// CHECK-NEXT: uID: 0
// CHECK-NEXT: BindCount: 1
// CHECK-NEXT: BindPoint: 4294967295
// CHECK-NEXT: Space: 4294967295
// CHECK-NEXT: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK-NEXT: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK-NEXT: NumSamples (or stride): 4294967295
// CHECK-NEXT: uFlags: 0xc
#endif
Texture2D g_txDiffuse;
SamplerState g_samLinear;
cbuffer X {
half e, f;
}
static float g[2] = { 1, f };
[shader("pixel")]
float4 test(float2 c : C) : SV_TARGET
{
float4 x = g_txDiffuse.Sample( g_samLinear, c );
return x + g[1];
}
void update() {
g[1]++;
}

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -T lib_6_3 -auto-binding-space 11 -default-linkage external %s | %D3DReflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -auto-binding-space 11 -default-linkage external %s | %D3DReflect %s | FileCheck %s
float cbval1;
cbuffer MyCB : register(b11, space2) { int4 cbval2, cbval3; }

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -E main -T vs_6_0 %s | %D3DReflect %s | FileCheck %s
// Verify SB type description does not follow the CB offseting alignment
// even when structure is shared with a ConstantBuffer.

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %dxc -T lib_6_3 -auto-binding-space 11 %s | FileCheck %s
// RUN: %dxilver 1.5 | %dxc -T lib_6_3 -auto-binding-space 11 %s | FileCheck %s
// Make sure ST is removed
// CHECK-NOT: @ST

Просмотреть файл

@ -4,7 +4,10 @@ Texture2D g_txDiffuse;
SamplerState g_samLinear;
cbuffer X {
float f;
// Use min-precision type to force conversion of constant buffer type for legacy.
// This has to happen at link time at the moment, so this will break unless type
// annotations are retained for library.
min16float f;
}
static float g[2] = { 1, f };

Просмотреть файл

@ -141,7 +141,7 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
outStream.flush();
CComPtr<IDxcBlob> pResultBlob;
hlsl::SerializeDxilFlags flags = hlsl::SerializeDxilFlags::None;
hlsl::SerializeDxilFlags flags = hlsl::SerializeDxilFlags::IncludeReflectionPart;
if (HasDebugInfo(*M)) {
flags |= SerializeDxilFlags::IncludeDebugInfoPart;
flags |= SerializeDxilFlags::IncludeDebugNamePart;

Просмотреть файл

@ -624,6 +624,11 @@ public:
needsValidation = false;
}
if (compiler.getCodeGenOpts().HLSLProfile == "lib_6_x") {
// Currently do not support stripping reflection from offline linking target.
opts.KeepReflectionInDxil = true;
}
if (opts.ValVerMajor != UINT_MAX) {
// user-specified validator version override
compiler.getCodeGenOpts().HLSLValidatorMajorVer = opts.ValVerMajor;
@ -735,7 +740,7 @@ public:
// Implies name part
SerializeFlags |= SerializeDxilFlags::IncludeDebugNamePart;
}
if (opts.StripReflection || opts.StripReflectionFromDxil) {
if (!opts.KeepReflectionInDxil) {
SerializeFlags |= SerializeDxilFlags::StripReflectionFromDxilPart;
}
if (!opts.StripReflection) {

Просмотреть файл

@ -123,7 +123,8 @@ HRESULT STDMETHODCALLTYPE DxcContainerBuilder::RemovePart(_In_ UINT32 fourCC) {
IFTBOOL(fourCC == DxilFourCC::DFCC_ShaderDebugInfoDXIL ||
fourCC == DxilFourCC::DFCC_ShaderDebugName ||
fourCC == DxilFourCC::DFCC_RootSignature ||
fourCC == DxilFourCC::DFCC_PrivateData,
fourCC == DxilFourCC::DFCC_PrivateData ||
fourCC == DxilFourCC::DFCC_ShaderStatistics,
E_INVALIDARG); // You can only remove debug info, debug info name, rootsignature, or private data blob
PartList::iterator it =
std::find_if(m_parts.begin(), m_parts.end(),

Просмотреть файл

@ -336,8 +336,12 @@ public:
std::vector<FileRunCommandPart> parts;
ParseCommandPartsFromFile(path, parts);
VERIFY_IS_TRUE(parts.size() > 0);
VERIFY_ARE_EQUAL_STR(parts[0].Command.c_str(), "%dxc");
FileRunCommandPart &dxc = parts[0];
unsigned partIdx = 0;
if (parts[0].Command.compare("%dxilver") == 0) {
partIdx = 1;
}
FileRunCommandPart &dxc = parts[partIdx];
VERIFY_ARE_EQUAL_STR(dxc.Command.c_str(), "%dxc");
m_dllSupport.Initialize();
hlsl::options::MainArgs args;
@ -504,6 +508,18 @@ public:
void ReflectionTest(LPCWSTR name, bool ignoreIfDXBCFails) {
WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Reflection comparison for %s", name));
// Skip if unsupported.
std::vector<FileRunCommandPart> parts;
ParseCommandPartsFromFile(name, parts);
VERIFY_IS_TRUE(parts.size() > 0);
if (parts[0].Command.compare("%dxilver") == 0) {
VERIFY_IS_TRUE(parts.size() > 1);
auto result = parts[0].Run(m_dllSupport, nullptr);
if (result.ExitCode != 0)
return;
}
CComPtr<IDxcBlob> pProgram;
CComPtr<IDxcBlob> pProgramDXBC;
HRESULT hrDXBC = CompileFromFile(name, true, &pProgramDXBC);

Просмотреть файл

@ -431,6 +431,14 @@ FileRunCommandResult FileRunCommandPart::RunDxc(dxc::DxcDllSupport &DllSupport,
}
}
// For now, too many tests are sensitive to stripping the refleciton info
// from the main module, so use this flag to prevent this until tests
// can be updated.
// That is, unless the test explicitly requests -Qstrip_reflect_from_dxil or -Qstrip_reflect
if (!opts.StripReflectionFromDxil && !opts.StripReflection) {
flags.push_back(L"-Qkeep_reflect_in_dxil");
}
std::vector<std::wstring> argWStrings;
CopyArgsToWStrings(opts.Args, hlsl::options::CoreOption, argWStrings);
for (const std::wstring &a : argWStrings)

Просмотреть файл

@ -72,7 +72,8 @@ public:
}
void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob,
llvm::ArrayRef<LPCWSTR> pArguments = {}) {
llvm::ArrayRef<LPCWSTR> pArguments = {},
LPCWSTR pShaderTarget = L"lib_6_x") {
std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
CComPtr<IDxcBlobEncoding> pSource;
CComPtr<IDxcLibrary> pLibrary;
@ -85,10 +86,9 @@ public:
CComPtr<IDxcOperationResult> pResult;
CComPtr<IDxcBlob> pProgram;
CA2W shWide("lib_6_x", CP_UTF8);
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", shWide,
VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", pShaderTarget,
const_cast<LPCWSTR*>(pArguments.data()), pArguments.size(),
nullptr, 0,
nullptr, &pResult));
@ -218,7 +218,7 @@ TEST_F(LinkerTest, RunLinkFailReDefine) {
TEST_F(LinkerTest, RunLinkGlobalInit) {
CComPtr<IDxcBlob> pEntryLib;
CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib, {}, L"lib_6_3");
CComPtr<IDxcLinker> pLinker;
CreateLinker(&pLinker);

Просмотреть файл

@ -179,12 +179,14 @@ void OptimizerTest::OptimizerWhenSliceNThenOK(int optLevel, LPCWSTR pText, LPCWS
highLevelArgs.insert(highLevelArgs.end(), args.begin(), args.end());
// Create the target program with a single invocation.
highLevelArgs.emplace_back(L"/Qkeep_reflect_in_dxil");
VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main", pTarget,
highLevelArgs.data(), static_cast<UINT32>(highLevelArgs.size()), nullptr, 0, nullptr, &pResult));
VerifyOperationSucceeded(pResult);
VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
pResult.Release();
std::string originalAssembly = DisassembleProgram(m_dllSupport, pProgram);
highLevelArgs.pop_back(); // Remove /keep_reflect_in_dxil
// Get a list of passes for this configuration.
highLevelArgs.emplace_back(L"/Odump");

Просмотреть файл

@ -356,10 +356,15 @@ public:
}
}
std::vector<LPCWSTR> args;
args.reserve(argCount + 1);
args.insert(args.begin(), pArguments, pArguments + argCount);
args.emplace_back(L"-Qkeep_reflect_in_dxil");
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", pEntryName, shWide,
pArguments, argCount, pDefines,
args.data(), (UINT32)args.size(), pDefines,
defineCount, nullptr, &pResult));
CheckOperationResultMsgs(pResult, nullptr, false, false);
VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));

Просмотреть файл

@ -2271,7 +2271,6 @@ class db_dxil(object):
self.add_valrule("Meta.TessellatorOutputPrimitive", "Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.")
self.add_valrule("Meta.MaxTessFactor", "Hull Shader MaxTessFactor must be [%0..%1]. %2 specified")
self.add_valrule("Meta.ValidSamplerMode", "Invalid sampler mode on sampler ")
self.add_valrule("Meta.FunctionAnnotation", "Cannot find function annotation for %0")
self.add_valrule("Meta.GlcNotOnAppendConsume", "globallycoherent cannot be used with append/consume buffers")
self.add_valrule_msg("Meta.StructBufAlignment", "StructuredBuffer stride not aligned","structured buffer element size must be a multiple of %0 bytes (actual size %1 bytes)")
self.add_valrule_msg("Meta.StructBufAlignmentOutOfBound", "StructuredBuffer stride out of bounds","structured buffer elements cannot be larger than %0 bytes (actual size %1 bytes)")