From e65daa94fe9d9e1ddbdacef39ee43ef17fa7c7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 9 Oct 2025 08:49:29 +0200 Subject: [PATCH] tessellation fix when using provoking index buffer --- WickedEngine/shaders/objectHF.hlsli | 17 ++++++++--------- .../shaders/objectVS_common_tessellation.hlsl | 1 + WickedEngine/shaders/objectVS_prepass.hlsl | 1 + .../shaders/objectVS_prepass_alphatest.hlsl | 1 + ...objectVS_prepass_alphatest_tessellation.hlsl | 1 + .../shaders/objectVS_prepass_tessellation.hlsl | 1 + WickedEngine/wiRenderer.cpp | 7 ++++++- WickedEngine/wiVersion.cpp | 2 +- 8 files changed, 20 insertions(+), 11 deletions(-) diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 8234ba759..6bf34a08f 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -80,6 +80,7 @@ PUSHCONSTANT(push, ObjectPushConstants); //#define OBJECTSHADER_USE_INSTANCEINDEX - shader will use instance ID //#define OBJECTSHADER_USE_CAMERAINDEX - shader will use camera ID //#define OBJECTSHADER_USE_COMMON - shader will use atlas, ambient occlusion, wetmap +//#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER - shader will load vertex ID through provoking index buffer reordering #ifdef OBJECTSHADER_LAYOUT_SHADOW @@ -121,25 +122,23 @@ struct VertexInput { uint vertexID : SV_VertexID; uint instanceID : SV_InstanceID; - + +#ifdef OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER uint GetPrimitiveID() { -#if defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) // For prepass the meshopt_generateProvokingIndexBuffer is used to emulate SV_PrimitiveID via provoking vertex return vertexID; -#else - return 0; -#endif // defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) } +#endif // OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER uint GetVertexID() { -#if defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) +#ifdef OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER // For prepass the meshopt_generateProvokingIndexBuffer is used to emulate SV_PrimitiveID via provoking vertex return bindless_buffers_uint[descriptor_index(GetMesh().ib_reorder)][vertexID]; #else return vertexID; -#endif // defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) +#endif // OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER } float4 GetPositionWind() @@ -410,9 +409,9 @@ PixelInput vertex_to_pixel_export(VertexInput input) ShaderCamera camera = GetCamera(); #endif // OBJECTSHADER_USE_CAMERAINDEX -#if defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) +#if defined(PREPASS) && defined(OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER) Out.primitiveID = input.GetPrimitiveID(); -#endif // defined(PREPASS) && !defined(OBJECTSHADER_COMPILE_MS) +#endif // defined(PREPASS) && defined(OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER) #ifndef OBJECTSHADER_USE_NOCAMERA Out.pos = mul(camera.view_projection, Out.pos); diff --git a/WickedEngine/shaders/objectVS_common_tessellation.hlsl b/WickedEngine/shaders/objectVS_common_tessellation.hlsl index e98c2a37e..4532052b1 100644 --- a/WickedEngine/shaders/objectVS_common_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_common_tessellation.hlsl @@ -1,4 +1,5 @@ #define OBJECTSHADER_COMPILE_VS #define OBJECTSHADER_LAYOUT_COMMON #define OBJECTSHADER_USE_NOCAMERA +#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass.hlsl b/WickedEngine/shaders/objectVS_prepass.hlsl index 46363f750..b201c32cf 100644 --- a/WickedEngine/shaders/objectVS_prepass.hlsl +++ b/WickedEngine/shaders/objectVS_prepass.hlsl @@ -1,3 +1,4 @@ #define OBJECTSHADER_COMPILE_VS #define OBJECTSHADER_LAYOUT_PREPASS +#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl b/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl index eb28e2a95..682fd3df8 100644 --- a/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl @@ -1,3 +1,4 @@ #define OBJECTSHADER_COMPILE_VS #define OBJECTSHADER_LAYOUT_PREPASS_TEX +#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl b/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl index 6af689c42..fe199202c 100644 --- a/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl @@ -2,5 +2,6 @@ #define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NOCAMERA #define OBJECTSHADER_USE_NORMAL +#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl b/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl index 08bbd402f..ad907338e 100644 --- a/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl @@ -2,4 +2,5 @@ #define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NOCAMERA #define OBJECTSHADER_USE_NORMAL +#define OBJECTSHADER_USE_PROVOKING_INDEX_BUFFER #include "objectHF.hlsli" diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index c64eecf6a..1bb34aad3 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3169,7 +3169,12 @@ void RenderMeshes( const float tessF = mesh.GetTessellationFactor(); const bool tessellatorRequested = tessF > 0 && tessellation; const bool meshShaderRequested = !tessellatorRequested && mesh_shader && mesh.vb_clu.IsValid(); - const bool provokingIBRequired = renderPass == RENDERPASS_PREPASS || renderPass == RENDERPASS_PREPASS_DEPTHONLY; // Note: depthonly doesn't need primitiveID, but for now I don't created specialized shader for it without primitiveID (TODO measure perf, additional shaders overhead) + + // Notes on provoking index buffer: + // Normally it's used for primitiveID generation, so it would be only used in PREPASS + // PREPASS_DEPTHONLY doesn't use separate shader variants, so it will also use provoking index buffer + // tessellation requires it to match same primitive order between prepass and color pass to have exact same tessellation + const bool provokingIBRequired = renderPass == RENDERPASS_PREPASS || renderPass == RENDERPASS_PREPASS_DEPTHONLY || tessellatorRequested; if (forwardLightmaskRequest) { diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 8c9e1266f..282ed104c 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 835; + const int revision = 836; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);