Add test with empty locations + fix directx 11 && 12 nil first argument

This commit is contained in:
Zyko 2024-04-13 13:56:13 +02:00
parent 0b53525808
commit d706d38ada
7 changed files with 65 additions and 25 deletions

View File

@ -36,9 +36,9 @@ var (
ebiten.NewImage(dstSize, dstSize),
ebiten.NewImage(dstSize, dstSize),
ebiten.NewImage(dstSize, dstSize),*/
ebiten.NewImageWithOptions(image.Rect(0, 0, dstSize, dstSize), &ebiten.NewImageOptions{
nil,/*ebiten.NewImageWithOptions(image.Rect(0, 0, dstSize, dstSize), &ebiten.NewImageOptions{
Unmanaged: true,
}),
}),*/
ebiten.NewImageWithOptions(image.Rect(0, 0, dstSize, dstSize), &ebiten.NewImageOptions{
Unmanaged: true,
}),
@ -101,7 +101,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
indices := []uint16{0, 1, 2, 1, 2, 3}
ebiten.DrawTrianglesShaderMRT(dsts, vertices, indices, s, nil)
// Dst 0
screen.DrawImage(dsts[0], nil)
//screen.DrawImage(dsts[0], nil)
// Dst 1
opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(dstSize, 0)

View File

@ -711,10 +711,8 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
//
// When the image i is disposed, DrawTrianglesShader does nothing.
func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesShaderOptions) {
if dsts[0] == nil || dsts[0].isDisposed() {
panic("ebiten: the first destination image given to DrawTrianglesShaderMRT must not be nil or disposed")
}
var dstImgs [graphics.ShaderDstImageCount]*ui.Image
var firstDst *Image
for i, dst := range dsts {
if dst == nil {
continue
@ -723,6 +721,9 @@ func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices
if dst.isDisposed() {
panic("ebiten: the destination images given to DrawTrianglesShaderMRT must not be disposed")
}
if firstDst == nil {
firstDst = dst
}
dstImgs[i] = dst.image
}
@ -754,7 +755,7 @@ func DrawTrianglesShaderMRT(dsts [graphics.ShaderDstImageCount]*Image, vertices
blend = options.CompositeMode.blend().internalBlend()
}
dst := dsts[0]
dst := firstDst
vs := dst.ensureTmpVertices(len(vertices) * graphics.VertexFloatCount)
src := options.Images[0]
for i, v := range vertices {

View File

@ -576,12 +576,14 @@ func drawTrianglesMRT(dsts [graphics.ShaderDstImageCount]*Image, srcs [graphics.
src.backend.sourceInThisFrame = true
}
var firstDst *Image
var dstImgs [graphics.ShaderDstImageCount]*graphicscommand.Image
for i, dst := range dsts {
if dst == nil {
continue
}
dst.ensureIsolatedFromSource(backends)
firstDst = dst
dstImgs[i] = dst.backend.image
}
@ -595,7 +597,7 @@ func drawTrianglesMRT(dsts [graphics.ShaderDstImageCount]*Image, srcs [graphics.
}
}
r := dsts[0].regionWithPadding()
r := firstDst.regionWithPadding()
// TODO: Check if dstRegion does not to violate the region.
dstRegion = dstRegion.Add(r.Min)

View File

@ -330,7 +330,14 @@ func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shade
copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms)
// Set the destination texture size.
dw, dh := dsts[0].InternalSize()
var firstDst *Image
for _, dst := range dsts {
if dst != nil {
firstDst = dst
break
}
}
dw, dh := firstDst.InternalSize()
uniforms[0] = math.Float32bits(float32(dw))
uniforms[1] = math.Float32bits(float32(dh))
uniformIndex := 2

View File

@ -517,6 +517,7 @@ func (g *graphics11) removeShader(s *shader11) {
func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error {
var rtvs []*_ID3D11RenderTargetView
var dsv *_ID3D11DepthStencilView
for _, i := range dsts {
// Ignore a nil image in case of MRT
if i == nil {
@ -532,7 +533,7 @@ func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error
}
rtvs = append(rtvs, i.renderTargetView)
if !useStencil {
if !useStencil || dsv != nil {
continue
}
@ -567,12 +568,13 @@ func (g *graphics11) setAsRenderTargets(dsts []*image11, useStencil bool) error
return err
}
i.stencilView = sv
dsv = sv
}
}
g.deviceContext.OMSetRenderTargets(rtvs, dsts[0].stencilView)
g.deviceContext.OMSetRenderTargets(rtvs, dsv)
if useStencil {
g.deviceContext.ClearDepthStencilView(dsts[0].stencilView, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
g.deviceContext.ClearDepthStencilView(dsv, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
}
return nil
@ -585,7 +587,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
g.deviceContext.PSSetShaderResources(0, srvs[:])
var dsts [graphics.ShaderDstImageCount]*image11
var viewports [graphics.ShaderDstImageCount]_D3D11_VIEWPORT
var vp _D3D11_VIEWPORT
var targetCount int
firstTarget := -1
for i, id := range dstIDs {
@ -598,7 +600,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
}
dsts[i] = img
w, h := img.internalSize()
viewports[i] = _D3D11_VIEWPORT{
vp = _D3D11_VIEWPORT{
TopLeftX: 0,
TopLeftY: 0,
Width: float32(w),
@ -621,13 +623,12 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
// If the number of targets is more than one, or if the only target is the first one, then
// it is safe to assume that MRT is used.
// Also, it only matters in order to specify empty targets/viewports when not all slots are
// being filled.
// being filled, even though it's not a MRT scenario.
if targetCount > 1 || firstTarget > 0 {
targetCount = graphics.ShaderDstImageCount
}
g.deviceContext.RSSetViewports(viewports[:targetCount])
g.deviceContext.RSSetViewports([]_D3D11_VIEWPORT{vp})
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
return err
}

View File

@ -1177,7 +1177,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
var resourceBarriers []_D3D12_RESOURCE_BARRIER_Transition
var dsts [graphics.ShaderDstImageCount]*image12
var viewports [graphics.ShaderDstImageCount]_D3D12_VIEWPORT
var vp _D3D12_VIEWPORT
var targetCount int
firstTarget := -1
for i, id := range dstIDs {
@ -1190,7 +1190,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
}
dsts[i] = img
w, h := img.internalSize()
viewports[i] = _D3D12_VIEWPORT{
vp = _D3D12_VIEWPORT{
TopLeftX: 0,
TopLeftY: 0,
Width: float32(w),
@ -1231,8 +1231,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
targetCount = graphics.ShaderDstImageCount
}
g.drawCommandList.RSSetViewports(viewports[:targetCount])
g.drawCommandList.RSSetViewports([]_D3D12_VIEWPORT{vp})
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
return err
}

View File

@ -2652,7 +2652,7 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) (vec4, vec4, vec4, vec4, vec
},
}
indices := []uint16{0, 1, 2, 1, 2, 3}
t.Run("8 slots", func(t *testing.T) {
t.Run("8 locations", func(t *testing.T) {
wantColors := [8]color.RGBA{
{R: 0xff, G: 0, B: 0, A: 0xff},
{R: 0, G: 0xff, B: 0, A: 0xff},
@ -2663,9 +2663,8 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) (vec4, vec4, vec4, vec4, vec
{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
{R: 0xff, G: 0xff, B: 0xff, A: 0},
}
dsts := imgs
ebiten.DrawTrianglesShaderMRT(dsts, vertices, indices, s, nil)
for k, dst := range dsts {
ebiten.DrawTrianglesShaderMRT(imgs, vertices, indices, s, nil)
for k, dst := range imgs {
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
@ -2677,4 +2676,35 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) (vec4, vec4, vec4, vec4, vec
}
}
})
for _, img := range imgs {
img.Clear()
}
t.Run("Empty locations", func(t *testing.T) {
wantColors := [8]color.RGBA{
{},
{R: 0, G: 0xff, B: 0, A: 0xff},
{},
{R: 0xff, G: 0, B: 0xff, A: 0xff},
{},
{R: 0, G: 0xff, B: 0xff, A: 0xff},
{},
{R: 0xff, G: 0xff, B: 0xff, A: 0},
}
dsts := [8]*ebiten.Image{
nil, imgs[1], nil, imgs[3], nil, imgs[5], nil, imgs[7],
}
ebiten.DrawTrianglesShaderMRT(dsts, vertices, indices, s, nil)
for k, dst := range imgs {
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := wantColors[k]
if !sameColors(got, want, 1) {
t.Errorf("%d dst.At(%d, %d): got: %v, want: %v", k, i, j, got, want)
}
}
}
}
})
}