mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +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
@ -179,6 +179,36 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||||
// Depending on the shader type, this will prepare
|
// Depending on the shader type, this will prepare
|
||||||
// input registers, call various shader functions
|
// input registers, call various shader functions
|
||||||
@ -2078,7 +2108,7 @@ namespace dxvk {
|
|||||||
emitOutputSetup();
|
emitOutputSetup();
|
||||||
emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||||
emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||||
emitXfbOutputSetup(streamId);
|
emitXfbOutputSetup(streamId, false);
|
||||||
m_module.opEmitVertex(streamVar);
|
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(
|
uint32_t DxbcCompiler::emitLoadSampledImage(
|
||||||
const DxbcShaderResource& textureResource,
|
const DxbcShaderResource& textureResource,
|
||||||
const DxbcSampler& samplerResource,
|
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++) {
|
for (size_t i = 0; i < m_xfbVars.size(); i++) {
|
||||||
if (m_xfbVars[i].streamId == streamId) {
|
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;
|
DxbcRegisterPointer dstPtr;
|
||||||
dstPtr.type.ctype = DxbcScalarType::Float32;
|
dstPtr.type.ctype = DxbcScalarType::Float32;
|
||||||
dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount();
|
dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount();
|
||||||
|
@ -382,6 +382,15 @@ namespace dxvk {
|
|||||||
void processInstruction(
|
void processInstruction(
|
||||||
const DxbcShaderInstruction& ins);
|
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
|
* \brief Finalizes the shader
|
||||||
* \returns The final shader object
|
* \returns The final shader object
|
||||||
@ -851,6 +860,13 @@ namespace dxvk {
|
|||||||
DxbcRegisterValue value,
|
DxbcRegisterValue value,
|
||||||
DxbcOpModifiers modifiers);
|
DxbcOpModifiers modifiers);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Pointer manipulation methods
|
||||||
|
DxbcRegisterPointer emitArrayAccess(
|
||||||
|
DxbcRegisterPointer pointer,
|
||||||
|
spv::StorageClass sclass,
|
||||||
|
uint32_t index);
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Image register manipulation methods
|
// Image register manipulation methods
|
||||||
uint32_t emitLoadSampledImage(
|
uint32_t emitLoadSampledImage(
|
||||||
@ -1065,7 +1081,8 @@ namespace dxvk {
|
|||||||
void emitXfbOutputDeclarations();
|
void emitXfbOutputDeclarations();
|
||||||
|
|
||||||
void emitXfbOutputSetup(
|
void emitXfbOutputSetup(
|
||||||
uint32_t streamId);
|
uint32_t streamId,
|
||||||
|
bool passthrough);
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Hull shader phase methods
|
// 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(
|
void DxbcModule::runAnalyzer(
|
||||||
DxbcAnalyzer& analyzer,
|
DxbcAnalyzer& analyzer,
|
||||||
DxbcCodeSlice slice) const {
|
DxbcCodeSlice slice) const {
|
||||||
|
@ -60,6 +60,20 @@ namespace dxvk {
|
|||||||
const DxbcModuleInfo& moduleInfo,
|
const DxbcModuleInfo& moduleInfo,
|
||||||
const std::string& fileName) const;
|
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:
|
private:
|
||||||
|
|
||||||
DxbcHeader m_header;
|
DxbcHeader m_header;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user