mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-11 19:48:54 +01:00
Directx 12 mrt working - 1st iteration
This commit is contained in:
parent
2faf8a551d
commit
7dd4aa9150
@ -127,7 +127,7 @@ func main() {
|
|||||||
ebiten.SetVsyncEnabled(false)
|
ebiten.SetVsyncEnabled(false)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -625,6 +625,7 @@ func (g *graphics11) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
|
|||||||
if targetCount > 1 || firstTarget > 0 {
|
if targetCount > 1 || firstTarget > 0 {
|
||||||
targetCount = graphics.ShaderDstImageCount
|
targetCount = graphics.ShaderDstImageCount
|
||||||
}
|
}
|
||||||
|
|
||||||
g.deviceContext.RSSetViewports(viewports[:targetCount])
|
g.deviceContext.RSSetViewports(viewports[:targetCount])
|
||||||
|
|
||||||
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
|
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
|
||||||
|
@ -1082,7 +1082,78 @@ func (g *graphics12) NewShader(program *shaderir.Program) (graphicsdriver.Shader
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdriver.ImageID, srcs [graphics.ShaderSrcImageCount]graphicsdriver.ImageID, shaderID graphicsdriver.ShaderID, dstRegions []graphicsdriver.DstRegion, indexOffset int, blend graphicsdriver.Blend, uniforms []uint32, fillRule graphicsdriver.FillRule) error {
|
func (g *graphics12) setAsRenderTargets(dsts []*image12, useStencil bool) error {
|
||||||
|
var rtvs []_D3D12_CPU_DESCRIPTOR_HANDLE
|
||||||
|
var dsvPtr *_D3D12_CPU_DESCRIPTOR_HANDLE
|
||||||
|
|
||||||
|
for i, img := range dsts {
|
||||||
|
// Ignore a nil image in case of MRT
|
||||||
|
if img == nil {
|
||||||
|
_ = i
|
||||||
|
rtvBase, err := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rtv := rtvBase
|
||||||
|
rtv.Offset(int32(g.frameIndex), g.rtvDescriptorSize)
|
||||||
|
rtvs = append(rtvs, rtv)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := img.ensureRenderTargetView(g.device); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if img.screen {
|
||||||
|
if useStencil {
|
||||||
|
return fmt.Errorf("directx: stencils are not available on the screen framebuffer")
|
||||||
|
}
|
||||||
|
|
||||||
|
rtvBase, err := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rtv := rtvBase
|
||||||
|
rtv.Offset(int32(g.frameIndex), g.rtvDescriptorSize)
|
||||||
|
rtvs = append(rtvs, rtv)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rtvBase, err := img.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rtv := rtvBase
|
||||||
|
rtvs = append(rtvs, rtv)
|
||||||
|
|
||||||
|
if !useStencil || dsvPtr != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := img.ensureDepthStencilView(g.device); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dsv, err := img.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dsvPtr = &dsv
|
||||||
|
}
|
||||||
|
|
||||||
|
if !useStencil {
|
||||||
|
g.drawCommandList.OMSetRenderTargets(rtvs, false, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
g.drawCommandList.OMSetStencilRef(0)
|
||||||
|
g.drawCommandList.OMSetRenderTargets(rtvs, false, dsvPtr)
|
||||||
|
g.drawCommandList.ClearDepthStencilView(*dsvPtr, _D3D12_CLEAR_FLAG_STENCIL, 0, 0, nil)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdriver.ImageID, srcIDs [graphics.ShaderSrcImageCount]graphicsdriver.ImageID, shaderID graphicsdriver.ShaderID, dstRegions []graphicsdriver.DstRegion, indexOffset int, blend graphicsdriver.Blend, uniforms []uint32, fillRule graphicsdriver.FillRule) error {
|
||||||
if shaderID == graphicsdriver.InvalidShaderID {
|
if shaderID == graphicsdriver.InvalidShaderID {
|
||||||
return fmt.Errorf("directx: shader ID is invalid")
|
return fmt.Errorf("directx: shader ID is invalid")
|
||||||
}
|
}
|
||||||
@ -1103,20 +1174,46 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
|
|||||||
g.pipelineStates.releaseConstantBuffers(g.frameIndex)
|
g.pipelineStates.releaseConstantBuffers(g.frameIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := g.images[dstIDs[0]] // TODO: handle array
|
|
||||||
var resourceBarriers []_D3D12_RESOURCE_BARRIER_Transition
|
var resourceBarriers []_D3D12_RESOURCE_BARRIER_Transition
|
||||||
if rb, ok := dst.transiteState(_D3D12_RESOURCE_STATE_RENDER_TARGET); ok {
|
|
||||||
resourceBarriers = append(resourceBarriers, rb)
|
|
||||||
}
|
|
||||||
|
|
||||||
var srcImages [graphics.ShaderSrcImageCount]*image12
|
var dsts [graphics.ShaderDstImageCount]*image12
|
||||||
for i, srcID := range srcs {
|
var viewports [graphics.ShaderDstImageCount]_D3D12_VIEWPORT
|
||||||
src := g.images[srcID]
|
var targetCount int
|
||||||
if src == nil {
|
firstTarget := -1
|
||||||
|
for i, id := range dstIDs {
|
||||||
|
img := g.images[id]
|
||||||
|
if img == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
srcImages[i] = src
|
if firstTarget == -1 {
|
||||||
if rb, ok := src.transiteState(_D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); ok {
|
firstTarget = i
|
||||||
|
}
|
||||||
|
dsts[i] = img
|
||||||
|
w, h := img.internalSize()
|
||||||
|
viewports[i] = _D3D12_VIEWPORT{
|
||||||
|
TopLeftX: 0,
|
||||||
|
TopLeftY: 0,
|
||||||
|
Width: float32(w),
|
||||||
|
Height: float32(h),
|
||||||
|
MinDepth: _D3D12_MIN_DEPTH,
|
||||||
|
MaxDepth: _D3D12_MAX_DEPTH,
|
||||||
|
}
|
||||||
|
|
||||||
|
if rb, ok := img.transiteState(_D3D12_RESOURCE_STATE_RENDER_TARGET); ok {
|
||||||
|
resourceBarriers = append(resourceBarriers, rb)
|
||||||
|
}
|
||||||
|
|
||||||
|
targetCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
var srcs [graphics.ShaderSrcImageCount]*image12
|
||||||
|
for i, srcID := range srcIDs {
|
||||||
|
img := g.images[srcID]
|
||||||
|
if img == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
srcs[i] = img
|
||||||
|
if rb, ok := img.transiteState(_D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); ok {
|
||||||
resourceBarriers = append(resourceBarriers, rb)
|
resourceBarriers = append(resourceBarriers, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1125,25 +1222,26 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
|
|||||||
g.drawCommandList.ResourceBarrier(resourceBarriers)
|
g.drawCommandList.ResourceBarrier(resourceBarriers)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := dst.setAsRenderTarget(g.drawCommandList, g.device, fillRule != graphicsdriver.FillAll); err != nil {
|
// 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.
|
||||||
|
usesMRT := targetCount > 1 || firstTarget > 0
|
||||||
|
if usesMRT {
|
||||||
|
targetCount = graphics.ShaderDstImageCount
|
||||||
|
}
|
||||||
|
|
||||||
|
g.drawCommandList.RSSetViewports(viewports[:targetCount])
|
||||||
|
|
||||||
|
if err := g.setAsRenderTargets(dsts[:targetCount], fillRule != graphicsdriver.FillAll); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
shader := g.shaders[shaderID]
|
shader := g.shaders[shaderID]
|
||||||
adjustedUniforms := adjustUniforms(shader.uniformTypes, shader.uniformOffsets, uniforms)
|
adjustedUniforms := adjustUniforms(shader.uniformTypes, shader.uniformOffsets, uniforms)
|
||||||
|
|
||||||
w, h := dst.internalSize()
|
|
||||||
g.needFlushDrawCommandList = true
|
g.needFlushDrawCommandList = true
|
||||||
g.drawCommandList.RSSetViewports([]_D3D12_VIEWPORT{
|
|
||||||
{
|
|
||||||
TopLeftX: 0,
|
|
||||||
TopLeftY: 0,
|
|
||||||
Width: float32(w),
|
|
||||||
Height: float32(h),
|
|
||||||
MinDepth: _D3D12_MIN_DEPTH,
|
|
||||||
MaxDepth: _D3D12_MAX_DEPTH,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
g.drawCommandList.IASetPrimitiveTopology(_D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
|
g.drawCommandList.IASetPrimitiveTopology(_D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
|
||||||
g.drawCommandList.IASetVertexBuffers(0, []_D3D12_VERTEX_BUFFER_VIEW{
|
g.drawCommandList.IASetVertexBuffers(0, []_D3D12_VERTEX_BUFFER_VIEW{
|
||||||
{
|
{
|
||||||
@ -1158,7 +1256,7 @@ func (g *graphics12) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphics
|
|||||||
Format: _DXGI_FORMAT_R32_UINT,
|
Format: _DXGI_FORMAT_R32_UINT,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := g.pipelineStates.drawTriangles(g.device, g.drawCommandList, g.frameIndex, dst.screen, srcImages, shader, dstRegions, adjustedUniforms, blend, indexOffset, fillRule); err != nil {
|
if err := g.pipelineStates.drawTriangles(g.device, g.drawCommandList, g.frameIndex, !usesMRT && dsts[firstTarget].screen, srcs, shader, dstRegions, adjustedUniforms, blend, indexOffset, fillRule); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +510,90 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||||
RenderTargetWriteMask: writeMask,
|
RenderTargetWriteMask: writeMask,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlendEnable: 1,
|
||||||
|
LogicOpEnable: 0,
|
||||||
|
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,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SampleMask: math.MaxUint32,
|
SampleMask: math.MaxUint32,
|
||||||
@ -532,9 +616,10 @@ func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3D
|
|||||||
NumElements: uint32(len(inputElementDescsForDX12)),
|
NumElements: uint32(len(inputElementDescsForDX12)),
|
||||||
},
|
},
|
||||||
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||||
NumRenderTargets: 1,
|
NumRenderTargets: graphics.ShaderDstImageCount,
|
||||||
RTVFormats: [8]_DXGI_FORMAT{
|
RTVFormats: [8]_DXGI_FORMAT{
|
||||||
rtvFormat,
|
rtvFormat, rtvFormat, rtvFormat, rtvFormat,
|
||||||
|
rtvFormat, rtvFormat, rtvFormat, rtvFormat,
|
||||||
},
|
},
|
||||||
DSVFormat: dsvFormat,
|
DSVFormat: dsvFormat,
|
||||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||||
|
Loading…
Reference in New Issue
Block a user