From 094a26beadf74809c2ca9cf39743c220902348ca Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Thu, 9 Jan 2025 11:26:34 -0800 Subject: [PATCH] gosl: read-or-write var flag working for Context like variables that are mostly read-only but sometimes writeable. --- gosl/examples/basic/shaders/Compute.wgsl | 2 +- gosl/gotosl/gengpu.go | 2 +- gosl/gotosl/genkernel.go | 3 +-- gosl/gotosl/gotosl.go | 8 +++++++- gosl/gotosl/nodes.go | 6 +++++- gosl/gotosl/testdata/Compute.golden | 2 +- gosl/gotosl/testdata/basic.go | 5 +++-- gosl/gotosl/testdata/basic.goal | 5 +++-- gosl/gotosl/testdata/gosl.golden | 1 - 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/gosl/examples/basic/shaders/Compute.wgsl b/gosl/examples/basic/shaders/Compute.wgsl index 51b96c2..09706da 100644 --- a/gosl/examples/basic/shaders/Compute.wgsl +++ b/gosl/examples/basic/shaders/Compute.wgsl @@ -57,7 +57,7 @@ fn ParamStruct_IntegFromRaw(ps: ParamStruct, idx: i32) { SubStruct_IntegFromRaw(ps.Sub, idx); } fn Compute(i: u32) { //gosl:kernel - let Params=Params[0]; ParamStruct_IntegFromRaw(Params, i32(i)); + let params=Params[0]; ParamStruct_IntegFromRaw(params, i32(i)); } //////// import: "atomic.go" diff --git a/gosl/gotosl/gengpu.go b/gosl/gotosl/gengpu.go index 9f37eef..0c51fc6 100644 --- a/gosl/gotosl/gengpu.go +++ b/gosl/gotosl/gengpu.go @@ -197,7 +197,7 @@ func (st *State) GenGPUSystemInit(sy *System) string { } else { b.WriteString(fmt.Sprintf("\t\t\tvr = sgp.AddStruct(%q, int(unsafe.Sizeof(%s{})), 1, gpu.ComputeShader)\n", vr.Name, vr.SLType())) } - if vr.ReadOnly { + if vr.ReadOnly && !vr.ReadOrWrite { b.WriteString("\t\t\tvr.ReadOnly = true\n") } } diff --git a/gosl/gotosl/genkernel.go b/gosl/gotosl/genkernel.go index cdf178f..03ab8d7 100644 --- a/gosl/gotosl/genkernel.go +++ b/gosl/gotosl/genkernel.go @@ -36,8 +36,7 @@ func (st *State) GenKernelHeader(sy *System, kn *Kernel, avars map[string]*Var) } for vi, vr := range gp.Vars { access := ", read_write" - rw := st.VarIsReadWrite(vr.Name) - if vr.ReadOnly && !rw { + if vr.ReadOnly && !vr.ReadOrWrite { access = ", read" } if gp.Uniform { diff --git a/gosl/gotosl/gotosl.go b/gosl/gotosl/gotosl.go index 586ca92..5fb1c2e 100644 --- a/gosl/gotosl/gotosl.go +++ b/gosl/gotosl/gotosl.go @@ -52,7 +52,7 @@ type Kernel struct { // Lines is full shader code Lines [][]byte - // ReadWriteVars are variables marked as read_write for current kernel. + // ReadWriteVars are variables marked as read-write for current kernel. ReadWriteVars map[string]bool } @@ -71,6 +71,12 @@ type Var struct { // It is important to optimize GPU memory usage to indicate this. ReadOnly bool + // ReadOrWrite indicates that this variable defaults to ReadOnly + // but is also flagged as read-write in some cases. It is registered + // as read_write in the gpu ComputeSystem, but processed as ReadOnly + // by default except for kernels that declare it as read-write. + ReadOrWrite bool + // True if a tensor type Tensor bool diff --git a/gosl/gotosl/nodes.go b/gosl/gotosl/nodes.go index 98cbe7e..c036fc9 100644 --- a/gosl/gotosl/nodes.go +++ b/gosl/gotosl/nodes.go @@ -2690,8 +2690,12 @@ func (p *printer) systemVars(d *ast.GenDecl, sysname string) { vs := s.(*ast.ValueSpec) dirs, docs := p.findDirective(vs.Doc) readOnly := false + readOrWrite := false if hasDirective(dirs, "read-only") { readOnly = true + } else if hasDirective(dirs, "read-or-write") { + readOnly = true + readOrWrite = true } if gpnm, ok := directiveAfter(dirs, "group"); ok { if gpnm == "" { @@ -2754,7 +2758,7 @@ func (p *printer) systemVars(d *ast.GenDecl, sysname string) { } typ = sid.Name + "." + sel.Sel.Name } - vr := &Var{Name: nm, Type: typ, ReadOnly: readOnly} + vr := &Var{Name: nm, Type: typ, ReadOnly: readOnly, ReadOrWrite: readOrWrite} if strings.HasPrefix(typ, "tensor.") { vr.Tensor = true dstr, ok := directiveAfter(dirs, "dims") diff --git a/gosl/gotosl/testdata/Compute.golden b/gosl/gotosl/testdata/Compute.golden index 047bd4f..aba4452 100644 --- a/gosl/gotosl/testdata/Compute.golden +++ b/gosl/gotosl/testdata/Compute.golden @@ -7,7 +7,7 @@ var TensorStrides: array; @group(0) @binding(1) var Params: array; @group(0) @binding(2) -var Ctx: array; +var Ctx: array; // // Data is the data on which the computation operates. // 2D: outer index is data, inner index is: Raw, Integ, Exp vars. // @group(1) @binding(0) var Data: array; diff --git a/gosl/gotosl/testdata/basic.go b/gosl/gotosl/testdata/basic.go index 32d1716..a4a89e1 100644 --- a/gosl/gotosl/testdata/basic.go +++ b/gosl/gotosl/testdata/basic.go @@ -20,9 +20,10 @@ var ( //gosl:read-only Params []ParamStruct - // Ctx provides additional context. + // Ctx provides additional context, and is usually read-only, + // but is updated in a specific kernel flagged as read-write. // - //gosl:read-only + //gosl:read-or-write Ctx []Context // Data is the data on which the computation operates. diff --git a/gosl/gotosl/testdata/basic.goal b/gosl/gotosl/testdata/basic.goal index 26c9340..f2afee0 100644 --- a/gosl/gotosl/testdata/basic.goal +++ b/gosl/gotosl/testdata/basic.goal @@ -16,8 +16,9 @@ var ( //gosl:read-only Params []ParamStruct - // Ctx provides additional context. - //gosl:read-only + // Ctx provides additional context, and is usually read-only, + // but is updated in a specific kernel flagged as read-write. + //gosl:read-or-write Ctx []Context // Data is the data on which the computation operates. diff --git a/gosl/gotosl/testdata/gosl.golden b/gosl/gotosl/testdata/gosl.golden index 3e64bdb..408cae2 100644 --- a/gosl/gotosl/testdata/gosl.golden +++ b/gosl/gotosl/testdata/gosl.golden @@ -58,7 +58,6 @@ func GPUInit() { vr = sgp.AddStruct("Params", int(unsafe.Sizeof(ParamStruct{})), 1, gpu.ComputeShader) vr.ReadOnly = true vr = sgp.AddStruct("Ctx", int(unsafe.Sizeof(Context{})), 1, gpu.ComputeShader) - vr.ReadOnly = true sgp.SetNValues(1) } {