mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
internal/graphicsdriver/directx: refactoring
This is a preparation for a DirectX 11 driver. Updates #2613
This commit is contained in:
parent
4779bbc04d
commit
c8a2e5dc71
@ -726,7 +726,7 @@ type _D3D12_ROOT_SIGNATURE_DESC struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type _D3D12_SHADER_BYTECODE struct {
|
type _D3D12_SHADER_BYTECODE struct {
|
||||||
pShaderBytecode uintptr
|
pShaderBytecode unsafe.Pointer
|
||||||
BytecodeLength uintptr
|
BytecodeLength uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1507,10 +1507,10 @@ func (i *_ID3D12Device) CreateRenderTargetView(pResource *_ID3D12Resource, pDesc
|
|||||||
runtime.KeepAlive(pDesc)
|
runtime.KeepAlive(pDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *_ID3D12Device) CreateRootSignature(nodeMask uint32, pBlobWithRootSignature uintptr, blobLengthInBytes uintptr) (*_ID3D12RootSignature, error) {
|
func (i *_ID3D12Device) CreateRootSignature(nodeMask uint32, pBlobWithRootSignature unsafe.Pointer, blobLengthInBytes uintptr) (*_ID3D12RootSignature, error) {
|
||||||
var signature *_ID3D12RootSignature
|
var signature *_ID3D12RootSignature
|
||||||
r, _, _ := syscall.Syscall6(i.vtbl.CreateRootSignature, 6, uintptr(unsafe.Pointer(i)),
|
r, _, _ := syscall.Syscall6(i.vtbl.CreateRootSignature, 6, uintptr(unsafe.Pointer(i)),
|
||||||
uintptr(nodeMask), pBlobWithRootSignature, blobLengthInBytes,
|
uintptr(nodeMask), uintptr(pBlobWithRootSignature), blobLengthInBytes,
|
||||||
uintptr(unsafe.Pointer(&_IID_ID3D12RootSignature)), uintptr(unsafe.Pointer(&signature)))
|
uintptr(unsafe.Pointer(&_IID_ID3D12RootSignature)), uintptr(unsafe.Pointer(&signature)))
|
||||||
if uint32(r) != uint32(windows.S_OK) {
|
if uint32(r) != uint32(windows.S_OK) {
|
||||||
return nil, fmt.Errorf("directx: ID3D12Device::CreateRootSignature failed: %w", handleError(windows.Handle(uint32(r))))
|
return nil, fmt.Errorf("directx: ID3D12Device::CreateRootSignature failed: %w", handleError(windows.Handle(uint32(r))))
|
||||||
|
@ -112,10 +112,10 @@ func (i *_ID3DBlob) AddRef() uint32 {
|
|||||||
return uint32(r)
|
return uint32(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *_ID3DBlob) GetBufferPointer() uintptr {
|
func (i *_ID3DBlob) GetBufferPointer() unsafe.Pointer {
|
||||||
r, _, _ := syscall.Syscall(i.vtbl.GetBufferPointer, 1, uintptr(unsafe.Pointer(i)),
|
r, _, _ := syscall.Syscall(i.vtbl.GetBufferPointer, 1, uintptr(unsafe.Pointer(i)),
|
||||||
0, 0)
|
0, 0)
|
||||||
return r
|
return unsafe.Pointer(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *_ID3DBlob) GetBufferSize() uintptr {
|
func (i *_ID3DBlob) GetBufferSize() uintptr {
|
||||||
|
@ -17,7 +17,6 @@ package directx
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
@ -91,9 +90,9 @@ type graphics12 struct {
|
|||||||
nextImageID graphicsdriver.ImageID
|
nextImageID graphicsdriver.ImageID
|
||||||
disposedImages [frameCount][]*image12
|
disposedImages [frameCount][]*image12
|
||||||
|
|
||||||
shaders map[graphicsdriver.ShaderID]*Shader
|
shaders map[graphicsdriver.ShaderID]*shader12
|
||||||
nextShaderID graphicsdriver.ShaderID
|
nextShaderID graphicsdriver.ShaderID
|
||||||
disposedShaders [frameCount][]*Shader
|
disposedShaders [frameCount][]*shader12
|
||||||
|
|
||||||
vsyncEnabled bool
|
vsyncEnabled bool
|
||||||
transparent bool
|
transparent bool
|
||||||
@ -864,18 +863,6 @@ func (g *graphics12) SetTransparent(transparent bool) {
|
|||||||
g.transparent = transparent
|
g.transparent = transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
func pow2(x uint32) uint32 {
|
|
||||||
if x > (math.MaxUint32+1)/2 {
|
|
||||||
return math.MaxUint32
|
|
||||||
}
|
|
||||||
|
|
||||||
var p2 uint32 = 1
|
|
||||||
for p2 < x {
|
|
||||||
p2 *= 2
|
|
||||||
}
|
|
||||||
return p2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr error) {
|
func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr error) {
|
||||||
// Create buffers if necessary.
|
// Create buffers if necessary.
|
||||||
vidx := len(g.vertices[g.frameIndex])
|
vidx := len(g.vertices[g.frameIndex])
|
||||||
@ -884,7 +871,7 @@ func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr err
|
|||||||
} else {
|
} else {
|
||||||
g.vertices[g.frameIndex] = append(g.vertices[g.frameIndex], nil)
|
g.vertices[g.frameIndex] = append(g.vertices[g.frameIndex], nil)
|
||||||
}
|
}
|
||||||
vsize := pow2(uint32(len(vertices)) * uint32(unsafe.Sizeof(float32(0))))
|
vsize := pow2(uint32(len(vertices)) * uint32(unsafe.Sizeof(vertices[0])))
|
||||||
if g.vertices[g.frameIndex][vidx] != nil && g.vertices[g.frameIndex][vidx].sizeInBytes < vsize {
|
if g.vertices[g.frameIndex][vidx] != nil && g.vertices[g.frameIndex][vidx].sizeInBytes < vsize {
|
||||||
g.vertices[g.frameIndex][vidx].release()
|
g.vertices[g.frameIndex][vidx].release()
|
||||||
g.vertices[g.frameIndex][vidx] = nil
|
g.vertices[g.frameIndex][vidx] = nil
|
||||||
@ -913,7 +900,7 @@ func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr err
|
|||||||
} else {
|
} else {
|
||||||
g.indices[g.frameIndex] = append(g.indices[g.frameIndex], nil)
|
g.indices[g.frameIndex] = append(g.indices[g.frameIndex], nil)
|
||||||
}
|
}
|
||||||
isize := pow2(uint32(len(indices)) * uint32(unsafe.Sizeof(uint16(0))))
|
isize := pow2(uint32(len(indices)) * uint32(unsafe.Sizeof(indices[0])))
|
||||||
if g.indices[g.frameIndex][iidx] != nil && g.indices[g.frameIndex][iidx].sizeInBytes < isize {
|
if g.indices[g.frameIndex][iidx] != nil && g.indices[g.frameIndex][iidx].sizeInBytes < isize {
|
||||||
g.indices[g.frameIndex][iidx].release()
|
g.indices[g.frameIndex][iidx].release()
|
||||||
g.indices[g.frameIndex][iidx] = nil
|
g.indices[g.frameIndex][iidx] = nil
|
||||||
@ -1031,9 +1018,9 @@ func (g *graphics12) removeImage(img *image12) {
|
|||||||
g.disposedImages[g.frameIndex] = append(g.disposedImages[g.frameIndex], img)
|
g.disposedImages[g.frameIndex] = append(g.disposedImages[g.frameIndex], img)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *graphics12) addShader(s *Shader) {
|
func (g *graphics12) addShader(s *shader12) {
|
||||||
if g.shaders == nil {
|
if g.shaders == nil {
|
||||||
g.shaders = map[graphicsdriver.ShaderID]*Shader{}
|
g.shaders = map[graphicsdriver.ShaderID]*shader12{}
|
||||||
}
|
}
|
||||||
if _, ok := g.shaders[s.id]; ok {
|
if _, ok := g.shaders[s.id]; ok {
|
||||||
panic(fmt.Sprintf("directx: shader ID %d was already registered", s.id))
|
panic(fmt.Sprintf("directx: shader ID %d was already registered", s.id))
|
||||||
@ -1041,7 +1028,7 @@ func (g *graphics12) addShader(s *Shader) {
|
|||||||
g.shaders[s.id] = s
|
g.shaders[s.id] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *graphics12) removeShader(s *Shader) {
|
func (g *graphics12) removeShader(s *shader12) {
|
||||||
delete(g.shaders, s.id)
|
delete(g.shaders, s.id)
|
||||||
g.disposedShaders[g.frameIndex] = append(g.disposedShaders[g.frameIndex], s)
|
g.disposedShaders[g.frameIndex] = append(g.disposedShaders[g.frameIndex], s)
|
||||||
}
|
}
|
||||||
@ -1078,7 +1065,7 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Shader{
|
s := &shader12{
|
||||||
graphics: g,
|
graphics: g,
|
||||||
id: g.genNextShaderID(),
|
id: g.genNextShaderID(),
|
||||||
uniformTypes: program.Uniforms,
|
uniformTypes: program.Uniforms,
|
||||||
@ -1138,7 +1125,7 @@ func (g *graphics12) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.
|
|||||||
}
|
}
|
||||||
|
|
||||||
shader := g.shaders[shaderID]
|
shader := g.shaders[shaderID]
|
||||||
adjustedUniforms := shader.adjustUniforms(uniforms)
|
adjustedUniforms := adjustUniforms(shader.uniformTypes, shader.uniformOffsets, uniforms)
|
||||||
|
|
||||||
w, h := dst.internalSize()
|
w, h := dst.internalSize()
|
||||||
g.needFlushDrawCommandList = true
|
g.needFlushDrawCommandList = true
|
||||||
|
@ -17,6 +17,7 @@ package directx
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -28,8 +29,28 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type stencilMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
prepareStencil stencilMode = iota
|
||||||
|
drawWithStencil
|
||||||
|
noStencil
|
||||||
|
)
|
||||||
|
|
||||||
const frameCount = 2
|
const frameCount = 2
|
||||||
|
|
||||||
|
func pow2(x uint32) uint32 {
|
||||||
|
if x > (math.MaxUint32+1)/2 {
|
||||||
|
return math.MaxUint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var p2 uint32 = 1
|
||||||
|
for p2 < x {
|
||||||
|
p2 *= 2
|
||||||
|
}
|
||||||
|
return p2
|
||||||
|
}
|
||||||
|
|
||||||
// NewGraphics creates an implementation of graphicsdriver.Graphics for DirectX.
|
// NewGraphics creates an implementation of graphicsdriver.Graphics for DirectX.
|
||||||
// The returned graphics value is nil iff the error is not nil.
|
// The returned graphics value is nil iff the error is not nil.
|
||||||
func NewGraphics() (graphicsdriver.Graphics, error) {
|
func NewGraphics() (graphicsdriver.Graphics, error) {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
)
|
)
|
||||||
|
|
||||||
var inputElementDescs = []_D3D12_INPUT_ELEMENT_DESC{
|
var inputElementDescsForDX12 = []_D3D12_INPUT_ELEMENT_DESC{
|
||||||
{
|
{
|
||||||
SemanticName: &([]byte("POSITION\000"))[0],
|
SemanticName: &([]byte("POSITION\000"))[0],
|
||||||
SemanticIndex: 0,
|
SemanticIndex: 0,
|
||||||
@ -55,7 +55,7 @@ var inputElementDescs = []_D3D12_INPUT_ELEMENT_DESC{
|
|||||||
|
|
||||||
const numDescriptorsPerFrame = 32
|
const numDescriptorsPerFrame = 32
|
||||||
|
|
||||||
func blendFactorToBlend(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
func blendFactorToBlend12(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||||
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
||||||
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ func blendFactorToBlend(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func blendOperationToBlendOp(o graphicsdriver.BlendOperation) _D3D12_BLEND_OP {
|
func blendOperationToBlendOp12(o graphicsdriver.BlendOperation) _D3D12_BLEND_OP {
|
||||||
switch o {
|
switch o {
|
||||||
case graphicsdriver.BlendOperationAdd:
|
case graphicsdriver.BlendOperationAdd:
|
||||||
return _D3D12_BLEND_OP_ADD
|
return _D3D12_BLEND_OP_ADD
|
||||||
@ -176,7 +176,7 @@ func (p *pipelineStates) initialize(device *_ID3D12Device) (ferr error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipelineStates) drawTriangles(device *_ID3D12Device, commandList *_ID3D12GraphicsCommandList, frameIndex int, screen bool, srcs [graphics.ShaderImageCount]*image12, shader *Shader, dstRegions []graphicsdriver.DstRegion, uniforms []uint32, blend graphicsdriver.Blend, indexOffset int, evenOdd bool) error {
|
func (p *pipelineStates) drawTriangles(device *_ID3D12Device, commandList *_ID3D12GraphicsCommandList, frameIndex int, screen bool, srcs [graphics.ShaderImageCount]*image12, shader *shader12, dstRegions []graphicsdriver.DstRegion, uniforms []uint32, blend graphicsdriver.Blend, indexOffset int, evenOdd bool) error {
|
||||||
idx := len(p.constantBuffers[frameIndex])
|
idx := len(p.constantBuffers[frameIndex])
|
||||||
if idx >= numDescriptorsPerFrame {
|
if idx >= numDescriptorsPerFrame {
|
||||||
return fmt.Errorf("directx: too many constant buffers")
|
return fmt.Errorf("directx: too many constant buffers")
|
||||||
@ -479,12 +479,12 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
{
|
{
|
||||||
BlendEnable: 1,
|
BlendEnable: 1,
|
||||||
LogicOpEnable: 0,
|
LogicOpEnable: 0,
|
||||||
SrcBlend: blendFactorToBlend(blend.BlendFactorSourceRGB, false),
|
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
|
||||||
DestBlend: blendFactorToBlend(blend.BlendFactorDestinationRGB, false),
|
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
|
||||||
BlendOp: blendOperationToBlendOp(blend.BlendOperationRGB),
|
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
|
||||||
SrcBlendAlpha: blendFactorToBlend(blend.BlendFactorSourceAlpha, true),
|
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
|
||||||
DestBlendAlpha: blendFactorToBlend(blend.BlendFactorDestinationAlpha, true),
|
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
|
||||||
BlendOpAlpha: blendOperationToBlendOp(blend.BlendOperationAlpha),
|
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
|
||||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||||
RenderTargetWriteMask: writeMask,
|
RenderTargetWriteMask: writeMask,
|
||||||
},
|
},
|
||||||
@ -506,8 +506,8 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
},
|
},
|
||||||
DepthStencilState: depthStencilDesc,
|
DepthStencilState: depthStencilDesc,
|
||||||
InputLayout: _D3D12_INPUT_LAYOUT_DESC{
|
InputLayout: _D3D12_INPUT_LAYOUT_DESC{
|
||||||
pInputElementDescs: &inputElementDescs[0],
|
pInputElementDescs: &inputElementDescsForDX12[0],
|
||||||
NumElements: uint32(len(inputElementDescs)),
|
NumElements: uint32(len(inputElementDescsForDX12)),
|
||||||
},
|
},
|
||||||
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||||
NumRenderTargets: 1,
|
NumRenderTargets: 1,
|
||||||
|
89
internal/graphicsdriver/directx/shader12_windows.go
Normal file
89
internal/graphicsdriver/directx/shader12_windows.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright 2023 The Ebitengine Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package directx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pipelineStateKey struct {
|
||||||
|
blend graphicsdriver.Blend
|
||||||
|
stencilMode stencilMode
|
||||||
|
screen bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type shader12 struct {
|
||||||
|
graphics *graphics12
|
||||||
|
id graphicsdriver.ShaderID
|
||||||
|
uniformTypes []shaderir.Type
|
||||||
|
uniformOffsets []int
|
||||||
|
vertexShader *_ID3DBlob
|
||||||
|
pixelShader *_ID3DBlob
|
||||||
|
|
||||||
|
pipelineStates map[pipelineStateKey]*_ID3D12PipelineState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *shader12) ID() graphicsdriver.ShaderID {
|
||||||
|
return s.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *shader12) Dispose() {
|
||||||
|
s.graphics.removeShader(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *shader12) disposeImpl() {
|
||||||
|
for c, p := range s.pipelineStates {
|
||||||
|
p.Release()
|
||||||
|
delete(s.pipelineStates, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.pixelShader != nil {
|
||||||
|
s.pixelShader.Release()
|
||||||
|
s.pixelShader = nil
|
||||||
|
}
|
||||||
|
if s.vertexShader != nil {
|
||||||
|
count := s.vertexShader.Release()
|
||||||
|
if count == 0 {
|
||||||
|
for k, v := range vertexShaderCache {
|
||||||
|
if v == s.vertexShader {
|
||||||
|
delete(vertexShaderCache, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.vertexShader = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *shader12) pipelineState(blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (*_ID3D12PipelineState, error) {
|
||||||
|
key := pipelineStateKey{
|
||||||
|
blend: blend,
|
||||||
|
stencilMode: stencilMode,
|
||||||
|
screen: screen,
|
||||||
|
}
|
||||||
|
if state, ok := s.pipelineStates[key]; ok {
|
||||||
|
return state, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err := s.graphics.pipelineStates.newPipelineState(s.graphics.device, s.vertexShader, s.pixelShader, blend, stencilMode, screen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if s.pipelineStates == nil {
|
||||||
|
s.pipelineStates = map[pipelineStateKey]*_ID3D12PipelineState{}
|
||||||
|
}
|
||||||
|
s.pipelineStates[key] = state
|
||||||
|
return state, nil
|
||||||
|
}
|
@ -20,34 +20,9 @@ import (
|
|||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stencilMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
prepareStencil stencilMode = iota
|
|
||||||
drawWithStencil
|
|
||||||
noStencil
|
|
||||||
)
|
|
||||||
|
|
||||||
type pipelineStateKey struct {
|
|
||||||
blend graphicsdriver.Blend
|
|
||||||
stencilMode stencilMode
|
|
||||||
screen bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Shader struct {
|
|
||||||
graphics *graphics12
|
|
||||||
id graphicsdriver.ShaderID
|
|
||||||
uniformTypes []shaderir.Type
|
|
||||||
uniformOffsets []int
|
|
||||||
vertexShader *_ID3DBlob
|
|
||||||
pixelShader *_ID3DBlob
|
|
||||||
pipelineStates map[pipelineStateKey]*_ID3D12PipelineState
|
|
||||||
}
|
|
||||||
|
|
||||||
var vertexShaderCache = map[string]*_ID3DBlob{}
|
var vertexShaderCache = map[string]*_ID3DBlob{}
|
||||||
|
|
||||||
func compileShader(vs, ps string) (vsh, psh *_ID3DBlob, ferr error) {
|
func compileShader(vs, ps string) (vsh, psh *_ID3DBlob, ferr error) {
|
||||||
@ -105,64 +80,12 @@ func compileShader(vs, ps string) (vsh, psh *_ID3DBlob, ferr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) ID() graphicsdriver.ShaderID {
|
func adjustUniforms(uniformTypes []shaderir.Type, uniformOffsets []int, uniforms []uint32) []uint32 {
|
||||||
return s.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shader) Dispose() {
|
|
||||||
s.graphics.removeShader(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shader) disposeImpl() {
|
|
||||||
for c, p := range s.pipelineStates {
|
|
||||||
p.Release()
|
|
||||||
delete(s.pipelineStates, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.pixelShader != nil {
|
|
||||||
s.pixelShader.Release()
|
|
||||||
s.pixelShader = nil
|
|
||||||
}
|
|
||||||
if s.vertexShader != nil {
|
|
||||||
count := s.vertexShader.Release()
|
|
||||||
if count == 0 {
|
|
||||||
for k, v := range vertexShaderCache {
|
|
||||||
if v == s.vertexShader {
|
|
||||||
delete(vertexShaderCache, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.vertexShader = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shader) pipelineState(blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (*_ID3D12PipelineState, error) {
|
|
||||||
key := pipelineStateKey{
|
|
||||||
blend: blend,
|
|
||||||
stencilMode: stencilMode,
|
|
||||||
screen: screen,
|
|
||||||
}
|
|
||||||
if state, ok := s.pipelineStates[key]; ok {
|
|
||||||
return state, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
state, err := s.graphics.pipelineStates.newPipelineState(s.graphics.device, s.vertexShader, s.pixelShader, blend, stencilMode, screen)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if s.pipelineStates == nil {
|
|
||||||
s.pipelineStates = map[pipelineStateKey]*_ID3D12PipelineState{}
|
|
||||||
}
|
|
||||||
s.pipelineStates[key] = state
|
|
||||||
return state, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shader) adjustUniforms(uniforms []uint32) []uint32 {
|
|
||||||
var fs []uint32
|
var fs []uint32
|
||||||
var idx int
|
var idx int
|
||||||
for i, typ := range s.uniformTypes {
|
for i, typ := range uniformTypes {
|
||||||
if len(fs) < s.uniformOffsets[i]/4 {
|
if len(fs) < uniformOffsets[i]/4 {
|
||||||
fs = append(fs, make([]uint32, s.uniformOffsets[i]/4-len(fs))...)
|
fs = append(fs, make([]uint32, uniformOffsets[i]/4-len(fs))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
n := typ.Uint32Count()
|
n := typ.Uint32Count()
|
||||||
|
Loading…
Reference in New Issue
Block a user