From 7024a0e6914d048cd245b1b2a4fc96df3d9538ab Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 11 Mar 2020 16:36:08 +0100 Subject: [PATCH] gpu: fix depth buffer on direct3d and headless opengl Signed-off-by: Elias Naur --- app/headless/headless_test.go | 41 +++++++++++++++ app/internal/d3d11/backend_windows.go | 72 +++++++++++++++++---------- app/internal/d3d11/d3d11_windows.go | 15 ++++++ gpu/gl/backend.go | 1 + gpu/gl/gl.go | 1 + 5 files changed, 103 insertions(+), 27 deletions(-) diff --git a/app/headless/headless_test.go b/app/headless/headless_test.go index 553d04e9..1ac8ff03 100644 --- a/app/headless/headless_test.go +++ b/app/headless/headless_test.go @@ -98,6 +98,47 @@ func TestClipping(t *testing.T) { } } +func TestDepth(t *testing.T) { + w, release := newTestWindow(t) + defer release() + var ops op.Ops + + blue := color.RGBA{B: 0xFF, A: 0xFF} + paint.ColorOp{Color: blue}.Add(&ops) + paint.PaintOp{Rect: f32.Rectangle{ + Max: f32.Point{X: 50, Y: 100}, + }}.Add(&ops) + red := color.RGBA{R: 0xFF, A: 0xFF} + paint.ColorOp{Color: red}.Add(&ops) + paint.PaintOp{Rect: f32.Rectangle{ + Max: f32.Point{X: 100, Y: 50}, + }}.Add(&ops) + w.Frame(&ops) + + img, err := w.Screenshot() + if err != nil { + t.Fatal(err) + } + if *dumpImages { + if err := saveImage("depth.png", img); err != nil { + t.Fatal(err) + } + } + tests := []struct { + x, y int + color color.RGBA + }{ + {25, 25, red}, + {75, 25, red}, + {25, 75, blue}, + } + for _, test := range tests { + if got := img.RGBAAt(test.x, test.y); got != test.color { + t.Errorf("(%d,%d): got color %v, expected %v", test.x, test.y, got, test.color) + } + } +} + func newTestWindow(t *testing.T) (*Window, func()) { t.Helper() sz := image.Point{X: 800, Y: 600} diff --git a/app/internal/d3d11/backend_windows.go b/app/internal/d3d11/backend_windows.go index b04b8c29..1b1210ae 100644 --- a/app/internal/d3d11/backend_windows.go +++ b/app/internal/d3d11/backend_windows.go @@ -193,6 +193,10 @@ func (s *SwapChain) Framebuffer(d *Device) (*Framebuffer, error) { if s.fbo.renderTarget != nil { return s.fbo, nil } + desc, err := s.swchain.GetDesc() + if err != nil { + return nil, err + } backBuffer, err := s.swchain.GetBuffer(0, &_IID_ID3D11Texture2D) if err != nil { return nil, err @@ -203,7 +207,13 @@ func (s *SwapChain) Framebuffer(d *Device) (*Framebuffer, error) { if err != nil { return nil, err } + depthView, err := createDepthView(d.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24) + if err != nil { + _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) + return nil, err + } s.fbo.renderTarget = renderTarget + s.fbo.depthView = depthView s.fbo.dev = d return s.fbo, nil } @@ -255,6 +265,8 @@ func NewBackend(d *Device) (*Backend, error) { FillMode: _D3D11_FILL_SOLID, DepthClipEnable: 1, }) + // Enable depth mask to match OpenGL. + b.depthState.mask = true if err != nil { return nil, err } @@ -359,8 +371,10 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi func (b *Backend) CurrentFramebuffer() backend.Framebuffer { renderTarget := b.dev.ctx.OMGetRenderTargets() - // Assume someone else is holding on to it. - _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) + if renderTarget != nil { + // Assume someone else is holding on to it. + _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) + } if renderTarget == b.fbo.renderTarget { return b.fbo } @@ -379,30 +393,7 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr } fbo := &Framebuffer{dev: b.dev, format: d3dtex.format, resource: resource, renderTarget: renderTarget} if depthBits > 0 { - depthTex, err := b.dev.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ - Width: uint32(d3dtex.width), - Height: uint32(d3dtex.height), - MipLevels: 1, - ArraySize: 1, - Format: _DXGI_FORMAT_D24_UNORM_S8_UINT, - SampleDesc: _DXGI_SAMPLE_DESC{ - Count: 1, - Quality: 0, - }, - BindFlags: _D3D11_BIND_DEPTH_STENCIL, - }) - if err != nil { - _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) - return nil, err - } - depthView, err := b.dev.dev.CreateDepthStencilViewTEX2D( - (*_ID3D11Resource)(unsafe.Pointer(depthTex)), - &_D3D11_DEPTH_STENCIL_VIEW_DESC_TEX2D{ - Format: _DXGI_FORMAT_D24_UNORM_S8_UINT, - ViewDimension: _D3D11_DSV_DIMENSION_TEXTURE2D, - }, - ) - _IUnknownRelease(unsafe.Pointer(depthTex), depthTex.vtbl.Release) + depthView, err := createDepthView(b.dev.dev, d3dtex.width, d3dtex.height, depthBits) if err != nil { _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) return nil, err @@ -412,6 +403,33 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr return fbo, nil } +func createDepthView(d *_ID3D11Device, width, height, depthBits int) (*_ID3D11DepthStencilView, error) { + depthTex, err := d.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ + Width: uint32(width), + Height: uint32(height), + MipLevels: 1, + ArraySize: 1, + Format: _DXGI_FORMAT_D24_UNORM_S8_UINT, + SampleDesc: _DXGI_SAMPLE_DESC{ + Count: 1, + Quality: 0, + }, + BindFlags: _D3D11_BIND_DEPTH_STENCIL, + }) + if err != nil { + return nil, err + } + depthView, err := d.CreateDepthStencilViewTEX2D( + (*_ID3D11Resource)(unsafe.Pointer(depthTex)), + &_D3D11_DEPTH_STENCIL_VIEW_DESC_TEX2D{ + Format: _DXGI_FORMAT_D24_UNORM_S8_UINT, + ViewDimension: _D3D11_DSV_DIMENSION_TEXTURE2D, + }, + ) + _IUnknownRelease(unsafe.Pointer(depthTex), depthTex.vtbl.Release) + return depthView, err +} + func (b *Backend) NewInputLayout(vertexShader backend.ShaderSources, layout []backend.InputDesc) (backend.InputLayout, error) { if len(vertexShader.Inputs) != len(layout) { return nil, fmt.Errorf("NewInputLayout: got %d inputs, expected %d", len(layout), len(vertexShader.Inputs)) @@ -583,7 +601,7 @@ func (b *Backend) prepareDraw(mode backend.DrawMode) { if b.depthState.enable { desc.DepthEnable = 1 } - if !b.depthState.mask { + if b.depthState.mask { desc.DepthWriteMask = _D3D11_DEPTH_WRITE_MASK_ALL } switch b.depthState.fn { diff --git a/app/internal/d3d11/d3d11_windows.go b/app/internal/d3d11/d3d11_windows.go index f84e8f25..940dd68c 100644 --- a/app/internal/d3d11/d3d11_windows.go +++ b/app/internal/d3d11/d3d11_windows.go @@ -912,6 +912,21 @@ func (d *_ID3D11Device) CreateDepthStencilState(desc *_D3D11_DEPTH_STENCIL_DESC) return state, nil } +func (s *_IDXGISwapChain) GetDesc() (_DXGI_SWAP_CHAIN_DESC, error) { + var desc _DXGI_SWAP_CHAIN_DESC + r, _, _ := syscall.Syscall( + s.vtbl.GetDesc, + 2, + uintptr(unsafe.Pointer(s)), + uintptr(unsafe.Pointer(&desc)), + 0, + ) + if r != 0 { + return _DXGI_SWAP_CHAIN_DESC{}, ErrorCode{Name: "IDXGISwapChainGetDesc", Code: uint32(r)} + } + return desc, nil +} + func (s *_IDXGISwapChain) ResizeBuffers(buffers, width, height, newFormat, flags uint32) error { r, _, _ := syscall.Syscall6( s.vtbl.ResizeBuffers, diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go index dbcd9d58..e7fe7c3c 100644 --- a/gpu/gl/backend.go +++ b/gpu/gl/backend.go @@ -194,6 +194,7 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr depthBuf := b.funcs.CreateRenderbuffer() b.funcs.BindRenderbuffer(RENDERBUFFER, depthBuf) b.funcs.RenderbufferStorage(RENDERBUFFER, size, gltex.width, gltex.height) + b.funcs.FramebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, depthBuf) fbo.depthBuf = depthBuf fbo.hasDepth = true if err := glErr(b.funcs); err != nil { diff --git a/gpu/gl/gl.go b/gpu/gl/gl.go index 1508a1cd..1106bf73 100644 --- a/gpu/gl/gl.go +++ b/gpu/gl/gl.go @@ -129,6 +129,7 @@ type Functions interface { EnableVertexAttribArray(a Attrib) EndQuery(target Enum) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) + FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) GetBinding(pname Enum) Object GetError() Enum GetInteger(pname Enum) int