Intersection testing of dense geometry data using triangle pre-filtering

By using fixed-point mesh encoding and low-precision intersection testing, the problems of high computational resource consumption and redundant storage in ray tracing systems are solved, enabling more efficient ray-scene intersection testing.

CN121970091APending Publication Date: 2026-05-01ADVANCED MICRO DEVICES INC
View PDF 0 Cites 0 Cited by

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
ADVANCED MICRO DEVICES INC
Filing Date
2024-06-14
Publication Date
2026-05-01

AI Technical Summary

Technical Problem

Existing ray tracing systems suffer from high computational resource consumption and redundant data storage when processing dense geometric data, especially in real-time rendering where it is difficult to efficiently perform ray-scene intersection tests.

Method used

Fixed-point grid encoding is used to encode graph data, and low-precision intersection testers and pre-filter nodes are used to compress and decode graph data. Graph primitives are organized by accelerating structures (such as BVH) to reduce redundant storage and computational load.

Benefits of technology

It improves the rendering efficiency of the ray tracing system, reduces computational resource consumption, lowers storage requirements, and improves the speed and accuracy of ray intersection testing.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN121970091A_ABST
    Figure CN121970091A_ABST
Patent Text Reader

Abstract

Systems and methods for ray intersection for primitives are described. The primitive data is efficiently encoded into an array of data blocks of fixed size using a data format that can directly consume for ray traversal. The vertex data in the block is pre-quantized and stored using a fixed bit quantization grid. Mesh connectivity is encoded using triangular stripes based on control values representing triangular interconnectivity and a compressed index buffer storing indices of vertices in each stripe. Alternatively, the primitives may be quantized to generate primitive packets that are stored compactly in, with, or near leaf nodes of the acceleration structure. A low precision intersection tester simultaneously tests light for primitives to find candidate triangles that require full precision intersection. The primitives that generate uncertain results during the low precision test are retested using a full precision tester to explicitly determine a ray-triangle hit or miss.
Need to check novelty before this filing date? Find Prior Art

Description

Intersection testing of dense geometric data using triangular pre-filtering.

[0001] Cross-Reference to Related Applications This application claims priority to Provisional Patent Application Serial No. 63 / 591,946, filed on October 20, 2023, entitled “Intersection Testing on DenseGeometry Data using Triangle Prefiltering”, the entire contents of which are incorporated herein by reference. Background Technology

[0002] Description of related technologies Ray tracing involves using physically based rendering methods to simulate how light moves through a scene. While the technique has been widely used in cinematic rendering, it was only recently considered too demanding for real-time applications. A key aspect of ray tracing is the computation of the visibility of ray-scene intersections, achieved through a process called "ray traversal." This involves calculating the intersections between rays and scene objects by navigating through and intersecting nodes organized by structures such as bounding volume hierarchies (BVH).

[0003] The standard approach to performing ray tracing operations typically involves executing a graphics processing pipeline consisting of a series of stages dedicated to graphics operations. For example, during each stage of this pipeline, the GPU can perform various graphics-oriented processing tasks. In one stage, the GPU might collect a set of geometric primitives depicting the graphics scene, and in subsequent stages, it can perform shading operations using the vertices linked to these primitives. Ultimately, the GPU will convert these vertices into pixels through a process called rasterization, thereby rendering the graphics scene.

[0004] For each graphical primitive or geometric object created, identifying where rays intersect with geometry in the scene involves a significant amount of computation. A simple approach involves testing each ray for each primitive in the scene and then determining the nearest intersection point between them. However, this method becomes impractical for scenes with millions or billions of primitives, especially when the number of rays to be processed is also high. To address this issue, ray tracing systems typically employ acceleration architectures to characterize the geometry of the scene in a way that reduces the workload of intersection testing. Despite these advancements, achieving real-time intersection testing suitable for rendering images, especially for gaming applications, remains challenging. This challenge is particularly pronounced on devices such as smartphones, tablets, and laptops, which have stringent limitations in terms of silicon area, cost, and power consumption.

[0005] Furthermore, in various scenarios, multiple redundant copies of primitive data need to be maintained for intersecting test primitives of rays. This becomes problematic because typical graphics scenes contain a potentially massive number of primitives (potentially millions). Consequently, conventional ray tracing systems may end up storing millions of duplicate data copies. Processing such redundant data inefficiently consumes computational resources and can hinder the rendering speed of graphics scenes.

[0006] In view of the above, there is a need for improved systems and methods for encoding image data to perform intersection tests for rays. Attached Figure Description

[0007] The advantages of the methods and mechanisms described herein can be better understood by referring to the following description in conjunction with the accompanying drawings, in which: Figure 1 is a block diagram of a specific implementation of the computing system.

[0008] Figure 2 illustrates the details of the computing system.

[0009] Figure 3 is a block diagram illustrating the compression of graph data using a pre-filter node.

[0010] Figure 4 illustrates a dense geometry format (DGF) block used to store encoded map data.

[0011] Figure 5 is a block diagram illustrating a ray test using compressed image data.

[0012] Figure 6 illustrates a node decompressor used to decode encoded triangular data stored within DGF nodes and / or pre-filter nodes.

[0013] Figure 7 illustrates a method for decoding metadata used in primitive-ray intersection tests. Detailed Implementation

[0014] In the following description, numerous specific details are set forth to provide a thorough understanding of the methods and mechanisms presented herein. However, those skilled in the art will recognize that various specific implementations can be practiced without these specific details. In some cases, well-known structures, components, signals, computer program instructions, and techniques have not been shown in detail to avoid obscuring the methods described herein. It should be understood that, for simplicity and clarity, the elements shown in the accompanying drawings are not necessarily drawn to scale. For example, the dimensions of some of these elements may be enlarged relative to others.

[0015] This document discloses systems, apparatus, and methods for encoding graph data used in intersection tests. The graph data is efficiently encoded into fixed-size data blocks. In a specific implementation, these blocks can be directly consumed by processing circuitry (e.g., a GPU) for ray traversal. To create the data blocks, vertex data is encoded using a signed fixed-point mesh. As described herein, a “fixed-point mesh” refers to a representation of triangle vertices and other geometric entities using fixed-point coordinates instead of floating-point values. In one implementation, a fixed-point mesh is used due to its lower memory requirements and faster processing speed. A signed fixed-point mesh divides a coordinate space (e.g., a 2D plane or 3D space) into a mesh consisting of fixed-size cells or lattices. Each vertex of a triangle is quantized by mapping its floating-point position to a mesh cell within the fixed-point coordinate space. The floating-point position is multiplied by a scaling factor (e.g., a power of two scaling factor) to convert it to a fixed-point value. For each vertex of a triangle (or other geometric primitive), its position is quantized into a mesh cell using the fixed-point representation. The quantized mesh cell serves as an approximation of the original floating-point position. In practice, the data corresponding to the quantization of the vertices includes a 24-bit signed base position in the mesh. A variable-width (e.g., 1-16 bits) unsigned offset for each vertex (relative to the base position) is also stored. Finally, a power-of-2 scaling factor used to map the quantized mesh to the floating-point coordinates of each triangle vertex is stored as the "IEEE bias index".

[0016] In one implementation, encoded vertex data and other triangle data are stored as part of primitive mesh data. Primitive mesh data comprises a set of vertices, each defined by its position (e.g., in 3D space) and additional attributes such as normals (vectors perpendicular to the object), texture coordinates, or color. The mesh is composed of primitives, each defined by an index pointing to vertex data. For example, triangle meshes are typically stored using optimized data structures such as bounding volume hierarchies (BVH) or k-dimensional trees (KD trees). These structures spatially organize triangles to accelerate ray-triangle intersection testing.

[0017] In one implementation, primitive stripes (e.g., triangle stripes) and index buffers are used to encode mesh connectivity data. Primitive stripes are used to describe and render continuous surfaces or objects composed of primitives. In a primitive strip, each primitive shares an edge with the preceding primitive in the sequence. This shared edge is formed by two consecutive vertices from the vertex list. In one implementation, by sharing vertices between adjacent primitives, primitive stripes require less vertex data compared to individual primitive data, which reduces memory consumption and improves rendering performance.

[0018] In one or more embodiments, the index buffer includes a fixed number of control values ​​for primitives in a primitive strip. Each control value indicates the position of the primitive relative to a previously identified triangle in the strip. In some embodiments, the length (or size) of the index buffer is determined based on the contents of the control values. The index buffer includes a set of bits, where each bit corresponds to the index of a given vertex of the primitive. The index buffer is organized into two parts. The first part includes a bit array, storing one bit per vertex, indicating whether a first index (hereinafter referred to as "first index") of a given vertex has been encountered. The second part includes "N" bits for each index to store each non-first index to a vertex (hereinafter referred to as "non-first index"), where the value of N is predefined and stored in the data block header. In some embodiments, the index buffer (which can be calculated by an incrementing counter) is compressed by first reordering the vertices and omitting the storage of the first index corresponding to each vertex.

[0019] In one implementation, primitive identifiers can be derived from the primitive's position within the stripe and therefore do not need to be explicitly stored in the data block, further reducing memory usage. In another implementation, the data block also includes encoded geometric identifiers. These can be encoded in two modes, referred to as "constant mode" and "palette mode." In constant mode encoding, the geometry ID field in the data block stores the geometry ID applied to all triangles and an opacity flag (indicating whether the triangle is opaque or transparent to incident light). In palette mode, the geometry ID field is interpreted based on the least significant bit (LSB) and most significant bit (MSB).

[0020] As described herein, the ray tracing system uses multiple low-precision intersection testers in parallel to determine candidate nodes to be traversed in the accelerated structure. Geometry metadata is stored using data blocks as described above, and / or the geometry metadata is quantized to generate pre-filter nodes compactly stored at or near the leaf nodes of the accelerated structure. In a specific implementation, when constructing a given accelerated structure, the ray tracing circuitry is configured as a pre-quantized set of primitives and stored compactly (e.g., in a compressed format) within a given node of the structure (e.g., as nodes generated between internal nodes and leaf nodes of the BVH). These nodes are referred to below as “pre-filter nodes”. Furthermore, the low-precision intersection testers simultaneously test rays against multiple primitives based on data decoded from the data blocks and / or pre-filter nodes to find candidate primitives requiring full-precision intersection. Primitives that generated indeterminate results during the low-precision testing are retested using full-precision testers to deterministically determine whether a ray-triangle hit or miss occurs. Simultaneous (i.e., parallel) testing of primitives using low-precision testers accelerates the elimination of instances that do not require full-precision testing. As described herein, a deterministic intersection result or a deterministic test result is considered to mean that the ray-object intersection test definitively determines whether a ray intersects an object, and if so, at what point. Conversely, an indeterminate test result means that the ray intersection test cannot definitively determine whether a ray intersects an object. In one embodiment, the test result can be considered deterministic or indeterminate based on how the ray intersects the object relative to the boundary formed by the object. In another embodiment, an intersection plane can be created around each object, and the intersection or miss of the ray relative to the intersection plane can be used to determine whether the ray definitively hits the object, definitively misses the object, or whether the intersection test is indeterminate. Other embodiments are envisioned. In the following text, the terms “low precision” and “reduced precision” are used interchangeably unless otherwise stated. Similarly, the terms “full precision” and “high precision” are used interchangeably unless otherwise stated.

[0021] Referring now to FIG1, a block diagram of a specific embodiment of computing system 100 is shown. In one embodiment, computing system 100 includes at least processors 105A-N, input / output (I / O) interface 120, bus 125, memory controller 130, network interface 135, memory device 140, display controller 150, and display 155. In other embodiments, computing system 100 includes other components and / or computing system 100 is arranged in a different manner. Processors 105A-N represent any number of processors included in system 100. In several embodiments, one or more processors of processors 105A-N are configured to execute a plurality of instructions to perform the functions described herein with reference to FIGS. 4 through 8.

[0022] In one implementation, processor 105A is a general-purpose processor, such as a central processing unit (CPU). In another implementation, processor 105N is a data-parallel processor with a highly parallel architecture. Data-parallel processors include graphics processing units (GPUs), digital signal processors (DSPs), field-programmable gate arrays (FPGAs), application-specific integrated circuits (ASICs), etc. In some implementations, processors 105A-N include multiple data-parallel processors. In one implementation, processor 105N is a GPU that provides pixels to display controller 150 to drive display 155.

[0023] Memory controller 130 represents any number and type of memory controllers that can be accessed by processor 105A-N. Memory controller 130 is coupled to any number and type of memory devices 140. Memory devices 140 represent any number and type of memory devices. For example, the types of memory in memory devices 140 include dynamic random access memory (DRAM), static random access memory (SRAM), NAND flash memory, NOR flash memory, ferroelectric random access memory (FeRAM), etc.

[0024] I / O interface 120 represents any number and type of I / O interface (e.g., Peripheral Component Interconnect (PCI) bus, PCI-Extended (PCI-X), PCIe (PCI High Speed) bus, Gigabit Ethernet (GBE) bus, Universal Serial Bus (USB)). Various types of peripheral devices (not shown) are coupled to I / O interface 120. Such peripheral devices include (but are not limited to) monitors, keyboards, mice, printers, scanners, joysticks or other types of game controllers, media recording devices, external storage devices, network interface cards, etc. Network interface 135 is used to receive and send network messages over a network.

[0025] In various embodiments, computing system 100 is any of a computer, laptop, mobile device, game console, server, streaming device, wearable device, or various other types of computing system or device. It should be noted that the number of components in computing system 100 varies depending on the embodiment. For example, in other embodiments, there may be more or fewer of each component than shown in Figure 1. It should also be noted that in other embodiments, computing system 100 includes additional components not shown in Figure 1. Furthermore, in other embodiments, computing system 100 is constructed differently than shown in Figure 1.

[0026] As used below, "intersection tester," "intersection test filter," or simply "tester" refers to a dedicated hardware component that includes circuitry configured to perform ray tracing calculations in graphics rendering. In various implementations, these components include ray tracing (RT) kernels and tensor kernels. RT kernels include dedicated hardware circuitry specifically designed for ray tracing calculations. They are responsible for performing ray-object intersection tests to determine how light interacts with objects in the scene. Additionally, tensor kernels include dedicated hardware for accelerating certain aspects of ray tracing and other machine learning workloads. In the implementations described herein, low-precision (or reduced-precision) intersection test filters are configured to perform ray intersection tests using quantized (reduced)-precision objects, such as triangles. Similarly, full-precision intersection test filters are configured to perform ray intersection tests with high (or full)-precision calculations.

[0027] Turning now to Figure 2, which shows a block diagram of another specific embodiment of computing system 200. In one embodiment, system 200 includes a GPU 205, system memory 225, and local memory 230. System 200 also includes other components not shown to avoid obscuring the figures. GPU 205 includes at least an instruction processor 235, control logic unit 240, dispatch unit 250, compute units 255A-N, memory controller 220, global data sharing 270, level 1 (L1) cache 265, and level 2 (L2) cache 260. In other embodiments, GPU 205 includes other components, one or more of which are omitted from the diagram, multiple instances of which are present (even if only one instance is shown in Figure 2), and / or are organized in other suitable ways. In one embodiment, the circuitry of GPU 205 is included in processor 105N (of Figure 1). System 200 also includes ray tracing circuitry 280, which includes at least node decompression circuitry 281, test circuitry 282, and memory 284.

[0028] In various implementations, computing system 200 executes any software application from various types of software applications. As part of executing a given software application, the host CPU (not shown) of computing system 200 initiates a core to be executed on GPU 205. Command processor 235 receives the core from the host CPU and uses dispatch unit 250 to issue corresponding wavefronts to computing units 255A-N. The wavefronts executing on computing units 255A-N read and write data to the global data share 270, L1 cache 265, and L2 cache 260 within GPU 205. Although not shown in Figure 2, in one implementation, computing units 255A-N also include one or more caches and / or local memories within each computing unit 255A-N. As described below, certain types of circuitry are referred to as “units” (e.g., decoding units, computing units, arithmetic logic units, functional units, memory management units, etc.). Therefore, unless otherwise stated, the term “unit” also refers to circuitry.

[0029] As shown in the figure, the ray tracing circuitry 280 is independent of the GPU 205; however, in alternative implementations, the ray tracing circuitry 280 may be internal to the GPU 205 or otherwise formed as part of the GPU 205. Such implementations are envisioned. In one implementation, the ray tracing circuitry includes a test circuitry 282 configured to test rays against primitives included, for example, within an accelerated structure such as a bounding volume hierarchy (BVH). The test circuitry 282 also includes multiple low-precision (or “reduced precision”) test filters 286a-286n and a full-precision test filter 288. It should be noted that although only a single full-precision test filter 288 is shown for simplicity, multiple full-precision filters may be implemented based on application details in various implementations.

[0030] In one implementation, ray tracing circuitry 280 is configured to perform ray tracing operations to render a three-dimensional (3D) scene by using an acceleration structure, including testing the intersection between rays and objects in the scene geometry. In some implementations, most of the processes involved in ray tracing are performed by a programmable shader program executing on compute units 255A-N. In some implementations, ray tracing circuitry 280, as described herein, includes dedicated hardware components or dedicated processing units designed to accelerate ray tracing, a rendering technique used in computer graphics to generate highly realistic images by simulating the interaction of light and objects in a scene.

[0031] During operation, a ray intersection test is performed to determine whether a ray originating from a given (starting) source intersects a geometric primitive (e.g., a triangle, an implicit surface, or a complex geometric object). When an intersection point is identified, the distance from the ray's origin to the intersection point is calculated. In a specific implementation, ray tracing tests use a spatial representation of nodes, such as those in BVH. In BVH, each non-leaf node represents an axis-aligned bounding box that defines the geometry of all its child nodes. In one example, the root node represents the largest volume on which the ray intersection test is performed. Leaf nodes represent the triangles or other geometric primitives on which the ray intersection test is performed.

[0032] In a specific implementation, when constructing the acceleration structure, the ray tracing circuitry 280 is configured to store primitive-related data in a compressed data format. In one or more implementations, the acceleration structure may be formed as a combination of a top-level acceleration structure (TLAS) and a bottom-level acceleration structure (BLAS). TLAS (e.g., internal nodes) includes a hierarchical data structure that organizes a collection of BLAS (e.g., leaf nodes) representing individual geometric objects or primitives within the scene. TLAS is designed to quickly traverse rays through the scene by identifying relevant BLAS instances that may intersect with rays. In a specific implementation, data corresponding to, for example, the geometric primitives to be used to construct the acceleration structure may be provided in a pre-compressed format, allowing the ray tracing application to compute the compressed geometric representation and upload the data to GPU memory for further processing.

[0033] In one implementation, to encode the graph data used to construct the accelerated structure, primitives are clustered and stored in fixed-size data blocks (hereinafter referred to as "Dense Geometry Format" or DGF blocks). Each DGF block stores data corresponding to primitives that are spatially localized in a given scene. That is, the data in each DGF block corresponds to primitives that can be grouped together to represent a single node of the accelerated structure (e.g., an inner node of the underlying accelerated structure or a BLAS internal node). Because the primitives are clustered before the resulting accelerated structure is constructed, the construction speed can be significantly improved. In the example, a predetermined number of DGF blocks (e.g., storing data for a total of 65-128 primitives) can be combined to form a data node representing a single BLAS internal node of the BVH. For example, at the point in time when these data nodes are baked, a data node reference is generated for each data node storing multiple DGF blocks. This reference can be mapped to the BLAS node it represents. The BLAS node is constructed based on the data node reference. The node can then be combined with other TLAS and BLAS nodes to complete the construction of the BVH.

[0034] In one implementation, a DGF block is a fixed-size data block, for example, an array of data blocks totaling 128 bytes that encode primitive data. In this example, each DGF block stores a maximum of 64 primitives and 64 vertices. This data structure enables the mesh to be divided into small, spatially localized sets of primitives and each set to be “packed” into a minimum number of DGF blocks. An example DGF block is illustrated with reference to Figure 4.

[0035] In another implementation, the primitive data can also be compressed using "pre-filter nodes." In this implementation, when constructing a given acceleration structure, the ray tracing circuit 280 is configured as a prequantized primitive set and stored compactly (e.g., in a compressed format) within a given node of the structure (e.g., as a node generated between internal and leaf nodes of the BVH). These nodes are referred to below as "pre-filter nodes." An exemplary pre-filter node is illustrated with reference to Figure 3. The prequantized primitive set can be tested simultaneously for a single ray. In one implementation, leveraging the prequantization of primitives, if an intersection test using a low-precision test has indicated that no primitive in the prequantized primitives can be hit by a given ray, the ray tracing circuit 280 does not need to perform a full-precision test of the primitives. If the low-precision test is indeterminate for one or more primitives in the primitive set, then a full-precision test is performed only for those one or more primitives.

[0036] In a specific implementation, to prequantize the set of primitives to generate pre-filter nodes, the ray tracing circuit 280 is configured to calculate the boundary around the set of primitives and, for compactness, round the smallest corner of the resulting bounding box (e.g., round down to a "bfloat16" (16-bit floating-point) value). Furthermore, in this implementation, the largest corner of the bounding box is rounded up, such that the bounding box has a power of two size in each dimension. A power-of-two box size provides computational benefits because the bounding box can be compactly stored, for example, by storing only the smallest corner of the power-of-two box size and the bfloat16 value of the exponent bytes. Moreover, the processing efficiency of the ray tracing circuit 280 can be improved by quantizing the primitives, since multiplying and dividing floating-point values ​​by powers of two can be simply performed by adding or subtracting the floating-point value from the exponent contained within the floating-point value. Similarly, multiplying or dividing integers by powers of 2 can also be done by shifting bits to the left or right. In one implementation, the data associated with the prequantized primitives and the full-precision primitives is stored in memory 284.

[0037] In operation, when performing intersection testing, the ray tracing circuit 280 simultaneously and in parallel uses multiple low-precision test filters 286 to test a given ray against a compressed primitive set (stored using DGF nodes or pre-filter nodes). The node decompression circuit 281 decodes data corresponding to the compressed primitive set from the encoded primitive data stored in the DGF nodes and / or pre-filter nodes. By simultaneously testing the primitive set using low-precision test filters 286, the ray tracing circuit 280 can eliminate instances where the ray does not hit a triangle. This eliminates the need to use full-precision testing to test all instances. That is, for each primitive set, low-precision intersection testing can filter the primitive list before full-precision intersection testing. Since full-precision intersection testing has high hardware requirements, using multiple low-precision intersection test filters (such as parallel filters 286) reduces the number of full-precision tests required. This saves computational resources (and potential silicon space) and improves the efficiency of the ray tracing circuit 280.

[0038] In one implementation, low-precision test filter 286 performs simultaneous primitive tests in parallel. These tests are used by shader programs running on compute units 255A-N to generate images using ray tracing. The generated images are then queued for display by command processor 235. In this implementation, by utilizing the compression of primitive data, if an intersection test using low-precision tests has indicated that a given ray cannot hit any quantized primitive, the ray tracing circuit 280 does not need to perform full-precision tests on triangles. If the low-precision tests are indeterminate for one or more primitives, full-precision tests are performed only for those primitives. By reducing the number of full-precision tests performed, the computational efficiency of the system can be improved.

[0039] Turning now to Figure 3, a block diagram illustrating the compression of primitive data using a pre-filter node is depicted. It should be noted that while the example in Figure 3 describes the compression of triangle data, similar methods can be extended to perform data compression and encoding for data corresponding to other primitive types.

[0040] In a specific implementation, using pre-filter nodes, a quantization circuit (not shown) is able to quantize triangles and group them into primitive groups within the leaf nodes of the acceleration structure. As depicted, multiple pre-filter nodes 304-a to 304-n are generated between the internal node 302 and leaf node 308 of a given acceleration structure (such as a bounding volume hierarchy). In a specific implementation, pre-filter nodes are generated to filter out triangles (both individual triangles and groups of triangles) and create primitive groups 306. In one implementation, primitives from internal node 302 are quantized (i.e., to generate low-precision primitives) and stored as pre-filter nodes 304. Furthermore, full-precision primitives can be stored as primitive groups 306. For full-precision intersections, access to primitive groups 306 may depend on the uncertain results of low-precision tests from pre-filter nodes 304. In one specific implementation, pre-filter node 304 and primitive group 306 cumulatively form leaf node 308 of BVH, because a given branch of the structure can be replaced by pre-filter node 304 and primitive group 306, and test circuitry (e.g., test circuitry 282) together performs primitive intersection tests on BVH.

[0041] In another specific implementation, pre-filter node 304 is generated as the last layer of internal nodes 302. In this case, if a definite result of such a test is determined, the test circuit stops testing after testing pre-filter node 304. That is, for nodes that provide definite test results, the test circuit does not need to continue testing the full-precision triangles stored as primitive group 306. More specifically, low-precision intersection is performed by a low-precision tester on pre-filter node 304, while full-precision intersection testing is performed by a full-precision intersection tester on primitive group 306 (each time the low-precision tester generates an indeterminate result).

[0042] As shown in the figure, internal nodes 302 include internal nodes 302-a to 302-n. In one specific implementation, each internal node 302 corresponds to a bounding body that surrounds its child nodes (internal nodes or leaf nodes with triangles). For example, internal node 302-b includes individual triangles 310 and 314 and an overlapping set of triangles 312. Furthermore, internal node 302-n includes overlapping sets of triangles 316 and 318. Other internal nodes may similarly include triangles and sets of triangles. In the example, a pre-filter node 304-b is generated, which contains individual triangles 310 and 314 and an overlapping triangle 312 corresponding to internal node 302-b. Similarly, a pre-filter node 304-n corresponding to internal node 302-n is generated, which includes overlapping triangles 316 and 318.

[0043] In a specific implementation, the quantization circuit quantizes the individual triangles and overlapping triangles corresponding to the pre-filter node 304 and stores them compactly in the BVH node, for example, as primitive groups in the leaf node. For example, primitive groups 306-1 and 306-2 are generated from pre-filter node 304-b, where group 306-1 includes individual triangles 310 and 314, and group 306-2 includes overlapping triangle 312. Furthermore, primitive groups 306-3 and 306-4 are generated corresponding to pre-filter node 304-n, such that group 306-3 includes a set of overlapping triangles 316, and group 306-4 includes a set of overlapping triangles 318. It should be noted that the method described herein can also be used to filter objects other than triangles, and such specific implementations are conceivable.

[0044] In one specific implementation, to prequantize the triangle groups in the leaf node—that is, to generate primitive grouping 306—the boundary around each group of triangles in the leaf node is calculated, and the minimum angle of the resulting bounding box is rounded down to a bfloat16 value. Furthermore, the maximum angle of the bounding box is rounded so that the box has a power of two size in each dimension (thus allowing the quantization circuit to store the box size as a power-only, exponential, or other suitable compact integer). Once the bounding box is optimized, the node and box positions, along with the quantized triangle vertex coordinates (relative to the bounding box quantization) of all triangles grouped together within a given leaf node, are stored together in the BVH.

[0045] In one implementation, by pre-quantizing the triangles, if the quantized triangles used in the test demonstrate that none of them are actually hit by the light, then the test circuit does not need to acquire high-precision triangle data at all. In another implementation, only a subset of the high-precision triangle data can be extracted, for example, associated with the quantized triangles that produce uncertain results from the intersection test.

[0046] Figure 4 illustrates a Dense Geometry Format (DGF) block 400 used to store encoded primitive data. Similarly, while the example in Figure 4 describes compression of triangle data, similar methods can be extended to perform data compression and encoding for data corresponding to other primitive types.

[0047] In one implementation, DGF block 400 stores encoded data corresponding to triangle vertices, as well as triangle mesh data. In this implementation, the triangle vertex data is encoded using a signed “fixed-point mesh.” As described herein, a “fixed-point mesh” refers to a representation of triangle vertices using fixed-point coordinates instead of floating-point values. In one implementation, a fixed-point mesh is used due to its lower memory requirements and faster processing speed. A signed fixed-point mesh divides a coordinate space (e.g., a 2D plane or 3D space) into a mesh consisting of fixed-size cells or grids. Each vertex of a triangle is quantized by mapping its floating-point position to a grid cell within the fixed-point coordinate space. The floating-point position is multiplied by a scaling factor (e.g., a power of two scaling factor) to convert it to a fixed-point value. For each vertex of a triangle (or other geometric primitive), its position is quantized into a grid cell using a fixed-point representation. The quantized grid cell serves as an approximation of the original floating-point position. In this implementation, the data corresponding to the quantization of the vertex includes a 24-bit signed anchor position in the mesh. It also stores the variable-width (e.g., 1-16 bits) unsigned offset for each vertex (relative to the anchor position). Finally, a power-of-2 scaling factor used to map the quantized mesh to the floating-point coordinates of each triangle vertex is stored as the "IEEE bias index".

[0048] In one implementation, encoded vertex data and other triangle data are stored as part of a triangle mesh data set. The triangle mesh data comprises a set of vertices, each defined by its position (e.g., in 3D space) and additional attributes such as normals, texture coordinates, or color. The mesh is composed of triangles, each defined by an index pointing to the vertex data. For example, triangle meshes are typically stored using optimized data structures such as bounding volume hierarchies (BVH) or k-dimensional trees (KD trees). These structures spatially organize triangles to accelerate ray-triangle intersection testing.

[0049] In one implementation, triangle stripes and index buffers are used to encode mesh connectivity data. Triangle stripes are used to describe and render continuous surfaces or objects composed of triangles. In a triangle strip, each triangle shares an edge with the preceding primitive in the sequence. This shared edge is formed by two consecutive vertices from the vertex list. In one implementation, by sharing vertices between adjacent triangles, primitive stripes require less vertex data compared to individual triangle data, which reduces memory consumption and improves rendering performance.

[0050] In one or more embodiments, the index buffer comprises a fixed number of control values ​​for triangles in a triangle strip. Each control value indicates the position of a triangle relative to a previously identified triangle in the strip. In an embodiment, as described later, the length (or size) of the index buffer is determined based on the contents of the control values. The index buffer comprises a set of bits, where each bit corresponds to the index of a given vertex of a triangle. The index buffer is organized into two parts. The first part comprises a bit array, storing one bit per vertex, indicating whether a first index (hereinafter referred to as "first index") of a given vertex has been encountered. The second part comprises "N" bits for each index to store each non-first index to a vertex (hereinafter referred to as "non-first index"), where the value of N is predefined and stored in the data block header. In an embodiment, the index buffer (which can be calculated by an incrementing counter) is compressed by first reordering the vertices and omitting the storage of the first index corresponding to each vertex.

[0051] In one implementation, the primitive identifier can be derived from the triangle's position in the stripe and therefore does not need to be explicitly stored in the data block, further reducing memory usage. In another implementation, the data block also includes encoded geometry identifiers (GeomIDs). These can be encoded in two modes, referred to as "constant mode" and "palette mode." In constant mode encoding, the geometry ID field in the data block stores the geometry ID applied to all triangles and an opacity flag (indicating whether the triangle is opaque or transparent to incident light). In palette mode, the geometry ID field is interpreted based on the least significant bit (LSB) and most significant bit (MSB). These and other implementations will be explained in further detail with reference to the following description.

[0052] As shown in the figure, DGF block 400 is a fixed-size data block, for example, consisting of multiple buffers storing encoded triangle data and totaling 128 bytes. In this example, DGF block 400 stores a maximum of 64 triangles and 64 vertices. This data structure enables the division of a triangle mesh into small, spatially localized sets of triangles and the "packaging" of each set into a minimum number of DGF blocks.

[0053] In one specific implementation, the first five double words (“Dwords”) of DGF block 400 include a fixed header 402, the structure of which is shown in the figure (all bit fields are ordered from least significant bit (LSB) to most significant bit (MSB)). “Dwords” generally refer to a “double word” in the context of computer memory, which is a data unit twice the size of a standard word. The specific size of a double word can vary depending on the computer architecture and the word size of the system. For the specific implementation described herein, a word is 16 bits (2 bytes), and Dwords will be 32 bits (4 bytes). The layout of header 402 is given by the following pseudocode. As shown in the figure, vertex data 404 is packed in DGF block 400 in ascending vertex order 420, immediately following header 402. In one specific implementation, each vertex is 4-byte aligned. Furthermore, the size of the vertex data segment is also byte aligned. Padding bits can be inserted as needed, and all padding bits must be zero. Padding bits are used to align data with byte boundaries, which reduces hardware decoding costs. Additionally, as described herein, a "byte-aligned" buffer refers to a memory region storing data such that each data element or structure begins at an address that is a multiple of a certain byte boundary. This alignment ensures that data can be accessed efficiently by the processor, especially on architectures that require specific alignment for optimal performance.

[0054] Block 400 also includes an optional opaque micromap (OMM) palette 406 starting on the next byte boundary, and an optional geometry identifier (GeomID) palette 408 starting on the byte boundary following vertex data 404 and OMM palette 406. The region containing header 402, vertex data 404, GeomID palette 408, and OMM palette 406 is referred to as the “front buffer” 422. In one specific implementation, the front buffer 422 is byte-aligned, and its total size may be less than or equal to 96 bytes.

[0055] As previously mentioned, vertices are defined on a signed 24-bit quantized grid. Vertex data 404 stores the following: a 24-bit signed anchor position for each coordinate, a variable-width (1-16 bits) unsigned offset for each vertex (relative to the anchor position), and a power-of-2 scaling factor (stored as an IEEE bias exponent) used to map from the quantized grid to floating-point world coordinates. The decoded floating-point vertex positions can be calculated using the following pseudocode. Using this encoding scheme, the largest representable value is (0x7fffff + 0xffff) * 2^127 = 8,454,142 * 2^127 (approximately 1.438e+45), and the smallest representable value is (0x800000 * 2^127) = -8,388,608 * 2^127 (approximately -1.427e+45). This is a larger theoretical dynamic range than IEEE floating-point. The smallest and largest IEEE floating-point numbers that can be encoded using DGF block 400 appear at exponent 2^32 and integer positions 0x800001 and 0x7fffff (decimal values ​​-8388607 and 8388607). These values ​​are: -340282326356119256160033759537265639424.000000 and +340282326356119256160033759537265639424.0.

[0056] In a specific implementation, DGF block 400 can support exponent values ​​from 1 to 2^32. In one implementation, if the DGF block encodes an exponent value outside the supported range, all ray-triangle intersection tests for that block may have undefined results. However, ray tracing applications can ensure error-free results across blocks by selecting matching quantization factors for any two adjacent blocks. This can be done by selecting a uniform quantization factor across the entire mesh. In another implementation, a combination of base position and vertex offset during encoding can lead to errors in the mesh containing very large triangles. This issue can be addressed by selecting a coarser-grained quantization factor (trading down accuracy), subdividing the large problematic triangles (automatically or manually), or restoring to the uncompressed geometry of the problematic asset.

[0057] As described above, triangle stripes are used to encode the mesh topology. In one implementation, the order in which vertices are stored is used to minimize the size of the topology encoding. That is, data is not stored every time a new vertex is first referenced; instead, a counter is used to identify the first reference. To encode the mesh topology, the following data structures are generated: triangle control bits 324 and index buffer 426. Triangle control bits 424 include two control bits for each triangle, indicating the triangle's position relative to the previous two triangles. Furthermore, the length of index buffer 426 is determined by the contents of the control bits. Index buffer 426 is further organized into two segments: a first index buffer 412, which stores bits representing the first reference to a given vertex in a given strip; and non-first index buffers 410, each representing a non-first reference to a given vertex.

[0058] In one implementation, the index buffer is compressed by first reordering the vertices and omitting the storage of the first index for each vertex, as identified by the "is-first bit". This allows the first index of a given vertex to be calculated simply by using a counter, for example by counting the number of "is-first" bits encountered before a given vertex. In the example, a single "is-first" bit for each index is used to indicate whether it is the first index of its corresponding vertex. In one example, the first three indices of each vertex are always "first references", and therefore there is no need to store the corresponding "is-first" bits for these indices. As shown, the data in the first index buffer 412 is stored in ascending index order 428. In the implementation, each zero bit in the "is-first" vector has an index. The number of indices in the buffer is the number of zero bits in the "is-first" bit vector. The index of a "is-first" bit that is 1 can be calculated by counting the bits instead of explicitly storing them.

[0059] In practice, control bits and "is first" indices are allocated from the back of the block, which makes hardware decoding easier because the data is indexed from a known starting position and reduces the computation required to locate the data for a specific triangle. Furthermore, the first index buffer is ordered in ascending order to ensure the buffer is consistent with the vertex data (thus avoiding the need to store a large number of indices).

[0060] Furthermore, for non-first index buffers 410, the number of bits for each non-first index is stored in header 402. In one example, the valid values ​​for the number of bits for each non-first index can be 0, 1, 2, and 3, encoding 3 bits, 4 bits, 5 bits, and 6 bits respectively. In one specific implementation, the total size of first index buffer 412 is less than or equal to 24 bytes. Additionally, as shown, non-first index buffers 410 are immediately adjacent to the front buffer 422. Data in non-first index buffers 410 is stored in vertex ascending order 432. Triangle control bit 424 is located at the end of DGF block 400, and first index buffer 412 is stored directly in front of triangle control bit 424.

[0061] In one implementation, the DGF block 400 further stores a geometry identifier (GeomID 408) and an opaque micromap marker (OMM marker 406). The GeomID 408 can be used to uniquely identify and reference a specific geometric entity or element within a scene. This identifier facilitates efficient management and manipulation of geometric data in various graphics applications. Furthermore, the OMM marker can contain Boolean or numerical values ​​associated with a material or object to control its opacity properties. The GeomID 408 and OMM marker 406 can be stored in two different modes, with the mode selected based on the geometry ID field in the header 402. The two different modes include a constant mode and a palette mode. The constant mode is selected when the field value is 0, and the palette mode is selected when the field value is 1.

[0062] In constant mode, bit 0 of geometry ID field 408 includes an opacity flag, and bits 1-9 store geometry identifiers. These values ​​are used for all triangles. In this mode, no additional data is stored in block 400, and more space is available for vertex data. In palette mode, the geometry ID field is interpreted as LSB and MSB. For example, the LSB (4:0) encodes the GeomID prefix size in bits (5b, 0-25), and the MSB (9:5) encodes the GeomID count (5b, 1-32) (1 bit is added during decoding). For example, in palette mode, geometry ID field 408 is used to store palette attributes. For example, the higher bits encode the number of geometry identifiers in the palette. The lower bits store the number of bits (25 bits total) that have the same value in all IDs, which are stored only once and not repeatedly. In palette mode, the GeomID palette structure is inserted into the block (as shown in GeomID408). The position and size of the palette structure are aligned with byte boundaries. In one implementation, additional pads can be added as needed; however, all pads must be zero.

[0063] In one implementation, the GeomID 408 palette consists of a prefix value and a per-triangle index buffer. The bit length of the prefix value is given in 5 LSBs of the Geometry ID field 408, and each triangle index buffer identifies the payload to be used for each triangle. The size of each index is given by ceil(log2(GeomID count)), where ceil is the top function that returns the GeomID function of the smallest integer greater than or equal to the parameter. Additionally, an array of N-bit payloads is provided, where N is 25-prefixSize. In this implementation, the size of each triangle index field is only as large as needed to index all stored values. Furthermore, ceil(log2(GeomID count)) gives the required number of bits (using the ID count from the Geometry ID field 408). Each payload LSB contains an opacity flag. The 25-bit GeomID and opacity flag of a given triangle are decoded by selecting the payload from the payload buffer and concatenating it with the prefix value. The following pseudocode illustrates the process: In a non-restricted example, assuming a total of 8 triangles, the GeomID for each triangle is given as follows: 1, 4, 1, 1, 4, 3, 1, and 4. There are 3 unique ID values ​​(1, 4, and 3), so the number of palette entries is counted as 3. In binary, these values ​​(as 25-bit numbers) are given as follows: 0000000000000000000000001, 000000000000000000000100, and 0000000000000000000000011. The higher 22 bits are identical (all zeros in this case), so the prefix size is 22. In palette mode, the Geometry ID field 408 is a 10-bit field split in half. The first 5 bits contain the number of entries, for example, encoded using offset -1 (encoded values ​​0…31 correspond to 1…32). For 3 palette entries, the encoded value is calculated as 2. The lower 5 bits contain the prefix size (2^2). Therefore, the value stored in the geometry ID field 408 will be: (2<<5)+2^2=86. The palette has 47 bits of data (25 bits for the ID value and 22 bits for the prefix size). An extra zero bit is added at the end to align it with the byte boundary (48 bits in total). The resulting bits are given as follows: 00000000000000000000000 001 100 011 00 01 00 00 01 10 00 01 0.

[0064] In the specific implementation, the prefix bits are stored first. In this case, the prefix bits consist of 22 zero bits. Next, the non-shared low bits of each ID are stored. In this case, each of the three IDs has 3 bits: 001 (decimal: 1), 100 (decimal: 4), and 011 (decimal: 3). Finally, the index of each triangle from which the ID is selected is stored. The number of bits for each index depends on the number of IDs. In this case, there are 3 IDs to choose from, which means 2 bits per triangle, and there are 8 triangles, so a total of 16 bits. The decimal index of each triangle is: 0,1,0,0,1,2,0,1. In binary, these values ​​can be represented by 00 01 00 00 01 10 00 01.

[0065] In one implementation, the OMM palette 406 (if present) is also byte-aligned. Padding bits are inserted as needed, and all such bits must be zero. The OMM palette 408 includes "hot-patched" sections and "pre-computed" sections (not shown). When building the acceleration structure, the hot-patched sections are patched at runtime with OMM information. The pre-computed sections are calculated by the encoding circuitry when data is encoded within the DGF 400. The size and location of the hot-patched sections can be exposed to one or more applications via an API. However, the exact contents of the hot-patched sections are not exposed. When encoding a DGF block intended for use with the OMM, the encoding circuitry reserves space for the hot-patched sections and stores the pre-computed sections immediately afterward. In one example, the hot-patched sections contain 8 bytes, and each OMM descriptor contains an additional 4 bytes. The application using the block initializes this space with zeros. The pre-computed sections include an index for each triangle indicating which OMM descriptor to use. The triangles are ordered from front to back in ascending order 430. The number of bits for each index is derived from the OMM descriptor count field in header 402. Pre-computed segments are padded to the next byte boundary, and all padding bits must be zero. In one or more implementations, unused space in DGF block 400 (e.g., data not stored and / or otherwise generated by OMM palette 406 or GeomID palette 408) can be used to store additional vertex data.

[0066] Figure 5 is a block diagram illustrating ray testing using compressed primitive data. In the example shown in Figure 5, ray intersection testing is described for testing rays against triangles. However, in various implementations, other primitives can be tested similarly. In implementations, compressed triangle data is stored using DGF nodes (as described with respect to Figure 4), pre-filter nodes (as described with respect to Figure 3), or a combination of pre-filter nodes and DGF nodes. The example shown in Figure 5 only describes intersection testing triangles based on data decoded from DGF nodes. An intersection test using a combination of DGF nodes and pre-filter nodes is described in Figure 6.

[0067] The compressed triangle data is fed into an array of low-precision intersection testers (e.g., testers 286a-n described in Figure 2), and triangles not rejected by the low-precision intersection testers (e.g., those generating indeterminate intersection results) are forwarded to the full-precision intersection testers for final intersection testing. Using low-precision intersection testers to filter out triangles before the final intersection test reduces the area required for batch ray-triangle intersections because low-precision intersection testers are cost-effective and filter the data before joining the more expensive full-precision testers.

[0068] In operation, the intersection scheduler (not shown) requests the node decompressor 500 to decode the encoded triangle data (DGF node data) stored in the DGF nodes used for the intersection pipeline (e.g., pre-filter pipeline 520) for intersection testing. As used herein, the pre-filter pipeline is a processing pipeline formed using procedures and / or circuitry involved in decoding the encoded triangle data stored in the DGF nodes and / or pre-filter nodes and simultaneously performing a low-precision intersection test on a single ray for each triangle in a given set of triangles represented by the decoded data. In one embodiment, the intersection scheduler forwards the entire decoded data to the pre-filter pipeline 520 in consecutive clock cycles (e.g., the set of triangles for each clock cycle of the pre-filter pipeline 520). Furthermore, for each triangle that survives the intersection test performed using the pre-filter pipeline 520, high-precision triangle data is decoded from the encoded node data and forwarded to the high-precision or triangle pipeline 530 for further testing. In practice, the DGF block is kept in a buffer during the duration of the process.

[0069] As shown in the figure, the DGF block is first processed to decode index data (block 502) from the encoded DGF node data. In the example, the DGF block is processed by one or more index decoders to extract the index data. As described with reference to Figure 4, the encoded triangle data in the DGF block is stored as a triangle mesh. The triangle mesh data includes a set of vertices, where each vertex is defined by its 3D position and additional attributes such as normals, texture coordinates, or color (as described above). Furthermore, each triangle is defined by an index pointing to the corresponding vertex data. In one implementation, triangle strips and index buffers are used to encode the triangle mesh data. In a triangle strip, each triangle shares an edge with the previous triangle in the sequence. This shared edge is formed by two consecutive vertices in the vertex list. In one implementation, by sharing vertices between adjacent triangles, triangle strips require less vertex data compared to individual triangles, which reduces memory consumption and improves rendering performance.

[0070] In one or more embodiments, the index buffer includes a fixed number of control bits (e.g., 2 bits) for each triangle in the triangle strip, where each control bit indicates the position of the triangle relative to a previously identified triangle in the strip. In one embodiment, the control values ​​include a “RESTART” bit, an “EDGE1” bit, an “EDGE2” bit, and a “BACKTRACK” bit. In one embodiment, the RESTART bit is 0 (bit “00”), and these bits are used to start a new strip, specifying the 3 vertex indices of the triangle. Furthermore, the EDGE1 bit (value 1, bit “01”) indicates that the second side of the last identified triangle is reused as the first side of the current triangle. Similarly, the EDGE2 bit (value 2, bit “10”) indicates that the third side of the last identified triangle is reused as the first side of the current triangle.

[0071] In one implementation, the BACKTRACK bit (value 3, bit "11") indicates that the opposite edge of the preceding triangle of the last identified triangle is reused. In this implementation, if the last triangle used EDGE2, the "opposite edge" is given by the EDGE1 bit, or if the last triangle used EDGE1, the "opposite edge" is given by the EDGE2 bit. Furthermore, backtracking is not used to form the current triangle unless the last triangle was formed using EDGE1 or EDGE2. That is, backtracking is not used to form the current triangle after a new stripe is initiated or if the last triangle was formed using backtracking. It should be noted that when the edge of a previously identified triangle is reused, the reused edge is always the first edge in the new triangle, and the other two edges connect to a new vertex, which is always the third vertex in the triangle.

[0072] As previously mentioned, the length (or size) of the index buffer is determined based on the contents of the control bits. For example, the index buffer has 1 bit for each triangle and an additional two bits for each triangle with a control bit of 0. The control bit for the first triangle in a new strip is always 0, and therefore the first 3 bits are always 1 and are not stored. The index buffer consists of two segments, each storing a set of bits, where each bit corresponds to a triangle vertex. The first segment of the index buffer includes a data array of "is-first" bits. Each "is-first" bit indicates whether it is the first index corresponding to a given vertex. The second segment includes a second bit array, where each index stores "N" bits to store each non-first index, where the value of N is predefined, and the value of N is stored in the data block header. In one specific implementation, the index buffer is compressed by first reordering the vertices and omitting the storage of the first index for each vertex, as identified by the "is-first bit". This makes it possible to calculate the first index of a given vertex by simply using a counter, for example by counting the number of "is-first" bits encountered before the given vertex. In the example, a single "is first" for each index is used to indicate whether it is the first index of its corresponding vertex. Furthermore, non-first indices are stored directly in a tightly packed buffer (i.e., a data structure where elements are stored contiguously without any additional padding or alignment between them).

[0073] In one specific implementation, the following exemplary procedure is used to process DGF blocks for decoding index data: In one implementation, the DGF data is further decoded (e.g., via a ray tracing engine) to extract axis-aligned bounding boxes (AABBs) from the DGF block data (box 506). AABBs are used to set up a ray-triangle intersection test to efficiently test whether a ray intersects a given triangle. As previously described, to compress the triangle data to be stored in the DGF block, triangle vertices are defined on a signed 24-bit quantized grid. The encoded vertex data in the DGF block includes the following: a 24-bit signed anchor position for each coordinate, a variable-width (1-16 bits) unsigned offset for each vertex (relative to the anchor position), and a power-of-2 scaling factor (stored as an IEEE bias exponent) for mapping from the quantized grid to floating-point world coordinates. In this implementation, the AABB is extracted based on the anchor position (“A”), the exponent (“x”), and the bit width (“w”) of the unsigned offset. The lower bound of AABB is given by the following example sequence: Min = int_to_float(A) * 2^x. In addition, the range of powers of 2 of the box is calculated as: range = 2^(x + w).

[0074] In a specific implementation, anchor values ​​and exponent values, along with other triangle data, are fed into the pre-filter pipeline 520. For example, using index data decoded from DGF node data, low-precision vertex data corresponding to AABB is extracted (box 504). In one implementation, low-precision vertex data can be generated by shifting each stored vertex left or right to align it with the bit width (“Q”) of the pre-filter pipeline 520. As described herein, the bit width of a phase intersection pipeline (such as the pre-filter pipeline 520) defines the number of bits used to perform low-precision intersection tests. The bit width can be constant for different implementations chosen based on a tradeoff between precision and silicon area. Furthermore, as used herein, “shift” means moving a binary number to the left or right by a certain number of positions. Shifting can be used for tasks such as powers like multiplication or division by two, bit manipulation, and performance optimization. The left shift (<<) operation shifts all bits of a binary number to the left by a specified number of positions. For each left shift, the binary number is effectively multiplied by 2. The right shift (>>) operation shifts all bits of a binary number to the right by a specified number of positions. For each right shift, the binary number is effectively divided by 2 (rounded to negative infinity).

[0075] In one implementation, a left shift is performed if the stored offset is less than 10 bits; otherwise, a right shift is performed. The shift offset (O) is calculated from the vertex offset (v) using the following exemplary sequence: O = v << (Qw).

[0076] When the (Qw) subexpression is negative, a right shift is performed to generate low-precision vertex data. The following pseudocode illustrates the generation of low-precision vertex data: Based on low-precision vertex data, a set of triangles (e.g., included within the extracted AABB) is published to a pre-filter pipeline 520 for testing the ray using a low-precision intersection tester. The low-precision tester targets all triangles in the set for testing the ray. In a specific implementation, a decompressor 500 feeds decoded triangle data to the low-precision testers in parallel, e.g., for each set of triangles per clock cycle of the low-precision tester. Furthermore, triangle data from each set of triangles is fed to each low-precision tester, e.g., at a rate of N triangles per clock cycle (batch testing), where N is determined based on the width of the low-precision tester (i.e., the number of bits each tester can process simultaneously) and the number of low-precision tests that can be issued per clock cycle. Additionally, the number of triangles in a given set of triangles is determined based on the total number of low-precision intersection testers, the number of vertex decoders (as shown in Figure 6), and the control bits associated with each triangle (which determine the number of vertices to be consumed). In practice, because triangle connectivity is encoded using triangle stripes, where triangles in each strip share vertices with other triangles, a predetermined number of vertices from each set are retained so that they can be reused when testing triangles in the next set. Using triangle stripes to drive intersection scheduling allows full throughput to be achieved with a smaller number of vertex decoders.

[0077] In a practical implementation, the triangle pipeline 530 is driven by a “hit triangle mask” corresponding to triangles not rejected by the low-precision intersection tester (i.e., triangles with uncertain intersection results). As used herein, the triangle pipeline includes processes and / or circuitry involving decoding encoded triangle data stored in DGF nodes and / or pre-filter nodes, and performing a high-precision intersection test on a single ray for each triangle in a given set of triangles represented by the decoded data. Furthermore, the hit triangle mask is a data structure, for example, comprising a bit array associated with each candidate triangle. Each bit in the array corresponds to a triangle and indicates whether that triangle intersects with a ray. This mask can be efficiently updated during the intersection test to mark which triangles are hit by the ray.

[0078] In response to processing the hit triangle mask, decompressor 500 further decodes the encoded triangle data from the DGF nodes to generate high-precision vertex data (box 508). In one specific implementation, high-precision vertex data (V) of the triangle is generated by calculating the sum of each vertex offset (v) and anchor point (A), converting this sum to a floating-point value, and applying a power-of-2 scaling to the converted sum to generate a scaled sum. The scaled sum then represents the high-precision vertex data. This is illustrated using the following exemplary sequence: V = int_to_float(A+v) * 2^x.

[0079] The following pseudocode describes the generation of high-precision vertex data: High-precision vertex data, along with primitive identifiers and geometric identifiers associated with each triangle, is forwarded to the triangle pipeline. This is illustrated in boxes 510 and 512. In a specific implementation, the primitive identifier for each triangle is given by adding 29 bits per block basis to the triangle position in the strip. Furthermore, the geometric identifier is extracted based on the corresponding encoding pattern (i.e., constant pattern or palette pattern), as described with reference to Figure 4. The decoded high-precision vertex data, along with the primitive and geometric identifiers, is forwarded to triangle pipeline 530 for a final intersection test using a full-precision intersection tester. In one implementation, triangles that produce indeterminate results from low-precision intersection tests can be subjected to a full-precision test. In one implementation, the encoded triangle data stored in the DGF node allows both low-precision and high-precision vertex data to be generated from the same encoded data, thus eliminating data duplication.

[0080] In the specific implementation described in this paper, parallel rejection testing of large triangle groups enables the ray tracing circuitry to perform numerous ray-triangle intersections without acquiring additional node data (because the data can be simply decoded from the DGF node without copying data across multiple memory locations). This improves the computational bandwidth ratio of ray traversal and provides a corresponding speedup. These methods further reduce the area required for volume ray-triangle intersections by using an inexpensive low-precision pipeline to filter data before a more expensive full-precision pipeline.

[0081] In one or more embodiments, the decompressor 500 in the pre-filter pipeline 520 is configured to support decoding of data from both the pre-filter node and the DGF node (as shown in Figure 6). In one embodiment, the intersection scheduler pipelines data decoding requests to the decompressor 500 for multiple rays merged for the same node. All rays merged for the same node are sent first before switching to another node. The decompressor 500 switches to the next ray only after decoding the last batch test of the current ray. Furthermore, the decompressor 500 switches to the next node only after decoding the last batch test of the last ray of the current node it is processing.

[0082] Turning now to Figure 6, a node decompressor 600 is depicted for decoding encoded triangular data stored within DGF nodes and / or prefilter nodes. In the example shown in Figure 6, dashed and dotted lines depict processes or components that are reserved separately for DGF nodes or prefilter nodes or shared between prefilter nodes and DGF nodes (according to the legend provided at the bottom of the figure).

[0083] As described above, decompressor 600 is configured to support decoding of data from both pre-filter nodes and DGF nodes. In a specific implementation, an intersection scheduler pipelines data decoding requests (e.g., scheduler request 605) to decompressor 600 for multiple rays merged for the same node. In response to a scheduler request, decompressor 600 accesses node data 601 from the pre-filter node and / or DGF node. Parser 602 parses the pre-filter node data (procedure box 610) and DGF node data (procedure box 615) separately. The parser parses each distinct node to extract index data 625, vertex data 630, and sideband data 620 (e.g., application-defined data depending on the triangle order (such as the color, normal, or index buffer for each triangle)). In one example, index data 625 includes up to 64 bytes of data, and vertex data 630 includes up to 96 bytes of data. These data limitations can be configured when encoding data using DGF blocks and / or pre-filter nodes. In addition, the data can be stored in a local memory buffer allocated to the decompressor (e.g., parser storage device 604).

[0084] In a specific implementation, the data stored in the resolver storage device 604 is used to extract the axis-aligned bounding box (AABB) for ray setups that will be tested against multiple triangles. According to the specific implementation, the AABB is used to set up a ray-triangle intersection test to test whether a ray intersects with a set of triangles. As previously mentioned, to compress the triangle data to be stored in the DGF block, the triangle vertices are defined on a signed 24-bit quantized grid. The encoded vertex data in the DGF block includes the following: a 24-bit signed anchor position for each coordinate, a variable-width (1-16 bits) unsigned offset for each vertex (relative to the anchor position), and a power-of-2 scaling factor (stored as an IEEE bias exponent) for mapping from the quantized grid to floating-point world coordinates. In the example, the AABB is extracted based on the anchor position, the exponent, and the bit width of the unsigned offset.

[0085] In one implementation, vertex offset data decoded using vertex data 630 (from the parsed DGF node 615) and pre-filtered vertices decoded using the parsed pre-filter node 610 are accessed by vertex decoder 612. Additionally, index data 625 is accessed by index decoder 606. Index decoder 606 includes pre-filter index decoder 608 and DGF index decoder 610. Pre-filter index decoder 608 decodes a first predetermined number of indices per clock cycle and feeds these indices to the same number of pre-filter vertex decoders 614. DGF index decoder 610 also decodes a second predetermined number of indices per clock cycle. In one example, each triangle may require fewer than 3 indices to provide from DGF index decoder 610 to vertex decoder 612. DGF index decoder 610 must know the triangle boundaries and does not send local triangles to vertex decoder 612. Furthermore, in addition to the decoded indices, DGF index decoder 610 also sends the primitive ID, "is first bit," and control bits for each triangle in each batch. This data can be stored in a buffer for later use in primitive assembly, for example, in a first-in, first-out manner. In a specific implementation, the DGF index decoder 610 decodes the control bits of the next two triangles following the current triangle set, so that the vertices of the current set can be reused in the primitive assembly of the next set.

[0086] In a specific implementation, the pre-filter vertex decoder 614 uses pre-filter vertex data accessed from the parser storage device 604 and indexes extracted by the pre-filter index decoder 608 to decode the quantized triangle vertices. In one example, the quantized triangle vertices include three vertices for each triangle. In another implementation, the DGF / pre-filter vertex decoder 616 is configured to decode data to extract vertices from both the DGF node and the pre-filter node. For example, the DGF / pre-filter vertex decoder 616 decodes the quantized triangle vertices based on the pre-filter vertex data accessed from the parser storage device 604 and the indexes decoded by the pre-filter index decoder 608. Furthermore, the DGF / pre-filter vertex decoder 616 can also decode DGF vertex offsets based on vertex offset data accessed from the parser storage device 604 and the indexes decoded by the DGF index decoder 610.

[0087] Decoded vertex data from both the pre-filter node and the DGF node is fed into primitive assembly process 618. Within primitive assembly process 618, DGF vertex setting 645 is performed, where low-precision vertices (disclosed in Figure 5) are generated from the decoded vertex offsets. These vertices are forwarded to DGF primitive assembly 660, where the triangles corresponding to the vertices are assembled into triangle sets for traversal and intersection testing with set rays. In one implementation, a predefined number of vertices are retained from the set at the end of each intersection test for a triangle set for reuse in the primitive assembly of the next set. In the example shown in the figure, four vertices from a previous batch (box 665) are stored, which are reused by DGF primitive assembly 660 for the current triangle set for ray testing. This is done because triangles are interconnected using triangle stripes and vertices are shared between triangles.

[0088] Furthermore, the vertex data corresponding to the pre-filter nodes is used by the pre-filter primitive assembly 655. In a specific implementation, within the primitive assembly 655, low-precision triangles from the pre-filter nodes are grouped, for example, stored as leaf nodes of an accelerated structure. Additionally, high-precision primitives can be stored as primitive groups (as disclosed in Figure 3). For full-precision intersection, access to primitive groups depends on the uncertain results of the low-precision tests from the pre-filter nodes. In one implementation, the pre-filter nodes and primitive groups cumulatively form the leaf nodes of the BVH, as a given branch of the structure can be replaced by the pre-filter nodes and primitive groups, and the test circuitry together performs primitive intersection tests on the BVH. Based on the low-precision tests of the triangles grouped within the pre-filter nodes, the triangle data 670 of triangles not rejected by these tests is forwarded to the triangle pipeline for full-precision testing.

[0089] On the other hand, during the DGF primitive assembly 660, a low-precision intersection tester is used to simultaneously test triangles in the triangle set against the ray. In a specific implementation, a “hit triangle mask” corresponding to triangles not rejected by the low-precision intersection tester (i.e., triangles with uncertain intersection results) is forwarded to the triangle pipeline (as triangle data 670). As described herein, the hit triangle mask is a data structure, for example, including a bit array associated with each candidate triangle. Each bit in the array corresponds to a triangle, indicating whether the triangle intersects with the ray. This mask can be efficiently updated during the intersection test to mark which triangles are hit by the ray. In response to processing the hit triangle mask, the decompressor 600 can further decode the data from the DGF nodes to generate high-precision vertex data (as disclosed in Figure 5). This high-precision vertex data is used by the full-precision intersection test to further test triangles not rejected by the low-precision tester. For the pre-filter node, high-precision triangles corresponding to the quantized triangles that were not rejected by the low-precision tester are extracted from the corresponding primitive group (as shown in Figure 3).

[0090] In a specific implementation, the intersection test results of rays and triangle sets are serialized to the triangle pipeline to perform full-precision intersection tests. Triangles rejected by the low-precision intersection tester are not sent to the triangle pipeline except for the last test of a ray or the last test of the last ray. The last test must be indicated to the triangle pipeline to allow for the clearing of ray results and the popping of DGF node data. In one implementation, triangle data 670 includes ray data sent to the triangle pipeline once per ray, and only for rays requiring full-precision triangle testing. The last ray to be tested will not have a corresponding full-precision test to be sent to the triangle pipeline. However, after processing the last ray, it is still necessary to clear the DGF node data, and therefore, a virtual last test transaction for the last ray can be sent to the triangle pipeline to allow for the popping of DGF node data.

[0091] In various specific implementations, the method described in this paper describes ray-triangle phase exchange pipelines that use parallel low-precision ray-triangle intersection tests to generally reject large groups of triangles at once. Triangles are stored in a compressed format, which allows for the generation of both low-precision and high-precision triangles from the same data, thus eliminating data duplication. Furthermore, the parallel rejection tests on large groups of triangles enable the ray tracing system to perform numerous ray-triangle intersections without acquiring additional node data. This improves the computational bandwidth ratio of ray traversal and provides a corresponding speedup. The technique described in this paper further reduces the area required for volume ray-triangle intersections by filtering data before the more expensive full-precision pipeline using an inexpensive low-precision pipeline. Large-batch ray-triangle intersections, in turn, improve the efficiency of ray tracing because they eliminate the need for fine-grained spatial partitioning at the triangle level, resulting in lower memory footprint and lower memory bandwidth during traversal.

[0092] Figure 7 illustrates a method for decoding metadata used for primitive-ray intersection tests. As described above, the metadata is encoded in one of two ways: using pre-filter nodes and primitive grouping (as shown in Figure 3) and / or using DGF nodes (as shown in Figure 4). Based on which method is used to encode the metadata, the ray tracing system can decode the data accordingly and perform an intersection test for each primitive.

[0093] In one implementation, the ray tracing circuitry receives metadata for encoding ray test primitives (box 702). The ray tracing circuitry can determine whether the data is encoded using a pre-filter node or a DGF node (condition box 704). If the data is encoded using a pre-filter node (condition box 704, "pre-filter" branch), the ray tracing circuitry decodes the metadata stored in the pre-filter node (box 706). In this implementation, the decoded data corresponding to primitives (e.g., triangles) included in the pre-filter node is then used for a first intersection test on the ray test primitives (box 708). The first intersection test serves as a first pass to distinguish quantized primitives that explicitly intersect or miss the ray. Furthermore, for example, a low-precision intersection test filter (as described in Figure 2) is used to perform the first intersection test simultaneously for each primitive against a single ray. The number of low-precision intersection test filters can be determined based on the number of primitives within the pre-filter node, among other factors.

[0094] Based on the results of the first intersection test, it is further determined whether an indeterminate result is obtained for one or more quantized primitives (condition box 710). If no indeterminate result is obtained (condition box 710, "No" branch) (i.e., a definite intersection result (hit or miss) is obtained for all tested primitives), the method continues to box 722. At box 722, the results of the intersection test are provided to the renderer or rendering circuitry. In a specific implementation, the rendering circuitry uses the result data from the intersection test to calculate shadows and lighting at specific points on the primitive surface. This includes evaluating surface properties (e.g., color, texture, normals) and applying a lighting model to determine how the primitives interact with light sources in the scene. Other specific implementations are envisioned.

[0095] In the event of one or more uncertain results (condition box 710, "Yes" branch), a full-precision tester retests the primitives for which these uncertain results were generated for a given ray pair to perform a second intersection test (box 712). In a specific implementation, the full-precision tester uses a floating-point mechanism and tests the ray for the given primitive with a higher precision than that used for the first intersection test. Furthermore, in a specific implementation, a single full-precision tester may be associated with multiple low-precision testers operating in parallel, such that the full-precision primitives corresponding to the primitives that obtained uncertain test results during the first intersection test can be retested by the full-precision tester to definitively determine whether the ray hit or missed the primitive. The result of the second intersection test can then be provided to the rendering circuitry (box 722), which can use the result to render an image or scene.

[0096] In one specific implementation, when data is encoded using DGF nodes (condition box 704, "DGF" branch), low-precision vertex data is generated for each primitive by decoding the encoded data stored in the DGF nodes (box 716). Based on the low-precision vertex data, a low-precision intersection test is performed simultaneously on the primitive set for a given ray (box 718). Based on the results of the low-precision intersection test, it is determined whether an indeterminate result is obtained for one or more primitives (condition box 720). If no indeterminate result is obtained (condition box 720, "No" branch) (i.e., a definite intersection result (hit or miss) is obtained for all tested primitives), the method continues to box 722. At box 722, the results of the intersection test are provided to the renderer or rendering circuitry.

[0097] In the presence of one or more uncertain results (condition box 720, "Yes" branch), high-precision vertex data is generated by further decoding the encoded data from the DGF nodes (e.g., for primitives presenting uncertain results) (box 724). Based on the high-precision vertex data, these primitives are retested for a given ray using a full-precision tester (box 712), and the method continues to box 722. At box 722, the results of the intersection test are provided to the rendering circuitry.

[0098] It should be emphasized that the above-described specific embodiments are merely non-limiting examples. Many variations and modifications will become apparent to those skilled in the art once the above disclosure is fully understood. The following claims are intended to be interpreted as covering all such variations and modifications.

Claims

1. An apparatus, the apparatus comprising: A circuit configured to generate low-precision vertex data for each primitive in a set of primitives included in encoded primitive data; The low-precision vertex data is used to simultaneously perform a first ray intersection test for the rays of each primitive; And in response to the first ray intersection test, generate an uncertain intersection result for one or more primitives in the primitive set: generate high-precision vertex data for each of the one or more primitives; And using the high-precision vertex data, a second ray intersection test is performed on the ray for each of the one or more primitives.

2. The apparatus of claim 1, wherein for each primitive in the primitive set, the encoded primitive data includes: The anchor position of each coordinate of each vertex in three-dimensional space; And the offset of each vertex relative to the anchor position.

3. The apparatus of claim 2, wherein, in order to generate the high-precision vertex data, the circuitry is configured to, for each vertex of each of the one or more primitives, calculate the sum of the offset and the anchor position; Convert the sum to a floating-point number; And apply a scaling factor to the transformed sum to generate a scaled sum representing high-precision vertex data for a given vertex.

4. The apparatus of claim 2, wherein, in order to generate the low-precision vertex data, the circuit is configured to: calculate the bounding box of each primitive; and extract the low-precision vertex data corresponding to the bounding box.

5. The apparatus of claim 4, wherein, in order to generate the low-precision vertex data, the circuit is further configured to perform a logical shift bit on the offset of each vertex.

6. The apparatus of claim 1, further comprising graphics processing circuitry configured to render an image based on one or more primitives from the set of primitives, the one or more primitives being identified as intersecting with the ray by one of a first ray intersection test and a second ray intersection test.

7. The apparatus of claim 1, wherein the circuitry is configured to perform the second ray intersection test individually on the one or more primitives.

8. A method, the method comprising: The ray tracing circuitry generates low-precision vertex data for each primitive in the primitive set included in the encoded primitive data. The ray tracing circuit simultaneously performs a first ray intersection test for each primitive using the low-precision vertex data; in response to the first ray intersection test generating an indeterminate intersection result for one or more primitives: the ray tracing circuit generates high-precision vertex data for each of the one or more primitives; and the ray tracing circuit performs a second ray intersection test for each of the one or more primitives using the high-precision vertex data.

9. The method of claim 8, wherein for each primitive in the primitive set, the encoded primitive data includes: The anchor position of each coordinate of each vertex in three-dimensional space; And the offset of each vertex relative to the anchor position.

10. The method of claim 9, wherein, in order to extract the high-precision vertex data, the method further comprises, for each vertex of each of the one or more primitives: calculating the sum of the offset and the anchor position by the ray tracing circuit; converting the sum to a floating-point number by the ray tracing circuit; and applying a scaling factor to the converted sum by the ray tracing circuit to generate a scaled sum representing high-precision vertex data for a given vertex.

11. The method of claim 9, wherein, in order to generate the low-precision vertex data, the method further comprises: The bounding box of each primitive is calculated by the ray tracing circuit; The ray tracing circuit generates low-precision vertex data corresponding to the bounding box by aligning the offset of each vertex with the bit width of the intersection test processing pipeline.

12. The method of claim 11, wherein, in order to generate the low-precision vertex data, the method further comprises performing a logical shift bit on the offset of each vertex by the ray tracing circuit.

13. The method of claim 8, further comprising rendering an image by a graphics processing circuit based on one or more primitives from the set of primitives, the one or more primitives being identified as intersecting with the ray by one of a first ray intersection test and a second ray intersection test.

14. The method of claim 8, further comprising performing the second ray intersection test on the one or more primitives individually by the ray tracing circuit.

15. A ray tracing system, the ray tracing system comprising: A memory configured to store encoded image data; The circuit is configured to: generate low-precision vertex data for each primitive in a set of primitives included in the encoded primitive data; simultaneously perform a first ray intersection test for rays of each primitive using the low-precision vertex data; generate an indeterminate intersection result for one or more primitives in response to the first ray intersection test; and generate high-precision vertex data for each of the one or more primitives. And using the high-precision vertex data, a second ray intersection test is performed on the ray for each of the one or more primitives.

16. The ray tracing system of claim 15, wherein for each primitive in the primitive set, the encoded primitive data includes: The anchor position of each coordinate of each vertex in three-dimensional space; And the offset of each vertex relative to the anchor position.

17. The ray tracing system of claim 16, wherein, in order to generate the high-precision vertex data, the circuitry is configured to, for each vertex of each of the one or more primitives, calculate the sum of the offset and the anchor position; Convert the sum to a floating-point number; And apply a scaling factor to the transformed sum to generate a scaled sum, wherein the scaled sum represents high-precision vertex data for a given vertex.

18. The ray tracing system of claim 16, wherein, in order to generate the low-precision vertex data, the circuitry is configured to: compute a bounding box for each primitive; and extract low-precision vertex data corresponding to the bounding boxes.

19. The ray tracing system of claim 18, wherein, in order to generate the low-precision vertex data, the circuitry is further configured to perform a logical bit shift for each vertex offset based at least in part on the difference between the bit width of the intersection test processing pipeline and the bit width of the variable width offset for each vertex.

20. The ray tracing system of claim 15, wherein the circuitry is configured to perform the second ray intersection test individually on the one or more primitives.