mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
internal/graphicsdriver/directx: reduce memory usages for writing pixels
Updates #2294 Updates #2582
This commit is contained in:
parent
264f0bad42
commit
a5a5de2f3f
@ -1005,6 +1005,10 @@ func (g *Graphics) flushCommandList(commandList *_ID3D12GraphicsCommandList) err
|
|||||||
if err := commandList.Reset(g.copyCommandAllocators[g.frameIndex], nil); err != nil {
|
if err := commandList.Reset(g.copyCommandAllocators[g.frameIndex], nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, img := range g.images {
|
||||||
|
img.releaseUploadingStagingBuffers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -1118,20 +1122,13 @@ func (g *Graphics) NewImage(width, height int) (graphicsdriver.Image, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
layouts, _, _, totalBytes := g.device.GetCopyableFootprints(&desc, 0, 1, 0)
|
|
||||||
if totalBytes == ^uint64(0) {
|
|
||||||
return nil, fmt.Errorf("directx: GetCopyableFootprints returned an invalid total bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
i := &Image{
|
i := &Image{
|
||||||
graphics: g,
|
graphics: g,
|
||||||
id: g.genNextImageID(),
|
id: g.genNextImageID(),
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
texture: t,
|
texture: t,
|
||||||
states: [frameCount]_D3D12_RESOURCE_STATES{state},
|
states: [frameCount]_D3D12_RESOURCE_STATES{state},
|
||||||
layouts: layouts,
|
|
||||||
totalBytes: totalBytes,
|
|
||||||
}
|
}
|
||||||
g.addImage(i)
|
g.addImage(i)
|
||||||
return i, nil
|
return i, nil
|
||||||
@ -1329,14 +1326,13 @@ type Image struct {
|
|||||||
height int
|
height int
|
||||||
screen bool
|
screen bool
|
||||||
|
|
||||||
states [frameCount]_D3D12_RESOURCE_STATES
|
states [frameCount]_D3D12_RESOURCE_STATES
|
||||||
texture *_ID3D12Resource
|
texture *_ID3D12Resource
|
||||||
stencil *_ID3D12Resource
|
stencil *_ID3D12Resource
|
||||||
layouts _D3D12_PLACED_SUBRESOURCE_FOOTPRINT
|
rtvDescriptorHeap *_ID3D12DescriptorHeap
|
||||||
totalBytes uint64
|
dsvDescriptorHeap *_ID3D12DescriptorHeap
|
||||||
uploadingStagingBuffer *_ID3D12Resource
|
|
||||||
rtvDescriptorHeap *_ID3D12DescriptorHeap
|
uploadingStagingBuffers []*_ID3D12Resource
|
||||||
dsvDescriptorHeap *_ID3D12DescriptorHeap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ID() graphicsdriver.ImageID {
|
func (i *Image) ID() graphicsdriver.ImageID {
|
||||||
@ -1357,10 +1353,6 @@ func (i *Image) disposeImpl() {
|
|||||||
i.rtvDescriptorHeap.Release()
|
i.rtvDescriptorHeap.Release()
|
||||||
i.rtvDescriptorHeap = nil
|
i.rtvDescriptorHeap = nil
|
||||||
}
|
}
|
||||||
if i.uploadingStagingBuffer != nil {
|
|
||||||
i.uploadingStagingBuffer.Release()
|
|
||||||
i.uploadingStagingBuffer = nil
|
|
||||||
}
|
|
||||||
if i.stencil != nil {
|
if i.stencil != nil {
|
||||||
i.stencil.Release()
|
i.stencil.Release()
|
||||||
i.stencil = nil
|
i.stencil = nil
|
||||||
@ -1375,18 +1367,6 @@ func (*Image) IsInvalidated() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ensureUploadingStagingBuffer() error {
|
|
||||||
if i.uploadingStagingBuffer != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
i.uploadingStagingBuffer, err = createBuffer(i.graphics.device, i.totalBytes, _D3D12_HEAP_TYPE_UPLOAD)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Image) ReadPixels(buf []byte, x, y, width, height int) error {
|
func (i *Image) ReadPixels(buf []byte, x, y, width, height int) error {
|
||||||
if i.screen {
|
if i.screen {
|
||||||
return errors.New("directx: Pixels cannot be called on the screen")
|
return errors.New("directx: Pixels cannot be called on the screen")
|
||||||
@ -1473,25 +1453,62 @@ func (i *Image) WritePixels(args []*graphicsdriver.WritePixelsArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := i.ensureUploadingStagingBuffer(); err != nil {
|
minX := i.width
|
||||||
|
minY := i.height
|
||||||
|
maxX := 0
|
||||||
|
maxY := 0
|
||||||
|
for _, a := range args {
|
||||||
|
if minX > a.X {
|
||||||
|
minX = a.X
|
||||||
|
}
|
||||||
|
if minY > a.Y {
|
||||||
|
minY = a.Y
|
||||||
|
}
|
||||||
|
if maxX < a.X+a.Width {
|
||||||
|
maxX = a.X + a.Width
|
||||||
|
}
|
||||||
|
if maxY < a.Y+a.Height {
|
||||||
|
maxY = a.Y + a.Height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
desc := _D3D12_RESOURCE_DESC{
|
||||||
|
Dimension: _D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
Alignment: 0,
|
||||||
|
Width: uint64(maxX - minX),
|
||||||
|
Height: uint32(maxY - minY),
|
||||||
|
DepthOrArraySize: 1,
|
||||||
|
MipLevels: 0,
|
||||||
|
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||||
|
Count: 1,
|
||||||
|
Quality: 0,
|
||||||
|
},
|
||||||
|
Layout: _D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||||
|
Flags: _D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
|
||||||
|
}
|
||||||
|
layouts, _, _, totalBytes := i.graphics.device.GetCopyableFootprints(&desc, 0, 1, 0)
|
||||||
|
uploadingStagingBuffer, err := createBuffer(i.graphics.device, totalBytes, _D3D12_HEAP_TYPE_UPLOAD)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
i.uploadingStagingBuffers = append(i.uploadingStagingBuffers, uploadingStagingBuffer)
|
||||||
|
|
||||||
if rb, ok := i.transiteState(_D3D12_RESOURCE_STATE_COPY_DEST); ok {
|
if rb, ok := i.transiteState(_D3D12_RESOURCE_STATE_COPY_DEST); ok {
|
||||||
i.graphics.copyCommandList.ResourceBarrier([]_D3D12_RESOURCE_BARRIER_Transition{rb})
|
i.graphics.copyCommandList.ResourceBarrier([]_D3D12_RESOURCE_BARRIER_Transition{rb})
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := i.uploadingStagingBuffer.Map(0, &_D3D12_RANGE{0, 0})
|
m, err := uploadingStagingBuffer.Map(0, &_D3D12_RANGE{0, 0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
i.graphics.needFlushCopyCommandList = true
|
i.graphics.needFlushCopyCommandList = true
|
||||||
|
|
||||||
srcBytes := unsafe.Slice((*byte)(unsafe.Pointer(m)), i.totalBytes)
|
srcBytes := unsafe.Slice((*byte)(unsafe.Pointer(m)), totalBytes)
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
for j := 0; j < a.Height; j++ {
|
for j := 0; j < a.Height; j++ {
|
||||||
copy(srcBytes[(a.Y+j)*int(i.layouts.Footprint.RowPitch)+a.X*4:], a.Pixels[j*a.Width*4:(j+1)*a.Width*4])
|
copy(srcBytes[((a.Y-minY)+j)*int(layouts.Footprint.RowPitch)+(a.X-minX)*4:], a.Pixels[j*a.Width*4:(j+1)*a.Width*4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1502,22 +1519,22 @@ func (i *Image) WritePixels(args []*graphicsdriver.WritePixelsArgs) error {
|
|||||||
SubresourceIndex: 0,
|
SubresourceIndex: 0,
|
||||||
}
|
}
|
||||||
src := _D3D12_TEXTURE_COPY_LOCATION_PlacedFootPrint{
|
src := _D3D12_TEXTURE_COPY_LOCATION_PlacedFootPrint{
|
||||||
pResource: i.uploadingStagingBuffer,
|
pResource: uploadingStagingBuffer,
|
||||||
Type: _D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
Type: _D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||||
PlacedFootprint: i.layouts,
|
PlacedFootprint: layouts,
|
||||||
}
|
}
|
||||||
i.graphics.copyCommandList.CopyTextureRegion_SubresourceIndex_PlacedFootPrint(
|
i.graphics.copyCommandList.CopyTextureRegion_SubresourceIndex_PlacedFootPrint(
|
||||||
&dst, uint32(a.X), uint32(a.Y), 0, &src, &_D3D12_BOX{
|
&dst, uint32(a.X), uint32(a.Y), 0, &src, &_D3D12_BOX{
|
||||||
left: uint32(a.X),
|
left: uint32(a.X - minX),
|
||||||
top: uint32(a.Y),
|
top: uint32(a.Y - minY),
|
||||||
front: 0,
|
front: 0,
|
||||||
right: uint32(a.X + a.Width),
|
right: uint32(a.X - minX + a.Width),
|
||||||
bottom: uint32(a.Y + a.Height),
|
bottom: uint32(a.Y - minY + a.Height),
|
||||||
back: 1,
|
back: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
i.uploadingStagingBuffer.Unmap(0, nil)
|
uploadingStagingBuffer.Unmap(0, nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1699,6 +1716,14 @@ func (i *Image) ensureDepthStencilView(device *_ID3D12Device) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Image) releaseUploadingStagingBuffers() {
|
||||||
|
for idx, buf := range i.uploadingStagingBuffers {
|
||||||
|
buf.Release()
|
||||||
|
i.uploadingStagingBuffers[idx] = nil
|
||||||
|
}
|
||||||
|
i.uploadingStagingBuffers = i.uploadingStagingBuffers[:0]
|
||||||
|
}
|
||||||
|
|
||||||
type stencilMode int
|
type stencilMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
Loading…
Reference in New Issue
Block a user