330 lines
9.2 KiB
Go
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,
|
|
},
|
|
},
|
|
})
|
|
}
|