Преглед изворни кода

[spirv] Create hlsl::ShaderModel out of shader model string (#524)

Previously we parse the string by ourselves.
Lei Zhang пре 8 година
родитељ
комит
50517e7f34

+ 1 - 2
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -139,8 +139,7 @@ void DeclResultIdMapper::createStageVariables(const DeclaratorDecl *decl,
       stageVars.insert(varId);
     } else {
       // Handle output builtin variables first
-      if (shaderStage == spv::ExecutionModel::Vertex &&
-          kind == StageVarKind::Position) {
+      if (shaderModel.IsVS() && kind == StageVarKind::Position) {
         const uint32_t varId =
             theBuilder.addStageBuiltinVariable(typeId, spv::BuiltIn::Position);
 

+ 6 - 5
tools/clang/lib/SPIRV/DeclResultIdMapper.h

@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include "dxc/HLSL//DxilShaderModel.h"
 #include "spirv/1.0/spirv.hpp11"
 #include "clang/SPIRV/ModuleBuilder.h"
 #include "llvm/ADT/DenseMap.h"
@@ -49,8 +50,8 @@ namespace spirv {
 /// * FieldDecl if the field is attached with a semantic.
 class DeclResultIdMapper {
 public:
-  inline DeclResultIdMapper(spv::ExecutionModel stage, ModuleBuilder &builder,
-                            DiagnosticsEngine &diag);
+  inline DeclResultIdMapper(const hlsl::ShaderModel &stage,
+                            ModuleBuilder &builder, DiagnosticsEngine &diag);
 
   /// \brief Creates the stage variables by parsing the semantics attached to
   /// the given function's return value.
@@ -128,7 +129,7 @@ private:
   std::string getStageVarSemantic(const NamedDecl *decl) const;
 
 private:
-  const spv::ExecutionModel shaderStage;
+  const hlsl::ShaderModel &shaderModel;
   ModuleBuilder &theBuilder;
   TypeTranslator typeTranslator;
 
@@ -151,10 +152,10 @@ private:
   llvm::SmallVector<StageVarIdSemanticPair, 8> stageBuiltins;
 };
 
-DeclResultIdMapper::DeclResultIdMapper(spv::ExecutionModel stage,
+DeclResultIdMapper::DeclResultIdMapper(const hlsl::ShaderModel &model,
                                        ModuleBuilder &builder,
                                        DiagnosticsEngine &diag)
-    : shaderStage(stage), theBuilder(builder), typeTranslator(builder, diag) {}
+    : shaderModel(model), theBuilder(builder), typeTranslator(builder, diag) {}
 
 } // end namespace spirv
 } // end namespace clang

+ 26 - 29
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -128,17 +128,18 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
     : theCompilerInstance(ci), astContext(ci.getASTContext()),
       diags(ci.getDiagnostics()),
       entryFunctionName(ci.getCodeGenOpts().HLSLEntryFunction),
-      shaderStage(getSpirvShaderStageFromHlslProfile(
+      shaderModel(*hlsl::ShaderModel::GetByName(
           ci.getCodeGenOpts().HLSLProfile.c_str())),
       theContext(), theBuilder(&theContext),
-      declIdMapper(shaderStage, theBuilder, diags),
+      declIdMapper(shaderModel, theBuilder, diags),
       typeTranslator(theBuilder, diags), entryFunctionId(0),
-      curFunction(nullptr) {}
+      curFunction(nullptr) {
+  if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
+    emitError("unknown shader module: %0") << shaderModel.GetName();
+}
 
 void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
-  const spv::ExecutionModel em = getSpirvShaderStageFromHlslProfile(
-      theCompilerInstance.getCodeGenOpts().HLSLProfile.c_str());
-  AddRequiredCapabilitiesForExecutionModel(em);
+  AddRequiredCapabilitiesForShaderModel();
 
   // Addressing and memory model are required in a valid SPIR-V module.
   theBuilder.setAddressingModel(spv::AddressingModel::Logical);
@@ -162,10 +163,11 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
     doDecl(workQueue[i]);
   }
 
-  theBuilder.addEntryPoint(shaderStage, entryFunctionId, entryFunctionName,
+  theBuilder.addEntryPoint(getSpirvShaderStage(shaderModel), entryFunctionId,
+                           entryFunctionName,
                            declIdMapper.collectStageVariables());
 
-  AddExecutionModeForEntryPoint(shaderStage, entryFunctionId);
+  AddExecutionModeForEntryPoint(entryFunctionId);
 
   // Add Location decorations to stage input/output variables.
   declIdMapper.finalizeStageIOLocations();
@@ -184,7 +186,7 @@ void SPIRVEmitter::doDecl(const Decl *decl) {
   } else {
     // TODO: Implement handling of other Decl types.
     emitWarning("Decl type '%0' is not supported yet.")
-        << std::string(decl->getDeclKindName());
+        << decl->getDeclKindName();
   }
 }
 
@@ -2253,9 +2255,7 @@ uint32_t SPIRVEmitter::translateAPFloat(const llvm::APFloat &floatValue,
 }
 
 spv::ExecutionModel
-SPIRVEmitter::getSpirvShaderStageFromHlslProfile(const char *profile) {
-  assert(profile && "nullptr passed as HLSL profile.");
-
+SPIRVEmitter::getSpirvShaderStage(const hlsl::ShaderModel &model) {
   // DXIL Models are:
   // Profile (DXIL Model) : HLSL Shader Kind : SPIR-V Shader Stage
   // vs_<version>         : Vertex Shader    : Vertex Shader
@@ -2264,32 +2264,30 @@ SPIRVEmitter::getSpirvShaderStageFromHlslProfile(const char *profile) {
   // gs_<version>         : Geometry Shader  : Geometry Shader
   // ps_<version>         : Pixel Shader     : Fragment Shader
   // cs_<version>         : Compute Shader   : Compute Shader
-  switch (profile[0]) {
-  case 'v':
+  switch (model.GetKind()) {
+  case hlsl::ShaderModel::Kind::Vertex:
     return spv::ExecutionModel::Vertex;
-  case 'h':
+  case hlsl::ShaderModel::Kind::Hull:
     return spv::ExecutionModel::TessellationControl;
-  case 'd':
+  case hlsl::ShaderModel::Kind::Domain:
     return spv::ExecutionModel::TessellationEvaluation;
-  case 'g':
+  case hlsl::ShaderModel::Kind::Geometry:
     return spv::ExecutionModel::Geometry;
-  case 'p':
+  case hlsl::ShaderModel::Kind::Pixel:
     return spv::ExecutionModel::Fragment;
-  case 'c':
+  case hlsl::ShaderModel::Kind::Compute:
     return spv::ExecutionModel::GLCompute;
   default:
-    emitError("Unknown HLSL Profile: %0") << profile;
-    return spv::ExecutionModel::Fragment;
+    break;
   }
+  llvm_unreachable("unknown shader model");
 }
 
-void SPIRVEmitter::AddRequiredCapabilitiesForExecutionModel(
-    spv::ExecutionModel em) {
-  if (em == spv::ExecutionModel::TessellationControl ||
-      em == spv::ExecutionModel::TessellationEvaluation) {
+void SPIRVEmitter::AddRequiredCapabilitiesForShaderModel() {
+  if (shaderModel.IsHS() || shaderModel.IsDS()) {
     theBuilder.requireCapability(spv::Capability::Tessellation);
     emitError("Tasselation shaders are currently not supported.");
-  } else if (em == spv::ExecutionModel::Geometry) {
+  } else if (shaderModel.IsGS()) {
     theBuilder.requireCapability(spv::Capability::Geometry);
     emitError("Geometry shaders are currently not supported.");
   } else {
@@ -2297,9 +2295,8 @@ void SPIRVEmitter::AddRequiredCapabilitiesForExecutionModel(
   }
 }
 
-void SPIRVEmitter::AddExecutionModeForEntryPoint(spv::ExecutionModel execModel,
-                                                 uint32_t entryPointId) {
-  if (execModel == spv::ExecutionModel::Fragment) {
+void SPIRVEmitter::AddExecutionModeForEntryPoint(uint32_t entryPointId) {
+  if (shaderModel.IsPS()) {
     // TODO: Implement the logic to determine the proper Execution Mode for
     // fragment shaders. Currently using OriginUpperLeft as default.
     theBuilder.addExecutionMode(entryPointId,

+ 7 - 6
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -18,6 +18,7 @@
 #include <utility>
 #include <vector>
 
+#include "dxc/HLSL/DxilShaderModel.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
@@ -249,14 +250,14 @@ private:
                             QualType targetType);
 
 private:
-  spv::ExecutionModel getSpirvShaderStageFromHlslProfile(const char *profile);
+  static spv::ExecutionModel
+  getSpirvShaderStage(const hlsl::ShaderModel &model);
 
-  void AddRequiredCapabilitiesForExecutionModel(spv::ExecutionModel em);
+  void AddRequiredCapabilitiesForShaderModel();
 
   /// \brief Adds the execution mode for the given entry point based on the
-  /// execution model.
-  void AddExecutionModeForEntryPoint(spv::ExecutionModel execModel,
-                                     uint32_t entryPointId);
+  /// shader model.
+  void AddExecutionModeForEntryPoint(uint32_t entryPointId);
 
 private:
   /// \brief Returns true iff *all* the case values in the given switch
@@ -366,7 +367,7 @@ private:
   /// Entry function name and shader stage. Both of them are derived from the
   /// command line and should be const.
   const llvm::StringRef entryFunctionName;
-  const spv::ExecutionModel shaderStage;
+  const hlsl::ShaderModel &shaderModel;
 
   SPIRVContext theContext;
   ModuleBuilder theBuilder;