github.com/utopiagio/gio@v0.0.8/app/d3d11_windows.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package app 4 5 import ( 6 "fmt" 7 "unsafe" 8 9 "github.com/utopiagio/gio/gpu" 10 "github.com/utopiagio/gio/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 width, height int 21 } 22 23 const debugDirectX = false 24 25 func init() { 26 drivers = append(drivers, gpuAPI{ 27 priority: 1, 28 initializer: func(w *window) (context, error) { 29 hwnd, _, _ := w.HWND() 30 var flags uint32 31 if debugDirectX { 32 flags |= d3d11.CREATE_DEVICE_DEBUG 33 } 34 dev, ctx, _, err := d3d11.CreateDevice( 35 d3d11.DRIVER_TYPE_HARDWARE, 36 flags, 37 ) 38 if err != nil { 39 return nil, fmt.Errorf("NewContext: %v", err) 40 } 41 swchain, err := d3d11.CreateSwapChain(dev, hwnd) 42 if err != nil { 43 d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release) 44 d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release) 45 return nil, err 46 } 47 return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil 48 }, 49 }) 50 } 51 52 func (c *d3d11Context) API() gpu.API { 53 return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)} 54 } 55 56 func (c *d3d11Context) RenderTarget() (gpu.RenderTarget, error) { 57 return gpu.Direct3D11RenderTarget{ 58 RenderTarget: unsafe.Pointer(c.renderTarget), 59 }, nil 60 } 61 62 func (c *d3d11Context) Present() error { 63 return wrapErr(c.swchain.Present(1, 0)) 64 } 65 66 func wrapErr(err error) error { 67 if err, ok := err.(d3d11.ErrorCode); ok { 68 switch err.Code { 69 case d3d11.DXGI_STATUS_OCCLUDED: 70 // Ignore 71 return nil 72 case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED: 73 return gpu.ErrDeviceLost 74 } 75 } 76 return err 77 } 78 79 func (c *d3d11Context) Refresh() error { 80 var width, height int 81 _, width, height = c.win.HWND() 82 if c.renderTarget != nil && width == c.width && height == c.height { 83 return nil 84 } 85 c.releaseFBO() 86 if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil { 87 return wrapErr(err) 88 } 89 c.width = width 90 c.height = height 91 92 backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D) 93 if err != nil { 94 return err 95 } 96 texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer)) 97 renderTarget, err := c.dev.CreateRenderTargetView(texture) 98 d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release) 99 if err != nil { 100 return err 101 } 102 c.renderTarget = renderTarget 103 return nil 104 } 105 106 func (c *d3d11Context) Lock() error { 107 c.ctx.OMSetRenderTargets(c.renderTarget, nil) 108 return nil 109 } 110 111 func (c *d3d11Context) Unlock() {} 112 113 func (c *d3d11Context) Release() { 114 c.releaseFBO() 115 if c.swchain != nil { 116 d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release) 117 } 118 if c.ctx != nil { 119 d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release) 120 } 121 if c.dev != nil { 122 d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release) 123 } 124 *c = d3d11Context{} 125 if debugDirectX { 126 d3d11.ReportLiveObjects() 127 } 128 } 129 130 func (c *d3d11Context) releaseFBO() { 131 if c.renderTarget != nil { 132 d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release) 133 c.renderTarget = nil 134 } 135 }