mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-04-01 09:25:24 +02:00
[dxvk] Consider point-mode tessellation for GS topology
This commit is contained in:
parent
aa637d6286
commit
0dec617c4e
@ -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() {
|
DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -52,13 +65,13 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState(
|
DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* vs) {
|
const DxvkGraphicsPipelineShaders& shaders) {
|
||||||
std::array<uint32_t, MaxNumVertexBindings> viBindingMap = { };
|
std::array<uint32_t, MaxNumVertexBindings> viBindingMap = { };
|
||||||
|
|
||||||
iaInfo.topology = state.ia.primitiveTopology();
|
iaInfo.topology = state.ia.primitiveTopology();
|
||||||
iaInfo.primitiveRestartEnable = state.ia.primitiveRestart();
|
iaInfo.primitiveRestartEnable = state.ia.primitiveRestart();
|
||||||
|
|
||||||
uint32_t attrMask = vs->info().inputMask;
|
uint32_t attrMask = shaders.vs->info().inputMask;
|
||||||
uint32_t bindingMask = 0;
|
uint32_t bindingMask = 0;
|
||||||
|
|
||||||
// Find out which bindings are used based on the attribute mask
|
// Find out which bindings are used based on the attribute mask
|
||||||
@ -244,10 +257,10 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelineFragmentOutputState::DxvkGraphicsPipelineFragmentOutputState(
|
DxvkGraphicsPipelineFragmentOutputState::DxvkGraphicsPipelineFragmentOutputState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* fs) {
|
const DxvkGraphicsPipelineShaders& shaders) {
|
||||||
// Set up color formats and attachment blend states. Disable the write
|
// Set up color formats and attachment blend states. Disable the write
|
||||||
// mask for any attachment that the fragment shader does not write to.
|
// 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
|
// Dual-source blending can only write to one render target
|
||||||
if (state.useDualSourceBlending())
|
if (state.useDualSourceBlending())
|
||||||
@ -331,13 +344,13 @@ namespace dxvk {
|
|||||||
: VK_SAMPLE_COUNT_1_BIT;
|
: 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.sampleShadingEnable = VK_TRUE;
|
||||||
msInfo.minSampleShading = 1.0f;
|
msInfo.minSampleShading = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alpha to coverage is not supported with sample mask exports.
|
// 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);
|
msSampleMask = state.ms.sampleMask() & ((1u << msInfo.rasterizationSamples) - 1);
|
||||||
msInfo.pSampleMask = &msSampleMask;
|
msInfo.pSampleMask = &msSampleMask;
|
||||||
@ -518,9 +531,7 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelinePreRasterizationState::DxvkGraphicsPipelinePreRasterizationState(
|
DxvkGraphicsPipelinePreRasterizationState::DxvkGraphicsPipelinePreRasterizationState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* tes,
|
const DxvkGraphicsPipelineShaders& shaders) {
|
||||||
const DxvkShader* gs,
|
|
||||||
const DxvkShader* fs) {
|
|
||||||
// Set up tessellation state
|
// Set up tessellation state
|
||||||
tsInfo.patchControlPoints = state.ia.patchVertexCount();
|
tsInfo.patchControlPoints = state.ia.patchVertexCount();
|
||||||
|
|
||||||
@ -532,7 +543,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Set up rasterized stream depending on geometry shader state.
|
// Set up rasterized stream depending on geometry shader state.
|
||||||
// Rasterizing stream 0 is default behaviour in all situations.
|
// 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) {
|
if (streamIndex > 0) {
|
||||||
rsXfbStreamInfo.pNext = std::exchange(rsInfo.pNext, &rsXfbStreamInfo);
|
rsXfbStreamInfo.pNext = std::exchange(rsInfo.pNext, &rsXfbStreamInfo);
|
||||||
@ -558,7 +569,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up line rasterization mode as requested by the application.
|
// 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.pNext = std::exchange(rsInfo.pNext, &rsLineInfo);
|
||||||
rsLineInfo.lineRasterizationMode = state.rs.lineMode();
|
rsLineInfo.lineRasterizationMode = state.rs.lineMode();
|
||||||
|
|
||||||
@ -571,7 +582,7 @@ namespace dxvk {
|
|||||||
// in combination with smooth lines. Override the line mode to
|
// in combination with smooth lines. Override the line mode to
|
||||||
// rectangular to fix this, but keep the width fixed at 1.0.
|
// rectangular to fix this, but keep the width fixed at 1.0.
|
||||||
bool needsOverride = state.ms.enableAlphaToCoverage()
|
bool needsOverride = state.ms.enableAlphaToCoverage()
|
||||||
|| (fs && fs->flags().test(DxvkShaderFlag::HasSampleRateShading));
|
|| (shaders.fs && shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading));
|
||||||
|
|
||||||
if (needsOverride)
|
if (needsOverride)
|
||||||
rsLineInfo.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
rsLineInfo.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
||||||
@ -633,15 +644,14 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
bool DxvkGraphicsPipelinePreRasterizationState::isLineRendering(
|
bool DxvkGraphicsPipelinePreRasterizationState::isLineRendering(
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
const DxvkShader* tes,
|
const DxvkGraphicsPipelineStateInfo& state) {
|
||||||
const DxvkShader* gs) {
|
|
||||||
bool isLineRendering = state.rs.polygonMode() == VK_POLYGON_MODE_LINE;
|
bool isLineRendering = state.rs.polygonMode() == VK_POLYGON_MODE_LINE;
|
||||||
|
|
||||||
if (gs) {
|
if (shaders.gs) {
|
||||||
isLineRendering |= gs->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
isLineRendering |= shaders.gs->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||||
} else if (tes) {
|
} else if (shaders.tes) {
|
||||||
isLineRendering |= tes->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
isLineRendering |= shaders.tes->info().outputTopology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||||
} else {
|
} else {
|
||||||
VkPrimitiveTopology topology = state.ia.primitiveTopology();
|
VkPrimitiveTopology topology = state.ia.primitiveTopology();
|
||||||
|
|
||||||
@ -874,7 +884,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Fix up input topology for geometry shaders as necessary
|
// Fix up input topology for geometry shaders as necessary
|
||||||
if (shaderInfo.stage == VK_SHADER_STAGE_GEOMETRY_BIT) {
|
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);
|
info.inputTopology = determineGsInputTopology(shaderInfo.inputTopology, iaTopology);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1207,7 +1217,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
// We do not implement setting certain rarely used render
|
// We do not implement setting certain rarely used render
|
||||||
// states dynamically since they are generally not used
|
// 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
|
if (state.rs.polygonMode() != VK_POLYGON_MODE_FILL
|
||||||
|| state.rs.conservativeMode() != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
|
|| state.rs.conservativeMode() != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
|
||||||
@ -1235,7 +1245,7 @@ namespace dxvk {
|
|||||||
if (m_shaders.gs != nullptr) {
|
if (m_shaders.gs != nullptr) {
|
||||||
// If the geometry shader's input topology is not compatible with
|
// If the geometry shader's input topology is not compatible with
|
||||||
// the topology set to the pipeline, we need to patch the GS.
|
// 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;
|
VkPrimitiveTopology gsTopology = m_shaders.gs->info().inputTopology;
|
||||||
|
|
||||||
if (determineGsInputTopology(gsTopology, iaTopology) != gsTopology)
|
if (determineGsInputTopology(gsTopology, iaTopology) != gsTopology)
|
||||||
@ -1306,8 +1316,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
VkPipeline DxvkGraphicsPipeline::getBasePipeline(
|
VkPipeline DxvkGraphicsPipeline::getBasePipeline(
|
||||||
const DxvkGraphicsPipelineStateInfo& state) {
|
const DxvkGraphicsPipelineStateInfo& state) {
|
||||||
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr());
|
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders);
|
||||||
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr());
|
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders);
|
||||||
|
|
||||||
DxvkGraphicsPipelineBaseInstanceKey key;
|
DxvkGraphicsPipelineBaseInstanceKey key;
|
||||||
key.viLibrary = m_manager->createVertexInputLibrary(viState);
|
key.viLibrary = m_manager->createVertexInputLibrary(viState);
|
||||||
|
@ -50,7 +50,7 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelineVertexInputState(
|
DxvkGraphicsPipelineVertexInputState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* vs);
|
const DxvkGraphicsPipelineShaders& shaders);
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo iaInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
VkPipelineInputAssemblyStateCreateInfo iaInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||||
VkPipelineVertexInputStateCreateInfo viInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
VkPipelineVertexInputStateCreateInfo viInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||||
@ -109,7 +109,7 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelineFragmentOutputState(
|
DxvkGraphicsPipelineFragmentOutputState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* fs);
|
const DxvkGraphicsPipelineShaders& shaders);
|
||||||
|
|
||||||
VkPipelineRenderingCreateInfo rtInfo = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
|
VkPipelineRenderingCreateInfo rtInfo = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
|
||||||
VkPipelineColorBlendStateCreateInfo cbInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
VkPipelineColorBlendStateCreateInfo cbInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
||||||
@ -170,9 +170,7 @@ namespace dxvk {
|
|||||||
DxvkGraphicsPipelinePreRasterizationState(
|
DxvkGraphicsPipelinePreRasterizationState(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkShader* tes,
|
const DxvkGraphicsPipelineShaders& shaders);
|
||||||
const DxvkShader* gs,
|
|
||||||
const DxvkShader* fs);
|
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo vpInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
VkPipelineViewportStateCreateInfo vpInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||||
VkPipelineTessellationStateCreateInfo tsInfo = { VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO };
|
VkPipelineTessellationStateCreateInfo tsInfo = { VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO };
|
||||||
@ -187,9 +185,8 @@ namespace dxvk {
|
|||||||
size_t hash() const;
|
size_t hash() const;
|
||||||
|
|
||||||
static bool isLineRendering(
|
static bool isLineRendering(
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
const DxvkShader* tes,
|
const DxvkGraphicsPipelineStateInfo& state);
|
||||||
const DxvkShader* gs);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -413,10 +410,10 @@ namespace dxvk {
|
|||||||
uint32_t specConstantMask)
|
uint32_t specConstantMask)
|
||||||
: shState(shaders, state),
|
: shState(shaders, state),
|
||||||
dyState(device, state, flags),
|
dyState(device, state, flags),
|
||||||
viState(device, state, shaders.vs.ptr()),
|
viState(device, state, shaders),
|
||||||
prState(device, state, shaders.tes.ptr(), shaders.gs.ptr(), shaders.fs.ptr()),
|
prState(device, state, shaders),
|
||||||
fsState(device, state),
|
fsState(device, state),
|
||||||
foState(device, state, shaders.fs.ptr()),
|
foState(device, state, shaders),
|
||||||
scState(specConstantMask, state.sc) { }
|
scState(specConstantMask, state.sc) { }
|
||||||
|
|
||||||
DxvkGraphicsPipelineShaderState shState;
|
DxvkGraphicsPipelineShaderState shState;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user