internal/d3d11: extract Direct3D API to separate package

We're about the merge the Direct3D backend into package gpu. Extract the
raw Direct3D API to its own package, just like package glimpl.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-03-05 13:26:19 +01:00
parent 8ff6546285
commit e17dd5bd30
6 changed files with 574 additions and 603 deletions
+11 -4
View File
@@ -6,7 +6,9 @@ import (
"unsafe" "unsafe"
"gioui.org/gpu" "gioui.org/gpu"
"gioui.org/app/internal/d3d11" "gioui.org/internal/d3d11"
_ "gioui.org/app/internal/d3d11"
) )
type d3d11Context struct { type d3d11Context struct {
@@ -14,15 +16,20 @@ type d3d11Context struct {
} }
func newContext() (context, error) { func newContext() (context, error) {
dev, err := d3d11.NewDevice() dev, ctx, _, err := d3d11.CreateDevice(
d3d11.DRIVER_TYPE_HARDWARE,
0,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Don't need it.
d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
return &d3d11Context{dev: dev}, nil return &d3d11Context{dev: dev}, nil
} }
func (c *d3d11Context) API() gpu.API { func (c *d3d11Context) API() gpu.API {
return gpu.Direct3D11{Device: unsafe.Pointer(c.dev.Handle)} return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)}
} }
func (c *d3d11Context) MakeCurrent() error { func (c *d3d11Context) MakeCurrent() error {
@@ -33,6 +40,6 @@ func (c *d3d11Context) ReleaseCurrent() {
} }
func (c *d3d11Context) Release() { func (c *d3d11Context) Release() {
c.dev.Release() d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release)
c.dev = nil c.dev = nil
} }
+5
View File
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: Unlicense OR MIT
// This file exists so this package builds on non-Windows platforms.
package d3d11
+132 -279
View File
@@ -12,23 +12,17 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"gioui.org/gpu/backend" "gioui.org/gpu/backend"
"gioui.org/internal/d3d11"
gunsafe "gioui.org/internal/unsafe" gunsafe "gioui.org/internal/unsafe"
) )
const debug = false
type Device struct {
Handle *_ID3D11Device
ctx *_ID3D11DeviceContext
}
type Backend struct { type Backend struct {
dev *_ID3D11Device dev *d3d11.Device
ctx *_ID3D11DeviceContext ctx *d3d11.DeviceContext
// Temporary storage to avoid garbage. // Temporary storage to avoid garbage.
clearColor [4]float32 clearColor [4]float32
viewport _D3D11_VIEWPORT viewport d3d11.VIEWPORT
depthState depthState depthState depthState
blendState blendState blendState blendState
@@ -43,8 +37,8 @@ type Backend struct {
floatFormat uint32 floatFormat uint32
// cached state objects. // cached state objects.
depthStates map[depthState]*_ID3D11DepthStencilState depthStates map[depthState]*d3d11.DepthStencilState
blendStates map[blendState]*_ID3D11BlendState blendStates map[blendState]*d3d11.BlendState
} }
type blendState struct { type blendState struct {
@@ -63,9 +57,9 @@ type Texture struct {
backend *Backend backend *Backend
format uint32 format uint32
bindings backend.BufferBinding bindings backend.BufferBinding
tex *_ID3D11Texture2D tex *d3d11.Texture2D
sampler *_ID3D11SamplerState sampler *d3d11.SamplerState
resView *_ID3D11ShaderResourceView resView *d3d11.ShaderResourceView
width int width int
height int height int
} }
@@ -74,73 +68,52 @@ type Program struct {
backend *Backend backend *Backend
vert struct { vert struct {
shader *_ID3D11VertexShader shader *d3d11.VertexShader
uniforms *Buffer uniforms *Buffer
} }
frag struct { frag struct {
shader *_ID3D11PixelShader shader *d3d11.PixelShader
uniforms *Buffer uniforms *Buffer
} }
} }
type Framebuffer struct { type Framebuffer struct {
dev *_ID3D11Device dev *d3d11.Device
ctx *_ID3D11DeviceContext ctx *d3d11.DeviceContext
format uint32 format uint32
resource *_ID3D11Resource resource *d3d11.Resource
renderTarget *_ID3D11RenderTargetView renderTarget *d3d11.RenderTargetView
depthView *_ID3D11DepthStencilView depthView *d3d11.DepthStencilView
foreign bool foreign bool
} }
type Buffer struct { type Buffer struct {
backend *Backend backend *Backend
bind uint32 bind uint32
buf *_ID3D11Buffer buf *d3d11.Buffer
immutable bool immutable bool
} }
type InputLayout struct { type InputLayout struct {
layout *_ID3D11InputLayout layout *d3d11.InputLayout
}
type SwapChain struct {
swchain *_IDXGISwapChain
fbo *Framebuffer
} }
func init() { func init() {
backend.NewDirect3D11Device = newDirect3D11Device backend.NewDirect3D11Device = newDirect3D11Device
} }
func NewDevice() (*Device, error) { func detectFloatFormat(dev *d3d11.Device) (uint32, bool) {
var flags uint32
if debug {
flags |= _D3D11_CREATE_DEVICE_DEBUG
}
d3ddev, d3dctx, _, err := _D3D11CreateDevice(
_D3D_DRIVER_TYPE_HARDWARE,
flags,
)
if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
dev := &Device{Handle: d3ddev, ctx: d3dctx}
return dev, nil
}
func detectFloatFormat(dev *_ID3D11Device) (uint32, bool) {
formats := []uint32{ formats := []uint32{
_DXGI_FORMAT_R16_FLOAT, d3d11.DXGI_FORMAT_R16_FLOAT,
_DXGI_FORMAT_R32_FLOAT, d3d11.DXGI_FORMAT_R32_FLOAT,
_DXGI_FORMAT_R16G16_FLOAT, d3d11.DXGI_FORMAT_R16G16_FLOAT,
_DXGI_FORMAT_R32G32_FLOAT, d3d11.DXGI_FORMAT_R32G32_FLOAT,
// These last two are really wasteful, but c'est la vie. // These last two are really wasteful, but c'est la vie.
_DXGI_FORMAT_R16G16B16A16_FLOAT, d3d11.DXGI_FORMAT_R16G16B16A16_FLOAT,
_DXGI_FORMAT_R32G32B32A32_FLOAT, d3d11.DXGI_FORMAT_R32G32B32A32_FLOAT,
} }
for _, format := range formats { for _, format := range formats {
need := uint32(_D3D11_FORMAT_SUPPORT_TEXTURE2D | _D3D11_FORMAT_SUPPORT_RENDER_TARGET) need := uint32(d3d11.FORMAT_SUPPORT_TEXTURE2D | d3d11.FORMAT_SUPPORT_RENDER_TARGET)
if support, _ := dev.CheckFormatSupport(format); support&need == need { if support, _ := dev.CheckFormatSupport(format); support&need == need {
return format, true return format, true
} }
@@ -148,120 +121,27 @@ func detectFloatFormat(dev *_ID3D11Device) (uint32, bool) {
return 0, false return 0, false
} }
func (d *Device) CreateSwapChain(hwnd windows.Handle) (*SwapChain, error) {
dxgiDev, err := _IUnknownQueryInterface(unsafe.Pointer(d.Handle), d.Handle.vtbl.QueryInterface, &_IID_IDXGIDevice)
if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
adapter, err := (*_IDXGIDevice)(unsafe.Pointer(dxgiDev)).GetAdapter()
_IUnknownRelease(unsafe.Pointer(dxgiDev), dxgiDev.vtbl.Release)
if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
dxgiFactory, err := (*_IDXGIObject)(unsafe.Pointer(adapter)).GetParent(&_IID_IDXGIFactory)
_IUnknownRelease(unsafe.Pointer(adapter), adapter.vtbl.Release)
if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
d3dswchain, err := (*_IDXGIFactory)(unsafe.Pointer(dxgiFactory)).CreateSwapChain(
(*_IUnknown)(unsafe.Pointer(d.Handle)),
&_DXGI_SWAP_CHAIN_DESC{
BufferDesc: _DXGI_MODE_DESC{
Format: _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
},
SampleDesc: _DXGI_SAMPLE_DESC{
Count: 1,
},
BufferUsage: _DXGI_USAGE_RENDER_TARGET_OUTPUT,
BufferCount: 1,
OutputWindow: hwnd,
Windowed: 1,
SwapEffect: _DXGI_SWAP_EFFECT_DISCARD,
},
)
_IUnknownRelease(unsafe.Pointer(dxgiFactory), dxgiFactory.vtbl.Release)
if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
return &SwapChain{swchain: d3dswchain, fbo: &Framebuffer{}}, nil
}
func (d *Device) BindFramebuffer(fbo *Framebuffer) {
d.ctx.OMSetRenderTargets(fbo.renderTarget, fbo.depthView)
}
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
}
texture := (*_ID3D11Resource)(unsafe.Pointer(backBuffer))
renderTarget, err := d.Handle.CreateRenderTargetView(texture)
_IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.vtbl.Release)
if err != nil {
return nil, err
}
depthView, err := createDepthView(d.Handle, 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.Handle
s.fbo.ctx = d.ctx
return s.fbo, nil
}
func (d *Device) Release() {
_IUnknownRelease(unsafe.Pointer(d.ctx), d.ctx.vtbl.Release)
_IUnknownRelease(unsafe.Pointer(d.Handle), d.Handle.vtbl.Release)
*d = Device{}
}
func (s *SwapChain) Resize() error {
if s.fbo.renderTarget != nil {
s.fbo.Release()
}
return s.swchain.ResizeBuffers(0, 0, 0, _DXGI_FORMAT_UNKNOWN, 0)
}
func (s *SwapChain) Release() {
_IUnknownRelease(unsafe.Pointer(s.swchain), s.swchain.vtbl.Release)
}
func (s *SwapChain) Present() error {
return s.swchain.Present(1, 0)
}
func newDirect3D11Device(api backend.Direct3D11) (backend.Device, error) { func newDirect3D11Device(api backend.Direct3D11) (backend.Device, error) {
dev := (*_ID3D11Device)(api.Device) dev := (*d3d11.Device)(api.Device)
b := &Backend{ b := &Backend{
dev: dev, dev: dev,
ctx: dev.GetImmediateContext(), ctx: dev.GetImmediateContext(),
caps: backend.Caps{ caps: backend.Caps{
MaxTextureSize: 2048, // 9.1 maximum MaxTextureSize: 2048, // 9.1 maximum
}, },
depthStates: make(map[depthState]*_ID3D11DepthStencilState), depthStates: make(map[depthState]*d3d11.DepthStencilState),
blendStates: make(map[blendState]*_ID3D11BlendState), blendStates: make(map[blendState]*d3d11.BlendState),
} }
featLvl := dev.GetFeatureLevel() featLvl := dev.GetFeatureLevel()
if featLvl < _D3D_FEATURE_LEVEL_9_1 { if featLvl < d3d11.FEATURE_LEVEL_9_1 {
_IUnknownRelease(unsafe.Pointer(dev), dev.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release)
_IUnknownRelease(unsafe.Pointer(b.ctx), b.ctx.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(b.ctx), b.ctx.Vtbl.Release)
return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl) return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl)
} }
switch { switch {
case featLvl >= _D3D_FEATURE_LEVEL_11_0: case featLvl >= d3d11.FEATURE_LEVEL_11_0:
b.caps.MaxTextureSize = 16384 b.caps.MaxTextureSize = 16384
case featLvl >= _D3D_FEATURE_LEVEL_9_3: case featLvl >= d3d11.FEATURE_LEVEL_9_3:
b.caps.MaxTextureSize = 4096 b.caps.MaxTextureSize = 4096
} }
if fmt, ok := detectFloatFormat(dev); ok { if fmt, ok := detectFloatFormat(dev); ok {
@@ -271,15 +151,15 @@ func newDirect3D11Device(api backend.Direct3D11) (backend.Device, error) {
// Enable depth mask to match OpenGL. // Enable depth mask to match OpenGL.
b.depthState.mask = true b.depthState.mask = true
// Disable backface culling to match OpenGL. // Disable backface culling to match OpenGL.
state, err := dev.CreateRasterizerState(&_D3D11_RASTERIZER_DESC{ state, err := dev.CreateRasterizerState(&d3d11.RASTERIZER_DESC{
CullMode: _D3D11_CULL_NONE, CullMode: d3d11.CULL_NONE,
FillMode: _D3D11_FILL_SOLID, FillMode: d3d11.FILL_SOLID,
DepthClipEnable: 1, DepthClipEnable: 1,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) defer d3d11.IUnknownRelease(unsafe.Pointer(state), state.Vtbl.Release)
b.ctx.RSSetState(state) b.ctx.RSSetState(state)
return b, nil return b, nil
} }
@@ -288,10 +168,10 @@ func (b *Backend) BeginFrame() backend.Framebuffer {
renderTarget, depthView := b.ctx.OMGetRenderTargets() renderTarget, depthView := b.ctx.OMGetRenderTargets()
// Assume someone else is holding on to the render targets. // Assume someone else is holding on to the render targets.
if renderTarget != nil { if renderTarget != nil {
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
} }
if depthView != nil { if depthView != nil {
_IUnknownRelease(unsafe.Pointer(depthView), depthView.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(depthView), depthView.Vtbl.Release)
} }
return &Framebuffer{ctx: b.ctx, dev: b.dev, renderTarget: renderTarget, depthView: depthView, foreign: true} return &Framebuffer{ctx: b.ctx, dev: b.dev, renderTarget: renderTarget, depthView: depthView, foreign: true}
} }
@@ -313,12 +193,12 @@ func (b *Backend) IsTimeContinuous() bool {
func (b *Backend) Release() { func (b *Backend) Release() {
for _, state := range b.depthStates { for _, state := range b.depthStates {
_IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(state), state.Vtbl.Release)
} }
for _, state := range b.blendStates { for _, state := range b.blendStates {
_IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(state), state.Vtbl.Release)
} }
_IUnknownRelease(unsafe.Pointer(b.ctx), b.ctx.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(b.ctx), b.ctx.Vtbl.Release)
*b = Backend{} *b = Backend{}
} }
@@ -328,17 +208,17 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
case backend.TextureFormatFloat: case backend.TextureFormatFloat:
d3dfmt = b.floatFormat d3dfmt = b.floatFormat
case backend.TextureFormatSRGB: case backend.TextureFormatSRGB:
d3dfmt = _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB d3dfmt = d3d11.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
default: default:
return nil, fmt.Errorf("unsupported texture format %d", format) return nil, fmt.Errorf("unsupported texture format %d", format)
} }
tex, err := b.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ tex, err := b.dev.CreateTexture2D(&d3d11.TEXTURE2D_DESC{
Width: uint32(width), Width: uint32(width),
Height: uint32(height), Height: uint32(height),
MipLevels: 1, MipLevels: 1,
ArraySize: 1, ArraySize: 1,
Format: d3dfmt, Format: d3dfmt,
SampleDesc: _DXGI_SAMPLE_DESC{ SampleDesc: d3d11.DXGI_SAMPLE_DESC{
Count: 1, Count: 1,
Quality: 0, Quality: 0,
}, },
@@ -348,50 +228,50 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
return nil, err return nil, err
} }
var ( var (
sampler *_ID3D11SamplerState sampler *d3d11.SamplerState
resView *_ID3D11ShaderResourceView resView *d3d11.ShaderResourceView
) )
if bindings&backend.BufferBindingTexture != 0 { if bindings&backend.BufferBindingTexture != 0 {
var filter uint32 var filter uint32
switch { switch {
case minFilter == backend.FilterNearest && magFilter == backend.FilterNearest: case minFilter == backend.FilterNearest && magFilter == backend.FilterNearest:
filter = _D3D11_FILTER_MIN_MAG_MIP_POINT filter = d3d11.FILTER_MIN_MAG_MIP_POINT
case minFilter == backend.FilterLinear && magFilter == backend.FilterLinear: case minFilter == backend.FilterLinear && magFilter == backend.FilterLinear:
filter = _D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT filter = d3d11.FILTER_MIN_MAG_LINEAR_MIP_POINT
default: default:
_IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(tex), tex.Vtbl.Release)
return nil, fmt.Errorf("unsupported texture filter combination %d, %d", minFilter, magFilter) return nil, fmt.Errorf("unsupported texture filter combination %d, %d", minFilter, magFilter)
} }
var err error var err error
sampler, err = b.dev.CreateSamplerState(&_D3D11_SAMPLER_DESC{ sampler, err = b.dev.CreateSamplerState(&d3d11.SAMPLER_DESC{
Filter: filter, Filter: filter,
AddressU: _D3D11_TEXTURE_ADDRESS_CLAMP, AddressU: d3d11.TEXTURE_ADDRESS_CLAMP,
AddressV: _D3D11_TEXTURE_ADDRESS_CLAMP, AddressV: d3d11.TEXTURE_ADDRESS_CLAMP,
AddressW: _D3D11_TEXTURE_ADDRESS_CLAMP, AddressW: d3d11.TEXTURE_ADDRESS_CLAMP,
MaxAnisotropy: 1, MaxAnisotropy: 1,
MinLOD: -math.MaxFloat32, MinLOD: -math.MaxFloat32,
MaxLOD: math.MaxFloat32, MaxLOD: math.MaxFloat32,
}) })
if err != nil { if err != nil {
_IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(tex), tex.Vtbl.Release)
return nil, err return nil, err
} }
resView, err = b.dev.CreateShaderResourceViewTEX2D( resView, err = b.dev.CreateShaderResourceViewTEX2D(
(*_ID3D11Resource)(unsafe.Pointer(tex)), (*d3d11.Resource)(unsafe.Pointer(tex)),
&_D3D11_SHADER_RESOURCE_VIEW_DESC_TEX2D{ &d3d11.SHADER_RESOURCE_VIEW_DESC_TEX2D{
_D3D11_SHADER_RESOURCE_VIEW_DESC: _D3D11_SHADER_RESOURCE_VIEW_DESC{ SHADER_RESOURCE_VIEW_DESC: d3d11.SHADER_RESOURCE_VIEW_DESC{
Format: d3dfmt, Format: d3dfmt,
ViewDimension: _D3D11_SRV_DIMENSION_TEXTURE2D, ViewDimension: d3d11.SRV_DIMENSION_TEXTURE2D,
}, },
Texture2D: _D3D11_TEX2D_SRV{ Texture2D: d3d11.TEX2D_SRV{
MostDetailedMip: 0, MostDetailedMip: 0,
MipLevels: ^uint32(0), MipLevels: ^uint32(0),
}, },
}, },
) )
if err != nil { if err != nil {
_IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(tex), tex.Vtbl.Release)
_IUnknownRelease(unsafe.Pointer(sampler), sampler.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(sampler), sampler.Vtbl.Release)
return nil, err return nil, err
} }
} }
@@ -403,16 +283,16 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr
if d3dtex.bindings&backend.BufferBindingFramebuffer == 0 { if d3dtex.bindings&backend.BufferBindingFramebuffer == 0 {
return nil, errors.New("the texture was created without BufferBindingFramebuffer binding") return nil, errors.New("the texture was created without BufferBindingFramebuffer binding")
} }
resource := (*_ID3D11Resource)(unsafe.Pointer(d3dtex.tex)) resource := (*d3d11.Resource)(unsafe.Pointer(d3dtex.tex))
renderTarget, err := b.dev.CreateRenderTargetView(resource) renderTarget, err := b.dev.CreateRenderTargetView(resource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fbo := &Framebuffer{ctx: b.ctx, dev: b.dev, format: d3dtex.format, resource: resource, renderTarget: renderTarget} fbo := &Framebuffer{ctx: b.ctx, dev: b.dev, format: d3dtex.format, resource: resource, renderTarget: renderTarget}
if depthBits > 0 { if depthBits > 0 {
depthView, err := createDepthView(b.dev, d3dtex.width, d3dtex.height, depthBits) depthView, err := d3d11.CreateDepthView(b.dev, d3dtex.width, d3dtex.height, depthBits)
if err != nil { if err != nil {
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
return nil, err return nil, err
} }
fbo.depthView = depthView fbo.depthView = depthView
@@ -420,38 +300,11 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr
return fbo, nil 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) { func (b *Backend) NewInputLayout(vertexShader backend.ShaderSources, layout []backend.InputDesc) (backend.InputLayout, error) {
if len(vertexShader.Inputs) != len(layout) { if len(vertexShader.Inputs) != len(layout) {
return nil, fmt.Errorf("NewInputLayout: got %d inputs, expected %d", len(layout), len(vertexShader.Inputs)) return nil, fmt.Errorf("NewInputLayout: got %d inputs, expected %d", len(layout), len(vertexShader.Inputs))
} }
descs := make([]_D3D11_INPUT_ELEMENT_DESC, len(layout)) descs := make([]d3d11.INPUT_ELEMENT_DESC, len(layout))
for i, l := range layout { for i, l := range layout {
inp := vertexShader.Inputs[i] inp := vertexShader.Inputs[i]
cname, err := windows.BytePtrFromString(inp.Semantic) cname, err := windows.BytePtrFromString(inp.Semantic)
@@ -463,29 +316,29 @@ func (b *Backend) NewInputLayout(vertexShader backend.ShaderSources, layout []ba
case backend.DataTypeFloat: case backend.DataTypeFloat:
switch l.Size { switch l.Size {
case 1: case 1:
format = _DXGI_FORMAT_R32_FLOAT format = d3d11.DXGI_FORMAT_R32_FLOAT
case 2: case 2:
format = _DXGI_FORMAT_R32G32_FLOAT format = d3d11.DXGI_FORMAT_R32G32_FLOAT
case 3: case 3:
format = _DXGI_FORMAT_R32G32B32_FLOAT format = d3d11.DXGI_FORMAT_R32G32B32_FLOAT
case 4: case 4:
format = _DXGI_FORMAT_R32G32B32A32_FLOAT format = d3d11.DXGI_FORMAT_R32G32B32A32_FLOAT
default: default:
panic("unsupported float data size") panic("unsupported float data size")
} }
case backend.DataTypeShort: case backend.DataTypeShort:
switch l.Size { switch l.Size {
case 1: case 1:
format = _DXGI_FORMAT_R16_SINT format = d3d11.DXGI_FORMAT_R16_SINT
case 2: case 2:
format = _DXGI_FORMAT_R16G16_SINT format = d3d11.DXGI_FORMAT_R16G16_SINT
default: default:
panic("unsupported float data size") panic("unsupported float data size")
} }
default: default:
panic("unsupported data type") panic("unsupported data type")
} }
descs[i] = _D3D11_INPUT_ELEMENT_DESC{ descs[i] = d3d11.INPUT_ELEMENT_DESC{
SemanticName: cname, SemanticName: cname,
SemanticIndex: uint32(inp.SemanticIndex), SemanticIndex: uint32(inp.SemanticIndex),
Format: format, Format: format,
@@ -509,7 +362,7 @@ func (b *Backend) NewBuffer(typ backend.BufferBinding, size int) (backend.Buffer
} }
} }
bind := convBufferBinding(typ) bind := convBufferBinding(typ)
buf, err := b.dev.CreateBuffer(&_D3D11_BUFFER_DESC{ buf, err := b.dev.CreateBuffer(&d3d11.BUFFER_DESC{
ByteWidth: uint32(size), ByteWidth: uint32(size),
BindFlags: bind, BindFlags: bind,
}, nil) }, nil)
@@ -529,9 +382,9 @@ func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (ba
} }
} }
bind := convBufferBinding(typ) bind := convBufferBinding(typ)
buf, err := b.dev.CreateBuffer(&_D3D11_BUFFER_DESC{ buf, err := b.dev.CreateBuffer(&d3d11.BUFFER_DESC{
ByteWidth: uint32(len(data)), ByteWidth: uint32(len(data)),
Usage: _D3D11_USAGE_IMMUTABLE, Usage: d3d11.USAGE_IMMUTABLE,
BindFlags: bind, BindFlags: bind,
}, data) }, data)
if err != nil { if err != nil {
@@ -566,12 +419,12 @@ func (b *Backend) Clear(colr, colg, colb, cola float32) {
func (b *Backend) ClearDepth(depth float32) { func (b *Backend) ClearDepth(depth float32) {
if b.fbo.depthView != nil { if b.fbo.depthView != nil {
b.ctx.ClearDepthStencilView(b.fbo.depthView, _D3D11_CLEAR_DEPTH|_D3D11_CLEAR_STENCIL, depth, 0) b.ctx.ClearDepthStencilView(b.fbo.depthView, d3d11.CLEAR_DEPTH|d3d11.CLEAR_STENCIL, depth, 0)
} }
} }
func (b *Backend) Viewport(x, y, width, height int) { func (b *Backend) Viewport(x, y, width, height int) {
b.viewport = _D3D11_VIEWPORT{ b.viewport = d3d11.VIEWPORT{
TopLeftX: float32(x), TopLeftX: float32(x),
TopLeftY: float32(y), TopLeftY: float32(y),
Width: float32(width), Width: float32(width),
@@ -606,9 +459,9 @@ func (b *Backend) prepareDraw(mode backend.DrawMode) {
var topology uint32 var topology uint32
switch mode { switch mode {
case backend.DrawModeTriangles: case backend.DrawModeTriangles:
topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLELIST
case backend.DrawModeTriangleStrip: case backend.DrawModeTriangleStrip:
topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP topology = d3d11.PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
default: default:
panic("unsupported draw mode") panic("unsupported draw mode")
} }
@@ -616,18 +469,18 @@ func (b *Backend) prepareDraw(mode backend.DrawMode) {
depthState, ok := b.depthStates[b.depthState] depthState, ok := b.depthStates[b.depthState]
if !ok { if !ok {
var desc _D3D11_DEPTH_STENCIL_DESC var desc d3d11.DEPTH_STENCIL_DESC
if b.depthState.enable { if b.depthState.enable {
desc.DepthEnable = 1 desc.DepthEnable = 1
} }
if b.depthState.mask { if b.depthState.mask {
desc.DepthWriteMask = _D3D11_DEPTH_WRITE_MASK_ALL desc.DepthWriteMask = d3d11.DEPTH_WRITE_MASK_ALL
} }
switch b.depthState.fn { switch b.depthState.fn {
case backend.DepthFuncGreater: case backend.DepthFuncGreater:
desc.DepthFunc = _D3D11_COMPARISON_GREATER desc.DepthFunc = d3d11.COMPARISON_GREATER
case backend.DepthFuncGreaterEqual: case backend.DepthFuncGreaterEqual:
desc.DepthFunc = _D3D11_COMPARISON_GREATER_EQUAL desc.DepthFunc = d3d11.COMPARISON_GREATER_EQUAL
default: default:
panic("unsupported depth func") panic("unsupported depth func")
} }
@@ -642,11 +495,11 @@ func (b *Backend) prepareDraw(mode backend.DrawMode) {
blendState, ok := b.blendStates[b.blendState] blendState, ok := b.blendStates[b.blendState]
if !ok { if !ok {
var desc _D3D11_BLEND_DESC var desc d3d11.BLEND_DESC
t0 := &desc.RenderTarget[0] t0 := &desc.RenderTarget[0]
t0.RenderTargetWriteMask = _D3D11_COLOR_WRITE_ENABLE_ALL t0.RenderTargetWriteMask = d3d11.COLOR_WRITE_ENABLE_ALL
t0.BlendOp = _D3D11_BLEND_OP_ADD t0.BlendOp = d3d11.BLEND_OP_ADD
t0.BlendOpAlpha = _D3D11_BLEND_OP_ADD t0.BlendOpAlpha = d3d11.BLEND_OP_ADD
if b.blendState.enable { if b.blendState.enable {
t0.BlendEnable = 1 t0.BlendEnable = 1
} }
@@ -701,27 +554,27 @@ func (b *Backend) DispatchCompute(x, y, z int) {
func (t *Texture) Upload(offset, size image.Point, pixels []byte) { func (t *Texture) Upload(offset, size image.Point, pixels []byte) {
stride := size.X * 4 stride := size.X * 4
dst := &_D3D11_BOX{ dst := &d3d11.BOX{
left: uint32(offset.X), Left: uint32(offset.X),
top: uint32(offset.Y), Top: uint32(offset.Y),
right: uint32(offset.X + size.X), Right: uint32(offset.X + size.X),
bottom: uint32(offset.Y + size.Y), Bottom: uint32(offset.Y + size.Y),
front: 0, Front: 0,
back: 1, Back: 1,
} }
res := (*_ID3D11Resource)(unsafe.Pointer(t.tex)) res := (*d3d11.Resource)(unsafe.Pointer(t.tex))
t.backend.ctx.UpdateSubresource(res, dst, uint32(stride), uint32(len(pixels)), pixels) t.backend.ctx.UpdateSubresource(res, dst, uint32(stride), uint32(len(pixels)), pixels)
} }
func (t *Texture) Release() { func (t *Texture) Release() {
_IUnknownRelease(unsafe.Pointer(t.tex), t.tex.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(t.tex), t.tex.Vtbl.Release)
t.tex = nil t.tex = nil
if t.sampler != nil { if t.sampler != nil {
_IUnknownRelease(unsafe.Pointer(t.sampler), t.sampler.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(t.sampler), t.sampler.Vtbl.Release)
t.sampler = nil t.sampler = nil
} }
if t.resView != nil { if t.resView != nil {
_IUnknownRelease(unsafe.Pointer(t.resView), t.resView.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(t.resView), t.resView.Vtbl.Release)
t.resView = nil t.resView = nil
} }
} }
@@ -737,8 +590,8 @@ func (b *Backend) BindProgram(prog backend.Program) {
} }
func (p *Program) Release() { func (p *Program) Release() {
_IUnknownRelease(unsafe.Pointer(p.vert.shader), p.vert.shader.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(p.vert.shader), p.vert.shader.Vtbl.Release)
_IUnknownRelease(unsafe.Pointer(p.frag.shader), p.frag.shader.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(p.frag.shader), p.frag.shader.Vtbl.Release)
p.vert.shader = nil p.vert.shader = nil
p.frag.shader = nil p.frag.shader = nil
} }
@@ -760,7 +613,7 @@ func (b *Backend) BindVertexBuffer(buf backend.Buffer, stride, offset int) {
} }
func (b *Backend) BindIndexBuffer(buf backend.Buffer) { func (b *Backend) BindIndexBuffer(buf backend.Buffer) {
b.ctx.IASetIndexBuffer(buf.(*Buffer).buf, _DXGI_FORMAT_R16_UINT, 0) b.ctx.IASetIndexBuffer(buf.(*Buffer).buf, d3d11.DXGI_FORMAT_R16_UINT, 0)
} }
func (b *Buffer) Download(data []byte) error { func (b *Buffer) Download(data []byte) error {
@@ -768,11 +621,11 @@ func (b *Buffer) Download(data []byte) error {
} }
func (b *Buffer) Upload(data []byte) { func (b *Buffer) Upload(data []byte) {
b.backend.ctx.UpdateSubresource((*_ID3D11Resource)(unsafe.Pointer(b.buf)), nil, 0, 0, data) b.backend.ctx.UpdateSubresource((*d3d11.Resource)(unsafe.Pointer(b.buf)), nil, 0, 0, data)
} }
func (b *Buffer) Release() { func (b *Buffer) Release() {
_IUnknownRelease(unsafe.Pointer(b.buf), b.buf.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(b.buf), b.buf.Vtbl.Release)
b.buf = nil b.buf = nil
} }
@@ -781,40 +634,40 @@ func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte) error {
return errors.New("framebuffer does not support ReadPixels") return errors.New("framebuffer does not support ReadPixels")
} }
w, h := src.Dx(), src.Dy() w, h := src.Dx(), src.Dy()
tex, err := f.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ tex, err := f.dev.CreateTexture2D(&d3d11.TEXTURE2D_DESC{
Width: uint32(w), Width: uint32(w),
Height: uint32(h), Height: uint32(h),
MipLevels: 1, MipLevels: 1,
ArraySize: 1, ArraySize: 1,
Format: f.format, Format: f.format,
SampleDesc: _DXGI_SAMPLE_DESC{ SampleDesc: d3d11.DXGI_SAMPLE_DESC{
Count: 1, Count: 1,
Quality: 0, Quality: 0,
}, },
Usage: _D3D11_USAGE_STAGING, Usage: d3d11.USAGE_STAGING,
CPUAccessFlags: _D3D11_CPU_ACCESS_READ, CPUAccessFlags: d3d11.CPU_ACCESS_READ,
}) })
if err != nil { if err != nil {
return fmt.Errorf("ReadPixels: %v", err) return fmt.Errorf("ReadPixels: %v", err)
} }
defer _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) defer d3d11.IUnknownRelease(unsafe.Pointer(tex), tex.Vtbl.Release)
res := (*_ID3D11Resource)(unsafe.Pointer(tex)) res := (*d3d11.Resource)(unsafe.Pointer(tex))
f.ctx.CopySubresourceRegion( f.ctx.CopySubresourceRegion(
res, res,
0, // Destination subresource. 0, // Destination subresource.
0, 0, 0, // Destination coordinates (x, y, z). 0, 0, 0, // Destination coordinates (x, y, z).
f.resource, f.resource,
0, // Source subresource. 0, // Source subresource.
&_D3D11_BOX{ &d3d11.BOX{
left: uint32(src.Min.X), Left: uint32(src.Min.X),
top: uint32(src.Min.Y), Top: uint32(src.Min.Y),
right: uint32(src.Max.X), Right: uint32(src.Max.X),
bottom: uint32(src.Max.Y), Bottom: uint32(src.Max.Y),
front: 0, Front: 0,
back: 1, Back: 1,
}, },
) )
resMap, err := f.ctx.Map(res, 0, _D3D11_MAP_READ, 0) resMap, err := f.ctx.Map(res, 0, d3d11.MAP_READ, 0)
if err != nil { if err != nil {
return fmt.Errorf("ReadPixels: %v", err) return fmt.Errorf("ReadPixels: %v", err)
} }
@@ -822,7 +675,7 @@ func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte) error {
srcPitch := w * 4 srcPitch := w * 4
dstPitch := int(resMap.RowPitch) dstPitch := int(resMap.RowPitch)
mapSize := dstPitch * h mapSize := dstPitch * h
data := gunsafe.SliceOf(resMap.pData)[:mapSize:mapSize] data := gunsafe.SliceOf(resMap.PData)[:mapSize:mapSize]
width := w * 4 width := w * 4
for r := 0; r < h; r++ { for r := 0; r < h; r++ {
pixels := pixels[r*srcPitch:] pixels := pixels[r*srcPitch:]
@@ -844,11 +697,11 @@ func (f *Framebuffer) Release() {
panic("framebuffer not created by NewFramebuffer") panic("framebuffer not created by NewFramebuffer")
} }
if f.renderTarget != nil { if f.renderTarget != nil {
_IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.Vtbl.Release)
f.renderTarget = nil f.renderTarget = nil
} }
if f.depthView != nil { if f.depthView != nil {
_IUnknownRelease(unsafe.Pointer(f.depthView), f.depthView.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(f.depthView), f.depthView.Vtbl.Release)
f.depthView = nil f.depthView = nil
} }
} }
@@ -858,26 +711,26 @@ func (b *Backend) BindInputLayout(layout backend.InputLayout) {
} }
func (l *InputLayout) Release() { func (l *InputLayout) Release() {
_IUnknownRelease(unsafe.Pointer(l.layout), l.layout.vtbl.Release) d3d11.IUnknownRelease(unsafe.Pointer(l.layout), l.layout.Vtbl.Release)
l.layout = nil l.layout = nil
} }
func convBufferBinding(typ backend.BufferBinding) uint32 { func convBufferBinding(typ backend.BufferBinding) uint32 {
var bindings uint32 var bindings uint32
if typ&backend.BufferBindingVertices != 0 { if typ&backend.BufferBindingVertices != 0 {
bindings |= _D3D11_BIND_VERTEX_BUFFER bindings |= d3d11.BIND_VERTEX_BUFFER
} }
if typ&backend.BufferBindingIndices != 0 { if typ&backend.BufferBindingIndices != 0 {
bindings |= _D3D11_BIND_INDEX_BUFFER bindings |= d3d11.BIND_INDEX_BUFFER
} }
if typ&backend.BufferBindingUniforms != 0 { if typ&backend.BufferBindingUniforms != 0 {
bindings |= _D3D11_BIND_CONSTANT_BUFFER bindings |= d3d11.BIND_CONSTANT_BUFFER
} }
if typ&backend.BufferBindingTexture != 0 { if typ&backend.BufferBindingTexture != 0 {
bindings |= _D3D11_BIND_SHADER_RESOURCE bindings |= d3d11.BIND_SHADER_RESOURCE
} }
if typ&backend.BufferBindingFramebuffer != 0 { if typ&backend.BufferBindingFramebuffer != 0 {
bindings |= _D3D11_BIND_RENDER_TARGET bindings |= d3d11.BIND_RENDER_TARGET
} }
return bindings return bindings
} }
@@ -885,13 +738,13 @@ func convBufferBinding(typ backend.BufferBinding) uint32 {
func toBlendFactor(f backend.BlendFactor) (uint32, uint32) { func toBlendFactor(f backend.BlendFactor) (uint32, uint32) {
switch f { switch f {
case backend.BlendFactorOne: case backend.BlendFactorOne:
return _D3D11_BLEND_ONE, _D3D11_BLEND_ONE return d3d11.BLEND_ONE, d3d11.BLEND_ONE
case backend.BlendFactorOneMinusSrcAlpha: case backend.BlendFactorOneMinusSrcAlpha:
return _D3D11_BLEND_INV_SRC_ALPHA, _D3D11_BLEND_INV_SRC_ALPHA return d3d11.BLEND_INV_SRC_ALPHA, d3d11.BLEND_INV_SRC_ALPHA
case backend.BlendFactorZero: case backend.BlendFactorZero:
return _D3D11_BLEND_ZERO, _D3D11_BLEND_ZERO return d3d11.BLEND_ZERO, d3d11.BLEND_ZERO
case backend.BlendFactorDstColor: case backend.BlendFactorDstColor:
return _D3D11_BLEND_DEST_COLOR, _D3D11_BLEND_DEST_ALPHA return d3d11.BLEND_DEST_COLOR, d3d11.BLEND_DEST_ALPHA
default: default:
panic("unsupported blend source factor") panic("unsupported blend source factor")
} }
+69 -30
View File
@@ -3,45 +3,59 @@
package window package window
import ( import (
"fmt"
"unsafe" "unsafe"
"gioui.org/gpu" "gioui.org/gpu"
"gioui.org/app/internal/d3d11" "gioui.org/internal/d3d11"
) )
type d3d11Context struct { type d3d11Context struct {
win *window win *window
swchain *d3d11.SwapChain
fbo *d3d11.Framebuffer
dev *d3d11.Device dev *d3d11.Device
ctx *d3d11.DeviceContext
swchain *d3d11.IDXGISwapChain
renderTarget *d3d11.RenderTargetView
depthView *d3d11.DepthStencilView
width, height int width, height int
} }
const debug = false
func init() { func init() {
backends = append(backends, gpuAPI{ backends = append(backends, gpuAPI{
priority: 1, priority: 1,
initializer: func(w *window) (Context, error) { initializer: func(w *window) (Context, error) {
hwnd, _, _ := w.HWND() hwnd, _, _ := w.HWND()
dev, err := d3d11.NewDevice() var flags uint32
if debug {
flags |= d3d11.CREATE_DEVICE_DEBUG
}
dev, ctx, _, err := d3d11.CreateDevice(
d3d11.DRIVER_TYPE_HARDWARE,
flags,
)
if err != nil { if err != nil {
return nil, fmt.Errorf("NewContext: %v", err)
}
swchain, err := d3d11.CreateSwapChain(dev, hwnd)
if err != nil {
d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release)
return nil, err return nil, err
} }
swchain, err := dev.CreateSwapChain(hwnd) return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil
if err != nil {
dev.Release()
return nil, err
}
return &d3d11Context{win: w, dev: dev, swchain: swchain}, nil
}, },
}) })
} }
func (c *d3d11Context) API() gpu.API { func (c *d3d11Context) API() gpu.API {
return gpu.Direct3D11{Device: unsafe.Pointer(c.dev.Handle)} return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)}
} }
func (c *d3d11Context) Present() error { func (c *d3d11Context) Present() error {
err := c.swchain.Present() err := c.swchain.Present(1, 0)
if err == nil { if err == nil {
return nil return nil
} }
@@ -59,25 +73,40 @@ func (c *d3d11Context) Present() error {
func (c *d3d11Context) MakeCurrent() error { func (c *d3d11Context) MakeCurrent() error {
_, width, height := c.win.HWND() _, width, height := c.win.HWND()
if c.fbo != nil && width == c.width && height == c.height { if c.renderTarget != nil && width == c.width && height == c.height {
c.dev.BindFramebuffer(c.fbo) c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
return nil return nil
} }
if c.fbo != nil { c.releaseFBO()
c.fbo.Release() if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil {
c.fbo = nil
}
if err := c.swchain.Resize(); err != nil {
return err return err
} }
c.width = width c.width = width
c.height = height c.height = height
fbo, err := c.swchain.Framebuffer(c.dev)
desc, err := c.swchain.GetDesc()
if err != nil { if err != nil {
return err return err
} }
c.fbo = fbo backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D)
c.dev.BindFramebuffer(c.fbo) if err != nil {
return err
}
texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer))
renderTarget, err := c.dev.CreateRenderTargetView(texture)
d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release)
if err != nil {
return err
}
depthView, err := d3d11.CreateDepthView(c.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24)
if err != nil {
d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
return err
}
c.renderTarget = renderTarget
c.depthView = depthView
c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
return nil return nil
} }
@@ -86,16 +115,26 @@ func (c *d3d11Context) Lock() {}
func (c *d3d11Context) Unlock() {} func (c *d3d11Context) Unlock() {}
func (c *d3d11Context) Release() { func (c *d3d11Context) Release() {
if c.fbo != nil { c.releaseFBO()
c.fbo.Release()
}
if c.swchain != nil { if c.swchain != nil {
c.swchain.Release() d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release)
}
if c.ctx != nil {
d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release)
} }
if c.dev != nil { if c.dev != nil {
c.dev.Release() d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release)
}
*c = d3d11Context{}
}
func (c *d3d11Context) releaseFBO() {
if c.depthView != nil {
d3d11.IUnknownRelease(unsafe.Pointer(c.depthView), c.depthView.Vtbl.Release)
c.depthView = nil
}
if c.renderTarget != nil {
d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release)
c.renderTarget = nil
} }
c.fbo = nil
c.swchain = nil
c.dev = nil
} }
+2
View File
@@ -10,6 +10,8 @@ import (
"gioui.org/app/internal/window" "gioui.org/app/internal/window"
"gioui.org/gpu" "gioui.org/gpu"
"gioui.org/op" "gioui.org/op"
_ "gioui.org/app/internal/d3d11"
) )
type renderLoop struct { type renderLoop struct {
File diff suppressed because it is too large Load Diff