From eff81c7edfa0608e2a89ac06febce2d27885fb66 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 4 Sep 2018 02:41:34 +0200 Subject: [PATCH 01/30] [dxvk] Implement getShader method for graphics pipelines --- src/dxvk/dxvk_graphics.cpp | 19 +++++++++++++++++++ src/dxvk/dxvk_graphics.h | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index b8768514..14cf9a9d 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -81,6 +81,25 @@ namespace dxvk { } + Rc DxvkGraphicsPipeline::getShader( + VkShaderStageFlagBits stage) const { + switch (stage) { + case VK_SHADER_STAGE_VERTEX_BIT: + return m_vs != nullptr ? m_vs->shader() : nullptr; + case VK_SHADER_STAGE_GEOMETRY_BIT: + return m_gs != nullptr ? m_gs->shader() : nullptr; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return m_tcs != nullptr ? m_tcs->shader() : nullptr; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return m_tes != nullptr ? m_tes->shader() : nullptr; + case VK_SHADER_STAGE_FRAGMENT_BIT: + return m_fs != nullptr ? m_fs->shader() : nullptr; + default: + return nullptr; + } + } + + VkPipeline DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass& renderPass) { diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 756ed924..3d5277f2 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -168,6 +168,17 @@ namespace dxvk { return m_layout.ptr(); } + /** + * \brief Queries shader for a given stage + * + * In case no shader is specified for the + * given stage, \c nullptr will be returned. + * \param [in] stage The shader stage + * \returns Shader of the given stage + */ + Rc getShader( + VkShaderStageFlagBits stage) const; + /** * \brief Pipeline handle * From a42f03e32dee746a04c1ae668124dcad956b7ff8 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 23 Jun 2018 20:19:46 +0200 Subject: [PATCH 02/30] [dxbc] Add Xfb structures to DxbcModuleInfo --- src/d3d11/d3d11_device.cpp | 6 ++++++ src/dxbc/dxbc_compiler.cpp | 8 +++++++- src/dxbc/dxbc_compiler.h | 2 +- src/dxbc/dxbc_modinfo.h | 30 ++++++++++++++++++++++++++++++ src/dxvk/dxvk_device.cpp | 5 +++-- src/dxvk/dxvk_shader.cpp | 3 ++- src/dxvk/dxvk_shader.h | 22 ++++++++++++++++++++++ tests/dxbc/test_dxbc_compiler.cpp | 1 + 8 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index b5e13a5d..5bfcc955 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -622,6 +622,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (FAILED(this->CreateShaderModule(&module, pShaderBytecode, BytecodeLength, pClassLinkage, @@ -647,6 +648,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (FAILED(this->CreateShaderModule(&module, pShaderBytecode, BytecodeLength, pClassLinkage, @@ -691,6 +693,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (FAILED(this->CreateShaderModule(&module, pShaderBytecode, BytecodeLength, pClassLinkage, @@ -719,6 +722,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (tessInfo.maxTessFactor >= 8.0f) moduleInfo.tess = &tessInfo; @@ -747,6 +751,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (FAILED(this->CreateShaderModule(&module, pShaderBytecode, BytecodeLength, pClassLinkage, @@ -772,6 +777,7 @@ namespace dxvk { DxbcModuleInfo moduleInfo; moduleInfo.options = m_dxbcOptions; moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; if (FAILED(this->CreateShaderModule(&module, pShaderBytecode, BytecodeLength, pClassLinkage, diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 88d6b91c..f3f36d03 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -199,7 +199,12 @@ namespace dxvk { m_entryPointInterfaces.size(), m_entryPointInterfaces.data()); m_module.setDebugName(m_entryPointId, "main"); - + + DxvkShaderOptions shaderOptions = { }; + + if (m_moduleInfo.xfb != nullptr) + shaderOptions.rasterizedStream = m_moduleInfo.xfb->rasterizedStream; + // Create the shader module object return new DxvkShader( m_programInfo.shaderStage(), @@ -207,6 +212,7 @@ namespace dxvk { m_resourceSlots.data(), m_interfaceSlots, m_module.compile(), + shaderOptions, std::move(m_immConstData)); } diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 20323335..93ec819b 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -488,7 +488,7 @@ namespace dxvk { // Inter-stage shader interface slots. Also // covers vertex input and fragment output. DxvkInterfaceSlots m_interfaceSlots; - + /////////////////////////////////// // Shader-specific data structures DxbcCompilerVsPart m_vs; diff --git a/src/dxbc/dxbc_modinfo.h b/src/dxbc/dxbc_modinfo.h index 56588546..13e733dd 100644 --- a/src/dxbc/dxbc_modinfo.h +++ b/src/dxbc/dxbc_modinfo.h @@ -14,6 +14,35 @@ namespace dxvk { float maxTessFactor; }; + /** + * \brief Xfb capture entry + * + * Stores an output variable to capture, + * as well as the buffer to write it to. + */ + struct DxbcXfbEntry { + const char* semanticName; + uint32_t semanticIndex; + uint32_t componentIndex; + uint32_t componentCount; + uint32_t streamId; + uint32_t bufferId; + uint32_t offset; + }; + + /** + * \brief Xfb info + * + * Stores capture entries and output buffer + * strides. This structure must only be + * defined if \c entryCount is non-zero. + */ + struct DxbcXfbInfo { + uint32_t entryCount; + DxbcXfbEntry entries[128]; + uint32_t strides[4]; + int32_t rasterizedStream; + }; /** * \brief Shader module info @@ -24,6 +53,7 @@ namespace dxvk { struct DxbcModuleInfo { DxbcOptions options; DxbcTessInfo* tess; + DxbcXfbInfo* xfb; }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index 930f92f6..ed59f0e3 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -186,8 +186,9 @@ namespace dxvk { const DxvkInterfaceSlots& iface, const SpirvCodeBuffer& code) { return new DxvkShader(stage, - slotCount, slotInfos, iface, - code, DxvkShaderConstData()); + slotCount, slotInfos, iface, code, + DxvkShaderOptions(), + DxvkShaderConstData()); } diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index c597240b..ff22cc31 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -81,9 +81,10 @@ namespace dxvk { const DxvkResourceSlot* slotInfos, const DxvkInterfaceSlots& iface, const SpirvCodeBuffer& code, + const DxvkShaderOptions& options, DxvkShaderConstData&& constData) : m_stage(stage), m_code(code), m_interface(iface), - m_constData(std::move(constData)) { + m_options(options), m_constData(std::move(constData)) { // Write back resource slot infos for (uint32_t i = 0; i < slotCount; i++) m_slots.push_back(slotInfos[i]); diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index b6d414b5..a86ccd8c 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -50,6 +50,18 @@ namespace dxvk { }; + /** + * \brief Additional shader options + * + * Contains additional properties that should be + * taken into account when creating pipelines. + */ + struct DxvkShaderOptions { + /// Rasterized stream, or -1 + int32_t rasterizedStream; + }; + + /** * \brief Shader constants * @@ -107,6 +119,7 @@ namespace dxvk { const DxvkResourceSlot* slotInfos, const DxvkInterfaceSlots& iface, const SpirvCodeBuffer& code, + const DxvkShaderOptions& options, DxvkShaderConstData&& constData); ~DxvkShader(); @@ -164,6 +177,14 @@ namespace dxvk { return m_interface; } + /** + * \brief Shader options + * \returns Shader options + */ + DxvkShaderOptions shaderOptions() const { + return m_options; + } + /** * \brief Shader constant data * @@ -216,6 +237,7 @@ namespace dxvk { std::vector m_slots; std::vector m_idOffsets; DxvkInterfaceSlots m_interface; + DxvkShaderOptions m_options; DxvkShaderConstData m_constData; DxvkShaderKey m_key; diff --git a/tests/dxbc/test_dxbc_compiler.cpp b/tests/dxbc/test_dxbc_compiler.cpp index 0754dede..1920819f 100644 --- a/tests/dxbc/test_dxbc_compiler.cpp +++ b/tests/dxbc/test_dxbc_compiler.cpp @@ -43,6 +43,7 @@ int WINAPI WinMain(HINSTANCE hInstance, DxbcModuleInfo moduleInfo; moduleInfo.options = DxbcOptions(); + moduleInfo.xfb = nullptr; Rc shader = module.compile(moduleInfo, ifileName); std::ofstream ofile(str::fromws(argv[2]), std::ios::binary); From 6a5fe2247ad351c50a4d7dc7d5ea421ba1168822 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 23 Jun 2018 23:46:24 +0200 Subject: [PATCH 03/30] [dxbc] Add support for multiple streams in geometry shaders --- src/dxbc/dxbc_compiler.cpp | 24 +++++++++++++++++++++--- src/spirv/spirv_module.cpp | 20 ++++++++++++++++---- src/spirv/spirv_module.h | 6 ++++-- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index f3f36d03..7e5c80dc 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -796,7 +796,7 @@ namespace dxvk { void DxbcCompiler::emitDclStream(const DxbcShaderInstruction& ins) { - if (ins.dst[0].idx[0].offset != 0) + if (ins.dst[0].idx[0].offset != 0 && m_moduleInfo.xfb == nullptr) Logger::err("Dxbc: Multiple streams not supported"); } @@ -2053,6 +2053,16 @@ namespace dxvk { void DxbcCompiler::emitGeometryEmit(const DxbcShaderInstruction& ins) { + // In xfb mode we might have multiple streams, so + // we have to figure out which stream to write to + uint32_t streamId = 0; + uint32_t streamVar = 0; + + if (m_moduleInfo.xfb != nullptr) { + streamId = ins.dstCount > 0 ? ins.dst[0].idx[0].offset : 0; + streamVar = m_module.constu32(streamId); + } + // Checking the negation is easier for EmitThenCut/EmitThenCutStream bool doEmit = ins.op != DxbcOpcode::Cut && ins.op != DxbcOpcode::CutStream; bool doCut = ins.op != DxbcOpcode::Emit && ins.op != DxbcOpcode::EmitStream; @@ -2061,11 +2071,11 @@ namespace dxvk { emitOutputSetup(); emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); - m_module.opEmitVertex(); + m_module.opEmitVertex(streamVar); } if (doCut) - m_module.opEndPrimitive(); + m_module.opEndPrimitive(streamVar); } @@ -6008,6 +6018,14 @@ namespace dxvk { m_module.enableCapability(spv::CapabilityGeometry); m_module.enableCapability(spv::CapabilityClipDistance); m_module.enableCapability(spv::CapabilityCullDistance); + + // Enable capabilities for xfb mode if necessary + if (m_moduleInfo.xfb != nullptr) { + m_module.enableCapability(spv::CapabilityGeometryStreams); + m_module.enableCapability(spv::CapabilityTransformFeedback); + + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeXfb); + } // Declare the per-vertex output block. Outputs are not // declared as arrays, instead they will be flushed when diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 771ba027..bd69bde8 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -2937,13 +2937,25 @@ namespace dxvk { } - void SpirvModule::opEmitVertex() { - m_code.putIns (spv::OpEmitVertex, 1); + void SpirvModule::opEmitVertex( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEmitVertex, 1); + } else { + m_code.putIns (spv::OpEmitStreamVertex, 2); + m_code.putWord(streamId); + } } - void SpirvModule::opEndPrimitive() { - m_code.putIns (spv::OpEndPrimitive, 1); + void SpirvModule::opEndPrimitive( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEndPrimitive, 1); + } else { + m_code.putIns (spv::OpEndStreamPrimitive, 2); + m_code.putWord(streamId); + } } diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 73b702e0..9886fd3e 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -1022,9 +1022,11 @@ namespace dxvk { void opKill(); - void opEmitVertex(); + void opEmitVertex( + uint32_t streamId); - void opEndPrimitive(); + void opEndPrimitive( + uint32_t streamId); private: From bb780bbe10f958fabce659d899b1cb59e5263598 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 24 Jun 2018 01:07:06 +0200 Subject: [PATCH 04/30] [dxbc] Add Xfb decorations --- src/spirv/spirv_module.cpp | 28 ++++++++++++++++++++++++++++ src/spirv/spirv_module.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index bd69bde8..0f63facb 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -438,6 +438,34 @@ namespace dxvk { m_annotations.putInt32(specId); } + + void SpirvModule::decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationStream); + m_annotations.putInt32(streamId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbBuffer); + m_annotations.putInt32(bufferId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbStride); + m_annotations.putInt32(stride); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putInt32(offset); + } + void SpirvModule::memberDecorateBuiltIn( uint32_t structId, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 9886fd3e..36f0fdd2 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -197,6 +197,13 @@ namespace dxvk { uint32_t object, uint32_t specId); + void decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride); + void memberDecorateBuiltIn( uint32_t structId, uint32_t memberId, From 017699df1504a02a2210a92cf3d207a7f6f43122 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 24 Jun 2018 01:07:48 +0200 Subject: [PATCH 05/30] [dxbc] Implement Xfb output declarations and setup --- src/dxbc/dxbc_compiler.cpp | 89 ++++++++++++++++++++++++++++++++++++-- src/dxbc/dxbc_compiler.h | 22 ++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 7e5c80dc..33bdb753 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -673,12 +673,19 @@ namespace dxvk { info.type.ccount = regType.ccount; info.type.alength = regDim; info.sclass = spv::StorageClassOutput; + + // In xfb mode, we set up the actual + // output vars when emitting a vertex + if (m_moduleInfo.xfb != nullptr) + info.sclass = spv::StorageClassPrivate; const uint32_t varId = this->emitNewVariable(info); - - m_module.decorateLocation(varId, regIdx); m_module.setDebugName(varId, str::format("o", regIdx).c_str()); - m_entryPointInterfaces.push_back(varId); + + if (info.sclass == spv::StorageClassOutput) { + m_module.decorateLocation(varId, regIdx); + m_entryPointInterfaces.push_back(varId); + } m_oRegs.at(regIdx) = { regType, varId }; @@ -2071,6 +2078,7 @@ namespace dxvk { emitOutputSetup(); emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); + emitXfbOutputSetup(streamId); m_module.opEmitVertex(streamVar); } @@ -6050,6 +6058,10 @@ namespace dxvk { spv::BuiltInCullDistance, spv::StorageClassOutput); + // Emit Xfb variables if necessary + if (m_moduleInfo.xfb != nullptr) + emitXfbOutputDeclarations(); + // Main function of the vertex shader m_gs.functionId = m_module.allocateId(); m_module.setDebugName(m_gs.functionId, "gs_main"); @@ -6226,6 +6238,77 @@ namespace dxvk { } + void DxbcCompiler::emitXfbOutputDeclarations() { + for (uint32_t i = 0; i < m_moduleInfo.xfb->entryCount; i++) { + const DxbcXfbEntry* xfbEntry = m_moduleInfo.xfb->entries + i; + const DxbcSgnEntry* sigEntry = m_osgn->find( + xfbEntry->semanticName, + xfbEntry->semanticIndex, + xfbEntry->streamId); + + if (sigEntry == nullptr) + continue; + + DxbcRegisterInfo varInfo; + varInfo.type.ctype = DxbcScalarType::Float32; + varInfo.type.ccount = xfbEntry->componentCount; + varInfo.type.alength = 0; + varInfo.sclass = spv::StorageClassOutput; + + uint32_t dstComponentMask = (1 << xfbEntry->componentCount) - 1; + uint32_t srcComponentMask = dstComponentMask + << sigEntry->componentMask.firstSet() + << xfbEntry->componentIndex; + + DxbcXfbVar xfbVar; + xfbVar.varId = emitNewVariable(varInfo); + xfbVar.streamId = xfbEntry->streamId; + xfbVar.outputId = sigEntry->registerId; + xfbVar.srcMask = DxbcRegMask(srcComponentMask); + xfbVar.dstMask = DxbcRegMask(dstComponentMask); + m_xfbVars.push_back(xfbVar); + + m_entryPointInterfaces.push_back(xfbVar.varId); + m_module.setDebugName(xfbVar.varId, + str::format("xfb", i).c_str()); + + m_module.decorateXfb(xfbVar.varId, + xfbEntry->streamId, xfbEntry->bufferId, xfbEntry->offset, + m_moduleInfo.xfb->strides[xfbEntry->bufferId]); + } + + // TODO Compact location/component assignment + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + m_xfbVars[i].location = i; + m_xfbVars[i].component = 0; + } + + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + const DxbcXfbVar* var = &m_xfbVars[i]; + + m_module.decorateLocation (var->varId, var->location); + m_module.decorateComponent(var->varId, var->component); + } + } + + + void DxbcCompiler::emitXfbOutputSetup(uint32_t streamId) { + 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 dstPtr; + dstPtr.type.ctype = DxbcScalarType::Float32; + dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount(); + dstPtr.id = m_xfbVars[i].varId; + + DxbcRegisterValue value = emitRegisterExtract( + emitValueLoad(srcPtr), m_xfbVars[i].srcMask); + emitValueStore(dstPtr, value, m_xfbVars[i].dstMask); + } + } + } + + void DxbcCompiler::emitHsControlPointPhase( const DxbcCompilerHsControlPointPhase& phase) { m_module.opFunctionCall( diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 93ec819b..2e5e20fd 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -122,6 +122,17 @@ namespace dxvk { uint32_t labelElse = 0; uint32_t labelEnd = 0; }; + + + struct DxbcXfbVar { + uint32_t varId = 0; + uint32_t streamId = 0; + uint32_t outputId = 0; + DxbcRegMask srcMask = 0; + DxbcRegMask dstMask = 0; + uint32_t location = 0; + uint32_t component = 0; + }; /** @@ -419,6 +430,10 @@ namespace dxvk { DxbcRegisterPointer, DxbcMaxInterfaceRegs> m_oRegs; std::vector m_oMappings; + + ///////////////////////////////////////////// + // xfb output registers for geometry shaders + std::vector m_xfbVars; ////////////////////////////////////////////////////// // Shader resource variables. These provide access to @@ -1044,6 +1059,13 @@ namespace dxvk { void emitGsFinalize(); void emitPsFinalize(); void emitCsFinalize(); + + /////////////////////// + // Xfb related methods + void emitXfbOutputDeclarations(); + + void emitXfbOutputSetup( + uint32_t streamId); /////////////////////////////// // Hull shader phase methods From d2c62a864521abc86b2b7dc01103d9fc642ee695 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 25 Jul 2018 22:45:23 +0200 Subject: [PATCH 06/30] [dxbc] Implement passthrough geometry shader This is needed when vertex or domain shader code is passed to CreateGeometryShaderWithStreamOutput. - Fix compilation with new DxbcProgramInfo. --- src/dxbc/dxbc_compiler.cpp | 62 ++++++++++++++++++++++++++++++++++++-- src/dxbc/dxbc_compiler.h | 19 +++++++++++- src/dxbc/dxbc_module.cpp | 19 ++++++++++++ src/dxbc/dxbc_module.h | 14 +++++++++ 4 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 33bdb753..9c2fc70a 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -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 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(); diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 2e5e20fd..d1aff00f 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -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 diff --git a/src/dxbc/dxbc_module.cpp b/src/dxbc/dxbc_module.cpp index 5463cf9a..e712438d 100644 --- a/src/dxbc/dxbc_module.cpp +++ b/src/dxbc/dxbc_module.cpp @@ -64,6 +64,25 @@ namespace dxvk { } + Rc 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 { diff --git a/src/dxbc/dxbc_module.h b/src/dxbc/dxbc_module.h index fc420e70..35b20160 100644 --- a/src/dxbc/dxbc_module.h +++ b/src/dxbc/dxbc_module.h @@ -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 compilePassthroughShader( + const DxbcModuleInfo& moduleInfo, + const std::string& fileName) const; + private: DxbcHeader m_header; From 8cdccc6b050e41c43f24af36f4577d967ee3df24 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 14:06:18 +0200 Subject: [PATCH 07/30] [dxvk] Update Vulkan headers --- include/vulkan/vulkan_core.h | 745 ++++++++++++++++++++++++++++++++++- 1 file changed, 742 insertions(+), 3 deletions(-) diff --git a/include/vulkan/vulkan_core.h b/include/vulkan/vulkan_core.h index fe450142..e171626e 100644 --- a/include/vulkan/vulkan_core.h +++ b/include/vulkan/vulkan_core.h @@ -43,7 +43,7 @@ extern "C" { #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) // Version of this file -#define VK_HEADER_VERSION 84 +#define VK_HEADER_VERSION 87 #define VK_NULL_HANDLE 0 @@ -297,7 +297,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, @@ -404,18 +408,45 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005, + VK_STRUCTURE_TYPE_RAYTRACING_PIPELINE_CREATE_INFO_NVX = 1000165000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NVX = 1000165001, + VK_STRUCTURE_TYPE_GEOMETRY_INSTANCE_NVX = 1000165002, + VK_STRUCTURE_TYPE_GEOMETRY_NVX = 1000165003, + VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NVX = 1000165004, + VK_STRUCTURE_TYPE_GEOMETRY_AABB_NVX = 1000165005, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NVX = 1000165006, + VK_STRUCTURE_TYPE_DESCRIPTOR_ACCELERATION_STRUCTURE_INFO_NVX = 1000165007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NVX = 1000165008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAYTRACING_PROPERTIES_NVX = 1000165009, + VK_STRUCTURE_TYPE_HIT_SHADER_MODULE_CREATE_INFO_NVX = 1000165010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000, + VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = 1000177000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000, VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000, + VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, @@ -806,6 +837,8 @@ typedef enum VkQueryType { VK_QUERY_TYPE_OCCLUSION = 0, VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, VK_QUERY_TYPE_TIMESTAMP = 2, + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, + VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000, VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), @@ -835,6 +868,7 @@ typedef enum VkImageLayout { VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED, @@ -1068,6 +1102,9 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, + VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, + VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE, VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1), @@ -1131,6 +1168,7 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000, VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), @@ -1159,6 +1197,7 @@ typedef enum VkAttachmentStoreOp { typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, + VK_PIPELINE_BIND_POINT_RAYTRACING_NVX = 1000165000, VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), @@ -1230,6 +1269,7 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, @@ -1297,6 +1337,7 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100, VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageUsageFlagBits; typedef VkFlags VkImageUsageFlags; @@ -1314,6 +1355,7 @@ typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100, VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, + VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, @@ -1391,8 +1433,13 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000, + VK_PIPELINE_STAGE_RAYTRACING_BIT_NVX = 0x00200000, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; @@ -1480,7 +1527,10 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, + VK_BUFFER_USAGE_RAYTRACING_BIT_NVX = 0x00000400, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferUsageFlagBits; typedef VkFlags VkBufferUsageFlags; @@ -1495,6 +1545,7 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010, + VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NVX = 0x00000020, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1511,6 +1562,14 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_RAYGEN_BIT_NVX = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_NVX = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_NVX = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_NVX = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_NVX = 0x00002000, + VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; typedef VkFlags VkPipelineVertexInputStateCreateFlags; @@ -1592,10 +1651,16 @@ typedef enum VkAccessFlagBits { VK_ACCESS_HOST_WRITE_BIT = 0x00004000, VK_ACCESS_MEMORY_READ_BIT = 0x00008000, VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX = 0x00400000, VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAccessFlagBits; typedef VkFlags VkAccessFlags; @@ -4062,6 +4127,8 @@ typedef struct VkMemoryRequirements2 { VkMemoryRequirements memoryRequirements; } VkMemoryRequirements2; +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; + typedef struct VkSparseImageMemoryRequirements2 { VkStructureType sType; void* pNext; @@ -5826,8 +5893,6 @@ typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; -typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; - typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; @@ -5992,6 +6057,60 @@ typedef struct VkPhysicalDevice8BitStorageFeaturesKHR { +#define VK_KHR_shader_atomic_int64 1 +#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" + +typedef struct VkPhysicalDeviceShaderAtomicInt64FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; +} VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; + + + +#define VK_KHR_driver_properties 1 +#define VK_MAX_DRIVER_NAME_SIZE_KHR 256 +#define VK_MAX_DRIVER_INFO_SIZE_KHR 256 +#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" + + +typedef enum VkDriverIdKHR { + VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1, + VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2, + VK_DRIVER_ID_MESA_RADV_KHR = 3, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8, + VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9, + VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR, + VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_ARM_PROPRIETARY_KHR, + VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_ARM_PROPRIETARY_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1), + VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDriverIdKHR; + +typedef struct VkConformanceVersionKHR { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersionKHR; + +typedef struct VkPhysicalDeviceDriverPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE_KHR]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE_KHR]; + VkConformanceVersionKHR conformanceVersion; +} VkPhysicalDeviceDriverPropertiesKHR; + + + #define VK_KHR_vulkan_memory_model 1 #define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2 #define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" @@ -6049,6 +6168,7 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX_EXT = 1000165000, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, @@ -6250,6 +6370,95 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { +#define VK_EXT_transform_feedback 1 +#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" + +typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; + +typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 transformFeedback; + VkBool32 geometryStreams; +} VkPhysicalDeviceTransformFeedbackFeaturesEXT; + +typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTransformFeedbackStreams; + uint32_t maxTransformFeedbackBuffers; + VkDeviceSize maxTransformFeedbackBufferSize; + uint32_t maxTransformFeedbackStreamDataSize; + uint32_t maxTransformFeedbackBufferDataSize; + uint32_t maxTransformFeedbackBufferDataStride; + VkBool32 transformFeedbackQueries; + VkBool32 transformFeedbackStreamsLinesTriangles; + VkBool32 transformFeedbackRasterizationStreamSelect; + VkBool32 transformFeedbackDraw; +} VkPhysicalDeviceTransformFeedbackPropertiesEXT; + +typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateStreamCreateFlagsEXT flags; + uint32_t rasterizationStream; +} VkPipelineRasterizationStateStreamCreateInfoEXT; + + +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride); +#endif + #define VK_AMD_draw_indirect_count 1 #define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 #define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" @@ -6355,6 +6564,18 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" +#define VK_NV_corner_sampled_image 1 +#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 +#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" + +typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cornerSampledImage; +} VkPhysicalDeviceCornerSampledImageFeaturesNV; + + + #define VK_IMG_format_pvrtc 1 #define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 #define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" @@ -7711,6 +7932,397 @@ typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT { #define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" +#define VK_NV_shading_rate_image 1 +#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 +#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" + + +typedef enum VkShadingRatePaletteEntryNV { + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0, + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1, + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2, + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3, + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, + VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV, + VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1), + VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF +} VkShadingRatePaletteEntryNV; + +typedef enum VkCoarseSampleOrderTypeNV { + VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0, + VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, + VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, + VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, + VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV, + VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV, + VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1), + VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoarseSampleOrderTypeNV; + +typedef struct VkShadingRatePaletteNV { + uint32_t shadingRatePaletteEntryCount; + const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; +} VkShadingRatePaletteNV; + +typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 shadingRateImageEnable; + uint32_t viewportCount; + const VkShadingRatePaletteNV* pShadingRatePalettes; +} VkPipelineViewportShadingRateImageStateCreateInfoNV; + +typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shadingRateImage; + VkBool32 shadingRateCoarseSampleOrder; +} VkPhysicalDeviceShadingRateImageFeaturesNV; + +typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { + VkStructureType sType; + void* pNext; + VkExtent2D shadingRateTexelSize; + uint32_t shadingRatePaletteSize; + uint32_t shadingRateMaxCoarseSamples; +} VkPhysicalDeviceShadingRateImagePropertiesNV; + +typedef struct VkCoarseSampleLocationNV { + uint32_t pixelX; + uint32_t pixelY; + uint32_t sample; +} VkCoarseSampleLocationNV; + +typedef struct VkCoarseSampleOrderCustomNV { + VkShadingRatePaletteEntryNV shadingRate; + uint32_t sampleCount; + uint32_t sampleLocationCount; + const VkCoarseSampleLocationNV* pSampleLocations; +} VkCoarseSampleOrderCustomNV; + +typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCoarseSampleOrderTypeNV sampleOrderType; + uint32_t customSampleOrderCount; + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; +} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; + + +typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkShadingRatePaletteNV* pShadingRatePalettes); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( + VkCommandBuffer commandBuffer, + VkCoarseSampleOrderTypeNV sampleOrderType, + uint32_t customSampleOrderCount, + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +#endif + +#define VK_NVX_raytracing 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNVX) + +#define VK_NVX_RAYTRACING_SPEC_VERSION 1 +#define VK_NVX_RAYTRACING_EXTENSION_NAME "VK_NVX_raytracing" + + +typedef enum VkGeometryTypeNVX { + VK_GEOMETRY_TYPE_TRIANGLES_NVX = 0, + VK_GEOMETRY_TYPE_AABBS_NVX = 1, + VK_GEOMETRY_TYPE_BEGIN_RANGE_NVX = VK_GEOMETRY_TYPE_TRIANGLES_NVX, + VK_GEOMETRY_TYPE_END_RANGE_NVX = VK_GEOMETRY_TYPE_AABBS_NVX, + VK_GEOMETRY_TYPE_RANGE_SIZE_NVX = (VK_GEOMETRY_TYPE_AABBS_NVX - VK_GEOMETRY_TYPE_TRIANGLES_NVX + 1), + VK_GEOMETRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF +} VkGeometryTypeNVX; + +typedef enum VkAccelerationStructureTypeNVX { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX = 1, + VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX, + VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX, + VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NVX = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX + 1), + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF +} VkAccelerationStructureTypeNVX; + +typedef enum VkCopyAccelerationStructureModeNVX { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX, + VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX, + VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NVX = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX + 1), + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NVX = 0x7FFFFFFF +} VkCopyAccelerationStructureModeNVX; + + +typedef enum VkGeometryFlagBitsNVX { + VK_GEOMETRY_OPAQUE_BIT_NVX = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NVX = 0x00000002, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF +} VkGeometryFlagBitsNVX; +typedef VkFlags VkGeometryFlagsNVX; + +typedef enum VkGeometryInstanceFlagBitsNVX { + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NVX = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_FLIP_WINDING_BIT_NVX = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NVX = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NVX = 0x00000008, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsNVX; +typedef VkFlags VkGeometryInstanceFlagsNVX; + +typedef enum VkBuildAccelerationStructureFlagBitsNVX { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NVX = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NVX = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NVX = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NVX = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NVX = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsNVX; +typedef VkFlags VkBuildAccelerationStructureFlagsNVX; + +typedef struct VkRaytracingPipelineCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const uint32_t* pGroupNumbers; + uint32_t maxRecursionDepth; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRaytracingPipelineCreateInfoNVX; + +typedef struct VkGeometryTrianglesNVX { + VkStructureType sType; + const void* pNext; + VkBuffer vertexData; + VkDeviceSize vertexOffset; + uint32_t vertexCount; + VkDeviceSize vertexStride; + VkFormat vertexFormat; + VkBuffer indexData; + VkDeviceSize indexOffset; + uint32_t indexCount; + VkIndexType indexType; + VkBuffer transformData; + VkDeviceSize transformOffset; +} VkGeometryTrianglesNVX; + +typedef struct VkGeometryAABBNVX { + VkStructureType sType; + const void* pNext; + VkBuffer aabbData; + uint32_t numAABBs; + uint32_t stride; + VkDeviceSize offset; +} VkGeometryAABBNVX; + +typedef struct VkGeometryDataNVX { + VkGeometryTrianglesNVX triangles; + VkGeometryAABBNVX aabbs; +} VkGeometryDataNVX; + +typedef struct VkGeometryNVX { + VkStructureType sType; + const void* pNext; + VkGeometryTypeNVX geometryType; + VkGeometryDataNVX geometry; + VkGeometryFlagsNVX flags; +} VkGeometryNVX; + +typedef struct VkAccelerationStructureCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNVX type; + VkBuildAccelerationStructureFlagsNVX flags; + VkDeviceSize compactedSize; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNVX* pGeometries; +} VkAccelerationStructureCreateInfoNVX; + +typedef struct VkBindAccelerationStructureMemoryInfoNVX { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNVX accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNVX; + +typedef struct VkDescriptorAccelerationStructureInfoNVX { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNVX* pAccelerationStructures; +} VkDescriptorAccelerationStructureInfoNVX; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoNVX { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNVX accelerationStructure; +} VkAccelerationStructureMemoryRequirementsInfoNVX; + +typedef struct VkPhysicalDeviceRaytracingPropertiesNVX { + VkStructureType sType; + void* pNext; + uint32_t shaderHeaderSize; + uint32_t maxRecursionDepth; + uint32_t maxGeometryCount; +} VkPhysicalDeviceRaytracingPropertiesNVX; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNVX)(VkDevice device, const VkAccelerationStructureCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNVX* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureScratchMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNVX)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureTypeNVX type, uint32_t instanceCount, VkBuffer instanceData, VkDeviceSize instanceOffset, uint32_t geometryCount, const VkGeometryNVX* pGeometries, VkBuildAccelerationStructureFlagsNVX flags, VkBool32 update, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkCopyAccelerationStructureModeNVX mode); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNVX)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, uint32_t width, uint32_t height); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRaytracingPipelinesNVX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRaytracingPipelineCreateInfoNVX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRaytracingShaderHandlesNVX)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructurePropertiesNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNVX)(VkDevice device, VkPipeline pipeline, uint32_t shader); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNVX( + VkDevice device, + const VkAccelerationStructureCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureNVX* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNVX( + VkDevice device, + VkAccelerationStructureNVX accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNVX( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, + VkMemoryRequirements2KHR* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureScratchMemoryRequirementsNVX( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, + VkMemoryRequirements2KHR* pMemoryRequirements); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNVX( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNVX( + VkCommandBuffer commandBuffer, + VkAccelerationStructureTypeNVX type, + uint32_t instanceCount, + VkBuffer instanceData, + VkDeviceSize instanceOffset, + uint32_t geometryCount, + const VkGeometryNVX* pGeometries, + VkBuildAccelerationStructureFlagsNVX flags, + VkBool32 update, + VkAccelerationStructureNVX dst, + VkAccelerationStructureNVX src, + VkBuffer scratch, + VkDeviceSize scratchOffset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNVX( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNVX dst, + VkAccelerationStructureNVX src, + VkCopyAccelerationStructureModeNVX mode); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNVX( + VkCommandBuffer commandBuffer, + VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, + VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, + VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, + VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, + uint32_t width, + uint32_t height); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRaytracingPipelinesNVX( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRaytracingPipelineCreateInfoNVX* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRaytracingShaderHandlesNVX( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNVX( + VkDevice device, + VkAccelerationStructureNVX accelerationStructure, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructurePropertiesNVX( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNVX accelerationStructure, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNVX( + VkDevice device, + VkPipeline pipeline, + uint32_t shader); +#endif + +#define VK_NV_representative_fragment_test 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" + +typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 representativeFragmentTest; +} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; + +typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 representativeFragmentTestEnable; +} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + + + #define VK_EXT_global_priority 1 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 #define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" @@ -7845,6 +8457,133 @@ typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { #define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" +#define VK_NV_compute_shader_derivatives 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" + +typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeDerivativeGroupQuads; + VkBool32 computeDerivativeGroupLinear; +} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; + + + +#define VK_NV_mesh_shader 1 +#define VK_NV_MESH_SHADER_SPEC_VERSION 1 +#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" + +typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; +} VkPhysicalDeviceMeshShaderFeaturesNV; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDrawMeshTasksCount; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskTotalMemorySize; + uint32_t maxTaskOutputCount; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshTotalMemorySize; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; +} VkPhysicalDeviceMeshShaderPropertiesNV; + +typedef struct VkDrawMeshTasksIndirectCommandNV { + uint32_t taskCount; + uint32_t firstTask; +} VkDrawMeshTasksIndirectCommandNV; + + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( + VkCommandBuffer commandBuffer, + uint32_t taskCount, + uint32_t firstTask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + +#define VK_NV_fragment_shader_barycentric 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" + +typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderBarycentric; +} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + + + +#define VK_NV_shader_image_footprint 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" + +typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 imageFootprint; +} VkPhysicalDeviceShaderImageFootprintFeaturesNV; + + + +#define VK_NV_scissor_exclusive 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 +#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" + +typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t exclusiveScissorCount; + const VkRect2D* pExclusiveScissors; +} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + +typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 exclusiveScissor; +} VkPhysicalDeviceExclusiveScissorFeaturesNV; + + +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkRect2D* pExclusiveScissors); +#endif + #define VK_NV_device_diagnostic_checkpoints 1 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" From bf906aa226ab5a0a8a79de82460b7f7bd1ad5b65 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 6 Sep 2018 13:06:14 +0200 Subject: [PATCH 08/30] [dxvk] Add support for transform feedback access flags --- src/dxvk/dxvk_barrier.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dxvk/dxvk_barrier.cpp b/src/dxvk/dxvk_barrier.cpp index 0783ab28..b408e8fd 100644 --- a/src/dxvk/dxvk_barrier.cpp +++ b/src/dxvk/dxvk_barrier.cpp @@ -149,7 +149,8 @@ namespace dxvk { | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_HOST_READ_BIT - | VK_ACCESS_MEMORY_READ_BIT; + | VK_ACCESS_MEMORY_READ_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT; const VkAccessFlags wflags = VK_ACCESS_SHADER_WRITE_BIT @@ -157,7 +158,9 @@ namespace dxvk { | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT - | VK_ACCESS_MEMORY_WRITE_BIT; + | VK_ACCESS_MEMORY_WRITE_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; DxvkAccessFlags result; if (flags & rflags) result.set(DxvkAccess::Read); From 61d56a173239d0a9f88c1e6980022f1ca54c2a5f Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 15:04:50 +0200 Subject: [PATCH 09/30] [dxvk] Add definitions for transform feedback entry points --- src/dxvk/dxvk_cmdlist.h | 63 ++++++++++++++++++++++++++++ src/dxvk/vulkan/dxvk_vulkan_loader.h | 9 ++++ 2 files changed, 72 insertions(+) diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 25246865..f70ad676 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -221,12 +221,32 @@ namespace dxvk { } + void cmdBeginQueryIndexed( + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index) { + m_vkd->vkCmdBeginQueryIndexedEXT( + m_execBuffer, queryPool, query, flags, index); + } + + void cmdBeginRenderPass( const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) { m_vkd->vkCmdBeginRenderPass(m_execBuffer, pRenderPassBegin, contents); } + + + void cmdBeginTransformFeedback( + uint32_t firstBuffer, + uint32_t bufferCount, + const VkBuffer* counterBuffers, + const VkDeviceSize* counterOffsets) { + m_vkd->vkCmdBeginTransformFeedbackEXT(m_execBuffer, + firstBuffer, bufferCount, counterBuffers, counterOffsets); + } void cmdBindDescriptorSet( @@ -256,6 +276,17 @@ namespace dxvk { m_vkd->vkCmdBindPipeline(m_execBuffer, pipelineBindPoint, pipeline); } + + + void cmdBindTransformFeedbackBuffers( + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes) { + m_vkd->vkCmdBindTransformFeedbackBuffersEXT(m_execBuffer, + firstBinding, bindingCount, pBuffers, pOffsets, pSizes); + } void cmdBindVertexBuffers( @@ -425,6 +456,19 @@ namespace dxvk { m_vkd->vkCmdDrawIndexedIndirect(m_execBuffer, buffer, offset, drawCount, stride); } + + + void cmdDrawIndirectVertexCount( + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride) { + m_vkd->vkCmdDrawIndirectByteCountEXT(m_execBuffer, + instanceCount, firstInstance, counterBuffer, + counterBufferOffset, counterOffset, vertexStride); + } void cmdEndQuery( @@ -432,6 +476,15 @@ namespace dxvk { uint32_t query) { m_vkd->vkCmdEndQuery(m_execBuffer, queryPool, query); } + + + void cmdEndQueryIndexed( + VkQueryPool queryPool, + uint32_t query, + uint32_t index) { + m_vkd->vkCmdEndQueryIndexedEXT( + m_execBuffer, queryPool, query, index); + } void cmdEndRenderPass() { @@ -439,6 +492,16 @@ namespace dxvk { } + void cmdEndTransformFeedback( + uint32_t firstBuffer, + uint32_t bufferCount, + const VkBuffer* counterBuffers, + const VkDeviceSize* counterOffsets) { + m_vkd->vkCmdEndTransformFeedbackEXT(m_execBuffer, + firstBuffer, bufferCount, counterBuffers, counterOffsets); + } + + void cmdFillBuffer( VkBuffer dstBuffer, VkDeviceSize dstOffset, diff --git a/src/dxvk/vulkan/dxvk_vulkan_loader.h b/src/dxvk/vulkan/dxvk_vulkan_loader.h index 6b2a53ec..8a9b8508 100644 --- a/src/dxvk/vulkan/dxvk_vulkan_loader.h +++ b/src/dxvk/vulkan/dxvk_vulkan_loader.h @@ -284,6 +284,15 @@ namespace dxvk::vk { VULKAN_FN(vkGetBufferMemoryRequirements2KHR); VULKAN_FN(vkGetImageMemoryRequirements2KHR); #endif + + #ifdef VK_EXT_transform_feedback + VULKAN_FN(vkCmdBindTransformFeedbackBuffersEXT); + VULKAN_FN(vkCmdBeginTransformFeedbackEXT); + VULKAN_FN(vkCmdEndTransformFeedbackEXT); + VULKAN_FN(vkCmdDrawIndirectByteCountEXT); + VULKAN_FN(vkCmdBeginQueryIndexedEXT); + VULKAN_FN(vkCmdEndQueryIndexedEXT); + #endif }; } \ No newline at end of file From 13ecbcaaf59d82a78bdb83a0477610fdb08745f5 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 15:06:04 +0200 Subject: [PATCH 10/30] [dxvk] Enable VK_EXT_transform_feedback --- src/dxvk/dxvk_adapter.cpp | 3 ++- src/dxvk/dxvk_extensions.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 59c6eeb7..25059b1b 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -193,8 +193,9 @@ namespace dxvk { Rc DxvkAdapter::createDevice(DxvkDeviceFeatures enabledFeatures) { DxvkDeviceExtensions devExtensions; - std::array devExtensionList = {{ + std::array devExtensionList = {{ &devExtensions.extShaderViewportIndexLayer, + &devExtensions.extTransformFeedback, &devExtensions.extVertexAttributeDivisor, &devExtensions.khrDedicatedAllocation, &devExtensions.khrDescriptorUpdateTemplate, diff --git a/src/dxvk/dxvk_extensions.h b/src/dxvk/dxvk_extensions.h index 5b41efae..12160b5c 100644 --- a/src/dxvk/dxvk_extensions.h +++ b/src/dxvk/dxvk_extensions.h @@ -258,6 +258,7 @@ namespace dxvk { */ struct DxvkDeviceExtensions { DxvkExt extShaderViewportIndexLayer = { VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extTransformFeedback = { VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, DxvkExtMode::Optional }; DxvkExt extVertexAttributeDivisor = { VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, DxvkExtMode::Optional }; DxvkExt khrDedicatedAllocation = { VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, DxvkExtMode::Required }; DxvkExt khrDescriptorUpdateTemplate = { VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, DxvkExtMode::Required }; From e27083a04fdfb5daab01b376f392a166f8e51ab7 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 1 Aug 2018 01:11:00 +0200 Subject: [PATCH 11/30] [dxvk] Query transform feedback device properties if available --- src/dxvk/dxvk_adapter.cpp | 5 +++++ src/dxvk/dxvk_device_info.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 25059b1b..d6344e11 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -325,6 +325,11 @@ namespace dxvk { m_deviceInfo.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; m_deviceInfo.core.pNext = nullptr; + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceInfo.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; + m_deviceInfo.extTransformFeedback.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extTransformFeedback); + } + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { m_deviceInfo.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; m_deviceInfo.extVertexAttributeDivisor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extVertexAttributeDivisor); diff --git a/src/dxvk/dxvk_device_info.h b/src/dxvk/dxvk_device_info.h index de85fc5a..4af69735 100644 --- a/src/dxvk/dxvk_device_info.h +++ b/src/dxvk/dxvk_device_info.h @@ -14,6 +14,7 @@ namespace dxvk { */ struct DxvkDeviceInfo { VkPhysicalDeviceProperties2KHR core; + VkPhysicalDeviceTransformFeedbackPropertiesEXT extTransformFeedback; VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT extVertexAttributeDivisor; }; From 989a10ab88367f751b14bf82f06d12040d0179cc Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 14 Sep 2018 10:42:26 +0200 Subject: [PATCH 12/30] [dxvk] Enable transform feedback device feature if available - Enable geometryStreams feature --- src/d3d11/d3d11_device.cpp | 5 +++++ src/dxvk/dxvk_adapter.cpp | 12 ++++++++++++ src/dxvk/dxvk_device_info.h | 1 + 3 files changed, 18 insertions(+) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 5bfcc955..c7c2380f 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1338,6 +1338,9 @@ namespace dxvk { enabled.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; enabled.core.pNext = nullptr; + enabled.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + enabled.extTransformFeedback.pNext = nullptr; + enabled.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; enabled.extVertexAttributeDivisor.pNext = nullptr; @@ -1370,6 +1373,8 @@ namespace dxvk { enabled.core.features.shaderImageGatherExtended = VK_TRUE; enabled.core.features.textureCompressionBC = VK_TRUE; enabled.core.features.variableMultisampleRate = supported.core.features.variableMultisampleRate; + enabled.extTransformFeedback.transformFeedback = supported.extTransformFeedback.transformFeedback; + enabled.extTransformFeedback.geometryStreams = supported.extTransformFeedback.geometryStreams; } if (featureLevel >= D3D_FEATURE_LEVEL_10_1) { diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index d6344e11..079ade23 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -183,6 +183,8 @@ namespace dxvk { || !required.core.features.variableMultisampleRate) && (m_deviceFeatures.core.features.inheritedQueries || !required.core.features.inheritedQueries) + && (m_deviceFeatures.extTransformFeedback.transformFeedback + || !required.extTransformFeedback.transformFeedback) && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor || !required.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor) && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor @@ -226,6 +228,11 @@ namespace dxvk { // Create pNext chain for additional device features enabledFeatures.core.pNext = nullptr; + if (devExtensions.extTransformFeedback) { + enabledFeatures.extTransformFeedback.pNext = enabledFeatures.core.pNext; + enabledFeatures.core.pNext = &enabledFeatures.extTransformFeedback; + } + if (devExtensions.extVertexAttributeDivisor.revision() >= 3) { enabledFeatures.extVertexAttributeDivisor.pNext = enabledFeatures.core.pNext; enabledFeatures.core.pNext = &enabledFeatures.extVertexAttributeDivisor; @@ -352,6 +359,11 @@ namespace dxvk { m_deviceFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; m_deviceFeatures.core.pNext = nullptr; + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceFeatures.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + m_deviceFeatures.extTransformFeedback.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extTransformFeedback); + } + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) { m_deviceFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; m_deviceFeatures.extVertexAttributeDivisor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extVertexAttributeDivisor); diff --git a/src/dxvk/dxvk_device_info.h b/src/dxvk/dxvk_device_info.h index 4af69735..5434c44c 100644 --- a/src/dxvk/dxvk_device_info.h +++ b/src/dxvk/dxvk_device_info.h @@ -28,6 +28,7 @@ namespace dxvk { */ struct DxvkDeviceFeatures { VkPhysicalDeviceFeatures2KHR core; + VkPhysicalDeviceTransformFeedbackFeaturesEXT extTransformFeedback; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT extVertexAttributeDivisor; }; From 52e1671167a221cb762d8b62746e76bd0eb14527 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 17:08:32 +0200 Subject: [PATCH 13/30] [dxvk] Add Xfb context state --- src/dxvk/dxvk_context_state.h | 9 +++++++++ src/dxvk/dxvk_limits.h | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 5784ec35..33136a3b 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -22,6 +22,7 @@ namespace dxvk { */ enum class DxvkContextFlag : uint64_t { GpRenderPassBound, ///< Render pass is currently bound + GpXfbActive, ///< Transform feedback is enabled GpClearRenderTargets, ///< Render targets need to be cleared GpDirtyFramebuffer, ///< Framebuffer binding is out of date GpDirtyPipeline, ///< Graphics pipeline binding is out of date @@ -31,6 +32,7 @@ namespace dxvk { GpDirtyDescriptorSet, ///< Graphics descriptor set needs to be updated GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date GpDirtyIndexBuffer, ///< Index buffer binding are out of date + GpDirtyXfbBuffers, ///< Transform feedback buffer bindings are out of date GpDirtyBlendConstants, ///< Blend constants have changed GpDirtyStencilRef, ///< Stencil reference has changed GpDirtyViewport, ///< Viewport state has changed @@ -86,6 +88,12 @@ namespace dxvk { DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }; uint32_t stencilReference = 0; }; + + + struct DxvkXfbState { + std::array buffers; + std::array counters; + }; struct DxvkShaderStage { @@ -125,6 +133,7 @@ namespace dxvk { DxvkViewportState vp; DxvkDynamicDepthState ds; DxvkOutputMergerState om; + DxvkXfbState xfb; DxvkGraphicsPipelineState gp; DxvkComputePipelineState cp; diff --git a/src/dxvk/dxvk_limits.h b/src/dxvk/dxvk_limits.h index 12104fd4..183b4492 100644 --- a/src/dxvk/dxvk_limits.h +++ b/src/dxvk/dxvk_limits.h @@ -8,7 +8,8 @@ namespace dxvk { MaxNumRenderTargets = 8, MaxNumVertexAttributes = 32, MaxNumVertexBindings = 32, - MaxNumOutputStreams = 4, + MaxNumXfbBuffers = 4, + MaxNumXfbStreams = 4, MaxNumViewports = 16, MaxNumResourceSlots = 1216, MaxNumActiveBindings = 128, From 1f135f59edffa1079b133dc09b22c6702c8ce6c8 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 17:08:58 +0200 Subject: [PATCH 14/30] [dxvk] Add Xfb API stubs --- src/dxvk/dxvk_context.cpp | 11 +++++++++++ src/dxvk/dxvk_context.h | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 583dc91d..f550b7fb 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -218,6 +218,17 @@ namespace dxvk { } + void DxvkContext::bindXfbBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + const DxvkBufferSlice& counter) { + m_state.xfb.buffers [binding] = buffer; + m_state.xfb.counters[binding] = counter; + + m_flags.set(DxvkContextFlag::GpDirtyXfbBuffers); + } + + void DxvkContext::clearBuffer( const Rc& buffer, VkDeviceSize offset, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index d0a3ae3e..b186bf6a 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -173,6 +173,18 @@ namespace dxvk { const DxvkBufferSlice& buffer, uint32_t stride); + /** + * \brief Binds transform feedback buffer + * + * \param [in] binding Xfb buffer binding + * \param [in] buffer The buffer to bind + * \param [in] counter Xfb counter buffer + */ + void bindXfbBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + const DxvkBufferSlice& counter); + /** * \brief Clears a buffer with a fixed value * From a27e440272e32e923faf0b5aedee6ba128f10020 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 18:19:52 +0200 Subject: [PATCH 15/30] [dxvk] Detect Xfb and set rasterized stream index --- src/dxbc/dxbc_compiler.cpp | 6 +++++- src/dxvk/dxvk_graphics.cpp | 20 ++++++++++++++++++-- src/dxvk/dxvk_graphics.h | 19 +++++++++++++++++++ src/dxvk/dxvk_shader.h | 2 ++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 9c2fc70a..18586c31 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -232,9 +232,13 @@ namespace dxvk { DxvkShaderOptions shaderOptions = { }; - if (m_moduleInfo.xfb != nullptr) + if (m_moduleInfo.xfb != nullptr) { shaderOptions.rasterizedStream = m_moduleInfo.xfb->rasterizedStream; + for (uint32_t i = 0; i < 4; i++) + shaderOptions.xfbStrides[i] = m_moduleInfo.xfb->strides[i]; + } + // Create the shader module object return new DxvkShader( m_programInfo.shaderStage(), diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 14cf9a9d..86b476b5 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -69,6 +69,9 @@ namespace dxvk { m_vsIn = vs != nullptr ? vs->interfaceSlots().inputSlots : 0; m_fsOut = fs != nullptr ? fs->interfaceSlots().outputSlots : 0; + + if (gs != nullptr && gs->hasCapability(spv::CapabilityTransformFeedback)) + m_flags.set(DxvkGraphicsPipelineFlag::HasTransformFeedback); m_common.msSampleShadingEnable = fs != nullptr && fs->hasCapability(spv::CapabilitySampleRateShading); m_common.msSampleShadingFactor = 1.0f; @@ -226,7 +229,11 @@ namespace dxvk { viDivisorDesc[id].divisor = state.ilDivisors[i]; } } - + + int32_t rasterizedStream = m_gs != nullptr + ? m_gs->shader()->shaderOptions().rasterizedStream + : 0; + VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo; viDivisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; viDivisorInfo.pNext = nullptr; @@ -271,12 +278,18 @@ namespace dxvk { vpInfo.scissorCount = state.rsViewportCount; vpInfo.pScissors = nullptr; + VkPipelineRasterizationStateStreamCreateInfoEXT xfbStreamInfo; + xfbStreamInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT; + xfbStreamInfo.pNext = nullptr; + xfbStreamInfo.flags = 0; + xfbStreamInfo.rasterizationStream = uint32_t(rasterizedStream); + VkPipelineRasterizationStateCreateInfo rsInfo; rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rsInfo.pNext = nullptr; rsInfo.flags = 0; rsInfo.depthClampEnable = state.rsDepthClampEnable; - rsInfo.rasterizerDiscardEnable= VK_FALSE; + rsInfo.rasterizerDiscardEnable = rasterizedStream < 0; rsInfo.polygonMode = state.rsPolygonMode; rsInfo.cullMode = state.rsCullMode; rsInfo.frontFace = state.rsFrontFace; @@ -286,6 +299,9 @@ namespace dxvk { rsInfo.depthBiasSlopeFactor = 0.0f; rsInfo.lineWidth = 1.0f; + if (rasterizedStream > 0) + rsInfo.pNext = &xfbStreamInfo; + VkPipelineMultisampleStateCreateInfo msInfo; msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; msInfo.pNext = nullptr; diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 3d5277f2..c02d5722 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -15,6 +15,16 @@ namespace dxvk { class DxvkDevice; class DxvkPipelineManager; + + /** + * \brief Flags that describe pipeline properties + */ + enum class DxvkGraphicsPipelineFlag { + HasTransformFeedback, + }; + + using DxvkGraphicsCommonPipelineFlags = Flags; + /** * \brief Graphics pipeline state info @@ -156,6 +166,14 @@ namespace dxvk { const Rc& fs); ~DxvkGraphicsPipeline(); + /** + * \brief Returns graphics pipeline flags + * \returns Graphics pipeline property flags + */ + DxvkGraphicsCommonPipelineFlags flags() const { + return m_flags; + } + /** * \brief Pipeline layout * @@ -213,6 +231,7 @@ namespace dxvk { uint32_t m_vsIn = 0; uint32_t m_fsOut = 0; + DxvkGraphicsCommonPipelineFlags m_flags; DxvkGraphicsCommonPipelineStateInfo m_common; // List of pipeline instances, shared between threads diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index a86ccd8c..7f6620a8 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -59,6 +59,8 @@ namespace dxvk { struct DxvkShaderOptions { /// Rasterized stream, or -1 int32_t rasterizedStream; + /// Xfb vertex strides + uint32_t xfbStrides[MaxNumXfbBuffers]; }; From 93b1b9bc0099e7e8c33834577cdb7fdfe3f34cf2 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 18:20:45 +0200 Subject: [PATCH 16/30] [dxvk] Implement transform feedback Begins transform feedback when rendering with an xfb-enabled pipeline bound, and ends transform feedback as needed, while writing back the counters supplied by the app. This does not yet support transform feedback queries or the draw command. --- src/dxvk/dxvk_buffer.h | 8 ++- src/dxvk/dxvk_buffer_res.h | 4 +- src/dxvk/dxvk_context.cpp | 105 ++++++++++++++++++++++++++++++++++- src/dxvk/dxvk_context.h | 6 ++ src/dxvk/dxvk_renderpass.cpp | 5 +- 5 files changed, 123 insertions(+), 5 deletions(-) diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index ee8e1dd7..e0a3ff77 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -273,7 +273,9 @@ namespace dxvk { * \returns The physical buffer slice */ DxvkPhysicalBufferSlice physicalSlice() const { - return m_buffer->subSlice(m_offset, m_length); + return m_buffer != nullptr + ? m_buffer->subSlice(m_offset, m_length) + : DxvkPhysicalBufferSlice(); } /** @@ -301,7 +303,9 @@ namespace dxvk { * \returns Pointer into mapped buffer memory */ void* mapPtr(VkDeviceSize offset) const { - return m_buffer->mapPtr(m_offset + offset); + return m_buffer != nullptr + ? m_buffer->mapPtr(m_offset + offset) + : nullptr; } /** diff --git a/src/dxvk/dxvk_buffer_res.h b/src/dxvk/dxvk_buffer_res.h index ca69ef6f..d69eccd9 100644 --- a/src/dxvk/dxvk_buffer_res.h +++ b/src/dxvk/dxvk_buffer_res.h @@ -134,7 +134,9 @@ namespace dxvk { * \returns Buffer handle */ VkBuffer handle() const { - return m_buffer->handle(); + return m_buffer != nullptr + ? m_buffer->handle() + : VK_NULL_HANDLE; } /** diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index f550b7fb..425efed6 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -36,6 +36,7 @@ namespace dxvk { // before any draw or dispatch command is recorded. m_flags.clr( DxvkContextFlag::GpRenderPassBound, + DxvkContextFlag::GpXfbActive, DxvkContextFlag::GpClearRenderTargets); m_flags.set( @@ -44,6 +45,7 @@ namespace dxvk { DxvkContextFlag::GpDirtyResources, DxvkContextFlag::GpDirtyVertexBuffers, DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyXfbBuffers, DxvkContextFlag::CpDirtyPipeline, DxvkContextFlag::CpDirtyPipelineState, DxvkContextFlag::CpDirtyResources, @@ -222,6 +224,8 @@ namespace dxvk { uint32_t binding, const DxvkBufferSlice& buffer, const DxvkBufferSlice& counter) { + this->spillRenderPass(); + m_state.xfb.buffers [binding] = buffer; m_state.xfb.counters[binding] = counter; @@ -1151,6 +1155,9 @@ namespace dxvk { if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); + if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT) + m_flags.set(DxvkContextFlag::GpDirtyXfbBuffers); + if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) { m_flags.set(DxvkContextFlag::GpDirtyResources, @@ -2163,6 +2170,8 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { m_flags.clr(DxvkContextFlag::GpRenderPassBound); + this->pauseTransformFeedback(); + m_queries.endQueries(m_cmd, VK_QUERY_TYPE_OCCLUSION); m_queries.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS); @@ -2243,6 +2252,52 @@ namespace dxvk { } + void DxvkContext::startTransformFeedback() { + if (!m_flags.test(DxvkContextFlag::GpXfbActive)) { + m_flags.set(DxvkContextFlag::GpXfbActive); + + VkBuffer ctrBuffers[MaxNumXfbBuffers]; + VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; + + for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.counters[i].physicalSlice(); + + ctrBuffers[i] = physSlice.handle(); + ctrOffsets[i] = physSlice.offset(); + + if (physSlice.handle() != VK_NULL_HANDLE) + m_cmd->trackResource(physSlice.resource()); + } + + m_cmd->cmdBeginTransformFeedback( + 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + } + } + + + void DxvkContext::pauseTransformFeedback() { + if (m_flags.test(DxvkContextFlag::GpXfbActive)) { + m_flags.clr(DxvkContextFlag::GpXfbActive); + + VkBuffer ctrBuffers[MaxNumXfbBuffers]; + VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; + + for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.counters[i].physicalSlice(); + + ctrBuffers[i] = physSlice.handle(); + ctrOffsets[i] = physSlice.offset(); + + if (physSlice.handle() != VK_NULL_HANDLE) + m_cmd->trackResource(physSlice.resource()); + } + + m_cmd->cmdEndTransformFeedback( + 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + } + } + + void DxvkContext::unbindComputePipeline() { m_flags.set( DxvkContextFlag::CpDirtyPipeline, @@ -2289,7 +2344,8 @@ namespace dxvk { DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyResources, DxvkContextFlag::GpDirtyVertexBuffers, - DxvkContextFlag::GpDirtyIndexBuffer); + DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyXfbBuffers); m_gpActivePipeline = VK_NULL_HANDLE; } @@ -2315,6 +2371,8 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) { m_flags.clr(DxvkContextFlag::GpDirtyPipelineState); + this->pauseTransformFeedback(); + for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { const uint32_t binding = m_state.gp.state.ilBindings[i].binding; @@ -2677,6 +2735,50 @@ namespace dxvk { } } } + + + void DxvkContext::updateTransformFeedbackBuffers() { + VkBuffer xfbBuffers[MaxNumXfbBuffers]; + VkDeviceSize xfbOffsets[MaxNumXfbBuffers]; + VkDeviceSize xfbLengths[MaxNumXfbBuffers]; + + for (size_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.buffers[i].physicalSlice(); + + xfbBuffers[i] = physSlice.handle(); + xfbOffsets[i] = physSlice.offset(); + xfbLengths[i] = physSlice.length(); + + if (physSlice.handle() == VK_NULL_HANDLE) + xfbBuffers[i] = m_device->dummyBufferHandle(); + + if (physSlice.handle() != VK_NULL_HANDLE) + m_cmd->trackResource(physSlice.resource()); + } + + m_cmd->cmdBindTransformFeedbackBuffers( + 0, MaxNumXfbBuffers, + xfbBuffers, xfbOffsets, xfbLengths); + } + + + void DxvkContext::updateTransformFeedbackState() { + bool hasTransformFeedback = + m_state.gp.pipeline != nullptr + && m_state.gp.pipeline->flags().test(DxvkGraphicsPipelineFlag::HasTransformFeedback); + + if (!hasTransformFeedback) + return; + + if (m_flags.test(DxvkContextFlag::GpDirtyXfbBuffers)) { + m_flags.clr(DxvkContextFlag::GpDirtyXfbBuffers); + + this->pauseTransformFeedback(); + this->updateTransformFeedbackBuffers(); + } + + this->startTransformFeedback(); + } void DxvkContext::updateDynamicState() { @@ -2743,6 +2845,7 @@ namespace dxvk { this->updateVertexBufferBindings(); this->updateGraphicsShaderResources(); this->updateGraphicsPipelineState(); + this->updateTransformFeedbackState(); this->updateGraphicsShaderDescriptors(); this->updateDynamicState(); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index b186bf6a..388f12c7 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -788,6 +788,9 @@ namespace dxvk { const DxvkRenderTargets& renderTargets, DxvkRenderPassOps& renderPassOps); + void startTransformFeedback(); + void pauseTransformFeedback(); + void unbindComputePipeline(); void updateComputePipeline(); void updateComputePipelineState(); @@ -820,6 +823,9 @@ namespace dxvk { void updateIndexBufferBinding(); void updateVertexBufferBindings(); + + void updateTransformFeedbackBuffers(); + void updateTransformFeedbackState(); void updateDynamicState(); diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 9bb6517c..58422dd7 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -135,6 +135,8 @@ namespace dxvk { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT | + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | @@ -144,7 +146,8 @@ namespace dxvk { VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, 0 }, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }, }}; VkRenderPassCreateInfo info; From 76d917df20f023cb4949355c5be134dcd940d3b0 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 13 Sep 2018 10:43:30 +0200 Subject: [PATCH 17/30] [dxvk] Add xfb counter write -> xfb counter read barrier - Update xfb counter barrier --- src/dxvk/dxvk_context.cpp | 30 ++++++++++++++++++++++++++++++ src/dxvk/dxvk_context.h | 6 ++++++ src/dxvk/dxvk_context_state.h | 1 + src/dxvk/dxvk_renderpass.cpp | 7 ++++++- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 425efed6..f7766932 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2176,6 +2176,8 @@ namespace dxvk { m_queries.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS); this->renderPassUnbindFramebuffer(); + + m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters); } } @@ -2256,6 +2258,16 @@ namespace dxvk { if (!m_flags.test(DxvkContextFlag::GpXfbActive)) { m_flags.set(DxvkContextFlag::GpXfbActive); + if (m_flags.test(DxvkContextFlag::GpDirtyXfbCounters)) { + m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters); + + this->emitMemoryBarrier( + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */ + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT); + } + VkBuffer ctrBuffers[MaxNumXfbBuffers]; VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; @@ -2294,6 +2306,8 @@ namespace dxvk { m_cmd->cmdEndTransformFeedback( 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + + m_flags.set(DxvkContextFlag::GpDirtyXfbCounters); } } @@ -2967,6 +2981,22 @@ namespace dxvk { } + void DxvkContext::emitMemoryBarrier( + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + VkMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess; + barrier.dstAccessMask = dstAccess; + + m_cmd->cmdPipelineBarrier(srcStages, dstStages, + 0, 1, &barrier, 0, nullptr, 0, nullptr); + } + + void DxvkContext::trackDrawBuffer() { if (m_flags.test(DxvkContextFlag::DirtyDrawBuffer)) { m_flags.clr(DxvkContextFlag::DirtyDrawBuffer); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 388f12c7..27b41294 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -838,6 +838,12 @@ namespace dxvk { void commitComputeInitBarriers(); void commitComputePostBarriers(); + void emitMemoryBarrier( + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + void trackDrawBuffer(); }; diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 33136a3b..56107023 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -33,6 +33,7 @@ namespace dxvk { GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date GpDirtyIndexBuffer, ///< Index buffer binding are out of date GpDirtyXfbBuffers, ///< Transform feedback buffer bindings are out of date + GpDirtyXfbCounters, ///< Counter buffer values are dirty GpDirtyBlendConstants, ///< Blend constants have changed GpDirtyStencilRef, ///< Stencil reference has changed GpDirtyViewport, ///< Viewport state has changed diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 58422dd7..fff1d9cb 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -121,7 +121,7 @@ namespace dxvk { if (m_format.depth.format == VK_FORMAT_UNDEFINED) subpass.pDepthStencilAttachment = nullptr; - const std::array subpassDeps = {{ + const std::array subpassDeps = {{ { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, @@ -130,6 +130,11 @@ namespace dxvk { VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 0 }, + { 0, 0, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */ + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }, { 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, From 3435702719d5c1be321562dc478f587f173c3b6e Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 6 Sep 2018 12:50:44 +0200 Subject: [PATCH 18/30] [dxvk] Add basic support for indexed queries --- src/dxvk/dxvk_query.cpp | 12 +++++- src/dxvk/dxvk_query.h | 25 ++++++++++- src/dxvk/dxvk_query_manager.cpp | 76 ++++++++++++++++++++------------- src/dxvk/dxvk_query_manager.h | 8 ++++ src/dxvk/dxvk_query_pool.cpp | 1 + 5 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/dxvk/dxvk_query.cpp b/src/dxvk/dxvk_query.cpp index 0b054913..c8da6576 100644 --- a/src/dxvk/dxvk_query.cpp +++ b/src/dxvk/dxvk_query.cpp @@ -4,8 +4,11 @@ namespace dxvk { DxvkQuery::DxvkQuery( VkQueryType type, - VkQueryControlFlags flags) - : m_type(type), m_flags(flags) { + VkQueryControlFlags flags, + uint32_t index) + : m_type (type), + m_flags (flags), + m_index (index) { } @@ -15,6 +18,11 @@ namespace dxvk { } + bool DxvkQuery::isIndexed() const { + return false; + } + + uint32_t DxvkQuery::reset() { std::unique_lock lock(m_mutex); diff --git a/src/dxvk/dxvk_query.h b/src/dxvk/dxvk_query.h index 4f735b7f..a62c0952 100644 --- a/src/dxvk/dxvk_query.h +++ b/src/dxvk/dxvk_query.h @@ -81,6 +81,7 @@ namespace dxvk { VkQueryPool queryPool = VK_NULL_HANDLE; uint32_t queryId = 0; VkQueryControlFlags flags = 0; + uint32_t index = 0; }; /** @@ -91,12 +92,13 @@ namespace dxvk { * submissions, we need to */ class DxvkQuery : public RcObject { - + public: DxvkQuery( VkQueryType type, - VkQueryControlFlags flags); + VkQueryControlFlags flags, + uint32_t index = ~0u); ~DxvkQuery(); /** @@ -117,6 +119,24 @@ namespace dxvk { VkQueryControlFlags flags() const { return m_flags; } + + /** + * \brief Query type index + * + * The query type index. Will be undefined if the + * query type is not indexed. Not to be confused + * with the query index within the query pool. + * \returns Query type index + */ + uint32_t index() const { + return m_index; + } + + /** + * \brief Checks whether the query type is indexed + * \returns \c true if the query type is indexed + */ + bool isIndexed() const; /** * \brief Resets the query object @@ -188,6 +208,7 @@ namespace dxvk { const VkQueryType m_type; const VkQueryControlFlags m_flags; + const uint32_t m_index; std::mutex m_mutex; diff --git a/src/dxvk/dxvk_query_manager.cpp b/src/dxvk/dxvk_query_manager.cpp index a1a28d1c..3aa4fb67 100644 --- a/src/dxvk/dxvk_query_manager.cpp +++ b/src/dxvk/dxvk_query_manager.cpp @@ -44,14 +44,8 @@ namespace dxvk { const DxvkQueryRevision& query) { m_activeQueries.push_back(query); - if (m_activeTypes & getDxvkQueryTypeBit(query.query->type())) { - DxvkQueryHandle handle = this->allocQuery(cmd, query); - - cmd->cmdBeginQuery( - handle.queryPool, - handle.queryId, - handle.flags); - } + if (m_activeTypes & getDxvkQueryTypeBit(query.query->type())) + this->beginVulkanQuery(cmd, query); } @@ -69,13 +63,8 @@ namespace dxvk { } if (iter != m_activeQueries.end()) { - if (m_activeTypes & getDxvkQueryTypeBit(iter->query->type())) { - DxvkQueryHandle handle = iter->query->getHandle(); - - cmd->cmdEndQuery( - handle.queryPool, - handle.queryId); - } + if (m_activeTypes & getDxvkQueryTypeBit(iter->query->type())) + this->endVulkanQuery(cmd, query); m_activeQueries.erase(iter); } @@ -88,14 +77,8 @@ namespace dxvk { m_activeTypes |= getDxvkQueryTypeBit(type); for (const DxvkQueryRevision& query : m_activeQueries) { - if (type == query.query->type()) { - DxvkQueryHandle handle = this->allocQuery(cmd, query); - - cmd->cmdBeginQuery( - handle.queryPool, - handle.queryId, - handle.flags); - } + if (type == query.query->type()) + this->beginVulkanQuery(cmd, query); } } @@ -106,13 +89,8 @@ namespace dxvk { m_activeTypes &= ~getDxvkQueryTypeBit(type); for (const DxvkQueryRevision& query : m_activeQueries) { - if (type == query.query->type()) { - DxvkQueryHandle handle = query.query->getHandle(); - - cmd->cmdEndQuery( - handle.queryPool, - handle.queryId); - } + if (type == query.query->type()) + this->endVulkanQuery(cmd, query); } } @@ -136,6 +114,44 @@ namespace dxvk { } + void DxvkQueryManager::beginVulkanQuery( + const Rc& cmd, + const DxvkQueryRevision& query) { + DxvkQueryHandle handle = this->allocQuery(cmd, query); + + if (query.query->isIndexed()) { + cmd->cmdBeginQueryIndexed( + handle.queryPool, + handle.queryId, + handle.flags, + handle.index); + } else { + cmd->cmdBeginQuery( + handle.queryPool, + handle.queryId, + handle.flags); + } + } + + + void DxvkQueryManager::endVulkanQuery( + const Rc& cmd, + const DxvkQueryRevision& query) { + DxvkQueryHandle handle = query.query->getHandle(); + + if (query.query->isIndexed()) { + cmd->cmdEndQueryIndexed( + handle.queryPool, + handle.queryId, + handle.index); + } else { + cmd->cmdEndQuery( + handle.queryPool, + handle.queryId); + } + } + + Rc& DxvkQueryManager::getQueryPool(VkQueryType type) { switch (type) { case VK_QUERY_TYPE_OCCLUSION: diff --git a/src/dxvk/dxvk_query_manager.h b/src/dxvk/dxvk_query_manager.h index 5d8216f1..3674d29a 100644 --- a/src/dxvk/dxvk_query_manager.h +++ b/src/dxvk/dxvk_query_manager.h @@ -108,6 +108,14 @@ namespace dxvk { const Rc& cmd, const Rc& pool); + void beginVulkanQuery( + const Rc& cmd, + const DxvkQueryRevision& query); + + void endVulkanQuery( + const Rc& cmd, + const DxvkQueryRevision& query); + Rc& getQueryPool( VkQueryType type); diff --git a/src/dxvk/dxvk_query_pool.cpp b/src/dxvk/dxvk_query_pool.cpp index b0a5972c..0fb17cb0 100644 --- a/src/dxvk/dxvk_query_pool.cpp +++ b/src/dxvk/dxvk_query_pool.cpp @@ -54,6 +54,7 @@ namespace dxvk { result.queryPool = m_queryPool; result.queryId = queryIndex; result.flags = query.query->flags(); + result.index = query.query->index(); query.query->associateQuery(query.revision, result); m_queries.at(queryIndex) = query; From 4bdf6daa391b15b09f3120ea13bff10a4dae5490 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 31 Aug 2018 15:51:40 +0200 Subject: [PATCH 19/30] [dxvk] Add structure for transform feedback stream queries --- src/dxvk/dxvk_query.cpp | 7 ++++++- src/dxvk/dxvk_query.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_query.cpp b/src/dxvk/dxvk_query.cpp index c8da6576..39c0c5cd 100644 --- a/src/dxvk/dxvk_query.cpp +++ b/src/dxvk/dxvk_query.cpp @@ -19,7 +19,7 @@ namespace dxvk { bool DxvkQuery::isIndexed() const { - return false; + return m_type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT; } @@ -112,6 +112,11 @@ namespace dxvk { m_data.statistic.csInvocations += data.statistic.csInvocations; break; + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + m_data.xfbStream.primitivesWritten += data.xfbStream.primitivesWritten; + m_data.xfbStream.primitivesNeeded += data.xfbStream.primitivesNeeded; + break; + default: Logger::err(str::format("DxvkQuery: Unhandled query type: ", m_type)); } diff --git a/src/dxvk/dxvk_query.h b/src/dxvk/dxvk_query.h index a62c0952..e1da5912 100644 --- a/src/dxvk/dxvk_query.h +++ b/src/dxvk/dxvk_query.h @@ -58,6 +58,19 @@ namespace dxvk { uint64_t tesInvocations; uint64_t csInvocations; }; + + /** + * \brief Transform feedback stream query + * + * Stores the number of primitives written to the + * buffer, as well as the number of primitives + * generated. The latter can be used to check for + * overflow. + */ + struct DxvkQueryXfbStreamData { + uint64_t primitivesWritten; + uint64_t primitivesNeeded; + }; /** * \brief Query data @@ -69,6 +82,7 @@ namespace dxvk { DxvkQueryOcclusionData occlusion; DxvkQueryTimestampData timestamp; DxvkQueryStatisticData statistic; + DxvkQueryXfbStreamData xfbStream; }; /** From 929b75a038e7bdb1930a7267debc61eddac02ec9 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 31 Aug 2018 15:56:38 +0200 Subject: [PATCH 20/30] [dxvk] Add support for transform feedback queries --- src/dxvk/dxvk_context.cpp | 6 ++++++ src/dxvk/dxvk_query_manager.cpp | 13 +++++++++---- src/dxvk/dxvk_query_manager.h | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index f7766932..79e95440 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2283,6 +2283,9 @@ namespace dxvk { m_cmd->cmdBeginTransformFeedback( 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + + m_queries.beginQueries(m_cmd, + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT); } } @@ -2304,6 +2307,9 @@ namespace dxvk { m_cmd->trackResource(physSlice.resource()); } + m_queries.endQueries(m_cmd, + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT); + m_cmd->cmdEndTransformFeedback( 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); diff --git a/src/dxvk/dxvk_query_manager.cpp b/src/dxvk/dxvk_query_manager.cpp index 3aa4fb67..e459ef56 100644 --- a/src/dxvk/dxvk_query_manager.cpp +++ b/src/dxvk/dxvk_query_manager.cpp @@ -99,6 +99,7 @@ namespace dxvk { this->trackQueryPool(cmd, m_occlusion); this->trackQueryPool(cmd, m_pipeStats); this->trackQueryPool(cmd, m_timestamp); + this->trackQueryPool(cmd, m_xfbStream); } @@ -162,6 +163,9 @@ namespace dxvk { case VK_QUERY_TYPE_TIMESTAMP: return m_timestamp; + + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + return m_xfbStream; default: throw DxvkError("DXVK: Invalid query type"); @@ -171,10 +175,11 @@ namespace dxvk { uint32_t DxvkQueryManager::getDxvkQueryTypeBit(VkQueryType type) { switch (type) { - case VK_QUERY_TYPE_OCCLUSION: return 0x01; - case VK_QUERY_TYPE_PIPELINE_STATISTICS: return 0x02; - case VK_QUERY_TYPE_TIMESTAMP: return 0x04; - default: return 0; + case VK_QUERY_TYPE_OCCLUSION: return 0x01; + case VK_QUERY_TYPE_PIPELINE_STATISTICS: return 0x02; + case VK_QUERY_TYPE_TIMESTAMP: return 0x04; + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: return 0x08; + default: return 0; } } diff --git a/src/dxvk/dxvk_query_manager.h b/src/dxvk/dxvk_query_manager.h index 3674d29a..fd38ffaa 100644 --- a/src/dxvk/dxvk_query_manager.h +++ b/src/dxvk/dxvk_query_manager.h @@ -101,6 +101,7 @@ namespace dxvk { Rc m_occlusion; Rc m_pipeStats; Rc m_timestamp; + Rc m_xfbStream; std::vector m_activeQueries; From 3a4809263089384c98a835bf7969cce6d72b22e0 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 4 Sep 2018 02:17:05 +0200 Subject: [PATCH 21/30] [dxvk] Implement transform feedback draw call --- src/dxvk/dxvk_buffer.h | 25 ++++++++++++++++++++++++- src/dxvk/dxvk_context.cpp | 27 ++++++++++++++++++++++++++- src/dxvk/dxvk_context.h | 12 ++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index e0a3ff77..77887178 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -146,6 +146,28 @@ namespace dxvk { return prevSlice; } + /** + * \brief Transform feedback vertex stride + * + * Used when drawing after transform feedback, + * \returns The current xfb vertex stride + */ + uint32_t getXfbVertexStride() const { + return m_vertexStride; + } + + /** + * \brief Set transform feedback vertex stride + * + * When the buffer is used as a transform feedback + * buffer, this will be set to the vertex stride + * defined by the geometry shader. + * \param [in] stride Vertex stride + */ + void setXfbVertexStride(uint32_t stride) { + m_vertexStride = stride; + } + /** * \brief Allocates new physical resource * \returns The new backing buffer slice @@ -170,7 +192,8 @@ namespace dxvk { VkMemoryPropertyFlags m_memFlags; DxvkPhysicalBufferSlice m_physSlice; - uint32_t m_revision = 0; + uint32_t m_revision = 0; + uint32_t m_vertexStride = 0; sync::Spinlock m_freeMutex; sync::Spinlock m_swapMutex; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 79e95440..1e6bfc47 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1020,6 +1020,25 @@ namespace dxvk { } + void DxvkContext::drawIndirectXfb( + const DxvkBufferSlice& counterBuffer, + uint32_t counterDivisor, + uint32_t counterBias) { + this->commitGraphicsState(); + + if (this->validateGraphicsState()) { + auto physicalSlice = counterBuffer.physicalSlice(); + + m_cmd->cmdDrawIndirectVertexCount(1, 0, + physicalSlice.handle(), + physicalSlice.offset(), + counterBias, counterDivisor); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + void DxvkContext::initImage( const Rc& image, const VkImageSubresourceRange& subresources) { @@ -2758,6 +2777,8 @@ namespace dxvk { void DxvkContext::updateTransformFeedbackBuffers() { + auto gsOptions = m_state.gp.gs.shader->shaderOptions(); + VkBuffer xfbBuffers[MaxNumXfbBuffers]; VkDeviceSize xfbOffsets[MaxNumXfbBuffers]; VkDeviceSize xfbLengths[MaxNumXfbBuffers]; @@ -2772,8 +2793,12 @@ namespace dxvk { if (physSlice.handle() == VK_NULL_HANDLE) xfbBuffers[i] = m_device->dummyBufferHandle(); - if (physSlice.handle() != VK_NULL_HANDLE) + if (physSlice.handle() != VK_NULL_HANDLE) { + auto buffer = m_state.xfb.buffers[i].buffer(); + buffer->setXfbVertexStride(gsOptions.xfbStrides[i]); + m_cmd->trackResource(physSlice.resource()); + } } m_cmd->cmdBindTransformFeedbackBuffers( diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 27b41294..374eec3c 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -486,6 +486,18 @@ namespace dxvk { uint32_t count, uint32_t stride); + /** + * \brief Transform feddback draw call + + * \param [in] counterBuffer Xfb counter buffer + * \param [in] counterDivisor Vertex stride + * \param [in] counterBias Counter bias + */ + void drawIndirectXfb( + const DxvkBufferSlice& counterBuffer, + uint32_t counterDivisor, + uint32_t counterBias); + /** * \brief Generates mip maps * From f42ea9f1d1583dffe8f236828a12a33830459574 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 15:16:59 +0200 Subject: [PATCH 22/30] [d3d11] Set transform feedback usage, stage and access flags --- src/d3d11/d3d11_buffer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index c90c6411..c34b57fa 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -130,7 +130,9 @@ namespace dxvk { } if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) { - Logger::err("D3D11Device::CreateBuffer: D3D11_BIND_STREAM_OUTPUT not supported"); + info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + info.stages |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + info.access |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT; } if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) { From 5463dc7e6cb63fcb170587c97a447f27dcff7f5d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 16:20:38 +0200 Subject: [PATCH 23/30] [d3d11] Implement CreateGeometryShaderWithStreamOutput - Emit error instead of warning when enabling rasterization --- src/d3d11/d3d11_device.cpp | 72 +++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index c7c2380f..74566a95 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -674,11 +674,75 @@ namespace dxvk { ID3D11ClassLinkage* pClassLinkage, ID3D11GeometryShader** ppGeometryShader) { InitReturnPtr(ppGeometryShader); - Logger::err("D3D11Device::CreateGeometryShaderWithStreamOutput: Not implemented"); + D3D11CommonShader module; + + if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback) { + Logger::err( + "D3D11: CreateGeometryShaderWithStreamOutput:" + "\n Transform feedback not supoorted by device"); + return m_d3d11Options.fakeStreamOutSupport ? S_OK : E_NOTIMPL; + } + + // Zero-init some counterss so that we can increment + // them while walking over the stream output entries + DxbcXfbInfo xfb; + xfb.entryCount = 0; + + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) + xfb.strides[i] = 0; - // Returning S_OK instead of an error fixes some issues - // with Overwatch until this is properly implemented - return m_d3d11Options.fakeStreamOutSupport ? S_OK : E_NOTIMPL; + for (uint32_t i = 0; i < NumEntries; i++) { + const D3D11_SO_DECLARATION_ENTRY* so = &pSODeclaration[i]; + + if (so->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT) + return E_INVALIDARG; + + if (so->SemanticName != nullptr) { + if (so->Stream >= D3D11_SO_BUFFER_SLOT_COUNT + || so->StartComponent >= 4 + || so->ComponentCount < 1 + || so->ComponentCount > 4) + return E_INVALIDARG; + + DxbcXfbEntry* entry = &xfb.entries[xfb.entryCount++]; + entry->semanticName = so->SemanticName; + entry->semanticIndex = so->SemanticIndex; + entry->componentIndex = so->StartComponent; + entry->componentCount = so->ComponentCount; + entry->streamId = so->Stream; + entry->bufferId = so->OutputSlot; + entry->offset = xfb.strides[so->OutputSlot]; + } + + xfb.strides[so->OutputSlot] += so->ComponentCount * sizeof(uint32_t); + } + + // If necessary, override the buffer strides + for (uint32_t i = 0; i < NumStrides; i++) + xfb.strides[i] = pBufferStrides[i]; + + // Set stream to rasterize, if any + xfb.rasterizedStream = -1; + + if (RasterizedStream != D3D11_SO_NO_RASTERIZED_STREAM) + Logger::err("D3D11: CreateGeometryShaderWithStreamOutput: Rasterized stream not supported"); + + // Create the actual shader module + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = &xfb; + + if (FAILED(this->CreateShaderModule(&module, + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo, DxbcProgramType::GeometryShader))) + return E_INVALIDARG; + + if (ppGeometryShader == nullptr) + return S_FALSE; + + *ppGeometryShader = ref(new D3D11GeometryShader(this, module)); + return S_OK; } From 7369dee9d680806c0c2984d940ed1772845603a1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 25 Jul 2018 22:46:10 +0200 Subject: [PATCH 24/30] [d3d11] Create passthrough geometry shader if necessary Fixes stream output in Unity Engine titles. - Fix compilation with new DxbcProgramInfo struct. --- src/d3d11/d3d11_shader.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/d3d11/d3d11_shader.cpp b/src/d3d11/d3d11_shader.cpp index 05a1ee11..ba2ef8f1 100644 --- a/src/d3d11/d3d11_shader.cpp +++ b/src/d3d11/d3d11_shader.cpp @@ -31,7 +31,14 @@ namespace dxvk { std::ios_base::binary | std::ios_base::trunc)); } - m_shader = module.compile(*pDxbcModuleInfo, name); + // Decide whether we need to create a pass-through + // geometry shader for vertex shader stream output + bool passthroughShader = pDxbcModuleInfo->xfb != nullptr + && module.programInfo().type() != DxbcProgramType::GeometryShader; + + m_shader = passthroughShader + ? module.compilePassthroughShader(*pDxbcModuleInfo, name) + : module.compile (*pDxbcModuleInfo, name); m_shader->setShaderKey(*pShaderKey); if (dumpPath.size() != 0) { From 0d89dfae95323c6bf309b75ed19321cd064658fa Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 25 Jul 2018 11:42:05 +0200 Subject: [PATCH 25/30] [d3d11] Report format support for stream output buffers --- src/d3d11/d3d11_device.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 74566a95..71f05886 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1550,8 +1550,22 @@ namespace dxvk { || Format == DXGI_FORMAT_R32_UINT) flags1 |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER; - // TODO implement stream output - // D3D11_FORMAT_SUPPORT_SO_BUFFER + // These formats are technically irrelevant since + // SO buffers are passed in as raw buffers and not + // as views, but the feature flag exists regardless + if (Format == DXGI_FORMAT_R32_FLOAT + || Format == DXGI_FORMAT_R32_UINT + || Format == DXGI_FORMAT_R32_SINT + || Format == DXGI_FORMAT_R32G32_FLOAT + || Format == DXGI_FORMAT_R32G32_UINT + || Format == DXGI_FORMAT_R32G32_SINT + || Format == DXGI_FORMAT_R32G32B32_FLOAT + || Format == DXGI_FORMAT_R32G32B32_UINT + || Format == DXGI_FORMAT_R32G32B32_SINT + || Format == DXGI_FORMAT_R32G32B32A32_FLOAT + || Format == DXGI_FORMAT_R32G32B32A32_UINT + || Format == DXGI_FORMAT_R32G32B32A32_SINT) + flags1 |= D3D11_FORMAT_SUPPORT_SO_BUFFER; if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT || fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) { From 97d776cc00cf910dfb08bd2d31e3d4bcb16f3ccb Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 30 Aug 2018 15:56:51 +0200 Subject: [PATCH 26/30] [d3d11] Allocate counter for stream output buffers --- src/d3d11/d3d11_buffer.cpp | 172 +++++++++++++++++------------------ src/d3d11/d3d11_buffer.h | 23 ++++- src/d3d11/d3d11_device.cpp | 22 +++++ src/d3d11/d3d11_device.h | 16 ++-- src/d3d11/d3d11_view_uav.cpp | 4 +- 5 files changed, 138 insertions(+), 99 deletions(-) diff --git a/src/d3d11/d3d11_buffer.cpp b/src/d3d11/d3d11_buffer.cpp index c34b57fa..a67df242 100644 --- a/src/d3d11/d3d11_buffer.cpp +++ b/src/d3d11/d3d11_buffer.cpp @@ -11,92 +11,7 @@ namespace dxvk { const D3D11_BUFFER_DESC* pDesc) : m_device (pDevice), m_desc (*pDesc), - m_buffer (CreateBuffer(pDesc)), - m_mappedSlice (m_buffer->slice()), m_d3d10 (this) { - - } - - - D3D11Buffer::~D3D11Buffer() { - - } - - - HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) { - *ppvObject = nullptr; - - if (riid == __uuidof(IUnknown) - || riid == __uuidof(ID3D11DeviceChild) - || riid == __uuidof(ID3D11Resource) - || riid == __uuidof(ID3D11Buffer)) { - *ppvObject = ref(this); - return S_OK; - } - - if (riid == __uuidof(ID3D10DeviceChild) - || riid == __uuidof(ID3D10Resource) - || riid == __uuidof(ID3D10Buffer)) { - *ppvObject = ref(&m_d3d10); - return S_OK; - } - - Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query"); - Logger::warn(str::format(riid)); - return E_NOINTERFACE; - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetDevice(ID3D11Device** ppDevice) { - *ppDevice = m_device.ref(); - } - - - UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() { - Logger::warn("D3D11Buffer::GetEvictionPriority: Stub"); - return DXGI_RESOURCE_PRIORITY_NORMAL; - } - - - void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) { - Logger::warn("D3D11Buffer::SetEvictionPriority: Stub"); - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) { - *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER; - } - - - void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) { - *pDesc = m_desc; - } - - - bool D3D11Buffer::CheckViewCompatibility( - UINT BindFlags, - DXGI_FORMAT Format) const { - // Check whether the given bind flags are supported - VkBufferUsageFlags usage = GetBufferUsageFlags(BindFlags); - - if ((m_buffer->info().usage & usage) != usage) - return false; - - // Structured buffer views use no format - if (Format == DXGI_FORMAT_UNKNOWN) - return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0; - - // Check whether the given combination of buffer view - // type and view format is supported by the device - DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); - VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags); - - return CheckFormatFeatureSupport(viewFormat.Format, features); - } - - - Rc D3D11Buffer::CreateBuffer( - const D3D11_BUFFER_DESC* pDesc) const { DxvkBufferCreateInfo info; info.size = pDesc->ByteWidth; info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT @@ -175,7 +90,92 @@ namespace dxvk { if (pDesc->Usage == D3D11_USAGE_DYNAMIC && pDesc->BindFlags) memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - return m_device->GetDXVKDevice()->createBuffer(info, memoryFlags); + // Create the buffer and set the entire buffer slice as mapped, + // so that we only have to update it when invalidating th buffer + m_buffer = m_device->GetDXVKDevice()->createBuffer(info, memoryFlags); + m_mapped = m_buffer->slice(); + + // For Stream Output buffers we need a counter + if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) + m_soCounter = m_device->AllocXfbCounterSlice(); + } + + + D3D11Buffer::~D3D11Buffer() { + if (m_soCounter.defined()) + m_device->FreeXfbCounterSlice(m_soCounter); + } + + + HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) { + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Buffer)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Buffer)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetDevice(ID3D11Device** ppDevice) { + *ppDevice = m_device.ref(); + } + + + UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() { + Logger::warn("D3D11Buffer::GetEvictionPriority: Stub"); + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) { + Logger::warn("D3D11Buffer::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER; + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) { + *pDesc = m_desc; + } + + + bool D3D11Buffer::CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format) const { + // Check whether the given bind flags are supported + VkBufferUsageFlags usage = GetBufferUsageFlags(BindFlags); + + if ((m_buffer->info().usage & usage) != usage) + return false; + + // Structured buffer views use no format + if (Format == DXGI_FORMAT_UNKNOWN) + return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0; + + // Check whether the given combination of buffer view + // type and view format is supported by the device + DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); + VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags); + + return CheckFormatFeatureSupport(viewFormat.Format, features); } diff --git a/src/d3d11/d3d11_buffer.h b/src/d3d11/d3d11_buffer.h index 2d567dd3..bdb23137 100644 --- a/src/d3d11/d3d11_buffer.h +++ b/src/d3d11/d3d11_buffer.h @@ -11,6 +11,18 @@ namespace dxvk { class D3D11Device; class D3D11DeviceContext; + + + /** + * \brief Stream output buffer offset + * + * A byte offset into the buffer that + * stores the byte offset where new + * data will be written to. + */ + struct D3D11SOCounter { + uint32_t byteOffset; + }; class D3D11Buffer : public D3D11DeviceChild { @@ -62,17 +74,21 @@ namespace dxvk { DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const { return DxvkBufferSlice(m_buffer, offset, length); } + + DxvkBufferSlice GetSOCounter() { + return m_soCounter; + } VkDeviceSize GetSize() const { return m_buffer->info().size; } DxvkPhysicalBufferSlice GetMappedSlice() const { - return m_mappedSlice; + return m_mapped; } void SetMappedSlice(const DxvkPhysicalBufferSlice& slice) { - m_mappedSlice = slice; + m_mapped = slice; } D3D10Buffer* GetD3D10Iface() { @@ -85,7 +101,8 @@ namespace dxvk { const D3D11_BUFFER_DESC m_desc; Rc m_buffer; - DxvkPhysicalBufferSlice m_mappedSlice; + DxvkBufferSlice m_soCounter; + DxvkPhysicalBufferSlice m_mapped; D3D10Buffer m_d3d10; diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 71f05886..aa5065da 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -117,6 +117,7 @@ namespace dxvk { m_d3d10Device = new D3D10Device(this, m_context); m_uavCounters = CreateUAVCounterBuffer(); + m_xfbCounters = CreateXFBCounterBuffer(); } @@ -1496,6 +1497,27 @@ namespace dxvk { return new D3D11CounterBuffer(m_dxvkDevice, uavCounterInfo, uavCounterSliceLength); } + + + Rc D3D11Device::CreateXFBCounterBuffer() { + DxvkBufferCreateInfo xfbCounterInfo; + xfbCounterInfo.size = 4096 * sizeof(D3D11SOCounter); + xfbCounterInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; + xfbCounterInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT + | VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + xfbCounterInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; + + return new D3D11CounterBuffer(m_dxvkDevice, + xfbCounterInfo, sizeof(D3D11SOCounter)); + } HRESULT D3D11Device::CreateShaderModule( diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 9b257325..eb1d28f3 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -333,14 +333,6 @@ namespace dxvk { DXGI_FORMAT Format, DXGI_VK_FORMAT_MODE Mode) const; - DxvkBufferSlice AllocCounterSlice() { - return m_uavCounters->AllocSlice(); - } - - void FreeCounterSlice(const DxvkBufferSlice& Slice) { - m_uavCounters->FreeSlice(Slice); - } - DxvkCsChunkRef AllocCsChunk() { DxvkCsChunk* chunk = m_csChunkPool.allocChunk(); return DxvkCsChunkRef(chunk, &m_csChunkPool); @@ -354,6 +346,12 @@ namespace dxvk { return m_d3d10Device; } + DxvkBufferSlice AllocUavCounterSlice() { return m_uavCounters->AllocSlice(); } + DxvkBufferSlice AllocXfbCounterSlice() { return m_xfbCounters->AllocSlice(); } + + void FreeUavCounterSlice(const DxvkBufferSlice& Slice) { m_uavCounters->FreeSlice(Slice); } + void FreeXfbCounterSlice(const DxvkBufferSlice& Slice) { m_xfbCounters->FreeSlice(Slice); } + static bool CheckFeatureLevelSupport( const Rc& adapter, D3D_FEATURE_LEVEL featureLevel); @@ -383,6 +381,7 @@ namespace dxvk { D3D10Device* m_d3d10Device = nullptr; Rc m_uavCounters; + Rc m_xfbCounters; D3D11StateObjectSet m_bsStateObjects; D3D11StateObjectSet m_dsStateObjects; @@ -391,6 +390,7 @@ namespace dxvk { D3D11ShaderModuleSet m_shaderModules; Rc CreateUAVCounterBuffer(); + Rc CreateXFBCounterBuffer(); HRESULT CreateShaderModule( D3D11CommonShader* pShaderModule, diff --git a/src/d3d11/d3d11_view_uav.cpp b/src/d3d11/d3d11_view_uav.cpp index 1078fce1..2f5d1355 100644 --- a/src/d3d11/d3d11_view_uav.cpp +++ b/src/d3d11/d3d11_view_uav.cpp @@ -38,7 +38,7 @@ namespace dxvk { } if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)) - m_counterSlice = pDevice->AllocCounterSlice(); + m_counterSlice = pDevice->AllocUavCounterSlice(); m_bufferView = pDevice->GetDXVKDevice()->createBufferView( buffer->GetBuffer(), viewInfo); @@ -109,7 +109,7 @@ namespace dxvk { ResourceReleasePrivate(m_resource); if (m_counterSlice.defined()) - m_device->FreeCounterSlice(m_counterSlice); + m_device->FreeUavCounterSlice(m_counterSlice); } From 93753a5ce7eb3c53cce0bee97614dee9ac22a0d1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 24 Jul 2018 17:09:11 +0200 Subject: [PATCH 27/30] [d3d11] Bind transform feedback buffers in SOSetTargets --- src/d3d11/d3d11_context.cpp | 70 +++++++++++++++++++++++++++------ src/d3d11/d3d11_context.h | 5 +++ src/d3d11/d3d11_context_state.h | 10 ++++- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index c2f95db0..7fa01bbc 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -208,8 +208,10 @@ namespace dxvk { } // Default SO state - for (uint32_t i = 0; i < D3D11_SO_STREAM_COUNT; i++) - m_state.so.targets[i] = nullptr; + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + m_state.so.targets[i].buffer = nullptr; + m_state.so.targets[i].offset = 0; + } // Default predication m_state.pr.predicateObject = nullptr; @@ -2509,17 +2511,29 @@ namespace dxvk { *pNumRects = m_state.rs.numScissors; } - - + + void STDMETHODCALLTYPE D3D11DeviceContext::SOSetTargets( UINT NumBuffers, ID3D11Buffer* const* ppSOTargets, const UINT* pOffsets) { - // TODO implement properly, including pOffsets - for (uint32_t i = 0; i < D3D11_SO_STREAM_COUNT; i++) { - m_state.so.targets[i] = (ppSOTargets != nullptr && i < NumBuffers) - ? static_cast(ppSOTargets[i]) - : nullptr; + for (uint32_t i = 0; i < NumBuffers; i++) { + D3D11Buffer* buffer = static_cast(ppSOTargets[i]); + UINT offset = pOffsets != nullptr ? pOffsets[i] : 0; + + m_state.so.targets[i].buffer = buffer; + m_state.so.targets[i].offset = offset; + } + + for (uint32_t i = NumBuffers; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + m_state.so.targets[i].buffer = nullptr; + m_state.so.targets[i].offset = 0; + } + + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + BindXfbBuffer(i, + m_state.so.targets[i].buffer.ptr(), + m_state.so.targets[i].offset); } } @@ -2528,7 +2542,7 @@ namespace dxvk { UINT NumBuffers, ID3D11Buffer** ppSOTargets) { for (uint32_t i = 0; i < NumBuffers; i++) - ppSOTargets[i] = m_state.so.targets[i].ref(); + ppSOTargets[i] = m_state.so.targets[i].buffer.ref(); } @@ -2862,7 +2876,38 @@ namespace dxvk { }); } - + + void D3D11DeviceContext::BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset) { + DxvkBufferSlice bufferSlice; + DxvkBufferSlice counterSlice; + + if (pBuffer != nullptr) { + bufferSlice = pBuffer->GetBufferSlice(); + counterSlice = pBuffer->GetSOCounter(); + } + + EmitCs([ + cSlotId = Slot, + cOffset = Offset, + cBufferSlice = bufferSlice, + cCounterSlice = counterSlice + ] (DxvkContext* ctx) { + if (cCounterSlice.defined() && cOffset != ~0u) { + ctx->updateBuffer( + cCounterSlice.buffer(), + cCounterSlice.offset(), + sizeof(cOffset), + &cOffset); + } + + ctx->bindXfbBuffer(cSlotId, cBufferSlice, cCounterSlice); + }); + } + + void D3D11DeviceContext::BindConstantBuffer( UINT Slot, const D3D11ConstantBufferBinding* pBufferBinding) { @@ -3141,6 +3186,9 @@ namespace dxvk { m_state.ia.vertexBuffers[i].offset, m_state.ia.vertexBuffers[i].stride); } + + for (uint32_t i = 0; i < m_state.so.targets.size(); i++) + BindXfbBuffer(i, m_state.so.targets[i].buffer.ptr(), ~0u); RestoreConstantBuffers(DxbcProgramType::VertexShader, m_state.vs.constantBuffers); RestoreConstantBuffers(DxbcProgramType::HullShader, m_state.hs.constantBuffers); diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index e2e9166c..9fd7e56c 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -690,6 +690,11 @@ namespace dxvk { UINT Offset, DXGI_FORMAT Format); + void BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset); + void BindConstantBuffer( UINT Slot, const D3D11ConstantBufferBinding* pBufferBinding); diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 18b086cc..fc780782 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -139,10 +139,16 @@ namespace dxvk { Com state; }; + + + struct D3D11ContextSoTarget { + Com buffer; + UINT offset; + }; - + struct D3D11ContextStateSO { - std::array, D3D11_SO_STREAM_COUNT> targets; + std::array targets; }; From 44024e7a7a8ac758e5b4b3b624877d5ddf8474c6 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 31 Aug 2018 16:10:55 +0200 Subject: [PATCH 28/30] [d3d11] Implement Stream Output queries --- src/d3d11/d3d11_device.cpp | 10 -------- src/d3d11/d3d11_query.cpp | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index aa5065da..214c3668 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -985,16 +985,6 @@ namespace dxvk { ID3D11Query** ppQuery) { InitReturnPtr(ppQuery); - if (pQueryDesc->Query != D3D11_QUERY_EVENT - && pQueryDesc->Query != D3D11_QUERY_OCCLUSION - && pQueryDesc->Query != D3D11_QUERY_TIMESTAMP - && pQueryDesc->Query != D3D11_QUERY_TIMESTAMP_DISJOINT - && pQueryDesc->Query != D3D11_QUERY_PIPELINE_STATISTICS - && pQueryDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE) { - Logger::warn(str::format("D3D11Query: Unsupported query type ", pQueryDesc->Query)); - return E_INVALIDARG; - } - if (ppQuery == nullptr) return S_FALSE; diff --git a/src/d3d11/d3d11_query.cpp b/src/d3d11/d3d11_query.cpp index 3e64e22c..5ca413a2 100644 --- a/src/d3d11/d3d11_query.cpp +++ b/src/d3d11/d3d11_query.cpp @@ -36,6 +36,35 @@ namespace dxvk { VK_QUERY_TYPE_PIPELINE_STATISTICS, 0); break; + case D3D11_QUERY_SO_STATISTICS: + case D3D11_QUERY_SO_STATISTICS_STREAM0: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0: + // FIXME it is technically incorrect to map + // SO_OVERFLOW_PREDICATE to the first stream, + // but this is good enough for D3D10 behaviour + m_query = new DxvkQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 0); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM1: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1: + m_query = new DxvkQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 1); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM2: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2: + m_query = new DxvkQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 2); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM3: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: + m_query = new DxvkQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 3); + break; + default: throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query)); } @@ -246,7 +275,27 @@ namespace dxvk { data->DSInvocations = queryData.statistic.tesInvocations; data->CSInvocations = queryData.statistic.csInvocations; } return S_OK; + + case D3D11_QUERY_SO_STATISTICS: + case D3D11_QUERY_SO_STATISTICS_STREAM0: + case D3D11_QUERY_SO_STATISTICS_STREAM1: + case D3D11_QUERY_SO_STATISTICS_STREAM2: + case D3D11_QUERY_SO_STATISTICS_STREAM3: { + auto data = static_cast(pData); + data->NumPrimitivesWritten = queryData.xfbStream.primitivesWritten; + data->PrimitivesStorageNeeded = queryData.xfbStream.primitivesNeeded; + } return S_OK; + case D3D11_QUERY_SO_OVERFLOW_PREDICATE: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: { + auto data = static_cast(pData); + *data = queryData.xfbStream.primitivesNeeded + > queryData.xfbStream.primitivesWritten; + } return S_OK; + default: Logger::err(str::format("D3D11: Unhandled query type in GetData: ", m_desc.Query)); return E_INVALIDARG; From 93a851a2fc051efc35c82484afb41462f891121c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 4 Sep 2018 02:17:21 +0200 Subject: [PATCH 29/30] [d3d11] Implement DrawAuto method --- src/d3d11/d3d11_context.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 7fa01bbc..7159386b 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1267,7 +1267,22 @@ namespace dxvk { void STDMETHODCALLTYPE D3D11DeviceContext::DrawAuto() { - Logger::err("D3D11DeviceContext::DrawAuto: Not implemented"); + D3D11Buffer* buffer = m_state.ia.vertexBuffers[0].buffer.ptr(); + + if (buffer == nullptr) + return; + + DxvkBufferSlice vtxBuf = buffer->GetBufferSlice(); + DxvkBufferSlice ctrBuf = buffer->GetSOCounter(); + + if (!ctrBuf.defined()) + return; + + EmitCs([=] (DxvkContext* ctx) { + ctx->drawIndirectXfb(ctrBuf, + vtxBuf.buffer()->getXfbVertexStride(), + 0); // FIXME offset? + }); } From 406816d17c9ec9062a8d24c9dbe23c653fc4822d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 31 Aug 2018 12:29:33 +0200 Subject: [PATCH 30/30] [d3d10] Support pOffsets parameter in SOGetTargets --- src/d3d10/d3d10_device.cpp | 8 ++++---- src/d3d11/d3d11_context.cpp | 14 ++++++++++++++ src/d3d11/d3d11_context.h | 5 +++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/d3d10/d3d10_device.cpp b/src/d3d10/d3d10_device.cpp index 0a14fc80..cba6d008 100644 --- a/src/d3d10/d3d10_device.cpp +++ b/src/d3d10/d3d10_device.cpp @@ -1550,7 +1550,10 @@ namespace dxvk { ID3D10Buffer** ppSOTargets, UINT* pOffsets) { ID3D11Buffer* d3d11Buffers[D3D10_SO_BUFFER_SLOT_COUNT]; - m_context->SOGetTargets(NumBuffers, ppSOTargets ? d3d11Buffers : nullptr); + + m_context->SOGetTargetsWithOffsets(NumBuffers, + ppSOTargets ? d3d11Buffers : nullptr, + pOffsets); if (ppSOTargets != nullptr) { for (uint32_t i = 0; i < NumBuffers; i++) { @@ -1559,9 +1562,6 @@ namespace dxvk { : nullptr; } } - - if (pOffsets != nullptr) - Logger::warn("D3D10: SOGetTargets: Reporting buffer offsets not supported"); } diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 7159386b..32a1b024 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2561,6 +2561,20 @@ namespace dxvk { } + void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargetsWithOffsets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets, + UINT* pOffsets) { + for (uint32_t i = 0; i < NumBuffers; i++) { + if (ppSOTargets != nullptr) + ppSOTargets[i] = m_state.so.targets[i].buffer.ref(); + + if (pOffsets != nullptr) + pOffsets[i] = m_state.so.targets[i].offset; + } + } + + void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout( IDXGIVkInteropSurface* pSurface, const VkImageSubresourceRange* pSubresources, diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 9fd7e56c..47efa7a3 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -631,6 +631,11 @@ namespace dxvk { UINT NumBuffers, ID3D11Buffer** ppSOTargets) final; + void STDMETHODCALLTYPE SOGetTargetsWithOffsets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets, + UINT* pOffsets); + void STDMETHODCALLTYPE TransitionSurfaceLayout( IDXGIVkInteropSurface* pSurface, const VkImageSubresourceRange* pSubresources,