diff --git a/internal/config/allowlist/allowed_ext_test.go b/internal/config/allowlist/allowed_ext_test.go index e3cee2f71..dd309c4c7 100644 --- a/internal/config/allowlist/allowed_ext_test.go +++ b/internal/config/allowlist/allowed_ext_test.go @@ -90,6 +90,14 @@ func TestIsAllowedExt(t *testing.T) { {".SOL", true}, {".vy", true}, {".VY", true}, + {".glsl", true}, + {".GLSL", true}, + {".hlsl", true}, + {".HLSL", true}, + {".wgsl", true}, + {".WGSL", true}, + {".metal", true}, + {".METAL", true}, {".txt", false}, {".md", false}, {".png", false}, @@ -267,6 +275,12 @@ func TestIsExcludedPath(t *testing.T) { {"vyper non-test", "src/token.vy", false}, {"vyper test in filename only", "src/test_helpers.vy", false}, + // Shader languages have no conventional default test-file exclusion. + {"glsl shader", "shaders/fragment.glsl", false}, + {"hlsl shader", "shaders/lighting.hlsl", false}, + {"wgsl shader", "shaders/compute.wgsl", false}, + {"metal shader", "shaders/blur.metal", false}, + // Snapshot files {"jest snapshot dir", "src/__snapshots__/App.test.js.snap", true}, {"snap file", "src/components/Button.snap", true}, diff --git a/internal/config/allowlist/supported_file_types.json b/internal/config/allowlist/supported_file_types.json index c50002c89..8f7eb6c11 100644 --- a/internal/config/allowlist/supported_file_types.json +++ b/internal/config/allowlist/supported_file_types.json @@ -96,5 +96,9 @@ ".thrift", ".capnp", ".sol", - ".vy" + ".vy", + ".glsl", + ".hlsl", + ".wgsl", + ".metal" ] diff --git a/internal/config/rules/rule_docs/shader.md b/internal/config/rules/rule_docs/shader.md new file mode 100644 index 000000000..380a2d09e --- /dev/null +++ b/internal/config/rules/rule_docs/shader.md @@ -0,0 +1,40 @@ +> Favor precision over recall: only raise an issue when you are confident it is a real defect on the target shading language and pipeline stage; stay silent when the surrounding pipeline setup (bindings, render pass, vertex layout) is defined outside this file and cannot be verified. Treat correctness and security findings as blocking, and style or naming suggestions as non-blocking. + +#### Obvious Typos or Spelling Errors +- Spelling errors in uniform/binding names, semantic names (HLSL `SV_*`), varying/interpolant names, or shader entry-point names at their declaration sites +- Typos in preprocessor macros or `#include` paths that would fail to compile or silently pull in the wrong header + +#### Precision, Range, and Numeric Correctness +- Low/`half`/`mediump` precision qualifiers used for values that need full range or precision (depth, world-space position, accumulation buffers), risking banding or z-fighting +- Division, `rsqrt`, `normalize`, `log`, or `pow` calls on values that can be zero or negative without a guard, producing `NaN`/`Inf` that propagates through the pipeline +- Implicit or explicit type conversions between `float`/`half`/`int`/`uint` that truncate or wrap in a way that changes shading results, especially in loop counters and texture indices +- Non-uniform control flow around `pow`, `log`, or matrix operations that assumes IEEE-754 behavior not guaranteed across all target GPUs/drivers + +#### Texture and Buffer Access Safety +- Texture, buffer, or resource array indices computed from vertex/instance/thread IDs or user data without a bounds check, particularly on `RWStructuredBuffer`/`RWBuffer`/`ssbo`/`storage` writes +- Texture sampling (`tex2D`, `sample`, `textureLod`) called inside non-uniform control flow (e.g. inside an `if` that diverges per-lane) without an explicit LOD, which is undefined or produces incorrect derivatives on some hardware +- Mismatched texture format, channel count, or sRGB/linear color space assumptions between the shader and the resource binding declared on the host side +- Out-of-bounds writes to shared/groupshared/threadgroup memory in compute shaders, or missing barriers (`GroupMemoryBarrierWithGroupSync`, `barrier()`, `workgroupBarrier()`) before reading data another invocation wrote + +#### Binding, Layout, and Cross-Stage Contracts +- Uniform/constant buffer, descriptor set, or binding-slot indices that do not match the layout the host application (or a companion shader stage) expects, since mismatches fail silently at runtime rather than at compile time +- Struct layout (`std140`/`std430` in GLSL, register/space in HLSL, `@binding`/`@group` in WGSL) whose field alignment or padding does not match the CPU-side struct, causing misread values +- Vertex output / fragment input (varyings, `SV_Position`, `[[stage_in]]`) whose interpolation qualifiers (`flat`, `noperspective`, `centroid`) are inconsistent with how the value is used downstream +- Shader variants driven by preprocessor defines or pipeline permutations where a new code path is not covered by all defined permutations, leaving some variants uncompiled or behaviorally inconsistent + +#### Concurrency and Compute Correctness (Compute/Kernel Shaders) +- Race conditions on shared/groupshared/threadgroup memory or storage buffers written by multiple invocations without atomics or synchronization +- Workgroup/threadgroup size assumptions hardcoded in the shader that do not match the dispatch size declared on the host side +- Atomic operations used on types or backends that do not actually support atomics for that format, or atomics used where a simple reduction would be both correct and faster +- Divergent branches or early `return`/`discard` inside a compute kernel placed before a required barrier, causing a deadlock or undefined synchronization on affected lanes + +#### Performance Anti-Patterns +- Expensive operations (dynamic branching, texture-dependent reads, transcendental functions) inside tight loops that could be hoisted, precomputed on the CPU, or baked into a lookup texture +- Dynamic (non-uniform) branching on GPUs where the target hardware executes both sides of a branch per-warp/wavefront, negating the intended savings +- Redundant texture fetches or matrix multiplications recomputed per-fragment/per-thread that are invariant across the invocation and could be computed once (e.g. in the vertex stage or as a uniform) +- Overly large local/register usage (long-lived temporaries, unrolled loops) that reduces occupancy without a documented profiling justification + +#### Security-Sensitive and Portability Concerns +- Shader code paths that read attacker- or user-controlled buffer sizes/offsets (e.g. from a compute dispatch driven by untrusted input) without validating them before use as an index +- Vendor-specific intrinsics or extensions (`GL_ARB_*`, `SV_Barycentrics`, wave/subgroup intrinsics) used without a fallback or capability check, breaking portability across GPUs that lack the extension +- `discard`/`clip` used to implement alpha testing in a way that defeats early-Z/early-depth-test optimizations without a documented performance tradeoff diff --git a/internal/config/rules/system_rules.json b/internal/config/rules/system_rules.json index 21f4b02ec..d1154a5a2 100644 --- a/internal/config/rules/system_rules.json +++ b/internal/config/rules/system_rules.json @@ -44,6 +44,7 @@ "**/*.capnp": "capnp.md", "**/*.m": "matlab.md", "**/*.sol": "solidity.md", - "**/*.vy": "vyper.md" + "**/*.vy": "vyper.md", + "**/*.{glsl,hlsl,wgsl,metal}": "shader.md" } } diff --git a/internal/config/rules/system_rules_test.go b/internal/config/rules/system_rules_test.go index 74d144d54..075f2c6c6 100644 --- a/internal/config/rules/system_rules_test.go +++ b/internal/config/rules/system_rules_test.go @@ -135,6 +135,10 @@ func TestResolve_DefaultRules(t *testing.T) { {"if/common.thrift", "Field IDs and Wire Compatibility"}, {"schema/addressbook.capnp", "Ordinals and Wire Compatibility"}, {"src/rpc.capnp", "Ordinals and Wire Compatibility"}, + {"shaders/fragment.glsl", "Texture and Buffer Access Safety"}, + {"Shaders/Lighting.hlsl", "Texture and Buffer Access Safety"}, + {"shaders/compute.wgsl", "Texture and Buffer Access Safety"}, + {"Shaders/Blur.metal", "Texture and Buffer Access Safety"}, {"Models/main.m", "Indexing, Shapes, and Implicit Expansion"}, {"src/Counter.sol", "Checks-Effects-Interactions"}, {"contracts/Vault.sol", "Delegatecall and Proxy Upgradeability"}, diff --git a/pages/src/content/docs/en/review-rules.md b/pages/src/content/docs/en/review-rules.md index a8791dca2..dae199e0f 100644 --- a/pages/src/content/docs/en/review-rules.md +++ b/pages/src/content/docs/en/review-rules.md @@ -182,6 +182,7 @@ matching order: | `**/*.{jsonnet,libsonnet}` | `jsonnet.md` — Jsonnet configuration templates and libraries. | | `**/*.thrift` | `thrift.md` — Apache Thrift IDL wire compatibility. | | `**/*.capnp` | `capnp.md` — Cap'n Proto schema wire compatibility. | +| `**/*.{glsl,hlsl,wgsl,metal}` | `shader.md` — GLSL, HLSL, WGSL, and Metal shaders. | | `**/*.m` | `matlab.md` (or `objc.md` via [content sniffing](#content-sniffing-for-m-files)) | | `**/*.sol` | `solidity.md` — Solidity smart contracts. | | `**/*.vy` | `vyper.md` — Vyper smart contracts. | diff --git a/pages/src/content/docs/ja/review-rules.md b/pages/src/content/docs/ja/review-rules.md index bc8c02ce9..6e1f5046a 100644 --- a/pages/src/content/docs/ja/review-rules.md +++ b/pages/src/content/docs/ja/review-rules.md @@ -144,6 +144,7 @@ OCR は [`bmatcuk/doublestar/v4`](https://pkg.go.dev/github.com/bmatcuk/doublest | `**/*.{jsonnet,libsonnet}` | `jsonnet.md`: Jsonnet の設定テンプレートとライブラリ。 | | `**/*.thrift` | `thrift.md`: Apache Thrift IDL のワイヤ互換性。 | | `**/*.capnp` | `capnp.md`: Cap'n Proto スキーマのワイヤ互換性。 | +| `**/*.{glsl,hlsl,wgsl,metal}` | `shader.md` - GLSL、HLSL、WGSL、Metal シェーダー。 | | `**/*.m` | `matlab.md`(または[コンテンツスニッフィング](#content-sniffing-for-m-files)により `objc.md`) | | `**/*.sol` | `solidity.md`: Solidity スマートコントラクト。 | | `**/*.vy` | `vyper.md`: Vyper スマートコントラクト。 | diff --git a/pages/src/content/docs/ru/review-rules.md b/pages/src/content/docs/ru/review-rules.md index 19dc3e251..8bfca61d1 100644 --- a/pages/src/content/docs/ru/review-rules.md +++ b/pages/src/content/docs/ru/review-rules.md @@ -184,6 +184,7 @@ OCR использует [`bmatcuk/doublestar/v4`](https://pkg.go.dev/github.com | `**/*.{jsonnet,libsonnet}` | `jsonnet.md` — шаблоны конфигурации и библиотеки Jsonnet. | | `**/*.thrift` | `thrift.md` — совместимость Apache Thrift IDL на уровне wire. | | `**/*.capnp` | `capnp.md` — совместимость схем Cap'n Proto на уровне wire. | +| `**/*.{glsl,hlsl,wgsl,metal}` | `shader.md` - шейдеры GLSL, HLSL, WGSL и Metal. | | `**/*.m` | `matlab.md` (или `objc.md` через [определение содержимого](#content-sniffing-for-m-files)) | | `**/*.sol` | `solidity.md` — смарт-контракты Solidity. | | `**/*.vy` | `vyper.md` — смарт-контракты Vyper. | diff --git a/pages/src/content/docs/zh/review-rules.md b/pages/src/content/docs/zh/review-rules.md index ee790999e..484c1a4b6 100644 --- a/pages/src/content/docs/zh/review-rules.md +++ b/pages/src/content/docs/zh/review-rules.md @@ -165,6 +165,7 @@ OCR 用 [`bmatcuk/doublestar/v4`](https://pkg.go.dev/github.com/bmatcuk/doublest | `**/*.{jsonnet,libsonnet}` | `jsonnet.md`——Jsonnet 配置模板与库。 | | `**/*.thrift` | `thrift.md`——Apache Thrift IDL 线协议兼容性。 | | `**/*.capnp` | `capnp.md`——Cap'n Proto schema 线协议兼容性。 | +| `**/*.{glsl,hlsl,wgsl,metal}` | `shader.md` - GLSL、HLSL、WGSL、Metal 着色器。 | | `**/*.m` | `matlab.md`(或通过[内容嗅探](#针对-m-文件的内容嗅探)使用 `objc.md`) | | `**/*.sol` | `solidity.md`——Solidity 智能合约。 | | `**/*.vy` | `vyper.md`——Vyper 智能合约。 |