Dense geometry formats
By encoding geometric primitives into fixed-size data blocks using Dense Geometry Format (DGF), the problem of redundant vertex data storage in ray tracing is solved, enabling efficient storage and rendering of large triangular mesh models, and improving rendering performance and compression efficiency.
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-08
AI Technical Summary
Existing technologies in ray tracing suffer from redundant storage of vertex data in graphics scenes and low rendering efficiency. Traditional compression methods impose significant constraints on ray tracing and rasterization applications and cannot achieve fine-grained control and efficient storage.
The Dense Geometry Format (DGF) is used to efficiently encode geometric primitives into fixed-size data blocks. A signed fixed-point mesh is used to encode vertex data, and memory consumption is reduced through triangle stripes and index buffers, enabling efficient ray-triangle intersection testing.
It enables efficient storage and rendering of large triangular mesh models, reduces memory consumption, improves rendering performance, and provides fine-grained control over compression rate, making it suitable for direct consumption by fixed-function hardware.
Smart Images

Figure CN122003699A_ABST
Abstract
Description
[0001] Cross-reference to related applications This application claims priority to provisional patent application No. 63 / 591,964, filed on October 20, 2023, entitled “Dense Geometry Format”, 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 through a process called "ray traversal." This involves calculating the intersections between rays and scene objects by navigating through and intersecting nodes organized in a bounding volume hierarchy (BVH).
[0003] The standard approach to performing ray tracing or rasterization 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, the geometry shader generates vertex information linked to each vertex of that primitive or geometric object. For example, when processing a triangle, the geometry shader will provide vertex information for each of the triangle's three vertices. This vertex data can include details such as the vertex's position within the scene, overlay data associated with the vertex, or a set of attributes linked to the vertex, and so on. When the geometry shader generates graphical primitives or geometric objects, it typically organizes each generated graphical primitive, or each primitive forming part or all of the generated geometric object, into a set of vertices associated with that primitive, and corresponding vertex data for each vertex within that set.
[0005] However, in various scenarios, geometry shaders typically maintain multiple redundant copies of vertex data linked to vertices shared between graphics primitives or geometric objects. This practice becomes problematic due to the potentially large number of shared vertices in a typical graphics scene. Consequently, a conventional geometry shader may end up storing millions of duplicate data copies. Handling such redundant data inefficiently consumes computational resources and can hinder the rendering speed of the graphics scene.
[0006] Traditional methods for compressing geometric data can impose significant constraints on ray tracing or rasterization applications. These methods may include using lossy compression to compress data without providing any fine-grained control over content creation. Traditional methods may also involve generating fixed mesh topologies, resulting in limited flexibility and inefficient memory management. Furthermore, these methods typically involve expensive and complex preprocessing of the data before it can be used for rendering purposes.
[0007] In view of the above, there is a need for improved systems and methods for compressing map data. Attached Figure Description
[0008] 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 It is a block diagram of a specific implementation of a computing system.
[0009] Figure 2 The details of the computing system are illustrated.
[0010] Figure 3 This is an example based on the specific implementation of the enclosing volume hierarchy (BVH).
[0011] Figure 4 This is a block diagram illustrating the encoding of graph data used to generate accelerated structures.
[0012] Figure 5 An example of a dense geometry format (DGF) block used to store encoded graph data is shown.
[0013] Figure 6 The example illustrates triangular stripes used to encode grid topology data.
[0014] Figure 7 This is a block diagram illustrating the generation of a compressed index buffer based on grid topology data.
[0015] Figure 8 An example is given of a method for storing geometry metadata using fixed-size data blocks. Detailed Implementation
[0016] 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.
[0017] This document discloses systems, apparatuses, and methods for efficiently encoding geometric primitives into blocks of data. In specific implementations, these blocks can be directly consumed by processing circuitry (e.g., a GPU) for ray traversal or rasterization. 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 that uses fixed-point coordinates instead of floating-point values. In one specific implementation, fixed-point meshes are used due to their 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 associated with vertex quantization 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".
[0018] In one implementation, coded 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 normal vector data, 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.
[0019] 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 contiguous surfaces or objects composed of primitives. As described herein, in a primitive stripe, each primitive shares an edge with the preceding primitive in the sequence. This shared edge is formed by two consecutive vertices from a 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.
[0020] 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.
[0021] In one implementation, primitive identifiers can be derived from the primitive's position in 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). These and other implementations will be explained in further detail with reference to the following description.
[0022] The specific implementations described herein enable the compact storage of large mesh models in a manner that minimizes constraints on content creation and allows for direct rendering using encoded primitive data. In one implementation, fixed-size data blocks can be used to represent different types of primitive meshes, giving content creators fine-grained control over the compression rate, thus achieving a trade-off between accuracy and storage cost. Furthermore, the encoded data is stored in a manner suitable for direct consumption by fixed-function hardware (as opposed to computation-based shader rendering). Additionally, the data compression and storage disclosed herein enable lossy compression, with precise control over data loss and direct rendering of the compressed representation of primitive data.
[0023] Now for reference Figure 1 A block diagram of a specific embodiment of a computing system 100 is shown. In one embodiment, the 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, the computing system 100 includes other components and / or the computing system 100 is arranged in a different manner. Processors 105A-N represent any number of processors included in the system 100. In several embodiments, one or more processors of processors 105A-N are configured to execute a plurality of instructions to perform as referenced herein. Figures 4 to 8 The described functionality.
[0024] 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.
[0025] 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.
[0026] 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.
[0027] In various specific 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 specific embodiment. For example, in other embodiments, there may be a greater number of components than... Figure 1 The number of each component shown may be greater or less. It should also be noted that in other embodiments, the computing system 100 includes... Figure 1 Other components not shown. Additionally, in other embodiments, the computing system 100 differs from... Figure 1 Constructed as shown.
[0028] Turn now Figure 2 The diagram illustrates a block diagram of another specific embodiment of the 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, and multiple instances of the components (even if...) Figure 2 (Only one example is shown), and / or organized in other suitable ways. In one specific implementation, the circuitry of the GPU 205 includes ( Figure 1 The system 200 also includes a ray tracing circuit 280, which includes a compression circuit 284, an encoding circuit 286, and a memory 290.
[0029] In various specific 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 explicitly stated in the original text... Figure 2 As shown in the figure, but in one specific implementation, computing units 255A-N also include one or more caches and / or local memories within each computing unit 255A-N.
[0030] In one implementation, ray tracing circuitry 280 is configured to perform ray tracing operations using an accelerated tree structure (e.g., a bounding volume hierarchy or BVH), including testing the intersection between rays and objects in the scene geometry. In some implementations, much of the work involved in ray tracing is performed by a programmable shader program executing on compute units 255A-N. The ray intersection test emits rays from a starting source, determines whether the ray intersects with geometric primitives (e.g., triangles, implicit surfaces, or complex geometric objects), and if so, determines the distance from the origin to the intersection point of the triangle. In implementations, ray tracing tests use spatial representations of nodes, such as those included in the accelerated structure. For example, in a 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 maximum extent on the region on which the ray intersection test is being performed. For example, the root node may have child nodes, each representing a bounding box that typically divides the entire region. Each of these two child nodes may also have child nodes that also represent bounding boxes. Leaf nodes represent triangles or other geometric primitives on which ray intersection tests are performed (e.g., ... Figure 3 (As shown).
[0031] Furthermore, in a specific implementation, based on the tracing of rays within the scene geometry, an accelerated structure is formed by the command processor 235 and stored in system memory 225 and / or local memory 230. The tree is loaded into memory, and the command processor 235 further optimizes the hierarchical tree. Once a given accelerated structure is optimized, ray intersection tests are performed again, and the ray tracing circuitry 280 uses the optimized structure to retest ray intersections within a given scene geometry. These tests are used by shader programs running on compute units 255A-N to generate an image using ray tracing accelerated by the optimized structure. The updated image is then queued for display by the command processor 235.
[0032] In one specific implementation, triangular mesh models can be used to construct accelerated structures such as bounding volume hierarchies (BVH) or spatially partitioned meshes. When using these mesh models, geometric data defining the triangular mesh model is collected. This data can include vertex positions, vertex normals (vectors associated with vertices of the 3D mesh), texture coordinates, and connectivity information (defined by vertex indices). Each triangle in the mesh is then defined by three vertices and optionally includes other properties such as normals and texture coordinates. For each triangle, additional data (such as bounding boxes or bounding spheres) can be computed to quickly assess its spatial extent. For example, the bounding volume (typically an AABB axis-aligned bounding box) for each triangle in the mesh can be computed. The bounding box encapsulates the spatial extent of the triangle, thus providing a fast way to determine potential intersections without having to examine each triangle individually.
[0033] Triangles in a mesh can be sorted or partitioned to organize them spatially, enabling efficient construction of accelerated structures. Common approaches include using spatial meshes or hierarchical structures such as BVHs. Furthermore, depending on the chosen accelerated structure, sorted or partitioned triangles can be used to create hierarchical or mesh-based structures. In one example, to construct a BVH, a recursive partitioning process is initiated, where triangles are grouped based on a chosen partitioning heuristic (e.g., median partitioning or surface area heuristic). A tree structure is then constructed, where each node represents the bounding volume of the subset of triangles. In a BVH, leaf nodes directly store references to individual triangles.
[0034] In some implementations, optimization techniques can be applied during structure construction to enhance traversal and intersection performance. For example, the optimal dividing plane or mesh cell size can be selected based on scene statistics. Furthermore, memory layout can be optimized to efficiently utilize caches during traversal. Once the accelerated structure is built, supplementary processing can also be performed. This may involve refining the structure, balancing tree nodes, or storing additional data (such as pre-computed normals or material properties) to speed up ray tracing calculations.
[0035] In one or more specific implementations, large triangular mesh models can significantly increase rendering time in ray tracing due to the complexity of intersecting rays with detailed geometry. Ray-object intersection tests must be performed for every ray, and potentially for many triangles, leading to higher computational demands. Large triangular mesh models also require substantial memory resources for storage and processing during ray tracing. Memory-intensive data structures, such as acceleration structures, are needed to organize and efficiently access mesh data during ray-object intersection calculations. Ray tracing methods may also require additional memory for storing intermediate results (such as ray origins, directions, and shading information) during rendering.
[0036] Therefore, traditional models used in processing meshes for building accelerated structures can negatively impact content creation in ray tracing because they don't support compact storage of large triangular meshes. Furthermore, since ray tracing typically involves processing vast amounts of geometry and shading data, including vertex, normal, texture coordinates, and material properties, this data can be enormous, especially for complex scenes with detailed geometry. Traditional compression techniques may also fail to maintain the necessary accuracy of geometry and shading data to avoid visual artifacts or inaccuracies in rendered images. Additionally, these methods introduce overhead in terms of decompression time and memory usage. Compression techniques that disrupt sequential access patterns or require decompressing large chunks of data at once can be inefficient for real-time rendering. Moreover, lossy compression techniques sacrifice data fidelity for higher compression ratios. While this may be acceptable for certain types of data (e.g., textures), it can be problematic for geometry data where accuracy is critical.
[0037] In the specific implementation described herein, a data format for efficiently encoding geometric primitives into data arrays of fixed-size data blocks is disclosed, hereinafter referred to as Dense Geometry Format or DGF Blocks (e.g., 128-byte data blocks). In the specific implementation, these blocks can be directly consumed by processing circuitry (e.g., GPU 205) for ray traversal or rasterization. To create DGF blocks, vertex data is prequantized by compression circuitry 284 before being stored in a given block, and encoded by encoding circuitry 286 (e.g., a quantization mesh).
[0038] When encoding vertex data using variable-size integer offsets, compression circuitry 284 is configured to prequantize floating-point vertex coordinates into integers. In one example, the floating-point values are multiplied by a scaling factor and rounded to the nearest integer. The quantized integer values are then stored as offsets relative to a base point (e.g., the smallest vertex value in a triangle mesh). These offsets can be positive or negative. Finally, encoding circuitry 286 can encode the offsets for efficient storage. In the example, variable-size integers can be used to encode each component of a vertex individually (e.g., x, y, z). The encoded data can also include vectors (i.e., “normals” or “normal vectors”) specifying the direction perpendicular to the surface at the vertex. Normals are crucial for determining how light interacts with the surface, including calculating reflection, refraction, and shading. Furthermore, if the object is textured, the data can include texture coordinates specifying how the texture maps to the surface. This data can be stored in memory 290 for further processing by ray tracing circuitry 280.
[0039] In one implementation, the encoded vertex data and other triangle data are stored as a primitive mesh. In the context of ray tracing, a primitive mesh (e.g., a triangle mesh) refers to a collection of primitives representing a 3D surface or object, specifically tailored for rendering using ray tracing techniques. Primitive 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). The mesh is composed of primitives, where each primitive is 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 KD trees. These structures spatially organize triangles to accelerate ray-triangle intersection testing.
[0040] It should be noted that the specific implementation described herein pertains only to triangular meshes; however, similar techniques can be used to encode data corresponding to other primitive mesh types. In one implementation, encoding circuitry 286 uses triangle strips and an index buffer to encode triangular mesh connectivity data. As described herein, a "triangle strip" represents a series of connected triangles using a vertex sequence. Triangle strips 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 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.
[0041] In one or more implementations, 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 implementations, the length (or size) of the index buffer is determined based on the contents of the control bits (as will be discussed later). Figure 5 (As described in [reference]). The index buffer comprises two segments, each storing a set of bits, where each bit corresponds to a triangle vertex. The first segment of the index buffer comprises 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 comprises a second bit array, where each index stores "N" bits to store each non-first index, where the value of N is predefined and stored in the data block header. 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 makes it possible to compute the first index of a given vertex 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. 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).
[0042] In one implementation, the triangle identifier can be derived from the triangle's position within the triangle strip and therefore does not need to be explicitly stored in the data block, further reducing the required storage. Furthermore, the geometric identifier is encoded by the encoding circuit 286 in two modes: "constant mode" and "palette mode". In constant mode encoding, the geometry ID field in the data block stores the geometry ID and opacity flag applied to all triangles. In palette mode, the geometry ID field is interpreted based on the least significant bit (LSB) and most significant bit (MSB). Reference Figures 5 to 7 These and other specific implementations will be explained in further detail.
[0043] The specific implementations described herein enable the compact storage of large triangular mesh models in a manner that minimizes constraints on content creation and allows for direct rendering using encoded primitive data. In one implementation, fixed-size data blocks can be used to represent different types of primitive meshes, giving content creators fine-grained control over the compression rate, thus achieving a trade-off between accuracy and storage cost. In another implementation, the format of the data stored in the data blocks is aligned with the cache lines of the GPU 205. Furthermore, the encoded data is stored in a manner suitable for direct consumption by fixed-function hardware (as opposed to compute shader-based rendering). In one implementation, the encoding of triangular stripes, as disclosed herein, achieves smaller encoding bandwidth and cheaper decompression of the encoded data. Moreover, the compression and storage of the data disclosed herein enable lossy compression, where data loss is precisely controlled and the compressed representation of primitive data is rendered directly.
[0044] In specific implementations, as described herein, ray tracing circuitry 280 refers to a dedicated hardware component or processing unit designed to accelerate ray tracing, a rendering technique used in computer graphics to generate highly realistic images by simulating the behavior of light. Although shown as integrated with GPU 205, in one or more implementations, ray tracing circuitry 280 may also be a standalone hardware unit. These implementations are envisioned.
[0045] Figure 3 This is an example based on a specific implementation of the enclosing volume hierarchy (BVH). For simplicity, in Figure 3 In the exemplary embodiment depicted herein, the hierarchy is shown in two dimensions. However, in various alternative embodiments, it is possible to extend this to three dimensions, and it should be understood that the methods described herein are generally also applicable to three-dimensional hierarchies.
[0046] BVH spatial representation 302 in Figure 3 The left side is shown, and the tree representation of BVH is 304. Figure 3 The right side is shown. In one example, the bounding box is represented by "N", such that N1-N7 are distinct bounding boxes. In this example, bounding box N1 contains all other bounding boxes N2-N7. Furthermore, each bounding box N2-N7 includes one or more triangles, which represent geometric objects and are represented by "T". For example, bounding box N1 includes all other bounding boxes and their corresponding triangles T1-T8. In a similar manner, bounding box N2 includes smaller bounding boxes N5 and N4, such that N4 includes triangles T1 and T2, and N5 includes triangles T4 and T3. Furthermore, for simplicity, in tree representation 304, each bounding box is represented by a non-leaf node "N", and each triangle is represented by a leaf node T.
[0047] In order to perform ray tracing of the scene, the processing unit (e.g., Figure 2 The ray tracing circuit 280 performs ray intersection tests by traversing tree 304, and for each bounding box tested (i.e., by traversing the corresponding internal node N), if the test for that node fails, the branches below the traversed node are eliminated. In one example, assume ray 1 intersects triangle T5 as the closest hit. The processing unit will test bounding box N1, and then, after returning a hit, retrieve the resulting child nodes containing the bounding boxes for the next level below N1 (nodes N2 and N3). When the node data is returned from memory, the bounding boxes of N2 and N3 are tested. The processing unit returns a failure or miss result for bounding box N2 (because ray 1 does not interact with the bounding box). The processing unit eliminates all child nodes of node N2. Since ray 1 does interact with bounding box N3, it will return a hit, and then subsequently retrieve N3 from memory, which contains the bounding boxes of N6 and N7. Then, by traversing their respective representative nodes N6 and N7, tests are performed on bounding boxes N6 and N7. Note that the test for node N6 succeeds, but the test for node N7 fails. Next, the processing unit tests triangles T5 and T6 by traversing representative leaf nodes T5 and T6. Note that the test determines T5 to be the closest hit by the ray, and therefore the test for T5 succeeds, but the test for T6 fails (even though the ray might hit T6, it is not the closest hit).
[0048] In a specific implementation, BVH 304 is generated using a given scene geometry. The scene geometry includes primitives describing a scene comprising one or more geometric objects provided by an application or other entity. In one implementation, software executing on a processor (such as command processor 235) is configured to perform the functions described herein, hard-wired circuitry is configured to perform the functions described herein, or a combination of both software executing on the processor and hard-wired circuitry is configured to perform the functions described herein. In various examples, BVH 304 is constructed using one or more shader programs (such as shader programs executing on a processing unit or on a hardware unit in the command processor). In various implementations, BVH 304 is constructed prior to runtime. In other examples, BVH 304 is constructed on the same computer that renders the scene at runtime using ray tracing technology. In various examples, such runtime rendering is performed by a driver, application, or hardware unit of the command processor.
[0049] In a specific implementation, a data structure comprising one or more data fields is stored in a memory location accessible to the processing unit, each data field containing information related to a different node of the BVH 304 to which an intersection test is to be performed. For example, the data structure is stored in system memory 225 or local memory 230 (e.g., Figure 2 As shown, the data structure is updated by the processing unit each time a hierarchical tree is created and / or updated. The exemplary data structure includes node metadata, such as, but not limited to, node identifiers, node surface regions, node subtree information, node locking states, and node bounding boxes.
[0050] In one or more implementations, BVH 304 can be structured as a combination of a top-level acceleration architecture (TLAS) and a bottom-level acceleration architecture (BLAS). A TLAS (e.g., nodes N2-N7) is a hierarchical data structure that organizes a set of BLAS representing various geometric objects or primitives (e.g., triangles T1-T8) within a scene. TLAS are designed to quickly traverse rays through a scene by identifying relevant BLAS instances that may intersect with rays. In implementations, data corresponding to, for example, the geometric primitives to be used to construct BVH 304 can be provided in a pre-compressed format, allowing ray tracing applications to compute the compressed geometric representation and upload that data to GPU memory for further processing.
[0051] In practice, pre-compressed graph data is stored in DGF blocks. Furthermore, before generating the compressed graph data, the graph elements are clustered in such a way that each DGF block stores data corresponding to graph elements spatially localized in a given scene. That is, the data in each DGF block corresponds to graph elements that can be grouped together to represent a single node (e.g., an internal node of the BLAS) in the accelerated structure. Because the graph elements are clustered before constructing the BVH, 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 graph elements) can be combined to form a data node representing a single internal node of the BLAS in the BVH. For example, when these data nodes are created, 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 corresponding BLAS node is then constructed based on the data node reference. This accelerated structure can be further combined with other TLAS and BLAS nodes to complete the construction of the BVH.
[0052] Now go to Figure 4A block diagram illustrating the encoding of metadata for generating accelerated structures has been described. As described above, geometric primitives included in the primitive mesh are encoded, and the encoded data is stored using a data array of fixed-size data blocks (e.g., 128-byte blocks) for direct consumption by processing circuitry (e.g., GPU 205) for ray traversal or rasterization. In one or more specific implementations, the encoded data is in "Dense Geometry Format (DGF)" data blocks (e.g., Figure 5 The DGF blocks are generated in the form of DGF blocks (as shown). As described herein, DGF blocks include various data buffers to store information related to vertex indices, geometric identifiers, mesh connectivity, and opacity data associated with each primitive in the mesh. In one specific implementation, a DGF block is a fixed-size data block, for example, consisting of an array of 128-byte data blocks encoding triangle data. In this example, each data block 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 this implementation, for optimal ray tracing performance, a surface area heuristic (SAH) clustering strategy is used to initially cluster the graph data 420 (box 402). SAH-based pre-clustering of the geometry accelerates BVH construction because the BVH builder receives efficient spatial partitioning and does not require constructing partitions from the original large set of triangles. Initially, all triangles are clustered in a single cluster representing the root of the BVH (e.g., BVH 304). Then, a splitting plane (axis-aligned) is selected to divide the current triangle cluster into two subclusters. In one implementation, the selection of the splitting plane is determined by evaluating different candidate planes based on SAH. For each candidate splitting plane, the SAH cost is evaluated, taking into account surface area cost and traversal cost. The splitting plane that minimizes the SAH cost is selected, and the current triangle cluster is divided into two subclusters based on the selected splitting plane. Each subcluster represents a child node in the BVH. This process is performed recursively for each child node (subcluster) until a termination condition is met (e.g., the maximum depth of the BVH, the minimum number of triangles per node, etc.).
[0054] In a specific implementation, the vertices corresponding to each triangle in each SAH cluster are encoded to generate quantized vertices for each triangle (box 404). In one example, vertices are defined on a signed fixed-point mesh to compress the vertex data. For example, for quantization of vertex-related data, the vertex data is first defined using a 24-bit signed base position in the mesh. In a specific implementation, a variable-width (e.g., 1–16 bits) unsigned offset is further generated for each vertex (relative to the base 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 exponent.” The IEEE bias exponent is a component used in the IEEE 754 standard to represent the floating-point representation of real numbers in a computer. In this standard, floating-point numbers are typically represented as a combination of three components (sign bit, exponent, and significant digits (or mantissa)). The bias exponent is a way of representing an exponent with a fixed offset that allows for a variety of comparisons and arithmetic operations.
[0055] In one implementation, the data obtained from vertex quantization is stored in DGF blocks, and multiple DGF block nodes are combined to create data nodes (box 406). In one example, each DGF block can store data for up to 64 triangles, while each data node can store data related to 256 triangles, 256 vertices, and 64 materials. In one implementation, each data node corresponds to a BLAS node of the BVH. The example shown in the figure depicts a BLAS node 470 (e.g., an internal node of the BVH to be constructed) corresponding to data node 480 (which stores multiple DGF block nodes 482). Furthermore, a reference corresponding to each data node is generated, for example, at the point where these data nodes are created. This reference can be mapped to the BLAS node represented by the data node. That is, these references can be used to construct BLAS nodes when constructing the BVH.
[0056] In one implementation, each DGF block also includes data related to triangle mesh connectivity (i.e., mesh topology data). According to this implementation, the mesh topology data is encoded using triangle stripes. For each triangle, two control bits are generated, indicating the triangle's position relative to two previously identified triangles within the strip. In one implementation, these bits are encoded such that they indicate the position of the currently processed triangle, for example, based on the positions of previously identified triangles within the strip. For example, the control bits may indicate whether a new strip needs to be initiated using the current triangle, whether the first side of the last identified triangle needs to be reused for the current triangle, whether the second side of the last identified triangle needs to be reused for the current triangle, or whether the opposite side of the preceding leading triangle needs to be reused for the current triangle.
[0057] In one implementation, an index buffer is created based on the contents of the control bits. The buffer is divided into two parts: a first array that stores bits identifying whether a given index is the first index of a given vertex ("is-first" bits); and a second array that stores bits related to non-first indices of vertices (non-first bits). The "is-first" bits include one bit for each vertex reference, indicating whether each vertex reference is the first reference to a given vertex. In one implementation, the index buffer is compressed by reordering the vertices first and omitting the storage of the first index for each vertex, as indicated 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 implementation, the first three vertex references of a triangle will always be "first" vertex references, and therefore there is no need to store the corresponding "is-first" bits for these references. Furthermore, "N" bits for each index are used to store non-first indices, where the value of N is predefined. In one specific implementation, the value of N is stored in the header of the corresponding DGF block.
[0058] In a specific implementation, the triangles within the mesh can be further reordered or rotated to maximize the compression of the mesh topology data. According to this implementation, the triangles within the mesh can be reordered, and the triangle vertices can be rotated while maintaining triangle curl. Preserving triangle curl within the mesh is crucial for maintaining the correct orientation of the triangles, which directly affects how the mesh is rendered and shaded in computer graphics. The curling order of the triangles (i.e., clockwise or counterclockwise curl) determines whether the triangles face away from the viewer, thus affecting visibility and rendering results such as shading, lighting, and culling.
[0059] The remapping table 422 performs a reordering of the mesh topology data. The remapping table 422 includes a data structure for transforming input values (i.e., the original generated mesh topology data) into corresponding output values (reordered mesh topology data) according to a predefined mapping. In one implementation, the remapping table 422 has one entry for each triangle. Each entry stores the index of a given triangle in the input triangle sort (0...N-1), and further stores the index of each vertex (referred to herein as "input vertex") corresponding to each of the triangle's three vertices (0, 1, or 2). This mapping can be used to reorder the mesh topology while preserving the original triangle sort.
[0060] Offline preprocessing can be used to perform reordering of mesh topology data using a sideband data buffer (box 408). In a specific implementation, the sideband data consists of an array of each triangle element (color, normal, etc.). When the topology is reordered, the sideband data also needs to be reordered to match the order in which the triangles were connected. For each element in the sideband data, the input index from the corresponding remapping table 422 entry is loaded, and the corresponding element from the sideband data is mapped to that entry. Furthermore, if the data depends on the order of the vertices in the original triangles, the input vertex sort from the remapping table 422 is used to rearrange the data accordingly.
[0061] Based on the reordering of triangles in the mesh, the corresponding index buffer data is also updated to generate reordered buffer data 426. The next step in this process is to encapsulate the encoded DGF block 424 and the reordered buffer data 426 (box 410) to generate encapsulated geometric data for ray tracing and rasterization operations.
[0062] The packaged geometric data undergoes processing (e.g., via a GPU or other processing circuitry) for use during runtime asset streaming (box 412), for example, for dynamically loading and accessing the geometric data into a software application or game during execution or runtime. In a specific implementation, during streaming operations, when the application requires specific triangle data, the micro BLAS node 480 can be accessed and processed by one or more application drivers or hardware systems (box 414). Reference Figure 5 The exemplary DGF block is discussed in detail.
[0063] Figure 5 An example of a Dense Geometry Format (DGF) block 500 for storing encoded graph data is illustrated. A DGF data block comprises various data buffers that store information related to vertex indices, geometry identifiers, mesh connectivity, and opacity data associated with each primitive in the mesh. In one specific implementation, DGF block 500 is a fixed-size data block, for example, consisting of multiple buffers storing encoded graph data and totaling 128 bytes. In this example, DGF block 500 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.
[0064] In one specific implementation, the first five double words (“Dwords”) of DGF block 500 include a fixed header 502, 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 example, on a 32-bit system, where a word is typically 32 bits (4 bytes), a Dword would be 64 bits (8 bytes). Similarly, on a 64-bit system, where a word is 64 bits (8 bytes), a Dword would also be 64 bits (8 bytes), but the term may still be used in the context. The layout of header 502 is given by the following pseudocode. As shown in the figure, vertex data 504 is packed in DGF block 500 in ascending vertex order 520, immediately following header 502. In one implementation, each vertex is 4-byte aligned. Furthermore, the vertex data segment size is also byte aligned. Padding bits can be inserted as needed, and all padding bits must be zero. In this implementation, padding bits are used to align data to byte boundaries, which reduces hardware decoding costs. 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.
[0065] Block 500 also includes an optional Opacity Micromap (OMM) palette 506 starting on the next byte boundary, and an optional Geometry Identifier (GeomID) palette 508 starting on the byte boundary following Vertex Data 504 and OMM Palette 506. The region containing Header 502, Vertex Data 504, GeomID Palette 508, and OMM Palette 506 is referred to as the “front buffer” 522. In one implementation, the front buffer 522 is byte-aligned, and its total size may be less than or equal to 96 bytes.
[0066] As previously mentioned, vertices are defined on a signed 24-bit quantized grid. Vertex data 504 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 500 appear at exponent 2^32 and integer positions 0x800001 and 0x7fffff (decimal values -8388607 and 8388607). These values are: -340282326356119256160033759537265639424.000000 and +340282326356119256160033759537265639424.0.
[0067] In a specific implementation, DGF block 500 can support exponent values from 1 to 2^32. In one implementation, if the DGF block encoding 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.
[0068] 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 code. That is, instead of storing data every time a new vertex is first referenced, a counter is used to identify the first reference. To encode the mesh topology, the following data structures are generated—triangle control bits 524 and index buffer 526. Triangle control bits 524 include two control bits for each triangle, indicating the position of the triangle relative to the previous two triangles (in...). Figure 6 (See detailed description below). Furthermore, the length of the index buffer 526 is determined by the contents of the control bits. The index buffer 526 is further organized into two segments: a first index buffer 512, which stores bits representing the first reference to a given vertex in a given strip; and a non-first index buffer 510, each representing a non-first reference to a given vertex.
[0069] 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 referenced", 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 512 is stored in ascending index order 528. Control bits and "is-first" indices are allocated from the end of block 500 and can make hardware decoding easier because the data is indexed from a known starting position and may require less computation to locate the data for a particular triangle. The ascending order of the first index buffer 512 makes the buffer data consistent with the vertex data (thus avoiding the need to store the number of indices). Furthermore, in the implementation, each zero bit in the "is-first" bit vector has an index. In other words, the number of indices in the first index buffer 512 is the number of zero bits in the "is first" bit vector. Indices with a "is first" bit of 1 can be calculated using a counter instead of being explicitly stored.
[0070] Furthermore, for non-first index buffers 510, the number of bits for each non-first index is stored in header 502. 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 implementation, the total size of first index buffer 512 is less than or equal to 24 bytes. Additionally, as shown, non-first index buffers 510 are immediately adjacent to the front buffer 522. Data in non-first index buffers 510 is stored in vertex ascending order 532. Triangle control bit 524 is located at the end of DGF block 500, and first index buffer 512 is stored directly in front of triangle control bit 524. Furthermore, the boundary between compressed index buffer 526 and triangle control bit 524 may or may not be byte aligned.
[0071] In one implementation, the DGF block 500 further stores a geometry identifier (GeomID 508) and an opaque micromap marker (OMM marker 506). The GeomID 508 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 508 and OMM marker 506 can be stored in two different modes, with the mode selected based on the geometry ID field in header 502. 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.
[0072] In constant mode, bit 0 of geometry ID field 508 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 500, 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 508 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, and these bits are stored only once rather than repeatedly. Furthermore, in palette mode, the GeomID palette structure is inserted into the block (as shown in GeomID 508). 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.
[0073] In one implementation, the GeomID 508 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, and each triangle index buffer identifies the payload to be used for each triangle. The size of each subscript is given by ceil(log2(GeomID count)), where the ceil(parameter(X)) function returns the smallest integer not less than parameter(X). Additionally, there is an array of N-bit payloads, 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 508). 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 this 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.
[0074] In one implementation, the OMM palette 506 (if present) is also byte-aligned. Padding bits are inserted as needed, and all such bits must be zero. The OMM palette 508 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 500. 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 530. The number of bits for each index is derived from the OMM descriptor count field in header 502. 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 500 (e.g., data not stored and / or otherwise generated by OMM palette 506 or GeomID palette 508) can be used to store additional vertex data.
[0075] Figure 6 An example of triangle stripes used to encode mesh topology data is shown. As previously described, DGF blocks store mesh topology data in the form of triangle stripes. The encoded mesh topology data consists of an array of triangle control values and a compressed index buffer. In one specific implementation, the control values include the “RESTART” bit, the “EDGE1” bit, the “EDGE2” bit, and the “BACKTRACK” bit. As shown in Table 650, the value of the RESTART bit is 0 (bit “00”), and these bits are used to start a new stripe, specifying the three 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.
[0076] In one implementation, the BACKTRACK bit (value 3, bit "11") indicates the opposite edge of the preceding triangle that is reused as the last identified triangle. 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 an 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.
[0077] In the example shown, the vertex order of the three identified triangles is given by the following bits (the arrows within each triangle depict the order of the vertices): RESTART: 0,1,2 (New strip 600 starts with triangle 602 formed using vertices 0, 1, and 2); EDGE1: 2,1,3 (using vertices 2, 1, and 3 and reusing sides 1-2 from triangle 602 to form a second triangle 604); and EDGE1: 3,1,4 (Use vertices 3, 1, and 4 and reuse sides 1-3 from triangle 604 to form a third triangle 606).
[0078] The order of the four possible vertices of the next triangle depends on their corresponding control values, and can be one of the following: RESTART: 5,6,7 (The new strip begins with a triangle formed by vertices 0, 1, and 2), as shown in dashed triangle 608; EDGE1: 4,1,5 (using vertices 4, 1, and 5 and reusing sides 1-4 from triangle 606 to form a new triangle), as shown in dashed triangle 610; EDGE2: 3,4,5 (using vertices 3, 4, and 5 and reusing the 4-3 sides from triangle 606 to form a new triangle), as shown in dashed triangle 612; or BACKTRACK: 2,3,5 (using vertices 2, 3, and 5 and reusing the 3-2 sides from triangle 604 to form a new triangle), as shown in dashed triangle 614.
[0079] In one implementation, whenever an edge is reused, the corresponding vertex is reversed, thus maintaining the triangle wrapping. Triangle meshes with mixed wrapping can be encoded by restarting the stripe each time the wrapping changes.
[0080] The control values of the triangles define the size of the index buffer. For example, the index buffer stores 1 bit for each triangle and two additional bits for each triangle with a control bit of 0 (RESTART). The first triangle in any strip will always be the triangle with the RESTART control bit, and therefore the first 3 bits of these triangles are always 1 and are not stored. As mentioned earlier, the index buffer is organized into "is first" bits, where one "is first" bit per vertex indicates whether the first index for a given vertex has been encountered, and "N" bits per index are used to store each non-first index for the vertex. The index buffer is compressed by reordering the vertices first and omitting the storage of the first index for each vertex, as indicated by the corresponding "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 processing the current 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 specific implementation, the vertices of the first triangle in a new strip will always be referenced first, and therefore their corresponding "is first" bits do not need to be stored. Non-first indices are stored directly in the packed buffer. (See reference) Figure 7 Exemplary techniques for encoding index buffers are described in detail.
[0081] Figure 7 This is a block diagram illustrating the generation of a compressed index buffer based on grid topology data. For example... Figure 6 As described in detail, triangle strips are used to encode the mesh topology. In one specific implementation, to encode the mesh topology in a compressed manner, the order in which the vertices are stored is used to minimize the size of the mesh topology data. That is, instead of storing data every time a new vertex is referenced for the first time, a counter is used to identify the first reference.
[0082] In one implementation, the length of the index buffer is determined by the contents of the control bits. The index buffer is further organized into two segments: a first index buffer, which includes "is first" bits, each indicating whether a given index is the first reference to a given vertex; and a non-first index buffer. In one implementation, if the "is first" bit indicates that a vertex has been referenced for the first time, the corresponding vertex index is not stored; instead, the corresponding vertex index is calculated by incrementing a counter. Furthermore, the first three indices of a vertex are always "first referenced," and their corresponding "is first" bits are not stored. In one implementation, the total size of the first index buffer is less than or equal to 24 bytes. In one implementation, for each RESTART triangle at the same or earlier position (i.e., the first triangle in the new strip), the position of the triangle in the index buffer is calculated by adding 2 bits to the triangle's index in the buffer. This gives the index buffer position of the third vertex of the triangle. As described below, the remaining two vertices are inferred from the first two triangles based on the control bits.
[0083] In the example shown in the figure, a new strip 700 is generated, and the first triangle 702 in the strip is formed using vertices 0, 1, and 2. In one specific implementation, subsequent triangles are then formed based on EDGE 1 and EDGE 2 (bit 750). For example, a second triangle 704 can be formed based on EDGE 1 (i.e., using vertices 2, 1, and 3 and reusing the first side of the first triangle 702 (between vertices 2 and 1)). Furthermore, a third triangle 706 can then be formed using vertices 3, 1, and 4 and reusing the first side of the second triangle 704 (between vertices 3 and 1). Continuing with bit 750, a fourth triangle 708 is formed using vertices 3, 4, and 5 and reusing the second side of the second triangle 704 (between vertices 3 and 4). Triangles 710-716 are formed similarly.
[0084] Based on stripe 700 created using control values, an index buffer 760 is generated for stripe 700, which stores the index of each vertex for each created triangle. This can include first references and non-first references for each vertex. In this example, the stripe buffer stores references to vertices 0-8, where vertices 0 and 2 are referenced more than once. In a specific implementation, to store these references, index buffer 760 is divided into two sections—a "first" array 762 and a non-first array 764. In one implementation, the "first" array 762 stores the first reference for each vertex; that is, each time a vertex is referenced for the first time in stripe 700, the corresponding bit is stored in the "first" array 762. In this example, for vertices 0-8 that have been referenced every time in stripe 700, the "first" array stores 9 bits. Furthermore, the non-first array 764 directly stores the bits of the non-first index corresponding to the vertex. In this example, the non-first array 764 stores the bits of vertices 0 and 2, each of which has been referenced more than once (twice each). As previously stated, for each RESTART triangle at the same or earlier position (i.e., the first triangle in the new strip), the position of the triangle in the index buffer is calculated by adding 2 bits to the triangle's index in the buffer. This gives the index buffer position of the third vertex of the triangle. As described below, the remaining two vertices are inferred from the first two triangles based on the control bits. For example, to retrieve the third vertex of triangle "I" (where I is a zero-based index), the index buffer is read at address A, where A = 2 * R + I, and R is the number of RESTART bits at or before I. Referring to the example in the attached figure, for triangle 706 (formed using vertices 3, 1, and 4) with index 2 (i.e., I = 2), there exists a previous RESTART triangle (i.e., R = 1), and therefore the result is 2 * 1 + 2 = 4.
[0085] The index is extracted from the compressed index buffer as follows: In one implementation, the primitive index of a triangle can be inferred from its position in stripe 700, thus alleviating the need to directly store that primitive index. In the example, a 29-bit primitive index base is stored in the DGF block (e.g., the block header) and added to the triangle position (given by the triangle index) to generate the primitive index. This is shown in the following exemplary sequence: [PrimitiveIndex = header.prim_id_base + triangle_index]. In one implementation, the size of the result must be 29 bytes. In another implementation, the total number of vertices in the DGF block is given by the number of "first" bits. All index values encoded in non-first index buffers must be less than this total. If out-of-range indices are stored in the index buffer, all ray-triangle intersections with the affected triangle may result in a miss.
[0086] Figure 8 An example is illustrated using fixed-size data blocks to store geometric metadata. In one implementation, primitives such as geometric triangles included in a triangle mesh are encoded, and the encoded data is stored using a data array of fixed-size data blocks (e.g., 128-byte blocks) for direct consumption by processing circuitry (e.g., GPU 205) for ray traversal or rasterization. In one or more implementations, the encoded data is in dense geometry format (DGF) data blocks (e.g., Figure 5 It is generated in the form of DGF block 500 shown.
[0087] In the implementation, the triangular mesh data is initially clustered using a surface area heuristic (SAH) clustering strategy (box 802) to achieve optimal ray tracing performance. Pre-clustering the geometry based on SAH accelerates BVH construction because the BVH builder receives efficient spatial partitioning and does not require constructing partitions from the original large set of triangles. In one implementation, the vertices corresponding to each triangle in each cluster are encoded to generate quantized vertices for each triangle (box 804). In one example, a 24-bit signed base position in the mesh is used to define the vertex-related data. 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 exponent.
[0088] In one embodiment, encoding the mesh data also includes encoding data related to the connectivity of the triangle mesh (i.e., mesh topology data) (box 806). According to this embodiment, the mesh topology data is encoded using triangle strips. For each triangle, two control bits are generated, indicating the position of the triangle relative to two previously stored triangles in the triangle strip. These values can be encoded based on whether a new strip needs to be initiated, whether the first side of a previously stored triangle needs to be reused in an existing strip, whether the second side of a previously stored triangle needs to be reused in an existing strip, or whether the opposite side of a leading triangle needs to be reused in an existing strip.
[0089] Based on the content of the control values, a compressed index buffer (box 808) is created. The compressed buffer is divided into two sections: a first array of "first" bits and a second array for storing non-first bits. The "first" bits include one bit per vertex reference, indicating whether each vertex reference is the first reference to a given vertex. In one implementation, the first reference to a given vertex may be omitted from the compressed index buffer and can be calculated using an incrementing counter. Non-first references are stored using "N" bits per index, where the value of N is predefined. In one implementation, the value of N is stored in the header of the corresponding DGF block.
[0090] The compressed index buffer, along with the encoded mesh topology data, is stored in a DGF block (box 810). The DGF block may also include an optional OMM palette and an optional GeomID palette, as described above. Furthermore, multiple DGF blocks are processed by processing circuitry (box 812), for example, to dynamically load and access geometry data into the software application or game during execution or runtime. In one or more specific implementations, the described encoding mechanism aims to improve geometry compression and has the advantage of storing large models in a compact form in a manner that allows direct hardware consumption. Furthermore, a significant reduction in memory footprint and ray traversal time can be achieved compared to conventional techniques. The described encoding also enables the creation of preprocessing pipelines that are simpler than those available with conventional encoding devices. Moreover, the graph data can be compressed using lossy compression, where loss is precisely controlled and the compressed data can be rendered directly.
[0091] 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 encode grid data comprising a plurality of primitives, wherein, in order to encode the grid data, the circuit is configured to: Generate control values, where each control value indicates the position of a geometric primitive relative to one or more other geometric primitives; Generate an index buffer comprising multiple index bits, wherein each index bit indicates the first and non-first references to a given vertex of the geometric primitive; and Store the encoded grid data corresponding to the control value and the index buffer.
2. The apparatus of claim 1, wherein the length of the index buffer is determined at least in part based on the content of each of the control values.
3. The apparatus of claim 1, wherein the plurality of index bits at least partially comprises: Each vertex of the geometric primitive has one bit, wherein the bit indicates whether the given vertex is being referenced for the first time; and A predefined number of bits, the predefined number of bits being used to store each non-first reference to the given vertex, wherein the predefined number of bits are values.
4. The apparatus of claim 1, wherein an identifier corresponding to each geometric primitive is calculated by adding a predefined bit value to a value representing the position of the geometric primitive in a primitive strip.
5. The apparatus of claim 1, wherein for each geometric primitive, each of the control values includes one of the following: A first control value indicates the initiation of a new primitive stripe; The second control value indicates that the first edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; A third control value indicates that the second edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; and A fourth control value indicates that the opposite edge of the preceding geometric primitive is reused as an edge of the new geometric primitive.
6. The apparatus of claim 1, wherein, in order to encode the mesh data, the circuitry is further configured to generate for each vertex of a given geometric primitive: The fixed base position of each coordinate of the vertex in three-dimensional space; and The variable width offset of the vertex relative to the base position.
7. The apparatus of claim 6, wherein the circuit is further configured to generate a power-of-two scaling factor to map the fixed-bit base position of each coordinate of each vertex to the corresponding floating-point coordinate.
8. A method for encoding grid data comprising multiple primitives, the method comprising: The processing circuit generates control values, where each control value indicates the position of a geometric primitive relative to one or more previously stored geometric primitives; The processing circuit generates an index buffer comprising multiple index bits, wherein each index bit indicates whether a given vertex of the geometric primitive is a first or subsequent reference; and The processing circuit stores the encoded grid data corresponding to the control value and the index buffer in a data block.
9. The method of claim 8, wherein the length of the index buffer is determined at least in part based on the content of each of the control values.
10. The method of claim 8, wherein the plurality of index bits at least partially comprises: Each vertex of the geometric primitive has one bit, and the bit indicates whether the given vertex is being referenced for the first time. and A predefined number of bits, which are used to store each non-first reference of the given vertex, wherein the value of the predefined number of bits is stored in the header portion of the data block.
11. The method of claim 8, wherein an identifier corresponding to each geometric primitive is calculated by adding a predefined bit value to a value representing the position of the geometric primitive in a primitive strip.
12. The method of claim 8, wherein for each geometric primitive, the control value includes one of the following: A first control value indicates the initiation of a new primitive stripe; The second control value indicates that the first edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; A third control value indicates that the second edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; and A fourth control value indicates that the opposite edge of the preceding geometric primitive is reused as an edge of the new geometric primitive.
13. The method of claim 8, further comprising generating by the processing circuitry for each vertex of a given geometric primitive: The fixed base position of each coordinate of the vertex in three-dimensional space; and The variable width offset of the vertex relative to the base position.
14. The method of claim 13, further comprising generating a power-of-two scaling factor to map the fixed bit coordinates of each vertex to the corresponding floating-point coordinates.
15. A ray tracing system, the ray tracing system comprising: A memory configured to store grid data comprising multiple primitives; and Encoding circuit, the encoding circuit being configured as follows: Retrieve the grid data from the memory; Generate control values, where each control value indicates the position of a geometric primitive relative to one or more previously stored geometric primitives; Generate a compressed index buffer comprising multiple index bits, each index bit indicating either the first or subsequent reference to a given vertex of the geometric primitive; as well as The control value and the compressed index buffer are stored in the data block.
16. The ray tracing system of claim 15, wherein the plurality of index bits at least partially comprises: Each vertex of the geometric primitive has one bit, and the bit indicates whether the given vertex is being referenced for the first time. and A predefined number of bits, which are used to store each non-first reference of the given vertex, wherein the value of the predefined number of bits is stored in the header portion of the data block.
17. The ray tracing system of claim 15, wherein an identifier corresponding to each geometric primitive is calculated by adding a predefined bit value to a value representing the position of the geometric primitive in a primitive strip.
18. The ray tracing system of claim 15, wherein for each geometric primitive, the control value includes one of the following: A first control value indicates the initiation of a new primitive stripe; The second control value indicates that the first edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; A third control value indicates that the second edge of the leading geometry is reused as an edge of the new geometry in the existing geometry strip; and A fourth control value indicates that the opposite edge of the preceding geometric primitive is reused as an edge of the new geometric primitive.
19. The ray tracing system of claim 15, wherein, in order to encode the mesh data, the encoding circuitry is further configured to generate for each vertex of a given geometric primitive: The fixed base position of each coordinate of the vertex in three-dimensional space; and The variable width offset of the vertex relative to the base position.
20. The ray tracing system of claim 19, wherein the encoding circuit is further configured to generate a power-of-two scaling factor to map the fixed bit coordinates of each vertex to the corresponding floating-point coordinates.