github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/app/internal/wm/d3d11_windows.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package wm 4 5 import ( 6 "fmt" 7 "unsafe" 8 9 "github.com/cybriq/giocore/gpu" 10 "github.com/cybriq/giocore/internal/d3d11" 11 ) 12 13 type d3d11Context struct { 14 win *window 15 dev *d3d11.Device 16 ctx *d3d11.DeviceContext 17 18 swchain *d3d11.IDXGISwapChain 19 renderTarget *d3d11.RenderTargetView 20 depthView *d3d11.DepthStencilView 21 width, height int 22 } 23 24 const debug = false 25 26 func init() { 27 drivers = append(drivers, gpuAPI{ 28 priority: 1, 29 initializer: func(w *window) (Context, error) { 30 hwnd, _, _ := w.HWND() 31 var flags uint32 32 if debug { 33 flags |= d3d11.CREATE_DEVICE_DEBUG 34 } 35 dev, ctx, _, err := d3d11.CreateDevice( 36 d3d11.DRIVER_TYPE_HARDWARE, 37 flags, 38 ) 39 if err != nil { 40 return nil, fmt.Errorf("NewContext: %v", err) 41 } 42 swchain, err := d3d11.CreateSwapChain(dev, hwnd) 43 if err != nil { 44 d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release) 45 d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release) 46 return nil, err 47 } 48 return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil 49 }, 50 }) 51 } 52 53 func (c *d3d11Context) API() gpu.API { 54 return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)} 55 } 56 57 func (c *d3d11Context) Present() error { 58 err := c.swchain.Present(1, 0) 59 if err == nil { 60 return nil 61 } 62 if err, ok := err.(d3d11.ErrorCode); ok { 63 switch err.Code { 64 case d3d11.DXGI_STATUS_OCCLUDED: 65 // Ignore 66 return nil 67 case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED: 68 return ErrDeviceLost 69 } 70 } 71 return err 72 } 73 74 func (c *d3d11Context) Refresh() error { 75 return nil 76 } 77 78 func (c *d3d11Context) MakeCurrent() error { 79 var width, height int 80 c.win.w.Run(func() { 81 _, width, height = c.win.HWND() 82 }) 83 if c.renderTarget != nil && width == c.width && height == c.height { 84 c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView) 85 return nil 86 } 87 c.releaseFBO() 88 if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil { 89 return err 90 } 91 c.width = width 92 c.height = height 93 94 desc, err := c.swchain.GetDesc() 95 if err != nil { 96 return err 97 } 98 backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D) 99 if err != nil { 100 return err 101 } 102 texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer)) 103 renderTarget, err := c.dev.CreateRenderTargetView(texture) 104 d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release) 105 if err != nil { 106 return err 107 } 108 depthView, err := d3d11.CreateDepthView(c.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24) 109 if err != nil { 110 d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release) 111 return err 112 } 113 c.renderTarget = renderTarget 114 c.depthView = depthView 115 116 c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView) 117 return nil 118 } 119 120 func (c *d3d11Context) Lock() {} 121 122 func (c *d3d11Context) Unlock() {} 123 124 func (c *d3d11Context) Release() { 125 c.releaseFBO() 126 if c.swchain != nil { 127 d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release) 128 } 129 if c.ctx != nil { 130 d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release) 131 } 132 if c.dev != nil { 133 d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release) 134 } 135 *c = d3d11Context{} 136 } 137 138 func (c *d3d11Context) releaseFBO() { 139 if c.depthView != nil { 140 d3d11.IUnknownRelease(unsafe.Pointer(c.depthView), c.depthView.Vtbl.Release) 141 c.depthView = nil 142 } 143 if c.renderTarget != nil { 144 d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release) 145 c.renderTarget = nil 146 } 147 }