mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[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:
parent
87afb33228
commit
d2ca721387
@ -498,25 +498,11 @@ namespace dxvk {
|
|||||||
"oDepthLe");
|
"oDepthLe");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DxbcOperandType::OutputControlPointId: {
|
case DxbcOperandType::OutputControlPointId:
|
||||||
// The hull shader's invocation
|
|
||||||
// ID has been declared already
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DxbcOperandType::InputForkInstanceId:
|
case DxbcOperandType::InputForkInstanceId:
|
||||||
case DxbcOperandType::InputJoinInstanceId: {
|
case DxbcOperandType::InputJoinInstanceId: {
|
||||||
auto phase = this->getCurrentHsForkJoinPhase();
|
// All of these system values map to the hull shader's
|
||||||
|
// invocation ID, which has been declared already.
|
||||||
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");
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -4097,19 +4083,11 @@ namespace dxvk {
|
|||||||
m_ps.builtinDepth };
|
m_ps.builtinDepth };
|
||||||
|
|
||||||
case DxbcOperandType::OutputControlPointId:
|
case DxbcOperandType::OutputControlPointId:
|
||||||
return DxbcRegisterPointer {
|
|
||||||
{ DxbcScalarType::Uint32, 1 },
|
|
||||||
m_hs.builtinInvocationId };
|
|
||||||
|
|
||||||
case DxbcOperandType::InputForkInstanceId:
|
case DxbcOperandType::InputForkInstanceId:
|
||||||
return DxbcRegisterPointer {
|
|
||||||
{ DxbcScalarType::Uint32, 1 },
|
|
||||||
m_hs.forkPhases.at(m_hs.currPhaseId).instanceIdPtr };
|
|
||||||
|
|
||||||
case DxbcOperandType::InputJoinInstanceId:
|
case DxbcOperandType::InputJoinInstanceId:
|
||||||
return DxbcRegisterPointer {
|
return DxbcRegisterPointer {
|
||||||
{ DxbcScalarType::Uint32, 1 },
|
{ DxbcScalarType::Uint32, 1 },
|
||||||
m_hs.joinPhases.at(m_hs.currPhaseId).instanceIdPtr };
|
m_hs.builtinInvocationId };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
@ -5252,7 +5230,9 @@ namespace dxvk {
|
|||||||
this->emitHsForkJoinPhase(phase);
|
this->emitHsForkJoinPhase(phase);
|
||||||
|
|
||||||
this->emitHsPhaseBarrier();
|
this->emitHsPhaseBarrier();
|
||||||
|
this->emitHsInvocationBlockBegin(1);
|
||||||
this->emitOutputSetup();
|
this->emitOutputSetup();
|
||||||
|
this->emitHsInvocationBlockEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5300,11 +5280,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
void DxbcCompiler::emitHsForkJoinPhase(
|
void DxbcCompiler::emitHsForkJoinPhase(
|
||||||
const DxbcCompilerHsForkJoinPhase& phase) {
|
const DxbcCompilerHsForkJoinPhase& phase) {
|
||||||
for (uint32_t i = 0; i < phase.instanceCount; i++) {
|
this->emitHsInvocationBlockBegin(phase.instanceCount);
|
||||||
const uint32_t counterId = m_module.constu32(i);
|
m_module.opFunctionCall(
|
||||||
m_module.opFunctionCall(m_module.defVoidType(),
|
m_module.defVoidType(),
|
||||||
phase.functionId, 1, &counterId);
|
phase.functionId, 0, nullptr);
|
||||||
}
|
this->emitHsInvocationBlockEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5374,21 +5354,17 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() {
|
DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() {
|
||||||
uint32_t argTypeId = m_module.defIntType(32, 0);
|
|
||||||
uint32_t funTypeId = m_module.defFunctionType(
|
uint32_t funTypeId = m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 1, &argTypeId);
|
m_module.defVoidType(), 0, nullptr);
|
||||||
|
|
||||||
uint32_t funId = m_module.allocateId();
|
uint32_t funId = m_module.allocateId();
|
||||||
|
|
||||||
m_module.functionBegin(m_module.defVoidType(),
|
m_module.functionBegin(m_module.defVoidType(),
|
||||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
funId, funTypeId, spv::FunctionControlMaskNone);
|
||||||
|
|
||||||
uint32_t argId = m_module.functionParameter(argTypeId);
|
|
||||||
m_module.opLabel(m_module.allocateId());
|
m_module.opLabel(m_module.allocateId());
|
||||||
|
|
||||||
DxbcCompilerHsForkJoinPhase result;
|
DxbcCompilerHsForkJoinPhase result;
|
||||||
result.functionId = funId;
|
result.functionId = funId;
|
||||||
result.instanceId = argId;
|
|
||||||
return result;
|
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) {
|
uint32_t DxbcCompiler::emitTessInterfacePerPatch(spv::StorageClass storageClass) {
|
||||||
const bool isInput = storageClass == spv::StorageClassInput;
|
const bool isInput = storageClass == spv::StorageClassInput;
|
||||||
|
|
||||||
|
@ -161,8 +161,6 @@ namespace dxvk {
|
|||||||
struct DxbcCompilerHsForkJoinPhase {
|
struct DxbcCompilerHsForkJoinPhase {
|
||||||
uint32_t functionId = 0;
|
uint32_t functionId = 0;
|
||||||
uint32_t instanceCount = 1;
|
uint32_t instanceCount = 1;
|
||||||
uint32_t instanceId = 0;
|
|
||||||
uint32_t instanceIdPtr = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -209,6 +207,9 @@ namespace dxvk {
|
|||||||
uint32_t outputPerPatch = 0;
|
uint32_t outputPerPatch = 0;
|
||||||
uint32_t outputPerVertex = 0;
|
uint32_t outputPerVertex = 0;
|
||||||
|
|
||||||
|
uint32_t invocationBlockBegin = 0;
|
||||||
|
uint32_t invocationBlockEnd = 0;
|
||||||
|
|
||||||
DxbcCompilerHsControlPointPhase cpPhase;
|
DxbcCompilerHsControlPointPhase cpPhase;
|
||||||
std::vector<DxbcCompilerHsForkJoinPhase> forkPhases;
|
std::vector<DxbcCompilerHsForkJoinPhase> forkPhases;
|
||||||
std::vector<DxbcCompilerHsForkJoinPhase> joinPhases;
|
std::vector<DxbcCompilerHsForkJoinPhase> joinPhases;
|
||||||
@ -878,6 +879,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
void emitHsPhaseBarrier();
|
void emitHsPhaseBarrier();
|
||||||
|
|
||||||
|
void emitHsInvocationBlockBegin(
|
||||||
|
uint32_t count);
|
||||||
|
|
||||||
|
void emitHsInvocationBlockEnd();
|
||||||
|
|
||||||
uint32_t emitTessInterfacePerPatch(
|
uint32_t emitTessInterfacePerPatch(
|
||||||
spv::StorageClass storageClass);
|
spv::StorageClass storageClass);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user