set up renderer
This commit is contained in:
parent
8a01e2d1b9
commit
487b402b9f
BIN
assets/gui.frag.spv
Normal file
BIN
assets/gui.frag.spv
Normal file
Binary file not shown.
BIN
assets/gui.vert.spv
Normal file
BIN
assets/gui.vert.spv
Normal file
Binary file not shown.
BIN
assets/pc-9800.ttf
Normal file
BIN
assets/pc-9800.ttf
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit 38e4e44b4dbecd8b0cbe878adb4f8da397a1ae45
|
Subproject commit c0d9de9c4e7fd33e3329745496e601431f6e2970
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 1290c5f45ac49cc5534817e8d6b0adae4ac058af
|
Subproject commit 16820bdde294d59425fda6e115ae7b2d1e532e51
|
||||||
240
src/editor/editor.d
Normal file
240
src/editor/editor.d
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
import aliases;
|
||||||
|
import util;
|
||||||
|
import platform;
|
||||||
|
import fonts;
|
||||||
|
import vulkan;
|
||||||
|
import math;
|
||||||
|
import alloc;
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
import std.exception;
|
||||||
|
|
||||||
|
const UI_COUNT = 50000;
|
||||||
|
|
||||||
|
struct Editor
|
||||||
|
{
|
||||||
|
Arena arena;
|
||||||
|
Arena temp_arena;
|
||||||
|
PlatformWindow* window;
|
||||||
|
|
||||||
|
Renderer rd;
|
||||||
|
ImageView font_atlas;
|
||||||
|
Pipeline pipeline;
|
||||||
|
DescSetLayout desc_set_layout;
|
||||||
|
DescSet desc_set;
|
||||||
|
PipelineLayout pipeline_layout;
|
||||||
|
PushConst pc;
|
||||||
|
MappedBuffer!(Vertex) m_vertex_buf;
|
||||||
|
MappedBuffer!(u32) m_index_buf;
|
||||||
|
Vertex[] vertices;
|
||||||
|
u32[] indices;
|
||||||
|
u32 ui_count;
|
||||||
|
|
||||||
|
Buffer[] buffers;
|
||||||
|
u8[][] buffer_names;
|
||||||
|
|
||||||
|
u8[] font_data;
|
||||||
|
FontFace font;
|
||||||
|
FontAtlasBuf atlas_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PushConst
|
||||||
|
{
|
||||||
|
Vec2 res;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
Vec2 dst_start;
|
||||||
|
Vec2 dst_end;
|
||||||
|
Vec2 src_start;
|
||||||
|
Vec2 src_end;
|
||||||
|
Vec4 col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cycle(Editor* ed)
|
||||||
|
{
|
||||||
|
ed.ui_count = 0;
|
||||||
|
|
||||||
|
Reset(&ed.temp_arena);
|
||||||
|
|
||||||
|
DrawText(ed, 200.0, 200.0, 16.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
|
||||||
|
BeginFrame(&ed.rd);
|
||||||
|
|
||||||
|
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
||||||
|
ed.pc.res.x = cast(f32)ext.x;
|
||||||
|
ed.pc.res.y = cast(f32)ext.y;
|
||||||
|
|
||||||
|
BeginRendering(&ed.rd);
|
||||||
|
|
||||||
|
PushConstants(&ed.rd, ed.pipeline, &ed.pc);
|
||||||
|
|
||||||
|
Bind(&ed.rd, ed.pipeline, ed.desc_set);
|
||||||
|
|
||||||
|
BindBuffers(&ed.rd, &ed.m_index_buf, &ed.m_vertex_buf);
|
||||||
|
|
||||||
|
DrawIndexed(&ed.rd, 6, ed.ui_count, 0);
|
||||||
|
|
||||||
|
FinishRendering(&ed.rd);
|
||||||
|
|
||||||
|
SubmitAndPresent(&ed.rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[]
|
||||||
|
LoadFile(Arena* arena, string name)
|
||||||
|
{
|
||||||
|
File f;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
f = File(name, "rb");
|
||||||
|
}
|
||||||
|
catch (ErrnoException e)
|
||||||
|
{
|
||||||
|
assert(false, "Unable to open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[] data = AllocArray!(u8)(arena, f.size());
|
||||||
|
f.rawRead(data);
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor
|
||||||
|
CreateEditor(PlatformWindow* window)
|
||||||
|
{
|
||||||
|
InitFreeType();
|
||||||
|
|
||||||
|
version(linux)
|
||||||
|
{
|
||||||
|
PlatformHandles handles = {
|
||||||
|
window: window.window,
|
||||||
|
conn: window.conn,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Arena arena = CreateArena(MB(32));
|
||||||
|
|
||||||
|
u8[] font_data = LoadFile(&arena, "assets/pc-9800.ttf");
|
||||||
|
FontFace font = OpenFont(font_data);
|
||||||
|
FontAtlasBuf atlas_buf = CreateAtlas(&arena, font, 16.0, 256);
|
||||||
|
|
||||||
|
Editor editor = {
|
||||||
|
window: window,
|
||||||
|
arena: arena,
|
||||||
|
temp_arena: CreateArena(MB(8)),
|
||||||
|
rd: InitRenderer(handles, MB(32), MB(16)),
|
||||||
|
font_data: font_data,
|
||||||
|
font: font,
|
||||||
|
atlas_buf: atlas_buf,
|
||||||
|
};
|
||||||
|
|
||||||
|
DescLayoutBinding[2] layout_bindings = [
|
||||||
|
{ binding: 0, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All },
|
||||||
|
{ binding: 1, descriptorType: DT.Storage, descriptorCount: 1, stageFlags: SS.All },
|
||||||
|
];
|
||||||
|
|
||||||
|
editor.desc_set_layout = CreateDescSetLayout(&editor.rd, layout_bindings);
|
||||||
|
editor.desc_set = AllocDescSet(&editor.rd, editor.desc_set_layout);
|
||||||
|
editor.pipeline_layout = CreatePipelineLayout(&editor.rd, editor.desc_set_layout, PushConst.sizeof);
|
||||||
|
|
||||||
|
Attribute[5] attributes = [
|
||||||
|
{ binding: 0, location: 0, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof },
|
||||||
|
{ binding: 0, location: 1, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof },
|
||||||
|
{ binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.src_start.offsetof },
|
||||||
|
{ binding: 0, location: 3, format: FMT.RG_F32, offset: Vertex.src_end.offsetof },
|
||||||
|
{ binding: 0, location: 4, format: FMT.RGBA_F32, offset: Vertex.col.offsetof },
|
||||||
|
];
|
||||||
|
|
||||||
|
GfxPipelineInfo ui_info = {
|
||||||
|
vertex_shader: LoadFile(&editor.temp_arena, "assets/gui.vert.spv"),
|
||||||
|
frag_shader: LoadFile(&editor.temp_arena, "assets/gui.frag.spv"),
|
||||||
|
input_rate: IR.Instance,
|
||||||
|
input_rate_stride: Vertex.sizeof,
|
||||||
|
layout: editor.pipeline_layout,
|
||||||
|
vertex_attributes: attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(CreateGraphicsPipeline(&editor.rd, &editor.pipeline, &ui_info), "Unable to build UI pipeline");
|
||||||
|
|
||||||
|
editor.m_vertex_buf = CreateMappedBuffer!(Vertex)(&editor.rd, BT.Vertex, Vertex.sizeof * UI_COUNT);
|
||||||
|
editor.m_index_buf = CreateMappedBuffer!(u32)(&editor.rd, BT.Index, u32.sizeof * UI_COUNT);
|
||||||
|
editor.vertices = editor.m_vertex_buf.data;
|
||||||
|
editor.indices = editor.m_index_buf.data;
|
||||||
|
|
||||||
|
CreateImageView(&editor.rd, &editor.font_atlas, editor.atlas_buf.atlas.width, editor.atlas_buf.atlas.height, 4, editor.atlas_buf.data);
|
||||||
|
|
||||||
|
Write(&editor.rd, editor.desc_set, &editor.font_atlas, 0, DT.Image);
|
||||||
|
|
||||||
|
Reset(&editor.temp_arena);
|
||||||
|
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawText(Editor* ed, f32 x, f32 y, f32 px, string str)
|
||||||
|
{
|
||||||
|
u8[] str_buf = (cast(u8*)str.ptr)[0 .. str.length];
|
||||||
|
DrawText(ed, x, y, px, str_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawText(Editor* ed, f32 x, f32 y, f32 px, u8[] str)
|
||||||
|
{
|
||||||
|
f32 x_pos = x;
|
||||||
|
f32 scale = px / ed.atlas_buf.atlas.size;
|
||||||
|
foreach(ch; str)
|
||||||
|
{
|
||||||
|
foreach(glyph; ed.atlas_buf.atlas.glyphs)
|
||||||
|
{
|
||||||
|
if (ch == glyph.ch)
|
||||||
|
{
|
||||||
|
Vertex* v = ed.vertices.ptr + ed.ui_count;
|
||||||
|
|
||||||
|
f32 r = glyph.plane_right * scale;
|
||||||
|
f32 l = glyph.plane_left * scale;
|
||||||
|
f32 w = r - l;
|
||||||
|
f32 h = (glyph.plane_bottom - glyph.plane_top) * scale;
|
||||||
|
f32 y_pos = glyph.plane_top * scale;
|
||||||
|
|
||||||
|
v.dst_start.x = x_pos + l;
|
||||||
|
v.dst_start.y = y + h - y_pos;
|
||||||
|
v.dst_end.x = x_pos + w + l;
|
||||||
|
v.dst_end.y = y - y_pos;
|
||||||
|
|
||||||
|
v.src_start.x = glyph.atlas_left;
|
||||||
|
v.src_start.y = glyph.atlas_top;
|
||||||
|
v.src_end.x = glyph.atlas_right;
|
||||||
|
v.src_end.y = glyph.atlas_bottom;
|
||||||
|
|
||||||
|
v.col = Vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
x_pos += glyph.advance * scale;
|
||||||
|
|
||||||
|
AddUIIndices(ed);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddUIIndices(Editor* ed)
|
||||||
|
{
|
||||||
|
ed.indices[0] = 0;
|
||||||
|
ed.indices[1] = 1;
|
||||||
|
ed.indices[2] = 2;
|
||||||
|
ed.indices[3] = 2;
|
||||||
|
ed.indices[4] = 1;
|
||||||
|
ed.indices[5] = 3;
|
||||||
|
|
||||||
|
ed.ui_count += 1;
|
||||||
|
}
|
||||||
@ -1,76 +1,20 @@
|
|||||||
import aliases;
|
import platform;
|
||||||
import std.stdio;
|
import editor;
|
||||||
import buffer;
|
|
||||||
import util;
|
|
||||||
|
|
||||||
void main(string[] argv)
|
void main(string[] argv)
|
||||||
{
|
{
|
||||||
// Inserts
|
PlatformWindow window = CreateWindow("Editor", 1920, 1080);
|
||||||
|
|
||||||
|
Editor editor = CreateEditor(&window);
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
string test_str = "This is a test string for testing the GapBuffer struct.";
|
HandleEvents(&window);
|
||||||
string test_str_2 = "This is an additional string. ";
|
if (window.close)
|
||||||
u8[] data = (cast(u8*)test_str.ptr)[0 .. test_str.length];
|
|
||||||
GapBuffer buf = CreateGapBuffer(data);
|
|
||||||
|
|
||||||
u8[] insert = (cast(u8*)test_str_2.ptr)[0 .. test_str_2.length];
|
|
||||||
Insert(&buf, insert, insert.length, 0);
|
|
||||||
|
|
||||||
u8[][] line_buf = new u8[][](1, 1024);
|
|
||||||
GetLines(&buf, line_buf, 0);
|
|
||||||
|
|
||||||
u64 count = 0;
|
|
||||||
foreach(i, ch; test_str_2)
|
|
||||||
{
|
{
|
||||||
assert(buf.data[count] == ch, "Buffer doesn't match test_str_2");
|
break;
|
||||||
count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(i, ch; test_str)
|
Cycle(&editor);
|
||||||
{
|
|
||||||
assert(buf.data[count] == ch, "Buffer doesn't match test_str");
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string test_str_3 = "not ";
|
|
||||||
insert = (cast(u8*)test_str_3.ptr)[0 .. test_str_3.length];
|
|
||||||
Insert(&buf, insert, insert.length, 8);
|
|
||||||
GetLines(&buf, line_buf, 0);
|
|
||||||
|
|
||||||
string result = "This is not an additional string. This is a test string for testing the GapBuffer struct.";
|
|
||||||
foreach(i, ch; result)
|
|
||||||
{
|
|
||||||
assert(buf.data[i] == ch, "Buffer doesn't match result");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grow Buffer
|
|
||||||
{
|
|
||||||
u8[] data;
|
|
||||||
GapBuffer buf = CreateGapBuffer(data);
|
|
||||||
|
|
||||||
foreach(i; 0 .. buf.data.length)
|
|
||||||
{
|
|
||||||
Insert(&buf, ['a'], 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(i; 0 .. 1024)
|
|
||||||
{
|
|
||||||
Insert(&buf, ['b'], 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8[][] line_buf = new u8[][](1, 8096);
|
|
||||||
GetLines(&buf, line_buf, 0);
|
|
||||||
|
|
||||||
foreach(i; 0 .. 5120)
|
|
||||||
{
|
|
||||||
if (i < 1024)
|
|
||||||
{
|
|
||||||
assert(line_buf[0][i] == 'b');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(line_buf[0][i] == 'a');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/shaders/gui.frag.glsl
Normal file
18
src/shaders/gui.frag.glsl
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
|
||||||
|
#include "gui.layout"
|
||||||
|
|
||||||
|
layout (location = 0) in struct FragDataIn {
|
||||||
|
vec4 color;
|
||||||
|
vec2 uv;
|
||||||
|
} FragData;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FragData.uv);
|
||||||
|
FragColor = FragData.color * tex_color;
|
||||||
|
}
|
||||||
9
src/shaders/gui.layout
Normal file
9
src/shaders/gui.layout
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
layout (rgba16f, set = 0, binding = 0) uniform image2D DrawImage;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 1) uniform sampler SamplerNearest;
|
||||||
|
|
||||||
|
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
|
||||||
|
|
||||||
|
layout (push_constant) uniform Constants {
|
||||||
|
vec2 res;
|
||||||
|
} PC;
|
||||||
56
src/shaders/gui.vert.glsl
Normal file
56
src/shaders/gui.vert.glsl
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
|
||||||
|
#include "gui.layout"
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 in_dst_start;
|
||||||
|
layout (location = 1) in vec2 in_dst_end;
|
||||||
|
layout (location = 2) in vec2 in_src_start;
|
||||||
|
layout (location = 3) in vec2 in_src_end;
|
||||||
|
layout (location = 4) in vec4 in_col;
|
||||||
|
|
||||||
|
layout (location = 0) out struct FragDataOut {
|
||||||
|
vec4 color;
|
||||||
|
vec2 uv;
|
||||||
|
} FragData;
|
||||||
|
|
||||||
|
vec2 Vertices[4] = vec2[4](
|
||||||
|
vec2(-1.0, +1.0),
|
||||||
|
vec2(-1.0, -1.0),
|
||||||
|
vec2(+1.0, +1.0),
|
||||||
|
vec2(+1.0, -1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
vec2 rotate(vec2 coords, float theta)
|
||||||
|
{
|
||||||
|
return mat2(cos(theta), sin(theta), -sin(theta), cos(theta)) * coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 tex_size = textureSize(sampler2D(SpriteAtlas, SamplerNearest), 0);
|
||||||
|
|
||||||
|
vec2 dst_half_size = (in_dst_end - in_dst_start) / 2;
|
||||||
|
vec2 dst_center = (in_dst_end + in_dst_start) / 2;
|
||||||
|
vec2 dst_pos = (Vertices[gl_VertexIndex] * dst_half_size + dst_center);
|
||||||
|
|
||||||
|
vec2 src_half_size = (in_src_end - in_src_start) / 2;
|
||||||
|
vec2 src_center = (in_src_end + in_src_start) / 2;
|
||||||
|
vec2 src_pos = (Vertices[gl_VertexIndex] * src_half_size + src_center);
|
||||||
|
|
||||||
|
vec2 uvs[4] = vec2[4](
|
||||||
|
vec2(in_src_start.x, in_src_start.y),
|
||||||
|
vec2(in_src_start.x, in_src_end.y),
|
||||||
|
vec2(in_src_end.x, in_src_start.y),
|
||||||
|
vec2(in_src_end.x, in_src_end.y)
|
||||||
|
);
|
||||||
|
|
||||||
|
FragData.color = in_col;
|
||||||
|
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
||||||
|
|
||||||
|
gl_Position = vec4(2 * dst_pos.x / PC.res.x - 1,
|
||||||
|
2 * dst_pos.y / PC.res.y - 1,
|
||||||
|
0,
|
||||||
|
1);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user