mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxbc] Implement passthrough geometry shader
This is needed when vertex or domain shader code is passed to CreateGeometryShaderWithStreamOutput. - Fix compilation with new DxbcProgramInfo.
This commit is contained in:
parent
017699df15
commit
d2c62a8645
@ -177,6 +177,36 @@ namespace dxvk {
|
||||
ins.op));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::processXfbPassthrough() {
|
||||
m_module.setExecutionMode (m_entryPointId, spv::ExecutionModeInputPoints);
|
||||
m_module.setExecutionMode (m_entryPointId, spv::ExecutionModeOutputPoints);
|
||||
m_module.setOutputVertices(m_entryPointId, 1);
|
||||
m_module.setInvocations (m_entryPointId, 1);
|
||||
|
||||
for (auto e = m_isgn->begin(); e != m_isgn->end(); e++) {
|
||||
emitDclInput(e->registerId, 1,
|
||||
e->componentMask, e->systemValue,
|
||||
DxbcInterpolationMode::Undefined);
|
||||
}
|
||||
|
||||
// Figure out which streams to enable
|
||||
uint32_t streamMask = 0;
|
||||
|
||||
for (size_t i = 0; i < m_xfbVars.size(); i++)
|
||||
streamMask |= 1u << m_xfbVars[i].streamId;
|
||||
|
||||
for (uint32_t mask = streamMask; mask != 0; mask &= mask - 1) {
|
||||
const uint32_t streamId = bit::tzcnt(mask);
|
||||
|
||||
emitXfbOutputSetup(streamId, true);
|
||||
m_module.opEmitVertex(m_module.constu32(streamId));
|
||||
}
|
||||
|
||||
// End the main function
|
||||
emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||
@ -2078,7 +2108,7 @@ namespace dxvk {
|
||||
emitOutputSetup();
|
||||
emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||
emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||
emitXfbOutputSetup(streamId);
|
||||
emitXfbOutputSetup(streamId, false);
|
||||
m_module.opEmitVertex(streamVar);
|
||||
}
|
||||
|
||||
@ -4254,6 +4284,21 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxbcRegisterPointer DxbcCompiler::emitArrayAccess(
|
||||
DxbcRegisterPointer pointer,
|
||||
spv::StorageClass sclass,
|
||||
uint32_t index) {
|
||||
uint32_t ptrTypeId = m_module.defPointerType(
|
||||
getVectorTypeId(pointer.type), sclass);
|
||||
|
||||
DxbcRegisterPointer result;
|
||||
result.type = pointer.type;
|
||||
result.id = m_module.opAccessChain(
|
||||
ptrTypeId, pointer.id, 1, &index);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcCompiler::emitLoadSampledImage(
|
||||
const DxbcShaderResource& textureResource,
|
||||
const DxbcSampler& samplerResource,
|
||||
@ -6292,10 +6337,21 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::emitXfbOutputSetup(uint32_t streamId) {
|
||||
void DxbcCompiler::emitXfbOutputSetup(
|
||||
uint32_t streamId,
|
||||
bool passthrough) {
|
||||
for (size_t i = 0; i < m_xfbVars.size(); i++) {
|
||||
if (m_xfbVars[i].streamId == streamId) {
|
||||
DxbcRegisterPointer srcPtr = m_oRegs[m_xfbVars[i].outputId];
|
||||
DxbcRegisterPointer srcPtr = passthrough
|
||||
? m_vRegs[m_xfbVars[i].outputId]
|
||||
: m_oRegs[m_xfbVars[i].outputId];
|
||||
|
||||
if (passthrough) {
|
||||
srcPtr = emitArrayAccess(srcPtr,
|
||||
spv::StorageClassInput,
|
||||
m_module.constu32(0));
|
||||
}
|
||||
|
||||
DxbcRegisterPointer dstPtr;
|
||||
dstPtr.type.ctype = DxbcScalarType::Float32;
|
||||
dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount();
|
||||
|
@ -382,6 +382,15 @@ namespace dxvk {
|
||||
void processInstruction(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
/**
|
||||
* \brief Emits transform feedback passthrough
|
||||
*
|
||||
* Writes all captured input variables to the
|
||||
* corresponding xfb outputs, and sets up the
|
||||
* geometry shader for point-to-point mode.
|
||||
*/
|
||||
void processXfbPassthrough();
|
||||
|
||||
/**
|
||||
* \brief Finalizes the shader
|
||||
* \returns The final shader object
|
||||
@ -851,6 +860,13 @@ namespace dxvk {
|
||||
DxbcRegisterValue value,
|
||||
DxbcOpModifiers modifiers);
|
||||
|
||||
////////////////////////////////
|
||||
// Pointer manipulation methods
|
||||
DxbcRegisterPointer emitArrayAccess(
|
||||
DxbcRegisterPointer pointer,
|
||||
spv::StorageClass sclass,
|
||||
uint32_t index);
|
||||
|
||||
///////////////////////////////////////
|
||||
// Image register manipulation methods
|
||||
uint32_t emitLoadSampledImage(
|
||||
@ -1065,7 +1081,8 @@ namespace dxvk {
|
||||
void emitXfbOutputDeclarations();
|
||||
|
||||
void emitXfbOutputSetup(
|
||||
uint32_t streamId);
|
||||
uint32_t streamId,
|
||||
bool passthrough);
|
||||
|
||||
///////////////////////////////
|
||||
// Hull shader phase methods
|
||||
|
@ -64,6 +64,25 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkShader> DxbcModule::compilePassthroughShader(
|
||||
const DxbcModuleInfo& moduleInfo,
|
||||
const std::string& fileName) const {
|
||||
if (m_shexChunk == nullptr)
|
||||
throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk");
|
||||
|
||||
DxbcAnalysisInfo analysisInfo;
|
||||
|
||||
DxbcCompiler compiler(
|
||||
fileName, moduleInfo,
|
||||
DxbcProgramType::GeometryShader,
|
||||
m_osgnChunk, m_osgnChunk,
|
||||
analysisInfo);
|
||||
|
||||
compiler.processXfbPassthrough();
|
||||
return compiler.finalize();
|
||||
}
|
||||
|
||||
|
||||
void DxbcModule::runAnalyzer(
|
||||
DxbcAnalyzer& analyzer,
|
||||
DxbcCodeSlice slice) const {
|
||||
|
@ -60,6 +60,20 @@ namespace dxvk {
|
||||
const DxbcModuleInfo& moduleInfo,
|
||||
const std::string& fileName) const;
|
||||
|
||||
/**
|
||||
* \brief Compiles a pass-through geometry shader
|
||||
*
|
||||
* Applications can pass a vertex shader to create
|
||||
* a geometry shader with stream output. In this
|
||||
* case, we have to create a passthrough geometry
|
||||
* shader, which operates in point to point mode.
|
||||
* \param [in] moduleInfo DXBC module info
|
||||
* \param [in] fileName SPIR-V shader name
|
||||
*/
|
||||
Rc<DxvkShader> compilePassthroughShader(
|
||||
const DxbcModuleInfo& moduleInfo,
|
||||
const std::string& fileName) const;
|
||||
|
||||
private:
|
||||
|
||||
DxbcHeader m_header;
|
||||
|
Loading…
x
Reference in New Issue
Block a user