Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
SunSerega committed Dec 8, 2023
1 parent 21c1cac commit 98711eb
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 385 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
151 changes: 78 additions & 73 deletions Samples/OpenGLABC/Mandelbrot/0Mandelbrot.pas
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
// - "+" и "-": Гладкое изменение масштаба
// - Alt+Enter: Полноэкранный режим

//TODO Доделать ограничение view_bound
// - Сейчас его не возвращает из функции, создающей блоки
//TODO Сделать слежение за выделением памяти GPU
// - Может в OpenCLABC, но тогда выделения на стороне OpenGL надо вручную всё равно обрабатывать

//TODO Исследовать прямые концы внешнего круга - сколько там шагов и почему
// - Надо возможность приближать и возможность наводить мышку чтобы увидеть инфу

// Константы, которые можно быстро менять
uses Settings;
Expand Down Expand Up @@ -155,6 +158,7 @@ BoundUniforms = record

//TODO Использовать чтобы выдавать кол-во итераций под курсором
var mouse_pos: Vec2i;
var scale_speed := 0.0;
{$region Управление}
begin

Expand All @@ -165,22 +169,12 @@ BoundUniforms = record
// Result := pos*camera.scale + camera.pos;
// end;

f.MouseWheel += (o,e)->
begin
//TODO
// var pos := CoordsFromScreen(e.X, e.Y);
//
// var pow := 1 - Sign(e.Delta)*0.1;
// camera.scale := camera.scale * pow;
//
// camera.pos := camera.pos + (pos-CoordsFromScreen(e.X, e.Y));
end;

f.KeyDown += (o,e)->
case e.KeyCode of
Keys.Space: camera := new CameraPos(f.Width, f.Height);
end;

f.MouseWheel += (o,e)->(scale_speed += e.Delta/1000);
f.MouseMove += (o,e)->(mouse_pos := new Vec2i(e.X,e.Y));

end;
Expand All @@ -192,19 +186,13 @@ BoundUniforms = record
GL_CL_Context.Init(hdc);
gl := new OpenGL.gl(pl);

begin
var org_swap_interval := wglSwapControlEXT.Instance.GetSwapIntervalEXT;
var new_swap_interval := Settings.frame_interval;
if extra_debug_output then
$'Swap interval: {org_swap_interval}=>{new_swap_interval}'.Println;
if not wglSwapControlEXT.Instance.SwapIntervalEXT(new_swap_interval) then
raise new System.InvalidOperationException;
end;
// Реализация от NVidia тратит 16мс на вызов clGLSharingKHR.EnqueueAcquireGLObjects (при чём синхронно), если не выключить vsync
// Точнее vsync применяется и к EndFrame, и затем ещё раз к .EnqueueAcquireGLObjects
// Ну, в этой программе vsync не сдался...
if not wglSwapControlEXT.Instance.SwapIntervalEXT(0) then
raise new System.InvalidOperationException;

var sw := Stopwatch.StartNew;
var timings_max_count := 30;
// sw.Elapsed для каждого из последних timings_max_count кадров
var timings := new Queue<TimeSpan>(timings_max_count);
{$region Общие данные для всех кадров}

var s_vert_empty := InitShaderResource('Empty.vert', glShaderType.VERTEX_SHADER); {$resource Shaders/Empty.vert}

Expand All @@ -216,7 +204,6 @@ BoundUniforms = record
var uniform_view_bound, uniform_sheet_bound: BoundUniforms;
var uniform_sheet_size: integer;
var ssb_sheet: integer;
var uniform_max_steps: integer;
var choose_frag_shader := procedure(s_frag: gl_shader)->
begin
shader_prog := InitProgram(s_vert_empty, s_geom_box, s_frag);
Expand All @@ -225,19 +212,14 @@ BoundUniforms = record
uniform_sheet_bound := new BoundUniforms(shader_prog, 'sheet');
uniform_sheet_size := gl.GetUniformLocation(shader_prog, 'sheet_size');
ssb_sheet := gl.GetProgramResourceIndex(shader_prog, glProgramInterface.SHADER_STORAGE_BLOCK, 'sheet_block');
uniform_max_steps := gl.GetUniformLocation(shader_prog, 'max_steps');
end;
choose_frag_shader(s_frag_rainbow);

var cl_err_buffer := new CLArray<cardinal>(3);
var cl_uc_buffer := new CLValue<cardinal>;

var gl_sheet_buffer: gl_buffer;
gl.CreateBuffers(1, gl_sheet_buffer);
var cl_sheet_buffer: CLArray<cardinal>;
var cl_sheet_states: CLArray<byte>;
var curr_sheet_size := -1;
var Q_Init := CQNil;
var Q_Init, Q_Acquire, Q_Release: CommandQueueNil;
var ensure_sheet_buffer_size := procedure(w, h: integer)->
begin
var req_size := w*h;
Expand All @@ -249,14 +231,13 @@ BoundUniforms = record
GL_CL_Context.WrapBuffer(gl_sheet_buffer, cl_sheet_buffer);
if cl_sheet_buffer.Length <> req_size then
raise new InvalidOperationException;
cl_sheet_states := new CLArray<byte>(req_size);
//TODO Вместо этого надо сделать 2 буфера и копировать данные из предыдущего когда изменяются границы sheet
Q_Init := CQNil
+ cl_sheet_buffer.MakeCCQ.ThenFillValue(0)
+ cl_sheet_states.MakeCCQ.ThenFillValue(0)
+ cl_err_buffer.MakeCCQ.ThenFillValue(0)
+ cl_uc_buffer.MakeCCQ.ThenWriteValue(0)
+ CQNil
;
Q_Acquire := CQAcquireGL(cl_sheet_buffer);
Q_Release := CQReleaseGL(cl_sheet_buffer);
end;

// Для дебага
Expand All @@ -265,11 +246,23 @@ BoundUniforms = record
// gl.NamedBufferData(buffer_temp, new IntPtr(3*sizeof(real)), IntPtr.Zero, VertexBufferObjectUsage.DYNAMIC_READ);
// gl.BindBufferBase(BufferTarget.SHADER_STORAGE_BUFFER, 1, buffer_temp);

//TODO Calculate on-fly
var max_steps := 256;
var t_full := new UpdateTimingQueue(120);
var t_body := new UpdateTimingQueue(120);

{$endregion Общие данные для всех кадров}

while true do
begin
if scale_speed<>0 then
begin
camera.ApplyScaleSpeed(scale_speed);
scale_speed /= 2;
end;

var camera := camera; // Скопировать локально
var render_info := BlockLayer.GetLayer(camera).GetRenderInfo(camera);
BlockUpdater.SetCurrent(render_info.blocks);

var curr_frame_resized := false;
if need_resize then
begin
Expand All @@ -280,48 +273,55 @@ BoundUniforms = record

camera.Resize(w_size.Width, w_size.Height);
end;
var render_info := BlockLayer.BlocksForCurrentScale(camera);
t_body.Start;
{$region Кадр}
gl.Clear(glClearBufferMask.COLOR_BUFFER_BIT);

// clGLSharingKHR.PlatformLess.EnqueueAcquireGLObjects(q, 1, cl_temp0, 0,IntPtr.Zero,IntPtr.Zero).RaiseIfError;
//
// cl.SetKernelArg(k, 0, new UIntPtr(cl_mem.Size), cl_temp0).RaiseIfError;
// cl.EnqueueNDRangeKernel(q, k, 1, nil, |new UIntPtr(ram_temp0.Length)|, nil, 0,IntPtr.Zero,IntPtr.Zero).RaiseIfError;
//
// clGLSharingKHR.PlatformLess.EnqueueReleaseGLObjects(q, 1, cl_temp0, 0,IntPtr.Zero,IntPtr.Zero).RaiseIfError;

// cl.Finish(q);
//
// gl.GetNamedBufferSubData(gl_temp0, IntPtr.Zero, new UIntPtr(ram_temp0.Length*sizeof(integer)), ram_temp0);
// ram_temp0.Println;

var b_cy := render_info.blocks.GetLength(0);
var b_cx := render_info.blocks.GetLength(1);

var render_block_size := Settings.block_w shr render_info.mipmap_lvl;
var render_sheet_w := b_cx * render_block_size;
var render_sheet_h := b_cy * render_block_size;
var render_sheet_w := b_cx * block_w;
var render_sheet_h := b_cy * block_w;
ensure_sheet_buffer_size(render_sheet_w, render_sheet_h);

var Q_Steps := CQNil; //TODO Calculate in separate thread
var Q_Extract := CQNil;
for var b_y := 0 to b_cy-1 do
for var b_x := 0 to b_cx-1 do
begin
var b := render_info.blocks[b_y, b_x];

Q_Steps += b.CQ_MandelbrotBlockStep(max_steps, cl_uc_buffer, cl_err_buffer);

var sheet_shift := render_block_size * (b_x + b_y*render_sheet_w);
Q_Extract += b.CQ_GetData(render_info.mipmap_lvl
, new ShiftedCLArray<byte>(cl_sheet_states, sheet_shift, render_sheet_w)
, new ShiftedCLArray<cardinal>(cl_sheet_buffer, sheet_shift, render_sheet_w)
var sheet_shift := block_w * (b_x + b_y*render_sheet_w);
Q_Extract += b.CQ_GetData(
new ShiftedCLArray<cardinal>(cl_sheet_buffer, sheet_shift, render_sheet_w)
);

end;

begin
var cl_err := CLContext.Default.SyncInvoke(
Q_Init +
Q_Steps +
Q_Extract +
cl_err_buffer.MakeCCQ.ThenGetArray
);
if cl_err[0]<>0 then
$'OpenCL err at [{cl_err[1]},{cl_err[2]}]: {CLCodeExecutionError(cl_err[0])}'.Println;
end;
// var sw := Stopwatch.StartNew;
CLContext.Default.SyncInvoke(
Q_Acquire +
Q_Init +
Q_Extract +
Q_Release
);
// Println(sw.Elapsed);

uniform_view_bound.Write(render_info.view_bound);
uniform_sheet_bound.Write(render_info.sheet_bound);
gl.Uniform2i(uniform_sheet_size, render_sheet_w, render_sheet_h);
gl.BindBufferBase(glBufferTarget.SHADER_STORAGE_BUFFER, ssb_sheet, gl_sheet_buffer);
gl.Uniform1f(uniform_max_steps, max_steps);

// Для дебага
// gl.NamedBufferSubData(buffer_temp, new IntPtr(0*sizeof(real)), new IntPtr(2*sizeof(real)), mouse_pos);
Expand All @@ -332,36 +332,41 @@ BoundUniforms = record
// var temp_data := new real[1];
// gl.GetNamedBufferSubData(buffer_temp, new IntPtr(2*sizeof(real)), new IntPtr(1*sizeof(real)), temp_data);

{$endregion Кадр}
gl.Finish; //TODO Использовать обмент ивентами OpenCL/OpenGL
var err := gl.GetError;
if err.IS_ERROR then MessageBox.Show(err.ToString);

gl.Finish;
t_body.Stop;
if curr_frame_resized then
need_resize := false;
var curr_time := sw.Elapsed;

var title_parts := new List<string>;

// Для дебага
// title_parts += $'temp_data={_ObjectToString(temp_data)}';

//TODO Оттестировать и убрать
title_parts += $'rendering {b_cx} x {b_cy} blocks';
title_parts += $'sheet byte size={curr_sheet_size} (${curr_sheet_size:X})';

if timings.Count=timings_max_count then
begin
var time_diff := curr_time - timings.Dequeue;
var mspf := time_diff.TotalMilliseconds / timings_max_count;
var fps := 1000/mspf;
title_parts += $'{fps:N2} fps';
title_parts += $'{mspf:N2} mspf';
end;
timings += curr_time;
t_full.Update;
t_body.Update;
title_parts += $'{t_full.UPS:N2} fps';
title_parts += $'{t_full.MSPU:N2} full mspf';
// title_parts += $'{t_body.UPS:N2} body fps';
title_parts += $'{t_body.MSPU:N2} body mspf';

title_parts += $'pos=({camera.pos.r}; {camera.pos.i})';
title_parts += $'scale={camera.scale_fine:N3}*2^{camera.scale_pow}';
title_parts += $'pos=({camera.pos.r}; {camera.pos.i})';

f.Text := title_parts.JoinToString(', ');
f.BeginInvoke(()->
try
f.Text := title_parts.JoinToString(', ');
except
on e: Exception do
MessageBox.Show(e.ToString);
end);
EndFrame;
end;

Expand Down
Loading

0 comments on commit 98711eb

Please sign in to comment.