[spirv] Add CL option for stage I/O location assignment order (#578)
A new CL option -fvk-stage-io-order={alpha|decl} is added to control the order for assigning stage I/O location numbers. The default is also changed to declaration order (decl) instead of alphabetical order (alpha). Also extended testing fixtures to support additional CL options.
This commit is contained in:
Родитель
65d17b4f7c
Коммит
0e0e014232
|
@ -232,9 +232,6 @@ HLSL variables and resources
|
|||
|
||||
This section lists how various HLSL variables and resources are mapped.
|
||||
|
||||
Variable definition
|
||||
+++++++++++++++++++
|
||||
|
||||
Variables are defined in HLSL using the following
|
||||
`syntax <https://msdn.microsoft.com/en-us/library/windows/desktop/bb509706(v=vs.85).aspx>`_
|
||||
rules::
|
||||
|
@ -331,7 +328,7 @@ to ``Location`` 1.
|
|||
|
||||
[TODO] Another explicit way: using command-line options
|
||||
|
||||
Please note that the compiler does prohibits mixing the explicit and implicit
|
||||
Please note that the compiler prohibits mixing the explicit and implicit
|
||||
approach for the same SigPoint to avoid complexity and fallibility. However,
|
||||
for a certain shader stage, one SigPoint using the explicit approach while the
|
||||
other adopting the implicit approach is permitted.
|
||||
|
@ -375,8 +372,10 @@ corresponding SPIR-V ``Builtin`` decorations according to the above table.
|
|||
SV semantic strings not translated into SPIR-V BuiltIn decorations will be
|
||||
handled similarly as non-SV (arbitrary) semantic strings: a SPIR-V variable
|
||||
of the ``Input``/``Output`` storage class will be created for each entity with
|
||||
such semantic string. Then sort all semantic strings alphabetically, and assign
|
||||
``Location`` numbers sequentially to each SPIR-V variable. Note that this means
|
||||
such semantic string. Then sort all semantic strings according to declaration
|
||||
(the default, or if ``-fvk-stage-io-order=decl`` is given) or alphabetical
|
||||
(if ``-fvk-stage-io-order=alpha`` is given) order, and assign ``Location``
|
||||
numbers sequentially to the corresponding SPIR-V variables. Note that this means
|
||||
flattening all structs if structs are used as function parameters or returns.
|
||||
|
||||
There is an exception to the above rule for SV_Target[N]. It will always be
|
||||
|
|
|
@ -112,7 +112,6 @@ public:
|
|||
|
||||
bool AllResourcesBound; // OPT_all_resources_bound
|
||||
bool AstDump; // OPT_ast_dump
|
||||
bool GenSPIRV; // OPT_spirv // SPIRV change
|
||||
bool ColorCodeAssembly; // OPT_Cc
|
||||
bool CodeGenHighLevel; // OPT_fcgl
|
||||
bool DebugInfo; // OPT__SLASH_Zi
|
||||
|
@ -157,6 +156,13 @@ public:
|
|||
bool DisaseembleHex; //OPT_Lx
|
||||
bool IsRootSignatureProfile();
|
||||
bool IsLibraryProfile();
|
||||
|
||||
// SPIRV Change Starts
|
||||
#ifdef ENABLE_SPIRV_CODEGEN
|
||||
bool GenSPIRV; // OPT_spirv
|
||||
llvm::StringRef VkStageIoOrder;
|
||||
#endif
|
||||
// SPIRV Change Ends
|
||||
};
|
||||
|
||||
/// Use this class to capture, convert and handle the lifetime for the
|
||||
|
|
|
@ -67,6 +67,8 @@ def hlsloptz_Group : OptionGroup<"HLSL Optimization">, HelpText<"Optimization Op
|
|||
def hlslutil_Group : OptionGroup<"HLSL Utility">, HelpText<"Utility Options">;
|
||||
def hlslcore_Group : OptionGroup<"HLSL Core">, HelpText<"Common Options">;
|
||||
|
||||
def spirv_Group : OptionGroup<"SPIR-V CodeGen">, HelpText<"SPIR-V CodeGen Options">; // SPIRV Change
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Options
|
||||
|
||||
|
@ -209,8 +211,6 @@ def _help_question : Flag<["-", "/"], "?">, Flags<[DriverOption]>, Alias<help>;
|
|||
|
||||
def ast_dump : Flag<["-", "/"], "ast-dump">, Flags<[CoreOption, DriverOption, HelpHidden]>,
|
||||
HelpText<"Dumps the parsed Abstract Syntax Tree.">; // should not be core, but handy workaround until explicit API written
|
||||
def spirv : Flag<["-"], "spirv">, Flags<[CoreOption, DriverOption, HelpHidden]>, // SPIRV change: temporary solution to support
|
||||
HelpText<"Generates SPIR-V binary code">; // SPIRV change: SPIR-V gen in a command line tool
|
||||
def external_lib : Separate<["-", "/"], "external">, Group<hlslcore_Group>, Flags<[DriverOption, HelpHidden]>,
|
||||
HelpText<"External DLL name to load for compiler support">;
|
||||
def external_fn : Separate<["-", "/"], "external-fn">, Group<hlslcore_Group>, Flags<[DriverOption, HelpHidden]>,
|
||||
|
@ -233,6 +233,13 @@ def no_min_precision: Flag<["-", "/"], "no-min-precision">, Flags<[CoreOption, D
|
|||
HelpText<"Do not use min precision but use strict precision types.">;
|
||||
def ignore_line_directives : Flag<["-", "/"], "ignore-line-directives">, HelpText<"Ignore line directives">, Flags<[CoreOption]>, Group<hlslcomp_Group>;
|
||||
|
||||
// SPIRV Change Starts
|
||||
def spirv : Flag<["-"], "spirv">, Group<spirv_Group>, Flags<[CoreOption, DriverOption, HelpHidden]>,
|
||||
HelpText<"Generate SPIR-V binary code">;
|
||||
def fvk_stage_io_order_EQ : Joined<["-"], "fvk-stage-io-order=">, Group<spirv_Group>, Flags<[CoreOption, DriverOption, HelpHidden]>,
|
||||
HelpText<"Specify Vulkan stage I/O location assignment order">;
|
||||
// SPIRV Change Ends
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// fxc-based flags that don't match those previously defined.
|
||||
|
||||
|
|
|
@ -278,7 +278,6 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
opts.UseHexLiterals = Args.hasFlag(OPT_Lx, OPT_INVALID);
|
||||
opts.Preprocess = Args.getLastArgValue(OPT_P);
|
||||
opts.AstDump = Args.hasFlag(OPT_ast_dump, OPT_INVALID, false);
|
||||
opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false); // SPIRV change
|
||||
opts.CodeGenHighLevel = Args.hasFlag(OPT_fcgl, OPT_INVALID, false);
|
||||
opts.DebugInfo = Args.hasFlag(OPT__SLASH_Zi, OPT_INVALID, false);
|
||||
opts.DebugNameForBinary = Args.hasFlag(OPT_Zsb, OPT_INVALID, false);
|
||||
|
@ -432,6 +431,25 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
return 1;
|
||||
}
|
||||
|
||||
// SPIRV Change Starts
|
||||
#ifdef ENABLE_SPIRV_CODEGEN
|
||||
opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
|
||||
opts.VkStageIoOrder = Args.getLastArgValue(OPT_fvk_stage_io_order_EQ, "decl");
|
||||
if (opts.VkStageIoOrder != "alpha" && opts.VkStageIoOrder != "decl") {
|
||||
errors << "Unknown Vulkan stage I/O location assignment order : "
|
||||
<< opts.VkStageIoOrder;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
|
||||
!Args.getLastArgValue(OPT_fvk_stage_io_order_EQ).empty()) {
|
||||
errors << "SPIR-V CodeGen not available. "
|
||||
"Please recompile with -DENABLE_SPIRV_CODEGEN=ON.";
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
// SPIRV Change Ends
|
||||
|
||||
opts.Args = std::move(Args);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,12 +11,20 @@
|
|||
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
|
||||
#include "clang/SPIRV/EmitSPIRVOptions.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class EmitSPIRVAction : public ASTFrontendAction {
|
||||
public:
|
||||
EmitSPIRVAction(const EmitSPIRVOptions &opts) : options(opts) {}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef InFile) override;
|
||||
|
||||
private:
|
||||
EmitSPIRVOptions options;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
//===-- EmitSPIRVOptions.h - Options for SPIR-V CodeGen ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_SPIRV_EMITSPIRVOPTIONS_H
|
||||
#define LLVM_CLANG_SPIRV_EMITSPIRVOPTIONS_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace clang {
|
||||
/// Structs for controlling behaviors of SPIR-V codegen.
|
||||
struct EmitSPIRVOptions {
|
||||
llvm::StringRef stageIoOrder;
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -361,12 +361,13 @@ bool DeclResultIdMapper::finalizeStageIOLocations(bool forInput) {
|
|||
}
|
||||
}
|
||||
|
||||
// Sort stage input/output variables alphabetically
|
||||
const auto comp = [](const StageVar *a, const StageVar *b) {
|
||||
return a->getSemanticStr() < b->getSemanticStr();
|
||||
};
|
||||
|
||||
std::sort(vars.begin(), vars.end(), comp);
|
||||
if (spirvOptions.stageIoOrder == "alpha") {
|
||||
// Sort stage input/output variables alphabetically
|
||||
std::sort(vars.begin(), vars.end(),
|
||||
[](const StageVar *a, const StageVar *b) {
|
||||
return a->getSemanticStr() < b->getSemanticStr();
|
||||
});
|
||||
}
|
||||
|
||||
for (const auto *var : vars)
|
||||
theBuilder.decorateLocation(var->getSpirvId(), locSet.useNextLoc());
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "dxc/HLSL/DxilSigPoint.h"
|
||||
#include "spirv/1.0/spirv.hpp11"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/SPIRV/EmitSPIRVOptions.h"
|
||||
#include "clang/SPIRV/ModuleBuilder.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -115,7 +116,8 @@ private:
|
|||
class DeclResultIdMapper {
|
||||
public:
|
||||
inline DeclResultIdMapper(const hlsl::ShaderModel &stage, ASTContext &context,
|
||||
ModuleBuilder &builder, DiagnosticsEngine &diag);
|
||||
ModuleBuilder &builder, DiagnosticsEngine &diag,
|
||||
const EmitSPIRVOptions &spirvOptions);
|
||||
|
||||
/// \brief Creates the stage output variables by parsing the semantics
|
||||
/// attached to the given function's parameter or return value and returns
|
||||
|
@ -236,9 +238,11 @@ private:
|
|||
private:
|
||||
const hlsl::ShaderModel &shaderModel;
|
||||
ModuleBuilder &theBuilder;
|
||||
TypeTranslator typeTranslator;
|
||||
const EmitSPIRVOptions &spirvOptions;
|
||||
DiagnosticsEngine &diags;
|
||||
|
||||
TypeTranslator typeTranslator;
|
||||
|
||||
uint32_t entryFunctionId;
|
||||
|
||||
/// Mapping of all Clang AST decls to their <result-id>s.
|
||||
|
@ -252,9 +256,10 @@ private:
|
|||
DeclResultIdMapper::DeclResultIdMapper(const hlsl::ShaderModel &model,
|
||||
ASTContext &context,
|
||||
ModuleBuilder &builder,
|
||||
DiagnosticsEngine &diag)
|
||||
: shaderModel(model), theBuilder(builder),
|
||||
typeTranslator(context, builder, diag), diags(diag), entryFunctionId(0) {}
|
||||
DiagnosticsEngine &diag,
|
||||
const EmitSPIRVOptions &options)
|
||||
: shaderModel(model), theBuilder(builder), spirvOptions(options),
|
||||
diags(diag), typeTranslator(context, builder, diag), entryFunctionId(0) {}
|
||||
|
||||
bool DeclResultIdMapper::decorateStageIOLocations() {
|
||||
// Try both input and output even if input location assignment failed
|
||||
|
|
|
@ -18,6 +18,6 @@ namespace clang {
|
|||
|
||||
std::unique_ptr<ASTConsumer>
|
||||
EmitSPIRVAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
|
||||
return llvm::make_unique<spirv::SPIRVEmitter>(CI);
|
||||
return llvm::make_unique<spirv::SPIRVEmitter>(CI, options);
|
||||
}
|
||||
} // end namespace clang
|
||||
|
|
|
@ -135,14 +135,15 @@ bool isLoopStmt(const Stmt *stmt) {
|
|||
|
||||
} // namespace
|
||||
|
||||
SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
|
||||
SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci,
|
||||
const EmitSPIRVOptions &options)
|
||||
: theCompilerInstance(ci), astContext(ci.getASTContext()),
|
||||
diags(ci.getDiagnostics()),
|
||||
diags(ci.getDiagnostics()), spirvOptions(options),
|
||||
entryFunctionName(ci.getCodeGenOpts().HLSLEntryFunction),
|
||||
shaderModel(*hlsl::ShaderModel::GetByName(
|
||||
ci.getCodeGenOpts().HLSLProfile.c_str())),
|
||||
theContext(), theBuilder(&theContext),
|
||||
declIdMapper(shaderModel, astContext, theBuilder, diags),
|
||||
declIdMapper(shaderModel, astContext, theBuilder, diags, spirvOptions),
|
||||
typeTranslator(astContext, theBuilder, diags), entryFunctionId(0),
|
||||
curFunction(nullptr) {
|
||||
if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/SPIRV/EmitSPIRVOptions.h"
|
||||
#include "clang/SPIRV/ModuleBuilder.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
|
@ -42,7 +43,7 @@ namespace spirv {
|
|||
/// through the AST is done manually instead of using ASTConsumer's harness.
|
||||
class SPIRVEmitter : public ASTConsumer {
|
||||
public:
|
||||
explicit SPIRVEmitter(CompilerInstance &ci);
|
||||
explicit SPIRVEmitter(CompilerInstance &ci, const EmitSPIRVOptions &options);
|
||||
|
||||
void HandleTranslationUnit(ASTContext &context) override;
|
||||
|
||||
|
@ -433,6 +434,8 @@ private:
|
|||
ASTContext &astContext;
|
||||
DiagnosticsEngine &diags;
|
||||
|
||||
EmitSPIRVOptions spirvOptions;
|
||||
|
||||
/// Entry function name and shader stage. Both of them are derived from the
|
||||
/// command line and should be const.
|
||||
const llvm::StringRef entryFunctionName;
|
||||
|
|
|
@ -37,8 +37,8 @@ PSInput VSmain(float4 position: POSITION, float4 color: COLOR) {
|
|||
// OpName %color "color"
|
||||
// OpName %result "result"
|
||||
// OpDecorate %gl_Position BuiltIn Position
|
||||
// OpDecorate %in_var_COLOR Location 0
|
||||
// OpDecorate %in_var_POSITION Location 1
|
||||
// OpDecorate %in_var_POSITION Location 0
|
||||
// OpDecorate %in_var_COLOR Location 1
|
||||
// OpDecorate %out_var_COLOR Location 0
|
||||
// %int = OpTypeInt 32 1
|
||||
// %void = OpTypeVoid
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Run: %dxc -T vs_6_0 -E main
|
||||
// Run: %dxc -T vs_6_0 -E main -fvk-stage-io-order=alpha
|
||||
|
||||
struct S {
|
||||
float c: C;
|
|
@ -0,0 +1,44 @@
|
|||
// Run: %dxc -T vs_6_0 -E main
|
||||
|
||||
struct S {
|
||||
float c: C;
|
||||
float a: A;
|
||||
float b: B;
|
||||
};
|
||||
|
||||
struct T {
|
||||
float e: E;
|
||||
S s;
|
||||
float d: D;
|
||||
};
|
||||
|
||||
// CHECK: OpDecorate %in_var_N Location 0
|
||||
// CHECK-NEXT: OpDecorate %in_var_E Location 1
|
||||
// CHECK-NEXT: OpDecorate %in_var_C Location 2
|
||||
// CHECK-NEXT: OpDecorate %in_var_A Location 3
|
||||
// CHECK-NEXT: OpDecorate %in_var_B Location 4
|
||||
// CHECK-NEXT: OpDecorate %in_var_D Location 5
|
||||
// CHECK-NEXT: OpDecorate %in_var_M Location 6
|
||||
|
||||
// CHECK-NEXT: OpDecorate %out_var_E Location 0
|
||||
// CHECK-NEXT: OpDecorate %out_var_C Location 1
|
||||
// CHECK-NEXT: OpDecorate %out_var_A Location 2
|
||||
// CHECK-NEXT: OpDecorate %out_var_B Location 3
|
||||
// CHECK-NEXT: OpDecorate %out_var_D Location 4
|
||||
// CHECK-NEXT: OpDecorate %out_var_Q Location 5
|
||||
// CHECK-NEXT: OpDecorate %out_var_P Location 6
|
||||
|
||||
// Input semantics by declaration order: N, E, C, A, B, D, M
|
||||
// by alphabetic order: A, B, C, D, E, M, N
|
||||
|
||||
// Output semantics by declaration order: E, C, A, B, D, Q, P
|
||||
// by alphabetic order: A, B, C, D, E, P, Q
|
||||
|
||||
void main(in float input1 : N,
|
||||
in T input2 ,
|
||||
in float input3 : M,
|
||||
out T output1,
|
||||
out float output2: Q,
|
||||
out float output3: P
|
||||
) {
|
||||
}
|
|
@ -28,7 +28,7 @@ float main([[vk::location(0)]] in uint m: M, // On function parameter --- M -
|
|||
// CHECK: OpDecorate %in_var_B Location 1
|
||||
// CHECK: OpDecorate %in_var_A Location 2
|
||||
|
||||
// Alphabetical assignment
|
||||
// CHECK: OpDecorate %out_var_C Location 0
|
||||
// Declaration order assignment
|
||||
// CHECK: OpDecorate %out_var_R Location 0
|
||||
// CHECK: OpDecorate %out_var_N Location 1
|
||||
// CHECK: OpDecorate %out_var_R Location 2
|
||||
// CHECK: OpDecorate %out_var_C Location 2
|
||||
|
|
|
@ -24,13 +24,12 @@ float main( in uint m: M,
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
// Alphabetical assignment
|
||||
// CHECK: OpDecorate %in_var_A Location 0
|
||||
// Declaration order assignment
|
||||
// CHECK: OpDecorate %in_var_M Location 0
|
||||
// CHECK: OpDecorate %in_var_B Location 1
|
||||
// CHECK: OpDecorate %in_var_M Location 2
|
||||
// CHECK: OpDecorate %in_var_A Location 2
|
||||
|
||||
// Explicit assignment
|
||||
// CHECK: OpDecorate %out_var_R Location 2
|
||||
// CHECK: OpDecorate %out_var_N Location 0
|
||||
// CHECK: OpDecorate %out_var_C Location 1
|
||||
|
||||
|
|
|
@ -970,11 +970,6 @@ int __cdecl wmain(int argc, const wchar_t **argv_) {
|
|||
fprintf(stderr, "-spirv requires -Fo for output object file name.");
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
if (dxcOpts.GenSPIRV) {
|
||||
fprintf(stderr, "SPIR-V codegen not configured via ENABLE_SPIRV_CODEGEN");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
// SPIRV change ends
|
||||
|
||||
|
|
|
@ -462,7 +462,9 @@ public:
|
|||
// SPIRV change starts
|
||||
#ifdef ENABLE_SPIRV_CODEGEN
|
||||
else if (opts.GenSPIRV) {
|
||||
clang::EmitSPIRVAction action;
|
||||
clang::EmitSPIRVOptions spirvOpts;
|
||||
spirvOpts.stageIoOrder = opts.VkStageIoOrder;
|
||||
clang::EmitSPIRVAction action(spirvOpts);
|
||||
FrontendInputFile file(utf8SourceName.m_psz, IK_HLSL);
|
||||
action.BeginSourceFile(compiler, file);
|
||||
action.Execute();
|
||||
|
|
|
@ -286,8 +286,11 @@ TEST_F(FileTest, SemanticIsFrontFacePS) {
|
|||
runFileTest("semantic.is-front-face.ps.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, SemanticArbitrary) { runFileTest("semantic.arbitrary.hlsl"); }
|
||||
TEST_F(FileTest, SemanticArbitraryLocation) {
|
||||
runFileTest("semantic.arbitrary.location.hlsl");
|
||||
TEST_F(FileTest, SemanticArbitraryDeclLocation) {
|
||||
runFileTest("semantic.arbitrary.location.decl.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, SemanticArbitraryAlphaLocation) {
|
||||
runFileTest("semantic.arbitrary.location.alpha.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, SemanticDuplication) {
|
||||
runFileTest("semantic.duplication.hlsl", /*expectSuccess*/ false);
|
||||
|
|
|
@ -46,8 +46,8 @@ bool FileTest::parseInputFile() {
|
|||
if (runCmdStartPos != std::string::npos) {
|
||||
const auto runCmdEndPos = checkCommands.find('\n', runCmdStartPos);
|
||||
const auto runCommand = checkCommands.substr(runCmdStartPos, runCmdEndPos);
|
||||
if (!utils::processRunCommandArgs(runCommand, &targetProfile,
|
||||
&entryPoint)) {
|
||||
if (!utils::processRunCommandArgs(runCommand, &targetProfile, &entryPoint,
|
||||
&restArgs)) {
|
||||
// An error has occured when parsing the Run command.
|
||||
return false;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void FileTest::runFileTest(llvm::StringRef filename, bool expectSuccess,
|
|||
|
||||
// Feed the HLSL source into the Compiler.
|
||||
const bool compileOk = utils::runCompilerWithSpirvGeneration(
|
||||
inputFilePath, entryPoint, targetProfile, &generatedBinary,
|
||||
inputFilePath, entryPoint, targetProfile, restArgs, &generatedBinary,
|
||||
&errorMessages);
|
||||
|
||||
effcee::Result result(effcee::Result::Status::Ok);
|
||||
|
|
|
@ -34,6 +34,7 @@ private:
|
|||
|
||||
std::string targetProfile; ///< Target profile (argument of -T)
|
||||
std::string entryPoint; ///< Entry point name (argument of -E)
|
||||
std::string restArgs; ///< All the other arguments
|
||||
std::string inputFilePath; ///< Path to the input test file
|
||||
std::vector<uint32_t> generatedBinary; ///< The generated SPIR-V Binary
|
||||
std::string checkCommands; ///< CHECK commands that verify output
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "FileTestUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "SpirvTestOptions.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
@ -40,24 +41,29 @@ bool validateSpirvBinary(std::vector<uint32_t> &binary) {
|
|||
}
|
||||
|
||||
bool processRunCommandArgs(const llvm::StringRef runCommandLine,
|
||||
std::string *targetProfile,
|
||||
std::string *entryPoint) {
|
||||
std::string *targetProfile, std::string *entryPoint,
|
||||
std::string *restArgs) {
|
||||
std::istringstream buf(runCommandLine);
|
||||
std::istream_iterator<std::string> start(buf), end;
|
||||
std::vector<std::string> tokens(start, end);
|
||||
if (tokens[1].find("Run") == std::string::npos ||
|
||||
if (tokens.size() < 3 || tokens[1].find("Run") == std::string::npos ||
|
||||
tokens[2].find("%dxc") == std::string::npos) {
|
||||
fprintf(stderr, "The only supported format is: \"// Run: %%dxc -T "
|
||||
"<profile> -E <entry>\"\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < tokens.size(); ++i) {
|
||||
if (tokens[i] == "-T" && i + 1 < tokens.size())
|
||||
*targetProfile = tokens[i + 1];
|
||||
else if (tokens[i] == "-E" && i + 1 < tokens.size())
|
||||
*entryPoint = tokens[i + 1];
|
||||
std::ostringstream rest;
|
||||
for (uint32_t i = 3; i < tokens.size(); ++i) {
|
||||
if (tokens[i] == "-T" && (++i) < tokens.size())
|
||||
*targetProfile = tokens[i];
|
||||
else if (tokens[i] == "-E" && (++i) < tokens.size())
|
||||
*entryPoint = tokens[i];
|
||||
else
|
||||
rest << (restArgs->empty() ? "" : " ") << tokens[i];
|
||||
}
|
||||
*restArgs = rest.str();
|
||||
|
||||
if (targetProfile->empty()) {
|
||||
fprintf(stderr, "Error: Missing target profile argument (-T).\n");
|
||||
return false;
|
||||
|
@ -100,11 +106,13 @@ std::string getAbsPathOfInputDataFile(const llvm::StringRef filename) {
|
|||
bool runCompilerWithSpirvGeneration(const llvm::StringRef inputFilePath,
|
||||
const llvm::StringRef entryPoint,
|
||||
const llvm::StringRef targetProfile,
|
||||
const llvm::StringRef restArgs,
|
||||
std::vector<uint32_t> *generatedBinary,
|
||||
std::string *errorMessages) {
|
||||
std::wstring srcFile(inputFilePath.begin(), inputFilePath.end());
|
||||
std::wstring entry(entryPoint.begin(), entryPoint.end());
|
||||
std::wstring profile(targetProfile.begin(), targetProfile.end());
|
||||
std::wstring rest(restArgs.begin(), restArgs.end());
|
||||
bool success = true;
|
||||
|
||||
try {
|
||||
|
@ -126,6 +134,7 @@ bool runCompilerWithSpirvGeneration(const llvm::StringRef inputFilePath,
|
|||
flags.push_back(L"-T");
|
||||
flags.push_back(profile.c_str());
|
||||
flags.push_back(L"-spirv");
|
||||
flags.push_back(rest.c_str());
|
||||
|
||||
IFT(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
|
||||
IFT(pLibrary->CreateBlobFromFile(srcFile.c_str(), nullptr, &pSource));
|
||||
|
|
|
@ -35,10 +35,11 @@ bool disassembleSpirvBinary(std::vector<uint32_t> &binary,
|
|||
bool validateSpirvBinary(std::vector<uint32_t> &binary);
|
||||
|
||||
/// \brief Parses the Target Profile and Entry Point from the Run command
|
||||
/// Returns the target profile and entry point via arguments.
|
||||
/// Returns the target profile, entry point, and the rest via arguments.
|
||||
/// Returns true on success, and false otherwise.
|
||||
bool processRunCommandArgs(const llvm::StringRef runCommandLine,
|
||||
std::string *targetProfile, std::string *entryPoint);
|
||||
std::string *targetProfile, std::string *entryPoint,
|
||||
std::string *restArgs);
|
||||
|
||||
/// \brief Converts an IDxcBlob into a vector of 32-bit unsigned integers which
|
||||
/// is returned via the 'binaryWords' argument.
|
||||
|
@ -57,6 +58,7 @@ std::string getAbsPathOfInputDataFile(const llvm::StringRef filename);
|
|||
bool runCompilerWithSpirvGeneration(const llvm::StringRef inputFilePath,
|
||||
const llvm::StringRef entryPoint,
|
||||
const llvm::StringRef targetProfile,
|
||||
const llvm::StringRef restArgs,
|
||||
std::vector<uint32_t> *generatedBinary,
|
||||
std::string *errorMessages);
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ bool WholeFileTest::parseInputFile() {
|
|||
for (std::string line; std::getline(inputFile, line);) {
|
||||
if (line.find(hlslStartLabel) != std::string::npos) {
|
||||
foundRunCommand = true;
|
||||
if (!utils::processRunCommandArgs(line, &targetProfile, &entryPoint)) {
|
||||
if (!utils::processRunCommandArgs(line, &targetProfile, &entryPoint,
|
||||
&restArgs)) {
|
||||
// An error has occured when parsing the Run command.
|
||||
return false;
|
||||
}
|
||||
|
@ -94,7 +95,7 @@ void WholeFileTest::runWholeFileTest(llvm::StringRef filename,
|
|||
|
||||
// Feed the HLSL source into the Compiler.
|
||||
ASSERT_TRUE(utils::runCompilerWithSpirvGeneration(
|
||||
inputFilePath, entryPoint, targetProfile, &generatedBinary,
|
||||
inputFilePath, entryPoint, targetProfile, restArgs, &generatedBinary,
|
||||
&errorMessages));
|
||||
|
||||
// Disassemble the generated SPIR-V binary.
|
||||
|
|
|
@ -58,6 +58,7 @@ private:
|
|||
|
||||
std::string targetProfile; ///< Target profile (argument of -T)
|
||||
std::string entryPoint; ///< Entry point name (argument of -E)
|
||||
std::string restArgs; ///< All the other arguments
|
||||
std::string inputFilePath; ///< Path to the input test file
|
||||
std::vector<uint32_t> generatedBinary; ///< The generated SPIR-V Binary
|
||||
std::string expectedSpirvAsm; ///< Expected SPIR-V parsed from input
|
||||
|
|
Загрузка…
Ссылка в новой задаче