gpu: saturate instead of overflowing depth buffer

Use greater-than-or-equal test and saturate the z depth buffer
when more than 65k objects are drawn.

Fixes gio#127

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-06-08 16:25:47 +02:00
parent 52864950f1
commit 504664e014
6 changed files with 16 additions and 8 deletions
+2
View File
@@ -605,6 +605,8 @@ func (b *Backend) prepareDraw(mode backend.DrawMode) {
switch b.depthState.fn {
case backend.DepthFuncGreater:
desc.DepthFunc = _D3D11_COMPARISON_GREATER
case backend.DepthFuncGreaterEqual:
desc.DepthFunc = _D3D11_COMPARISON_GREATER_EQUAL
default:
panic("unsupported depth func")
}
+2 -1
View File
@@ -621,7 +621,8 @@ const (
_D3D11_DEPTH_WRITE_MASK_ALL = 1
_D3D11_COMPARISON_GREATER = 5
_D3D11_COMPARISON_GREATER = 5
_D3D11_COMPARISON_GREATER_EQUAL = 7
_D3D11_BLEND_OP_ADD = 1
_D3D11_BLEND_ONE = 2
+1
View File
@@ -156,6 +156,7 @@ type Texture interface {
const (
DepthFuncGreater DepthFunc = iota
DepthFuncGreaterEqual
)
const (
+2
View File
@@ -399,6 +399,8 @@ func (b *Backend) DepthFunc(f backend.DepthFunc) {
switch f {
case backend.DepthFuncGreater:
glfunc = GREATER
case backend.DepthFuncGreaterEqual:
glfunc = GEQUAL
default:
panic("unsupported depth func")
}
+1
View File
@@ -35,6 +35,7 @@ const (
INFO_LOG_LENGTH = 0x8B84
INVALID_INDEX = ^uint(0)
GREATER = 0x204
GEQUAL = 0x206
LINEAR = 0x2601
LINK_STATUS = 0x8b82
LUMINANCE = 0x1909
+8 -7
View File
@@ -71,7 +71,7 @@ type drawState struct {
t op.TransformOp
cpath *pathOp
rect bool
z int
z uint16
matType materialType
// Current paint.ImageOp
@@ -335,7 +335,8 @@ func (g *GPU) BeginFrame() {
g.zopsTimer.begin()
}
g.ctx.BindFramebuffer(g.defFBO)
g.ctx.DepthFunc(backend.DepthFuncGreater)
// Equal because of depth saturation.
g.ctx.DepthFunc(backend.DepthFuncGreaterEqual)
g.ctx.ClearDepth(0.0)
g.ctx.Clear(g.drawOps.clearColor.Float32())
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
@@ -680,7 +681,7 @@ func (d *drawOps) newPathOp() *pathOp {
return &d.pathOpCache[len(d.pathOpCache)-1]
}
func (d *drawOps) collectOps(r *ops.Reader, state drawState) int {
func (d *drawOps) collectOps(r *ops.Reader, state drawState) uint16 {
var aux []byte
var auxKey ops.Key
loop:
@@ -749,10 +750,10 @@ loop:
d.clearColor = mat.color.Opaque()
continue
}
state.z++
if state.z != int(uint16(state.z)) {
// TODO(eliasnaur) gioui.org/issue/127.
panic("more than 65k paint objects not supported")
// It's ok to saturate the depth value because we're using
// the >= depth comparison function.
if state.z < 0xffff {
state.z++
}
// Assume 16-bit depth buffer.
const zdepth = 1 << 16