zworld/engine/renderapi/command/buffer.go
2024-01-14 22:56:06 +08:00

330 lines
9.2 KiB
Go

package command
import (
"reflect"
"unsafe"
"zworld/engine/renderapi/buffer"
"zworld/engine/renderapi/descriptor"
"zworld/engine/renderapi/device"
"zworld/engine/renderapi/framebuffer"
"zworld/engine/renderapi/image"
"zworld/engine/renderapi/pipeline"
"zworld/engine/renderapi/renderpass"
"github.com/vkngwrapper/core/v2/core1_0"
)
type Buffer interface {
device.Resource[core1_0.CommandBuffer]
Reset()
Begin()
End()
CmdCopyBuffer(src, dst buffer.T, regions ...core1_0.BufferCopy)
CmdBindGraphicsPipeline(pipe pipeline.T)
CmdBindGraphicsDescriptor(sets descriptor.Set)
CmdBindVertexBuffer(vtx buffer.T, offset int)
CmdBindIndexBuffers(idx buffer.T, offset int, kind core1_0.IndexType)
CmdDraw(vertexCount, instanceCount, firstVertex, firstInstance int)
CmdDrawIndexed(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance int)
CmdBeginRenderPass(pass renderpass.T, framebuffer framebuffer.T)
CmdNextSubpass()
CmdEndRenderPass()
CmdSetViewport(x, y, w, h int) core1_0.Viewport
CmdSetScissor(x, y, w, h int) core1_0.Rect2D
CmdPushConstant(stages core1_0.ShaderStageFlags, offset int, value any)
CmdImageBarrier(srcMask, dstMask core1_0.PipelineStageFlags, image image.T, oldLayout, newLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags)
CmdCopyBufferToImage(source buffer.T, dst image.T, layout core1_0.ImageLayout)
CmdCopyImageToBuffer(src image.T, srcLayout core1_0.ImageLayout, aspect core1_0.ImageAspectFlags, dst buffer.T)
CmdConvertImage(src image.T, srcLayout core1_0.ImageLayout, dst image.T, dstLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags)
CmdCopyImage(src image.T, srcLayout core1_0.ImageLayout, dst image.T, dstLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags)
}
type buf struct {
ptr core1_0.CommandBuffer
pool core1_0.CommandPool
device device.T
// cached bindings
pipeline pipeline.T
vertex bufferBinding
index bufferBinding
scissor core1_0.Rect2D
viewport core1_0.Viewport
}
type bufferBinding struct {
buffer core1_0.Buffer
offset int
indexType core1_0.IndexType
}
func newBuffer(device device.T, pool core1_0.CommandPool, ptr core1_0.CommandBuffer) Buffer {
return &buf{
ptr: ptr,
pool: pool,
device: device,
}
}
func (b *buf) Ptr() core1_0.CommandBuffer {
return b.ptr
}
func (b *buf) Destroy() {
b.ptr.Free()
b.ptr = nil
}
func (b *buf) Reset() {
b.ptr.Reset(core1_0.CommandBufferResetReleaseResources)
}
func (b *buf) Begin() {
if _, err := b.ptr.Begin(core1_0.CommandBufferBeginInfo{}); err != nil {
panic(err)
}
}
func (b *buf) End() {
b.ptr.End()
}
func (b *buf) CmdCopyBuffer(src, dst buffer.T, regions ...core1_0.BufferCopy) {
if len(regions) == 0 {
regions = []core1_0.BufferCopy{
{
SrcOffset: 0,
DstOffset: 0,
Size: src.Size(),
},
}
}
if src.Ptr() == nil || dst.Ptr() == nil {
panic("copy to/from null buffer")
}
b.ptr.CmdCopyBuffer(src.Ptr(), dst.Ptr(), regions)
}
func (b *buf) CmdBindGraphicsPipeline(pipe pipeline.T) {
// if b.pipeline != nil && b.pipeline.Ptr() == pipe.Ptr() {
// return
// }
b.ptr.CmdBindPipeline(core1_0.PipelineBindPointGraphics, pipe.Ptr())
b.pipeline = pipe
}
func (b *buf) CmdBindGraphicsDescriptor(set descriptor.Set) {
if b.pipeline == nil {
panic("bind graphics pipeline first")
}
b.ptr.CmdBindDescriptorSets(core1_0.PipelineBindPointGraphics, b.pipeline.Layout().Ptr(), 0, []core1_0.DescriptorSet{set.Ptr()}, nil)
}
func (b *buf) CmdBindVertexBuffer(vtx buffer.T, offset int) {
binding := bufferBinding{buffer: vtx.Ptr(), offset: offset}
if b.vertex == binding {
return
}
b.ptr.CmdBindVertexBuffers(0, []core1_0.Buffer{vtx.Ptr()}, []int{offset})
b.vertex = binding
}
func (b *buf) CmdBindIndexBuffers(idx buffer.T, offset int, kind core1_0.IndexType) {
binding := bufferBinding{buffer: idx.Ptr(), offset: offset, indexType: kind}
if b.index == binding {
return
}
b.ptr.CmdBindIndexBuffer(idx.Ptr(), offset, kind)
b.index = binding
}
func (b *buf) CmdDraw(vertexCount, instanceCount, firstVertex, firstInstance int) {
b.ptr.CmdDraw(vertexCount, instanceCount, uint32(firstVertex), uint32(firstInstance))
}
func (b *buf) CmdDrawIndexed(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance int) {
b.ptr.CmdDrawIndexed(indexCount, instanceCount, uint32(firstIndex), vertexOffset, uint32(firstInstance))
}
func (b *buf) CmdBeginRenderPass(pass renderpass.T, framebuffer framebuffer.T) {
clear := pass.Clear()
w, h := framebuffer.Size()
b.ptr.CmdBeginRenderPass(core1_0.SubpassContentsInline, core1_0.RenderPassBeginInfo{
RenderPass: pass.Ptr(),
Framebuffer: framebuffer.Ptr(),
RenderArea: core1_0.Rect2D{
Offset: core1_0.Offset2D{},
Extent: core1_0.Extent2D{
Width: w,
Height: h,
},
},
ClearValues: clear,
})
b.CmdSetViewport(0, 0, w, h)
b.CmdSetScissor(0, 0, w, h)
}
func (b *buf) CmdEndRenderPass() {
b.ptr.CmdEndRenderPass()
}
func (b *buf) CmdNextSubpass() {
b.ptr.CmdNextSubpass(core1_0.SubpassContentsInline)
}
func (b *buf) CmdSetViewport(x, y, w, h int) core1_0.Viewport {
prev := b.viewport
b.viewport = core1_0.Viewport{
X: float32(x),
Y: float32(y),
Width: float32(w),
Height: float32(h),
MinDepth: 0,
MaxDepth: 1,
}
b.ptr.CmdSetViewport([]core1_0.Viewport{
b.viewport,
})
return prev
}
func (b *buf) CmdSetScissor(x, y, w, h int) core1_0.Rect2D {
prev := b.scissor
b.scissor = core1_0.Rect2D{
Offset: core1_0.Offset2D{
X: x,
Y: y,
},
Extent: core1_0.Extent2D{
Width: w,
Height: h,
},
}
b.ptr.CmdSetScissor([]core1_0.Rect2D{
b.scissor,
})
return prev
}
func (b *buf) CmdPushConstant(stages core1_0.ShaderStageFlags, offset int, value any) {
if b.pipeline == nil {
panic("bind graphics pipeline first")
}
// this is awkward
// ptr := reflect.ValueOf(value).UnsafePointer()
size := reflect.ValueOf(value).Elem().Type().Size()
ptr := reflect.ValueOf(value).UnsafePointer()
valueBytes := make([]byte, size)
device.Memcpy(unsafe.Pointer(&valueBytes[0]), ptr, int(size))
b.ptr.CmdPushConstants(b.pipeline.Layout().Ptr(), stages, offset, valueBytes)
}
func (b *buf) CmdImageBarrier(srcMask, dstMask core1_0.PipelineStageFlags, image image.T, oldLayout, newLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags) {
b.ptr.CmdPipelineBarrier(core1_0.PipelineStageFlags(srcMask), core1_0.PipelineStageFlags(dstMask), core1_0.DependencyFlags(0), nil, nil, []core1_0.ImageMemoryBarrier{
{
OldLayout: oldLayout,
NewLayout: newLayout,
Image: image.Ptr(),
SubresourceRange: core1_0.ImageSubresourceRange{
AspectMask: core1_0.ImageAspectFlags(aspects),
LayerCount: 1,
LevelCount: 1,
},
SrcAccessMask: core1_0.AccessMemoryRead | core1_0.AccessMemoryWrite,
DstAccessMask: core1_0.AccessMemoryRead | core1_0.AccessMemoryWrite,
},
})
}
func (b *buf) CmdCopyBufferToImage(source buffer.T, dst image.T, layout core1_0.ImageLayout) {
b.ptr.CmdCopyBufferToImage(source.Ptr(), dst.Ptr(), layout, []core1_0.BufferImageCopy{
{
ImageSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectColor,
LayerCount: 1,
},
ImageExtent: core1_0.Extent3D{
Width: dst.Width(),
Height: dst.Height(),
Depth: 1,
},
},
})
}
func (b *buf) CmdCopyImageToBuffer(src image.T, srcLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags, dst buffer.T) {
b.ptr.CmdCopyImageToBuffer(src.Ptr(), srcLayout, dst.Ptr(), []core1_0.BufferImageCopy{
{
ImageSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectFlags(aspects),
LayerCount: 1,
},
ImageExtent: core1_0.Extent3D{
Width: src.Width(),
Height: src.Height(),
Depth: 1,
},
},
})
}
func (b *buf) CmdConvertImage(src image.T, srcLayout core1_0.ImageLayout, dst image.T, dstLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags) {
b.ptr.CmdBlitImage(src.Ptr(), srcLayout, dst.Ptr(), dstLayout, []core1_0.ImageBlit{
{
SrcOffsets: [2]core1_0.Offset3D{
{X: 0, Y: 0, Z: 0},
{X: src.Width(), Y: src.Height(), Z: 1},
},
SrcSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectFlags(aspects),
MipLevel: 0,
BaseArrayLayer: 0,
LayerCount: 1,
},
DstOffsets: [2]core1_0.Offset3D{
{X: 0, Y: 0, Z: 0},
{X: dst.Width(), Y: dst.Height(), Z: 1},
},
DstSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectFlags(aspects),
MipLevel: 0,
BaseArrayLayer: 0,
LayerCount: 1,
},
},
}, core1_0.FilterNearest)
}
func (b *buf) CmdCopyImage(src image.T, srcLayout core1_0.ImageLayout, dst image.T, dstLayout core1_0.ImageLayout, aspects core1_0.ImageAspectFlags) {
b.ptr.CmdCopyImage(src.Ptr(), srcLayout, dst.Ptr(), dstLayout, []core1_0.ImageCopy{
{
SrcOffset: core1_0.Offset3D{X: 0, Y: 0, Z: 0},
SrcSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectFlags(aspects),
MipLevel: 0,
BaseArrayLayer: 0,
LayerCount: 1,
},
DstOffset: core1_0.Offset3D{X: 0, Y: 0, Z: 0},
DstSubresource: core1_0.ImageSubresourceLayers{
AspectMask: core1_0.ImageAspectFlags(aspects),
MipLevel: 0,
BaseArrayLayer: 0,
LayerCount: 1,
},
Extent: core1_0.Extent3D{
Width: dst.Width(),
Height: dst.Height(),
Depth: 1,
},
},
})
}