[dxbc] Reworked Hull Shader phase invocations

Instead of running individual phases sequentially, we can
run them in parallel if execution barriers are in place.
This commit is contained in:
Philip Rebohle 2018-03-06 15:05:58 +01:00
parent 87afb33228
commit d2ca721387
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 55 additions and 38 deletions

View File

@ -498,25 +498,11 @@ namespace dxvk {
"oDepthLe");
} break;
case DxbcOperandType::OutputControlPointId: {
// The hull shader's invocation
// ID has been declared already
} break;
case DxbcOperandType::OutputControlPointId:
case DxbcOperandType::InputForkInstanceId:
case DxbcOperandType::InputJoinInstanceId: {
auto phase = this->getCurrentHsForkJoinPhase();
phase->instanceIdPtr = m_module.newVar(
m_module.defPointerType(
m_module.defIntType(32, 0),
spv::StorageClassFunction),
spv::StorageClassFunction);
m_module.opStore(phase->instanceIdPtr, phase->instanceId);
m_module.setDebugName(phase->instanceIdPtr,
ins.dst[0].type == DxbcOperandType::InputForkInstanceId
? "vForkInstanceId" : "vJoinInstanceId");
// All of these system values map to the hull shader's
// invocation ID, which has been declared already.
} break;
default:
@ -4097,19 +4083,11 @@ namespace dxvk {
m_ps.builtinDepth };
case DxbcOperandType::OutputControlPointId:
return DxbcRegisterPointer {
{ DxbcScalarType::Uint32, 1 },
m_hs.builtinInvocationId };
case DxbcOperandType::InputForkInstanceId:
return DxbcRegisterPointer {
{ DxbcScalarType::Uint32, 1 },
m_hs.forkPhases.at(m_hs.currPhaseId).instanceIdPtr };
case DxbcOperandType::InputJoinInstanceId:
return DxbcRegisterPointer {
{ DxbcScalarType::Uint32, 1 },
m_hs.joinPhases.at(m_hs.currPhaseId).instanceIdPtr };
m_hs.builtinInvocationId };
default:
throw DxvkError(str::format(
@ -5252,7 +5230,9 @@ namespace dxvk {
this->emitHsForkJoinPhase(phase);
this->emitHsPhaseBarrier();
this->emitHsInvocationBlockBegin(1);
this->emitOutputSetup();
this->emitHsInvocationBlockEnd();
}
@ -5300,11 +5280,11 @@ namespace dxvk {
void DxbcCompiler::emitHsForkJoinPhase(
const DxbcCompilerHsForkJoinPhase& phase) {
for (uint32_t i = 0; i < phase.instanceCount; i++) {
const uint32_t counterId = m_module.constu32(i);
m_module.opFunctionCall(m_module.defVoidType(),
phase.functionId, 1, &counterId);
}
this->emitHsInvocationBlockBegin(phase.instanceCount);
m_module.opFunctionCall(
m_module.defVoidType(),
phase.functionId, 0, nullptr);
this->emitHsInvocationBlockEnd();
}
@ -5374,21 +5354,17 @@ namespace dxvk {
DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() {
uint32_t argTypeId = m_module.defIntType(32, 0);
uint32_t funTypeId = m_module.defFunctionType(
m_module.defVoidType(), 1, &argTypeId);
m_module.defVoidType(), 0, nullptr);
uint32_t funId = m_module.allocateId();
m_module.functionBegin(m_module.defVoidType(),
funId, funTypeId, spv::FunctionControlMaskNone);
uint32_t argId = m_module.functionParameter(argTypeId);
m_module.opLabel(m_module.allocateId());
DxbcCompilerHsForkJoinPhase result;
result.functionId = funId;
result.instanceId = argId;
return result;
}
@ -5402,6 +5378,41 @@ namespace dxvk {
}
void DxbcCompiler::emitHsInvocationBlockBegin(uint32_t count) {
uint32_t invocationId = m_module.opLoad(
getScalarTypeId(DxbcScalarType::Uint32),
m_hs.builtinInvocationId);
uint32_t condition = m_module.opULessThan(
m_module.defBoolType(), invocationId,
m_module.constu32(count));
m_hs.invocationBlockBegin = m_module.allocateId();
m_hs.invocationBlockEnd = m_module.allocateId();
m_module.opSelectionMerge(
m_hs.invocationBlockEnd,
spv::SelectionControlMaskNone);
m_module.opBranchConditional(
condition,
m_hs.invocationBlockBegin,
m_hs.invocationBlockEnd);
m_module.opLabel(
m_hs.invocationBlockBegin);
}
void DxbcCompiler::emitHsInvocationBlockEnd() {
m_module.opBranch (m_hs.invocationBlockEnd);
m_module.opLabel (m_hs.invocationBlockEnd);
m_hs.invocationBlockBegin = 0;
m_hs.invocationBlockEnd = 0;
}
uint32_t DxbcCompiler::emitTessInterfacePerPatch(spv::StorageClass storageClass) {
const bool isInput = storageClass == spv::StorageClassInput;

View File

@ -161,8 +161,6 @@ namespace dxvk {
struct DxbcCompilerHsForkJoinPhase {
uint32_t functionId = 0;
uint32_t instanceCount = 1;
uint32_t instanceId = 0;
uint32_t instanceIdPtr = 0;
};
@ -209,6 +207,9 @@ namespace dxvk {
uint32_t outputPerPatch = 0;
uint32_t outputPerVertex = 0;
uint32_t invocationBlockBegin = 0;
uint32_t invocationBlockEnd = 0;
DxbcCompilerHsControlPointPhase cpPhase;
std::vector<DxbcCompilerHsForkJoinPhase> forkPhases;
std::vector<DxbcCompilerHsForkJoinPhase> joinPhases;
@ -878,6 +879,11 @@ namespace dxvk {
void emitHsPhaseBarrier();
void emitHsInvocationBlockBegin(
uint32_t count);
void emitHsInvocationBlockEnd();
uint32_t emitTessInterfacePerPatch(
spv::StorageClass storageClass);