miniray 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -1
- package/esm/node.mjs +36 -2
- package/lib/browser.js +18 -0
- package/lib/main.d.ts +83 -0
- package/lib/main.js +36 -2
- package/miniray.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ console.log(result.code);
|
|
|
60
60
|
|
|
61
61
|
### `initialize(options)`
|
|
62
62
|
|
|
63
|
-
Initialize the WASM module. Must be called before `minify()`.
|
|
63
|
+
Initialize the WASM module. Must be called before `minify()` or `reflect()`.
|
|
64
64
|
|
|
65
65
|
```typescript
|
|
66
66
|
interface InitializeOptions {
|
|
@@ -95,6 +95,81 @@ interface MinifyResult {
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
### `reflect(source)`
|
|
99
|
+
|
|
100
|
+
Extract binding information, struct layouts, and entry points from WGSL source.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface ReflectResult {
|
|
104
|
+
bindings: BindingInfo[];
|
|
105
|
+
structs: Record<string, StructLayout>;
|
|
106
|
+
entryPoints: EntryPointInfo[];
|
|
107
|
+
errors: string[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface BindingInfo {
|
|
111
|
+
group: number;
|
|
112
|
+
binding: number;
|
|
113
|
+
name: string;
|
|
114
|
+
addressSpace: string; // "uniform", "storage", "handle"
|
|
115
|
+
accessMode?: string; // "read", "write", "read_write" (for storage)
|
|
116
|
+
type: string;
|
|
117
|
+
layout: StructLayout | null; // null for textures/samplers
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface StructLayout {
|
|
121
|
+
size: number;
|
|
122
|
+
alignment: number;
|
|
123
|
+
fields: FieldInfo[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface FieldInfo {
|
|
127
|
+
name: string;
|
|
128
|
+
type: string;
|
|
129
|
+
offset: number;
|
|
130
|
+
size: number;
|
|
131
|
+
alignment: number;
|
|
132
|
+
layout?: StructLayout; // for nested structs
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
interface EntryPointInfo {
|
|
136
|
+
name: string;
|
|
137
|
+
stage: string; // "vertex", "fragment", "compute"
|
|
138
|
+
workgroupSize: number[] | null; // [x, y, z] for compute, null otherwise
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Example:**
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
const result = reflect(`
|
|
146
|
+
struct Uniforms { time: f32, resolution: vec2<u32> }
|
|
147
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
148
|
+
@compute @workgroup_size(8, 8) fn main() {}
|
|
149
|
+
`);
|
|
150
|
+
|
|
151
|
+
console.log(result.bindings[0]);
|
|
152
|
+
// {
|
|
153
|
+
// group: 0, binding: 0, name: "u",
|
|
154
|
+
// addressSpace: "uniform", type: "Uniforms",
|
|
155
|
+
// layout: {
|
|
156
|
+
// size: 16, alignment: 8,
|
|
157
|
+
// fields: [
|
|
158
|
+
// { name: "time", type: "f32", offset: 0, size: 4, alignment: 4 },
|
|
159
|
+
// { name: "resolution", type: "vec2<u32>", offset: 8, size: 8, alignment: 8 }
|
|
160
|
+
// ]
|
|
161
|
+
// }
|
|
162
|
+
// }
|
|
163
|
+
|
|
164
|
+
console.log(result.entryPoints[0]);
|
|
165
|
+
// { name: "main", stage: "compute", workgroupSize: [8, 8, 1] }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Memory layouts follow the WGSL specification:
|
|
169
|
+
- `vec3` has alignment=16 but size=12
|
|
170
|
+
- Struct members are aligned to their natural alignment
|
|
171
|
+
- Struct size is rounded up to struct alignment
|
|
172
|
+
|
|
98
173
|
### `isInitialized()`
|
|
99
174
|
|
|
100
175
|
Returns `true` if the WASM module is initialized.
|
package/esm/node.mjs
CHANGED
|
@@ -40,8 +40,15 @@ export async function initialize(options) {
|
|
|
40
40
|
const wasmModule = options.wasmModule;
|
|
41
41
|
|
|
42
42
|
// Default to miniray.wasm in the package directory
|
|
43
|
+
// Use require.resolve to find files within the package, which works
|
|
44
|
+
// regardless of bundling or working directory
|
|
43
45
|
if (!wasmURL && !wasmModule) {
|
|
44
|
-
|
|
46
|
+
try {
|
|
47
|
+
wasmURL = require.resolve('miniray/miniray.wasm');
|
|
48
|
+
} catch {
|
|
49
|
+
// Fallback to relative path for local development
|
|
50
|
+
wasmURL = path.join(__dirname, '..', 'miniray.wasm');
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
_initPromise = _doInitialize(wasmURL, wasmModule);
|
|
@@ -57,7 +64,16 @@ export async function initialize(options) {
|
|
|
57
64
|
|
|
58
65
|
async function _doInitialize(wasmURL, wasmModule) {
|
|
59
66
|
// Load wasm_exec.js - this defines Go globally
|
|
60
|
-
|
|
67
|
+
// Use require.resolve to find files within the package, which works
|
|
68
|
+
// regardless of bundling or working directory
|
|
69
|
+
let wasmExecPath;
|
|
70
|
+
try {
|
|
71
|
+
wasmExecPath = require.resolve('miniray/wasm_exec.js');
|
|
72
|
+
} catch {
|
|
73
|
+
// Fallback to relative path for local development
|
|
74
|
+
wasmExecPath = path.join(__dirname, '..', 'wasm_exec.js');
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
if (!fs.existsSync(wasmExecPath)) {
|
|
62
78
|
throw new Error(`wasm_exec.js not found at ${wasmExecPath}`);
|
|
63
79
|
}
|
|
@@ -122,6 +138,23 @@ export function minify(source, options) {
|
|
|
122
138
|
return globalThis.__miniray.minify(source, options || {});
|
|
123
139
|
}
|
|
124
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Reflect WGSL source to extract binding and struct information.
|
|
143
|
+
* @param {string} source - WGSL source code
|
|
144
|
+
* @returns {Object} Reflection result with bindings, structs, entryPoints, and errors
|
|
145
|
+
*/
|
|
146
|
+
export function reflect(source) {
|
|
147
|
+
if (!_initialized) {
|
|
148
|
+
throw new Error('miniray not initialized. Call initialize() first.');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (typeof source !== 'string') {
|
|
152
|
+
throw new Error('source must be a string');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return globalThis.__miniray.reflect(source);
|
|
156
|
+
}
|
|
157
|
+
|
|
125
158
|
/**
|
|
126
159
|
* Check if initialized.
|
|
127
160
|
* @returns {boolean}
|
|
@@ -147,6 +180,7 @@ export const version = getVersion;
|
|
|
147
180
|
export default {
|
|
148
181
|
initialize,
|
|
149
182
|
minify,
|
|
183
|
+
reflect,
|
|
150
184
|
isInitialized,
|
|
151
185
|
version: getVersion
|
|
152
186
|
};
|
package/lib/browser.js
CHANGED
|
@@ -149,6 +149,23 @@
|
|
|
149
149
|
return globalThis.__miniray.minify(source, options || {});
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Reflect WGSL source to extract binding and struct information.
|
|
154
|
+
* @param {string} source - WGSL source code
|
|
155
|
+
* @returns {Object} Reflection result with bindings, structs, entryPoints, and errors
|
|
156
|
+
*/
|
|
157
|
+
function reflect(source) {
|
|
158
|
+
if (!_initialized) {
|
|
159
|
+
throw new Error('miniray not initialized. Call initialize() first.');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (typeof source !== 'string') {
|
|
163
|
+
throw new Error('source must be a string');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return globalThis.__miniray.reflect(source);
|
|
167
|
+
}
|
|
168
|
+
|
|
152
169
|
/**
|
|
153
170
|
* Check if initialized.
|
|
154
171
|
* @returns {boolean}
|
|
@@ -171,6 +188,7 @@
|
|
|
171
188
|
return {
|
|
172
189
|
initialize: initialize,
|
|
173
190
|
minify: minify,
|
|
191
|
+
reflect: reflect,
|
|
174
192
|
isInitialized: isInitialized,
|
|
175
193
|
get version() { return getVersion(); }
|
|
176
194
|
};
|
package/lib/main.d.ts
CHANGED
|
@@ -75,6 +75,82 @@ export interface MinifyResult {
|
|
|
75
75
|
minifiedSize: number;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Result of shader reflection.
|
|
80
|
+
*/
|
|
81
|
+
export interface ReflectResult {
|
|
82
|
+
/** Binding declarations (@group/@binding variables) */
|
|
83
|
+
bindings: BindingInfo[];
|
|
84
|
+
/** Struct type layouts */
|
|
85
|
+
structs: Record<string, StructLayout>;
|
|
86
|
+
/** Entry point functions */
|
|
87
|
+
entryPoints: EntryPointInfo[];
|
|
88
|
+
/** Parse errors, if any */
|
|
89
|
+
errors: string[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Information about a binding variable.
|
|
94
|
+
*/
|
|
95
|
+
export interface BindingInfo {
|
|
96
|
+
/** Binding group index from @group(n) */
|
|
97
|
+
group: number;
|
|
98
|
+
/** Binding index from @binding(n) */
|
|
99
|
+
binding: number;
|
|
100
|
+
/** Variable name */
|
|
101
|
+
name: string;
|
|
102
|
+
/** Address space: "uniform", "storage", "handle", or "" */
|
|
103
|
+
addressSpace: string;
|
|
104
|
+
/** Access mode for storage: "read", "write", "read_write", or undefined */
|
|
105
|
+
accessMode?: string;
|
|
106
|
+
/** Type as a string (e.g., "MyStruct", "texture_2d<f32>") */
|
|
107
|
+
type: string;
|
|
108
|
+
/** Memory layout for struct types, null for textures/samplers */
|
|
109
|
+
layout: StructLayout | null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Memory layout of a struct type.
|
|
114
|
+
*/
|
|
115
|
+
export interface StructLayout {
|
|
116
|
+
/** Total size in bytes */
|
|
117
|
+
size: number;
|
|
118
|
+
/** Required alignment in bytes */
|
|
119
|
+
alignment: number;
|
|
120
|
+
/** Field layouts */
|
|
121
|
+
fields: FieldInfo[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Layout information for a struct field.
|
|
126
|
+
*/
|
|
127
|
+
export interface FieldInfo {
|
|
128
|
+
/** Field name */
|
|
129
|
+
name: string;
|
|
130
|
+
/** Field type as a string */
|
|
131
|
+
type: string;
|
|
132
|
+
/** Byte offset from start of struct */
|
|
133
|
+
offset: number;
|
|
134
|
+
/** Size in bytes */
|
|
135
|
+
size: number;
|
|
136
|
+
/** Required alignment in bytes */
|
|
137
|
+
alignment: number;
|
|
138
|
+
/** Nested layout for struct or array-of-struct fields */
|
|
139
|
+
layout?: StructLayout;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Information about a shader entry point.
|
|
144
|
+
*/
|
|
145
|
+
export interface EntryPointInfo {
|
|
146
|
+
/** Function name */
|
|
147
|
+
name: string;
|
|
148
|
+
/** Shader stage: "vertex", "fragment", or "compute" */
|
|
149
|
+
stage: string;
|
|
150
|
+
/** Workgroup size [x, y, z] for compute, null otherwise */
|
|
151
|
+
workgroupSize: [number, number, number] | null;
|
|
152
|
+
}
|
|
153
|
+
|
|
78
154
|
/**
|
|
79
155
|
* Options for initializing the WASM module.
|
|
80
156
|
*/
|
|
@@ -106,6 +182,13 @@ export function initialize(options: InitializeOptions): Promise<void>;
|
|
|
106
182
|
*/
|
|
107
183
|
export function minify(source: string, options?: MinifyOptions): MinifyResult;
|
|
108
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Reflect WGSL source to extract binding and struct information.
|
|
187
|
+
* @param source - WGSL source code to analyze
|
|
188
|
+
* @returns Reflection result with bindings, structs, entryPoints, and errors
|
|
189
|
+
*/
|
|
190
|
+
export function reflect(source: string): ReflectResult;
|
|
191
|
+
|
|
109
192
|
/**
|
|
110
193
|
* Check if the WASM module is initialized.
|
|
111
194
|
*/
|
package/lib/main.js
CHANGED
|
@@ -36,8 +36,15 @@ async function initialize(options) {
|
|
|
36
36
|
const wasmModule = options.wasmModule;
|
|
37
37
|
|
|
38
38
|
// Default to miniray.wasm in the package directory
|
|
39
|
+
// Use require.resolve to find files within the package, which works
|
|
40
|
+
// regardless of bundling or working directory
|
|
39
41
|
if (!wasmURL && !wasmModule) {
|
|
40
|
-
|
|
42
|
+
try {
|
|
43
|
+
wasmURL = require.resolve('miniray/miniray.wasm');
|
|
44
|
+
} catch {
|
|
45
|
+
// Fallback to relative path for local development
|
|
46
|
+
wasmURL = path.join(__dirname, '..', 'miniray.wasm');
|
|
47
|
+
}
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
_initPromise = _doInitialize(wasmURL, wasmModule);
|
|
@@ -62,7 +69,16 @@ async function _doInitialize(wasmURL, wasmModule) {
|
|
|
62
69
|
globalThis.crypto ??= require('crypto');
|
|
63
70
|
|
|
64
71
|
// Load wasm_exec.js to set up Go runtime
|
|
65
|
-
|
|
72
|
+
// Use require.resolve to find files within the package, which works
|
|
73
|
+
// regardless of bundling or working directory
|
|
74
|
+
let wasmExecPath;
|
|
75
|
+
try {
|
|
76
|
+
wasmExecPath = require.resolve('miniray/wasm_exec.js');
|
|
77
|
+
} catch {
|
|
78
|
+
// Fallback to relative path for local development
|
|
79
|
+
wasmExecPath = path.join(__dirname, '..', 'wasm_exec.js');
|
|
80
|
+
}
|
|
81
|
+
|
|
66
82
|
if (!fs.existsSync(wasmExecPath)) {
|
|
67
83
|
throw new Error(`wasm_exec.js not found at ${wasmExecPath}`);
|
|
68
84
|
}
|
|
@@ -125,6 +141,23 @@ function minify(source, options) {
|
|
|
125
141
|
return global.__miniray.minify(source, options || {});
|
|
126
142
|
}
|
|
127
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Reflect WGSL source to extract binding and struct information.
|
|
146
|
+
* @param {string} source - WGSL source code
|
|
147
|
+
* @returns {Object} Reflection result with bindings, structs, entryPoints, and errors
|
|
148
|
+
*/
|
|
149
|
+
function reflect(source) {
|
|
150
|
+
if (!_initialized) {
|
|
151
|
+
throw new Error('miniray not initialized. Call initialize() first.');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (typeof source !== 'string') {
|
|
155
|
+
throw new Error('source must be a string');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return global.__miniray.reflect(source);
|
|
159
|
+
}
|
|
160
|
+
|
|
128
161
|
/**
|
|
129
162
|
* Check if initialized.
|
|
130
163
|
* @returns {boolean}
|
|
@@ -147,6 +180,7 @@ function getVersion() {
|
|
|
147
180
|
module.exports = {
|
|
148
181
|
initialize,
|
|
149
182
|
minify,
|
|
183
|
+
reflect,
|
|
150
184
|
isInitialized,
|
|
151
185
|
get version() { return getVersion(); }
|
|
152
186
|
};
|
package/miniray.wasm
CHANGED
|
Binary file
|