Compare commits

...

6 Commits

Author SHA1 Message Date
Bertrand Jung
62cfa059fa
Merge 577664c1cb into 9c070eb2f3 2024-04-06 20:40:10 +02:00
Hajime Hoshi
9c070eb2f3 Revert "internal/graphicsdriver/gl: use PureGo for Linux and UNIX"
This reverts commit 5701206229.

Reason: error on Android:

```
/Users/runner/go/pkg/mod/github.com/ebitengine/purego@v0.8.0-alpha.0.20240404024320-d0aedd0f4393/func.go:301:4: too few values in struct literal of type syscall15Args
```

https://github.com/hajimehoshi/ebiten/actions/runs/8582651053/job/23521003819
2024-04-07 03:00:13 +09:00
Hajime Hoshi
9dc103491a internal/ui: bug fix: a window was shown unexpectedly at start-up
Closes #2951
2024-04-07 02:55:48 +09:00
Hajime Hoshi
5701206229 internal/graphicsdriver/gl: use PureGo for Linux and UNIX
Updates #2284
2024-04-07 02:08:40 +09:00
Hajime Hoshi
d6f7b50387 internal/ui: bug fix: setting a size failed for an invisible window
Updates #2725
Closes #2951
2024-04-06 22:26:01 +09:00
Zyko
577664c1cb Dirty directx11 2024-04-06 14:54:32 +02:00
5 changed files with 127 additions and 13 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2020 The Ebiten Authors // Copyright 2024 The Ebiten Authors
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -124,7 +124,7 @@ func main() {
ebiten.SetWindowSize(screenWidth, screenHeight) ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("MRT (Ebitengine Demo)") ebiten.SetWindowTitle("MRT (Ebitengine Demo)")
if err := ebiten.RunGameWithOptions(&Game{}, &ebiten.RunGameOptions{ if err := ebiten.RunGameWithOptions(&Game{}, &ebiten.RunGameOptions{
GraphicsLibrary: ebiten.GraphicsLibraryOpenGL, GraphicsLibrary: ebiten.GraphicsLibraryDirectX,
}); err != nil { }); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -521,7 +521,15 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
srvs := [graphics.ShaderSrcImageCount]*_ID3D11ShaderResourceView{} srvs := [graphics.ShaderSrcImageCount]*_ID3D11ShaderResourceView{}
g.deviceContext.PSSetShaderResources(0, srvs[:]) g.deviceContext.PSSetShaderResources(0, srvs[:])
dst := g.images[dstIDs[0]] // TODO: handle array var dsts []*image11
for _, id := range dstIDs {
img := g.images[id]
if img == nil {
continue
}
dsts = append(dsts, img)
}
var srcs [graphics.ShaderSrcImageCount]*image11 var srcs [graphics.ShaderSrcImageCount]*image11
for i, id := range srcIDs { for i, id := range srcIDs {
img := g.images[id] img := g.images[id]
@ -531,7 +539,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
srcs[i] = img srcs[i] = img
} }
w, h := dst.internalSize() w, h := dsts[0].internalSize()
g.deviceContext.RSSetViewports([]_D3D11_VIEWPORT{ g.deviceContext.RSSetViewports([]_D3D11_VIEWPORT{
{ {
TopLeftX: 0, TopLeftX: 0,
@ -543,7 +551,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
}, },
}) })
if err := dst.setAsRenderTarget(fillRule != graphicsdriver.FillAll); err != nil { if err := setAsRenderTargets(dsts, fillRule != graphicsdriver.FillAll); err != nil {
return err return err
} }

View File

@ -204,6 +204,69 @@ func (i *image11) setAsRenderTarget(useStencil bool) error {
return nil return nil
} }
func setAsRenderTargets(dsts []*image11, useStencil bool) error {
for _, i := range dsts {
if i.renderTargetView == nil {
rtv, err := i.graphics.device.CreateRenderTargetView(unsafe.Pointer(i.texture), nil)
if err != nil {
return err
}
i.renderTargetView = rtv
}
if !useStencil {
continue
}
if i.screen {
return fmt.Errorf("directx: a stencil buffer is not available for a screen image")
}
if i.stencilView == nil {
sv, err := i.graphics.device.CreateDepthStencilView(unsafe.Pointer(i.stencil), nil)
if err != nil {
return err
}
i.stencilView = sv
}
if i.stencil == nil {
w, h := i.internalSize()
s, err := i.graphics.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
Width: uint32(w),
Height: uint32(h),
MipLevels: 0,
ArraySize: 1,
Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
SampleDesc: _DXGI_SAMPLE_DESC{
Count: 1,
Quality: 0,
},
Usage: _D3D11_USAGE_DEFAULT,
BindFlags: uint32(_D3D11_BIND_DEPTH_STENCIL),
CPUAccessFlags: 0,
MiscFlags: 0,
}, nil)
if err != nil {
return err
}
i.stencil = s
}
}
var rtvs []*_ID3D11RenderTargetView
var dsvs []*_ID3D11DepthStencilView
for _, i := range dsts {
rtvs = append(rtvs, i.renderTargetView)
dsvs = append(dsvs, i.stencilView)
}
dsts[0].graphics.deviceContext.OMSetRenderTargets(rtvs, dsts[0].stencilView)
if useStencil {
dsts[0].graphics.deviceContext.ClearDepthStencilView(dsts[0].stencilView, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
}
return nil
}
func (i *image11) getShaderResourceView() (*_ID3D11ShaderResourceView, error) { func (i *image11) getShaderResourceView() (*_ID3D11ShaderResourceView, error) {
if i.shaderResourceView == nil { if i.shaderResourceView == nil {
srv, err := i.graphics.device.CreateShaderResourceView(unsafe.Pointer(i.texture), nil) srv, err := i.graphics.device.CreateShaderResourceView(unsafe.Pointer(i.texture), nil)

View File

@ -22,6 +22,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
) )
@ -190,7 +191,15 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader string, offsets []i
} }
if p.FragmentFunc.Block != nil && len(p.FragmentFunc.Block.Stmts) > 0 { if p.FragmentFunc.Block != nil && len(p.FragmentFunc.Block.Stmts) > 0 {
pslines = append(pslines, "") pslines = append(pslines, "")
pslines = append(pslines, fmt.Sprintf("float4 PSMain(Varyings %s) : SV_TARGET {", vsOut)) pslines = append(pslines, "struct PS_OUTPUT")
pslines = append(pslines, "{")
for i := 0; i < graphics.ShaderDstImageCount; i++ {
pslines = append(pslines, fmt.Sprintf("\tfloat4 Color%d: SV_Target%d;", i, i))
}
pslines = append(pslines, "};")
pslines = append(pslines, "")
pslines = append(pslines, fmt.Sprintf("PS_OUTPUT PSMain(Varyings %s) {", vsOut))
pslines = append(pslines, "\tPS_OUTPUT output;")
pslines = append(pslines, c.block(p, p.FragmentFunc.Block, p.FragmentFunc.Block, 0)...) pslines = append(pslines, c.block(p, p.FragmentFunc.Block, p.FragmentFunc.Block, 0)...)
pslines = append(pslines, "}") pslines = append(pslines, "}")
} }
@ -227,6 +236,8 @@ func Compile(p *shaderir.Program) (vertexShader, pixelShader string, offsets []i
vertexShader = shaders[0] vertexShader = shaders[0]
pixelShader = shaders[1] pixelShader = shaders[1]
fmt.Println("PS:", pixelShader)
return return
} }
@ -353,7 +364,7 @@ func (c *compileContext) localVariableName(p *shaderir.Program, topBlock *shader
case idx < nv+1: case idx < nv+1:
return fmt.Sprintf("%s.M%d", vsOut, idx-1) return fmt.Sprintf("%s.M%d", vsOut, idx-1)
default: default:
return fmt.Sprintf("l%d", idx-(nv+1)) return fmt.Sprintf("output.Color%d", idx-(nv+1))
} }
default: default:
return fmt.Sprintf("l%d", idx) return fmt.Sprintf("l%d", idx)
@ -393,9 +404,6 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
} }
var lines []string var lines []string
for i := range block.LocalVars {
lines = append(lines, c.initVariable(p, topBlock, block, block.LocalVarIndexOffset+i, true, level)...)
}
var expr func(e *shaderir.Expr) string var expr func(e *shaderir.Expr) string
expr = func(e *shaderir.Expr) string { expr = func(e *shaderir.Expr) string {
@ -502,7 +510,8 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
case shaderir.Assign: case shaderir.Assign:
lhs := s.Exprs[0] lhs := s.Exprs[0]
rhs := s.Exprs[1] rhs := s.Exprs[1]
if lhs.Type == shaderir.LocalVariable { isOutput := strings.HasPrefix(expr(&lhs), "output.Color")
if !isOutput && lhs.Type == shaderir.LocalVariable {
if t := p.LocalVariableType(topBlock, block, lhs.Index); t.Main == shaderir.Array { if t := p.LocalVariableType(topBlock, block, lhs.Index); t.Main == shaderir.Array {
for i := 0; i < t.Length; i++ { for i := 0; i < t.Length; i++ {
lines = append(lines, fmt.Sprintf("%[1]s%[2]s[%[3]d] = %[4]s[%[3]d];", idt, expr(&lhs), i, expr(&rhs))) lines = append(lines, fmt.Sprintf("%[1]s%[2]s[%[3]d] = %[4]s[%[3]d];", idt, expr(&lhs), i, expr(&rhs)))
@ -564,7 +573,7 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
case topBlock == p.VertexFunc.Block: case topBlock == p.VertexFunc.Block:
lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, vsOut)) lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, vsOut))
case len(s.Exprs) == 0: case len(s.Exprs) == 0:
lines = append(lines, idt+"return;") lines = append(lines, idt+"return output;")
default: default:
lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, expr(&s.Exprs[0]))) lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, expr(&s.Exprs[0])))
} }

View File

@ -1027,7 +1027,7 @@ func (u *UserInterface) initOnMainThread(options *RunOptions) error {
return err return err
} }
// Window is shown after the first buffer swap. // Window is shown after the first buffer swap (#2725).
if err := glfw.WindowHint(glfw.Visible, glfw.False); err != nil { if err := glfw.WindowHint(glfw.Visible, glfw.False); err != nil {
return err return err
} }
@ -1294,6 +1294,40 @@ func (u *UserInterface) update() (float64, float64, error) {
if err = u.window.Focus(); err != nil { if err = u.window.Focus(); err != nil {
return return
} }
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
return
}
// On Linux or UNIX, there is a problematic desktop environment like i3wm
// where an invisible window size cannot be initialized correctly (#2951).
// Call SetSize explicitly after the window becomes visible.
fullscreen, e := u.isFullscreen()
if e != nil {
err = e
return
}
if fullscreen {
return
}
m, e := u.currentMonitor()
if e != nil {
err = e
return
}
s := m.DeviceScaleFactor()
newW := int(dipToGLFWPixel(float64(u.origWindowWidthInDIP), s))
newH := int(dipToGLFWPixel(float64(u.origWindowHeightInDIP), s))
// Even though a framebuffer callback is not called, waitForFramebufferSizeCallback returns by timeout,
// so it is safe to use this.
if err = u.waitForFramebufferSizeCallback(u.window, func() error {
return u.window.SetSize(newW, newH)
}); err != nil {
return
}
}) })
if err != nil { if err != nil {
return 0, 0, err return 0, 0, err