implementing missing functions in FFI
Build / build (push) Successful in 42s
Test / build (push) Successful in 1m17s

This commit is contained in:
2026-07-04 20:59:03 +02:00
parent 32806def90
commit 589d30168f
9 changed files with 368 additions and 113 deletions
+162 -46
View File
@@ -373,6 +373,41 @@ int main(void)
}
```
## Module reflection from C
`SpvModuleGetReflectionInfos` returns shader-wide metadata collected while parsing the module:
```c
SpvModuleReflectionInfos infos = SpvModuleGetReflectionInfos(module);
if (infos.needs_derivatives)
{
/* Provide derivative data before executing derivative operations. */
}
if (infos.has_control_barriers)
{
/* Use SpvBeginEntryPoint/SpvContinueEntryPoint and synchronize invocations. */
}
if (infos.has_atomics)
{
/* Descriptor or workgroup-backed storage may be modified atomically. */
}
if (infos.early_fragment_tests)
{
/* Fragment shader requested early fragment tests. */
}
```
Compute and geometry execution metadata is also available:
```c
SpvWord local_x = infos.local_size_x;
SpvWord geometry_output_count = infos.geometry_output_count;
```
## Writing inputs from C
Write by result id:
@@ -426,6 +461,24 @@ SpvWord result = 0;
SpvGetResultByLocationComponent(runtime, 0, 1, SPV_LOCATION_OUTPUT, &result);
```
For built-ins:
```c
SpvWord workgroup_id_result = 0;
if (SpvGetBuiltinResult(runtime, SpvBuiltInWorkgroupId, &workgroup_id_result) == SPV_RESULT_SUCCESS)
{
unsigned int workgroup_id[3] = {0};
SpvReadBuiltIn(runtime, (SpvByte*)workgroup_id, sizeof(workgroup_id), SpvBuiltInWorkgroupId);
}
```
If a result's layout depends on specialization constants or runtime-array sizes, refresh it before querying or reading by result id:
```c
SpvRefreshResultValueLayout(runtime, result);
```
## Push constants from C
```c
@@ -485,12 +538,49 @@ SpvAddSpecializationInfo(runtime, entry, (const SpvByte*)&value, sizeof(value));
Add specialization constants before calling the entry point.
If specialization constants affect array sizes, workgroup size, or other layout-dependent metadata, apply the specialization layout after adding the values:
```c
SpvApplySpecializationLayout(runtime);
```
For a fresh invocation layout, use:
```c
SpvApplySpecializationInvocationLayout(runtime);
```
To duplicate specialization constants from another runtime:
```c
SpvCopySpecializationConstantsFrom(runtime, source_runtime);
```
## Entry points from C
Entry points can be looked up by name:
```c
SpvWord entry = 0;
SpvGetEntryPointByName(runtime, "main", &entry);
```
When a module has multiple entry points with the same name, include the execution model:
```c
SpvGetEntryPointByNameAndExecutionModel(
runtime,
"main",
SpvExecutionModelGLCompute,
&entry);
```
Selecting an entry point filters interface lookups such as input and output locations to that entry point:
```c
SpvSelectEntryPoint(runtime, entry);
```
## Derivatives from C
```c
@@ -531,24 +621,63 @@ while (status == SPV_ENTRY_POINT_BARRIER)
}
```
## Workgroup data from C
Compute shaders may declare a static workgroup size. Query it with:
```c
SpvWorkgroupSize size;
if (SpvGetWorkgroupSize(runtime, &size) == SPV_RESULT_SUCCESS && size.has_size)
{
printf("workgroup size = %lu, %lu, %lu\n", size.x, size.y, size.z);
}
```
Workgroup storage is allocated separately so multiple runtime invocations can bind the same shared memory during barrier-based execution:
```c
SpvWorkgroupMemory memory;
if (SpvCreateWorkgroupMemory(runtime, &memory) != SPV_RESULT_SUCCESS)
return 1;
SpvSize count = SpvGetWorkgroupMemoryCount(memory);
for (SpvSize i = 0; i < count; ++i)
{
SpvWorkgroupMemoryItem item;
if (SpvGetWorkgroupMemoryItem(memory, i, &item) == SPV_RESULT_SUCCESS)
{
/* item.result is the Workgroup variable result id.
item.data points to item.size bytes owned by memory. */
}
}
SpvBindWorkgroupMemory(runtime, memory);
/* Run one or more invocations that share this workgroup memory. */
SpvDestroyWorkgroupMemory(runtime, memory);
```
## Image API from C
Shaders that execute image operations must provide callbacks in `SpvImageAPI`.
```c
static SpvResult ReadImageFloat4(
void* driver_image,
SpvDim dim,
int x,
int y,
int z,
SpvReadImageInfo info,
SpvVec4f* dst)
{
(void)driver_image;
(void)dim;
(void)x;
(void)y;
(void)z;
(void)info.driver_image;
(void)info.dim;
(void)info.x;
(void)info.y;
(void)info.z;
(void)info.has_lod;
(void)info.lod;
dst->x = 0.0f;
dst->y = 0.0f;
@@ -563,27 +692,19 @@ Sampling callbacks include an explicit-LOD flag/value and an offset:
```c
static SpvResult SampleImageFloat4(
void* driver_image,
void* driver_sampler,
SpvDim dim,
float x,
float y,
float z,
SpvBool has_lod,
float lod,
SpvImageOffset offset,
SpvSampleImageInfo info,
SpvVec4f* dst)
{
(void)driver_image;
(void)driver_sampler;
(void)dim;
(void)has_lod;
(void)lod;
(void)offset;
(void)info.driver_image;
(void)info.driver_sampler;
(void)info.dim;
(void)info.has_lod;
(void)info.lod;
(void)info.offset;
dst->x = x;
dst->y = y;
dst->z = z;
dst->x = (float)info.x;
dst->y = (float)info.y;
dst->z = (float)info.z;
dst->w = 1.0f;
return SPV_RESULT_SUCCESS;
}
@@ -593,27 +714,19 @@ Depth-comparison samplers add `dref` and write one `float`:
```c
static SpvResult SampleImageDref(
void* driver_image,
void* driver_sampler,
SpvDim dim,
float x,
float y,
float z,
SpvSampleImageInfo info,
float dref,
SpvBool has_lod,
float lod,
SpvImageOffset offset,
float* dst)
{
(void)driver_image;
(void)driver_sampler;
(void)dim;
(void)x;
(void)y;
(void)z;
(void)has_lod;
(void)lod;
(void)offset;
(void)info.driver_image;
(void)info.driver_sampler;
(void)info.dim;
(void)info.x;
(void)info.y;
(void)info.z;
(void)info.has_lod;
(void)info.lod;
(void)info.offset;
*dst = dref;
return SPV_RESULT_SUCCESS;
@@ -632,6 +745,9 @@ SpvImageAPI image_api = {
.SpvSampleImageInt4 = SampleImageInt4,
.SpvSampleImageDref = SampleImageDref,
.SpvQueryImageSize = QueryImageSize,
.SpvQueryImageLevels = QueryImageLevels,
.SpvQueryImageSamples = QueryImageSamples,
.SpvQueryImageLod = QueryImageLod,
};
```