d3d11_windows.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  package wm
   4  
   5  import (
   6  	"fmt"
   7  	"unsafe"
   8  
   9  	"github.com/p9c/p9/pkg/gel/gio/gpu"
  10  	"github.com/p9c/p9/pkg/gel/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  	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) MakeCurrent() error {
  75  	_, width, height := c.win.HWND()
  76  	if c.renderTarget != nil && width == c.width && height == c.height {
  77  		c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
  78  		return nil
  79  	}
  80  	c.releaseFBO()
  81  	if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil {
  82  		return err
  83  	}
  84  	c.width = width
  85  	c.height = height
  86  
  87  	desc, err := c.swchain.GetDesc()
  88  	if err != nil {
  89  		return err
  90  	}
  91  	backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D)
  92  	if err != nil {
  93  		return err
  94  	}
  95  	texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer))
  96  	renderTarget, err := c.dev.CreateRenderTargetView(texture)
  97  	d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release)
  98  	if err != nil {
  99  		return err
 100  	}
 101  	depthView, err := d3d11.CreateDepthView(c.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24)
 102  	if err != nil {
 103  		d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
 104  		return err
 105  	}
 106  	c.renderTarget = renderTarget
 107  	c.depthView = depthView
 108  
 109  	c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
 110  	return nil
 111  }
 112  
 113  func (c *d3d11Context) Lock() {}
 114  
 115  func (c *d3d11Context) Unlock() {}
 116  
 117  func (c *d3d11Context) Release() {
 118  	c.releaseFBO()
 119  	if c.swchain != nil {
 120  		d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release)
 121  	}
 122  	if c.ctx != nil {
 123  		d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release)
 124  	}
 125  	if c.dev != nil {
 126  		d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release)
 127  	}
 128  	*c = d3d11Context{}
 129  }
 130  
 131  func (c *d3d11Context) releaseFBO() {
 132  	if c.depthView != nil {
 133  		d3d11.IUnknownRelease(unsafe.Pointer(c.depthView), c.depthView.Vtbl.Release)
 134  		c.depthView = nil
 135  	}
 136  	if c.renderTarget != nil {
 137  		d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release)
 138  		c.renderTarget = nil
 139  	}
 140  }
 141