safely stage video frames
This commit is contained in:
@@ -3,17 +3,20 @@ package renderer
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mxl-player/internal/sdl"
|
||||
"unsafe"
|
||||
|
||||
"mxl-player/internal/sdl"
|
||||
|
||||
"github.com/christerso/vulkan-go/vk"
|
||||
)
|
||||
|
||||
// Raises by swapchain creation, whem windos is minimized
|
||||
var ErrMinimized = errors.New("window minimized")
|
||||
|
||||
// ErrOutOfDate is returned by DrawFrame when the swapchain needs recreation.
|
||||
var ErrOutOfDate = errors.New("swapchain out of date")
|
||||
var (
|
||||
// Raises by swapchain creation, whem windos is minimized
|
||||
ErrMinimized = errors.New("window minimized")
|
||||
// ErrOutOfDate is returned by DrawFrame when the swapchain needs recreation.
|
||||
ErrOutOfDate = errors.New("swapchain out of date")
|
||||
ErrInvalidVideoFrame = errors.New("invalid video frame")
|
||||
)
|
||||
|
||||
// shader push-constants block
|
||||
type PushConstants struct {
|
||||
@@ -392,6 +395,64 @@ func (r *Renderer) RecreateBuffers(newSize vk.DeviceSize) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Renderer) StageFrame(
|
||||
payload []byte,
|
||||
width uint32,
|
||||
height uint32,
|
||||
stride uint32,
|
||||
) error {
|
||||
frameSize, err := validateFramePayload(len(payload), width, height, stride)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if frameSize != r.FrameSize() {
|
||||
// RecreateBuffers waits for the device to become idle.
|
||||
if err := r.RecreateBuffers(frameSize); err != nil {
|
||||
return fmt.Errorf("resize video buffers: %w", err)
|
||||
}
|
||||
} else {
|
||||
// The previous submitted frame may still read the mapped staging buffer.
|
||||
if err := r.dev.WaitFence(r.inFlight, ^uint64(0)); err != nil {
|
||||
return fmt.Errorf("wait before staging video: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
vk.CopyToMapped(
|
||||
r.StagingMapped(),
|
||||
payload[:int(frameSize)],
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFramePayload(
|
||||
payloadLen int,
|
||||
width uint32,
|
||||
height uint32,
|
||||
stride uint32,
|
||||
) (vk.DeviceSize, error) {
|
||||
if width == 0 || height == 0 || stride == 0 {
|
||||
return 0, fmt.Errorf(
|
||||
"%w: dimensions=%dx%d stride=%d",
|
||||
ErrInvalidVideoFrame,
|
||||
width,
|
||||
height,
|
||||
stride,
|
||||
)
|
||||
}
|
||||
|
||||
requiredSize := uint64(stride) * uint64(height)
|
||||
if payloadLen < 0 || requiredSize > uint64(payloadLen) {
|
||||
return 0, fmt.Errorf(
|
||||
"%w: payload=%d required=%d",
|
||||
ErrInvalidVideoFrame,
|
||||
payloadLen,
|
||||
requiredSize,
|
||||
)
|
||||
}
|
||||
return vk.DeviceSize(requiredSize), nil
|
||||
}
|
||||
|
||||
// DrawFrame acquires an image, records commands, submits, and presents.
|
||||
// Returns ErrOutOfDate if the swapchain needs recreation
|
||||
func (r *Renderer) DrawFrame(videoW, videoH, stride uint32) error {
|
||||
|
||||
Reference in New Issue
Block a user