diff options
Diffstat (limited to 'vendor/gioui.org/app/internal/d3d11/backend_windows.go')
-rw-r--r-- | vendor/gioui.org/app/internal/d3d11/backend_windows.go | 856 |
1 files changed, 0 insertions, 856 deletions
diff --git a/vendor/gioui.org/app/internal/d3d11/backend_windows.go b/vendor/gioui.org/app/internal/d3d11/backend_windows.go deleted file mode 100644 index 48ff175..0000000 --- a/vendor/gioui.org/app/internal/d3d11/backend_windows.go +++ /dev/null @@ -1,856 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -package d3d11 - -import ( - "errors" - "fmt" - "image" - "math" - "unsafe" - - "gioui.org/gpu/backend" - gunsafe "gioui.org/internal/unsafe" - "golang.org/x/sys/windows" -) - -const debug = false - -type Device struct { - dev *_ID3D11Device - ctx *_ID3D11DeviceContext - featLvl uint32 - floatFormat uint32 - depthStates map[depthState]*_ID3D11DepthStencilState - blendStates map[blendState]*_ID3D11BlendState -} - -type Backend struct { - // Temporary storage to avoid garbage. - clearColor [4]float32 - viewport _D3D11_VIEWPORT - depthState depthState - blendState blendState - prog *Program - - dev *Device - caps backend.Caps - - // fbo is the currently bound fbo. - fbo *Framebuffer -} - -type blendState struct { - enable bool - sfactor backend.BlendFactor - dfactor backend.BlendFactor -} - -type depthState struct { - enable bool - mask bool - fn backend.DepthFunc -} - -type Texture struct { - backend *Backend - format uint32 - bindings backend.BufferBinding - tex *_ID3D11Texture2D - sampler *_ID3D11SamplerState - resView *_ID3D11ShaderResourceView - width int - height int -} - -type Program struct { - backend *Backend - - vert struct { - shader *_ID3D11VertexShader - uniforms *Buffer - } - frag struct { - shader *_ID3D11PixelShader - uniforms *Buffer - } -} - -type Framebuffer struct { - dev *Device - format uint32 - resource *_ID3D11Resource - renderTarget *_ID3D11RenderTargetView - depthView *_ID3D11DepthStencilView - foreign bool -} - -type Buffer struct { - backend *Backend - bind uint32 - buf *_ID3D11Buffer - immutable bool -} - -type InputLayout struct { - dev *Device - layout *_ID3D11InputLayout -} - -type SwapChain struct { - swchain *_IDXGISwapChain - fbo *Framebuffer -} - -func NewDevice() (*Device, error) { - var flags uint32 - if debug { - flags |= _D3D11_CREATE_DEVICE_DEBUG - } - d3ddev, d3dctx, featLvl, err := _D3D11CreateDevice( - _D3D_DRIVER_TYPE_HARDWARE, - flags, - ) - if err != nil { - return nil, fmt.Errorf("NewContext: %v", err) - } - dev := &Device{dev: d3ddev, ctx: d3dctx, featLvl: featLvl} - if featLvl < _D3D_FEATURE_LEVEL_9_1 { - _IUnknownRelease(unsafe.Pointer(d3ddev), d3ddev.vtbl.Release) - _IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release) - return nil, fmt.Errorf("d3d11: feature level too low: %d", featLvl) - } - floatFormat, ok := detectFloatFormat(d3ddev) - if !ok { - _IUnknownRelease(unsafe.Pointer(d3ddev), d3ddev.vtbl.Release) - _IUnknownRelease(unsafe.Pointer(d3dctx), d3dctx.vtbl.Release) - return nil, fmt.Errorf("d3d11: no available floating point formats") - } - dev.floatFormat = floatFormat - dev.depthStates = make(map[depthState]*_ID3D11DepthStencilState) - dev.blendStates = make(map[blendState]*_ID3D11BlendState) - return dev, nil -} - -func detectFloatFormat(dev *_ID3D11Device) (uint32, bool) { - formats := []uint32{ - _DXGI_FORMAT_R16_FLOAT, - _DXGI_FORMAT_R32_FLOAT, - _DXGI_FORMAT_R16G16_FLOAT, - _DXGI_FORMAT_R32G32_FLOAT, - // These last two are really wasteful, but c'est la vie. - _DXGI_FORMAT_R16G16B16A16_FLOAT, - _DXGI_FORMAT_R32G32B32A32_FLOAT, - } - for _, format := range formats { - need := uint32(_D3D11_FORMAT_SUPPORT_TEXTURE2D | _D3D11_FORMAT_SUPPORT_RENDER_TARGET) - if support, _ := dev.CheckFormatSupport(format); support&need == need { - return format, true - } - } - return 0, false -} - -func (d *Device) CreateSwapChain(hwnd windows.Handle) (*SwapChain, error) { - dxgiDev, err := _IUnknownQueryInterface(unsafe.Pointer(d.dev), d.dev.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.dev)), - &_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 (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.dev.CreateRenderTargetView(texture) - _IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.vtbl.Release) - 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 -} - -func (d *Device) Release() { - _IUnknownRelease(unsafe.Pointer(d.ctx), d.ctx.vtbl.Release) - _IUnknownRelease(unsafe.Pointer(d.dev), d.dev.vtbl.Release) - d.ctx = nil - d.dev = nil - for _, state := range d.depthStates { - _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) - } - d.depthStates = nil - for _, state := range d.blendStates { - _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) - } - d.blendStates = nil -} - -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 NewBackend(d *Device) (*Backend, error) { - caps := backend.Caps{ - MaxTextureSize: 2048, // 9.1 maximum - } - switch { - case d.featLvl >= _D3D_FEATURE_LEVEL_11_0: - caps.MaxTextureSize = 16384 - case d.featLvl >= _D3D_FEATURE_LEVEL_9_3: - caps.MaxTextureSize = 4096 - } - b := &Backend{dev: d, caps: caps} - // Disable backface culling to match OpenGL. - state, err := b.dev.dev.CreateRasterizerState(&_D3D11_RASTERIZER_DESC{ - CullMode: _D3D11_CULL_NONE, - FillMode: _D3D11_FILL_SOLID, - DepthClipEnable: 1, - }) - // Enable depth mask to match OpenGL. - b.depthState.mask = true - if err != nil { - return nil, err - } - b.dev.ctx.RSSetState(state) - _IUnknownRelease(unsafe.Pointer(state), state.vtbl.Release) - return b, nil -} - -func (b *Backend) BeginFrame() { -} - -func (b *Backend) EndFrame() { -} - -func (b *Backend) Caps() backend.Caps { - return b.caps -} - -func (b *Backend) NewTimer() backend.Timer { - panic("timers not supported") -} - -func (b *Backend) IsTimeContinuous() bool { - panic("timers not supported") -} - -func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, minFilter, magFilter backend.TextureFilter, bindings backend.BufferBinding) (backend.Texture, error) { - var d3dfmt uint32 - switch format { - case backend.TextureFormatFloat: - d3dfmt = b.dev.floatFormat - case backend.TextureFormatSRGB: - d3dfmt = _DXGI_FORMAT_R8G8B8A8_UNORM_SRGB - default: - return nil, fmt.Errorf("unsupported texture format %d", format) - } - tex, err := b.dev.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ - Width: uint32(width), - Height: uint32(height), - MipLevels: 1, - ArraySize: 1, - Format: d3dfmt, - SampleDesc: _DXGI_SAMPLE_DESC{ - Count: 1, - Quality: 0, - }, - BindFlags: convBufferBinding(bindings), - }) - if err != nil { - return nil, err - } - var ( - sampler *_ID3D11SamplerState - resView *_ID3D11ShaderResourceView - ) - if bindings&backend.BufferBindingTexture != 0 { - var filter uint32 - switch { - case minFilter == backend.FilterNearest && magFilter == backend.FilterNearest: - filter = _D3D11_FILTER_MIN_MAG_MIP_POINT - case minFilter == backend.FilterLinear && magFilter == backend.FilterLinear: - filter = _D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT - default: - _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) - return nil, fmt.Errorf("unsupported texture filter combination %d, %d", minFilter, magFilter) - } - var err error - sampler, err = b.dev.dev.CreateSamplerState(&_D3D11_SAMPLER_DESC{ - Filter: filter, - AddressU: _D3D11_TEXTURE_ADDRESS_CLAMP, - AddressV: _D3D11_TEXTURE_ADDRESS_CLAMP, - AddressW: _D3D11_TEXTURE_ADDRESS_CLAMP, - MaxAnisotropy: 1, - MinLOD: -math.MaxFloat32, - MaxLOD: math.MaxFloat32, - }) - if err != nil { - _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) - return nil, err - } - resView, err = b.dev.dev.CreateShaderResourceViewTEX2D( - (*_ID3D11Resource)(unsafe.Pointer(tex)), - &_D3D11_SHADER_RESOURCE_VIEW_DESC_TEX2D{ - _D3D11_SHADER_RESOURCE_VIEW_DESC: _D3D11_SHADER_RESOURCE_VIEW_DESC{ - Format: d3dfmt, - ViewDimension: _D3D11_SRV_DIMENSION_TEXTURE2D, - }, - Texture2D: _D3D11_TEX2D_SRV{ - MostDetailedMip: 0, - MipLevels: ^uint32(0), - }, - }, - ) - if err != nil { - _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) - _IUnknownRelease(unsafe.Pointer(sampler), sampler.vtbl.Release) - return nil, err - } - } - return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil -} - -func (b *Backend) CurrentFramebuffer() backend.Framebuffer { - renderTarget := b.dev.ctx.OMGetRenderTargets() - 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 - } - return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true} -} - -func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Framebuffer, error) { - d3dtex := tex.(*Texture) - if d3dtex.bindings&backend.BufferBindingFramebuffer == 0 { - return nil, errors.New("the texture was created without BufferBindingFramebuffer binding") - } - resource := (*_ID3D11Resource)(unsafe.Pointer(d3dtex.tex)) - renderTarget, err := b.dev.dev.CreateRenderTargetView(resource) - if err != nil { - return nil, err - } - fbo := &Framebuffer{dev: b.dev, format: d3dtex.format, resource: resource, renderTarget: renderTarget} - if depthBits > 0 { - depthView, err := createDepthView(b.dev.dev, d3dtex.width, d3dtex.height, depthBits) - if err != nil { - _IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release) - return nil, err - } - fbo.depthView = depthView - } - 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)) - } - descs := make([]_D3D11_INPUT_ELEMENT_DESC, len(layout)) - for i, l := range layout { - inp := vertexShader.Inputs[i] - cname, err := windows.BytePtrFromString(inp.Semantic) - if err != nil { - return nil, err - } - var format uint32 - switch l.Type { - case backend.DataTypeFloat: - switch l.Size { - case 1: - format = _DXGI_FORMAT_R32_FLOAT - case 2: - format = _DXGI_FORMAT_R32G32_FLOAT - case 3: - format = _DXGI_FORMAT_R32G32B32_FLOAT - case 4: - format = _DXGI_FORMAT_R32G32B32A32_FLOAT - default: - panic("unsupported float data size") - } - case backend.DataTypeShort: - switch l.Size { - case 1: - format = _DXGI_FORMAT_R16_SINT - case 2: - format = _DXGI_FORMAT_R16G16_SINT - default: - panic("unsupported float data size") - } - default: - panic("unsupported data type") - } - descs[i] = _D3D11_INPUT_ELEMENT_DESC{ - SemanticName: cname, - SemanticIndex: uint32(inp.SemanticIndex), - Format: format, - AlignedByteOffset: uint32(l.Offset), - } - } - l, err := b.dev.dev.CreateInputLayout(descs, vertexShader.HLSL) - if err != nil { - return nil, err - } - return &InputLayout{dev: b.dev, layout: l}, nil -} - -func (b *Backend) NewBuffer(typ backend.BufferBinding, size int) (backend.Buffer, error) { - if typ&backend.BufferBindingUniforms != 0 { - if typ != backend.BufferBindingUniforms { - return nil, errors.New("uniform buffers cannot have other bindings") - } - if size%16 != 0 { - return nil, fmt.Errorf("constant buffer size is %d, expected a multiple of 16", size) - } - } - bind := convBufferBinding(typ) - buf, err := b.dev.dev.CreateBuffer(&_D3D11_BUFFER_DESC{ - ByteWidth: uint32(size), - BindFlags: bind, - }, nil) - if err != nil { - return nil, err - } - return &Buffer{backend: b, buf: buf, bind: bind}, nil -} - -func (b *Backend) NewImmutableBuffer(typ backend.BufferBinding, data []byte) (backend.Buffer, error) { - if typ&backend.BufferBindingUniforms != 0 { - if typ != backend.BufferBindingUniforms { - return nil, errors.New("uniform buffers cannot have other bindings") - } - if len(data)%16 != 0 { - return nil, fmt.Errorf("constant buffer size is %d, expected a multiple of 16", len(data)) - } - } - bind := convBufferBinding(typ) - buf, err := b.dev.dev.CreateBuffer(&_D3D11_BUFFER_DESC{ - ByteWidth: uint32(len(data)), - Usage: _D3D11_USAGE_IMMUTABLE, - BindFlags: bind, - }, data) - if err != nil { - return nil, err - } - return &Buffer{backend: b, buf: buf, bind: bind, immutable: true}, nil -} - -func (b *Backend) NewProgram(vertexShader, fragmentShader backend.ShaderSources) (backend.Program, error) { - vs, err := b.dev.dev.CreateVertexShader(vertexShader.HLSL) - if err != nil { - return nil, err - } - ps, err := b.dev.dev.CreatePixelShader(fragmentShader.HLSL) - if err != nil { - return nil, err - } - p := &Program{backend: b} - p.vert.shader = vs - p.frag.shader = ps - return p, nil -} - -func (b *Backend) Clear(colr, colg, colb, cola float32) { - b.clearColor = [4]float32{colr, colg, colb, cola} - b.dev.ctx.ClearRenderTargetView(b.fbo.renderTarget, &b.clearColor) -} - -func (b *Backend) ClearDepth(depth float32) { - if b.fbo.depthView != nil { - b.dev.ctx.ClearDepthStencilView(b.fbo.depthView, _D3D11_CLEAR_DEPTH|_D3D11_CLEAR_STENCIL, depth, 0) - } -} - -func (b *Backend) Viewport(x, y, width, height int) { - b.viewport = _D3D11_VIEWPORT{ - TopLeftX: float32(x), - TopLeftY: float32(y), - Width: float32(width), - Height: float32(height), - MinDepth: 0.0, - MaxDepth: 1.0, - } - b.dev.ctx.RSSetViewports(&b.viewport) -} - -func (b *Backend) DrawArrays(mode backend.DrawMode, off, count int) { - b.prepareDraw(mode) - b.dev.ctx.Draw(uint32(count), uint32(off)) -} - -func (b *Backend) DrawElements(mode backend.DrawMode, off, count int) { - b.prepareDraw(mode) - b.dev.ctx.DrawIndexed(uint32(count), uint32(off), 0) -} - -func (b *Backend) prepareDraw(mode backend.DrawMode) { - if p := b.prog; p != nil { - b.dev.ctx.VSSetShader(p.vert.shader) - b.dev.ctx.PSSetShader(p.frag.shader) - if buf := p.vert.uniforms; buf != nil { - b.dev.ctx.VSSetConstantBuffers(buf.buf) - } - if buf := p.frag.uniforms; buf != nil { - b.dev.ctx.PSSetConstantBuffers(buf.buf) - } - } - var topology uint32 - switch mode { - case backend.DrawModeTriangles: - topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST - case backend.DrawModeTriangleStrip: - topology = _D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP - default: - panic("unsupported draw mode") - } - b.dev.ctx.IASetPrimitiveTopology(topology) - - depthState, ok := b.dev.depthStates[b.depthState] - if !ok { - var desc _D3D11_DEPTH_STENCIL_DESC - if b.depthState.enable { - desc.DepthEnable = 1 - } - if b.depthState.mask { - desc.DepthWriteMask = _D3D11_DEPTH_WRITE_MASK_ALL - } - switch b.depthState.fn { - case backend.DepthFuncGreater: - desc.DepthFunc = _D3D11_COMPARISON_GREATER - case backend.DepthFuncGreaterEqual: - desc.DepthFunc = _D3D11_COMPARISON_GREATER_EQUAL - default: - panic("unsupported depth func") - } - var err error - depthState, err = b.dev.dev.CreateDepthStencilState(&desc) - if err != nil { - panic(err) - } - b.dev.depthStates[b.depthState] = depthState - } - b.dev.ctx.OMSetDepthStencilState(depthState, 0) - - blendState, ok := b.dev.blendStates[b.blendState] - if !ok { - var desc _D3D11_BLEND_DESC - t0 := &desc.RenderTarget[0] - t0.RenderTargetWriteMask = _D3D11_COLOR_WRITE_ENABLE_ALL - t0.BlendOp = _D3D11_BLEND_OP_ADD - t0.BlendOpAlpha = _D3D11_BLEND_OP_ADD - if b.blendState.enable { - t0.BlendEnable = 1 - } - scol, salpha := toBlendFactor(b.blendState.sfactor) - dcol, dalpha := toBlendFactor(b.blendState.dfactor) - t0.SrcBlend = scol - t0.SrcBlendAlpha = salpha - t0.DestBlend = dcol - t0.DestBlendAlpha = dalpha - var err error - blendState, err = b.dev.dev.CreateBlendState(&desc) - if err != nil { - panic(err) - } - b.dev.blendStates[b.blendState] = blendState - } - b.dev.ctx.OMSetBlendState(blendState, nil, 0xffffffff) -} - -func (b *Backend) DepthFunc(f backend.DepthFunc) { - b.depthState.fn = f -} - -func (b *Backend) SetBlend(enable bool) { - b.blendState.enable = enable -} - -func (b *Backend) SetDepthTest(enable bool) { - b.depthState.enable = enable -} - -func (b *Backend) DepthMask(mask bool) { - b.depthState.mask = mask -} - -func (b *Backend) BlendFunc(sfactor, dfactor backend.BlendFactor) { - b.blendState.sfactor = sfactor - b.blendState.dfactor = dfactor -} - -func (t *Texture) Upload(img *image.RGBA) { - b := img.Bounds() - w := b.Dx() - if img.Stride != w*4 { - panic("unsupported stride") - } - start := (b.Min.X + b.Min.Y*w) * 4 - end := (b.Max.X + (b.Max.Y-1)*w) * 4 - pixels := img.Pix[start:end] - res := (*_ID3D11Resource)(unsafe.Pointer(t.tex)) - t.backend.dev.ctx.UpdateSubresource(res, uint32(img.Stride), uint32(len(pixels)), pixels) -} - -func (t *Texture) Release() { - _IUnknownRelease(unsafe.Pointer(t.tex), t.tex.vtbl.Release) - t.tex = nil - if t.sampler != nil { - _IUnknownRelease(unsafe.Pointer(t.sampler), t.sampler.vtbl.Release) - t.sampler = nil - } - if t.resView != nil { - _IUnknownRelease(unsafe.Pointer(t.resView), t.resView.vtbl.Release) - t.resView = nil - } -} - -func (b *Backend) BindTexture(unit int, tex backend.Texture) { - t := tex.(*Texture) - b.dev.ctx.PSSetSamplers(uint32(unit), t.sampler) - b.dev.ctx.PSSetShaderResources(uint32(unit), t.resView) -} - -func (b *Backend) BindProgram(prog backend.Program) { - b.prog = prog.(*Program) -} - -func (p *Program) Release() { - _IUnknownRelease(unsafe.Pointer(p.vert.shader), p.vert.shader.vtbl.Release) - _IUnknownRelease(unsafe.Pointer(p.frag.shader), p.frag.shader.vtbl.Release) - p.vert.shader = nil - p.frag.shader = nil -} - -func (p *Program) SetVertexUniforms(buf backend.Buffer) { - p.vert.uniforms = buf.(*Buffer) -} - -func (p *Program) SetFragmentUniforms(buf backend.Buffer) { - p.frag.uniforms = buf.(*Buffer) -} - -func (b *Backend) BindVertexBuffer(buf backend.Buffer, stride, offset int) { - b.dev.ctx.IASetVertexBuffers(buf.(*Buffer).buf, uint32(stride), uint32(offset)) -} - -func (b *Backend) BindIndexBuffer(buf backend.Buffer) { - b.dev.ctx.IASetIndexBuffer(buf.(*Buffer).buf, _DXGI_FORMAT_R16_UINT, 0) -} - -func (b *Buffer) Upload(data []byte) { - b.backend.dev.ctx.UpdateSubresource((*_ID3D11Resource)(unsafe.Pointer(b.buf)), 0, 0, data) -} - -func (b *Buffer) Release() { - _IUnknownRelease(unsafe.Pointer(b.buf), b.buf.vtbl.Release) - b.buf = nil -} - -func (f *Framebuffer) ReadPixels(src image.Rectangle, pixels []byte) error { - if f.resource == nil { - return errors.New("framebuffer does not support ReadPixels") - } - w, h := src.Dx(), src.Dy() - tex, err := f.dev.dev.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{ - Width: uint32(w), - Height: uint32(h), - MipLevels: 1, - ArraySize: 1, - Format: f.format, - SampleDesc: _DXGI_SAMPLE_DESC{ - Count: 1, - Quality: 0, - }, - Usage: _D3D11_USAGE_STAGING, - CPUAccessFlags: _D3D11_CPU_ACCESS_READ, - }) - if err != nil { - return fmt.Errorf("ReadPixels: %v", err) - } - defer _IUnknownRelease(unsafe.Pointer(tex), tex.vtbl.Release) - res := (*_ID3D11Resource)(unsafe.Pointer(tex)) - f.dev.ctx.CopySubresourceRegion( - res, - 0, // Destination subresource. - 0, 0, 0, // Destination coordinates (x, y, z). - f.resource, - 0, // Source subresource. - &_D3D11_BOX{ - left: uint32(src.Min.X), - top: uint32(src.Min.Y), - right: uint32(src.Max.X), - bottom: uint32(src.Max.Y), - front: 0, - back: 1, - }, - ) - resMap, err := f.dev.ctx.Map(res, 0, _D3D11_MAP_READ, 0) - if err != nil { - return fmt.Errorf("ReadPixels: %v", err) - } - defer f.dev.ctx.Unmap(res, 0) - srcPitch := w * 4 - dstPitch := int(resMap.RowPitch) - mapSize := dstPitch * h - data := gunsafe.SliceOf(resMap.pData)[:mapSize:mapSize] - width := w * 4 - for r := 0; r < h; r++ { - pixels := pixels[r*srcPitch:] - copy(pixels[:width], data[r*dstPitch:]) - } - return nil -} - -func (b *Backend) BindFramebuffer(fbo backend.Framebuffer) { - b.fbo = fbo.(*Framebuffer) - b.dev.ctx.OMSetRenderTargets(b.fbo.renderTarget, b.fbo.depthView) -} - -func (f *Framebuffer) Invalidate() { -} - -func (f *Framebuffer) Release() { - if f.foreign { - panic("cannot release Framebuffer from CurrentFramebuffer") - } - if f.renderTarget != nil { - _IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release) - f.renderTarget = nil - } - if f.depthView != nil { - _IUnknownRelease(unsafe.Pointer(f.depthView), f.depthView.vtbl.Release) - f.depthView = nil - } -} - -func (b *Backend) BindInputLayout(layout backend.InputLayout) { - b.dev.ctx.IASetInputLayout(layout.(*InputLayout).layout) -} - -func (l *InputLayout) Release() { - _IUnknownRelease(unsafe.Pointer(l.layout), l.layout.vtbl.Release) - l.layout = nil -} - -func convBufferBinding(typ backend.BufferBinding) uint32 { - var bindings uint32 - if typ&backend.BufferBindingVertices != 0 { - bindings |= _D3D11_BIND_VERTEX_BUFFER - } - if typ&backend.BufferBindingIndices != 0 { - bindings |= _D3D11_BIND_INDEX_BUFFER - } - if typ&backend.BufferBindingUniforms != 0 { - bindings |= _D3D11_BIND_CONSTANT_BUFFER - } - if typ&backend.BufferBindingTexture != 0 { - bindings |= _D3D11_BIND_SHADER_RESOURCE - } - if typ&backend.BufferBindingFramebuffer != 0 { - bindings |= _D3D11_BIND_RENDER_TARGET - } - return bindings -} - -func toBlendFactor(f backend.BlendFactor) (uint32, uint32) { - switch f { - case backend.BlendFactorOne: - return _D3D11_BLEND_ONE, _D3D11_BLEND_ONE - case backend.BlendFactorOneMinusSrcAlpha: - return _D3D11_BLEND_INV_SRC_ALPHA, _D3D11_BLEND_INV_SRC_ALPHA - case backend.BlendFactorZero: - return _D3D11_BLEND_ZERO, _D3D11_BLEND_ZERO - case backend.BlendFactorDstColor: - return _D3D11_BLEND_DEST_COLOR, _D3D11_BLEND_DEST_ALPHA - default: - panic("unsupported blend source factor") - } -} |