Commit: 446eebd60d359c0a748ea69dbdd82ab67d1c4fb4
Parent: 23d41865917638b402f4f30aa039f4d5837eabfe
Author: Randy Palamar
Date: Thu, 25 Sep 2025 17:23:13 -0600
shaders/decode: switch hadamard matrix back to f32
this saves another ~4.5% since the gpu doesn't have to waste
cycles converting to float. Texture cache is seperate from L1 so
we don't need to worry about polluting it with the large texture
data
Diffstat:
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -245,14 +245,14 @@ alloc_beamform_frame(GLParams *gp, BeamformerFrame *out, iv3 out_dim, GLenum gl_
function void
update_hadamard_texture(BeamformerComputePlan *cp, i32 order, Arena arena)
{
- i32 *hadamard = make_hadamard_transpose(&arena, order);
+ f32 *hadamard = make_hadamard_transpose(&arena, order);
if (hadamard) {
cp->hadamard_order = order;
u32 *texture = cp->textures + BeamformerComputeTextureKind_Hadamard;
glDeleteTextures(1, texture);
glCreateTextures(GL_TEXTURE_2D, 1, texture);
- glTextureStorage2D(*texture, 1, GL_R8I, order, order);
- glTextureSubImage2D(*texture, 0, 0, 0, order, order, GL_RED_INTEGER, GL_INT, hadamard);
+ glTextureStorage2D(*texture, 1, GL_R32F, order, order);
+ glTextureSubImage2D(*texture, 0, 0, 0, order, order, GL_RED, GL_FLOAT, hadamard);
Stream label = arena_stream(arena);
stream_append_s8(&label, s8("Hadamard"));
@@ -878,7 +878,7 @@ do_compute_shader(BeamformerCtx *ctx, BeamformerComputePlan *cp, BeamformerFrame
switch (shader) {
case BeamformerShaderKind_Decode:{
- glBindImageTexture(0, cp->textures[BeamformerComputeTextureKind_Hadamard], 0, 0, 0, GL_READ_ONLY, GL_R8I);
+ glBindImageTexture(0, cp->textures[BeamformerComputeTextureKind_Hadamard], 0, 0, 0, GL_READ_ONLY, GL_R32F);
if (shader_slot == 0) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, cc->ping_pong_ssbos[input_ssbo_idx]);
diff --git a/beamformer.h b/beamformer.h
@@ -138,7 +138,7 @@ typedef enum {BEAMFORMER_COMPUTE_UBO_LIST BeamformerComputeUBOKind_Count} Beamfo
#define BEAMFORMER_COMPUTE_TEXTURE_LIST_FULL \
BEAMFORMER_COMPUTE_TEXTURE_LIST \
- X(Hadamard, GL_R8I)
+ X(Hadamard, GL_R32F)
typedef enum {
#define X(k, ...) BeamformerComputeTextureKind_##k,
diff --git a/math.c b/math.c
@@ -1,13 +1,13 @@
#include "external/cephes.c"
function void
-fill_kronecker_sub_matrix(i32 *out, i32 out_stride, i32 scale, i32 *b, iv2 b_dim)
+fill_kronecker_sub_matrix(f32 *out, i32 out_stride, f32 scale, f32 *b, iv2 b_dim)
{
f32x4 vscale = dup_f32x4((f32)scale);
for (i32 i = 0; i < b_dim.y; i++) {
for (i32 j = 0; j < b_dim.x; j += 4, b += 4) {
- f32x4 vb = cvt_i32x4_f32x4(load_i32x4(b));
- store_i32x4(out + j, cvt_f32x4_i32x4(mul_f32x4(vscale, vb)));
+ f32x4 vb = load_f32x4(b);
+ store_f32x4(out + j, mul_f32x4(vscale, vb));
}
out += out_stride;
}
@@ -15,12 +15,12 @@ fill_kronecker_sub_matrix(i32 *out, i32 out_stride, i32 scale, i32 *b, iv2 b_dim
/* NOTE: this won't check for valid space/etc and assumes row major order */
function void
-kronecker_product(i32 *out, i32 *a, iv2 a_dim, i32 *b, iv2 b_dim)
+kronecker_product(f32 *out, f32 *a, iv2 a_dim, f32 *b, iv2 b_dim)
{
iv2 out_dim = {{a_dim.x * b_dim.x, a_dim.y * b_dim.y}};
assert(out_dim.y % 4 == 0);
for (i32 i = 0; i < a_dim.y; i++) {
- i32 *vout = out;
+ f32 *vout = out;
for (i32 j = 0; j < a_dim.x; j++, a++) {
fill_kronecker_sub_matrix(vout, out_dim.y, *a, b, b_dim);
vout += b_dim.y;
@@ -30,10 +30,10 @@ kronecker_product(i32 *out, i32 *a, iv2 a_dim, i32 *b, iv2 b_dim)
}
/* NOTE/TODO: to support even more hadamard sizes use the Paley construction */
-function i32 *
+function f32 *
make_hadamard_transpose(Arena *a, i32 dim)
{
- read_only local_persist i32 hadamard_12_12_transpose[] = {
+ read_only local_persist f32 hadamard_12_12_transpose[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1,
1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1,
@@ -48,7 +48,7 @@ make_hadamard_transpose(Arena *a, i32 dim)
1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1,
};
- read_only local_persist i32 hadamard_20_20_transpose[] = {
+ read_only local_persist f32 hadamard_20_20_transpose[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1,
1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1,
@@ -71,7 +71,7 @@ make_hadamard_transpose(Arena *a, i32 dim)
1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1,
};
- i32 *result = 0;
+ f32 *result = 0;
b32 power_of_2 = ISPOWEROF2(dim);
b32 multiple_of_12 = dim % 12 == 0;
@@ -89,18 +89,18 @@ make_hadamard_transpose(Arena *a, i32 dim)
dim /= 12;
}
- if (ISPOWEROF2(dim) && base_dim && arena_capacity(a, i32) >= elements * (1 + (dim != base_dim))) {
- result = push_array(a, i32, elements);
+ if (ISPOWEROF2(dim) && base_dim && arena_capacity(a, f32) >= elements * (1 + (dim != base_dim))) {
+ result = push_array(a, f32, elements);
Arena tmp = *a;
- i32 *m = dim == base_dim ? result : push_array(&tmp, i32, elements);
+ f32 *m = dim == base_dim ? result : push_array(&tmp, f32, elements);
#define IND(i, j) ((i) * dim + (j))
m[0] = 1;
for (i32 k = 1; k < dim; k *= 2) {
for (i32 i = 0; i < k; i++) {
for (i32 j = 0; j < k; j++) {
- i32 val = m[IND(i, j)];
+ f32 val = m[IND(i, j)];
m[IND(i + k, j)] = val;
m[IND(i, j + k)] = val;
m[IND(i + k, j + k)] = -val;
@@ -109,7 +109,7 @@ make_hadamard_transpose(Arena *a, i32 dim)
}
#undef IND
- i32 *m2 = 0;
+ f32 *m2 = 0;
iv2 m2_dim;
switch (base_dim) {
case 12:{ m2 = hadamard_12_12_transpose; m2_dim = (iv2){{12, 12}}; }break;
diff --git a/shaders/decode.glsl b/shaders/decode.glsl
@@ -55,7 +55,7 @@ layout(std430, binding = 3) writeonly restrict buffer buffer_3 {
SAMPLE_DATA_TYPE out_data[];
};
-layout(r8i, binding = 0) readonly restrict uniform iimage2D hadamard;
+layout(r32f, binding = 0) readonly restrict uniform image2D hadamard;
layout(r16i, binding = 1) readonly restrict uniform iimage1D channel_mapping;
SAMPLE_DATA_TYPE sample_rf_data(uint index)