1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-28 02:19:26 +01:00

[dxvk] Consider point-mode tessellation for GS topology

This commit is contained in:
Philip Rebohle 2025-03-14 23:59:12 +01:00
parent aa637d6286
commit 0dec617c4e
2 changed files with 42 additions and 35 deletions

View File

@ -44,6 +44,19 @@ namespace dxvk {
}
VkPrimitiveTopology determinePreGsTopology(
const DxvkGraphicsPipelineShaders& shaders,
const DxvkGraphicsPipelineStateInfo& state) {
if (shaders.tcs && shaders.tcs->flags().test(DxvkShaderFlag::TessellationPoints))
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
if (shaders.tes)
return shaders.tes->info().outputTopology;
return state.ia.primitiveTopology();
}
DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState() {
}
@ -52,13 +65,13 @@ namespace dxvk {
DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* vs) {
const DxvkGraphicsPipelineShaders& shaders) {
std::array<uint32_t, MaxNumVertexBindings> viBindingMap = { };
iaInfo.topology = state.ia.primitiveTopology();
iaInfo.primitiveRestartEnable = state.ia.primitiveRestart();
uint32_t attrMask = vs->info().inputMask;
uint32_t attrMask = shaders.vs->info().inputMask;
uint32_t bindingMask = 0;
// Find out which bindings are used based on the attribute mask
@ -244,10 +257,10 @@ namespace dxvk {
DxvkGraphicsPipelineFragmentOutputState::DxvkGraphicsPipelineFragmentOutputState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* fs) {
const DxvkGraphicsPipelineShaders& shaders) {
// Set up color formats and attachment blend states. Disable the write
// mask for any attachment that the fragment shader does not write to.
uint32_t fsOutputMask = fs ? fs->info().outputMask : 0u;
uint32_t fsOutputMask = shaders.fs ? shaders.fs->info().outputMask : 0u;
// Dual-source blending can only write to one render target
if (state.useDualSourceBlending())
@ -331,13 +344,13 @@ namespace dxvk {
: VK_SAMPLE_COUNT_1_BIT;
}
if (fs && fs->flags().test(DxvkShaderFlag::HasSampleRateShading)) {
if (shaders.fs && shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading)) {
msInfo.sampleShadingEnable = VK_TRUE;
msInfo.minSampleShading = 1.0f;
}
// Alpha to coverage is not supported with sample mask exports.
cbUseDynamicAlphaToCoverage = !fs || !fs->flags().test(DxvkShaderFlag::ExportsSampleMask);
cbUseDynamicAlphaToCoverage = !shaders.fs || !shaders.fs->flags().test(DxvkShaderFlag::ExportsSampleMask);
msSampleMask = state.ms.sampleMask() & ((1u << msInfo.rasterizationSamples) - 1);
msInfo.pSampleMask = &msSampleMask;
@ -518,9 +531,7 @@ namespace dxvk {
DxvkGraphicsPipelinePreRasterizationState::DxvkGraphicsPipelinePreRasterizationState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* tes,
const DxvkShader* gs,
const DxvkShader* fs) {
const DxvkGraphicsPipelineShaders& shaders) {
// Set up tessellation state
tsInfo.patchControlPoints = state.ia.patchVertexCount();
@ -532,7 +543,7 @@ namespace dxvk {
// Set up rasterized stream depending on geometry shader state.
// Rasterizing stream 0 is default behaviour in all situations.
int32_t streamIndex = gs ? gs->info().xfbRasterizedStream : 0;
int32_t streamIndex = shaders.gs ? shaders.gs->info().xfbRasterizedStream : 0;
if (streamIndex > 0) {
rsXfbStreamInfo.pNext = std::exchange(rsInfo.pNext, &rsXfbStreamInfo);
@ -558,7 +569,7 @@ namespace dxvk {
}
// Set up line rasterization mode as requested by the application.
if (state.rs.lineMode() != VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT && isLineRendering(state, tes, gs)) {
if (state.rs.lineMode() != VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT && isLineRendering(shaders, state)) {
rsLineInfo.pNext = std::exchange(rsInfo.pNext, &rsLineInfo);
rsLineInfo.lineRasterizationMode = state.rs.lineMode();
@ -571,7 +582,7 @@ namespace dxvk {
// in combination with smooth lines. Override the line mode to
// rectangular to fix this, but keep the width fixed at 1.0.
bool needsOverride = state.ms.enableAlphaToCoverage()
|| (fs && fs->flags().test(DxvkShaderFlag::HasSampleRateShading));
|| (shaders.fs && shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading));
if (needsOverride)
rsLineInfo.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
@ -633,15 +644,14 @@ namespace dxvk {
bool DxvkGraphicsPipelinePreRasterizationState::isLineRendering(
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* tes,
const DxvkShader* gs) {
const DxvkGraphicsPipelineShaders& shaders,
const DxvkGraphicsPipelineStateInfo& state) {
bool isLineRendering = state.rs.polygonMode() == VK_POLYGON_MODE_LINE;
if (gs) {
isLineRendering |= gs->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
} else if (tes) {
isLineRendering |= tes->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
if (shaders.gs) {
isLineRendering |= shaders.gs->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
} else if (shaders.tes) {
isLineRendering |= shaders.tes->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
} else {
VkPrimitiveTopology topology = state.ia.primitiveTopology();
@ -874,7 +884,7 @@ namespace dxvk {
// Fix up input topology for geometry shaders as necessary
if (shaderInfo.stage == VK_SHADER_STAGE_GEOMETRY_BIT) {
VkPrimitiveTopology iaTopology = shaders.tes ? shaders.tes->info().outputTopology : state.ia.primitiveTopology();
VkPrimitiveTopology iaTopology = determinePreGsTopology(shaders, state);
info.inputTopology = determineGsInputTopology(shaderInfo.inputTopology, iaTopology);
}
@ -1207,7 +1217,7 @@ namespace dxvk {
// We do not implement setting certain rarely used render
// states dynamically since they are generally not used
bool isLineRendering = DxvkGraphicsPipelinePreRasterizationState::isLineRendering(state, m_shaders.tes.ptr(), m_shaders.gs.ptr());
bool isLineRendering = DxvkGraphicsPipelinePreRasterizationState::isLineRendering(m_shaders, state);
if (state.rs.polygonMode() != VK_POLYGON_MODE_FILL
|| state.rs.conservativeMode() != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
@ -1235,7 +1245,7 @@ namespace dxvk {
if (m_shaders.gs != nullptr) {
// If the geometry shader's input topology is not compatible with
// the topology set to the pipeline, we need to patch the GS.
VkPrimitiveTopology iaTopology = m_shaders.tes ? m_shaders.tes->info().outputTopology : state.ia.primitiveTopology();
VkPrimitiveTopology iaTopology = determinePreGsTopology(m_shaders, state);
VkPrimitiveTopology gsTopology = m_shaders.gs->info().inputTopology;
if (determineGsInputTopology(gsTopology, iaTopology) != gsTopology)
@ -1306,8 +1316,8 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getBasePipeline(
const DxvkGraphicsPipelineStateInfo& state) {
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr());
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr());
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders);
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders);
DxvkGraphicsPipelineBaseInstanceKey key;
key.viLibrary = m_manager->createVertexInputLibrary(viState);

View File

@ -50,7 +50,7 @@ namespace dxvk {
DxvkGraphicsPipelineVertexInputState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* vs);
const DxvkGraphicsPipelineShaders& shaders);
VkPipelineInputAssemblyStateCreateInfo iaInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
VkPipelineVertexInputStateCreateInfo viInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
@ -109,7 +109,7 @@ namespace dxvk {
DxvkGraphicsPipelineFragmentOutputState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* fs);
const DxvkGraphicsPipelineShaders& shaders);
VkPipelineRenderingCreateInfo rtInfo = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
VkPipelineColorBlendStateCreateInfo cbInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
@ -170,9 +170,7 @@ namespace dxvk {
DxvkGraphicsPipelinePreRasterizationState(
const DxvkDevice* device,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* tes,
const DxvkShader* gs,
const DxvkShader* fs);
const DxvkGraphicsPipelineShaders& shaders);
VkPipelineViewportStateCreateInfo vpInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
VkPipelineTessellationStateCreateInfo tsInfo = { VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO };
@ -187,9 +185,8 @@ namespace dxvk {
size_t hash() const;
static bool isLineRendering(
const DxvkGraphicsPipelineStateInfo& state,
const DxvkShader* tes,
const DxvkShader* gs);
const DxvkGraphicsPipelineShaders& shaders,
const DxvkGraphicsPipelineStateInfo& state);
};
@ -413,10 +410,10 @@ namespace dxvk {
uint32_t specConstantMask)
: shState(shaders, state),
dyState(device, state, flags),
viState(device, state, shaders.vs.ptr()),
prState(device, state, shaders.tes.ptr(), shaders.gs.ptr(), shaders.fs.ptr()),
viState(device, state, shaders),
prState(device, state, shaders),
fsState(device, state),
foState(device, state, shaders.fs.ptr()),
foState(device, state, shaders),
scState(specConstantMask, state.sc) { }
DxvkGraphicsPipelineShaderState shState;