Skip to content

Commit

Permalink
Merge branch 'dev/adunn/visibility_test_perf' into 'main'
Browse files Browse the repository at this point in the history
GPU Perf: Helps the compiler generate more optimal code for visibility tests by eliminating a bunch of unnecessary work. Since for visibility tests we only need a subset of the 'Surface' and 'SurfaceInteraction' data we dont need to compute/load all of it. Primarily, this improves the RTXDI and ReSTIR GI buckets.

See merge request lightspeedrtx/dxvk-remix-nv!964
  • Loading branch information
AlexDunn committed Aug 27, 2024
2 parents 33701c0 + 77ee81e commit dd39314
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/dxvk/shaders/rtx/algorithm/geometry_resolver.slangh
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ void geometryResolverVertexOutputDebugView(
uint iterations = 0;
if (opaqueSurfaceMaterial.heightTextureIndex != BINDING_INDEX_INVALID && opaqueSurfaceMaterial.displaceIn > 0.0f)
{
SurfaceInteraction tempSurfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray);
SurfaceInteraction tempSurfaceInteraction = surfaceInteractionCreate<SurfaceGenerateTangents>(surface, rayInteraction, ray);
const f16mat3 worldToTangent = f16mat3(tempSurfaceInteraction.interpolatedTangent, tempSurfaceInteraction.interpolatedBitangent, tempSurfaceInteraction.interpolatedNormal);
const f16vec3 viewDirTangentSpace = normalize(mul(worldToTangent, rayInteraction.viewDirection));
hitPos = pomCalculateTexcoord(opaqueSurfaceMaterial, tempSurfaceInteraction, viewDirTangentSpace, iterations);
Expand All @@ -980,7 +980,7 @@ void geometryResolverVertexOutputDebugView(
float3 hitPos = float3(0.f);
if (opaqueSurfaceMaterial.heightTextureIndex != BINDING_INDEX_INVALID && opaqueSurfaceMaterial.displaceIn > 0.0f)
{
SurfaceInteraction tempSurfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray);
SurfaceInteraction tempSurfaceInteraction = surfaceInteractionCreate<SurfaceGenerateTangents>(surface, rayInteraction, ray);
const f16mat3 worldToTangent = f16mat3(tempSurfaceInteraction.interpolatedTangent, tempSurfaceInteraction.interpolatedBitangent, tempSurfaceInteraction.interpolatedNormal);
const f16vec3 viewDirTangentSpace = normalize(mul(worldToTangent, rayInteraction.viewDirection));
uint iterations = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct NEECacheUtils
Ray ray = {};
ray.origin = shadingPosition;
ray.spreadAngle = spreadAngle;
surfaceInteraction = surfaceInteractionCreate(surface, rayInteracton, ray, false, footprintMode);
surfaceInteraction = surfaceInteractionCreate<SurfaceIgnoreTangents>(surface, rayInteracton, ray, false, footprintMode);
surfaceInteraction.textureGradientX *= cb.neeCacheArgs.emissiveTextureSampleFootprintScale;
surfaceInteraction.textureGradientY *= cb.neeCacheArgs.emissiveTextureSampleFootprintScale;

Expand Down Expand Up @@ -305,7 +305,7 @@ struct NEECacheUtils

Ray dummyRay;
dummyRay.direction = f16vec3(1.0);
SurfaceInteraction surfaceInteraction = surfaceInteractionCreate(surface, rayInteracton, dummyRay, false, kFootprintFromTextureCoordDiff);
SurfaceInteraction surfaceInteraction = surfaceInteractionCreate<SurfaceIgnoreTangents>(surface, rayInteracton, dummyRay, false, kFootprintFromTextureCoordDiff);
triangleCenter = surfaceInteraction.position;
triangleNormal = surfaceInteraction.triangleNormal;
lightIntensity = vec3(0);
Expand Down
4 changes: 2 additions & 2 deletions src/dxvk/shaders/rtx/algorithm/resolve.slangh
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ void resolveVertex<T: IBasePayloadState>(

surface = surfaces[uint(rayInteraction.surfaceIndex)];

surfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray);
surfaceInteraction = surfaceInteractionCreate<SurfaceGenerateTangents>(surface, rayInteraction, ray);

// Process user clip planes and view distance

Expand Down Expand Up @@ -967,7 +967,7 @@ void resolveVertexUnordered<let RAY_FLAGS : uint8_t>(
const Surface surface = surfaces[uint(rayInteraction.surfaceIndex)];

if (isTriangle)
surfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray);
surfaceInteraction = surfaceInteractionCreate<SurfaceGenerateTangents>(surface, rayInteraction, ray);

// Test the hit surface against view distance and ignored surface clipping

Expand Down
31 changes: 25 additions & 6 deletions src/dxvk/shaders/rtx/algorithm/visibility.slangh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static const uint visibilityModeOpaqueOnly = (1 << 5); // Only q
// Visibility Helper Functions

// Returns the attenuation factor for the surface, i.e. (1.0 - opacity)
f16vec3 handleVisibilityVertex<let VisibilityMode : uint>(Ray ray, RayHitInfo rayHitInfo, bool usePreviousTLAS)
f16vec3 handleVisibilityVertex<let VisibilityMode : uint>(Ray ray, RayHitInfo rayHitInfo, const bool usePreviousTLAS)
{
RayInteraction rayInteraction = rayInteractionCreate(ray, rayHitInfo);

Expand All @@ -57,13 +57,32 @@ f16vec3 handleVisibilityVertex<let VisibilityMode : uint>(Ray ray, RayHitInfo ra
return 1.0;
}

const Surface surface = surfaces[uint(rayInteraction.surfaceIndex)];
Surface surface = surfaces[uint(rayInteraction.surfaceIndex)];

if (surfaceIsDecal(surface))
// Decals do not cast shadows
return 1.0;
// Since during visibility testing, we dont need all the data, we can just explicitly
// initialize these values and help the compiler generate more optimal code paths.
const bool requiresNormalsAndTangents = VisibilityMode & (visibilityModeEnableSubsurfaceMaterials|visibilityModeEnableTranslucentMaterials);
{
surface.displaceIn = 0.f;
surface.decalSortOrder = 0;
surface.objectPickingValue = 0;
surface.hashPacked = 0;
surface.texcoordGenerationMode = TexGenMode::None;

if (!usePreviousTLAS)
{
surface.previousPositionBufferIndex = BINDING_INDEX_INVALID;
surface.prevObjectToWorld = mat4x3(1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f);
}

if (!requiresNormalsAndTangents)
{
surface.normalBufferIndex = BINDING_INDEX_INVALID;
surface.normalObjectToWorld = getIdentityMatrix();
}
}

SurfaceInteraction surfaceInteraction = surfaceInteractionCreate(surface, rayInteraction, ray, usePreviousTLAS);
SurfaceInteraction surfaceInteraction = surfaceInteractionCreate<requiresNormalsAndTangents ? SurfaceGenerateTangents : SurfaceIgnoreTangents>(surface, rayInteraction, ray, usePreviousTLAS);

if (isSurfaceClipped(surface, surfaceInteraction))
// Ignore parts of surfaces that are under clip planes
Expand Down
26 changes: 16 additions & 10 deletions src/dxvk/shaders/rtx/concept/surface/surface_interaction.slangh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ static const uint kFootprintFromRayDirection = 1u;
static const uint kFootprintFromTextureCoordDiff = 2u;
static const uint kFootprintFromRayOriginClamped = 3u;

static const bool SurfaceGenerateTangents = true;
static const bool SurfaceIgnoreTangents = false;

// Surface Interaction Helper Functions

// Texture Gradient from Ray Cone Helper
Expand Down Expand Up @@ -170,7 +173,7 @@ void calcSpriteSheetAdjustment(
textureGradientY *= uvSize;
}

SurfaceInteraction surfaceInteractionCreate(
SurfaceInteraction surfaceInteractionCreate<let GenerateTangents : bool>(
Surface surface, RayInteraction rayInteraction, Ray ray,
bool usePreviousPositions = false, uint footprintMode = kFootprintFromRayDirection)
{
Expand Down Expand Up @@ -440,18 +443,21 @@ SurfaceInteraction surfaceInteractionCreate(

surfaceInteraction.textureCoordinates = interpolateHitAttribute(texcoords, bary);

// Note: World positions used here, the original PBRT usage uses model space vertex positions since it calculates the
// TBN in local space, but since we generate the TBN frame in world space this is more applicable. Additionally
// it removes the need to keep the object space positions around which should ideally reduce register pressure.
genTangSpace(
if (GenerateTangents)
{
// Note: World positions used here, the original PBRT usage uses model space vertex positions since it calculates the
// TBN in local space, but since we generate the TBN frame in world space this is more applicable. Additionally
// it removes the need to keep the object space positions around which should ideally reduce register pressure.
genTangSpace(
texcoords, worldPositions, surfaceInteraction.interpolatedNormal,
surfaceInteraction.interpolatedTangent, surfaceInteraction.interpolatedBitangent, surfaceInteraction.rawTangent, surfaceInteraction.rawBitangent);

// Derive triangle TBN based on interpolated TBN. This works in all cases tested,
// and should be much cheaper than calling genTangSpace again.
f16vec4 interpolatedToTriangle = quaternionCreateOrientation(surfaceInteraction.interpolatedNormal, surfaceInteraction.triangleNormal);
surfaceInteraction.triangleTangent = quaternionTransformVector(interpolatedToTriangle, surfaceInteraction.interpolatedTangent);
surfaceInteraction.triangleBitangent = quaternionTransformVector(interpolatedToTriangle, surfaceInteraction.interpolatedBitangent);
// Derive triangle TBN based on interpolated TBN. This works in all cases tested,
// and should be much cheaper than calling genTangSpace again.
f16vec4 interpolatedToTriangle = quaternionCreateOrientation(surfaceInteraction.interpolatedNormal, surfaceInteraction.triangleNormal);
surfaceInteraction.triangleTangent = quaternionTransformVector(interpolatedToTriangle, surfaceInteraction.interpolatedTangent);
surfaceInteraction.triangleBitangent = quaternionTransformVector(interpolatedToTriangle, surfaceInteraction.interpolatedBitangent);
}

// Convert texcoords from the 1st cascade to a corresponding cascade in a combined tiled cascades texture space
if (surface.texcoordGenerationMode == uint(TexGenMode::CascadedViewPositions))
Expand Down

0 comments on commit dd39314

Please sign in to comment.