|
@@ -6097,6 +6097,7 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
|
|
uint32_t numOutputControlPoints = 0;
|
|
uint32_t numOutputControlPoints = 0;
|
|
uint32_t outputControlPointIdVal = 0; // SV_OutputControlPointID value
|
|
uint32_t outputControlPointIdVal = 0; // SV_OutputControlPointID value
|
|
uint32_t primitiveIdVar = 0; // SV_PrimitiveID variable
|
|
uint32_t primitiveIdVar = 0; // SV_PrimitiveID variable
|
|
|
|
+ uint32_t viewIdVar = 0; // SV_ViewID variable
|
|
uint32_t hullMainInputPatchParam = 0; // Temporary parameter for InputPatch<>
|
|
uint32_t hullMainInputPatchParam = 0; // Temporary parameter for InputPatch<>
|
|
|
|
|
|
// The array size of per-vertex input/output variables
|
|
// The array size of per-vertex input/output variables
|
|
@@ -6225,12 +6226,15 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
|
|
|
|
|
|
theBuilder.createStore(tempVar, loadedValue);
|
|
theBuilder.createStore(tempVar, loadedValue);
|
|
|
|
|
|
- // Record the temporary variable holding SV_OutputControlPointID and
|
|
|
|
- // SV_PrimitiveID. It may be used later in the patch constant function.
|
|
|
|
|
|
+ // Record the temporary variable holding SV_OutputControlPointID,
|
|
|
|
+ // SV_PrimitiveID, and SV_ViewID. It may be used later in the patch
|
|
|
|
+ // constant function.
|
|
if (hasSemantic(param, hlsl::DXIL::SemanticKind::OutputControlPointID))
|
|
if (hasSemantic(param, hlsl::DXIL::SemanticKind::OutputControlPointID))
|
|
outputControlPointIdVal = loadedValue;
|
|
outputControlPointIdVal = loadedValue;
|
|
- if (hasSemantic(param, hlsl::DXIL::SemanticKind::PrimitiveID))
|
|
|
|
|
|
+ else if (hasSemantic(param, hlsl::DXIL::SemanticKind::PrimitiveID))
|
|
primitiveIdVar = tempVar;
|
|
primitiveIdVar = tempVar;
|
|
|
|
+ else if (hasSemantic(param, hlsl::DXIL::SemanticKind::ViewID))
|
|
|
|
+ viewIdVar = tempVar;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6250,9 +6254,10 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
|
|
if (!declIdMapper.createStageOutputVar(decl, numOutputControlPoints,
|
|
if (!declIdMapper.createStageOutputVar(decl, numOutputControlPoints,
|
|
outputControlPointIdVal, retVal))
|
|
outputControlPointIdVal, retVal))
|
|
return false;
|
|
return false;
|
|
- if (!processHullEntryPointOutputAndPatchConstFunc(
|
|
|
|
|
|
+ if (!processHSEntryPointOutputAndPCF(
|
|
decl, retType, retVal, numOutputControlPoints,
|
|
decl, retType, retVal, numOutputControlPoints,
|
|
- outputControlPointIdVal, primitiveIdVar, hullMainInputPatchParam))
|
|
|
|
|
|
+ outputControlPointIdVal, primitiveIdVar, viewIdVar,
|
|
|
|
+ hullMainInputPatchParam))
|
|
return false;
|
|
return false;
|
|
} else {
|
|
} else {
|
|
if (!declIdMapper.createStageOutputVar(decl, retVal, /*forPCF*/ false))
|
|
if (!declIdMapper.createStageOutputVar(decl, retVal, /*forPCF*/ false))
|
|
@@ -6290,10 +6295,10 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-bool SPIRVEmitter::processHullEntryPointOutputAndPatchConstFunc(
|
|
|
|
|
|
+bool SPIRVEmitter::processHSEntryPointOutputAndPCF(
|
|
const FunctionDecl *hullMainFuncDecl, uint32_t retType, uint32_t retVal,
|
|
const FunctionDecl *hullMainFuncDecl, uint32_t retType, uint32_t retVal,
|
|
uint32_t numOutputControlPoints, uint32_t outputControlPointId,
|
|
uint32_t numOutputControlPoints, uint32_t outputControlPointId,
|
|
- uint32_t primitiveId, uint32_t hullMainInputPatch) {
|
|
|
|
|
|
+ uint32_t primitiveId, uint32_t viewId, uint32_t hullMainInputPatch) {
|
|
// This method may only be called for Hull shaders.
|
|
// This method may only be called for Hull shaders.
|
|
assert(shaderModel.IsHS());
|
|
assert(shaderModel.IsHS());
|
|
|
|
|
|
@@ -6356,32 +6361,53 @@ bool SPIRVEmitter::processHullEntryPointOutputAndPatchConstFunc(
|
|
theBuilder.setMergeTarget(mergeBB);
|
|
theBuilder.setMergeTarget(mergeBB);
|
|
|
|
|
|
theBuilder.setInsertPoint(thenBB);
|
|
theBuilder.setInsertPoint(thenBB);
|
|
|
|
+
|
|
// Call the PCF. Since the function is not explicitly called, we must first
|
|
// Call the PCF. Since the function is not explicitly called, we must first
|
|
// register an ID for it.
|
|
// register an ID for it.
|
|
const uint32_t pcfId = declIdMapper.getOrRegisterFnResultId(patchConstFunc);
|
|
const uint32_t pcfId = declIdMapper.getOrRegisterFnResultId(patchConstFunc);
|
|
const uint32_t pcfRetType =
|
|
const uint32_t pcfRetType =
|
|
typeTranslator.translateType(patchConstFunc->getReturnType());
|
|
typeTranslator.translateType(patchConstFunc->getReturnType());
|
|
|
|
+
|
|
std::vector<uint32_t> pcfParams;
|
|
std::vector<uint32_t> pcfParams;
|
|
|
|
+
|
|
|
|
+ // A lambda for creating a stage input variable and its associated temporary
|
|
|
|
+ // variable for function call. Also initializes the temporary variable using
|
|
|
|
+ // the contents loaded from the stage input variable. Returns the <result-id>
|
|
|
|
+ // of the temporary variable.
|
|
|
|
+ const auto createParmVarAndInitFromStageInputVar =
|
|
|
|
+ [this](const ParmVarDecl *param) {
|
|
|
|
+ const uint32_t typeId = typeTranslator.translateType(param->getType());
|
|
|
|
+ std::string tempVarName = "param.var." + param->getNameAsString();
|
|
|
|
+ const uint32_t tempVar = theBuilder.addFnVar(typeId, tempVarName);
|
|
|
|
+ uint32_t loadedValue = 0;
|
|
|
|
+ declIdMapper.createStageInputVar(param, &loadedValue, /*forPCF*/ true);
|
|
|
|
+ theBuilder.createStore(tempVar, loadedValue);
|
|
|
|
+ return tempVar;
|
|
|
|
+ };
|
|
|
|
+
|
|
for (const auto *param : patchConstFunc->parameters()) {
|
|
for (const auto *param : patchConstFunc->parameters()) {
|
|
// Note: According to the HLSL reference, the PCF takes an InputPatch of
|
|
// Note: According to the HLSL reference, the PCF takes an InputPatch of
|
|
// ControlPoints as well as the PatchID (PrimitiveID). This does not
|
|
// ControlPoints as well as the PatchID (PrimitiveID). This does not
|
|
// necessarily mean that they are present. There is also no requirement
|
|
// necessarily mean that they are present. There is also no requirement
|
|
// for the order of parameters passed to PCF.
|
|
// for the order of parameters passed to PCF.
|
|
- if (hlsl::IsHLSLInputPatchType(param->getType()))
|
|
|
|
|
|
+ if (hlsl::IsHLSLInputPatchType(param->getType())) {
|
|
pcfParams.push_back(hullMainInputPatch);
|
|
pcfParams.push_back(hullMainInputPatch);
|
|
- if (hlsl::IsHLSLOutputPatchType(param->getType()))
|
|
|
|
|
|
+ } else if (hlsl::IsHLSLOutputPatchType(param->getType())) {
|
|
pcfParams.push_back(hullMainOutputPatch);
|
|
pcfParams.push_back(hullMainOutputPatch);
|
|
- if (hasSemantic(param, hlsl::DXIL::SemanticKind::PrimitiveID)) {
|
|
|
|
|
|
+ } else if (hasSemantic(param, hlsl::DXIL::SemanticKind::PrimitiveID)) {
|
|
if (!primitiveId) {
|
|
if (!primitiveId) {
|
|
- const uint32_t typeId = typeTranslator.translateType(param->getType());
|
|
|
|
- std::string tempVarName = "param.var." + param->getNameAsString();
|
|
|
|
- const uint32_t tempVar = theBuilder.addFnVar(typeId, tempVarName);
|
|
|
|
- uint32_t loadedValue = 0;
|
|
|
|
- declIdMapper.createStageInputVar(param, &loadedValue, /*forPCF*/ true);
|
|
|
|
- theBuilder.createStore(tempVar, loadedValue);
|
|
|
|
- primitiveId = tempVar;
|
|
|
|
|
|
+ primitiveId = createParmVarAndInitFromStageInputVar(param);
|
|
}
|
|
}
|
|
pcfParams.push_back(primitiveId);
|
|
pcfParams.push_back(primitiveId);
|
|
|
|
+ } else if (hasSemantic(param, hlsl::DXIL::SemanticKind::ViewID)) {
|
|
|
|
+ if (!viewId) {
|
|
|
|
+ viewId = createParmVarAndInitFromStageInputVar(param);
|
|
|
|
+ }
|
|
|
|
+ pcfParams.push_back(viewId);
|
|
|
|
+ } else {
|
|
|
|
+ emitError("patch constant function parameter '%0' unknown",
|
|
|
|
+ param->getLocation())
|
|
|
|
+ << param->getName();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const uint32_t pcfResultId =
|
|
const uint32_t pcfResultId =
|