Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions demos/wm/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ static void new_win(wm_t wm, wm_win_t win, char const* app_id, void* data) {

float x = 0;

static void redraw(wm_t wm, void* raw_image, void* data) {
static void redraw(wm_t wm, void* raw_image, uint32_t x_res, uint32_t y_res, void* data) {
(void) wm;

state_t* const s = data;

WGPUTexture const tex = aqua_wgpuRenderTextureFromVkImage(s->wgpu_ctx, s->device, raw_image, WGPUTextureFormat_RGBA8Snorm, 1280, 720);
WGPUTexture const tex = aqua_wgpuRenderTextureFromVkImage(s->wgpu_ctx, s->device, raw_image, WGPUTextureFormat_RGBA8Snorm, x_res, y_res);
WGPUTextureView const view = aqua_wgpuTextureCreateView(s->wgpu_ctx, tex, NULL);

WGPUQueue const queue = aqua_wgpuDeviceGetQueue(s->wgpu_ctx, s->device);
Expand Down
15 changes: 12 additions & 3 deletions lib/bindings/go/wm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ package aqua

#include <aqua/wm.h>

extern void go_lib_bindings_wm_redraw_cb(wm_t wm, void* raw_vk_image, void* raw_vk_cmd_pool, void* raw_vk_cmd_buf, void* data);
extern void go_lib_bindings_wm_redraw_cb(
wm_t wm,
void* raw_vk_image,
void* raw_vk_cmd_pool,
void* raw_vk_cmd_buf,
uint32_t x_res,
uint32_t y_res,
void* data
);
extern void go_lib_bindings_wm_new_win_cb(wm_t wm, wm_win_t win, char* app_id, void* data);
extern void go_lib_bindings_wm_redraw_win_cb(wm_t wm, wm_win_t win, uint32_t x_res, uint32_t y_res, void* raw_image, void* data);
extern void go_lib_bindings_wm_destroy_win_cb(wm_t wm, wm_win_t win, void* data);
Expand Down Expand Up @@ -122,20 +130,21 @@ func (w *Wm) WinNotifyMouseButton(win WmWin, time uint32, pressed bool, button u
C.wm_win_notify_mouse_button(w.wm, C.wm_win_t(win), C.uint32_t(time), C.bool(pressed), C.uint32_t(button))
}

type WmRedrawCb func(raw_vk_image unsafe.Pointer, raw_vk_cmd_pool unsafe.Pointer, raw_vk_cmd_buf unsafe.Pointer)
type WmRedrawCb func(raw_vk_image unsafe.Pointer, raw_vk_cmd_pool unsafe.Pointer, raw_vk_cmd_buf unsafe.Pointer, x_res, y_res uint32)

//export go_lib_bindings_wm_redraw_cb
func go_lib_bindings_wm_redraw_cb(
_ C.wm_t,
raw_vk_image unsafe.Pointer,
raw_vk_cmd_pool unsafe.Pointer,
raw_vk_cmd_buf unsafe.Pointer,
x_res, y_res C.uint32_t,
data unsafe.Pointer,
) {
handle := (cgo.Handle)(data)

if cb, ok := handle.Value().(WmRedrawCb); ok {
cb(raw_vk_image, raw_vk_cmd_pool, raw_vk_cmd_buf)
cb(raw_vk_image, raw_vk_cmd_pool, raw_vk_cmd_buf, uint32(x_res), uint32(y_res))
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/wm.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ typedef struct __attribute__((packed)) {
uint64_t raw_vk_image;
uint64_t raw_vk_cmd_pool;
uint64_t raw_vk_cmd_buf;
uint32_t x_res;
uint32_t y_res;
} intr_redraw_t;

typedef struct __attribute__((packed)) {
Expand Down Expand Up @@ -543,6 +545,8 @@ static void interrupt(kos_notif_t const* notif, void* data) {
(void*) (uintptr_t) redraw->raw_vk_image,
(void*) (uintptr_t) redraw->raw_vk_cmd_pool,
(void*) (uintptr_t) redraw->raw_vk_cmd_buf,
redraw->x_res,
redraw->y_res,
wm->redraw_data
);
}
Expand Down
12 changes: 11 additions & 1 deletion lib/wm.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,19 @@ typedef uint64_t wm_win_t;
* @param raw_vk_image Raw Vulkan image which we have to draw to.
* @param raw_vk_cmd_pool Raw Vulkan command pool the {@link raw_vk_cmd_buf} command buffer was created on.
* @param raw_vk_cmd_buf Raw Vulkan command buffer we must use for rendering.
* @param x_res The image's X resolution.
* @param y_res The image's Y resolution.
* @param data User-defined data passed to the callback. This is set when registering the callback with {@link wm_register_redraw_cb}.
*/
typedef void (*wm_redraw_cb_t)(wm_t wm, void* raw_vk_image, void* raw_vk_cmd_pool, void* raw_vk_cmd_buf, void* data);
typedef void (*wm_redraw_cb_t)(
wm_t wm,
void* raw_vk_image,
void* raw_vk_cmd_pool,
void* raw_vk_cmd_buf,
uint32_t x_res,
uint32_t y_res,
void* data
);

/**
* WM new window event callback.
Expand Down
50 changes: 26 additions & 24 deletions vdev/ui/wgpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ type WgpuBackend struct {
texture_pipeline *TexturePipeline
frost_pipeline *FrostPipeline

frost WgpuBackendFrost
last_frost *Div
frost WgpuBackendFrost
}

type IWgpuBackendData interface {
Expand Down Expand Up @@ -251,7 +252,7 @@ func GoUiBackendWgpuInit(
//export GoUiBackendWgpuRender
func GoUiBackendWgpuRender(
ui_raw C.uintptr_t,
frame_raw unsafe.Pointer,
frame_raw unsafe.Pointer, // XXX This cannot have wgpu.TextureUsageCopyDst on it!
cmd_enc_raw unsafe.Pointer,
x_res, y_res uint32,
) {
Expand Down Expand Up @@ -292,24 +293,38 @@ func GoUiBackendWgpuRender(
ui.dirty = false
}

// Get view for our frame (swapchain texture).

frame_tex := b.dev.TextureFromRaw(frame_raw)
frame_view, err := frame_tex.CreateView(nil)
if err != nil {
panic(err)
}
defer frame_view.Release()

// Find last frost element.

b.last_frost = b.find_last_frost(&ui.root)

// Create initial render pass.
// All passes should use LoadOpLoad except for the first.
// If there are no frost elements, we can render to the swapchain texture directly.

initial_view := frame_view
if b.last_frost != nil {
initial_view = b.render_buf.view
}

b.cmd_enc = b.dev.CommandEncoderFromRaw(cmd_enc_raw)

b.render_pass = b.cmd_enc.BeginRenderPass(&wgpu.RenderPassDescriptor{
Label: "Initial render pass",
ColorAttachments: []wgpu.RenderPassColorAttachment{
{
View: b.render_buf.view,
LoadOp: wgpu.LoadOpClear,
StoreOp: wgpu.StoreOpStore,
ClearValue: wgpu.Color{
R: 0.0,
G: 0.0,
B: 0.0,
A: 0.5,
},
View: initial_view,
LoadOp: wgpu.LoadOpClear,
StoreOp: wgpu.StoreOpStore,
ClearValue: wgpu.Color{R: 0.0, G: 0.0, B: 0.0, A: 0.5},
},
},
})
Expand All @@ -322,17 +337,4 @@ func GoUiBackendWgpuRender(

b.render_pass.End()
b.render_pass.Release()

// Write last render buffer texture to the final texture view.
// This is kind of inefficient for the last render, because we are doing one extra copy for no reason.
// I guess a solution would be to look forward to see if there are any other frost elements, and just use the swapchain buffer as the new render buffer if there are none left.
// Also, we could fold frost elements together by checking if they are overlapping or not - if not, we render them all in the same render pass.

final_tex := b.dev.TextureFromRaw(frame_raw)

b.cmd_enc.CopyTextureToTexture(b.render_buf.tex.AsImageCopy(), final_tex.AsImageCopy(), &wgpu.Extent3D{
Width: x_res,
Height: y_res,
DepthOrArrayLayers: 1,
})
}
29 changes: 29 additions & 0 deletions vdev/ui/wgpu_frost.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,35 @@ func (d *WgpuBackendDivData) create_frost(b *WgpuBackend, w, h uint32) error {
return nil
}

// Find the last frost div to be rendered.
// This is needed so we ping-pong to the final output render buffer instead of one of the intermediate render buffers once the last frost element is encountered.
func (b *WgpuBackend) find_last_frost(d *Div) *Div {
// Check if any of our children (which are gonna be in front of us so last to be rendered) are frosted.
// This is a DFS that goes front to back.

for i := len(d.children) - 1; i >= 0; i-- {
child := d.children[i]

if child.ElemBase().kind == ElemKindDiv {
frost := b.find_last_frost(child.(*Div))

if frost != nil {
return frost
}
}
}

// See if we are frosted ourselves.

if d.do_frost() {
return d
}

// Otherwise, we have nothing to do with frost.

return nil
}

func (b *WgpuBackend) encounter_frost(d *Div) {
f := b.frost

Expand Down
7 changes: 7 additions & 0 deletions vdev/wm/wm.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ typedef struct __attribute__((packed)) {
uint64_t raw_vk_image;
uint64_t raw_vk_cmd_pool;
uint64_t raw_vk_cmd_buf;
uint32_t x_res;
uint32_t y_res;
} redraw_intr_t;

typedef struct __attribute__((packed)) {
Expand Down Expand Up @@ -272,9 +274,14 @@ static void output_frame_notify(struct wl_listener* listener, void* data) {

LOG_V(cls, "Take care of rendering.");

// XXX AAAAAAAAAAAAAAAAAAAAAAAAAA
wlr_render_pass_submit(wlr_renderer_begin_buffer_pass(wm->wlr_renderer, buf, NULL));

redraw_intr_t intr = {
.intr = INTR_REDRAW,
.raw_vk_image = (uintptr_t) attribs.image,
.x_res = output->output->width,
.y_res = output->output->height,
};

interrupt(wm, sizeof intr, &intr);
Expand Down
Loading