Skip to content

Commit

Permalink
Fix possible divide by zero explode edge case
Browse files Browse the repository at this point in the history
Only currently apparent with vulkan but could also exist with d3d in the
right circumstances:  With vulkan mesh drawing, the axis construction lines
would disappear even when all explode params are zero.  This is almost
certainly down to normalizing a vertex offset that's coincident with
'exploderCentre', producing INFs/NaNs.  Hlsl would return explodeDir to zero
by multiplying with a zero 'exploderScale' but vulkan doesn't seem to do
that... TLDR:  Avoid dividing by zero.

Also added some lines between MeshUBOData fields to better see padding
requirements, since I wondered if I'd misaligned something.
  • Loading branch information
GertyP committed Nov 24, 2023
1 parent 6de048f commit 308c7c9
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 4 deletions.
4 changes: 4 additions & 0 deletions renderdoc/data/glsl/glsl_ubos.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,19 @@ BINDING(0) uniform MeshUBOData
mat4 mvp;
mat4 invProj;
vec4 color;

int displayFormat;
uint homogenousInput;
vec2 pointSpriteSize;

uint rawoutput;
uint flipY;
float vtxExploderSNorm;
float exploderScale;

vec3 exploderCentre;
float padding;

uvec4 meshletColours[12];
}
INST_NAME(Mesh);
Expand Down
11 changes: 9 additions & 2 deletions renderdoc/data/glsl/mesh.vert
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,17 @@ void vtxExploder(in int vtxID, inout vec3 pos, inout vec3 secondary)
{
float nonLinearVtxExplodeScale = 4.0f * Mesh.exploderScale * Mesh.vtxExploderSNorm *
Mesh.vtxExploderSNorm * Mesh.vtxExploderSNorm;
vec3 explodeDir = normalize(pos - Mesh.exploderCentre);

// A vertex might be coincident with our 'exploderCentre' so that, when normalized,
// can give us INFs/NaNs that, even if multiplied by a zero 'exploderScale', can
// leave us with bad numbers (as seems to be the case with glsl/vulkan, but not hlsl).
// Still, we should make this case safe for when we have a non-zero 'exploderScale' -
vec3 offset = pos - Mesh.exploderCentre;
float offsetDistSquared = dot(offset, offset);
vec3 safeExplodeDir = offset * inversesqrt(max(offsetDistSquared, FLT_EPSILON));

float displacement = nonLinearVtxExplodeScale * ((float((vtxID >> 1) & 0xf) / 15.0f) * 1.5f - 0.5f);
pos += (explodeDir * displacement);
pos += (safeExplodeDir * displacement);

if(Mesh.exploderScale > 0.0f)
{
Expand Down
11 changes: 9 additions & 2 deletions renderdoc/data/hlsl/mesh.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,18 @@ void vtxExploder(in uint vtxID, inout float3 pos, inout float3 secondary)
{
float nonLinearVtxExplodeScale =
4.0f * exploderScale * vtxExploderSNorm * vtxExploderSNorm * vtxExploderSNorm;
float3 explodeDir = normalize(pos - exploderCentre);

// A vertex might be coincident with our 'exploderCentre' so that, when normalized,
// can give us INFs/NaNs that, even if multiplied by a zero 'exploderScale', can
// leave us with bad numbers (as seems to be the case with glsl/vulkan, but not hlsl).
// Still, we should make this case safe for when we have a non-zero 'exploderScale' -
float3 offset = pos - exploderCentre;
float offsetDistSquared = dot(offset, offset);
float3 safeExplodeDir = offset * rsqrt(max(offsetDistSquared, FLT_EPSILON));

float displacement =
nonLinearVtxExplodeScale * ((float((vtxID >> 1u) & 0xfu) / 15.0f) * 1.5f - 0.5f);
pos += (explodeDir * displacement);
pos += (safeExplodeDir * displacement);

if(exploderScale > 0.0f)
{
Expand Down

0 comments on commit 308c7c9

Please sign in to comment.