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

Previously we parse the string by ourselves.
This commit is contained in:
Lei Zhang 2017-08-08 16:18:03 -04:00 коммит произвёл David Peixotto
Родитель e4db8bda97
Коммит 50517e7f34
4 изменённых файлов: 40 добавлений и 42 удалений

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

@ -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);

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

@ -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

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

@ -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,

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

@ -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;