16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-09-01 22:09:20 +02:00

merge manul

This commit is contained in:
WLs50
2025-03-09 15:36:11 +01:00
parent a687f551a2
commit a5f6397eca
1211 changed files with 483542 additions and 58643 deletions

View File

@@ -0,0 +1,74 @@
# This file is part of the FidelityFX SDK.
#
# Copyright (C) 2024 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set(BRIXELIZER_BASE_ARGS
-reflection -deps=gcc -DFFX_GPU=1)
set(BRIXELIZER_INCLUDE_ARGS
"${FFX_GPU_PATH}"
"${FFX_GPU_PATH}/brixelizer")
if (NOT BRIXELIZER_SHADER_EXT)
set(BRIXELIZER_SHADER_EXT *)
endif()
file(GLOB BRIXELIZER_SHADERS
"shaders/brixelizer/ffx_brixelizer_cascade_ops_build_tree_aabb_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_clear_brick_storage_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_clear_build_counters_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_clear_job_counter_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_clear_ref_counters_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_coarse_culling_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_compact_references_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_compress_brick_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_emit_sdf_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_free_cascade_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_initialize_cascade_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_invalidate_job_areas_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_mark_cascade_uninitialized_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_reset_cascade_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_scan_jobs_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_scan_references_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_scroll_cascade_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_cascade_ops_voxelize_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_clear_brick_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_clear_counters_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_collect_clear_bricks_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_collect_dirty_bricks_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_eikonal_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_merge_bricks_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_merge_cascades_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_prepare_clear_bricks_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_prepare_eikonal_args_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_context_ops_prepare_merge_bricks_args_pass.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_debug_draw_aabb_tree.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_debug_draw_instance_aabbs.${BRIXELIZER_SHADER_EXT}"
"shaders/brixelizer/ffx_brixelizer_debug_visualization_pass.${BRIXELIZER_SHADER_EXT}")
# compile all the shaders
compile_shaders_with_depfile(
"${FFX_SC_EXECUTABLE}"
"${BRIXELIZER_BASE_ARGS}" "${BRIXELIZER_API_BASE_ARGS}" "" "${BRIXELIZER_INCLUDE_ARGS}"
"${BRIXELIZER_SHADERS}" "${FFX_PASS_SHADER_OUTPUT_PATH}" BRIXELIZER_PERMUTATION_OUTPUTS)
# add the header files they generate to the main list of dependencies
add_shader_output("${BRIXELIZER_PERMUTATION_OUTPUTS}")

View File

@@ -0,0 +1,117 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_BRICK_COMMON_H
#define FFX_BRIXELIZER_BRICK_COMMON_H
#include "ffx_brixelizer_common.h"
FfxUInt32 FfxBrixelizerBrickGetIndex(FfxUInt32 brick_id)
{
return brick_id & FFX_BRIXELIZER_BRICK_ID_MASK;
}
FfxUInt32x3 FfxBrixelizerWrapCoords(FfxInt32x3 clipmap_offset, FfxUInt32 wrap_mask, FfxUInt32x3 voxel_coord)
{
return (voxel_coord + FfxUInt32x3(clipmap_offset)) & FfxUInt32x3(wrap_mask, wrap_mask, wrap_mask);
}
FfxUInt32x3 FfxBrixelizerWrapCoords(FfxBrixelizerCascadeInfo cinfo, FfxUInt32x3 voxel_coord)
{
return (voxel_coord + cinfo.clipmap_offset) & FfxUInt32x3(FFX_BRIXELIZER_CASCADE_WRAP_MASK, FFX_BRIXELIZER_CASCADE_WRAP_MASK, FFX_BRIXELIZER_CASCADE_WRAP_MASK);
}
FfxUInt32 FfxBrixelizerLoadBrickIDUniform(FfxUInt32 voxel_flat_id, FfxUInt32 cascade_id)
{
return LoadCascadeBrickMapArrayUniform(cascade_id, voxel_flat_id);
}
FfxUInt32x3 FfxBrixelizerGetSDFAtlasOffset(FfxUInt32 brick_id)
{
FfxUInt32 dim = 8;
FfxUInt32 offset = FfxBrixelizerBrickGetIndex(brick_id);
FfxUInt32 bperdim = FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE / dim;
FfxUInt32 xoffset = offset % bperdim;
FfxUInt32 yoffset = (offset / bperdim) % bperdim;
FfxUInt32 zoffset = (offset / bperdim / bperdim);
return FfxUInt32x3(xoffset, yoffset, zoffset) * dim;
}
struct FfxBxAtlasBounds
{
FfxUInt32 brick_dim;
FfxFloat32x3 uvw_min;
FfxFloat32x3 uvw_max;
};
FfxBxAtlasBounds FfxBrixelizerGetAtlasBounds(FfxUInt32 brick_id)
{
FfxUInt32x3 brick_offset = FfxBrixelizerGetSDFAtlasOffset(brick_id);
FfxBxAtlasBounds bounds;
bounds.brick_dim = FfxUInt32(8);
bounds.uvw_min = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(0.5)) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
bounds.uvw_max = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(float(8.0 - 0.5))) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
return bounds;
}
FfxFloat32 FfxBrixelizerSampleBrixelDistance(FfxUInt32 brick_id, FfxFloat32x3 uvw)
{
FfxUInt32 brick_dim = FfxUInt32(8);
FfxFloat32 idim = FfxFloat32(1.0) / FfxFloat32(brick_dim);
FfxUInt32 texture_offset = FfxBrixelizerBrickGetIndex(brick_id);
// Offset for 7x7x7 region
FfxUInt32x3 brick_offset = FfxBrixelizerGetSDFAtlasOffset(brick_id);
FfxFloat32x3 uvw_min = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(0.5)) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
FfxFloat32x3 uvw_max = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(FfxFloat32(brick_dim - FfxFloat32(0.5)))) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
uvw = ffxLerp(uvw_min, uvw_max, uvw);
return SampleSDFAtlas(uvw);
}
FfxFloat32 FfxBrixelizerSampleBrixelDistance(FfxFloat32x3 uvw_min, FfxFloat32x3 uvw_max, FfxFloat32x3 uvw)
{
uvw = ffxLerp(uvw_min, uvw_max, uvw);
return SampleSDFAtlas(uvw);
}
FfxFloat32x3 FfxBrixelizerGetBrixelGrad(FfxFloat32x3 uvw_min, FfxFloat32x3 uvw_max, FfxFloat32x3 uvw) {
FfxFloat32 EPS = FfxFloat32(0.25) / (FfxFloat32(8.0) - FfxFloat32(1.0));
FfxFloat32x4 k = FfxFloat32x4(1.0, 1.0, 1.0, 0.0);
if (uvw.x > FfxFloat32(0.5)) k.x = -k.x;
if (uvw.y > FfxFloat32(0.5)) k.y = -k.y;
if (uvw.z > FfxFloat32(0.5)) k.z = -k.z;
FfxFloat32 fcenter = FfxBrixelizerSampleBrixelDistance(uvw_min, uvw_max, uvw);
FfxFloat32x3 grad = normalize(
k.xww * (FfxBrixelizerSampleBrixelDistance(uvw_min, uvw_max, uvw + k.xww * EPS) - fcenter) +
k.wyw * (FfxBrixelizerSampleBrixelDistance(uvw_min, uvw_max, uvw + k.wyw * EPS) - fcenter) +
k.wwz * (FfxBrixelizerSampleBrixelDistance(uvw_min, uvw_max, uvw + k.wwz * EPS) - fcenter)
);
if (any(isnan(grad))) {
return normalize(uvw - FFX_BROADCAST_FLOAT32X3(0.5));
}
return grad;
}
#endif // FFX_BRIXELIZER_BRICK_COMMON_H

View File

@@ -0,0 +1,58 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_BRICK_COMMON_PRIVATE_H
#define FFX_BRIXELIZER_BRICK_COMMON_PRIVATE_H
#include "ffx_brixelizer_common_private.h"
#include "ffx_brixelizer_brick_common.h"
FfxUInt32 FfxBrixelizerVoxelGetIndex(FfxUInt32 voxel_id)
{
return voxel_id & FFX_BRIXELIZER_VOXEL_ID_MASK;
}
FfxUInt32 FfxBrixelizerGetVoxelCascade(FfxUInt32 voxel_id)
{
return voxel_id >> FFX_BRIXELIZER_CASCADE_ID_SHIFT;
}
FfxUInt32 WrapFlatCoords(FfxBrixelizerCascadeInfo CINFO, FfxUInt32 voxel_idx)
{
return FfxBrixelizerFlattenPOT((FfxBrixelizerUnflattenPOT(voxel_idx, FFX_BRIXELIZER_CASCADE_DEGREE) + CINFO.clipmap_offset) & FFX_BROADCAST_UINT32X3(FFX_BRIXELIZER_CASCADE_WRAP_MASK), FFX_BRIXELIZER_CASCADE_DEGREE);
}
FfxUInt32 FfxBrixelizerMakeBrickID(FfxUInt32 offset)
{
return offset;
}
FfxFloat32x3 FfxBrixelizerGetBrixelGrad(FfxUInt32 brick_id, FfxFloat32x3 uvw)
{
FfxFloat32 EPS = FfxFloat32(0.1) / (FfxFloat32(8.0) - FfxFloat32(1.0));
FfxUInt32x3 brick_offset = FfxBrixelizerGetSDFAtlasOffset(brick_id);
FfxFloat32x3 uvw_min = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(0.5)) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
FfxFloat32x3 uvw_max = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(float(8.0 - float(0.5)))) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
return FfxBrixelizerGetBrixelGrad(uvw_min, uvw_max, uvw);
}
#endif // FFX_BRIXELIZER_BRICK_COMMON_PRIVATE_H

View File

@@ -0,0 +1,39 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_BUILD_COMMON_H
#define FFX_BRIXELIZER_BUILD_COMMON_H
#include "ffx_brixelizer_common_private.h"
void FfxBrixelizerMarkBrickFree(FfxUInt32 brick_id)
{
StoreBricksVoxelMap(FfxBrixelizerBrickGetIndex(brick_id), FFX_BRIXELIZER_INVALID_ID);
}
FfxUInt32 FfxBrixelizerLoadBrickVoxelID(FfxUInt32 brick_id)
{
return LoadBricksVoxelMap(FfxBrixelizerBrickGetIndex(brick_id));
}
// FfxUInt32 FfxBrixelizerLoadBrickCascadeID(FfxUInt32 brick_id) { return LoadBricksVoxelMap(FfxBrixelizerBrickGetIndex(brick_id)) >> FFX_BRIXELIZER_CASCADE_ID_SHIFT; }
#endif // FFX_BRIXELIZER_BUILD_COMMON_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_COMMON_H
#define FFX_BRIXELIZER_COMMON_H
#include "../ffx_core.h"
#include "ffx_brixelizer_host_gpu_shared.h"
#define ffxassert(x)
FfxBoolean FfxBrixelizerIsValidID(FfxUInt32 id)
{
return (id & FFX_BRIXELIZER_INVALID_ID) != FFX_BRIXELIZER_INVALID_ID;
}
FfxBoolean FfxBrixelizerIntersectAABB(FfxFloat32x3 ray_origin, FfxFloat32x3 ray_invdir, FfxFloat32x3 box_min, FfxFloat32x3 box_max, FFX_PARAMETER_OUT FfxFloat32 hit_min, FFX_PARAMETER_OUT FfxFloat32 hit_max)
{
FfxFloat32x3 tbot = ray_invdir * (box_min - ray_origin);
FfxFloat32x3 ttop = ray_invdir * (box_max - ray_origin);
FfxFloat32x3 tmin = min(ttop, tbot);
FfxFloat32x3 tmax = max(ttop, tbot);
FfxFloat32x2 t = max(tmin.xx, tmin.yz);
FfxFloat32 t0 = max(t.x, t.y);
t = min(tmax.xx, tmax.yz);
FfxFloat32 t1 = min(t.x, t.y);
hit_min = max(t0, FfxFloat32(0.0));
hit_max = max(t1, FfxFloat32(0.0));
return hit_max > hit_min;
}
FfxUInt32 FfxBrixelizerFlattenPOT(FfxUInt32x3 voxel_coord, FfxUInt32 degree)
{
return voxel_coord.x | (voxel_coord.y << degree) | (voxel_coord.z << (2 * degree));
}
FfxUInt32x3 FfxBrixelizerUnflattenPOT(FfxUInt32 flat_bx_coord, FfxUInt32 degree)
{
return FfxUInt32x3(flat_bx_coord & ((FfxUInt32(1) << degree) - 1), (flat_bx_coord >> degree) & ((FfxUInt32(1) << degree) - 1), flat_bx_coord >> (2 * degree));
}
FfxUInt32 FfxBrixelizerPackUnsigned8Bits(FfxFloat32 a)
{
return FfxUInt32(ffxSaturate(a) * FfxFloat32(255.0)) & 0xffu;
}
FfxFloat32 FfxBrixelizerUnpackUnsigned8Bits(FfxUInt32 uval)
{
return FfxFloat32(uval & 0xff) / FfxFloat32(255.0);
}
FfxUInt32 PackUVWC(FfxFloat32x4 uvwc)
{
FfxUInt32 pack = //
(FfxBrixelizerPackUnsigned8Bits(uvwc.x) << 0) //
| (FfxBrixelizerPackUnsigned8Bits(uvwc.y) << 8) //
| (FfxBrixelizerPackUnsigned8Bits(uvwc.z) << 16) //
| (FfxBrixelizerPackUnsigned8Bits(uvwc.w) << 24); //
return pack;
}
FfxFloat32x2 FfxBrixelizerOctahedronToUV(FfxFloat32x3 N)
{
N.xy = FfxFloat32x2(N.xy) / dot(FFX_BROADCAST_FLOAT32X3(1.0), abs(N));
FfxFloat32x2 k;
k.x = N.x >= float(0.0) ? float(1.0) : -float(1.0);
k.y = N.y >= float(0.0) ? float(1.0) : -float(1.0);
if (N.z <= float(0.0)) N.xy = (float(1.0) - abs(FfxFloat32x2(N.yx))) * k;
return N.xy * float(0.5) + float(0.5);
}
FfxFloat32x3 FfxBrixelizerUVToOctahedron(FfxFloat32x2 UV)
{
UV = float(2.0) * (UV - float(0.5));
FfxFloat32x3 N = FfxFloat32x3(UV, float(1.0) - abs(UV.x) - abs(UV.y));
float t = max(-N.z, float(0.0));
FfxFloat32x2 k;
k.x = N.x >= float(0.0) ? -t : t;
k.y = N.y >= float(0.0) ? -t : t;
N.xy += k;
return normalize(N);
}
#endif // FFX_BRIXELIZER_COMMON_H

View File

@@ -0,0 +1,243 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_COMMON_PRIVATE_H
#define FFX_BRIXELIZER_COMMON_PRIVATE_H
#include "ffx_brixelizer_common.h"
#include "ffx_brixelizer_host_gpu_shared_private.h"
FfxInt32x3 to_int3(FfxUInt32x3 a) { return FfxInt32x3(FfxInt32(a.x), FfxInt32(a.y), FfxInt32(a.z)); }
FfxFloat32x3 to_float3(FfxUInt32x3 a) { return FfxFloat32x3(FfxFloat32(a.x), FfxFloat32(a.y), FfxFloat32(a.z)); }
FfxFloat32x3 to_float3(FfxInt32x3 a) { return FfxFloat32x3(FfxFloat32(a.x), FfxFloat32(a.y), FfxFloat32(a.z)); }
FfxUInt32 FfxBrixelizerPackDistance(FfxFloat32 distance)
{
FfxUInt32 uval = ffxAsUInt32(distance);
FfxUInt32 sign_bit = uval >> FfxUInt32(31);
return (uval << 1) | sign_bit;
}
FfxFloat32 FfxBrixelizerUnpackDistance(FfxUInt32 uval)
{
FfxUInt32 sign_bit = (uval & 1);
return ffxAsFloat((uval >> FfxUInt32(1)) | (sign_bit << FfxUInt32(31)));
}
// Returns the minimal absolute value with its sign unchanged
FfxFloat32 FfxBrixelizerUnsignedMin(FfxFloat32 a, FfxFloat32 b) { return abs(a) < abs(b) ? a : b; }
// sign without zero
FfxFloat32 FfxBrixelizerGetSign(FfxFloat32 v) { return v < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0); }
FfxFloat32 dot2(FfxFloat32x3 v) { return dot(v, v); }
FfxFloat32 dot2(FfxFloat32x2 v) { return dot(v, v); }
// https://www.shadertoy.com/view/4sXXRN
// The MIT License
// Copyright © 2014 Inigo Quilez
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// It computes the distance to a triangle.
//
// See here: http://iquilezles.org/www/articles/triangledistance/triangledistance.htm
//
// In case a mesh was rendered, only one square root would be needed for the
// whole mesh. In this example the triangle is given a thckness of 0.01 units
// for display purposes. Like the square root, this thickness should be added
// only once for the whole mesh too.
FfxFloat32 CalculateDistanceToTriangle(FfxFloat32x3 p, FfxFloat32x3 a, FfxFloat32x3 b, FfxFloat32x3 c) {
FfxFloat32x3 ba = b - a;
FfxFloat32x3 pa = p - a;
FfxFloat32x3 cb = c - b;
FfxFloat32x3 pb = p - b;
FfxFloat32x3 ac = a - c;
FfxFloat32x3 pc = p - c;
FfxFloat32x3 nor = cross(ba, ac);
return sqrt( //
(sign(dot(cross(ba, nor), pa)) + //
sign(dot(cross(cb, nor), pb)) + //
sign(dot(cross(ac, nor), pc)) < //
FfxFloat32(2.0)) //
? //
min(min( //
dot2(ba * ffxSaturate(dot(ba, pa) / dot2(ba)) - pa), //
dot2(cb * ffxSaturate(dot(cb, pb) / dot2(cb)) - pb)), //
dot2(ac * ffxSaturate(dot(ac, pc) / dot2(ac)) - pc)) //
: //
dot(nor, pa) * dot(nor, pa) / dot2(nor) //
); //
}
FfxFloat32 CalculateDistanceToTriangleSquared(FfxFloat32x3 ba, //
FfxFloat32x3 pa, //
FfxFloat32x3 cb, //
FfxFloat32x3 pb, //
FfxFloat32x3 ac, //
FfxFloat32x3 pc, //
FfxFloat32x3 nor, //
FfxFloat32x3 cross_ba_nor, //
FfxFloat32x3 cross_cb_nor, //
FfxFloat32x3 cross_ac_nor, //
FfxFloat32 dot2_ba, //
FfxFloat32 dot2_cb, //
FfxFloat32 dot2_ac, //
FfxFloat32 dot2_nor //
) {
return //
( //
(sign(dot(cross_ba_nor, pa)) + //
sign(dot(cross_cb_nor, pb)) + //
sign(dot(cross_ac_nor, pc)) < //
FfxFloat32(2.0)) //
? //
min(min( //
dot2(ba * ffxSaturate(dot(ba, pa) / dot2_ba) - pa), //
dot2(cb * ffxSaturate(dot(cb, pb) / dot2_cb) - pb)), //
dot2(ac * ffxSaturate(dot(ac, pc) / dot2_ac) - pc)) //
: //
dot(nor, pa) * dot(nor, pa) / dot2_nor //
); //
}
#define brixelizerreal FfxFloat32
#define brixelizerreal2 FfxFloat32x2
#define brixelizerreal3 FfxFloat32x3
#define brixelizerreal4 FfxFloat32x4
#ifdef FFX_HLSL
# define brixelizerreal3x2 float3x2
#else
# define brixelizerreal3x2 mat3x2
#endif
brixelizerreal3 to_brixelizerreal3(FfxUInt32x3 a) { return brixelizerreal3(brixelizerreal(a.x), brixelizerreal(a.y), brixelizerreal(a.z)); }
// Offsets the plane equation for the nearest grid point
brixelizerreal FfxBrixelizerOffsetByMax(brixelizerreal de, brixelizerreal2 ne, brixelizerreal offset)
{
de += max(FfxFloat32(0.0), ne.x) + abs(ne.x * offset);
de += max(FfxFloat32(0.0), ne.y) + abs(ne.y * offset);
return de;
}
// Offsets the plane equation for the next grid point
brixelizerreal FfxBrixelizerOffsetByMin(brixelizerreal de, brixelizerreal2 ne, brixelizerreal offset)
{
de += min(FfxFloat32(0.0), ne.x) - abs(ne.x * offset);
de += min(FfxFloat32(0.0), ne.y) - abs(ne.x * offset);
return de;
}
void FfxBrixelizerGet2DEdge(FFX_PARAMETER_OUT brixelizerreal2 ne,
FFX_PARAMETER_OUT brixelizerreal de,
brixelizerreal orientation,
brixelizerreal edge_x,
brixelizerreal edge_y,
brixelizerreal vertex_x,
brixelizerreal vertex_y,
brixelizerreal offset)
{
ne = brixelizerreal2(-orientation * edge_y, orientation * edge_x);
de = -(ne.x * vertex_x + ne.y * vertex_y);
de = FfxBrixelizerOffsetByMax(de, ne, offset);
}
void FfxBrixelizerGet2DEdges(
FFX_PARAMETER_OUT brixelizerreal3 de_xy,
FFX_PARAMETER_OUT brixelizerreal3x2 ne_xy,
FFX_PARAMETER_OUT brixelizerreal3 de_xz,
FFX_PARAMETER_OUT brixelizerreal3x2 ne_xz,
FFX_PARAMETER_OUT brixelizerreal3 de_yz,
FFX_PARAMETER_OUT brixelizerreal3x2 ne_yz,
FFX_PARAMETER_OUT brixelizerreal3 gn,
brixelizerreal3 TRIANGLE_VERTEX_0,
brixelizerreal3 TRIANGLE_VERTEX_1,
brixelizerreal3 TRIANGLE_VERTEX_2,
brixelizerreal offset,
bool invert)
{
brixelizerreal3 e0 = TRIANGLE_VERTEX_1.xyz - TRIANGLE_VERTEX_0.xyz;
brixelizerreal3 e1 = TRIANGLE_VERTEX_2.xyz - TRIANGLE_VERTEX_1.xyz;
brixelizerreal3 e2 = TRIANGLE_VERTEX_0.xyz - TRIANGLE_VERTEX_2.xyz;
if (invert) {
e0 = -e0;
e1 = -e1;
e2 = -e2;
}
gn = normalize(cross(e2, e0));
brixelizerreal orientation_xy = brixelizerreal(gn.z < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
FfxBrixelizerGet2DEdge(/* out */ ne_xy[0], /* out */ de_xy[0], orientation_xy, e0.x, e0.y, TRIANGLE_VERTEX_0.x, TRIANGLE_VERTEX_0.y, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_xy[1], /* out */ de_xy[1], orientation_xy, e1.x, e1.y, TRIANGLE_VERTEX_1.x, TRIANGLE_VERTEX_1.y, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_xy[2], /* out */ de_xy[2], orientation_xy, e2.x, e2.y, TRIANGLE_VERTEX_2.x, TRIANGLE_VERTEX_2.y, offset);
brixelizerreal orientation_xz = brixelizerreal(gn.y > FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
FfxBrixelizerGet2DEdge(/* out */ ne_xz[0], /* out */ de_xz[0], orientation_xz, e0.x, e0.z, TRIANGLE_VERTEX_0.x, TRIANGLE_VERTEX_0.z, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_xz[1], /* out */ de_xz[1], orientation_xz, e1.x, e1.z, TRIANGLE_VERTEX_1.x, TRIANGLE_VERTEX_1.z, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_xz[2], /* out */ de_xz[2], orientation_xz, e2.x, e2.z, TRIANGLE_VERTEX_2.x, TRIANGLE_VERTEX_2.z, offset);
brixelizerreal orientation_yz = brixelizerreal(gn.x < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
FfxBrixelizerGet2DEdge(/* out */ ne_yz[0], /* out */ de_yz[0], orientation_yz, e0.y, e0.z, TRIANGLE_VERTEX_0.y, TRIANGLE_VERTEX_0.z, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_yz[1], /* out */ de_yz[1], orientation_yz, e1.y, e1.z, TRIANGLE_VERTEX_1.y, TRIANGLE_VERTEX_1.z, offset);
FfxBrixelizerGet2DEdge(/* out */ ne_yz[2], /* out */ de_yz[2], orientation_yz, e2.y, e2.z, TRIANGLE_VERTEX_2.y, TRIANGLE_VERTEX_2.z, offset);
}
bool FfxBrixelizerEvalEdge(brixelizerreal2 vertex, brixelizerreal3 de, brixelizerreal3x2 ne)
{
return (ne[0].x * vertex.x + ne[0].y * vertex.y + de[0] >= brixelizerreal(FfxFloat32(0.0))) &&
(ne[1].x * vertex.x + ne[1].y * vertex.y + de[1] >= brixelizerreal(FfxFloat32(0.0))) &&
(ne[2].x * vertex.x + ne[2].y * vertex.y + de[2] >= brixelizerreal(FfxFloat32(0.0)));
}
// We need those non-POT versions around for culling
FfxUInt32x3 FfxBrixelizerUnflatten(FfxUInt32 flat_bx_coord, FfxUInt32x3 dim)
{
return FfxUInt32x3(flat_bx_coord % dim.x, (flat_bx_coord / dim.x) % dim.y, flat_bx_coord / (dim.x * dim.y));
}
FfxUInt32x2 FfxBrixelizerUnflatten(FfxUInt32 flat_bx_coord, FfxUInt32x2 dim)
{
return FfxUInt32x2(flat_bx_coord % dim.x, (flat_bx_coord / dim.x) % dim.y);
}
FfxUInt32 FfxBrixelizerFlatten(FfxUInt32x3 voxel_coord, FfxUInt32x3 dim)
{
return voxel_coord.x + voxel_coord.y * dim.x + voxel_coord.z * dim.x * dim.y;
}
#endif // FFX_BRIXELIZER_COMMON_PRIVATE_H

View File

@@ -0,0 +1,306 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_CONTEXT_OPS_H
#define FFX_BRIXELIZER_CONTEXT_OPS_H
#include "ffx_brixelizer_host_gpu_shared_private.h"
#include "ffx_brixelizer_brick_common_private.h"
#include "ffx_brixelizer_build_common.h"
#include "ffx_brixelizer_common_private.h"
void FfxBrixelizerAppendClearBrick(FfxUInt32 brick_id)
{
FfxUInt32 offset;
IncrementContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_CLEAR_BRICKS, FfxUInt32(1), offset);
StoreBricksClearList(offset, brick_id);
}
void FfxBrixelizerAppendDirtyBrick(FfxUInt32 brick_id)
{
FfxUInt32 offset;
IncrementContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_DIRTY_BRICKS, FfxUInt32(1), offset);
StoreBricksDirtyList(offset, brick_id);
}
void FfxBrixelizerClearCounters()
{
for (FfxUInt32 i = 0; i < FFX_BRIXELIZER_NUM_CONTEXT_COUNTERS; i++) {
StoreContextCounter(i, FfxUInt32(0));
}
}
void FfxBrixelizerAddBrickToFreeList(FfxUInt32 brick_id)
{
FfxUInt32 offset;
IncrementContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_FREE_BRICKS, FfxUInt32(1), offset);
StoreBricksFreeList(offset, brick_id);
}
FfxFloat32 FfxBrixelizerLoadBrixelDist(FfxUInt32 brick_id, FfxInt32x3 coord)
{
if (any(FFX_GREATER_THAN(coord, FFX_BROADCAST_INT32X3(7))) || any(FFX_LESS_THAN(coord, FFX_BROADCAST_INT32X3(0)))) return FfxFloat32(1.0);
return LoadSDFAtlas(FfxBrixelizerGetSDFAtlasOffset(brick_id) + coord);
}
void FfxBrixelizerStoreBrixelDist(FfxUInt32 brick_id, FfxUInt32x3 coord, FfxFloat32 dist)
{
StoreSDFAtlas(FfxBrixelizerGetSDFAtlasOffset(brick_id) + coord, clamp(dist, FfxFloat32(0.0), FfxFloat32(1.0)));
}
void FfxBrixelizerClearBrick(FfxUInt32 brick_id, FfxUInt32x3 voxel_coord)
{
FfxBrixelizerStoreBrixelDist(brick_id, voxel_coord, FfxFloat32(1.0));
}
FfxFloat32 FfxBrixelizerEikonalMin(FfxFloat32 a, FfxFloat32 b)
{
return FfxBrixelizerUnsignedMin(a, b);
}
// Eikonal solver, enforce |gradient|==d
// Generic form for n dimensions:
// U = 1/n * (sum(U_i) + sqrt(sum(U_i) * sum(U_i) - n * (sum(U_i * U_i) - D)))
// when sqrt is non real then fall back to min of lower dimensions
FfxFloat32 FfxBrixelizerEikonal1D(FfxFloat32 x, FfxFloat32 y, FfxFloat32 z, FfxFloat32 d)
{
FfxFloat32 xyz = FfxBrixelizerEikonalMin(x, FfxBrixelizerEikonalMin(y, z));
return (xyz + d * FfxBrixelizerGetSign(xyz));
}
FfxFloat32 FfxBrixelizerEikonal2D(FfxFloat32 x, FfxFloat32 y, FfxFloat32 d)
{
const FfxFloat32 k = FfxFloat32(1.0) / FfxFloat32(2.0);
FfxFloat32 xy = x + y;
FfxFloat32 v = xy * xy - FfxFloat32(2.0) * (x * x + y * y - d * d);
if (v < FfxFloat32(0.0)) return FfxFloat32(1.0);
return k * (xy + sqrt(v) * FfxBrixelizerGetSign(xy));
}
FfxFloat32 FfxBrixelizerEikonal3D(FfxFloat32 x, FfxFloat32 y, FfxFloat32 z, FfxFloat32 d)
{
const FfxFloat32 k = FfxFloat32(1.0) / FfxFloat32(3.0);
FfxFloat32 xyz = x + y + z;
FfxFloat32 v = xyz * xyz - FfxFloat32(3.0) * (x * x + y * y + z * z - d * d);
if (v < FfxFloat32(0.0)) return FfxFloat32(1.0);
return k * (xyz + sqrt(v) * FfxBrixelizerGetSign(xyz));
}
FFX_GROUPSHARED FfxFloat32 lds_eikonal_sdf_cache[512];
FfxFloat32 FfxBrixelizerLDSLoadSDF(FfxInt32x3 coord)
{
if (any(FFX_LESS_THAN(coord, FFX_BROADCAST_INT32X3(0))) || any(FFX_GREATER_THAN(coord, FFX_BROADCAST_INT32X3(7)))) return FfxFloat32(1.0);
return lds_eikonal_sdf_cache[FfxUInt32(coord.x) + FfxUInt32(coord.y) * FfxUInt32(8) + FfxUInt32(coord.z) * FfxUInt32(8 * 8)];
}
void FfxBrixelizerLDSStoreSDF(FfxInt32x3 coord, FfxFloat32 sdf)
{
lds_eikonal_sdf_cache[FfxUInt32(coord.x) + FfxUInt32(coord.y) * FfxUInt32(8) + FfxUInt32(coord.z) * FfxUInt32(8 * 8)] = sdf;
}
// Collects a list of bricks to clear for indirect args
// those don't have a brick_id->voxel_id mapping are considered free
// those that got eikonal counter are considered dirty as they had something baked in them
// DEFINE_ENTRY(64, 1, 1, CollectClearBricks)
void FfxBrixelizerCollectClearBricks(FfxUInt32 brick_offset)
{
if (brick_offset >= GetContextInfoNumBricks()) return;
FfxUInt32 brick_id = FfxBrixelizerMakeBrickID(brick_offset);
FfxUInt32 dim = 8;
FfxUInt32 voxel_id = FfxBrixelizerLoadBrickVoxelID(brick_id);
FfxUInt32 voxel_idx = FfxBrixelizerVoxelGetIndex(voxel_id);
FfxUInt32 cascade_id = FfxBrixelizerGetVoxelCascade(voxel_id);
FfxUInt32 eikonal_counter = LoadBricksEikonalCounters(brick_id);
// @TODO cleanup this mess
if (GetBuildInfoDoInitialization() > 0) {
StoreBricksEikonalCounters(brick_id, 0);
FfxBrixelizerMarkBrickFree(brick_id);
FfxBrixelizerAddBrickToFreeList(brick_id);
FfxBrixelizerAppendClearBrick(brick_id);
} else {
#ifdef FFX_BRIXELIZER_DEBUG_FORCE_REBUILD
StoreBricksEikonalCounters(brick_id, 0);
FfxBrixelizerMarkBrickFree(brick_id);
FfxBrixelizerAddBrickToFreeList(brick_id);
FfxBrixelizerAppendClearBrick(brick_id);
#else // !FFX_BRIXELIZER_DEBUG_FORCE_REBUILD
if (FfxBrixelizerIsInvalidID(voxel_id)) {
FfxBrixelizerAddBrickToFreeList(brick_id);
if (eikonal_counter > 0) { // Means there's been some baking using this brick so need to clear
FfxBrixelizerAppendClearBrick(brick_id);
StoreBricksEikonalCounters(brick_id, 0);
}
}
#endif // !FFX_BRIXELIZER_DEBUG_FORCE_REBUILD
}
}
void FfxBrixelizerPrepareClearBricks()
{
FfxUInt32 tier_cnt = LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_CLEAR_BRICKS);
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_CLEAR_BRICKS_32 + FfxUInt32(0), tier_cnt * FfxUInt32(1 << (3)));
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_CLEAR_BRICKS_32 + FfxUInt32(1), FfxUInt32(1));
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_CLEAR_BRICKS_32 + FfxUInt32(2), FfxUInt32(1));
}
void FfxBrixelizerClearBrickEntry(FfxUInt32 gtid, FfxUInt32 group_id)
{
FfxUInt32 brick_offset = group_id.x >> (3);
FfxUInt32 stamp_id = group_id.x & ((1 << (3)) - 1);
FfxUInt32 brick_id = LoadBricksClearList(brick_offset);
FfxUInt32 brick_dim = 8;
FfxUInt32x3 local_coord = FfxBrixelizerUnflattenPOT(gtid, 2) + FfxBrixelizerUnflattenPOT(stamp_id, 1) * FfxUInt32(4);
FfxBrixelizerClearBrick(brick_id, local_coord);
}
void FfxBrixelizerCollectDirtyBricks(FfxUInt32 brick_offset)
{
FfxUInt32 brick_id = FfxBrixelizerMakeBrickID(brick_offset);
FfxUInt32 eikonal_counter = LoadBricksEikonalCounters(brick_id);
FfxUInt32 dim = 8;
FfxUInt32 voxel_id = FfxBrixelizerLoadBrickVoxelID(brick_id);
if (FfxBrixelizerIsValidID(voxel_id)) {
FfxUInt32 voxel_idx = FfxBrixelizerVoxelGetIndex(voxel_id);
FfxUInt32 cascade_idx = FfxBrixelizerGetVoxelCascade(voxel_id);
FfxUInt32x3 clipmap_offset = GetContextInfoCascadeClipmapOffset(cascade_idx);
FfxUInt32x3 voxel_offset = FfxBrixelizerUnflattenPOT(voxel_idx, FFX_BRIXELIZER_CASCADE_DEGREE);
FfxUInt32 wrapped_voxel_idx = FfxBrixelizerFlattenPOT(FfxBrixelizerWrapCoords(FfxInt32x3(clipmap_offset), FFX_BRIXELIZER_CASCADE_WRAP_MASK, voxel_offset), FFX_BRIXELIZER_CASCADE_DEGREE);
if (eikonal_counter < 16) {
FfxBrixelizerAppendDirtyBrick(brick_id);
StoreBricksEikonalCounters(brick_id, eikonal_counter + 16);
}
}
}
// DEFINE_ENTRY(512, 1, 1, Eikonal)
void FfxBrixelizerEikonal(FfxUInt32 local_coord_packed, FfxUInt32 brick_offset)
{
FfxUInt32 brick_id = LoadBricksDirtyList(brick_offset);
FfxUInt32 voxel_id = FfxBrixelizerLoadBrickVoxelID(brick_id);
FfxUInt32x3 local_coord = FfxBrixelizerUnflattenPOT(local_coord_packed, 3);
if (FfxBrixelizerIsValidID(voxel_id)) {
FfxFloat32 cell_distance = FfxFloat32(1.0) / (FfxFloat32(8));
FfxFloat32 e = FfxBrixelizerLoadBrixelDist(brick_id, FfxInt32x3(local_coord));
FfxBrixelizerLDSStoreSDF(FfxInt32x3(local_coord), e);
FFX_GROUP_MEMORY_BARRIER;
for (FfxUInt32 j = FfxUInt32(0); j < FfxUInt32(3); j++) {
for (FfxUInt32 i = FfxUInt32(0); i < FfxUInt32(4); i++) {
FfxUInt32 d = FfxUInt32(1) << (FfxUInt32(3) - i);
FfxFloat32x3 min_dists = FFX_BROADCAST_FLOAT32X3(FfxFloat32(1.0));
min_dists.x = FfxBrixelizerEikonalMin(FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(d, 0, 0)), FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(-d, 0, 0)));
min_dists.y = FfxBrixelizerEikonalMin(FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(0, d, 0)), FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(0, -d, 0)));
min_dists.z = FfxBrixelizerEikonalMin(FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(0, 0, d)), FfxBrixelizerLDSLoadSDF(FfxInt32x3(local_coord) + FfxInt32x3(0, 0, -d)));
min_dists = abs(min_dists);
FfxFloat32 e10 = FfxBrixelizerEikonal1D(min_dists.x, min_dists.y, min_dists.z, d * cell_distance);
FfxFloat32 e20 = FfxBrixelizerEikonal2D(min_dists.x, min_dists.y, d * cell_distance);
FfxFloat32 e21 = FfxBrixelizerEikonal2D(min_dists.x, min_dists.z, d * cell_distance);
FfxFloat32 e22 = FfxBrixelizerEikonal2D(min_dists.z, min_dists.y, d * cell_distance);
FfxFloat32 e30 = FfxBrixelizerEikonal3D(min_dists.x, min_dists.y, min_dists.z, d * cell_distance);
e = FfxBrixelizerEikonalMin(e, FfxBrixelizerEikonalMin(e10, FfxBrixelizerEikonalMin(e20, FfxBrixelizerEikonalMin(e21, FfxBrixelizerEikonalMin(e22, e30)))));
e = FfxBrixelizerEikonalMin(e, e10);
FfxBrixelizerLDSStoreSDF(FfxInt32x3(local_coord), e);
}
}
FfxBrixelizerStoreBrixelDist(brick_id, local_coord, e);
}
}
void FfxBrixelizerMergeBricks(FfxUInt32 gtid, FfxUInt32 group_id)
{
FfxUInt32 cnt = LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_MERGE_BRICKS);
FfxUInt32 merge_idx = group_id / FfxUInt32(8);
FfxUInt32 stamp_idx = group_id % FfxUInt32(8);
FfxUInt32 voxel_idx = gtid + stamp_idx * FfxUInt32(64);
FfxUInt32x3 voxel_offset = FfxBrixelizerUnflattenPOT(voxel_idx, FfxUInt32(3));
if (merge_idx >= cnt) return;
FfxUInt32 brick_A = LoadBricksMergeList(merge_idx * FfxUInt32(2) + FfxUInt32(0));
FfxUInt32 brick_B = LoadBricksMergeList(merge_idx * FfxUInt32(2) + FfxUInt32(1));
FfxUInt32x3 atlas_offset_A = FfxBrixelizerGetSDFAtlasOffset(brick_A);
FfxUInt32x3 atlas_offset_B = FfxBrixelizerGetSDFAtlasOffset(brick_B);
{
FfxFloat32 sdf_val_A = LoadSDFAtlas(atlas_offset_A + voxel_offset);
FfxFloat32 sdf_val_B = LoadSDFAtlas(atlas_offset_B + voxel_offset);
StoreSDFAtlas(atlas_offset_B + voxel_offset, min(sdf_val_A, sdf_val_B));
}
}
void FfxBrixelizerMergeCascades(FfxUInt32 voxel_idx)
{
// Assume the same clipmap state so no need to wrap the coords
FfxUInt32 brick_A = LoadCascadeBrickMapArrayUniform(GetBuildInfo().src_cascade_A, voxel_idx);
FfxUInt32 brick_B = LoadCascadeBrickMapArrayUniform(GetBuildInfo().src_cascade_B, voxel_idx);
if (FfxBrixelizerIsValidID(brick_A) && FfxBrixelizerIsValidID(brick_B)) {
FfxUInt32 offset;
IncrementContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_MERGE_BRICKS, FfxUInt32(1), /* out */ offset);
StoreBricksMergeList(offset * FfxUInt32(2) + FfxUInt32(0), brick_A);
StoreBricksMergeList(offset * FfxUInt32(2) + FfxUInt32(1), brick_B);
StoreCascadeBrickMapArrayUniform(GetBuildInfo().dst_cascade, voxel_idx, brick_B); // we store the 2nd brick and merge into it
FfxUInt32 brick_A_aabb_pack = LoadBricksAABB(FfxBrixelizerBrickGetIndex(brick_A));
FfxUInt32x3 brick_A_aabb_umin = FfxBrixelizerUnflattenPOT(brick_A_aabb_pack & ((FfxUInt32(1) << FfxUInt32(9)) - FfxUInt32(1)), FfxUInt32(3));
FfxUInt32x3 brick_A_aabb_umax = FfxBrixelizerUnflattenPOT((brick_A_aabb_pack >> FfxUInt32(9)) & ((FfxUInt32(1) << FfxUInt32(9)) - FfxUInt32(1)), FfxUInt32(3));
FfxUInt32 brick_B_aabb_pack = LoadBricksAABB(FfxBrixelizerBrickGetIndex(brick_B));
FfxUInt32x3 brick_B_aabb_umin = FfxBrixelizerUnflattenPOT(brick_B_aabb_pack & ((FfxUInt32(1) << FfxUInt32(9)) - FfxUInt32(1)), FfxUInt32(3));
FfxUInt32x3 brick_B_aabb_umax = FfxBrixelizerUnflattenPOT((brick_B_aabb_pack >> FfxUInt32(9)) & ((FfxUInt32(1) << FfxUInt32(9)) - FfxUInt32(1)), FfxUInt32(3));
brick_B_aabb_umin = min(brick_A_aabb_umin, brick_B_aabb_umin);
brick_B_aabb_umax = max(brick_A_aabb_umax, brick_B_aabb_umax);
brick_B_aabb_pack = FfxBrixelizerFlattenPOT(brick_B_aabb_umin, 3) | (FfxBrixelizerFlattenPOT(brick_B_aabb_umax, 3) << 9);
StoreBricksAABB(FfxBrixelizerBrickGetIndex(brick_B), brick_B_aabb_pack);
} else if (brick_B == FFX_BRIXELIZER_UNINITIALIZED_ID || brick_A == FFX_BRIXELIZER_UNINITIALIZED_ID) {
StoreCascadeBrickMapArrayUniform(GetBuildInfo().dst_cascade, voxel_idx, FFX_BRIXELIZER_UNINITIALIZED_ID);
} else if (FfxBrixelizerIsValidID(brick_B)) {
StoreCascadeBrickMapArrayUniform(GetBuildInfo().dst_cascade, voxel_idx, brick_B);
} else {
StoreCascadeBrickMapArrayUniform(GetBuildInfo().dst_cascade, voxel_idx, brick_A);
}
}
void FfxBrixelizerPrepareEikonalArgs()
{
FfxUInt32 tier_cnt = LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_DIRTY_BRICKS);
StoreContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_DIRTY_BRICKS, 0);
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_EIKONAL_32 + 0, tier_cnt);
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_EIKONAL_32 + FfxUInt32(1), 1);
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_EIKONAL_32 + 2, 1);
}
void FfxBrixelizerPrepareMergeBricksArgs()
{
FfxUInt32 cnt = LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_MERGE_BRICKS);
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_MERGE_BRICKS_32 + FfxUInt32(0), cnt * FfxUInt32(8)); // 2^3 of 4^3 lanes
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_MERGE_BRICKS_32 + FfxUInt32(1), FfxUInt32(1));
StoreIndirectArgs(FFX_BRIXELIZER_INDIRECT_OFFSETS_MERGE_BRICKS_32 + FfxUInt32(2), FfxUInt32(1));
}
#endif // ifndef FFX_BRIXELIZER_CONTEXT_OPS_H

View File

@@ -0,0 +1,105 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffx_brixelizer_common.h"
#include "ffx_brixelizer_host_gpu_shared.h"
void PushAABB(FfxBrixelizerDebugAABB aabb)
{
FfxUInt32 offset;
IncrementContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_NUM_DEBUG_AABBS, 1, offset);
if (offset < GetDebugInfoMaxAABBs()) {
StoreDebugAABB(offset, aabb);
}
}
void FfxBrixelizerDrawAABBTreeAABB(FfxUInt32 aabb_index)
{
// if g_debug_info.debug_state is set to 1 we only want to draw the cascade bounding box
if (GetDebugInfoDebugState() == 1 && aabb_index > 0) {
return;
}
if (aabb_index == 0) {
FfxBrixelizerCascadeInfo cascade_info = GetCascadeInfo();
FfxBrixelizerDebugAABB debug_aabb;
debug_aabb.color = FfxFloat32x3(1.0f, 0.0f, 0.0f);
debug_aabb.aabbMin = cascade_info.grid_min;
debug_aabb.aabbMax = cascade_info.grid_max;
PushAABB(debug_aabb);
} else if (aabb_index == 1) {
// root aabb
FfxUInt32 index = 16*16*16 + 4*4*4*6;
FfxBrixelizerDebugAABB debug_aabb;
debug_aabb.color = FfxFloat32x3(0.0f, 1.0f, 1.0f);
debug_aabb.aabbMin = LoadCascadeAABBTreeFloat3(index);
debug_aabb.aabbMax = LoadCascadeAABBTreeFloat3(index + 3);
PushAABB(debug_aabb);
} else if (aabb_index <= 1 + 4*4*4) {
// second level aabb
FfxUInt32 index = 16*16*16 + (aabb_index - 2)*6;
FfxBrixelizerDebugAABB debug_aabb;
debug_aabb.color = FfxFloat32x3(1.0f, 1.0f, 0.0f);
debug_aabb.aabbMin = LoadCascadeAABBTreeFloat3(index);
debug_aabb.aabbMax = LoadCascadeAABBTreeFloat3(index + 3);
if (ffxAsUInt32(debug_aabb.aabbMin.x) == ffxAsUInt32(debug_aabb.aabbMax.x)) {
return;
}
PushAABB(debug_aabb);
} else if (aabb_index <= 1 + 4*4*4 + 16*16*16) {
// leaf aabb
FfxBrixelizerCascadeInfo cascade_info = GetCascadeInfo();
FfxUInt32 index = aabb_index - (4*4*4 + 1 + 1);
FfxUInt32 packedAABB = LoadCascadeAABBTreeUInt(index);
if (packedAABB == FFX_BRIXELIZER_INVALID_BOTTOM_AABB_NODE) {
return;
}
FfxUInt32x3 leaf_offset = FfxBrixelizerUnflattenPOT(index, 4) * 32;
FfxUInt32x3 aabbMin = leaf_offset + FfxBrixelizerUnflattenPOT(packedAABB & ((1 << 15) - 1), 5);
FfxUInt32x3 aabbMax = leaf_offset + FfxBrixelizerUnflattenPOT((packedAABB >> 16) & ((1 << 15) - 1), 5) + 1;
FfxBrixelizerDebugAABB debug_aabb;
debug_aabb.color = FfxFloat32x3(0.0f, 1.0f, 0.0f);
debug_aabb.aabbMin = cascade_info.grid_min + FfxFloat32x3(aabbMin) * cascade_info.voxel_size / 8.0f;
debug_aabb.aabbMax = cascade_info.grid_min + FfxFloat32x3(aabbMax) * cascade_info.voxel_size / 8.0f;
PushAABB(debug_aabb);
}
}
void FfxBrixelizerDrawInstanceAABB(FfxUInt32 index)
{
// XXX -- use debug_state to pass in number of instance IDs
if (index >= GetDebugInfoDebugState()) {
return;
}
FfxUInt32 instance_id = GetDebugInstanceID(index);
FfxBrixelizerInstanceInfo instance_info = LoadInstanceInfo(instance_id);
FfxBrixelizerDebugAABB debug_aabb;
debug_aabb.color = FfxFloat32x3(0.0f, 0.0f, 1.0f);
debug_aabb.aabbMin = instance_info.aabbMin;
debug_aabb.aabbMax = instance_info.aabbMax;
PushAABB(debug_aabb);
}

View File

@@ -0,0 +1,199 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_DEBUG_VISUALIZATION_H
#define FFX_BRIXELIZER_DEBUG_VISUALIZATION_H
#include "ffx_brixelizer_host_gpu_shared.h"
#define FFX_BRIXELIZER_TRAVERSAL_EPS (GetDebugInfoPreviewSDFSolveEpsilon() / FfxFloat32(8.0))
#include "ffx_brixelizer_trace_ops.h"
// XXX -- tmp
FfxUInt32 FfxBrixelizerGetVoxelCascade(FfxUInt32 voxel_id)
{
return voxel_id >> FFX_BRIXELIZER_CASCADE_ID_SHIFT;
}
#define FLT_INF 1e30f
// By Morgan McGuire @morgan3d, http://graphicscodex.com
// Reuse permitted under the BSD license.
// https://www.shadertoy.com/view/4dsSzr
FfxFloat32x3 FFX_HeatmapGradient(FfxFloat32 t)
{
return clamp((pow(t, 1.5) * 0.8 + 0.2) * FfxFloat32x3(smoothstep(0.0, 0.35, t) + t * 0.5, smoothstep(0.5, 1.0, t), max(1.0 - t * 1.7, t * 7.0 - 6.0)), 0.0, 1.0);
}
// License?
FfxFloat32x3 FFX_RandomColor(FfxFloat32x2 uv) {
uv = ffxFract(uv * FfxFloat32(15.718281828459045));
FfxFloat32x3 seeds = FfxFloat32x3(FfxFloat32(0.123), FfxFloat32(0.456), FfxFloat32(0.789));
seeds = ffxFract((uv.x + FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.x, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
seeds = ffxFract((uv.y + FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.y, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
seeds = ffxFract((FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.x, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
return seeds;
}
FfxFloat32x3 FFX_ViewSpaceToWorldSpace(FfxFloat32x4 view_space_coord)
{
return FFX_TRANSFORM_VECTOR(GetDebugInfoInvView(), view_space_coord).xyz;
}
FfxFloat32x3 FFX_InvProjectPosition(FfxFloat32x3 coord, FfxFloat32x4x4 mat)
{
coord.y = (FfxFloat32(1.0) - coord.y);
coord.xy = FfxFloat32(2.0) * coord.xy - 1;
FfxFloat32x4 projected = FFX_TRANSFORM_VECTOR(mat, FfxFloat32x4(coord, 1));
projected.xyz /= projected.w;
return projected.xyz;
}
FfxFloat32x3 FFX_ScreenSpaceToViewSpace(FfxFloat32x3 screen_uv_coord)
{
return FFX_InvProjectPosition(screen_uv_coord, GetDebugInfoInvProj());
}
FfxFloat32 FFX_HitEdgeDist(FfxFloat32x3 hit, FfxFloat32x3 boxMin, FfxFloat32x3 boxMax)
{
FfxFloat32x3 a = min(abs(hit - boxMin), abs(hit - boxMax));
return min(min(a.x + a.y, a.x + a.z), a.y + a.z);
}
// modified from inigo quilez
FfxFloat32 FFX_BoxHitDist(FfxUInt32x2 tid, FfxFloat32x3 ro, FfxFloat32x3 rd, FfxFloat32x3 boxMin, FfxFloat32x3 boxMax)
{
FfxFloat32x3 halfSize = (boxMax - boxMin) / 2.0f;
FfxFloat32x3 center = boxMin + halfSize;
FfxFloat32x3 rop = ro - center;
FfxFloat32x3 ird = 1.0f / rd;
FfxFloat32x3 n = rop * ird;
FfxFloat32x3 k = abs(ird) * halfSize;
FfxFloat32x3 t1 = -n - k;
FfxFloat32x3 t2 = -n + k;
FfxFloat32 tNear = max(max(t1.x, t1.y), t1.z);
FfxFloat32 tFar = min(min(t2.x, t2.y), t2.z);
if (tNear > tFar || tFar < 0.0f) return FLT_INF;
FfxFloat32 nearEdgeDist = FFX_HitEdgeDist(ro + tNear * rd, boxMin, boxMax);
FfxFloat32 farEdgeDist = FFX_HitEdgeDist(ro + tFar * rd, boxMin, boxMax);
const FfxFloat32 nearClip = 0.1f;
if (tNear > nearClip && nearEdgeDist / tNear < 0.001f) {
return tNear;
} else if (tFar > nearClip && farEdgeDist / tFar < 0.001f) {
return tFar;
}
return FLT_INF;
}
void FfxBrixelizerDebugVisualization(FfxUInt32x2 tid)
{
FfxUInt32 width, height;
GetDebugOutputDimensions(width, height);
FfxFloat32x2 uv = (FfxFloat32x2(tid.xy) + FfxFloat32(0.5).xx) / FfxFloat32x2(width, height);
FfxFloat32x3 screen_uv_space_ray_origin = FfxFloat32x3(uv, FfxFloat32(0.5));
FfxFloat32x3 view_space_ray = FFX_ScreenSpaceToViewSpace(screen_uv_space_ray_origin);
FfxFloat32x3 view_space_ray_direction = normalize(view_space_ray);
FfxFloat32x3 ray_direction = normalize(FFX_ViewSpaceToWorldSpace(FfxFloat32x4(view_space_ray_direction, FfxFloat32(0.0))));
FfxFloat32x3 ray_origin = FFX_ViewSpaceToWorldSpace(FfxFloat32x4(0.0, 0.0, 0.0, 1.0));
FfxBrixelizerRayDesc ray_desc;
ray_desc.start_cascade_id = GetDebugInfoStartCascadeIndex();
ray_desc.end_cascade_id = GetDebugInfoEndCascadeIndex();
ray_desc.t_min = GetDebugInfoTMin();
ray_desc.t_max = GetDebugInfoTMax();
ray_desc.origin = ray_origin;
ray_desc.direction = ray_direction;
FfxBrixelizerHitRaw hit_payload;
FfxBoolean hit = FfxBrixelizerTraverseRaw(ray_desc, hit_payload);
FfxFloat32 hit_dist = FLT_INF;
FfxFloat32x3 out_color = FfxFloat32x3(0.0f, 0.0f, 0.0f);
if (hit) {
hit_dist = hit_payload.t;
switch (GetDebugInfoDebugState()) {
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_DISTANCE: {
FfxFloat32 dist = (hit_payload.t - ray_desc.t_min) / (ray_desc.t_max - ray_desc.t_min);
out_color = FfxFloat32x3(0.0f, smoothstep(0.0f, 1.0f, dist), smoothstep(0.0f, 1.0f, 1.0f - dist));
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_UVW: {
FfxFloat32x3 uvw = FfxFloat32x3(
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 0) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 8) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 16) & 0xff)
);
out_color = uvw;
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_ITERATIONS:
out_color = FFX_HeatmapGradient(FfxFloat32(hit_payload.iter_count) / FfxFloat32(64));
break;
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_GRAD: {
out_color = FfxBrixelizerGetHitNormal(hit_payload) * FfxFloat32(0.5) + FfxFloat32(0.5);
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_BRICK_ID:
out_color = FFX_RandomColor(FfxFloat32x2(FfxFloat32(hit_payload.brick_id % 256) / FfxFloat32(256.0), FfxFloat32((hit_payload.brick_id / 256) % 256) / FfxFloat32(256.0)));
break;
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_CASCADE_ID: {
FfxUInt32 voxel_id = LoadBricksVoxelMap(FfxBrixelizerBrickGetIndex(hit_payload.brick_id));
FfxUInt32 cascade_id = FfxBrixelizerGetVoxelCascade(voxel_id);
out_color = FFX_RandomColor(FfxFloat32x2(FfxFloat32(cascade_id % 256) / FfxFloat32(256.0), FfxFloat32((cascade_id / 256) % 256) / FfxFloat32(256.0)));
break;
}
}
} else {
out_color = FFX_HeatmapGradient(FfxFloat32(hit_payload.iter_count) / FfxFloat32(64));
}
FfxFloat32 aabb_hit_dist = FLT_INF;
FfxFloat32x3 aabb_color = FfxFloat32x3(0.0f, 0.0f, 0.0f);
FfxUInt32 num_debug_aabbs = min(GetDebugInfoMaxAABBs(), LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_NUM_DEBUG_AABBS));
for (FfxUInt32 i = 0; i < num_debug_aabbs; ++i) {
FfxBrixelizerDebugAABB aabb = GetDebugAABB(i);
FfxFloat32 this_hit_dist = FFX_BoxHitDist(tid, ray_desc.origin, ray_desc.direction, aabb.aabbMin, aabb.aabbMax);
if (this_hit_dist < aabb_hit_dist) {
aabb_hit_dist = this_hit_dist;
aabb_color = aabb.color;
}
}
if (aabb_hit_dist < hit_dist) {
out_color = aabb_color;
} else if (aabb_hit_dist < FLT_INF) {
out_color = ffxLerp(out_color, aabb_color, 0.25f);
}
StoreDebugOutput(tid, out_color);
}
#endif // ifndef FFX_BRIXELIZER_DEBUG_VISUALIZATION_H

View File

@@ -0,0 +1,230 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_HOST_GPU_SHARED_H
#define FFX_BRIXELIZER_HOST_GPU_SHARED_H
#include "../ffx_core.h"
#define FFX_BRIXELIZER_MAX_CASCADES 24
#define FFX_BRIXELIZER_MAX_INSTANCES (FfxUInt32(1) << FfxUInt32(16))
#define FFX_BRIXELIZER_CASCADE_RESOLUTION 64
#define FFX_BRIXELIZER_MAX_INSTANCES (FfxUInt32(1) << FfxUInt32(16))
#define FFX_BRIXELIZER_INVALID_ID 0x00ffffffu
#define FFX_BRIXELIZER_UNINITIALIZED_ID 0xffffffffu
#define FFX_BRIXELIZER_INVALID_BOTTOM_AABB_NODE 0x7fff
#define FFX_BRIXELIZER_MAX_BRICKS_X8 (1 << 18)
#define FFX_BRIXELIZER_MAX_BRICKS FFX_BRIXELIZER_MAX_BRICKS_X8
#define FFX_BRIXELIZER_BRICK_AABBS_STRIDE (sizeof(FfxUInt32))
#define FFX_BRIXELIZER_BRICK_AABBS_SIZE (FFX_BRIXELIZER_MAX_BRICKS_X8 * FFX_BRIXELIZER_BRICK_AABBS_STRIDE)
#define FFX_BRIXELIZER_CASCADE_AABB_TREE_SIZE ((16 * 16 * 16) * sizeof(FfxUInt32) + (4 * 4 * 4 + 1) * sizeof(FfxFloat32x3) * 2)
#define FFX_BRIXELIZER_CASCADE_AABB_TREE_STRIDE (sizeof(FfxUInt32))
#define FFX_BRIXELIZER_CASCADE_BRICK_MAP_SIZE (FFX_BRIXELIZER_CASCADE_RESOLUTION * FFX_BRIXELIZER_CASCADE_RESOLUTION * FFX_BRIXELIZER_CASCADE_RESOLUTION * sizeof(FfxUInt32))
#define FFX_BRIXELIZER_CASCADE_BRICK_MAP_STRIDE (sizeof(FfxUInt32))
#define FFX_BRIXELIZER_BRICK_ID_MASK 0xffffff
#define FFX_BRIXELIZER_CASCADE_DEGREE FfxUInt32(6)
#define FFX_BRIXELIZER_CASCADE_WRAP_MASK FfxUInt32(63)
#define FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE FfxUInt32(512)
#if defined(FFX_CPU)
#define FFX_BRIXELIZER_CONST static const
#elif defined(FFX_HLSL)
#define FFX_BRIXELIZER_CONST static const
#elif defined(FFX_GLSL)
#define FFX_BRIXELIZER_CONST const
#else
FFX_STATIC_ASSERT(0)
#endif
#ifdef FFX_CPU
#define FFX_BRIXELIZER_BEGIN_STRUCT(name) typedef struct name {
#define FFX_BRIXELIZER_END_STRUCT(name) } name;
#define FFX_BRIXELIZER_BEGIN_ENUM(name) typedef enum name {
#define FFX_BRIXELIZER_END_ENUM(name) } name;
#define FFX_BRIXELIZER_ENUM_VALUE(name, value) name = value,
#else
#define FFX_BRIXELIZER_BEGIN_STRUCT(name) struct name {
#define FFX_BRIXELIZER_END_STRUCT(name) };
#define FFX_BRIXELIZER_BEGIN_ENUM(name)
#define FFX_BRIXELIZER_END_ENUM(name)
#define FFX_BRIXELIZER_ENUM_VALUE(name, value) FFX_BRIXELIZER_CONST FfxUInt32 name = value;
#endif
/// An enumeration of flags which can be specified for different options when doing a cascade update.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerCascadeUpdateFlags)
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_CASCADE_UPDATE_FLAG_NONE, FfxUInt32(0)) ///< No flags.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_CASCADE_UPDATE_FLAG_RESET, FfxUInt32(1) << FfxUInt32(0)) ///< Reset the cascade. This clears and frees all bricks currently in the cascade ready to rebuild the cascade completely.
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerCascadeUpdateFlags)
/// An enumeration of the different possible debug outputs for the Brixelizer debug visualization.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerTraceDebugModes)
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_DISTANCE, 0) ///< Display a visualisation of the distance to hit, with closer hits in blue and further hits in green.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_UVW, 1) ///< Display the UVW coordinates of hits.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_ITERATIONS, 2) ///< Display a heatmap visualizing number of iterations in the scene.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_GRAD, 3) ///< Display the normals at hits.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_BRICK_ID, 4) ///< Display each brick in its own color.
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_TRACE_DEBUG_MODE_CASCADE_ID, 5) ///< Display each cascade in itw own color.
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerTraceDebugModes)
/// A structure of parameters describing a cascade. This structure is primarily for Brixelizer
/// internal use.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerCascadeInfo)
FfxFloat32x3 grid_min;
FfxFloat32 voxel_size;
FfxFloat32x3 grid_max;
FfxUInt32 flags; ///< the latest build_flags; see FfxBrixelizerCascadeUpdateFlags
FfxUInt32x3 clipmap_offset;
FfxUInt32 pad00;
FfxInt32x3 clipmap_invalidation_offset;
FfxUInt32 pad33;
FfxInt32x3 ioffset;
FfxUInt32 index;
FfxFloat32x3 grid_mid;
FfxUInt32 is_enabled;
FfxUInt32x2 rel_grid_min_fp16;
FfxUInt32x2 rel_grid_max_fp16;
FfxUInt32 pad11;
FfxUInt32 pad22;
FfxFloat32 ivoxel_size;
FfxUInt32 is_initialized;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerCascadeInfo)
/// A structure of parameters describing the Brixelizer context. This structure is primarily
/// for Brixelizer internal use.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerContextInfo)
FfxUInt32 num_bricks;
FfxUInt32 frame_index;
FfxFloat32 imesh_unit;
FfxFloat32 mesh_unit;
FfxBrixelizerCascadeInfo cascades[FFX_BRIXELIZER_MAX_CASCADES];
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerContextInfo)
// =============================================================================
// Debug/context counters
// =============================================================================
// Important to match the first a couple of counters with the FfxBrixelizerScratchCounters to share code
#define MEMBER_LIST \
MEMBER(brickCount, BRICK_COUNT, 0) \
MEMBER(dirtyBricks, DIRTY_BRICKS, 1) \
MEMBER(freeBricks, FREE_BRICKS, 2) \
MEMBER(clearBricks, CLEAR_BRICKS, 3) \
MEMBER(mergeBricks, MERGE_BRICKS, 4) \
MEMBER(numDebugAABBs, NUM_DEBUG_AABBS, 5)
/// A structure containing all the counters used by the Brixelizer context. These can
/// be read back from the context after processing each update for analysis.
/// <c><i>brickCount</i></c> gives the total number of bricks allocated.
/// <c><i>dirtyBricks</i></c> gives the total number of bricks requiring an eikonal pass for completion.
/// <c><i>freeBricks</i></c> gives the total number of free bricks. This is the maximum number of bricks which can be allocated within a frame.
/// <c><i>clearBricks</i></c> gives the total number of bricks to be cleared in a frame. Bricks are cleared by having all distance values reset to 1.
/// <c><i>mergeBricks</i></c> gives the total number of bricks to be merged in a frame.
/// <c><i>numDebugAABBs</i></c> gives the total number of debug AABBs requested to be drawn in a debug visualization.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerDebugCounters)
#define MEMBER(camel_name, _upper_name, _index) FfxUInt32 camel_name;
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerDebugCounters)
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerContextCounterIndex)
#define MEMBER(_camel_name, upper_name, index) FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_CONTEXT_COUNTER_##upper_name, index)
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerContextCounterIndex)
#define MEMBER(_camel_name, _upper_name, _index) + 1
FFX_BRIXELIZER_CONST FfxUInt32 FFX_BRIXELIZER_NUM_CONTEXT_COUNTERS = 0 MEMBER_LIST;
#undef MEMBER
#undef MEMBER_LIST
// =============================================================================
// Scratch counters
// =============================================================================
#define MEMBER_LIST \
MEMBER(triangles, TRIANGLES, 0) \
MEMBER(maxTriangles, MAX_TRIANGLES, 1) \
MEMBER(references, REFERENCES, 2) \
MEMBER(maxReferences, MAX_REFERENCES, 3) \
MEMBER(groupIndex, GROUP_INDEX, 4) \
MEMBER(compressionBricks, COMPRESSION_BRICKS, 5) \
MEMBER(storageOffset, STORAGE_OFFSET, 6) \
MEMBER(storageSize, STORAGE_SIZE, 7) \
MEMBER(numBricksAllocated, NUM_BRICKS_ALLOCATED, 8) \
MEMBER(clearBricks, CLEAR_BRICKS, 9)
/// A structure containing the counters used by the Brixelizer context for each cascade
/// update. This can be readback and used for analysis after each update. The following
/// members contain useful information for analysing Brixelizer resource usage.
///
/// <c><i>triangles</i></c> is used to store the total amount of storage space requested within the triangle buffer during an update. This is useful for determining a sensible value of <c><i>triangleSwapSize</i></c> in either <c><i>FfxBrixelizerRawCascadeUpdateDescription</i></c> or <c><i>FfxBrixelizerUpdateDescription</i></c>.
/// <c><i>references</i></c> is used to store the total number of reference allocations requested by Brixelizer during an update. This is useful for determining a sensible value of <c><i>maxReferences</i></c> in either <c><i>FfxBrixelizerRawCascadeUpdateDescription</i></c> or <c><i>FfxBrixelizerUpdateDescription</i></c>.
/// <c><i>numBricksAllocated</i></c> is used to store the number of brick allocations requested in an update. This is useful for determining a sensible value of <c><i>maxBricksPerBake</i></c> in either <c><i>FfxBrixelizerRawCascadeUpdateDescription</i></c> or <c><i>FfxBrixelizerUpdateDescription</i></c>.
///
/// The following counters are used internally by Brixelizer.
///
/// <c><i>maxTriangles</i></c> is used to store the storage size of the triangle buffer.
/// <c><i>maxReferences</i></c> is used to store the maxmimum number of references that can be stored.
/// <c><i>groupIndex</i></c> is used as a global atomic for wavefront synchronisation.
/// <c><i>compressionBricks</i></c> the number of bricks to compress (i.e. calculate AABBs for) this udpate.
/// <c><i>storageOffset</i></c> the next free position in the bricks scratch buffer.
/// <c><i>storageSize</i></c> the size of the bricks scratch buffer.
/// <c><i>clearBricks</i></c> the amount of bricks in the scratch buffer to initialize.
///
/// @ingroup Brixelizer
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerScratchCounters)
#define MEMBER(camel_name, _upper_name, _index) FfxUInt32 camel_name;
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerScratchCounters)
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerScratchCounterIndex)
#define MEMBER(_camel_name, upper_name, index) FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_SCRATCH_COUNTER_##upper_name, index)
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerScratchCounterIndex)
#define MEMBER(_camel_name, _upper_name, _index) + 1
FFX_BRIXELIZER_CONST FfxUInt32 FFX_BRIXELIZER_NUM_SCRATCH_COUNTERS = 0 MEMBER_LIST;
#undef MEMBER
#undef MEMBER_LIST
#endif

View File

@@ -0,0 +1,222 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_HOST_GPU_SHARED_PRIVATE_H
#define FFX_BRIXELIZER_HOST_GPU_SHARED_PRIVATE_H
#include "../ffx_core.h"
#include "ffx_brixelizer_host_gpu_shared.h"
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerInstanceFlagsInternal)
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_USE_U16_INDEX, (FfxUInt32(1) << FfxUInt32(0)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_USE_RGBA16_VERTEX, (FfxUInt32(1) << FfxUInt32(2)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_USE_INDEXLESS_QUAD_LIST, (FfxUInt32(1) << FfxUInt32(3)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_UV_FORMAT_RG16_UNORM, (FfxUInt32(1) << FfxUInt32(4)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_UV_FORMAT_RG32_FLOAT, (FfxUInt32(1) << FfxUInt32(5)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_COLOR_FORMAT_RGBA32_FLOAT, (FfxUInt32(1) << FfxUInt32(6)))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INSTANCE_FLAG_COLOR_FORMAT_RGBA8_UNORM, (FfxUInt32(1) << FfxUInt32(7)))
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerInstanceFlagsInternal)
#define FFX_BRIXELIZER_STATIC_CONFIG_VOXELIZER_GROUP_SIZE FfxUInt32(256)
#define FFX_BRIXELIZER_STATIC_CONFIG_SCAN_REFERENCES_GROUP_SIZE FfxUInt32(256)
#define FFX_BRIXELIZER_STATIC_CONFIG_MAX_VERTEX_BUFFERS FfxUInt32(8192)
#define FFX_BRIXELIZER_STATIC_CONFIG_COMPACT_REFERENCES_GROUP_SIZE FfxUInt32(64)
#define FFX_BRIXELIZER_STATIC_CONFIG_EMIT_SDF_GROUP_SIZE FfxUInt32(32)
#define FFX_BRIXELIZER_STATIC_CONFIG_EMIT_SDF_REFS_PER_GROUP FFX_BRIXELIZER_STATIC_CONFIG_EMIT_SDF_GROUP_SIZE
#define FFX_BRIXELIZER_STATIC_CONFIG_INDIRECT_DISPATCH_STRIDE32 FfxUInt32(4)
#define FFX_BRIXELIZER_STATIC_CONFIG_INDIRECT_DISPATCH_STRIDE FfxUInt32(16)
// index deliberately starts at 1
#define MEMBER_LIST \
MEMBER(CompactReferences, COMPACT_REFERENCES, 1) \
MEMBER(EmitSDF, EMIT_SDF, 2) \
MEMBER(Voxelize, VOXELIZE, 3) \
MEMBER(Compress, COMPRESS, 4) \
MEMBER(Eikonal, EIKONAL, 5) \
MEMBER(ClearBricks, CLEAR_BRICKS, 6) \
MEMBER(MergeBricks, MERGE_BRICKS, 7) \
MEMBER(InstanceOpsTrianglePass1, INSTANCE_OPS_TRIANGLE_PASS_1, 8) \
MEMBER(InstanceOpsDeferredReleaseBrits, INSTANCE_OPS_DEFERRED_RELEASE_BRITS, 9) \
MEMBER(ClearBrits, CLEAR_BRITS, 10)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerIndirectOffsets)
FfxUInt32x4 pad;
#define MEMBER(pascal_name, _upper_name, _index) FfxUInt32x4 pascal_name;
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerIndirectOffsets)
#define MEMBER(_pascal_name, _upper_name, _index) + 1
FFX_BRIXELIZER_CONST FfxUInt32 FFX_BRIXELIZER_NUM_INDIRECT_OFFSETS = 1 MEMBER_LIST;
#undef MEMBER
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerIndirectOffsetsEnum)
#define MEMBER(_pascal_name, upper_name, index) FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INDIRECT_OFFSETS_##upper_name, index * FFX_BRIXELIZER_STATIC_CONFIG_INDIRECT_DISPATCH_STRIDE)
MEMBER_LIST
#undef MEMBER
#define MEMBER(_pascal_name, upper_name, index) FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_INDIRECT_OFFSETS_##upper_name##_32, index * FFX_BRIXELIZER_STATIC_CONFIG_INDIRECT_DISPATCH_STRIDE32)
MEMBER_LIST
#undef MEMBER
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerIndirectOffsetsEnum)
#undef MEMBER_LIST
FFX_BRIXELIZER_BEGIN_ENUM(FfxBrixelizerJobFlagsInternal)
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_JOB_FLAG_NONE, FfxUInt32(0))
FFX_BRIXELIZER_ENUM_VALUE(FFX_BRIXELIZER_JOB_FLAG_INVALIDATE, (FfxUInt32(1) << FfxUInt32(0)))
FFX_BRIXELIZER_END_ENUM(FfxBrixelizerJobFlagsInternal)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerBasicMeshInfo)
FfxUInt32 flags;
FfxUInt32 indexBufferID;
FfxUInt32 indexBufferOffset;
FfxUInt32 vertexBufferID;
FfxUInt32 vertexBufferOffset;
FfxUInt32 vertexCount;
FfxUInt32 vertexStride;
FfxUInt32 triangleCount;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerBasicMeshInfo)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerInstanceInfo)
FfxFloat32x3 aabbMin; // voxel aligned
FfxUInt32 pack0; // | 16: vertex buffer id | 16: index buffer id |
FfxFloat32x3 aabbMax; // voxel aligned
FfxUInt32 pack1; // ! 6: vertex stride | 10: flags | | |
FfxUInt32 indexBufferOffset;
FfxUInt32 vertexBufferOffset;
FfxUInt32 vertexCount;
FfxUInt32 triangleCount;
FfxUInt32x3 padding;
FfxUInt32 index;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerInstanceInfo)
#ifdef FFX_GPU
FfxBrixelizerBasicMeshInfo ffxBrixelizerInstanceInfoGetMeshInfo(FFX_PARAMETER_IN FfxBrixelizerInstanceInfo instance_info)
{
FfxBrixelizerBasicMeshInfo info;
info.flags = (instance_info.pack1 >> 16) & FfxUInt32(0x1ff);
info.triangleCount = instance_info.triangleCount;
info.indexBufferID = (instance_info.pack0 >> 0) & FfxUInt32(0xffff);
info.indexBufferOffset = instance_info.indexBufferOffset;
info.vertexBufferID = (instance_info.pack0 >> 16) & FfxUInt32(0xffff);
info.vertexBufferOffset = instance_info.vertexBufferOffset;
info.vertexStride = (instance_info.pack1 >> 26) & 0x3f;
return info;
}
#endif
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerBrixelizationJob)
FfxUInt32x3 aabbMin; // in local cascade voxel size
FfxUInt32 instanceIdx;
FfxUInt32x3 aabbMax; // in local cascade voxel size
FfxUInt32 flags;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerBrixelizationJob)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerIndexRef)
FfxUInt32 surface_id;
FfxUInt32 instance_id;
FfxUInt32 triangle_index;
FfxUInt32 pad0;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerIndexRef)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerTriangleReference)
FfxUInt32 voxel_idx;
FfxUInt32 triangle_id;
FfxUInt32 local_ref_idx;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerTriangleReference)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerInstanceReference)
FfxUInt32 voxel_idx;
FfxUInt32 instance_id;
FfxUInt32 local_ref_idx;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerInstanceReference)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerTriangle)
FfxUInt32 job_idx;
FfxUInt32 triangle_index;
FfxUInt32x3 face3;
FfxFloat32x3 wp0;
FfxFloat32x3 wp1;
FfxFloat32x3 wp2;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerTriangle)
#define FFX_BRIXELIZER_TRIANGLE_SMALL_FLAG (FfxUInt32(1) << FfxUInt32(31))
#define FFX_BRIXELIZER_TRIANGLE_OFFSET_MASK (0x7fffffffu)
#define FFX_BRIXELIZER_INVALID_ALLOCATION 0x00ffffffu
#define FFX_BRIXELIZER_VOXEL_ID_MASK 0xffffff
#define FFX_BRIXELIZER_CASCADE_ID_SHIFT 24
#ifdef FFX_GPU
FfxBoolean FfxBrixelizerTriangleIsSmall(FfxUInt32 id) { return ((id & FFX_BRIXELIZER_TRIANGLE_SMALL_FLAG) != 0); }
FfxUInt32 FfxBrixelizerTriangleIDGetOffset(FfxUInt32 id) { return id & FFX_BRIXELIZER_TRIANGLE_OFFSET_MASK; }
FfxBoolean FfxBrixelizerIsInvalidID(FfxUInt32 id) { return (id & FFX_BRIXELIZER_INVALID_ID) == FFX_BRIXELIZER_INVALID_ID; }
#endif
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerBuildInfo)
FfxInt32 tree_iteration;
FfxUInt32 max_bricks_per_bake;
FfxUInt32 num_jobs;
FfxUInt32 cascade_index;
FfxUInt32 cascade_shift; // [1, 2, 4] for 1x, 2x and 4x
FfxUInt32 is_dynamic;
FfxUInt32 do_initialization;
FfxUInt32 num_job_voxels;
FfxUInt32 src_cascade_A;
FfxUInt32 src_cascade_B;
FfxUInt32 dst_cascade;
FfxUInt32 merge_instance_idx;
FfxUInt32x3 _padding;
FfxUInt32 build_flags;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerBuildInfo)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerDebugAABB)
FfxFloat32x3 color;
FfxFloat32x3 aabbMin;
FfxFloat32x3 aabbMax;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerDebugAABB)
FFX_BRIXELIZER_BEGIN_STRUCT(FfxBrixelizerDebugInfo)
FfxFloat32x4x4 inv_view; ///< Stored in row-major order.
FfxFloat32x4x4 inv_proj; ///< Stored in row-major order.
FfxFloat32 t_min;
FfxFloat32 t_max;
FfxFloat32 preview_sdf_solve_eps;
FfxUInt32 start_cascade_idx;
FfxUInt32 end_cascade_idx;
FfxUInt32 debug_state;
FfxUInt32 max_aabbs;
FfxUInt32 _padding;
FFX_BRIXELIZER_END_STRUCT(FfxBrixelizerDebugInfo)
#endif // FFX_BRIXELIZER_HOST_GPU_SHARED_PRIVATE_H

View File

@@ -0,0 +1,173 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_MESH_COMMON_H
#define FFX_BRIXELIZER_MESH_COMMON_H
#include "ffx_brixelizer_common_private.h"
struct FfxBrixelizerTrianglePos {
FfxUInt32x3 face3;
FfxFloat32x3 wp0;
FfxFloat32x3 wp1;
FfxFloat32x3 wp2;
};
FfxFloat32x3 FFX_Fetch_PositionRGBA16(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
FfxUInt32x2 pack = LoadVertexBufferUInt2(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
FfxFloat32x2 xy = ffxUnpackF32(pack.x);
FfxFloat32x2 zw = ffxUnpackF32(pack.y);
#if 0
FfxFloat32 x = f16tof32((pack.x >> FfxUInt32(0)) & FfxUInt32(0xFFFF));
FfxFloat32 y = f16tof32((pack.x >> FfxUInt32(16)) & FfxUInt32(0xFFFF));
FfxFloat32 z = f16tof32((pack.y >> FfxUInt32(0)) & FfxUInt32(0xFFFF));
FfxFloat32 w = f16tof32((pack.y >> FfxUInt32(16)) & FfxUInt32(0xFFFF));
#endif
return FfxFloat32x4(xy, zw).xyz;
}
FfxFloat32x4 FFX_Fetch_Unorm4(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
FfxUInt32 pack = LoadVertexBufferUInt(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
FfxFloat32 x = FfxFloat32((pack >> FfxUInt32(0)) & FfxUInt32(0xFF)) / FfxFloat32(255.0);
FfxFloat32 y = FfxFloat32((pack >> FfxUInt32(8)) & FfxUInt32(0xFF)) / FfxFloat32(255.0);
FfxFloat32 z = FfxFloat32((pack >> FfxUInt32(16)) & FfxUInt32(0xFF)) / FfxFloat32(255.0);
FfxFloat32 w = FfxFloat32((pack >> FfxUInt32(24)) & FfxUInt32(0xFF)) / FfxFloat32(255.0);
return FfxFloat32x4(x, y, z, w);
}
FfxFloat32x2 FFX_Fetch_RG16_UNORM(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
FfxUInt32 pack = LoadVertexBufferUInt(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
FfxFloat32 x = FfxFloat32((pack >> FfxUInt32(0)) & 0xFFFFu) / FfxFloat32(65535.0);
FfxFloat32 y = FfxFloat32((pack >> FfxUInt32(16)) & 0xFFFFu) / FfxFloat32(65535.0);
return FfxFloat32x2(x, y);
}
void FFX_Fetch_Face_Indices_U32(FfxUInt32 buffer_id, FFX_PARAMETER_OUT FfxUInt32x3 face3, FfxUInt32 offset, FfxUInt32 triangle_id)
{
face3 = LoadVertexBufferUInt3(buffer_id, (offset + FfxUInt32(12) * triangle_id) / FFX_BRIXELIZER_SIZEOF_UINT);
}
void FFX_Fetch_Face_Indices_U16(FfxUInt32 buffer_id, FFX_PARAMETER_OUT FfxUInt32x3 face3, FfxUInt32 offset, FfxUInt32 triangle_id)
{
FfxUInt32 word_offset = offset / 2;
FfxUInt32 word_id_0 = word_offset + triangle_id * FfxUInt32(3) + FfxUInt32(0);
FfxUInt32 dword_id_0 = word_id_0 / FfxUInt32(2);
FfxUInt32 shift_0 = FfxUInt32(16) * (word_id_0 & FfxUInt32(1));
FfxUInt32 word_id_1 = word_offset + triangle_id * FfxUInt32(3) + FfxUInt32(1);
FfxUInt32 dword_id_1 = word_id_1 / FfxUInt32(2);
FfxUInt32 shift_1 = FfxUInt32(16) * (word_id_1 & FfxUInt32(1));
FfxUInt32 word_id_2 = word_offset + triangle_id * FfxUInt32(3) + FfxUInt32(2);
FfxUInt32 dword_id_2 = word_id_2 / FfxUInt32(2);
FfxUInt32 shift_2 = FfxUInt32(16) * (word_id_2 & FfxUInt32(1));
FfxUInt32 u0 = LoadVertexBufferUInt(buffer_id, dword_id_0);
u0 = (u0 >> shift_0) & FfxUInt32(0xFFFF);
FfxUInt32 u1 = LoadVertexBufferUInt(buffer_id, dword_id_1);
u1 = (u1 >> shift_1) & FfxUInt32(0xFFFF);
FfxUInt32 u2 = LoadVertexBufferUInt(buffer_id, dword_id_2);
u2 = (u2 >> shift_2) & FfxUInt32(0xFFFF);
face3 = FfxUInt32x3(u0, u1, u2);
}
FfxFloat32x2 FFX_Fetch_float2(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
return LoadVertexBufferFloat2(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
}
FfxFloat32x3 FFX_Fetch_float3(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
return LoadVertexBufferFloat3(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
}
FfxFloat32x4 FFX_Fetch_float4(FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
return LoadVertexBufferFloat4(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
}
FfxFloat32x3 FFX_Fetch_Position(FfxUInt32 flags, FfxUInt32 buffer_id, FfxUInt32 offset, FfxUInt32 vertex_id, FfxUInt32 stride)
{
if (FFX_HAS_FLAG(flags, FFX_BRIXELIZER_INSTANCE_FLAG_USE_RGBA16_VERTEX)) {
FfxUInt32x2 pack = LoadVertexBufferUInt2(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
FfxFloat32x2 xy = ffxUnpackF32(pack.x);
FfxFloat32x2 zw = ffxUnpackF32(pack.y);
return FfxFloat32x4(xy, zw).xyz;
} else
return LoadVertexBufferFloat3(buffer_id, (offset + stride * vertex_id) / FFX_BRIXELIZER_SIZEOF_UINT);
}
FfxUInt32x3 FfxBrixelizerFetchFace(FfxUInt32 flags, FfxUInt32 indexBufferID, FfxUInt32 indexBufferOffset, FfxUInt32 triangle_idx)
{
if (FFX_HAS_FLAG(flags, FFX_BRIXELIZER_INSTANCE_FLAG_USE_INDEXLESS_QUAD_LIST)) { // Procedural quad index buffer
FfxUInt32 quad_id = triangle_idx / FfxUInt32(2); // 2 triangles per quad
FfxUInt32 base_vertex = quad_id * FfxUInt32(4); // 4 vertices per quad
if (FFX_HAS_FLAG(triangle_idx, FfxUInt32(1))) {
return FFX_BROADCAST_UINT32X3(base_vertex) + FfxUInt32x3(FfxUInt32(2), FfxUInt32(3), FfxUInt32(0));
} else {
return FFX_BROADCAST_UINT32X3(base_vertex) + FfxUInt32x3(FfxUInt32(0), FfxUInt32(1), FfxUInt32(2));
}
} else {
FfxUInt32x3 face3;
if (FFX_HAS_FLAG(flags, FFX_BRIXELIZER_INSTANCE_FLAG_USE_U16_INDEX)) {
FFX_Fetch_Face_Indices_U16(indexBufferID, /* out */ face3, /* in */ indexBufferOffset, /* in */ triangle_idx);
} else { // FFX_BRIXELIZER_INDEX_TYPE_U32
FFX_Fetch_Face_Indices_U32(indexBufferID, /* out */ face3, /* in */ indexBufferOffset, /* in */ triangle_idx);
}
return face3;
}
}
FfxBrixelizerTrianglePos FfxBrixelizerFetchTriangle(FfxUInt32 flags, FfxUInt32 indexBufferID, FfxUInt32 indexBufferOffset, FfxUInt32 vertexBufferID, FfxUInt32 vertexBufferOffset, FfxUInt32 vertexBufferStride,
FfxUInt32 instance_idx, FfxUInt32 triangle_idx)
{
FfxUInt32x3 face3 = FfxBrixelizerFetchFace(flags, indexBufferID, indexBufferOffset, triangle_idx);
FfxFloat32x3 p0 = FFX_Fetch_Position(flags, vertexBufferID, vertexBufferOffset, face3.x, vertexBufferStride);
FfxFloat32x3 p1 = FFX_Fetch_Position(flags, vertexBufferID, vertexBufferOffset, face3.y, vertexBufferStride);
FfxFloat32x3 p2 = FFX_Fetch_Position(flags, vertexBufferID, vertexBufferOffset, face3.z, vertexBufferStride);
FfxBrixelizerTrianglePos tri;
FfxFloat32x3x4 obj_to_anchor = LoadInstanceTransform(instance_idx);
tri.face3 = face3;
tri.wp0 = FFX_TRANSFORM_VECTOR(obj_to_anchor, FfxFloat32x4(p0, FfxFloat32(1.0))).xyz;
tri.wp1 = FFX_TRANSFORM_VECTOR(obj_to_anchor, FfxFloat32x4(p1, FfxFloat32(1.0))).xyz;
tri.wp2 = FFX_TRANSFORM_VECTOR(obj_to_anchor, FfxFloat32x4(p2, FfxFloat32(1.0))).xyz;
return tri;
}
FfxBrixelizerTrianglePos FfxBrixelizerFetchTriangle(FfxBrixelizerBasicMeshInfo mesh_info, FfxUInt32 instance_id, FfxUInt32 triangle_id)
{
return FfxBrixelizerFetchTriangle(mesh_info.flags, mesh_info.indexBufferID, mesh_info.indexBufferOffset, mesh_info.vertexBufferID, mesh_info.vertexBufferOffset,
mesh_info.vertexStride, instance_id, triangle_id);
}
#endif // FFX_BRIXELIZER_MESH_COMMON_H

View File

@@ -0,0 +1,91 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_RESOURCES_H
#define FFX_BRIXELIZER_RESOURCES_H
#if defined(FFX_CPU) || defined(FFX_GPU)
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_NULL 0
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CASCADE_AABB_TREE 1 // 24 elements
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CASCADE_AABB_TREES 1 // 24 elements (Same as the previous ID, used for binding the descriptor array)
// The cascade octree previously occupied 24 elements here.
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CASCADE_BRICK_MAP 25 // 24 elements
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CASCADE_BRICK_MAPS 25 // 24 elements (Same as the previous ID, used for binding the descriptor array)
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CASCADE_READBACK_BUFFERS 49 // 3 * 24 elements
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_INSTANCE_INFO_BUFFER 121
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_INSTANCE_TRANSFORM_BUFFER 122
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_JOB_BUFFER 123
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_JOB_INDEX_BUFFER 124
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_INDIRECT_ARGS_1 125
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_COUNTERS 126
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_INDEX_SWAP 127
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_VOXEL_ALLOCATION_FAIL_COUNTER 128
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_BRICKS_STORAGE 129
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_BRICKS_STORAGE_OFFSETS 130
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_BRICKS_COMPRESSION_LIST 131
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_BRICKS_CLEAR_LIST 132
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_JOB_COUNTERS 133
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_JOB_COUNTERS_SCAN 134
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_JOB_GLOBAL_COUNTERS_SCAN 135
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_REFERENCES 136
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_COMPACTED_REFERENCES 137
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_REF_COUNTERS 138
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_REF_COUNTER_SCAN 139
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_REF_GLOBAL_SCAN 140
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_STAMP_SCAN 141
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_CR1_STAMP_GLOBAL_SCAN 142
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_DEBUG_AABBS 143
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_VOXEL_MAP 144
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_AABB 145
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_FREE_LIST 146
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_CLEAR_LIST 147
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_EIKONAL_LIST 148
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_MERGE_LIST 149
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_BRICKS_EIKONAL_COUNTERS 150
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_COUNTERS 151
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_COUNTERS_READBACK_0 152
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_COUNTERS_READBACK_1 153
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_COUNTERS_READBACK_2 154
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_CONTEXT_SDF_ATLAS 155
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_UPLOAD_INSTANCE_INFO_BUFFER 156
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_UPLOAD_INSTANCE_TRANSFORM_BUFFER 157
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_UPLOAD_JOB_BUFFER 158
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_UPLOAD_JOB_INDEX_BUFFER 159
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_DEBUG_OUTPUT 160
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_SCRATCH_BUFFER 161
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_UPLOAD_DEBUG_INSTANCE_ID_BUFFER 162
#define FFX_BRIXELIZER_RESOURCE_IDENTIFIER_COUNT 163
#define FFX_BRIXELIZER_CONSTANTBUFFER_IDENTIFIER_CASCADE_INFO 0
#define FFX_BRIXELIZER_CONSTANTBUFFER_IDENTIFIER_CONTEXT_INFO 1
#define FFX_BRIXELIZER_CONSTANTBUFFER_IDENTIFIER_BUILD_INFO 2
#define FFX_BRIXELIZER_CONSTANTBUFFER_IDENTIFIER_DEBUG_INFO 3
#endif // #if defined(FFX_CPU) || defined(FFX_GPU)
#endif //!defined( FFX_BRIXELIZER_RESOURCES_H )

View File

@@ -0,0 +1,354 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_TRACE_OPS_H
#define FFX_BRIXELIZER_TRACE_OPS_H
#include "../ffx_core.h"
#include "ffx_brixelizer_host_gpu_shared.h"
FfxFloat32x3 LoadCascadeAABBTreesFloat3(FfxUInt32 cascadeID, FfxUInt32 elementIndex);
FfxUInt32 LoadCascadeAABBTreesUInt(FfxUInt32 cascadeID, FfxUInt32 elementIndex);
FfxUInt32 LoadBricksAABB(FfxUInt32 elementIndex);
FfxBrixelizerCascadeInfo GetCascadeInfo(FfxUInt32 cascadeID);
FfxFloat32 SampleSDFAtlas(FfxFloat32x3 uvw);
FfxUInt32 LoadCascadeBrickMapArrayUniform(FfxUInt32 cascadeID, FfxUInt32 elementIndex);
#include "ffx_brixelizer_brick_common.h"
/// A structure encapsulating the parameters for a ray to be marched using Brixelizer.
///
/// @ingroup Brixelizer
struct FfxBrixelizerRayDesc {
FfxUInt32 start_cascade_id; ///< The index of the most detailed cascade for ray traversal.
FfxUInt32 end_cascade_id; ///< The index of the least detailed cascade for ray traversal.
FfxFloat32 t_min; ///< The minimum distance at which to accept a hit.
FfxFloat32 t_max; ///< The maximum distance at which to accept a hit.
FfxFloat32x3 origin; ///< The origin of the ray.
FfxFloat32x3 direction; ///< The direction of the ray. This input should be normalized.
};
/// A structure encapsulating all data associated with a ray SDF hit.
///
/// @ingroup Brixelizer
struct FfxBrixelizerHitRaw {
FfxFloat32 t; ///< The distance from the ray origin to the hit.
FfxUInt32 brick_id; ///< The ID of a hit brick.
FfxUInt32 uvwc; ///< Packed UVW coordinates of the hit location. UVW coordinates are in brick space.
FfxUInt32 iter_count; ///< The count of iterations to find the intersection.
};
/// A structure encapsulating minimal data associated with a ray SDF hit.
///
/// @ingroup Brixelizer
struct FfxBrixelizerHit {
FfxFloat32 t; ///< The distance from the ray origin to the hit.
};
/// A structure encapsulating the distance to a ray hit and the normal of the surface hit.
///
/// @ingroup Brixelizer
struct FfxBrixelizerHitWithNormal {
FfxFloat32 t; ///< The distance from the ray origin to the hit.
FfxFloat32x3 normal; ///< The normal of the SDF surface at the hit location.
};
FfxFloat32 FfxBrixelizerGetIntersectCorner(FfxBrixelizerCascadeInfo CINFO, FfxFloat32x3 corner_sign, FfxFloat32x3 ray_cursor, FfxFloat32x3 ray_idirection, FfxFloat32 EPS, inout FfxUInt32x3 coord, FfxFloat32 voxel_k)
{
FfxFloat32x3 relative_cascade_origin = CINFO.grid_min - ray_cursor;
coord = FfxUInt32x3(-relative_cascade_origin / (CINFO.voxel_size * voxel_k));
FfxFloat32x3 node_max = relative_cascade_origin + (FfxFloat32x3(coord.x, coord.y, coord.z) + corner_sign) * (CINFO.voxel_size * voxel_k);
FfxFloat32x3 tbot = ray_idirection * node_max;
FfxFloat32 hit_max = min(tbot.x, min(tbot.y, tbot.z)) + EPS;
return hit_max;
}
/// This function is used for running a ray query against the Brixelizer SDF acceleration structure.
/// The "raw" version returns the data immediately accessible from the SDF structure generated by a hit.
///
/// @param [in] ray_desc A structure encapsulating the parameters of the ray for ray traversal. See <c><i>FfxBrixelizerRayDesc</i></c>.
/// @param [out] hit A structure of values to be filled in with details of any hit.
///
/// @retval
/// true The ray hit the SDF and hit data has been written to the <c><i>hit</i></c> parameter.
/// @retval
/// false The ray did not intersect the SDF and no hit data has been written.
///
/// @ingroup Brixelizer
FfxBoolean FfxBrixelizerTraverseRaw(in FfxBrixelizerRayDesc ray_desc, out FfxBrixelizerHitRaw hit)
{
FfxUInt32 cascade_id = ray_desc.start_cascade_id;
FfxUInt32 g_end_cascade = ray_desc.end_cascade_id;
FfxFloat32x3 ray_origin = ray_desc.origin;
FfxFloat32 ray_t = ray_desc.t_min;
FfxFloat32x3 ray_direction = ray_desc.direction;
FfxFloat32x3 ray_idirection = FfxFloat32(1.0) / ray_desc.direction;
FfxFloat32x3 corner_sign = FfxFloat32x3(
ray_direction.x > FfxFloat32(0.0) ? FfxFloat32(1.0) : FfxFloat32(0.0),
ray_direction.y > FfxFloat32(0.0) ? FfxFloat32(1.0) : FfxFloat32(0.0),
ray_direction.z > FfxFloat32(0.0) ? FfxFloat32(1.0) : FfxFloat32(0.0)
);
hit.iter_count = 0;
FfxUInt32 local_iter_cnt = 0;
cascade_id = ffxWaveMin(cascade_id);
for (; cascade_id <= g_end_cascade; cascade_id++) {
cascade_id = ffxWaveReadLaneFirstU1(cascade_id);
FfxBrixelizerCascadeInfo CINFO = GetCascadeInfo(cascade_id);
const FfxFloat32 voxel_size = CINFO.voxel_size;
local_iter_cnt = 0;
FfxFloat32 orig_ray_t = ray_t;
FfxFloat32 EPS = CINFO.voxel_size / FfxFloat32(1024.0);
FfxFloat32 cascade_hit_min;
FfxFloat32 cascade_hit_max;
FfxFloat32x3 ray_cursor = ray_origin + ray_direction * ray_t;
FfxFloat32 top_level_max;
const FfxUInt32 ITER_LIMIT = 32;
FfxFloat32x3 cascade_aabb_min = LoadCascadeAABBTreesFloat3(cascade_id, (16 * 16 * 16) + (2 * 4 * 4 * 4 + 0) * 3);
FfxFloat32x3 cascade_aabb_max = LoadCascadeAABBTreesFloat3(cascade_id, (16 * 16 * 16) + (2 * 4 * 4 * 4 + 1) * 3);
// if the ray cursor isn't inside the current cascade skip to the next one
if (!((CINFO.is_enabled > 0) && all(FFX_GREATER_THAN(ray_cursor, CINFO.grid_min)) && all(FFX_LESS_THAN(ray_cursor, CINFO.grid_max)))) {
continue;
}
if (FfxBrixelizerIntersectAABB(ray_origin, ray_idirection, cascade_aabb_min, cascade_aabb_max,
/* out */ cascade_hit_min,
/* out */ cascade_hit_max)) {
FfxFloat32 stamp_size = FfxFloat32(16.0);
FfxUInt32 level = 0;
cascade_hit_max = min(cascade_hit_max, ray_desc.t_max);
while (ray_t < cascade_hit_max) {
hit.iter_count++;
local_iter_cnt++;
if (local_iter_cnt > ITER_LIMIT)
break;
ray_cursor = ray_origin + ray_direction * ray_t;
FfxFloat32x3 stamp_aabb_min;
FfxFloat32x3 stamp_aabb_max;
FfxUInt32x3 stamp_coord;
FfxFloat32 stamp_hit_max = ray_t + FfxBrixelizerGetIntersectCorner(CINFO, corner_sign, ray_cursor, ray_idirection, EPS, /* inout */ stamp_coord, stamp_size);
FfxUInt32 stamp_idx = FfxBrixelizerFlattenPOT(stamp_coord, FfxUInt32(2) << level);
if (level == 0) {
top_level_max = stamp_hit_max;
stamp_aabb_min = LoadCascadeAABBTreesFloat3(cascade_id, (16 * 16 * 16) + (2 * stamp_idx + 0) * 3);
stamp_aabb_max = LoadCascadeAABBTreesFloat3(cascade_id, (16 * 16 * 16) + (2 * stamp_idx + 1) * 3);
} else {
FfxUInt32 bottom_stamp_pack = LoadCascadeAABBTreesUInt(cascade_id, stamp_idx);
if (bottom_stamp_pack == FFX_BRIXELIZER_INVALID_BOTTOM_AABB_NODE) {
stamp_aabb_min = FFX_BROADCAST_FLOAT32X3(0.0);
stamp_aabb_max = FFX_BROADCAST_FLOAT32X3(0.0);
} else {
FfxUInt32x3 bottom_iaabb_min = FfxBrixelizerUnflattenPOT(bottom_stamp_pack & 0x7fff, 5);
FfxUInt32x3 bottom_iaabb_max = FfxBrixelizerUnflattenPOT((bottom_stamp_pack >> 16) & 0x7fff, 5);
FfxFloat32x3 bottom_stamp_world_coord = FfxFloat32x3(stamp_coord) * CINFO.voxel_size * FfxFloat32(4.0) + CINFO.grid_min;
stamp_aabb_min = bottom_stamp_world_coord + FfxFloat32x3(bottom_iaabb_min) * CINFO.voxel_size / FfxFloat32(8.0);
stamp_aabb_max = bottom_stamp_world_coord + FfxFloat32x3(bottom_iaabb_max + FFX_BROADCAST_UINT32X3(1)) * CINFO.voxel_size / FfxFloat32(8.0);
}
}
FfxFloat32 stamp_aabb_hit_max;
FfxFloat32 stamp_aabb_hit_min;
if (ffxAsUInt32(stamp_aabb_min.x) == ffxAsUInt32(stamp_aabb_max.x) || !FfxBrixelizerIntersectAABB(ray_origin, ray_idirection, stamp_aabb_min, stamp_aabb_max,
/* out */ stamp_aabb_hit_min,
/* out */ stamp_aabb_hit_max)) { // empty node
ray_t = stamp_hit_max; // Advance the ray
if (level == 0) {
continue;
} else {
if (ray_t > top_level_max) {
level = 0;
stamp_size = FfxFloat32(16.0);
}
continue;
}
} else {
if (level == 0) {
level = 1;
stamp_size = FfxFloat32(4.0);
continue;
} else {
stamp_aabb_hit_max = min(stamp_aabb_hit_max, ray_desc.t_max);
while (ray_t < stamp_aabb_hit_max) {
hit.iter_count++;
local_iter_cnt++;
if (local_iter_cnt > ITER_LIMIT)
break;
ray_cursor = ray_origin + ray_direction * ray_t;
FfxUInt32x3 voxel;
FfxFloat32 voxel_hit_max = FfxBrixelizerGetIntersectCorner(CINFO, corner_sign, ray_cursor, ray_idirection, EPS, /* inout */ voxel, FfxFloat32(1.0));
if (voxel_hit_max < EPS) {
ray_t = ray_t + voxel_hit_max;
break;
}
voxel_hit_max += ray_t;
FfxUInt32 brick_id = FfxBrixelizerLoadBrickIDUniform(FfxBrixelizerFlattenPOT(FfxBrixelizerWrapCoords(CINFO, voxel), 6), cascade_id);
if (brick_id == FFX_BRIXELIZER_UNINITIALIZED_ID) {
hit.iter_count = ITER_LIMIT + 1;
local_iter_cnt = ITER_LIMIT + 1;
break;
}
if (FfxBrixelizerIsValidID(brick_id)) {
FfxFloat32x3 voxel_min = FfxFloat32x3(voxel.x, voxel.y, voxel.z) * CINFO.voxel_size + CINFO.grid_min;
FfxUInt32 brick_aabb_pack = LoadBricksAABB(FfxBrixelizerBrickGetIndex(brick_id));
FfxUInt32x3 brick_aabb_umin = FfxBrixelizerUnflattenPOT(brick_aabb_pack & ((1 << 9) - 1), 3);
FfxUInt32x3 brick_aabb_umax = FfxBrixelizerUnflattenPOT((brick_aabb_pack >> 9) & ((1 << 9) - 1), 3) + FFX_BROADCAST_UINT32X3(1);
FfxFloat32x3 brick_aabb_min = voxel_min - FFX_BROADCAST_FLOAT32X3(CINFO.voxel_size / FfxFloat32(2.0 * 7.0)) + FfxFloat32x3(brick_aabb_umin) * (CINFO.voxel_size / FfxFloat32(7.0));
FfxFloat32x3 brick_aabb_max = voxel_min - FFX_BROADCAST_FLOAT32X3(CINFO.voxel_size / FfxFloat32(2.0 * 7.0)) + FfxFloat32x3(brick_aabb_umax) * (CINFO.voxel_size / FfxFloat32(7.0));
FfxFloat32 brick_hit_min;
FfxFloat32 brick_hit_max;
if (FfxBrixelizerIntersectAABB(ray_cursor, ray_idirection, brick_aabb_min, brick_aabb_max,
/* out */ brick_hit_min,
/* out */ brick_hit_max)) {
FfxFloat32x3 uvw = (ray_cursor + brick_hit_min * ray_direction - voxel_min) * CINFO.ivoxel_size;
FfxFloat32 dist = FfxFloat32(1.0);
FfxFloat32 total_dist = 0.0f;
FfxFloat32x3 brick_offset = FfxBrixelizerGetSDFAtlasOffset(brick_id);
FfxFloat32x3 uvw_min = (brick_offset + FFX_BROADCAST_FLOAT32X3(FfxFloat32(0.5))) / FfxFloat32(FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE);
FfxFloat32x3 uvw_max = uvw_min + FFX_BROADCAST_FLOAT32X3(FfxFloat32(7.0)) / FfxFloat32(FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE);
for (FfxUInt32 i = 0; i < 8; i++) {
hit.iter_count++;
dist = FfxBrixelizerSampleBrixelDistance(uvw_min, uvw_max, uvw) - FFX_BRIXELIZER_TRAVERSAL_EPS;
if (dist < FFX_BRIXELIZER_TRAVERSAL_EPS) {
hit.t = ray_t + brick_hit_min + total_dist * voxel_size;
if (hit.t > ray_desc.t_max) {
return false;
}
hit.brick_id = brick_id;
hit.uvwc = PackUVWC(FfxFloat32x4(uvw, 0.0));
return true;
}
uvw += ray_direction * dist;
total_dist += dist;
if (any(FFX_GREATER_THAN(abs(uvw - FFX_BROADCAST_FLOAT32X3(0.5)), FFX_BROADCAST_FLOAT32X3(0.501))))
break;
}
}
}
ray_t = voxel_hit_max;
}
if (ray_t > top_level_max) {
level = 0;
stamp_size = FfxFloat32(16.0);
}
if (local_iter_cnt > ITER_LIMIT)
break;
ray_t = stamp_hit_max;
continue;
}
}
}
}
if (local_iter_cnt > ITER_LIMIT) {
ray_t = max(orig_ray_t, ray_t - CINFO.voxel_size);
continue;
}
// advance ray to end of current cascade
FfxBrixelizerIntersectAABB(ray_origin, ray_idirection, CINFO.grid_min, CINFO.grid_max, /* out */ cascade_hit_min, /* out */ cascade_hit_max);
ray_t = max(orig_ray_t, cascade_hit_max - CINFO.voxel_size);
}
return false;
}
/// Calculate a normal from a hit described by an <c><i>FfxBrixelizerHitRaw</i></c> structure.
///
/// @param [in] hit A ray hit with the SDF returned by <c><i>FfxBrixelizerTraverseRaw</i></c>.
///
/// @retval A normal to the hit described by the <c><i>hit</i></c> paramter.
///
/// @ingroup Brixelizer
FfxFloat32x3 FfxBrixelizerGetHitNormal(FfxBrixelizerHitRaw hit)
{
FfxFloat32x3 uvw = FfxFloat32x3(
FfxBrixelizerUnpackUnsigned8Bits((hit.uvwc >> 0) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit.uvwc >> 8) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit.uvwc >> 16) & 0xff)
);
uvw += FFX_BROADCAST_FLOAT32X3(1.0 / 512.0);
FfxUInt32x3 brick_offset = FfxBrixelizerGetSDFAtlasOffset(hit.brick_id);
FfxFloat32x3 uvw_min = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(0.5)) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
FfxFloat32x3 uvw_max = (FfxFloat32x3(brick_offset) + FFX_BROADCAST_FLOAT32X3(float(8.0 - 0.5))) / FFX_BRIXELIZER_STATIC_CONFIG_SDF_ATLAS_SIZE;
return FfxBrixelizerGetBrixelGrad(uvw_min, uvw_max, uvw);
}
/// This function is used for running a ray query against the Brixelizer SDF acceleration structure.
/// This version simply returns the distance to a hit if a hit is encountered.
///
/// @param [in] ray_desc A structure encapsulating the parameters of the ray for ray traversal. See <c><i>FfxBrixelizerRayDesc</i></c>.
/// @param [out] hit A structure of values to be filled in with details of any hit.
///
/// @retval
/// true The ray hit the SDF and hit data has been written to the <c><i>hit</i></c> parameter.
/// @retval
/// false The ray did not intersect the SDF and no hit data has been written.
///
/// @ingroup Brixelizer
FfxBoolean FfxBrixelizerTraverse(FfxBrixelizerRayDesc ray_desc, out FfxBrixelizerHit hit)
{
FfxBrixelizerHitRaw raw_payload;
FfxBoolean result = FfxBrixelizerTraverseRaw(ray_desc, raw_payload);
hit.t = raw_payload.t;
return result;
}
/// This function is used for running a ray query against the Brixelizer SDF acceleration structure.
/// This version returns the distance to a hit and a normal to the SDF geometry at a hit location when a hit
/// is encountered.
///
///
/// @param [in] ray_desc A structure encapsulating the parameters of the ray for ray traversal. See <c><i>FfxBrixelizerRayDesc</i></c>.
/// @param [out] hit A structure of values to be filled in with details of any hit.
///
/// @retval
/// true The ray hit the SDF and hit data has been written to the <c><i>hit</i></c> parameter.
/// @retval
/// false The ray did not intersect the SDF and no hit data has been written.
///
/// @ingroup Brixelizer
FfxBoolean FfxBrixelizerTraverseWithNormal(FfxBrixelizerRayDesc ray_desc, out FfxBrixelizerHitWithNormal hit)
{
FfxBrixelizerHitRaw raw_payload;
FfxBoolean result = FfxBrixelizerTraverseRaw(ray_desc, raw_payload);
if (!result) {
return false;
}
hit.t = raw_payload.t;
hit.normal = FfxBrixelizerGetHitNormal(raw_payload);
return true;
}
#endif // FFX_BRIXELIZER_TRACE_OPS_H