1
0
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:
Philip Rebohle 2018-07-25 22:45:23 +02:00
parent 017699df15
commit d2c62a8645
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 110 additions and 4 deletions

View File

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

View File

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

View File

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

View File

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