|
1 | 1 | # DirectX Raytracing (DXR) Functional Spec, Part 2 <!-- omit in toc --> |
2 | 2 |
|
3 | | -v0.19 3/17/2026 |
| 3 | +v0.20 3/18/2026 |
4 | 4 |
|
5 | 5 | --- |
6 | 6 |
|
@@ -1654,95 +1654,126 @@ typedef int INT; |
1654 | 1654 | ###### D3D12_VERTEX_FORMAT_COMPRESSED1_HEADER macros |
1655 | 1655 |
|
1656 | 1656 | ```C++ |
1657 | | -// 24-bit sign extension (portable, no arithmetic-shift dependency) |
1658 | | -#define D3D12_COMPRESSED1_SIGN_EXTEND_24(val) \ |
1659 | | - ((INT)(((val) ^ 0x800000) - 0x800000)) |
1660 | | - |
1661 | | -// ENCODER MACRO: Store exponent field (read-modify-write). Caller must pass biased exponent (actual + 127). |
1662 | | -#define ENCODE_D3D12_COMPRESSED1_EXPONENT(header, exponent) ((header).field0 = ((header).field0 & 0xFFFFFF00) | ((UINT)(exponent) & 0xFF)) |
| 1657 | +// ENCODER MACRO: Store exponent field (read-modify-write). |
| 1658 | +// Caller must pass biased exponent (actual + 127). |
| 1659 | +#define ENCODE_D3D12_COMPRESSED1_EXPONENT(header, exponent) \ |
| 1660 | + ((header).field0 = ((header).field0 & ~0xFF) | (UINT(exponent) & 0xFF)) |
1663 | 1661 |
|
1664 | 1662 | // ENCODER MACRO: Store x_anchor field (read-modify-write). |
1665 | | -#define ENCODE_D3D12_COMPRESSED1_X_ANCHOR(header, x_anchor) ((header).field0 = ((header).field0 & 0xFF) | (((UINT)(x_anchor) << 8) & 0xFFFFFF00)) |
| 1663 | +#define ENCODE_D3D12_COMPRESSED1_X_ANCHOR(header, x_anchor) \ |
| 1664 | + ((header).field0 = ((header).field0 & 0xFF) | ((UINT(x_anchor) << 8))) |
1666 | 1665 |
|
1667 | 1666 | // ENCODER MACRO: Store x_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1668 | | -#define ENCODE_D3D12_COMPRESSED1_X_BITS(header, x_bits) ((header).field1 = ((header).field1 & ~0xF) | ((UINT)(x_bits) & 0xF)) |
| 1667 | +#define ENCODE_D3D12_COMPRESSED1_X_BITS(header, x_bits) \ |
| 1668 | + ((header).field1 = ((header).field1 & ~0xF) | ((UINT(x_bits) & 0xF))) |
1669 | 1669 |
|
1670 | 1670 | // ENCODER MACRO: Store y_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1671 | | -#define ENCODE_D3D12_COMPRESSED1_Y_BITS(header, y_bits) ((header).field1 = ((header).field1 & ~0xF0) | (((UINT)(y_bits) & 0xF) << 4)) |
| 1671 | +#define ENCODE_D3D12_COMPRESSED1_Y_BITS(header, y_bits) \ |
| 1672 | + ((header).field1 = ((header).field1 & ~0xF0) | ((UINT(y_bits) & 0xF) << 4)) |
1672 | 1673 |
|
1673 | 1674 | // ENCODER MACRO: Store y_anchor field (read-modify-write). |
1674 | | -#define ENCODE_D3D12_COMPRESSED1_Y_ANCHOR(header, y_anchor) ((header).field1 = ((header).field1 & 0xFF) | (((UINT)(y_anchor) << 8) & 0xFFFFFF00)) |
| 1675 | +#define ENCODE_D3D12_COMPRESSED1_Y_ANCHOR(header, y_anchor) \ |
| 1676 | + ((header).field1 = ((header).field1 & 0xFF) | ((UINT(y_anchor) << 8))) |
1675 | 1677 |
|
1676 | 1678 | // ENCODER MACRO: Store z_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1677 | | -#define ENCODE_D3D12_COMPRESSED1_Z_BITS(header, z_bits) ((header).field2 = ((header).field2 & ~0xF) | ((UINT)(z_bits) & 0xF)) |
| 1679 | +#define ENCODE_D3D12_COMPRESSED1_Z_BITS(header, z_bits) \ |
| 1680 | + ((header).field2 = ((header).field2 & ~0xF) | ((UINT(z_bits) & 0xF))) |
1678 | 1681 |
|
1679 | 1682 | // ENCODER MACRO: Store z_anchor field (read-modify-write). |
1680 | | -#define ENCODE_D3D12_COMPRESSED1_Z_ANCHOR(header, z_anchor) ((header).field2 = ((header).field2 & 0xFF) | (((UINT)(z_anchor) << 8) & 0xFFFFFF00)) |
| 1683 | +#define ENCODE_D3D12_COMPRESSED1_Z_ANCHOR(header, z_anchor) \ |
| 1684 | + ((header).field2 = ((header).field2 & 0xFF) | ((UINT(z_anchor) << 8))) |
1681 | 1685 |
|
1682 | | -// ENCODER MACRO Store all field0 members: exponent and x_anchor. Caller must pass biased exponent (actual + 127). |
| 1686 | +// ENCODER MACRO Store all field0 members: exponent and x_anchor. |
| 1687 | +// Caller must pass biased exponent (actual + 127). |
1683 | 1688 | #define ENCODE_D3D12_COMPRESSED1_EXPONENT_X_ANCHOR(header, exponent, x_anchor) \ |
1684 | | - ((header).field0 = (((UINT)(exponent) & 0xFF) | (((UINT)(x_anchor) << 8) & 0xFFFFFF00))) |
| 1689 | + ((header).field0 = ((UINT(exponent) & 0xFF) | (UINT(x_anchor) << 8))) |
1685 | 1690 |
|
1686 | | -// ENCODER MACRO Store all field1 members: x_bits, y_bits, and y_anchor. Caller must pass (bit_count - 1) for x_bits and y_bits. |
| 1691 | +// ENCODER MACRO Store all field1 members: x_bits, y_bits, and y_anchor. |
| 1692 | +// Caller must pass (bit_count - 1) for x_bits and y_bits. |
1687 | 1693 | #define ENCODE_D3D12_COMPRESSED1_XY_BITS_Y_ANCHOR(header, x_bits, y_bits, y_anchor) \ |
1688 | | - ((header).field1 = (((UINT)(x_bits) & 0xF) | (((UINT)(y_bits) & 0xF) << 4) | (((UINT)(y_anchor) << 8) & 0xFFFFFF00))) |
| 1694 | + ((header).field1 = ((UINT(x_bits) & 0xF) | ((UINT(y_bits) & 0xF) << 4) | (UINT(y_anchor) << 8))) |
1689 | 1695 |
|
1690 | | -// ENCODER MACRO Store all field2 members: z_bits and z_anchor. Caller must pass (bit_count - 1) for z_bits. Bits [07:04] are set to zero (unused). |
| 1696 | +// ENCODER MACRO Store all field2 members: z_bits and z_anchor. |
| 1697 | +// Caller must pass (bit_count - 1) for z_bits. Bits [07:04] are set to zero (unused). |
1691 | 1698 | #define ENCODE_D3D12_COMPRESSED1_Z_BITS_Z_ANCHOR(header, z_bits, z_anchor) \ |
1692 | | - ((header).field2 = (((UINT)(z_bits) & 0xF) | (((UINT)(z_anchor) << 8) & 0xFFFFFF00))) |
1693 | | - |
1694 | | -// DECODER MACRO: Extract the 8-bit biased exponent. Caller must subtract 127 from result to get the actual exponent. |
| 1699 | + ((header).field2 = ((UINT(z_bits) & 0xF) | (UINT(z_anchor) << 8))) |
| 1700 | + |
| 1701 | +// ENCODER MACRO: Store all fields. Caller must pass biased exponent |
| 1702 | +// (actual + 127) and (bit_count - 1) for x_bits, y_bits, and z_bits. |
| 1703 | +// Bits [07:04] in field2 are set to zero (unused). |
| 1704 | +#define ENCODE_D3D12_COMPRESSED1(header, exponent, x_anchor, y_anchor, z_anchor, x_bits, y_bits, z_bits ) \ |
| 1705 | + ((header).field0 = ((UINT(exponent) & 0xFF) | (UINT(x_anchor) << 8)), \ |
| 1706 | + (header).field1 = ((UINT(x_bits) & 0xF) | ((UINT(y_bits) & 0xF) << 4) | (UINT(y_anchor) << 8)), \ |
| 1707 | + (header).field2 = ((UINT(z_bits) & 0xF) | (UINT(z_anchor) << 8))) |
| 1708 | + |
| 1709 | +// DECODER MACRO: Extract the 8-bit biased exponent. |
| 1710 | +// Caller must subtract 127 from result to get the actual exponent. |
1695 | 1711 | #define DECODE_D3D12_COMPRESSED1_EXPONENT(header) (((header).field0) & 0xFF) |
1696 | 1712 |
|
1697 | 1713 | // DECODER MACRO: Extract the 24-bit x_anchor as a signed integer. |
1698 | | -#define DECODE_D3D12_COMPRESSED1_X_ANCHOR(header) D3D12_COMPRESSED1_SIGN_EXTEND_24((((header).field0) >> 8) & 0xFFFFFF) |
| 1714 | +#define DECODE_D3D12_COMPRESSED1_X_ANCHOR(header) (INT((header).field0) >> 8) |
1699 | 1715 |
|
1700 | | -// DECODER MACRO: Extract the 4-bit x_bits value. Caller must add 1 to result to get the actual bit count. |
| 1716 | +// DECODER MACRO: Extract the 4-bit x_bits value. |
| 1717 | +// Caller must add 1 to result to get the actual bit count. |
1701 | 1718 | #define DECODE_D3D12_COMPRESSED1_X_BITS(header) (((header).field1) & 0xF) |
1702 | 1719 |
|
1703 | | -// DECODER MACRO: Extract the 4-bit y_bits value. Caller must add 1 to result to get the actual bit count. |
| 1720 | +// DECODER MACRO: Extract the 4-bit y_bits value. |
| 1721 | +// Caller must add 1 to result to get the actual bit count. |
1704 | 1722 | #define DECODE_D3D12_COMPRESSED1_Y_BITS(header) ((((header).field1) >> 4) & 0xF) |
1705 | 1723 |
|
1706 | 1724 | // DECODER MACRO: Extract the 24-bit y_anchor as a signed integer. |
1707 | | -#define DECODE_D3D12_COMPRESSED1_Y_ANCHOR(header) D3D12_COMPRESSED1_SIGN_EXTEND_24((((header).field1) >> 8) & 0xFFFFFF) |
| 1725 | +#define DECODE_D3D12_COMPRESSED1_Y_ANCHOR(header) (INT((header).field1) >> 8) |
1708 | 1726 |
|
1709 | | -// DECODER MACRO: Extract the 4-bit z_bits value. Caller must add 1 to result to get the actual bit count. |
| 1727 | +// DECODER MACRO: Extract the 4-bit z_bits value. |
| 1728 | +// Caller must add 1 to result to get the actual bit count. |
1710 | 1729 | #define DECODE_D3D12_COMPRESSED1_Z_BITS(header) (((header).field2) & 0xF) |
1711 | 1730 |
|
1712 | 1731 | // DECODER MACRO: Extract the 24-bit z_anchor as a signed integer. |
1713 | | -#define DECODE_D3D12_COMPRESSED1_Z_ANCHOR(header) D3D12_COMPRESSED1_SIGN_EXTEND_24((((header).field2) >> 8) & 0xFFFFFF) |
| 1732 | +#define DECODE_D3D12_COMPRESSED1_Z_ANCHOR(header) (INT((header).field2) >> 8) |
| 1733 | + |
1714 | 1734 | ``` |
1715 | 1735 |
|
1716 | 1736 | ###### D3D12_VERTEX_FORMAT_COMPRESSED1_TEMPLATE_HEADER macros |
1717 | 1737 |
|
1718 | 1738 | ```C++ |
1719 | 1739 | // ENCODER MACRO: Store exponent field (read-modify-write). Caller must pass biased exponent (actual + 127). |
1720 | | -#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_EXPONENT(header, exponent) ((header).field0 = ((header).field0 & ~0xFF) | ((UINT)(exponent) & 0xFF)) |
| 1740 | +#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_EXPONENT(header, exponent) \ |
| 1741 | + ((header).field0 = ((header).field0 & ~0xFF) | (UINT(exponent) & 0xFF)) |
1721 | 1742 |
|
1722 | 1743 | // ENCODER MACRO: Store x_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1723 | | -#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_X_BITS(header, x_bits) ((header).field0 = ((header).field0 & ~0xF00) | (((UINT)(x_bits) & 0xF) << 8)) |
| 1744 | +#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_X_BITS(header, x_bits) \ |
| 1745 | + ((header).field0 = ((header).field0 & ~0xF00) | ((UINT(x_bits) & 0xF) << 8)) |
1724 | 1746 |
|
1725 | 1747 | // ENCODER MACRO: Store y_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1726 | | -#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_Y_BITS(header, y_bits) ((header).field0 = ((header).field0 & ~0xF000) | (((UINT)(y_bits) & 0xF) << 12)) |
| 1748 | +#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_Y_BITS(header, y_bits) \ |
| 1749 | + ((header).field0 = ((header).field0 & ~0xF000) | ((UINT(y_bits) & 0xF) << 12)) |
1727 | 1750 |
|
1728 | 1751 | // ENCODER MACRO: Store z_bits field (read-modify-write). Caller must pass (bit_count - 1). |
1729 | | -#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_Z_BITS(header, z_bits) ((header).field0 = ((header).field0 & ~0xF0000) | (((UINT)(z_bits) & 0xF) << 16)) |
| 1752 | +#define ENCODE_D3D12_COMPRESSED1_TEMPLATE_Z_BITS(header, z_bits) \ |
| 1753 | + ((header).field0 = ((header).field0 & ~0xF0000) | ((UINT(z_bits) & 0xF) << 16)) |
1730 | 1754 |
|
1731 | | -// ENCODER MACRO: Store all members: exponent, x_bits, y_bits, and z_bits. Caller must pass biased exponent (actual + 127) and (bit_count - 1) for each bits field. Bits [31:20] are set to zero (unused). |
| 1755 | +// ENCODER MACRO: Store all members: exponent, x_bits, y_bits, and z_bits. |
| 1756 | +// Caller must pass biased exponent (actual + 127) and (bit_count - 1) for each bits field. |
| 1757 | +// Bits [31:20] are set to zero (unused). |
1732 | 1758 | #define ENCODE_D3D12_COMPRESSED1_TEMPLATE(header, exponent, x_bits, y_bits, z_bits) \ |
1733 | | - ((header).field0 = (((UINT)(exponent) & 0xFF) | (((UINT)(x_bits) & 0xF) << 8) | (((UINT)(y_bits) & 0xF) << 12) | (((UINT)(z_bits) & 0xF) << 16))) |
| 1759 | + ((header).field0 = ((UINT(exponent) & 0xFF) | ((UINT(x_bits) & 0xF) << 8) | ((UINT(y_bits) & 0xF) << 12) | ((UINT(z_bits) & 0xF) << 16))) |
1734 | 1760 |
|
1735 | 1761 | // DECODER MACRO: Extract the 8-bit biased exponent. Caller must subtract 127 to get the actual exponent. |
1736 | | -#define DECODE_D3D12_COMPRESSED1_TEMPLATE_EXPONENT(header) (((header).field0) & 0xFF) |
| 1762 | +#define DECODE_D3D12_COMPRESSED1_TEMPLATE_EXPONENT(header) \ |
| 1763 | + (((header).field0) & 0xFF) |
1737 | 1764 |
|
1738 | 1765 | // DECODER MACRO: Extract the 4-bit x_bits value. Caller must add 1 to get the actual bit count. |
1739 | | -#define DECODE_D3D12_COMPRESSED1_TEMPLATE_X_BITS(header) ((((header).field0) >> 8) & 0xF) |
| 1766 | +#define DECODE_D3D12_COMPRESSED1_TEMPLATE_X_BITS(header) \ |
| 1767 | + ((((header).field0) >> 8) & 0xF) |
1740 | 1768 |
|
1741 | 1769 | // DECODER MACRO: Extract the 4-bit y_bits value. Caller must add 1 to get the actual bit count. |
1742 | | -#define DECODE_D3D12_COMPRESSED1_TEMPLATE_Y_BITS(header) ((((header).field0) >> 12) & 0xF) |
| 1770 | +#define DECODE_D3D12_COMPRESSED1_TEMPLATE_Y_BITS(header) \ |
| 1771 | + ((((header).field0) >> 12) & 0xF) |
1743 | 1772 |
|
1744 | 1773 | // DECODER MACRO: Extract the 4-bit z_bits value. Caller must add 1 to get the actual bit count. |
1745 | | -#define DECODE_D3D12_COMPRESSED1_TEMPLATE_Z_BITS(header) ((((header).field0) >> 16) & 0xF) |
| 1774 | +#define DECODE_D3D12_COMPRESSED1_TEMPLATE_Z_BITS(header) \ |
| 1775 | + ((((header).field0) >> 16) & 0xF) |
| 1776 | + |
1746 | 1777 | ``` |
1747 | 1778 |
|
1748 | 1779 | --- |
@@ -2204,3 +2235,4 @@ v0.16|3/11/2026|<li>In [D3D12_RTAS_CLUSTER_TRIANGLES_INPUTS_DESC](#d3d12_rtas_cl |
2204 | 2235 | v0.17|3/12/2026|<li>Added [Why compaction doesn't apply to clustered geometry](#why-compaction-doesnt-apply-to-clustered-geometry) section</li> |
2205 | 2236 | v0.18|3/16/2026|<li>Replaced C++ bitfields with plain `UINT` members (to be manually packed by user) in [D3D12_VERTEX_FORMAT_COMPRESSED1_HEADER](#compressed1-position-encoding) and [D3D12_VERTEX_FORMAT_COMPRESSED1_TEMPLATE_HEADER](#d3d12_vertex_format_compressed1_template_header) for portable layout across C++ compilers, architectures, and HLSL. Added [Compressed1 bitfield helper macros](#compressed1-bitfield-helper-macros) section with encode/decode macros from `d3d12.h` that work in both C++ and HLSL (with `UINT`/`INT` typedefs). For the same reason, in [D3D12_RTAS_OPERATION_BUILD_CLAS_FROM_TRIANGLES_ARGS](#d3d12_rtas_operation_build_clas_from_triangles_args) replaced bitfield members with vanilla typed members.</li><li>In [D3D12_RTAS_OPERATION_BUILD_CLAS_FROM_TRIANGLES_ARGS](#d3d12_rtas_operation_build_clas_from_triangles_args), for `IndexBufferStride` limited the maximum stride value to 4 bytes. The purpose of this stride is just for cases where an application may have index values of a larger size (e.g. 4 bytes) but knows the values would happen to fit in a smaller size like 1 byte, which implementations might process more efficiently. The intent isn't for interleaving arbitrary data between indices (something more reasonable to do with the other stride values in this struct).</li> |
2206 | 2237 | v0.19|3/17/2026|<li>Moved `D3D12_RTAS_CLUSTER_OPERATION_CLAS_FLAG_ALLOW_DATA_ACCESS` from [D3D12_RTAS_CLUSTER_OPERATION_CLAS_FLAGS](#d3d12_rtas_cluster_operation_clas_flags) to [D3D12_RTAS_OPERATION_FLAGS](#d3d12_rtas_operation_flags) as `D3D12_RTAS_OPERATION_FLAG_ALLOW_DATA_ACCESS`. This flag applies to CLAS builds and CLAS template builds; it is ignored for CLAS template instantiation, which inherits the allow/disallow state from the template. It not allowed for cluster BLAS builds; instead, all CLAS referenced by a given cluster BLAS must have consistently chosen to allow data access or not when they were built.</li><li>Added `D3D12_RTAS_CLUSTER_OPERATION_CLAS_FLAG_DISALLOW_DATA_ACCESS` to [D3D12_RTAS_CLUSTER_OPERATION_CLAS_FLAGS](#d3d12_rtas_cluster_operation_clas_flags) to selectively disable data access for individual cluster builds within an operation that has `ALLOW_DATA_ACCESS` globally set.</li> |
| 2238 | +v0.20|3/18/2026|<li>In [Compressed1 bitfield helper macros](#compressed1-bitfield-helper-macros), macro cleanup and bugfixes: removed unnecessary mask after left shifting; `UINT(val)` instead of `(UINT)(val)` (less verbose); use sign extend on right shift - support is ubiquitous enough (old macro also incorrectly masked result)</li> |
0 commit comments