gpu: rename DrawMode to Topology and move it to pipeline descriptors

Vulkan needs the topology stated in its pipeline descriptor, not at
draw time.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-09-08 09:48:48 +02:00
parent 41e812d5e8
commit 3d1e9b0856
8 changed files with 82 additions and 65 deletions
+4 -2
View File
@@ -463,6 +463,7 @@ func newCompute(ctx driver.Device) (*compute, error) {
SrcFactor: driver.BlendFactorOne, SrcFactor: driver.BlendFactorOne,
DstFactor: driver.BlendFactorOneMinusSrcAlpha, DstFactor: driver.BlendFactorOneMinusSrcAlpha,
}, },
Topology: driver.TopologyTriangles,
}) })
if err != nil { if err != nil {
g.Release() g.Release()
@@ -496,6 +497,7 @@ func newCompute(ctx driver.Device) (*compute, error) {
Stride: int(unsafe.Sizeof(g.materials.quads[0])), Stride: int(unsafe.Sizeof(g.materials.quads[0])),
}, },
PixelFormat: driver.TextureFormatRGBA8, PixelFormat: driver.TextureFormatRGBA8,
Topology: driver.TopologyTriangles,
}) })
if err != nil { if err != nil {
g.Release() g.Release()
@@ -909,7 +911,7 @@ func (g *compute) blitLayers(viewport image.Point) {
g.output.buffer.buffer.Upload(vertexData) g.output.buffer.buffer.Upload(vertexData)
g.ctx.BindVertexBuffer(g.output.buffer.buffer, 0) g.ctx.BindVertexBuffer(g.output.buffer.buffer, 0)
g.ctx.BindTexture(0, atlas.image) 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 { for i, a := range newAllocs {
sz := a.rect.Size().Sub(padding) sz := a.rect.Size().Sub(padding)
g.ctx.Viewport(a.rect.Min.X, a.rect.Min.Y, sz.X, sz.Y) 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() g.ctx.EndRenderPass()
if !g.useCPU { if !g.useCPU {
+5 -2
View File
@@ -584,6 +584,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
BlendDesc: blend, BlendDesc: blend,
VertexLayout: layout, VertexLayout: layout,
PixelFormat: driver.TextureFormatOutput, PixelFormat: driver.TextureFormatOutput,
Topology: driver.TopologyTriangleStrip,
}) })
if err != nil { if err != nil {
return pipelines, err return pipelines, err
@@ -611,6 +612,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
BlendDesc: blend, BlendDesc: blend,
VertexLayout: layout, VertexLayout: layout,
PixelFormat: driver.TextureFormatOutput, PixelFormat: driver.TextureFormatOutput,
Topology: driver.TopologyTriangleStrip,
}) })
if err != nil { if err != nil {
pipelines[materialTexture].Release() pipelines[materialTexture].Release()
@@ -639,6 +641,7 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
BlendDesc: blend, BlendDesc: blend,
VertexLayout: layout, VertexLayout: layout,
PixelFormat: driver.TextureFormatOutput, PixelFormat: driver.TextureFormatOutput,
Topology: driver.TopologyTriangleStrip,
}) })
if err != nil { if err != nil {
pipelines[materialTexture].Release() 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.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.uniforms.vert.subUVTransform = [4]float32{subScale.X, subScale.Y, subOff.X, subOff.Y}
r.pather.stenciler.ipipeline.pipeline.UploadUniforms(r.ctx) 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) { 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} uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
p.UploadUniforms(b.ctx) 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 // newUniformBuffer creates a new GPU uniform buffer backed by the
+4 -2
View File
@@ -56,6 +56,7 @@ func TestSimpleShader(t *testing.T) {
VertexShader: vsh, VertexShader: vsh,
FragmentShader: fsh, FragmentShader: fsh,
PixelFormat: driver.TextureFormatSRGBA, PixelFormat: driver.TextureFormatSRGBA,
Topology: driver.TopologyTriangles,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -68,7 +69,7 @@ func TestSimpleShader(t *testing.T) {
b.BeginRenderPass(fbo, d) b.BeginRenderPass(fbo, d)
b.Viewport(0, 0, sz.X, sz.Y) b.Viewport(0, 0, sz.X, sz.Y)
b.BindPipeline(p) b.BindPipeline(p)
b.DrawArrays(driver.DrawModeTriangles, 0, 3) b.DrawArrays(0, 3)
b.EndRenderPass() b.EndRenderPass()
img := screenshot(t, b, fbo, sz) img := screenshot(t, b, fbo, sz)
if got := img.RGBAAt(0, 0); got != clearColExpect { if got := img.RGBAAt(0, 0); got != clearColExpect {
@@ -107,6 +108,7 @@ func TestInputShader(t *testing.T) {
FragmentShader: fsh, FragmentShader: fsh,
VertexLayout: layout, VertexLayout: layout,
PixelFormat: driver.TextureFormatSRGBA, PixelFormat: driver.TextureFormatSRGBA,
Topology: driver.TopologyTriangles,
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -131,7 +133,7 @@ func TestInputShader(t *testing.T) {
b.Viewport(0, 0, sz.X, sz.Y) b.Viewport(0, 0, sz.X, sz.Y)
b.BindPipeline(pipe) b.BindPipeline(pipe)
b.BindVertexBuffer(buf, 0) b.BindVertexBuffer(buf, 0)
b.DrawArrays(driver.DrawModeTriangles, 0, 3) b.DrawArrays(0, 3)
b.EndRenderPass() b.EndRenderPass()
img := screenshot(t, b, fbo, sz) img := screenshot(t, b, fbo, sz)
if got := img.RGBAAt(0, 0); got != clearColExpect { if got := img.RGBAAt(0, 0); got != clearColExpect {
+30 -26
View File
@@ -42,11 +42,12 @@ type Backend struct {
} }
type Pipeline struct { type Pipeline struct {
vert *d3d11.VertexShader vert *d3d11.VertexShader
frag *d3d11.PixelShader frag *d3d11.PixelShader
layout *d3d11.InputLayout layout *d3d11.InputLayout
blend *d3d11.BlendState blend *d3d11.BlendState
stride int stride int
topology driver.Topology
} }
type Texture struct { 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) d3d11.IUnknownAddRef(unsafe.Pointer(fshRef), fshRef.Vtbl.AddRef)
return &Pipeline{ return &Pipeline{
vert: vshRef, vert: vshRef,
frag: fshRef, frag: fshRef,
layout: layout, layout: layout,
stride: desc.VertexLayout.Stride, stride: desc.VertexLayout.Stride,
blend: blend, blend: blend,
topology: desc.Topology,
}, nil }, nil
} }
@@ -551,31 +553,33 @@ func (b *Backend) Viewport(x, y, width, height int) {
b.ctx.RSSetViewports(&b.viewport) b.ctx.RSSetViewports(&b.viewport)
} }
func (b *Backend) DrawArrays(mode driver.DrawMode, off, count int) { func (b *Backend) DrawArrays(off, count int) {
b.prepareDraw(mode) b.prepareDraw()
b.ctx.Draw(uint32(count), uint32(off)) b.ctx.Draw(uint32(count), uint32(off))
} }
func (b *Backend) DrawElements(mode driver.DrawMode, off, count int) { func (b *Backend) DrawElements(off, count int) {
b.prepareDraw(mode) b.prepareDraw()
b.ctx.DrawIndexed(uint32(count), uint32(off), 0) b.ctx.DrawIndexed(uint32(count), uint32(off), 0)
} }
func (b *Backend) prepareDraw(mode driver.DrawMode) { func (b *Backend) prepareDraw() {
if p := b.pipeline; p != nil { p := b.pipeline
b.ctx.VSSetShader(p.vert) if p == nil {
b.ctx.PSSetShader(p.frag) return
b.ctx.IASetInputLayout(p.layout) }
b.ctx.OMSetBlendState(p.blend, nil, 0xffffffff) b.ctx.VSSetShader(p.vert)
if b.vert.buffer != nil { b.ctx.PSSetShader(p.frag)
b.ctx.IASetVertexBuffers(b.vert.buffer.buf, uint32(p.stride), uint32(b.vert.offset)) 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 var topology uint32
switch mode { switch p.topology {
case driver.DrawModeTriangles: case driver.TopologyTriangles:
topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLELIST topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLELIST
case driver.DrawModeTriangleStrip: case driver.TopologyTriangleStrip:
topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLESTRIP topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
default: default:
panic("unsupported draw mode") panic("unsupported draw mode")
+6 -5
View File
@@ -32,8 +32,8 @@ type Device interface {
NewPipeline(desc PipelineDesc) (Pipeline, error) NewPipeline(desc PipelineDesc) (Pipeline, error)
Viewport(x, y, width, height int) Viewport(x, y, width, height int)
DrawArrays(mode DrawMode, off, count int) DrawArrays(off, count int)
DrawElements(mode DrawMode, off, count int) DrawElements(off, count int)
BeginRenderPass(f Framebuffer, desc LoadDesc) BeginRenderPass(f Framebuffer, desc LoadDesc)
EndRenderPass() EndRenderPass()
@@ -71,6 +71,7 @@ type PipelineDesc struct {
VertexLayout VertexLayout VertexLayout VertexLayout
BlendDesc BlendDesc BlendDesc BlendDesc
PixelFormat TextureFormat PixelFormat TextureFormat
Topology Topology
} }
type VertexLayout struct { type VertexLayout struct {
@@ -95,7 +96,7 @@ type AccessBits uint8
type BlendFactor uint8 type BlendFactor uint8
type DrawMode uint8 type Topology uint8
type TextureFilter uint8 type TextureFilter uint8
type TextureFormat uint8 type TextureFormat uint8
@@ -186,8 +187,8 @@ const (
) )
const ( const (
DrawModeTriangleStrip DrawMode = iota TopologyTriangleStrip Topology = iota
DrawModeTriangles TopologyTriangles
) )
const ( const (
+12 -11
View File
@@ -387,7 +387,8 @@ type Backend struct {
computeEnc C.CFTypeRef computeEnc C.CFTypeRef
blitEnc C.CFTypeRef blitEnc C.CFTypeRef
prog *Program prog *Program
topology C.MTLPrimitiveType
stagingBuf C.CFTypeRef stagingBuf C.CFTypeRef
stagingOff int stagingOff int
@@ -420,6 +421,7 @@ type Program struct {
type Pipeline struct { type Pipeline struct {
pipeline C.CFTypeRef pipeline C.CFTypeRef
topology C.MTLPrimitiveType
} }
type Framebuffer struct { type Framebuffer struct {
@@ -659,7 +661,7 @@ func (b *Backend) NewPipeline(desc driver.PipelineDesc) (driver.Pipeline, error)
if pipe == 0 { if pipe == 0 {
return nil, errors.New("metal: pipeline construction failed") 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 { 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 enc := b.renderEnc
if enc == 0 { if enc == 0 {
panic("no active render pass") panic("no active render pass")
} }
t := primitiveFor(mode) C.renderEncDrawPrimitives(enc, b.topology, C.NSUInteger(off), C.NSUInteger(count))
C.renderEncDrawPrimitives(enc, t, 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 enc := b.renderEnc
if enc == 0 { if enc == 0 {
panic("no active render pass") panic("no active render pass")
} }
t := primitiveFor(mode) C.renderEncDrawIndexedPrimitives(enc, b.topology, b.indexBuf.buffer, C.NSUInteger(off), C.NSUInteger(count))
C.renderEncDrawIndexedPrimitives(enc, t, 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 { switch mode {
case driver.DrawModeTriangles: case driver.TopologyTriangles:
return C.MTLPrimitiveTypeTriangle return C.MTLPrimitiveTypeTriangle
case driver.DrawModeTriangleStrip: case driver.TopologyTriangleStrip:
return C.MTLPrimitiveTypeTriangleStrip return C.MTLPrimitiveTypeTriangleStrip
default: default:
panic("metal: unknown draw mode") panic("metal: unknown draw mode")
@@ -960,6 +960,7 @@ func (b *Backend) BindPipeline(pipe driver.Pipeline) {
panic("no active render pass") panic("no active render pass")
} }
C.renderEncSetRenderPipelineState(enc, p.pipeline) C.renderEncSetRenderPipelineState(enc, p.pipeline)
b.topology = p.topology
} }
func (b *Backend) BindProgram(prog driver.Program) { func (b *Backend) BindProgram(prog driver.Program) {
+17 -15
View File
@@ -113,10 +113,11 @@ type framebuffer struct {
} }
type pipeline struct { type pipeline struct {
prog *program prog *program
inputs []shader.InputLocation inputs []shader.InputLocation
layout driver.VertexLayout layout driver.VertexLayout
blend driver.BlendDesc blend driver.BlendDesc
topology driver.Topology
} }
type buffer struct { type buffer struct {
@@ -822,16 +823,16 @@ func (b *Backend) SetBlend(enable bool) {
b.glstate.set(b.funcs, gl.BLEND, enable) 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() b.prepareDraw()
// off is in 16-bit indices, but DrawElements take a byte offset. // off is in 16-bit indices, but DrawElements take a byte offset.
byteOff := off * 2 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.prepareDraw()
b.funcs.DrawArrays(toGLDrawMode(mode), off, count) b.funcs.DrawArrays(toGLDrawMode(b.state.pipeline.topology), off, count)
} }
func (b *Backend) prepareDraw() { func (b *Backend) prepareDraw() {
@@ -843,11 +844,11 @@ func (b *Backend) prepareDraw() {
p.prog.updateUniforms() p.prog.updateUniforms()
} }
func toGLDrawMode(mode driver.DrawMode) gl.Enum { func toGLDrawMode(mode driver.Topology) gl.Enum {
switch mode { switch mode {
case driver.DrawModeTriangleStrip: case driver.TopologyTriangleStrip:
return gl.TRIANGLE_STRIP return gl.TRIANGLE_STRIP
case driver.DrawModeTriangles: case driver.TopologyTriangles:
return gl.TRIANGLES return gl.TRIANGLES
default: default:
panic("unsupported draw mode") panic("unsupported draw mode")
@@ -918,10 +919,11 @@ func (b *Backend) NewPipeline(desc driver.PipelineDesc) (driver.Pipeline, error)
} }
} }
return &pipeline{ return &pipeline{
prog: p, prog: p,
inputs: vsrc.Inputs, inputs: vsrc.Inputs,
layout: layout, layout: layout,
blend: desc.BlendDesc, blend: desc.BlendDesc,
topology: desc.Topology,
}, nil }, nil
} }
+4 -2
View File
@@ -226,6 +226,7 @@ func newStenciler(ctx driver.Device) *stenciler {
DstFactor: driver.BlendFactorOne, DstFactor: driver.BlendFactorOne,
}, },
PixelFormat: driver.TextureFormatFloat, PixelFormat: driver.TextureFormatFloat,
Topology: driver.TopologyTriangles,
}) })
st.pipeline.pipeline = &pipeline{pipe, vertUniforms, nil} st.pipeline.pipeline = &pipeline{pipe, vertUniforms, nil}
if err != nil { if err != nil {
@@ -249,6 +250,7 @@ func newStenciler(ctx driver.Device) *stenciler {
DstFactor: driver.BlendFactorZero, DstFactor: driver.BlendFactorZero,
}, },
PixelFormat: driver.TextureFormatFloat, PixelFormat: driver.TextureFormatFloat,
Topology: driver.TopologyTriangleStrip,
}) })
st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms, nil} st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms, nil}
return st return st
@@ -375,7 +377,7 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
} }
off := vertStride * start * 4 off := vertStride * start * 4
s.ctx.BindVertexBuffer(data.data, off) s.ctx.BindVertexBuffer(data.data, off)
s.ctx.DrawElements(driver.DrawModeTriangles, 0, batch*6) s.ctx.DrawElements(0, batch*6)
start += batch 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.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y} uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y}
c.pipelines[mat].UploadUniforms(c.ctx) c.pipelines[mat].UploadUniforms(c.ctx)
c.ctx.DrawArrays(driver.DrawModeTriangleStrip, 0, 4) c.ctx.DrawArrays(0, 4)
} }
func init() { func init() {