mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +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 {
|
||||
pShaderBytecode uintptr
|
||||
pShaderBytecode unsafe.Pointer
|
||||
BytecodeLength uintptr
|
||||
}
|
||||
|
||||
@ -1507,10 +1507,10 @@ func (i *_ID3D12Device) CreateRenderTargetView(pResource *_ID3D12Resource, 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
|
||||
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)))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
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)
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) GetBufferPointer() uintptr {
|
||||
func (i *_ID3DBlob) GetBufferPointer() unsafe.Pointer {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetBufferPointer, 1, uintptr(unsafe.Pointer(i)),
|
||||
0, 0)
|
||||
return r
|
||||
return unsafe.Pointer(r)
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) GetBufferSize() uintptr {
|
||||
|
@ -17,7 +17,6 @@ package directx
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@ -91,9 +90,9 @@ type graphics12 struct {
|
||||
nextImageID graphicsdriver.ImageID
|
||||
disposedImages [frameCount][]*image12
|
||||
|
||||
shaders map[graphicsdriver.ShaderID]*Shader
|
||||
shaders map[graphicsdriver.ShaderID]*shader12
|
||||
nextShaderID graphicsdriver.ShaderID
|
||||
disposedShaders [frameCount][]*Shader
|
||||
disposedShaders [frameCount][]*shader12
|
||||
|
||||
vsyncEnabled bool
|
||||
transparent bool
|
||||
@ -864,18 +863,6 @@ func (g *graphics12) SetTransparent(transparent bool) {
|
||||
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) {
|
||||
// Create buffers if necessary.
|
||||
vidx := len(g.vertices[g.frameIndex])
|
||||
@ -884,7 +871,7 @@ func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr err
|
||||
} else {
|
||||
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 {
|
||||
g.vertices[g.frameIndex][vidx].release()
|
||||
g.vertices[g.frameIndex][vidx] = nil
|
||||
@ -913,7 +900,7 @@ func (g *graphics12) SetVertices(vertices []float32, indices []uint16) (ferr err
|
||||
} else {
|
||||
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 {
|
||||
g.indices[g.frameIndex][iidx].release()
|
||||
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)
|
||||
}
|
||||
|
||||
func (g *graphics12) addShader(s *Shader) {
|
||||
func (g *graphics12) addShader(s *shader12) {
|
||||
if g.shaders == nil {
|
||||
g.shaders = map[graphicsdriver.ShaderID]*Shader{}
|
||||
g.shaders = map[graphicsdriver.ShaderID]*shader12{}
|
||||
}
|
||||
if _, ok := g.shaders[s.id]; ok {
|
||||
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
|
||||
}
|
||||
|
||||
func (g *graphics12) removeShader(s *Shader) {
|
||||
func (g *graphics12) removeShader(s *shader12) {
|
||||
delete(g.shaders, s.id)
|
||||
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
|
||||
}
|
||||
|
||||
s := &Shader{
|
||||
s := &shader12{
|
||||
graphics: g,
|
||||
id: g.genNextShaderID(),
|
||||
uniformTypes: program.Uniforms,
|
||||
@ -1138,7 +1125,7 @@ func (g *graphics12) DrawTriangles(dstID graphicsdriver.ImageID, srcs [graphics.
|
||||
}
|
||||
|
||||
shader := g.shaders[shaderID]
|
||||
adjustedUniforms := shader.adjustUniforms(uniforms)
|
||||
adjustedUniforms := adjustUniforms(shader.uniformTypes, shader.uniformOffsets, uniforms)
|
||||
|
||||
w, h := dst.internalSize()
|
||||
g.needFlushDrawCommandList = true
|
||||
|
@ -17,6 +17,7 @@ package directx
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -28,8 +29,28 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
type stencilMode int
|
||||
|
||||
const (
|
||||
prepareStencil stencilMode = iota
|
||||
drawWithStencil
|
||||
noStencil
|
||||
)
|
||||
|
||||
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.
|
||||
// The returned graphics value is nil iff the error is not nil.
|
||||
func NewGraphics() (graphicsdriver.Graphics, error) {
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
var inputElementDescs = []_D3D12_INPUT_ELEMENT_DESC{
|
||||
var inputElementDescsForDX12 = []_D3D12_INPUT_ELEMENT_DESC{
|
||||
{
|
||||
SemanticName: &([]byte("POSITION\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
@ -55,7 +55,7 @@ var inputElementDescs = []_D3D12_INPUT_ELEMENT_DESC{
|
||||
|
||||
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.
|
||||
// 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 {
|
||||
case graphicsdriver.BlendOperationAdd:
|
||||
return _D3D12_BLEND_OP_ADD
|
||||
@ -176,7 +176,7 @@ func (p *pipelineStates) initialize(device *_ID3D12Device) (ferr error) {
|
||||
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])
|
||||
if idx >= numDescriptorsPerFrame {
|
||||
return fmt.Errorf("directx: too many constant buffers")
|
||||
@ -479,12 +479,12 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
||||
{
|
||||
BlendEnable: 1,
|
||||
LogicOpEnable: 0,
|
||||
SrcBlend: blendFactorToBlend(blend.BlendFactorSourceRGB, false),
|
||||
DestBlend: blendFactorToBlend(blend.BlendFactorDestinationRGB, false),
|
||||
BlendOp: blendOperationToBlendOp(blend.BlendOperationRGB),
|
||||
SrcBlendAlpha: blendFactorToBlend(blend.BlendFactorSourceAlpha, true),
|
||||
DestBlendAlpha: blendFactorToBlend(blend.BlendFactorDestinationAlpha, true),
|
||||
BlendOpAlpha: blendOperationToBlendOp(blend.BlendOperationAlpha),
|
||||
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
|
||||
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
|
||||
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
|
||||
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
|
||||
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
|
||||
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
|
||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||
RenderTargetWriteMask: writeMask,
|
||||
},
|
||||
@ -506,8 +506,8 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
||||
},
|
||||
DepthStencilState: depthStencilDesc,
|
||||
InputLayout: _D3D12_INPUT_LAYOUT_DESC{
|
||||
pInputElementDescs: &inputElementDescs[0],
|
||||
NumElements: uint32(len(inputElementDescs)),
|
||||
pInputElementDescs: &inputElementDescsForDX12[0],
|
||||
NumElements: uint32(len(inputElementDescsForDX12)),
|
||||
},
|
||||
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
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"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"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{}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Shader) ID() graphicsdriver.ShaderID {
|
||||
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 {
|
||||
func adjustUniforms(uniformTypes []shaderir.Type, uniformOffsets []int, uniforms []uint32) []uint32 {
|
||||
var fs []uint32
|
||||
var idx int
|
||||
for i, typ := range s.uniformTypes {
|
||||
if len(fs) < s.uniformOffsets[i]/4 {
|
||||
fs = append(fs, make([]uint32, s.uniformOffsets[i]/4-len(fs))...)
|
||||
for i, typ := range uniformTypes {
|
||||
if len(fs) < uniformOffsets[i]/4 {
|
||||
fs = append(fs, make([]uint32, uniformOffsets[i]/4-len(fs))...)
|
||||
}
|
||||
|
||||
n := typ.Uint32Count()
|
||||
|
Loading…
Reference in New Issue
Block a user