Compare commits
3 Commits
282f78baae
...
d4c86e7ac5
| Author | SHA1 | Date | |
|---|---|---|---|
| d4c86e7ac5 | |||
| e324e47896 | |||
| 0081887f19 |
Binary file not shown.
BIN
assets/shaders/full_screen_triangle.vert.spv
Normal file
BIN
assets/shaders/full_screen_triangle.vert.spv
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
assets/shaders/oit.frag.spv
Normal file
BIN
assets/shaders/oit.frag.spv
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
209
src/gears/game.d
209
src/gears/game.d
@ -2,16 +2,20 @@ import aliases;
|
|||||||
import includes;
|
import includes;
|
||||||
import renderer : Destroy;
|
import renderer : Destroy;
|
||||||
import renderer;
|
import renderer;
|
||||||
|
import vulkan;
|
||||||
import util;
|
import util;
|
||||||
|
import alloc;
|
||||||
import platform;
|
import platform;
|
||||||
import math;
|
import math;
|
||||||
import core.stdc.math : cosf, sinf;
|
import core.stdc.math : cosf, sinf;
|
||||||
|
import std.algorithm.sorting;
|
||||||
|
|
||||||
f32 g_DELTA;
|
f32 g_DELTA;
|
||||||
|
|
||||||
struct Game
|
struct Game
|
||||||
{
|
{
|
||||||
Renderer rd;
|
Renderer rd;
|
||||||
|
Arena frame_arena;
|
||||||
|
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
|
|
||||||
@ -19,6 +23,10 @@ struct Game
|
|||||||
Pipeline triangle_pipeline;
|
Pipeline triangle_pipeline;
|
||||||
Pipeline compute_pipeline;
|
Pipeline compute_pipeline;
|
||||||
Pipeline ui_pipeline;
|
Pipeline ui_pipeline;
|
||||||
|
Pipeline oit_pipeline;
|
||||||
|
|
||||||
|
ImageView draw_image, depth_image;
|
||||||
|
ImageView aux_image;
|
||||||
|
|
||||||
GlobalUniforms globals;
|
GlobalUniforms globals;
|
||||||
PushConst pc;
|
PushConst pc;
|
||||||
@ -27,15 +35,21 @@ struct Game
|
|||||||
|
|
||||||
Camera camera;
|
Camera camera;
|
||||||
|
|
||||||
Model model;
|
Model tree;
|
||||||
}
|
Model rock;
|
||||||
|
Model magic_rock;
|
||||||
|
Model log;
|
||||||
|
Model stump;
|
||||||
|
|
||||||
|
SLList!(Model) models;
|
||||||
|
}
|
||||||
|
|
||||||
Game
|
Game
|
||||||
InitGame(PlatformWindow* window)
|
InitGame(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
Game g = {
|
Game g = {
|
||||||
rd: InitRenderer(window),
|
rd: InitRenderer(window),
|
||||||
|
frame_arena: CreateArena(MB(16)),
|
||||||
window: window,
|
window: window,
|
||||||
timer: CreateTimer(),
|
timer: CreateTimer(),
|
||||||
globals: {
|
globals: {
|
||||||
@ -45,14 +59,24 @@ InitGame(PlatformWindow* window)
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Extent ext = GetExtent(&g.rd);
|
||||||
|
|
||||||
|
CreateImageView(&g.rd, &g.draw_image, ext.w, ext.h, GetDrawImageFormat(&g.rd), IU.Draw, false);
|
||||||
|
CreateImageView(&g.rd, &g.depth_image, ext.w, ext.h, FMT.D_SF32, IU.Depth, true);
|
||||||
|
CreateImageView(&g.rd, &g.aux_image, ext.w, ext.h, FMT.R_U32, IU.Storage);
|
||||||
|
|
||||||
GfxPipelineInfo triangle_info = {
|
GfxPipelineInfo triangle_info = {
|
||||||
vertex_shader: "shaders/triangle.vert.spv",
|
vertex_shader: "shaders/triangle.vert.spv",
|
||||||
frag_shader: "shaders/triangle.frag.spv",
|
frag_shader: "shaders/triangle.frag.spv",
|
||||||
|
draw_image: &g.draw_image,
|
||||||
|
depth_image: &g.depth_image,
|
||||||
};
|
};
|
||||||
|
|
||||||
GfxPipelineInfo ui_info = {
|
GfxPipelineInfo ui_info = {
|
||||||
vertex_shader: "shaders/gui.vert.spv",
|
vertex_shader: "shaders/gui.vert.spv",
|
||||||
frag_shader: "shaders/gui.frag.spv",
|
frag_shader: "shaders/gui.frag.spv",
|
||||||
|
draw_image: &g.draw_image,
|
||||||
|
depth_image: &g.depth_image,
|
||||||
input_rate: IR.Instance,
|
input_rate: IR.Instance,
|
||||||
input_rate_stride: UIVertex.sizeof,
|
input_rate_stride: UIVertex.sizeof,
|
||||||
vertex_attributes: [
|
vertex_attributes: [
|
||||||
@ -66,6 +90,8 @@ InitGame(PlatformWindow* window)
|
|||||||
GfxPipelineInfo pbr_info = {
|
GfxPipelineInfo pbr_info = {
|
||||||
vertex_shader: "shaders/pbr.vert.spv",
|
vertex_shader: "shaders/pbr.vert.spv",
|
||||||
frag_shader: "shaders/pbr.frag.spv",
|
frag_shader: "shaders/pbr.frag.spv",
|
||||||
|
draw_image: &g.draw_image,
|
||||||
|
depth_image: &g.depth_image,
|
||||||
input_rate_stride: Vertex.sizeof,
|
input_rate_stride: Vertex.sizeof,
|
||||||
vertex_attributes: [
|
vertex_attributes: [
|
||||||
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
|
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
|
||||||
@ -76,6 +102,13 @@ InitGame(PlatformWindow* window)
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GfxPipelineInfo oit_info = {
|
||||||
|
vertex_shader: "shaders/full_screen_triangle.vert.spv",
|
||||||
|
frag_shader: "shaders/oit.frag.spv",
|
||||||
|
draw_image: &g.draw_image,
|
||||||
|
depth_image: &g.depth_image,
|
||||||
|
};
|
||||||
|
|
||||||
CompPipelineInfo gradient_info = {
|
CompPipelineInfo gradient_info = {
|
||||||
shader: "shaders/gradient.comp.spv",
|
shader: "shaders/gradient.comp.spv",
|
||||||
};
|
};
|
||||||
@ -83,18 +116,85 @@ InitGame(PlatformWindow* window)
|
|||||||
g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info);
|
g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info);
|
||||||
g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info);
|
g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info);
|
||||||
g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info);
|
g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info);
|
||||||
|
g.oit_pipeline = BuildGfxPipeline(&g.rd, &oit_info);
|
||||||
g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info);
|
g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info);
|
||||||
|
|
||||||
PrintShader(&g.rd, &g.pbr_pipeline, VK_SHADER_STAGE_VERTEX_BIT);
|
PrintShader(&g.rd, &g.pbr_pipeline, VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
|
|
||||||
g.model = LoadModel(&g.rd, "models/Tree01.m3d");
|
g.rock = LoadModel(&g.rd, "models/BigRock01.m3d");
|
||||||
|
g.tree = LoadModel(&g.rd, "models/Tree01.m3d");
|
||||||
|
g.magic_rock = LoadModel(&g.rd, "models/MagicRock01.m3d");
|
||||||
|
g.log = LoadModel(&g.rd, "models/Log01.m3d");
|
||||||
|
g.stump = LoadModel(&g.rd, "models/Stump01.m3d");
|
||||||
|
|
||||||
|
SetClearColor(&g.rd, Vec4(0.3, 0.5, 0.9, 1.0));
|
||||||
|
|
||||||
|
ClearColorEnabled(&g.rd, true);
|
||||||
|
|
||||||
|
assert(g.aux_image.view != null);
|
||||||
|
|
||||||
|
UpdateAuxImage(&g.rd, &g.aux_image);
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Copy(Model* dst, Model* src)
|
||||||
|
{
|
||||||
|
dst.vertex_buffer = src.vertex_buffer;
|
||||||
|
dst.index_buffer = src.index_buffer;
|
||||||
|
dst.parts = src.parts;
|
||||||
|
dst.materials = src.materials;
|
||||||
|
dst.textures = src.textures;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ProcessInputs(Game* g, Camera* cam)
|
ProcessInputs(Game* g, Camera* cam)
|
||||||
{
|
{
|
||||||
|
foreach(i; 0 .. g.window.inputs.count)
|
||||||
|
{
|
||||||
|
InputEvent event = g.window.inputs.events[i];
|
||||||
|
switch(event.key)
|
||||||
|
{
|
||||||
|
case Input.One:
|
||||||
|
{
|
||||||
|
Node!(Model)* node = Alloc!(Node!(Model));
|
||||||
|
Copy(&node.value, &g.tree);
|
||||||
|
node.value.pos = cam.pos;
|
||||||
|
PushFront(&g.models, node, null);
|
||||||
|
} break;
|
||||||
|
case Input.Two:
|
||||||
|
{
|
||||||
|
Node!(Model)* node = Alloc!(Node!(Model));
|
||||||
|
Copy(&node.value, &g.rock);
|
||||||
|
node.value.pos = cam.pos;
|
||||||
|
PushFront(&g.models, node, null);
|
||||||
|
} break;
|
||||||
|
case Input.Three:
|
||||||
|
{
|
||||||
|
Node!(Model)* node = Alloc!(Node!(Model));
|
||||||
|
Copy(&node.value, &g.magic_rock);
|
||||||
|
node.value.pos = cam.pos;
|
||||||
|
PushFront(&g.models, node, null);
|
||||||
|
} break;
|
||||||
|
case Input.Four:
|
||||||
|
{
|
||||||
|
Node!(Model)* node = Alloc!(Node!(Model));
|
||||||
|
Copy(&node.value, &g.log);
|
||||||
|
node.value.pos = cam.pos;
|
||||||
|
PushFront(&g.models, node, null);
|
||||||
|
} break;
|
||||||
|
case Input.Five:
|
||||||
|
{
|
||||||
|
Node!(Model)* node = Alloc!(Node!(Model));
|
||||||
|
Copy(&node.value, &g.stump);
|
||||||
|
node.value.pos = cam.pos;
|
||||||
|
PushFront(&g.models, node, null);
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HandleInputs(cam, &g.window.inputs);
|
HandleInputs(cam, &g.window.inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,16 +203,32 @@ Cycle(Game* g)
|
|||||||
{
|
{
|
||||||
g_DELTA = DeltaTime(&g.timer);
|
g_DELTA = DeltaTime(&g.timer);
|
||||||
|
|
||||||
|
Reset(&g.frame_arena);
|
||||||
|
|
||||||
ProcessInputs(g, &g.camera);
|
ProcessInputs(g, &g.camera);
|
||||||
|
|
||||||
|
ResizeDrawImageIfNeeded(&g.rd, &g.draw_image);
|
||||||
|
ResizeDrawImageIfNeeded(&g.rd, &g.depth_image);
|
||||||
|
ResizeDrawImageIfNeeded(&g.rd, &g.aux_image);
|
||||||
|
|
||||||
|
UpdateAuxImage(&g.rd, &g.aux_image);
|
||||||
|
|
||||||
|
//Sort(g, g.camera.pos, &g.model);
|
||||||
|
|
||||||
//Update(g, &g.camera);
|
//Update(g, &g.camera);
|
||||||
|
|
||||||
Update(&g.camera);
|
Update(&g.camera);
|
||||||
|
|
||||||
BeginFrame(&g.rd);
|
BeginFrame(&g.rd);
|
||||||
|
|
||||||
|
PrepAuxImage(&g.rd.vk, &g.aux_image);
|
||||||
|
|
||||||
Bind(&g.rd, &g.compute_pipeline);
|
Bind(&g.rd, &g.compute_pipeline);
|
||||||
|
|
||||||
|
ClearColor(&g.rd, &g.aux_image, Vec4(0.0));
|
||||||
|
|
||||||
|
ImageBarrier(&g.rd);
|
||||||
|
|
||||||
Extent ext = GetExtent(&g.rd);
|
Extent ext = GetExtent(&g.rd);
|
||||||
f32 aspect = (cast(f32)ext.x) / (cast(f32)ext.y);
|
f32 aspect = (cast(f32)ext.x) / (cast(f32)ext.y);
|
||||||
Mat4 projection = Perspective(90.0, aspect, 10000.0, 0.1);
|
Mat4 projection = Perspective(90.0, aspect, 10000.0, 0.1);
|
||||||
@ -123,36 +239,56 @@ Cycle(Game* g)
|
|||||||
g.globals.res.y = ext.y;
|
g.globals.res.y = ext.y;
|
||||||
SetUniform(&g.rd, &g.globals);
|
SetUniform(&g.rd, &g.globals);
|
||||||
|
|
||||||
//DrawRect(&g.rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0));
|
BeginRendering(&g.rd, &g.draw_image, &g.depth_image);
|
||||||
|
|
||||||
//PrepComputeDrawImage(&g.rd);
|
|
||||||
|
|
||||||
//Dispatch(&g.rd);
|
|
||||||
|
|
||||||
BeginRender(&g.rd);
|
|
||||||
|
|
||||||
Bind(&g.rd, &g.ui_pipeline);
|
Bind(&g.rd, &g.ui_pipeline);
|
||||||
|
|
||||||
BindUIBuffers(&g.rd);
|
BindUIBuffers(&g.rd);
|
||||||
|
|
||||||
//DrawUI(&g.rd);
|
|
||||||
|
|
||||||
Bind(&g.rd, &g.triangle_pipeline);
|
Bind(&g.rd, &g.triangle_pipeline);
|
||||||
|
|
||||||
//Draw(&g.rd, 3, 1);
|
|
||||||
|
|
||||||
Bind(&g.rd, &g.pbr_pipeline);
|
Bind(&g.rd, &g.pbr_pipeline);
|
||||||
|
|
||||||
g.pc.model_matrix = Mat4Identity();
|
g.pc.model_matrix = Mat4Identity();
|
||||||
DrawModel(g, &g.model);
|
|
||||||
|
|
||||||
FinishFrame(&g.rd);
|
Node!(Model)* model = g.models.first;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawModel(g, &model.value);
|
||||||
|
model = model.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ImageBarrier(&g.rd);
|
||||||
|
|
||||||
|
Bind(&g.rd, &g.oit_pipeline);
|
||||||
|
|
||||||
|
Draw(&g.rd, 3, 1);
|
||||||
|
*/
|
||||||
|
|
||||||
|
FinishRendering(&g.rd);
|
||||||
|
|
||||||
|
//ImageBarrier(&g.rd);
|
||||||
|
|
||||||
|
//BeginRendering(&g.rd, &g.draw_image, &g.depth_image);
|
||||||
|
|
||||||
|
|
||||||
|
//FinishRendering(&g.rd);
|
||||||
|
|
||||||
|
Submit(&g.rd, &g.draw_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
DrawModel(Game* g, Model* model)
|
DrawModel(Game* g, Model* model)
|
||||||
{
|
{
|
||||||
BindBuffers(&g.rd, &model.index_buffer, &model.vertex_buffer);
|
BindBuffers(&g.rd, &model.index_buffer, &model.vertex_buffer);
|
||||||
|
g.pc.model_matrix = Mat4Identity();
|
||||||
|
Translate(&g.pc.model_matrix, model.pos);
|
||||||
foreach(i, part; model.parts)
|
foreach(i, part; model.parts)
|
||||||
{
|
{
|
||||||
g.pc.mat_id = part.mat;
|
g.pc.mat_id = part.mat;
|
||||||
@ -169,13 +305,25 @@ Destroy(Game* g)
|
|||||||
Destroy(&g.rd, &g.triangle_pipeline);
|
Destroy(&g.rd, &g.triangle_pipeline);
|
||||||
Destroy(&g.rd, &g.ui_pipeline);
|
Destroy(&g.rd, &g.ui_pipeline);
|
||||||
Destroy(&g.rd, &g.compute_pipeline);
|
Destroy(&g.rd, &g.compute_pipeline);
|
||||||
|
|
||||||
|
Node!(Model)* model = g.models.first;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Destroy(&g.rd, &model.value);
|
||||||
|
model = model.next;
|
||||||
|
}
|
||||||
Destroy(&g.rd);
|
Destroy(&g.rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Camera
|
struct Camera
|
||||||
{
|
{
|
||||||
Vec3 velocity = Vec3(0.0);
|
Vec3 velocity = Vec3(0.0);
|
||||||
Vec3 pos = Vec3(0.0, 0.0, 5.0);
|
Vec3 pos = Vec3(0.0, 0.0, 2.0);
|
||||||
f32 pitch = 0.0;
|
f32 pitch = 0.0;
|
||||||
f32 yaw = 0.0;
|
f32 yaw = 0.0;
|
||||||
}
|
}
|
||||||
@ -183,8 +331,6 @@ struct Camera
|
|||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
HandleInputs(Camera* cam, Inputs* inputs)
|
HandleInputs(Camera* cam, Inputs* inputs)
|
||||||
{
|
{
|
||||||
Logf("%.04f %.04f", cam.pitch, cam.yaw);
|
|
||||||
|
|
||||||
foreach(i; 0 .. inputs.count)
|
foreach(i; 0 .. inputs.count)
|
||||||
{
|
{
|
||||||
InputEvent event = inputs.events[i];
|
InputEvent event = inputs.events[i];
|
||||||
@ -231,3 +377,28 @@ Update(Camera* cam)
|
|||||||
Vec4 pos = rotation * Vec4(cam.velocity * 0.5 * g_DELTA, 0.0);
|
Vec4 pos = rotation * Vec4(cam.velocity * 0.5 * g_DELTA, 0.0);
|
||||||
cam.pos += pos.xyz;
|
cam.pos += pos.xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Sort(Game* g, Vec3 pos, Model* model)
|
||||||
|
{
|
||||||
|
f32[] lengths = AllocArray!(f32)(&g.frame_arena, model.positions.length);
|
||||||
|
|
||||||
|
foreach(i; 0 .. lengths.length)
|
||||||
|
{
|
||||||
|
model.pos_indices[i] = cast(u32)i;
|
||||||
|
lengths.ptr[i] = fabs(Norm(&pos) - Norm(model.positions.ptr + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
makeIndex!("a < b")(lengths, model.pos_indices);
|
||||||
|
|
||||||
|
Logf("%s", model.positions.length);
|
||||||
|
|
||||||
|
foreach(i, v; model.pos_indices)
|
||||||
|
{
|
||||||
|
model.indices[i+0] = cast(u32)((3*v)+0);
|
||||||
|
model.indices[i+1] = cast(u32)((3*v)+1);
|
||||||
|
model.indices[i+2] = cast(u32)((3*v)+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateIndexBuffer(&g.rd, model);
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ import core.stdc.string : memcpy;
|
|||||||
// 2. Set up VK_AMD_shader_info
|
// 2. Set up VK_AMD_shader_info
|
||||||
// 3. Determine how to better handle inputs
|
// 3. Determine how to better handle inputs
|
||||||
// 4. Make assets loaded from the disk in debug mode
|
// 4. Make assets loaded from the disk in debug mode
|
||||||
|
// 5. Set up multisampling
|
||||||
|
// 6. Remove renderer.d and just move the interface into vulkan.d
|
||||||
|
// 7. Remove dynamic rendering
|
||||||
|
|
||||||
void main(string[] argv)
|
void main(string[] argv)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import assets;
|
|||||||
import util;
|
import util;
|
||||||
import alloc;
|
import alloc;
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers;
|
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRendering, SetUniform, PrepComputeDrawImage, Dispatch, SubmitAndPresent, BeginFrame, WaitIdle, PushConstants, BindBuffers, SetClearColor, ImageBarrier, CreateImageView, GetDrawImageFormat, FinishRendering, UpdateAuxImage, ClearColor, SubmitAndPresent;
|
||||||
import assets;
|
import assets;
|
||||||
import std.math.traits : isNaN;
|
import std.math.traits : isNaN;
|
||||||
import util : Logf;
|
import util : Logf;
|
||||||
@ -25,6 +25,20 @@ enum InputRate : int
|
|||||||
|
|
||||||
alias IR = InputRate;
|
alias IR = InputRate;
|
||||||
|
|
||||||
|
enum ImageUsage : VkImageUsageFlagBits
|
||||||
|
{
|
||||||
|
None = cast(VkImageUsageFlagBits)0,
|
||||||
|
Draw = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
Depth = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||||
|
Texture = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
Convert = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
Storage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
Swapchain = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias IU = ImageUsage;
|
||||||
|
|
||||||
enum Format : VkFormat
|
enum Format : VkFormat
|
||||||
{
|
{
|
||||||
UINT = VK_FORMAT_R32_UINT,
|
UINT = VK_FORMAT_R32_UINT,
|
||||||
@ -33,24 +47,35 @@ enum Format : VkFormat
|
|||||||
RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT,
|
RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT,
|
||||||
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
|
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT,
|
RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT,
|
||||||
|
R_U32 = VK_FORMAT_R32_UINT,
|
||||||
|
RG_U32 = VK_FORMAT_R32G32_UINT,
|
||||||
RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM,
|
RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB,
|
RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB,
|
||||||
|
D_SF32 = VK_FORMAT_D32_SFLOAT,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias FMT = Format;
|
alias FMT = Format;
|
||||||
|
|
||||||
enum BufferType : int
|
enum BufferType : VkBufferUsageFlagBits
|
||||||
{
|
{
|
||||||
None = 0,
|
None = cast(VkBufferUsageFlagBits)0,
|
||||||
Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
Vertex = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
Index = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||||
Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias BT = BufferType;
|
alias BT = BufferType;
|
||||||
|
|
||||||
|
enum ImageLayout : VkImageLayout
|
||||||
|
{
|
||||||
|
Undefined = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
General = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
ColorAttach = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
}
|
||||||
|
|
||||||
struct GlobalUniforms
|
struct GlobalUniforms
|
||||||
{
|
{
|
||||||
Mat4 view_matrix = Mat4Identity();
|
Mat4 view_matrix = Mat4Identity();
|
||||||
@ -85,35 +110,24 @@ struct Specialization
|
|||||||
|
|
||||||
struct GfxPipelineInfo
|
struct GfxPipelineInfo
|
||||||
{
|
{
|
||||||
string vertex_shader;
|
string vertex_shader;
|
||||||
string frag_shader;
|
string frag_shader;
|
||||||
InputRate input_rate;
|
InputRate input_rate;
|
||||||
u32 input_rate_stride;
|
u32 input_rate_stride;
|
||||||
Attribute[] vertex_attributes;
|
Attribute[] vertex_attributes;
|
||||||
Specialization vert_spec;
|
Specialization vert_spec;
|
||||||
Specialization frag_spec;
|
Specialization frag_spec;
|
||||||
|
ImageView* draw_image;
|
||||||
|
ImageView* depth_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompPipelineInfo
|
struct CompPipelineInfo
|
||||||
{
|
{
|
||||||
string shader;
|
string shader;
|
||||||
Specialization spec;
|
Specialization spec;
|
||||||
VkPipelineLayout *layout;
|
VkPipelineLayout *layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Renderer
|
|
||||||
{
|
|
||||||
Arena arena;
|
|
||||||
Arena temp_arena;
|
|
||||||
|
|
||||||
Vulkan vk;
|
|
||||||
PlatformWindow* window;
|
|
||||||
|
|
||||||
UIVertex[] ui_vertex_buf;
|
|
||||||
u32[] ui_index_buf;
|
|
||||||
u32 ui_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PushConst
|
struct PushConst
|
||||||
{
|
{
|
||||||
Mat4 model_matrix;
|
Mat4 model_matrix;
|
||||||
@ -124,6 +138,8 @@ struct Extent
|
|||||||
{
|
{
|
||||||
u32 x;
|
u32 x;
|
||||||
u32 y;
|
u32 y;
|
||||||
|
alias x w;
|
||||||
|
alias y h;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIVertex
|
struct UIVertex
|
||||||
@ -161,6 +177,58 @@ struct Model
|
|||||||
|
|
||||||
Buffer[] materials;
|
Buffer[] materials;
|
||||||
ImageView[] textures;
|
ImageView[] textures;
|
||||||
|
|
||||||
|
Vec3[] positions;
|
||||||
|
u32[] pos_indices;
|
||||||
|
u32[] indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Image
|
||||||
|
{
|
||||||
|
VkImage image;
|
||||||
|
VmaAllocation alloc;
|
||||||
|
Format format;
|
||||||
|
VkImageLayout layout;
|
||||||
|
u32 w;
|
||||||
|
u32 h;
|
||||||
|
bool depth_image;
|
||||||
|
ImageUsage usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BufferView
|
||||||
|
{
|
||||||
|
Buffer base;
|
||||||
|
VkBufferView view;
|
||||||
|
|
||||||
|
alias base this;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImageView
|
||||||
|
{
|
||||||
|
Image base;
|
||||||
|
VkImageView view;
|
||||||
|
|
||||||
|
alias base this;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
VkBuffer buffer;
|
||||||
|
VmaAllocation alloc;
|
||||||
|
u64 size;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Renderer
|
||||||
|
{
|
||||||
|
Arena arena;
|
||||||
|
Arena temp_arena;
|
||||||
|
|
||||||
|
Vulkan vk;
|
||||||
|
PlatformWindow* window;
|
||||||
|
|
||||||
|
UIVertex[] ui_vertex_buf;
|
||||||
|
u32[] ui_index_buf;
|
||||||
|
u32 ui_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer
|
Renderer
|
||||||
@ -206,12 +274,6 @@ DrawUI(Renderer* rd)
|
|||||||
DrawIndexed(rd, 6, rd.ui_count, 0);
|
DrawIndexed(rd, 6, rd.ui_count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
|
||||||
FinishFrame(Renderer* rd)
|
|
||||||
{
|
|
||||||
FinishFrame(&rd.vk);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
Dispatch(Renderer* rd)
|
Dispatch(Renderer* rd)
|
||||||
{
|
{
|
||||||
@ -231,9 +293,9 @@ SetUniform(Renderer* rd, GlobalUniforms* uniforms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
BeginRender(Renderer* rd)
|
BeginRendering(Renderer* rd, ImageView* draw_image, ImageView* depth_image)
|
||||||
{
|
{
|
||||||
BeginRender(&rd.vk);
|
BeginRendering(&rd.vk, draw_image, depth_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
@ -260,6 +322,12 @@ Bind(Renderer* rd, Pipeline* pipeline)
|
|||||||
Bind(&rd.vk, pipeline);
|
Bind(&rd.vk, pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UpdateIndexBuffer(Renderer* rd, Model* model)
|
||||||
|
{
|
||||||
|
assert(Transfer(&rd.vk, &model.index_buffer, model.indices), "UpdateIndexBuffer failure");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
|
DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
|
||||||
{
|
{
|
||||||
@ -371,6 +439,7 @@ LoadModel(Renderer* rd, string name)
|
|||||||
case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break;
|
case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break;
|
||||||
case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break;
|
case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break;
|
||||||
case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break;
|
case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break;
|
||||||
|
case m3dp_d: mats[i].alpha = m3d.material[i].prop[j].value.fnum; break;
|
||||||
case m3dp_map_Kd:
|
case m3dp_map_Kd:
|
||||||
{
|
{
|
||||||
mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
@ -386,7 +455,12 @@ LoadModel(Renderer* rd, string name)
|
|||||||
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
mats[i].specular_has_texture = true;
|
mats[i].specular_has_texture = true;
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
case m3dp_map_D:
|
||||||
|
{
|
||||||
|
mats[i].alpha_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
|
mats[i].alpha_has_texture = true;
|
||||||
|
} break;
|
||||||
|
default: Logf("Unsupported property: %s", M3DPropToStr(m3d.material[i].prop[j].type)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,8 +512,10 @@ LoadModel(Renderer* rd, string name)
|
|||||||
|
|
||||||
m3dv_t* vertex;
|
m3dv_t* vertex;
|
||||||
|
|
||||||
u32[] indices = AllocArray!(u32)(&rd.temp_arena, m3d.numface * 3);
|
u32[] indices = AllocArray!(u32)(&rd.arena, m3d.numface * 3);
|
||||||
Vertex[] vertices = AllocArray!(Vertex)(&rd.temp_arena, m3d.numface * 3);
|
Vertex[] vertices = AllocArray!(Vertex)(&rd.temp_arena, m3d.numface * 3);
|
||||||
|
Vec3[] positions = AllocArray!(Vec3)(&rd.arena, m3d.numface);
|
||||||
|
u32[] pos_indices = AllocArray!(u32)(&rd.arena, m3d.numface);
|
||||||
|
|
||||||
foreach(i; 0 .. m3d.numface)
|
foreach(i; 0 .. m3d.numface)
|
||||||
{
|
{
|
||||||
@ -475,6 +551,11 @@ LoadModel(Renderer* rd, string name)
|
|||||||
indices[i0] = i0;
|
indices[i0] = i0;
|
||||||
indices[i1] = i1;
|
indices[i1] = i1;
|
||||||
indices[i2] = i2;
|
indices[i2] = i2;
|
||||||
|
|
||||||
|
Vec3 center = (vertices[i0].pos + vertices[i1].pos + vertices[i2].pos) / 3.0;
|
||||||
|
|
||||||
|
positions[i] = center;
|
||||||
|
pos_indices[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u64 i = 0; i < indices.length; i += 3)
|
for(u64 i = 0; i < indices.length; i += 3)
|
||||||
@ -520,11 +601,55 @@ LoadModel(Renderer* rd, string name)
|
|||||||
WriteDescriptors(&rd.vk, DT.Material, model.materials, mat_lookup);
|
WriteDescriptors(&rd.vk, DT.Material, model.materials, mat_lookup);
|
||||||
WriteDescriptors(&rd.vk, DT.SampledImage, model.textures, tex_lookup);
|
WriteDescriptors(&rd.vk, DT.SampledImage, model.textures, tex_lookup);
|
||||||
|
|
||||||
|
model.positions = positions;
|
||||||
|
model.indices = indices;
|
||||||
|
model.pos_indices = pos_indices;
|
||||||
|
|
||||||
Reset(&rd.temp_arena);
|
Reset(&rd.temp_arena);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
M3DPropToStr(u8 type)
|
||||||
|
{
|
||||||
|
string result = "Unknown";
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case m3dp_Kd: result = "Diffuse"; break;
|
||||||
|
case m3dp_Ka: result = "Ambient"; break;
|
||||||
|
case m3dp_Ks: result = "Specular Color"; break;
|
||||||
|
case m3dp_Ns: result = "Specular Exponent"; break;
|
||||||
|
case m3dp_Ke: result = "Emissive"; break;
|
||||||
|
case m3dp_Tf: result = "Transmission"; break;
|
||||||
|
case m3dp_Km: result = "Bump Strength"; break;
|
||||||
|
case m3dp_d: result = "Alpha"; break;
|
||||||
|
case m3dp_il: result = "Illumination"; break;
|
||||||
|
case m3dp_Pr: result = "Roughness"; break;
|
||||||
|
case m3dp_Pm: result = "Metallic"; break;
|
||||||
|
case m3dp_Ps: result = "Sheen"; break;
|
||||||
|
case m3dp_Ni: result = "Refraction"; break;
|
||||||
|
case m3dp_Nt: result = "Face Thickness"; break;
|
||||||
|
case m3dp_map_Kd: result = "Diffuse Texture"; break;
|
||||||
|
case m3dp_map_Ka: result = "Ambient Texture"; break;
|
||||||
|
case m3dp_map_Ks: result = "Specular Texture"; break;
|
||||||
|
case m3dp_map_Ns: result = "Specular Exponent Texture"; break;
|
||||||
|
case m3dp_map_Ke: result = "Emissive Texture"; break;
|
||||||
|
case m3dp_map_Tf: result = "Transmission Texture"; break;
|
||||||
|
case m3dp_map_Km: result = "Bump Map"; break;
|
||||||
|
case m3dp_map_D: result = "Alpha Map"; break;
|
||||||
|
case m3dp_map_N: result = "Normal Map"; break;
|
||||||
|
case m3dp_map_Pr: result = "Roughness Map"; break;
|
||||||
|
case m3dp_map_Pm: result = "Metallic Map"; break;
|
||||||
|
case m3dp_map_Ps: result = "Sheen Map"; break;
|
||||||
|
case m3dp_map_Ni: result = "Refraction Map"; break;
|
||||||
|
case m3dp_map_Nt: result = "Thickness Map"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
CopyVertex(Vec3* dst, m3dv_t* src)
|
CopyVertex(Vec3* dst, m3dv_t* src)
|
||||||
{
|
{
|
||||||
@ -557,3 +682,85 @@ PrintShader(Renderer* rd, Pipeline* pipeline, VkShaderStageFlagBits stage)
|
|||||||
PrintShaderDisassembly(&rd.vk, pipeline, stage);
|
PrintShaderDisassembly(&rd.vk, pipeline, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetClearColor(Renderer* rd, Vec4 color)
|
||||||
|
{
|
||||||
|
SetClearColor(&rd.vk, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearColorEnabled(Renderer* rd, bool enabled)
|
||||||
|
{
|
||||||
|
rd.vk.enable_clear_color = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageBarrier(Renderer* rd)
|
||||||
|
{
|
||||||
|
ImageBarrier(&rd.vk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CreateImageView(Renderer* rd, ImageView* view, u32 w, u32 h, Format format, ImageUsage usage, bool depth_image = false)
|
||||||
|
{
|
||||||
|
CreateImageView(&rd.vk, view, w, h, format, usage, depth_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
Format
|
||||||
|
GetDrawImageFormat(Renderer* rd)
|
||||||
|
{
|
||||||
|
return cast(Format)GetDrawImageFormat(&rd.vk);
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
ResizeDrawImageIfNeeded(Renderer* rd, ImageView* view)
|
||||||
|
{
|
||||||
|
Extent ext = GetExtent(rd);
|
||||||
|
|
||||||
|
if (view.w != ext.w || view.h != ext.h)
|
||||||
|
{
|
||||||
|
Destroy(view, rd.vk.device, rd.vk.vma);
|
||||||
|
CreateImageView(&rd.vk, view, ext.w, ext.h, view.format, view.usage, view.depth_image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FinishRendering(Renderer* rd)
|
||||||
|
{
|
||||||
|
FinishRendering(&rd.vk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Submit(Renderer* rd, ImageView* view)
|
||||||
|
{
|
||||||
|
SubmitAndPresent(&rd.vk, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UpdateAuxImage(Renderer* rd, ImageView* view)
|
||||||
|
{
|
||||||
|
UpdateAuxImage(&rd.vk, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearColor(Renderer* rd, ImageView* view, Vec4 color)
|
||||||
|
{
|
||||||
|
ClearColor(&rd.vk, view, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Destroy(Renderer* rd, Model* model)
|
||||||
|
{
|
||||||
|
Destroy(&rd.vk, &model.vertex_buffer);
|
||||||
|
Destroy(&rd.vk, &model.index_buffer);
|
||||||
|
|
||||||
|
foreach(i, mat; model.materials)
|
||||||
|
{
|
||||||
|
Destroy(&rd.vk, model.materials.ptr + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i, view; model.textures)
|
||||||
|
{
|
||||||
|
Destroy(model.textures.ptr + i, rd.vk.device, rd.vk.vma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import aliases;
|
|||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import core.stdc.string : strcmp, memcpy;
|
import core.stdc.string : strcmp, memcpy;
|
||||||
|
import core.stdc.stdio : Printf = printf;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
import util;
|
import util;
|
||||||
import alloc;
|
import alloc;
|
||||||
@ -52,6 +53,7 @@ const char*[] VK_BASE_DEVICE_EXTENSIONS = [
|
|||||||
cast(char*)VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
cast(char*)VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
cast(char*)VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME,
|
cast(char*)VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME,
|
||||||
cast(char*)VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
|
cast(char*)VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
|
||||||
|
cast(char*)"VK_KHR_dynamic_rendering_local_read",
|
||||||
];
|
];
|
||||||
|
|
||||||
const char*[] VK_AMD_DEVICE_EXTENSIONS = [
|
const char*[] VK_AMD_DEVICE_EXTENSIONS = [
|
||||||
@ -75,11 +77,6 @@ const VkFormat[] VK_IMAGE_FORMATS = [
|
|||||||
VK_FORMAT_R8G8B8A8_UNORM,
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
];
|
];
|
||||||
|
|
||||||
const VkImageUsageFlags VK_DRAW_IMAGE_USAGE_FLAGS = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
||||||
VK_IMAGE_USAGE_STORAGE_BIT |
|
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
||||||
|
|
||||||
enum StepInitialized : u32
|
enum StepInitialized : u32
|
||||||
{
|
{
|
||||||
Renderer = 1,
|
Renderer = 1,
|
||||||
@ -93,6 +90,7 @@ enum StepInitialized : u32
|
|||||||
Swapchain,
|
Swapchain,
|
||||||
DrawImages,
|
DrawImages,
|
||||||
Descriptors,
|
Descriptors,
|
||||||
|
Pipelines,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias SI = StepInitialized;
|
alias SI = StepInitialized;
|
||||||
@ -108,22 +106,6 @@ enum DescType : u32
|
|||||||
|
|
||||||
alias DT = DescType;
|
alias DT = DescType;
|
||||||
|
|
||||||
struct Image
|
|
||||||
{
|
|
||||||
VkImage image;
|
|
||||||
VmaAllocation alloc;
|
|
||||||
VkFormat format;
|
|
||||||
VkImageLayout layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ImageView
|
|
||||||
{
|
|
||||||
Image base;
|
|
||||||
VkImageView view;
|
|
||||||
|
|
||||||
alias base this;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MappedBuffer(T)
|
struct MappedBuffer(T)
|
||||||
{
|
{
|
||||||
Buffer base;
|
Buffer base;
|
||||||
@ -133,13 +115,6 @@ struct MappedBuffer(T)
|
|||||||
alias base this;
|
alias base this;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Buffer
|
|
||||||
{
|
|
||||||
VkBuffer buffer;
|
|
||||||
VmaAllocation alloc;
|
|
||||||
u64 size;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DescBindings
|
struct DescBindings
|
||||||
{
|
{
|
||||||
u32[] free;
|
u32[] free;
|
||||||
@ -198,6 +173,7 @@ struct Vulkan
|
|||||||
DescBindings[DT.max] desc_bindings;
|
DescBindings[DT.max] desc_bindings;
|
||||||
|
|
||||||
VkSampler nearest_sampler;
|
VkSampler nearest_sampler;
|
||||||
|
VkSampler oit_sampler;
|
||||||
|
|
||||||
VkPipeline[FRAME_OVERLAP] last_pipeline;
|
VkPipeline[FRAME_OVERLAP] last_pipeline;
|
||||||
VkPipelineLayout pipeline_layout;
|
VkPipelineLayout pipeline_layout;
|
||||||
@ -220,6 +196,12 @@ struct Vulkan
|
|||||||
VkPipeline last_comp_pipeline;
|
VkPipeline last_comp_pipeline;
|
||||||
bool compute_pass_started;
|
bool compute_pass_started;
|
||||||
|
|
||||||
|
bool enable_clear_color;
|
||||||
|
VkClearColorValue clear_color;
|
||||||
|
|
||||||
|
BufferView a_buffer_view;
|
||||||
|
ImageView aux_image;
|
||||||
|
|
||||||
alias queues this;
|
alias queues this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,6 +276,8 @@ Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem)
|
|||||||
bool
|
bool
|
||||||
InitConversionPipeline(Vulkan* vk)
|
InitConversionPipeline(Vulkan* vk)
|
||||||
{
|
{
|
||||||
|
Push(vk, SI.Pipelines);
|
||||||
|
|
||||||
VkDescriptorBindingFlags[] binding_flags;
|
VkDescriptorBindingFlags[] binding_flags;
|
||||||
binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
||||||
|
|
||||||
@ -432,6 +416,7 @@ InitBuffers(Vulkan* vk)
|
|||||||
Push(vk, SI.Buffers);
|
Push(vk, SI.Buffers);
|
||||||
|
|
||||||
vk.global_buf = CreateMappedBuffer!(GlobalUniforms)(vk, BT.Uniform, 1);
|
vk.global_buf = CreateMappedBuffer!(GlobalUniforms)(vk, BT.Uniform, 1);
|
||||||
|
vk.shader_buf = CreateMappedBuffer!(ShaderUniforms)(vk, BT.Uniform, 1);
|
||||||
|
|
||||||
u64 transfer_size = MB(64);
|
u64 transfer_size = MB(64);
|
||||||
vk.transfer_buf = CreateMappedBuffer!(u8)(vk, BT.Staging, transfer_size);
|
vk.transfer_buf = CreateMappedBuffer!(u8)(vk, BT.Staging, transfer_size);
|
||||||
@ -527,27 +512,30 @@ BeginFrame(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BeginRender(Vulkan* vk)
|
BeginRendering(Vulkan* vk, ImageView* draw_image, ImageView* depth_image)
|
||||||
{
|
{
|
||||||
// TODO: probably get rid of these
|
// TODO: probably get rid of these
|
||||||
Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
Transition(vk.cmds[vk.frame_index], &vk.depth_image, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], depth_image, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
VkImage image = CurrentImage(vk);
|
VkImage image = CurrentImage(vk);
|
||||||
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
VkRenderingAttachmentInfo col_attach = {
|
VkRenderingAttachmentInfo col_attach = {
|
||||||
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||||
imageView: vk.draw_image.view,
|
imageView: draw_image.view,
|
||||||
imageLayout: vk.draw_image.layout,
|
imageLayout: draw_image.layout,
|
||||||
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, // CLEAR instead of LOAD if wanting to clear colors, also clearColor value (or whatever)
|
loadOp: (vk.enable_clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD), // CLEAR instead of LOAD if wanting to clear colors, also clearColor value (or whatever)
|
||||||
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
clearValue: {
|
||||||
|
color: vk.clear_color,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
VkRenderingAttachmentInfo depth_attach = {
|
VkRenderingAttachmentInfo depth_attach = {
|
||||||
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
sType: VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||||
imageView: vk.depth_image.view,
|
imageView: depth_image.view,
|
||||||
imageLayout: vk.depth_image.layout,
|
imageLayout: depth_image.layout,
|
||||||
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
|
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
storeOp: VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
};
|
};
|
||||||
@ -569,6 +557,21 @@ BeginRender(Vulkan* vk)
|
|||||||
vkCmdBeginRendering(vk.cmds[vk.frame_index], &render_info);
|
vkCmdBeginRendering(vk.cmds[vk.frame_index], &render_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetClearColor(Vulkan* vk, Vec4 color)
|
||||||
|
{
|
||||||
|
vk.clear_color.float32[0] = color.r;
|
||||||
|
vk.clear_color.float32[1] = color.g;
|
||||||
|
vk.clear_color.float32[2] = color.b;
|
||||||
|
vk.clear_color.float32[3] = color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PrepAuxImage(Vulkan* vk, ImageView* view)
|
||||||
|
{
|
||||||
|
Transition(vk.cmds[vk.frame_index], view, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PrepComputeDrawImage(Vulkan* vk)
|
PrepComputeDrawImage(Vulkan* vk)
|
||||||
{
|
{
|
||||||
@ -576,7 +579,13 @@ PrepComputeDrawImage(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FinishFrame(Vulkan* vk)
|
FinishRendering(Vulkan* vk)
|
||||||
|
{
|
||||||
|
vkCmdEndRendering(vk.cmds[vk.frame_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SubmitAndPresent(Vulkan* vk, ImageView* draw_image)
|
||||||
{
|
{
|
||||||
scope(exit)
|
scope(exit)
|
||||||
{
|
{
|
||||||
@ -588,9 +597,7 @@ FinishFrame(Vulkan* vk)
|
|||||||
VkSemaphore acquire_sem = vk.acquire_sems[vk.frame_index];
|
VkSemaphore acquire_sem = vk.acquire_sems[vk.frame_index];
|
||||||
VkSemaphore submit_sem = vk.submit_sems[vk.image_index];
|
VkSemaphore submit_sem = vk.submit_sems[vk.image_index];
|
||||||
|
|
||||||
vkCmdEndRendering(vk.cmds[vk.frame_index]);
|
Transition(vk.cmds[vk.frame_index], draw_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
|
||||||
Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
|
||||||
|
|
||||||
VkExtent2D extent = {
|
VkExtent2D extent = {
|
||||||
width: vk.swapchain_extent.width,
|
width: vk.swapchain_extent.width,
|
||||||
@ -598,7 +605,7 @@ FinishFrame(Vulkan* vk)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Find out how to copy from same dimension images (pretty sure its not blitting)
|
// TODO: Find out how to copy from same dimension images (pretty sure its not blitting)
|
||||||
Copy(vk.cmds[vk.frame_index], &vk.draw_image.base, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent);
|
Copy(vk.cmds[vk.frame_index], &draw_image.base, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent);
|
||||||
|
|
||||||
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
Transition(vk.cmds[vk.frame_index], image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
|
||||||
@ -736,7 +743,7 @@ TransferAssets(Vulkan* vk)
|
|||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
||||||
{
|
{
|
||||||
CreateImageView(vk, view, w, h);
|
CreateImageView(vk, view, w, h, FMT.RGBA_UNORM, IU.Texture);
|
||||||
|
|
||||||
if (ch == 4)
|
if (ch == 4)
|
||||||
{
|
{
|
||||||
@ -749,7 +756,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
|||||||
assert(Transfer(vk, &buf, data), "CreateImageView failure: Buffer Transfer error");
|
assert(Transfer(vk, &buf, data), "CreateImageView failure: Buffer Transfer error");
|
||||||
|
|
||||||
ImageView conv_view;
|
ImageView conv_view;
|
||||||
CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32);
|
CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32, IU.Convert);
|
||||||
|
|
||||||
WriteConvDescriptor(vk, &buf);
|
WriteConvDescriptor(vk, &buf);
|
||||||
WriteConvDescriptor(vk, &conv_view);
|
WriteConvDescriptor(vk, &conv_view);
|
||||||
@ -853,7 +860,25 @@ FinishComputePass(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.RGBA_UNORM)
|
CreateBufferView(Vulkan* vk, BufferView* view, u64 size, Format format)
|
||||||
|
{
|
||||||
|
CreateBuffer(vk, &view.base, BT.BufferView, size, false);
|
||||||
|
|
||||||
|
VkBufferViewCreateInfo info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
||||||
|
buffer: view.buffer,
|
||||||
|
format: format,
|
||||||
|
range: size,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult result = vkCreateBufferView(vk.device, &info, null, &view.view);
|
||||||
|
VkCheckA("CreateBufferView failure: vkCreateBufferView failed", result);
|
||||||
|
|
||||||
|
view.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageUsage usage, bool depth_image = false)
|
||||||
{
|
{
|
||||||
VmaAllocationCreateInfo alloc_info = {
|
VmaAllocationCreateInfo alloc_info = {
|
||||||
usage: VMA_MEMORY_USAGE_GPU_ONLY,
|
usage: VMA_MEMORY_USAGE_GPU_ONLY,
|
||||||
@ -868,7 +893,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.R
|
|||||||
format: format,
|
format: format,
|
||||||
tiling: VK_IMAGE_TILING_OPTIMAL,
|
tiling: VK_IMAGE_TILING_OPTIMAL,
|
||||||
initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
|
initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
usage: format == FMT.RGBA_F32 ? (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) : (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
|
usage: usage,
|
||||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
samples: VK_SAMPLE_COUNT_1_BIT,
|
||||||
extent: {
|
extent: {
|
||||||
width: w,
|
width: w,
|
||||||
@ -884,9 +909,6 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.R
|
|||||||
image_info.pQueueFamilyIndices = cast(const u32*)[vk.gfx_index, vk.tfer_index];
|
image_info.pQueueFamilyIndices = cast(const u32*)[vk.gfx_index, vk.tfer_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
view.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
view.format = VK_FORMAT_R8G8B8A8_SRGB;
|
|
||||||
|
|
||||||
VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, &view.alloc, null);
|
VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &view.image, &view.alloc, null);
|
||||||
// TODO: handle errors and realloc
|
// TODO: handle errors and realloc
|
||||||
assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure");
|
assert(VkCheck("CreateImageView failure: vmaCreateImage error", result), "CreateImageView failure");
|
||||||
@ -897,7 +919,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.R
|
|||||||
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
||||||
format: format,
|
format: format,
|
||||||
subresourceRange: {
|
subresourceRange: {
|
||||||
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
aspectMask: (depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
|
||||||
levelCount: 1,
|
levelCount: 1,
|
||||||
layerCount: 1,
|
layerCount: 1,
|
||||||
},
|
},
|
||||||
@ -906,6 +928,13 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.R
|
|||||||
result = vkCreateImageView(vk.device, &view_info, null, &view.view);
|
result = vkCreateImageView(vk.device, &view_info, null, &view.view);
|
||||||
// TODO: also handle here
|
// TODO: also handle here
|
||||||
assert(VkCheck("CreateImageView failure: vkCreateImageView error", result), "CreateImageView failure");
|
assert(VkCheck("CreateImageView failure: vkCreateImageView error", result), "CreateImageView failure");
|
||||||
|
|
||||||
|
view.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
view.format = format;
|
||||||
|
view.w = w;
|
||||||
|
view.h = h;
|
||||||
|
view.depth_image = depth_image;
|
||||||
|
view.usage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32
|
u32
|
||||||
@ -977,6 +1006,27 @@ PushConstants(Vulkan* vk, PushConst* pc)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageBarrier(Vulkan* vk)
|
||||||
|
{
|
||||||
|
VkMemoryBarrier2 barrier = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||||
|
srcStageMask: VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||||
|
srcAccessMask: VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||||
|
dstStageMask: VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
dstAccessMask: VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDependencyInfo dependency = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||||
|
dependencyFlags: VK_DEPENDENCY_BY_REGION_BIT,
|
||||||
|
memoryBarrierCount: 1,
|
||||||
|
pMemoryBarriers: &barrier,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier2(vk.cmds[vk.frame_index], &dependency);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Transfer(T)(Vulkan* vk, Buffer* buf, T[] data)
|
Transfer(T)(Vulkan* vk, Buffer* buf, T[] data)
|
||||||
{
|
{
|
||||||
@ -1315,13 +1365,19 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
|||||||
VkPipelineRenderingCreateInfo rendering_info = {
|
VkPipelineRenderingCreateInfo rendering_info = {
|
||||||
sType: VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||||
colorAttachmentCount: 1,
|
colorAttachmentCount: 1,
|
||||||
pColorAttachmentFormats: &vk.draw_image.format,
|
pColorAttachmentFormats: cast(VkFormat*)&build_info.draw_image.format,
|
||||||
depthAttachmentFormat: vk.depth_image.format,
|
depthAttachmentFormat: build_info.depth_image.format,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState blend_state = {
|
VkPipelineColorBlendAttachmentState blend_state = {
|
||||||
colorWriteMask: VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
colorWriteMask: VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
||||||
blendEnable: VK_FALSE,
|
blendEnable: VK_TRUE,
|
||||||
|
srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
colorBlendOp: VK_BLEND_OP_ADD,
|
||||||
|
srcAlphaBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
dstAlphaBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
alphaBlendOp: VK_BLEND_OP_ADD,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo blend_info = {
|
VkPipelineColorBlendStateCreateInfo blend_info = {
|
||||||
@ -1355,36 +1411,36 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
|||||||
VkPipelineShaderStageCreateInfo[] shader_info = [
|
VkPipelineShaderStageCreateInfo[] shader_info = [
|
||||||
{
|
{
|
||||||
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
stage: VK_SHADER_STAGE_VERTEX_BIT,
|
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
pName: "main",
|
pName: "main",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
stage: VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
pName: "main",
|
pName: "main",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Arena* arena = &vk.frame_arenas[0];
|
Arena* arena = &vk.frame_arenas[0];
|
||||||
|
|
||||||
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
|
||||||
u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader);
|
u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader);
|
||||||
|
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
||||||
|
|
||||||
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
||||||
|
|
||||||
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
|
||||||
Result!(Shader) frag_module = BuildShader(vk, frag_bytes);
|
Result!(Shader) frag_module = BuildShader(vk, frag_bytes);
|
||||||
|
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
||||||
|
|
||||||
assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders");
|
assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders");
|
||||||
|
|
||||||
scope(exit)
|
scope(exit)
|
||||||
{
|
{
|
||||||
Destroy(vk, vert_module.value);
|
|
||||||
Destroy(vk, frag_module.value);
|
Destroy(vk, frag_module.value);
|
||||||
|
Destroy(vk, vert_module.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__traits(getMember, shader_info.ptr + 0, "module") = vert_module.value;
|
__traits(getMember, shader_info.ptr + 0, "module") = frag_module.value;
|
||||||
__traits(getMember, shader_info.ptr + 1, "module") = frag_module.value;
|
__traits(getMember, shader_info.ptr + 1, "module") = vert_module.value;
|
||||||
|
|
||||||
VkSpecializationInfo vert_spec_info = {
|
VkSpecializationInfo vert_spec_info = {
|
||||||
dataSize: build_info.vert_spec.size,
|
dataSize: build_info.vert_spec.size,
|
||||||
@ -1475,6 +1531,25 @@ CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info)
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearColor(Vulkan* vk, ImageView* view, Vec4 color)
|
||||||
|
{
|
||||||
|
VkImageSubresourceRange clear_range = {
|
||||||
|
aspectMask: (view.depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
|
||||||
|
levelCount: 1,
|
||||||
|
layerCount: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdClearColorImage(
|
||||||
|
vk.cmds[vk.frame_index],
|
||||||
|
view.image,
|
||||||
|
view.layout,
|
||||||
|
cast(VkClearColorValue*)color.v,
|
||||||
|
1,
|
||||||
|
&clear_range
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetUniform(Vulkan* vk, GlobalUniforms* globals)
|
SetUniform(Vulkan* vk, GlobalUniforms* globals)
|
||||||
{
|
{
|
||||||
@ -1558,6 +1633,13 @@ Destroy(Vulkan* vk)
|
|||||||
break;
|
break;
|
||||||
case SI.Buffers:
|
case SI.Buffers:
|
||||||
Destroy(vk, &vk.transfer_buf);
|
Destroy(vk, &vk.transfer_buf);
|
||||||
|
Destroy(vk, &vk.ui_vert_buf);
|
||||||
|
Destroy(vk, &vk.ui_index_buf);
|
||||||
|
Destroy(vk, &vk.global_buf);
|
||||||
|
Destroy(vk, &vk.shader_buf);
|
||||||
|
break;
|
||||||
|
case SI.Pipelines:
|
||||||
|
DestroyPipelines(vk);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1565,6 +1647,35 @@ Destroy(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DestroyPipelines(Vulkan* vk)
|
||||||
|
{
|
||||||
|
if (vk.conv_pipeline_layout)
|
||||||
|
{
|
||||||
|
vkDestroyPipelineLayout(vk.device, vk.conv_pipeline_layout, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.conv_desc_layout)
|
||||||
|
{
|
||||||
|
vkDestroyDescriptorSetLayout(vk.device, vk.conv_desc_layout, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.r_to_rgba_pipeline.handle)
|
||||||
|
{
|
||||||
|
vkDestroyPipeline(vk.device, vk.r_to_rgba_pipeline.handle, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.rg_to_rgba_pipeline.handle)
|
||||||
|
{
|
||||||
|
vkDestroyPipeline(vk.device, vk.rg_to_rgba_pipeline.handle, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.rgb_to_rgba_pipeline.handle)
|
||||||
|
{
|
||||||
|
vkDestroyPipeline(vk.device, vk.rgb_to_rgba_pipeline.handle, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Destroy(T)(Vulkan* vk, MappedBuffer!(T)* buf)
|
Destroy(T)(Vulkan* vk, MappedBuffer!(T)* buf)
|
||||||
{
|
{
|
||||||
@ -1591,6 +1702,7 @@ InitDescriptors(Vulkan* vk)
|
|||||||
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 },
|
||||||
{ type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 4096 },
|
||||||
{ type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 },
|
{ type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 },
|
||||||
|
{ type: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 4096 },
|
||||||
];
|
];
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo pool_info = {
|
VkDescriptorPoolCreateInfo pool_info = {
|
||||||
@ -1606,7 +1718,17 @@ InitDescriptors(Vulkan* vk)
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkDescriptorBindingFlags[4] shared_binding_flags;
|
VkDescriptorSetLayoutBinding[] shared_bindings = [
|
||||||
|
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 4, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 5, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
{ binding: 6, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||||
|
];
|
||||||
|
|
||||||
|
VkDescriptorBindingFlags[] shared_binding_flags = AllocArray!(VkDescriptorBindingFlags)(&vk.frame_arenas[0], shared_bindings.length);
|
||||||
shared_binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
shared_binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
||||||
|
|
||||||
VkDescriptorSetLayoutBindingFlagsCreateInfo shared_flag_info = {
|
VkDescriptorSetLayoutBindingFlagsCreateInfo shared_flag_info = {
|
||||||
@ -1615,13 +1737,6 @@ InitDescriptors(Vulkan* vk)
|
|||||||
pBindingFlags: shared_binding_flags.ptr,
|
pBindingFlags: shared_binding_flags.ptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding[] shared_bindings = [
|
|
||||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
|
||||||
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
|
||||||
{ binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
|
||||||
{ binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
|
||||||
];
|
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo shared_set_info = {
|
VkDescriptorSetLayoutCreateInfo shared_set_info = {
|
||||||
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
pNext: &shared_flag_info,
|
pNext: &shared_flag_info,
|
||||||
@ -1753,20 +1868,80 @@ InitDescriptors(Vulkan* vk)
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
VkSamplerCreateInfo sampler_info = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
|
magFilter: VK_FILTER_LINEAR,
|
||||||
|
minFilter: VK_FILTER_LINEAR,
|
||||||
|
addressModeU: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
addressModeV: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
anisotropyEnable: VK_FALSE,
|
||||||
|
compareEnable: VK_FALSE,
|
||||||
|
borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||||
|
mipmapMode: VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||||
|
unnormalizedCoordinates: VK_FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
result = vkCreateSampler(vk.device, &sampler_info, null, &vk.oit_sampler);
|
||||||
|
success = VkCheck("vkCreateSampler failure", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
// TODO: move this elsewhere later
|
||||||
|
// Also add samples/supersampling scaling
|
||||||
|
|
||||||
|
CreateBufferView(vk, &vk.a_buffer_view, (u32.sizeof * 2) * vk.swapchain_extent.width * vk.swapchain_extent.height, FMT.RG_U32);
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo a_buffer_info = {
|
||||||
|
buffer: vk.a_buffer_view.buffer,
|
||||||
|
offset: 0,
|
||||||
|
range: VK_WHOLE_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorImageInfo aux_info = {
|
||||||
|
sampler: vk.oit_sampler,
|
||||||
|
imageView: vk.aux_image.view,
|
||||||
|
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
};
|
||||||
|
|
||||||
VkDescriptorImageInfo sampler_info = {
|
VkDescriptorImageInfo sampler_info = {
|
||||||
sampler: vk.nearest_sampler,
|
sampler: vk.nearest_sampler,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkWriteDescriptorSet write = {
|
VkDescriptorImageInfo oit_sample_info = {
|
||||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
sampler: vk.oit_sampler,
|
||||||
dstSet: vk.desc_sets[DT.Shared],
|
|
||||||
dstBinding: 3,
|
|
||||||
descriptorCount: 1,
|
|
||||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
|
||||||
pImageInfo: &sampler_info,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
VkWriteDescriptorSet[] writes = [
|
||||||
|
{
|
||||||
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
|
dstBinding: 3,
|
||||||
|
descriptorCount: 1,
|
||||||
|
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
|
pImageInfo: &sampler_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
|
dstBinding: 4,
|
||||||
|
descriptorCount: 1,
|
||||||
|
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||||||
|
pBufferInfo: &a_buffer_info,
|
||||||
|
pTexelBufferView: &vk.a_buffer_view.view,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
|
dstBinding: 6,
|
||||||
|
descriptorCount: 1,
|
||||||
|
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
|
pImageInfo: &oit_sample_info,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null);
|
||||||
|
|
||||||
WriteDrawImageDesc(vk);
|
WriteDrawImageDesc(vk);
|
||||||
}
|
}
|
||||||
@ -1774,6 +1949,31 @@ InitDescriptors(Vulkan* vk)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: better descriptor updating
|
||||||
|
void
|
||||||
|
UpdateAuxImage(Vulkan* vk, ImageView* view)
|
||||||
|
{
|
||||||
|
VkDescriptorImageInfo aux_info = {
|
||||||
|
sampler: vk.oit_sampler,
|
||||||
|
imageView: view.view,
|
||||||
|
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(view.view != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VkWriteDescriptorSet write = {
|
||||||
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
|
dstBinding: 5,
|
||||||
|
descriptorCount: 1,
|
||||||
|
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||||
|
pImageInfo: &aux_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WriteDrawImageDesc(Vulkan* vk)
|
WriteDrawImageDesc(Vulkan* vk)
|
||||||
{
|
{
|
||||||
@ -2054,7 +2254,7 @@ GetDrawImageFormat(Vulkan* vk)
|
|||||||
format,
|
format,
|
||||||
VK_IMAGE_TYPE_2D,
|
VK_IMAGE_TYPE_2D,
|
||||||
VK_IMAGE_TILING_OPTIMAL,
|
VK_IMAGE_TILING_OPTIMAL,
|
||||||
VK_DRAW_IMAGE_USAGE_FLAGS,
|
IU.Draw,
|
||||||
0,
|
0,
|
||||||
&props
|
&props
|
||||||
);
|
);
|
||||||
@ -2080,91 +2280,14 @@ CreateDrawImages(Vulkan* vk)
|
|||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
VkFormat draw_format = GetDrawImageFormat(vk);
|
Format draw_format = cast(Format)GetDrawImageFormat(vk);
|
||||||
VkFormat depth_format = VK_FORMAT_D32_SFLOAT;
|
Format depth_format = cast(Format)VK_FORMAT_D32_SFLOAT;
|
||||||
|
|
||||||
VmaAllocationCreateInfo alloc_info = {
|
u32 w = vk.swapchain_extent.width;
|
||||||
usage: VMA_MEMORY_USAGE_GPU_ONLY,
|
u32 h = vk.swapchain_extent.height;
|
||||||
requiredFlags: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkImageCreateInfo image_info = {
|
CreateImageView(vk, &vk.draw_image, w, h, draw_format, IU.Draw, false);
|
||||||
sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
CreateImageView(vk, &vk.depth_image, w, h, depth_format, IU.Depth, true);
|
||||||
imageType: VK_IMAGE_TYPE_2D,
|
|
||||||
mipLevels: 1,
|
|
||||||
arrayLayers: 1,
|
|
||||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
tiling: VK_IMAGE_TILING_OPTIMAL,
|
|
||||||
usage: VK_DRAW_IMAGE_USAGE_FLAGS,
|
|
||||||
extent: vk.swapchain_extent,
|
|
||||||
format: draw_format,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkResult result = vmaCreateImage(vk.vma, &image_info, &alloc_info, &vk.draw_image.image, &vk.draw_image.alloc, null);
|
|
||||||
success = VkCheck("vmaCreateImage failure", result);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
VkImageViewCreateInfo view_info = {
|
|
||||||
sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
||||||
image: vk.draw_image.image,
|
|
||||||
format: draw_format,
|
|
||||||
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
|
||||||
subresourceRange: {
|
|
||||||
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
baseMipLevel: 0,
|
|
||||||
levelCount: 1,
|
|
||||||
baseArrayLayer: 0,
|
|
||||||
layerCount: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
result = vkCreateImageView(vk.device, &view_info, null, &vk.draw_image.view);
|
|
||||||
success = VkCheck("vkCreateImageView failure", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
VkImageCreateInfo depth_image_info = {
|
|
||||||
sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
||||||
imageType: VK_IMAGE_TYPE_2D,
|
|
||||||
mipLevels: 1,
|
|
||||||
arrayLayers: 1,
|
|
||||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
tiling: VK_IMAGE_TILING_OPTIMAL,
|
|
||||||
format: depth_format,
|
|
||||||
usage: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
||||||
extent: vk.swapchain_extent,
|
|
||||||
};
|
|
||||||
|
|
||||||
result = vmaCreateImage(vk.vma, &depth_image_info, &alloc_info, &vk.depth_image.image, &vk.depth_image.alloc, null);
|
|
||||||
success = VkCheck("vmaCreateImage failure", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
VkImageViewCreateInfo depth_view_info = {
|
|
||||||
sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
||||||
image: vk.depth_image.image,
|
|
||||||
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
|
||||||
format: depth_format,
|
|
||||||
subresourceRange: {
|
|
||||||
aspectMask: VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
||||||
baseMipLevel: 0,
|
|
||||||
levelCount: 1,
|
|
||||||
baseArrayLayer: 0,
|
|
||||||
layerCount: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
result = vkCreateImageView(vk.device, &depth_view_info, null, &vk.depth_image.view);
|
|
||||||
success = VkCheck("vmaCreateImageView failure", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
vk.draw_image.format = draw_format;
|
|
||||||
vk.draw_image.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
vk.depth_image.format = depth_format;
|
|
||||||
vk.depth_image.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -2218,7 +2341,7 @@ CreateSwapchain(Vulkan* vk)
|
|||||||
VkSwapchainCreateInfoKHR info = {
|
VkSwapchainCreateInfoKHR info = {
|
||||||
sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
imageArrayLayers: 1,
|
imageArrayLayers: 1,
|
||||||
imageUsage: VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
imageUsage: IU.Swapchain,
|
||||||
compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||||
clipped: VK_TRUE,
|
clipped: VK_TRUE,
|
||||||
imageSharingMode: VK_SHARING_MODE_EXCLUSIVE,
|
imageSharingMode: VK_SHARING_MODE_EXCLUSIVE,
|
||||||
@ -2406,6 +2529,7 @@ InitDevice(Vulkan* vk)
|
|||||||
descriptorBindingSampledImageUpdateAfterBind: VK_TRUE,
|
descriptorBindingSampledImageUpdateAfterBind: VK_TRUE,
|
||||||
descriptorBindingStorageImageUpdateAfterBind: VK_TRUE,
|
descriptorBindingStorageImageUpdateAfterBind: VK_TRUE,
|
||||||
descriptorBindingStorageBufferUpdateAfterBind: VK_TRUE,
|
descriptorBindingStorageBufferUpdateAfterBind: VK_TRUE,
|
||||||
|
descriptorBindingStorageTexelBufferUpdateAfterBind: VK_TRUE,
|
||||||
descriptorBindingPartiallyBound: VK_TRUE,
|
descriptorBindingPartiallyBound: VK_TRUE,
|
||||||
shaderSampledImageArrayNonUniformIndexing: VK_TRUE,
|
shaderSampledImageArrayNonUniformIndexing: VK_TRUE,
|
||||||
shaderUniformBufferArrayNonUniformIndexing: VK_TRUE,
|
shaderUniformBufferArrayNonUniformIndexing: VK_TRUE,
|
||||||
@ -2427,6 +2551,7 @@ InitDevice(Vulkan* vk)
|
|||||||
shaderStorageBufferArrayDynamicIndexing: VK_TRUE,
|
shaderStorageBufferArrayDynamicIndexing: VK_TRUE,
|
||||||
shaderStorageImageArrayDynamicIndexing: VK_TRUE,
|
shaderStorageImageArrayDynamicIndexing: VK_TRUE,
|
||||||
samplerAnisotropy: VK_TRUE,
|
samplerAnisotropy: VK_TRUE,
|
||||||
|
fragmentStoresAndAtomics: VK_TRUE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2496,6 +2621,7 @@ CheckDeviceFeatures(VkPhysicalDevice device)
|
|||||||
VkPhysicalDeviceFeatures features = features2.features;
|
VkPhysicalDeviceFeatures features = features2.features;
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
|
result &= cast(bool)features.fragmentStoresAndAtomics;
|
||||||
result &= cast(bool)features.shaderUniformBufferArrayDynamicIndexing;
|
result &= cast(bool)features.shaderUniformBufferArrayDynamicIndexing;
|
||||||
result &= cast(bool)features.shaderSampledImageArrayDynamicIndexing;
|
result &= cast(bool)features.shaderSampledImageArrayDynamicIndexing;
|
||||||
result &= cast(bool)features.shaderStorageBufferArrayDynamicIndexing;
|
result &= cast(bool)features.shaderStorageBufferArrayDynamicIndexing;
|
||||||
@ -2505,6 +2631,7 @@ CheckDeviceFeatures(VkPhysicalDevice device)
|
|||||||
result &= cast(bool)features_12.descriptorIndexing;
|
result &= cast(bool)features_12.descriptorIndexing;
|
||||||
result &= cast(bool)features_12.bufferDeviceAddress;
|
result &= cast(bool)features_12.bufferDeviceAddress;
|
||||||
result &= cast(bool)features_12.descriptorBindingUniformBufferUpdateAfterBind;
|
result &= cast(bool)features_12.descriptorBindingUniformBufferUpdateAfterBind;
|
||||||
|
result &= cast(bool)features_12.descriptorBindingStorageTexelBufferUpdateAfterBind;
|
||||||
result &= cast(bool)features_12.descriptorBindingSampledImageUpdateAfterBind;
|
result &= cast(bool)features_12.descriptorBindingSampledImageUpdateAfterBind;
|
||||||
result &= cast(bool)features_12.descriptorBindingStorageImageUpdateAfterBind;
|
result &= cast(bool)features_12.descriptorBindingStorageImageUpdateAfterBind;
|
||||||
result &= cast(bool)features_12.descriptorBindingStorageBufferUpdateAfterBind;
|
result &= cast(bool)features_12.descriptorBindingStorageBufferUpdateAfterBind;
|
||||||
@ -2789,6 +2916,21 @@ DestroyFS(Vulkan* vk)
|
|||||||
vkDestroyCommandPool(vk.device, vk.imm_pool, null);
|
vkDestroyCommandPool(vk.device, vk.imm_pool, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vk.comp_cmd)
|
||||||
|
{
|
||||||
|
vkFreeCommandBuffers(vk.device, vk.comp_cmd_pool, 1, &vk.comp_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.comp_cmd_pool)
|
||||||
|
{
|
||||||
|
vkDestroyCommandPool(vk.device, vk.comp_cmd_pool, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vk.comp_fence)
|
||||||
|
{
|
||||||
|
vkDestroyFence(vk.device, vk.comp_fence, null);
|
||||||
|
}
|
||||||
|
|
||||||
foreach(sem; vk.submit_sems)
|
foreach(sem; vk.submit_sems)
|
||||||
{
|
{
|
||||||
if (sem)
|
if (sem)
|
||||||
|
|||||||
@ -58,6 +58,7 @@ version(AMD_GPU)
|
|||||||
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = null;
|
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = null;
|
||||||
PFN_vkCreateImage vkCreateImage = null;
|
PFN_vkCreateImage vkCreateImage = null;
|
||||||
PFN_vkCreateImageView vkCreateImageView = null;
|
PFN_vkCreateImageView vkCreateImageView = null;
|
||||||
|
PFN_vkCreateBufferView vkCreateBufferView = null;
|
||||||
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = null;
|
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = null;
|
||||||
PFN_vkGetDeviceQueue vkGetDeviceQueue = null;
|
PFN_vkGetDeviceQueue vkGetDeviceQueue = null;
|
||||||
PFN_vkCreateSemaphore vkCreateSemaphore = null;
|
PFN_vkCreateSemaphore vkCreateSemaphore = null;
|
||||||
@ -154,6 +155,7 @@ LoadDeviceFunctions(Vulkan* vk)
|
|||||||
vkCreateSwapchainKHR = cast(PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(vk.device, "vkCreateSwapchainKHR");
|
vkCreateSwapchainKHR = cast(PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(vk.device, "vkCreateSwapchainKHR");
|
||||||
vkCreateImage = cast(PFN_vkCreateImage)vkGetDeviceProcAddr(vk.device, "vkCreateImage");
|
vkCreateImage = cast(PFN_vkCreateImage)vkGetDeviceProcAddr(vk.device, "vkCreateImage");
|
||||||
vkCreateImageView = cast(PFN_vkCreateImageView)vkGetDeviceProcAddr(vk.device, "vkCreateImageView");
|
vkCreateImageView = cast(PFN_vkCreateImageView)vkGetDeviceProcAddr(vk.device, "vkCreateImageView");
|
||||||
|
vkCreateBufferView = cast(PFN_vkCreateBufferView)vkGetDeviceProcAddr(vk.device, "vkCreateBufferView");
|
||||||
vkGetSwapchainImagesKHR = cast(PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(vk.device, "vkGetSwapchainImagesKHR");
|
vkGetSwapchainImagesKHR = cast(PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(vk.device, "vkGetSwapchainImagesKHR");
|
||||||
vkGetDeviceQueue = cast(PFN_vkGetDeviceQueue)vkGetDeviceProcAddr(vk.device, "vkGetDeviceQueue");
|
vkGetDeviceQueue = cast(PFN_vkGetDeviceQueue)vkGetDeviceProcAddr(vk.device, "vkGetDeviceQueue");
|
||||||
vkCreateSemaphore = cast(PFN_vkCreateSemaphore)vkGetDeviceProcAddr(vk.device, "vkCreateSemaphore");
|
vkCreateSemaphore = cast(PFN_vkCreateSemaphore)vkGetDeviceProcAddr(vk.device, "vkCreateSemaphore");
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
#extension GL_EXT_shader_8bit_storage : require
|
#extension GL_EXT_shader_8bit_storage : require
|
||||||
#extension GL_EXT_debug_printf : require
|
|
||||||
|
|
||||||
layout (constant_id = 0) const int CHANNELS = 3;
|
layout (constant_id = 0) const int CHANNELS = 3;
|
||||||
|
|
||||||
@ -35,7 +34,6 @@ void main()
|
|||||||
uint index = x + y * PC.x;
|
uint index = x + y * PC.x;
|
||||||
|
|
||||||
vec4 col = vec4(vec3(uint(src[index]) / 255.0), 1.0);
|
vec4 col = vec4(vec3(uint(src[index]) / 255.0), 1.0);
|
||||||
debugPrintfEXT("col = %v4f", col);
|
|
||||||
imageStore(dst, ivec2(x, y), col);
|
imageStore(dst, ivec2(x, y), col);
|
||||||
}
|
}
|
||||||
else if (CHANNELS == 2)
|
else if (CHANNELS == 2)
|
||||||
@ -45,7 +43,6 @@ void main()
|
|||||||
float f = uint(src[index]) / 255.0;
|
float f = uint(src[index]) / 255.0;
|
||||||
float a = uint(src[index+1]) / 255.0;
|
float a = uint(src[index+1]) / 255.0;
|
||||||
vec4 col = vec4(f, f, f, a);
|
vec4 col = vec4(f, f, f, a);
|
||||||
debugPrintfEXT("col = %v4f", col);
|
|
||||||
imageStore(dst, ivec2(x, y), col);
|
imageStore(dst, ivec2(x, y), col);
|
||||||
}
|
}
|
||||||
else if (CHANNELS == 3)
|
else if (CHANNELS == 3)
|
||||||
@ -53,7 +50,6 @@ void main()
|
|||||||
uint index = (x + y * PC.x) * 3;
|
uint index = (x + y * PC.x) * 3;
|
||||||
|
|
||||||
vec4 col = vec4(uint(src[index]) / 255.0, uint(src[index+1]) / 255.0, uint(src[index+2]) / 255.0, 1.0);
|
vec4 col = vec4(uint(src[index]) / 255.0, uint(src[index+1]) / 255.0, uint(src[index+2]) / 255.0, 1.0);
|
||||||
debugPrintfEXT("col = %v4f", col);
|
|
||||||
imageStore(dst, ivec2(x, y), col);
|
imageStore(dst, ivec2(x, y), col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/shaders/full_screen_triangle.vert.glsl
Normal file
7
src/shaders/full_screen_triangle.vert.glsl
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 pos = vec4((float((gl_VertexIndex >> 1U) & 1U)) * 4.0 - 1.0, (float(gl_VertexIndex & 1U)) * 4.0 - 1.0, 0, 1.0);
|
||||||
|
gl_Position = pos;
|
||||||
|
}
|
||||||
84
src/shaders/oit.frag.glsl
Normal file
84
src/shaders/oit.frag.glsl
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
#extension GL_EXT_nonuniform_qualifier : require
|
||||||
|
|
||||||
|
#define COMPOSITE_PASS
|
||||||
|
|
||||||
|
#include "structures.layout"
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void BubbleSort(inout uvec2 array[OIT_LAYERS], int n)
|
||||||
|
{
|
||||||
|
for(int i = (n - 2); i >= 0; --i)
|
||||||
|
{
|
||||||
|
for(int j = 0; j <= i; ++j)
|
||||||
|
{
|
||||||
|
if(uintBitsToFloat(array[j].g) >= uintBitsToFloat(array[j+1].g))
|
||||||
|
{
|
||||||
|
uvec2 temp = array[j+1];
|
||||||
|
array[j+1] = array[j];
|
||||||
|
array[j] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float UnPreMultSRGBToLinear(float col)
|
||||||
|
{
|
||||||
|
return (col < 0.04045f) ? (col / 12.92f) : pow((col + 0.055f) / 1.055f, 2.4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 UnPreMultSRGBToLinear(vec4 col)
|
||||||
|
{
|
||||||
|
col.r = UnPreMultSRGBToLinear(col.r);
|
||||||
|
col.g = UnPreMultSRGBToLinear(col.g);
|
||||||
|
col.b = UnPreMultSRGBToLinear(col.b);
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoBlend(inout vec4 color, vec4 base_color)
|
||||||
|
{
|
||||||
|
color.rgb += (1 - color.a) * base_color.rgb;
|
||||||
|
color.a += (1 - color.a) * base_color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoBlendPacked(inout vec4 color, uint fragment)
|
||||||
|
{
|
||||||
|
vec4 unpacked_color = unpackUnorm4x8(fragment);
|
||||||
|
//unpacked_color = UnPreMultSRGBToLinear(unpacked_color);
|
||||||
|
unpacked_color.rgb *= unpacked_color.a;
|
||||||
|
DoBlend(color, unpacked_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||||
|
int store_mask = 0;
|
||||||
|
int view_size = int(G.res.x) * int(G.res.y);
|
||||||
|
int sample_id = 0;
|
||||||
|
int list_pos = view_size * OIT_LAYERS * sample_id + coord.y * int(G.res.x) + coord.x;
|
||||||
|
uvec2 array[OIT_LAYERS];
|
||||||
|
|
||||||
|
vec4 color = vec4(0.0);
|
||||||
|
|
||||||
|
int fragments = int(imageLoad(ImageAux, coord).r);
|
||||||
|
fragments = min(OIT_LAYERS, fragments);
|
||||||
|
|
||||||
|
for (int i = 0; i < fragments; i++)
|
||||||
|
{
|
||||||
|
array[i] = imageLoad(ImageABuffer, list_pos + i * view_size).rg;
|
||||||
|
}
|
||||||
|
|
||||||
|
BubbleSort(array, fragments);
|
||||||
|
|
||||||
|
vec4 color_sum = vec4(0.0);
|
||||||
|
|
||||||
|
for(int i = 0; i < fragments; i++)
|
||||||
|
{
|
||||||
|
DoBlendPacked(color_sum, array[i].x);
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = color_sum;
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ layout (location = 0) in struct FragDataIn {
|
|||||||
vec2 uv;
|
vec2 uv;
|
||||||
} FragData;
|
} FragData;
|
||||||
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
layout (location = 0, index = 0) out vec4 FragColor;
|
||||||
|
|
||||||
vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, vec3 dir, vec3 normal)
|
vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, vec3 dir, vec3 normal)
|
||||||
{
|
{
|
||||||
@ -25,10 +25,57 @@ vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, ve
|
|||||||
return (ambient + diffuse);
|
return (ambient + diffuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float UnPreMultLinearToSRGB(float col)
|
||||||
|
{
|
||||||
|
return col < 0.0031308f ? col * 12.92f : (pow(col, 1.0f / 2.4f) * 1.055f) - 0.055f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 UnPreMultLinearToSRGB(vec4 col)
|
||||||
|
{
|
||||||
|
col.r = UnPreMultLinearToSRGB(col.x);
|
||||||
|
col.g = UnPreMultLinearToSRGB(col.x);
|
||||||
|
col.b = UnPreMultLinearToSRGB(col.x);
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||||
|
int store_mask = 0;
|
||||||
|
int view_size = int(G.res.x) * int(G.res.y);
|
||||||
|
int sample_id = 0;
|
||||||
|
int list_pos = view_size * OIT_LAYERS * sample_id + coord.y * int(G.res.x) + coord.x;
|
||||||
|
|
||||||
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
|
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
|
||||||
vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), FragData.uv);
|
vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), FragData.uv);
|
||||||
|
|
||||||
FragColor = CalculateDirectionalLight(col, tex_col, G.light_color, G.light_direction, FragData.normal);
|
vec4 out_col = CalculateDirectionalLight(col, tex_col, G.light_color, G.light_direction, FragData.normal);
|
||||||
|
out_col.a = 1.0;// Materials[nonuniformEXT(PC.mat_id)].alpha;
|
||||||
|
|
||||||
|
if (Materials[nonuniformEXT(PC.mat_id)].alpha_has_texture)
|
||||||
|
{
|
||||||
|
vec4 alpha_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].alpha_texture)], SamplerNearest), FragData.uv);
|
||||||
|
out_col.a = alpha_col.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = out_col;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: set up OIT again
|
||||||
|
vec4 srgb_col = out_col;// UnPreMultLinearToSRGB(out_col);
|
||||||
|
|
||||||
|
uvec4 store_value = uvec4(packUnorm4x8(srgb_col), floatBitsToUint(gl_FragCoord.z), store_mask, 0);
|
||||||
|
|
||||||
|
uint old_counter = imageAtomicAdd(ImageAux, coord, 1u);
|
||||||
|
if (old_counter < OIT_LAYERS)
|
||||||
|
{
|
||||||
|
imageStore(ImageABuffer, list_pos + int(old_counter) * view_size, store_value);
|
||||||
|
|
||||||
|
FragColor = vec4(0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FragColor = vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS ****
|
// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS ****
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
|
|
||||||
|
#define OIT_LAYERS 8
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform GlobalUniforms {
|
layout (set = 0, binding = 0) uniform GlobalUniforms {
|
||||||
mat4 view_matrix;
|
mat4 view_matrix;
|
||||||
mat4 projection_matrix;
|
mat4 projection_matrix;
|
||||||
@ -20,6 +22,20 @@ layout (rgba16f, set = 0, binding = 2) uniform image2D DrawImage;
|
|||||||
|
|
||||||
layout (set = 0, binding = 3) uniform sampler SamplerNearest;
|
layout (set = 0, binding = 3) uniform sampler SamplerNearest;
|
||||||
|
|
||||||
|
#ifdef COMPOSITE_PASS
|
||||||
|
|
||||||
|
layout (set = 0, binding = 4, rg32ui) uniform restrict readonly uimageBuffer ImageABuffer;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 5, r32ui) uniform restrict readonly uimage2D ImageAux;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
layout (set = 0, binding = 4, rg32ui) uniform coherent uimageBuffer ImageABuffer;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 5, r32ui) uniform coherent uimage2D ImageAux;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
layout (set = 1, binding = 0) uniform texture2D Textures[];
|
layout (set = 1, binding = 0) uniform texture2D Textures[];
|
||||||
|
|
||||||
layout (set = 2, binding = 0) uniform Material {
|
layout (set = 2, binding = 0) uniform Material {
|
||||||
@ -29,10 +45,13 @@ layout (set = 2, binding = 0) uniform Material {
|
|||||||
uint albedo_texture;
|
uint albedo_texture;
|
||||||
uint ambient_texture;
|
uint ambient_texture;
|
||||||
uint specular_texture;
|
uint specular_texture;
|
||||||
|
uint alpha_texture;
|
||||||
bool albedo_has_texture;
|
bool albedo_has_texture;
|
||||||
bool ambient_has_texture;
|
bool ambient_has_texture;
|
||||||
bool specular_has_texture;
|
bool specular_has_texture;
|
||||||
|
bool alpha_has_texture;
|
||||||
float shininess;
|
float shininess;
|
||||||
|
float alpha;
|
||||||
} Materials[];
|
} Materials[];
|
||||||
|
|
||||||
layout (push_constant) uniform Constants {
|
layout (push_constant) uniform Constants {
|
||||||
|
|||||||
@ -73,10 +73,13 @@ struct Material
|
|||||||
u32 albedo_texture;
|
u32 albedo_texture;
|
||||||
u32 ambient_texture;
|
u32 ambient_texture;
|
||||||
u32 specular_texture;
|
u32 specular_texture;
|
||||||
|
u32 alpha_texture;
|
||||||
b32 albedo_has_texture;
|
b32 albedo_has_texture;
|
||||||
b32 ambient_has_texture;
|
b32 ambient_has_texture;
|
||||||
b32 specular_has_texture;
|
b32 specular_has_texture;
|
||||||
|
b32 alpha_has_texture;
|
||||||
f32 shininess = 0.0;
|
f32 shininess = 0.0;
|
||||||
|
f32 alpha = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TextureInfo
|
struct TextureInfo
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user