diff --git a/gpu/compute.go b/gpu/compute.go index bd177fd1..cbd7c753 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -463,6 +463,7 @@ func newCompute(ctx driver.Device) (*compute, error) { SrcFactor: driver.BlendFactorOne, DstFactor: driver.BlendFactorOneMinusSrcAlpha, }, + Topology: driver.TopologyTriangles, }) if err != nil { g.Release() @@ -496,6 +497,7 @@ func newCompute(ctx driver.Device) (*compute, error) { Stride: int(unsafe.Sizeof(g.materials.quads[0])), }, PixelFormat: driver.TextureFormatRGBA8, + Topology: driver.TopologyTriangles, }) if err != nil { g.Release() @@ -909,7 +911,7 @@ func (g *compute) blitLayers(viewport image.Point) { g.output.buffer.buffer.Upload(vertexData) g.ctx.BindVertexBuffer(g.output.buffer.buffer, 0) g.ctx.BindTexture(0, atlas.image) - g.ctx.DrawArrays(driver.DrawModeTriangles, 0, len(g.output.layerVertices)) + g.ctx.DrawArrays(0, len(g.output.layerVertices)) } } @@ -1020,7 +1022,7 @@ func (g *compute) renderMaterials() error { for i, a := range newAllocs { sz := a.rect.Size().Sub(padding) g.ctx.Viewport(a.rect.Min.X, a.rect.Min.Y, sz.X, sz.Y) - g.ctx.DrawArrays(driver.DrawModeTriangles, i*6, 6) + g.ctx.DrawArrays(i*6, 6) } g.ctx.EndRenderPass() if !g.useCPU { diff --git a/gpu/gpu.go b/gpu/gpu.go index d83a995c..10423650 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -584,6 +584,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader. BlendDesc: blend, VertexLayout: layout, PixelFormat: driver.TextureFormatOutput, + Topology: driver.TopologyTriangleStrip, }) if err != nil { return pipelines, err @@ -611,6 +612,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader. BlendDesc: blend, VertexLayout: layout, PixelFormat: driver.TextureFormatOutput, + Topology: driver.TopologyTriangleStrip, }) if err != nil { pipelines[materialTexture].Release() @@ -639,6 +641,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader. BlendDesc: blend, VertexLayout: layout, PixelFormat: driver.TextureFormatOutput, + Topology: driver.TopologyTriangleStrip, }) if err != nil { pipelines[materialTexture].Release() @@ -740,7 +743,7 @@ func (r *renderer) intersectPath(p *pathOp, clip image.Rectangle) { r.pather.stenciler.ipipeline.uniforms.vert.uvTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y} r.pather.stenciler.ipipeline.uniforms.vert.subUVTransform = [4]float32{subScale.X, subScale.Y, subOff.X, subOff.Y} r.pather.stenciler.ipipeline.pipeline.UploadUniforms(r.ctx) - r.ctx.DrawArrays(driver.DrawModeTriangleStrip, 0, 4) + r.ctx.DrawArrays(0, 4) } func (r *renderer) packIntersections(ops []imageOp) { @@ -1166,7 +1169,7 @@ func (b *blitter) blit(mat materialType, col f32color.RGBA, col1, col2 f32color. } uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y} p.UploadUniforms(b.ctx) - b.ctx.DrawArrays(driver.DrawModeTriangleStrip, 0, 4) + b.ctx.DrawArrays(0, 4) } // newUniformBuffer creates a new GPU uniform buffer backed by the diff --git a/gpu/headless/driver_test.go b/gpu/headless/driver_test.go index 550edefb..ddebc2b4 100644 --- a/gpu/headless/driver_test.go +++ b/gpu/headless/driver_test.go @@ -56,6 +56,7 @@ func TestSimpleShader(t *testing.T) { VertexShader: vsh, FragmentShader: fsh, PixelFormat: driver.TextureFormatSRGBA, + Topology: driver.TopologyTriangles, }) if err != nil { t.Fatal(err) @@ -68,7 +69,7 @@ func TestSimpleShader(t *testing.T) { b.BeginRenderPass(fbo, d) b.Viewport(0, 0, sz.X, sz.Y) b.BindPipeline(p) - b.DrawArrays(driver.DrawModeTriangles, 0, 3) + b.DrawArrays(0, 3) b.EndRenderPass() img := screenshot(t, b, fbo, sz) if got := img.RGBAAt(0, 0); got != clearColExpect { @@ -107,6 +108,7 @@ func TestInputShader(t *testing.T) { FragmentShader: fsh, VertexLayout: layout, PixelFormat: driver.TextureFormatSRGBA, + Topology: driver.TopologyTriangles, }) if err != nil { t.Fatal(err) @@ -131,7 +133,7 @@ func TestInputShader(t *testing.T) { b.Viewport(0, 0, sz.X, sz.Y) b.BindPipeline(pipe) b.BindVertexBuffer(buf, 0) - b.DrawArrays(driver.DrawModeTriangles, 0, 3) + b.DrawArrays(0, 3) b.EndRenderPass() img := screenshot(t, b, fbo, sz) if got := img.RGBAAt(0, 0); got != clearColExpect { diff --git a/gpu/internal/d3d11/d3d11_windows.go b/gpu/internal/d3d11/d3d11_windows.go index 3d845c15..f53fea0f 100644 --- a/gpu/internal/d3d11/d3d11_windows.go +++ b/gpu/internal/d3d11/d3d11_windows.go @@ -42,11 +42,12 @@ type Backend struct { } type Pipeline struct { - vert *d3d11.VertexShader - frag *d3d11.PixelShader - layout *d3d11.InputLayout - blend *d3d11.BlendState - stride int + vert *d3d11.VertexShader + frag *d3d11.PixelShader + layout *d3d11.InputLayout + blend *d3d11.BlendState + stride int + topology driver.Topology } type Texture struct { @@ -497,11 +498,12 @@ func (b *Backend) NewPipeline(desc driver.PipelineDesc) (driver.Pipeline, error) d3d11.IUnknownAddRef(unsafe.Pointer(fshRef), fshRef.Vtbl.AddRef) return &Pipeline{ - vert: vshRef, - frag: fshRef, - layout: layout, - stride: desc.VertexLayout.Stride, - blend: blend, + vert: vshRef, + frag: fshRef, + layout: layout, + stride: desc.VertexLayout.Stride, + blend: blend, + topology: desc.Topology, }, nil } @@ -551,31 +553,33 @@ func (b *Backend) Viewport(x, y, width, height int) { b.ctx.RSSetViewports(&b.viewport) } -func (b *Backend) DrawArrays(mode driver.DrawMode, off, count int) { - b.prepareDraw(mode) +func (b *Backend) DrawArrays(off, count int) { + b.prepareDraw() b.ctx.Draw(uint32(count), uint32(off)) } -func (b *Backend) DrawElements(mode driver.DrawMode, off, count int) { - b.prepareDraw(mode) +func (b *Backend) DrawElements(off, count int) { + b.prepareDraw() b.ctx.DrawIndexed(uint32(count), uint32(off), 0) } -func (b *Backend) prepareDraw(mode driver.DrawMode) { - if p := b.pipeline; p != nil { - b.ctx.VSSetShader(p.vert) - b.ctx.PSSetShader(p.frag) - b.ctx.IASetInputLayout(p.layout) - b.ctx.OMSetBlendState(p.blend, nil, 0xffffffff) - if b.vert.buffer != nil { - b.ctx.IASetVertexBuffers(b.vert.buffer.buf, uint32(p.stride), uint32(b.vert.offset)) - } +func (b *Backend) prepareDraw() { + p := b.pipeline + if p == nil { + return + } + b.ctx.VSSetShader(p.vert) + b.ctx.PSSetShader(p.frag) + b.ctx.IASetInputLayout(p.layout) + b.ctx.OMSetBlendState(p.blend, nil, 0xffffffff) + if b.vert.buffer != nil { + b.ctx.IASetVertexBuffers(b.vert.buffer.buf, uint32(p.stride), uint32(b.vert.offset)) } var topology uint32 - switch mode { - case driver.DrawModeTriangles: + switch p.topology { + case driver.TopologyTriangles: topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLELIST - case driver.DrawModeTriangleStrip: + case driver.TopologyTriangleStrip: topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLESTRIP default: panic("unsupported draw mode") diff --git a/gpu/internal/driver/driver.go b/gpu/internal/driver/driver.go index 9a74096e..08a1558c 100644 --- a/gpu/internal/driver/driver.go +++ b/gpu/internal/driver/driver.go @@ -32,8 +32,8 @@ type Device interface { NewPipeline(desc PipelineDesc) (Pipeline, error) Viewport(x, y, width, height int) - DrawArrays(mode DrawMode, off, count int) - DrawElements(mode DrawMode, off, count int) + DrawArrays(off, count int) + DrawElements(off, count int) BeginRenderPass(f Framebuffer, desc LoadDesc) EndRenderPass() @@ -71,6 +71,7 @@ type PipelineDesc struct { VertexLayout VertexLayout BlendDesc BlendDesc PixelFormat TextureFormat + Topology Topology } type VertexLayout struct { @@ -95,7 +96,7 @@ type AccessBits uint8 type BlendFactor uint8 -type DrawMode uint8 +type Topology uint8 type TextureFilter uint8 type TextureFormat uint8 @@ -186,8 +187,8 @@ const ( ) const ( - DrawModeTriangleStrip DrawMode = iota - DrawModeTriangles + TopologyTriangleStrip Topology = iota + TopologyTriangles ) const ( diff --git a/gpu/internal/metal/metal_darwin.go b/gpu/internal/metal/metal_darwin.go index e9b00445..3adb8749 100644 --- a/gpu/internal/metal/metal_darwin.go +++ b/gpu/internal/metal/metal_darwin.go @@ -387,7 +387,8 @@ type Backend struct { computeEnc C.CFTypeRef blitEnc C.CFTypeRef - prog *Program + prog *Program + topology C.MTLPrimitiveType stagingBuf C.CFTypeRef stagingOff int @@ -420,6 +421,7 @@ type Program struct { type Pipeline struct { pipeline C.CFTypeRef + topology C.MTLPrimitiveType } type Framebuffer struct { @@ -659,7 +661,7 @@ func (b *Backend) NewPipeline(desc driver.PipelineDesc) (driver.Pipeline, error) if pipe == 0 { return nil, errors.New("metal: pipeline construction failed") } - return &Pipeline{pipeline: pipe}, nil + return &Pipeline{pipeline: pipe, topology: primitiveFor(desc.Topology)}, nil } func dataTypeSize(d shader.DataType) int { @@ -799,29 +801,27 @@ func (b *Backend) Viewport(x, y, width, height int) { }) } -func (b *Backend) DrawArrays(mode driver.DrawMode, off, count int) { +func (b *Backend) DrawArrays(off, count int) { enc := b.renderEnc if enc == 0 { panic("no active render pass") } - t := primitiveFor(mode) - C.renderEncDrawPrimitives(enc, t, C.NSUInteger(off), C.NSUInteger(count)) + C.renderEncDrawPrimitives(enc, b.topology, C.NSUInteger(off), C.NSUInteger(count)) } -func (b *Backend) DrawElements(mode driver.DrawMode, off, count int) { +func (b *Backend) DrawElements(off, count int) { enc := b.renderEnc if enc == 0 { panic("no active render pass") } - t := primitiveFor(mode) - C.renderEncDrawIndexedPrimitives(enc, t, b.indexBuf.buffer, C.NSUInteger(off), C.NSUInteger(count)) + C.renderEncDrawIndexedPrimitives(enc, b.topology, b.indexBuf.buffer, C.NSUInteger(off), C.NSUInteger(count)) } -func primitiveFor(mode driver.DrawMode) C.MTLPrimitiveType { +func primitiveFor(mode driver.Topology) C.MTLPrimitiveType { switch mode { - case driver.DrawModeTriangles: + case driver.TopologyTriangles: return C.MTLPrimitiveTypeTriangle - case driver.DrawModeTriangleStrip: + case driver.TopologyTriangleStrip: return C.MTLPrimitiveTypeTriangleStrip default: panic("metal: unknown draw mode") @@ -960,6 +960,7 @@ func (b *Backend) BindPipeline(pipe driver.Pipeline) { panic("no active render pass") } C.renderEncSetRenderPipelineState(enc, p.pipeline) + b.topology = p.topology } func (b *Backend) BindProgram(prog driver.Program) { diff --git a/gpu/internal/opengl/opengl.go b/gpu/internal/opengl/opengl.go index 131dd7aa..51bc1e73 100644 --- a/gpu/internal/opengl/opengl.go +++ b/gpu/internal/opengl/opengl.go @@ -113,10 +113,11 @@ type framebuffer struct { } type pipeline struct { - prog *program - inputs []shader.InputLocation - layout driver.VertexLayout - blend driver.BlendDesc + prog *program + inputs []shader.InputLocation + layout driver.VertexLayout + blend driver.BlendDesc + topology driver.Topology } type buffer struct { @@ -822,16 +823,16 @@ func (b *Backend) SetBlend(enable bool) { b.glstate.set(b.funcs, gl.BLEND, enable) } -func (b *Backend) DrawElements(mode driver.DrawMode, off, count int) { +func (b *Backend) DrawElements(off, count int) { b.prepareDraw() // off is in 16-bit indices, but DrawElements take a byte offset. byteOff := off * 2 - b.funcs.DrawElements(toGLDrawMode(mode), count, gl.UNSIGNED_SHORT, byteOff) + b.funcs.DrawElements(toGLDrawMode(b.state.pipeline.topology), count, gl.UNSIGNED_SHORT, byteOff) } -func (b *Backend) DrawArrays(mode driver.DrawMode, off, count int) { +func (b *Backend) DrawArrays(off, count int) { b.prepareDraw() - b.funcs.DrawArrays(toGLDrawMode(mode), off, count) + b.funcs.DrawArrays(toGLDrawMode(b.state.pipeline.topology), off, count) } func (b *Backend) prepareDraw() { @@ -843,11 +844,11 @@ func (b *Backend) prepareDraw() { p.prog.updateUniforms() } -func toGLDrawMode(mode driver.DrawMode) gl.Enum { +func toGLDrawMode(mode driver.Topology) gl.Enum { switch mode { - case driver.DrawModeTriangleStrip: + case driver.TopologyTriangleStrip: return gl.TRIANGLE_STRIP - case driver.DrawModeTriangles: + case driver.TopologyTriangles: return gl.TRIANGLES default: panic("unsupported draw mode") @@ -918,10 +919,11 @@ func (b *Backend) NewPipeline(desc driver.PipelineDesc) (driver.Pipeline, error) } } return &pipeline{ - prog: p, - inputs: vsrc.Inputs, - layout: layout, - blend: desc.BlendDesc, + prog: p, + inputs: vsrc.Inputs, + layout: layout, + blend: desc.BlendDesc, + topology: desc.Topology, }, nil } diff --git a/gpu/path.go b/gpu/path.go index 940c4e86..d28c7c96 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -226,6 +226,7 @@ func newStenciler(ctx driver.Device) *stenciler { DstFactor: driver.BlendFactorOne, }, PixelFormat: driver.TextureFormatFloat, + Topology: driver.TopologyTriangles, }) st.pipeline.pipeline = &pipeline{pipe, vertUniforms, nil} if err != nil { @@ -249,6 +250,7 @@ func newStenciler(ctx driver.Device) *stenciler { DstFactor: driver.BlendFactorZero, }, PixelFormat: driver.TextureFormatFloat, + Topology: driver.TopologyTriangleStrip, }) st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms, nil} return st @@ -375,7 +377,7 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima } off := vertStride * start * 4 s.ctx.BindVertexBuffer(data.data, off) - s.ctx.DrawElements(driver.DrawModeTriangles, 0, batch*6) + s.ctx.DrawElements(0, batch*6) start += batch } } @@ -407,7 +409,7 @@ func (c *coverer) cover(mat materialType, col f32color.RGBA, col1, col2 f32color uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y} uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y} c.pipelines[mat].UploadUniforms(c.ctx) - c.ctx.DrawArrays(driver.DrawModeTriangleStrip, 0, 4) + c.ctx.DrawArrays(0, 4) } func init() {