Compare commits
No commits in common. "d4c86e7ac56430c2a9af0f6b51989b911b0bf82c" and "282f78baaef13ba03efe2bcb37e3359c3412d05d" have entirely different histories.
d4c86e7ac5
...
282f78baae
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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,20 +2,16 @@ 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;
|
||||||
|
|
||||||
@ -23,10 +19,6 @@ 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;
|
||||||
@ -35,21 +27,15 @@ struct Game
|
|||||||
|
|
||||||
Camera camera;
|
Camera camera;
|
||||||
|
|
||||||
Model tree;
|
Model model;
|
||||||
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: {
|
||||||
@ -59,24 +45,14 @@ 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: [
|
||||||
@ -90,8 +66,6 @@ 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 },
|
||||||
@ -102,13 +76,6 @@ 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",
|
||||||
};
|
};
|
||||||
@ -116,85 +83,18 @@ 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.rock = LoadModel(&g.rd, "models/BigRock01.m3d");
|
g.model = LoadModel(&g.rd, "models/Tree01.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,32 +103,16 @@ 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);
|
||||||
@ -239,56 +123,36 @@ 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);
|
||||||
|
|
||||||
BeginRendering(&g.rd, &g.draw_image, &g.depth_image);
|
//DrawRect(&g.rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0));
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
Node!(Model)* model = g.models.first;
|
FinishFrame(&g.rd);
|
||||||
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;
|
||||||
@ -305,25 +169,13 @@ 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, 2.0);
|
Vec3 pos = Vec3(0.0, 0.0, 5.0);
|
||||||
f32 pitch = 0.0;
|
f32 pitch = 0.0;
|
||||||
f32 yaw = 0.0;
|
f32 yaw = 0.0;
|
||||||
}
|
}
|
||||||
@ -331,6 +183,8 @@ 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];
|
||||||
@ -377,28 +231,3 @@ 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,9 +14,6 @@ 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, BeginRendering, SetUniform, PrepComputeDrawImage, Dispatch, SubmitAndPresent, BeginFrame, WaitIdle, PushConstants, BindBuffers, SetClearColor, ImageBarrier, CreateImageView, GetDrawImageFormat, FinishRendering, UpdateAuxImage, ClearColor, SubmitAndPresent;
|
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers;
|
||||||
import assets;
|
import assets;
|
||||||
import std.math.traits : isNaN;
|
import std.math.traits : isNaN;
|
||||||
import util : Logf;
|
import util : Logf;
|
||||||
@ -25,20 +25,6 @@ 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,
|
||||||
@ -47,35 +33,24 @@ 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 : VkBufferUsageFlagBits
|
enum BufferType : int
|
||||||
{
|
{
|
||||||
None = cast(VkBufferUsageFlagBits)0,
|
None = 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();
|
||||||
@ -117,8 +92,6 @@ struct GfxPipelineInfo
|
|||||||
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
|
||||||
@ -128,6 +101,19 @@ struct CompPipelineInfo
|
|||||||
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;
|
||||||
@ -138,8 +124,6 @@ struct Extent
|
|||||||
{
|
{
|
||||||
u32 x;
|
u32 x;
|
||||||
u32 y;
|
u32 y;
|
||||||
alias x w;
|
|
||||||
alias y h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIVertex
|
struct UIVertex
|
||||||
@ -177,58 +161,6 @@ 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
|
||||||
@ -274,6 +206,12 @@ 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)
|
||||||
{
|
{
|
||||||
@ -293,9 +231,9 @@ SetUniform(Renderer* rd, GlobalUniforms* uniforms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
BeginRendering(Renderer* rd, ImageView* draw_image, ImageView* depth_image)
|
BeginRender(Renderer* rd)
|
||||||
{
|
{
|
||||||
BeginRendering(&rd.vk, draw_image, depth_image);
|
BeginRender(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
@ -322,12 +260,6 @@ 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)
|
||||||
{
|
{
|
||||||
@ -439,7 +371,6 @@ 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];
|
||||||
@ -455,12 +386,7 @@ 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;
|
||||||
case m3dp_map_D:
|
default: break;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,10 +438,8 @@ LoadModel(Renderer* rd, string name)
|
|||||||
|
|
||||||
m3dv_t* vertex;
|
m3dv_t* vertex;
|
||||||
|
|
||||||
u32[] indices = AllocArray!(u32)(&rd.arena, m3d.numface * 3);
|
u32[] indices = AllocArray!(u32)(&rd.temp_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)
|
||||||
{
|
{
|
||||||
@ -551,11 +475,6 @@ 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)
|
||||||
@ -601,55 +520,11 @@ 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)
|
||||||
{
|
{
|
||||||
@ -682,85 +557,3 @@ 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,7 +4,6 @@ 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;
|
||||||
@ -53,7 +52,6 @@ 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 = [
|
||||||
@ -77,6 +75,11 @@ 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,
|
||||||
@ -90,7 +93,6 @@ enum StepInitialized : u32
|
|||||||
Swapchain,
|
Swapchain,
|
||||||
DrawImages,
|
DrawImages,
|
||||||
Descriptors,
|
Descriptors,
|
||||||
Pipelines,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
alias SI = StepInitialized;
|
alias SI = StepInitialized;
|
||||||
@ -106,6 +108,22 @@ 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;
|
||||||
@ -115,6 +133,13 @@ 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;
|
||||||
@ -173,7 +198,6 @@ 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;
|
||||||
@ -196,12 +220,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,8 +294,6 @@ 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;
|
||||||
|
|
||||||
@ -416,7 +432,6 @@ 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);
|
||||||
@ -512,30 +527,27 @@ BeginFrame(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BeginRendering(Vulkan* vk, ImageView* draw_image, ImageView* depth_image)
|
BeginRender(Vulkan* vk)
|
||||||
{
|
{
|
||||||
// TODO: probably get rid of these
|
// TODO: probably get rid of these
|
||||||
Transition(vk.cmds[vk.frame_index], draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], &vk.draw_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
Transition(vk.cmds[vk.frame_index], depth_image, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
Transition(vk.cmds[vk.frame_index], &vk.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: draw_image.view,
|
imageView: vk.draw_image.view,
|
||||||
imageLayout: draw_image.layout,
|
imageLayout: vk.draw_image.layout,
|
||||||
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)
|
loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, // 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: depth_image.view,
|
imageView: vk.depth_image.view,
|
||||||
imageLayout: depth_image.layout,
|
imageLayout: vk.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,
|
||||||
};
|
};
|
||||||
@ -557,21 +569,6 @@ BeginRendering(Vulkan* vk, ImageView* draw_image, ImageView* depth_image)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -579,13 +576,7 @@ PrepComputeDrawImage(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FinishRendering(Vulkan* vk)
|
FinishFrame(Vulkan* vk)
|
||||||
{
|
|
||||||
vkCmdEndRendering(vk.cmds[vk.frame_index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SubmitAndPresent(Vulkan* vk, ImageView* draw_image)
|
|
||||||
{
|
{
|
||||||
scope(exit)
|
scope(exit)
|
||||||
{
|
{
|
||||||
@ -597,7 +588,9 @@ SubmitAndPresent(Vulkan* vk, ImageView* draw_image)
|
|||||||
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];
|
||||||
|
|
||||||
Transition(vk.cmds[vk.frame_index], draw_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
vkCmdEndRendering(vk.cmds[vk.frame_index]);
|
||||||
|
|
||||||
|
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,
|
||||||
@ -605,7 +598,7 @@ SubmitAndPresent(Vulkan* vk, ImageView* draw_image)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 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], &draw_image.base, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, extent, extent);
|
Copy(vk.cmds[vk.frame_index], &vk.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);
|
||||||
|
|
||||||
@ -743,7 +736,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, FMT.RGBA_UNORM, IU.Texture);
|
CreateImageView(vk, view, w, h);
|
||||||
|
|
||||||
if (ch == 4)
|
if (ch == 4)
|
||||||
{
|
{
|
||||||
@ -756,7 +749,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, IU.Convert);
|
CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32);
|
||||||
|
|
||||||
WriteConvDescriptor(vk, &buf);
|
WriteConvDescriptor(vk, &buf);
|
||||||
WriteConvDescriptor(vk, &conv_view);
|
WriteConvDescriptor(vk, &conv_view);
|
||||||
@ -860,25 +853,7 @@ FinishComputePass(Vulkan* vk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
CreateBufferView(Vulkan* vk, BufferView* view, u64 size, Format format)
|
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.RGBA_UNORM)
|
||||||
{
|
|
||||||
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,
|
||||||
@ -893,7 +868,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
|
|||||||
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: usage,
|
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),
|
||||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
samples: VK_SAMPLE_COUNT_1_BIT,
|
||||||
extent: {
|
extent: {
|
||||||
width: w,
|
width: w,
|
||||||
@ -909,6 +884,9 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
|
|||||||
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");
|
||||||
@ -919,7 +897,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
|
|||||||
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
viewType: VK_IMAGE_VIEW_TYPE_2D,
|
||||||
format: format,
|
format: format,
|
||||||
subresourceRange: {
|
subresourceRange: {
|
||||||
aspectMask: (depth_image ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
levelCount: 1,
|
levelCount: 1,
|
||||||
layerCount: 1,
|
layerCount: 1,
|
||||||
},
|
},
|
||||||
@ -928,13 +906,6 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU
|
|||||||
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
|
||||||
@ -1006,27 +977,6 @@ 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)
|
||||||
{
|
{
|
||||||
@ -1365,19 +1315,13 @@ 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: cast(VkFormat*)&build_info.draw_image.format,
|
pColorAttachmentFormats: &vk.draw_image.format,
|
||||||
depthAttachmentFormat: build_info.depth_image.format,
|
depthAttachmentFormat: vk.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_TRUE,
|
blendEnable: VK_FALSE,
|
||||||
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 = {
|
||||||
@ -1411,36 +1355,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_FRAGMENT_BIT,
|
stage: VK_SHADER_STAGE_VERTEX_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_VERTEX_BIT,
|
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
pName: "main",
|
pName: "main",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Arena* arena = &vk.frame_arenas[0];
|
Arena* arena = &vk.frame_arenas[0];
|
||||||
|
|
||||||
u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader);
|
|
||||||
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
||||||
|
u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader);
|
||||||
|
|
||||||
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
||||||
|
|
||||||
Result!(Shader) frag_module = BuildShader(vk, frag_bytes);
|
|
||||||
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
||||||
|
Result!(Shader) frag_module = BuildShader(vk, frag_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, frag_module.value);
|
|
||||||
Destroy(vk, vert_module.value);
|
Destroy(vk, vert_module.value);
|
||||||
|
Destroy(vk, frag_module.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
__traits(getMember, shader_info.ptr + 0, "module") = frag_module.value;
|
__traits(getMember, shader_info.ptr + 0, "module") = vert_module.value;
|
||||||
__traits(getMember, shader_info.ptr + 1, "module") = vert_module.value;
|
__traits(getMember, shader_info.ptr + 1, "module") = frag_module.value;
|
||||||
|
|
||||||
VkSpecializationInfo vert_spec_info = {
|
VkSpecializationInfo vert_spec_info = {
|
||||||
dataSize: build_info.vert_spec.size,
|
dataSize: build_info.vert_spec.size,
|
||||||
@ -1531,25 +1475,6 @@ 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)
|
||||||
{
|
{
|
||||||
@ -1633,13 +1558,6 @@ 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;
|
||||||
@ -1647,35 +1565,6 @@ 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)
|
||||||
{
|
{
|
||||||
@ -1702,7 +1591,6 @@ 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 = {
|
||||||
@ -1718,17 +1606,7 @@ InitDescriptors(Vulkan* vk)
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayoutBinding[] shared_bindings = [
|
VkDescriptorBindingFlags[4] shared_binding_flags;
|
||||||
{ 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 = {
|
||||||
@ -1737,6 +1615,13 @@ 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,
|
||||||
@ -1868,80 +1753,20 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorImageInfo oit_sample_info = {
|
VkWriteDescriptorSet write = {
|
||||||
sampler: vk.oit_sampler,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkWriteDescriptorSet[] writes = [
|
|
||||||
{
|
|
||||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
dstSet: vk.desc_sets[DT.Shared],
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
dstBinding: 3,
|
dstBinding: 3,
|
||||||
descriptorCount: 1,
|
descriptorCount: 1,
|
||||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
pImageInfo: &sampler_info,
|
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);
|
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
||||||
|
|
||||||
WriteDrawImageDesc(vk);
|
WriteDrawImageDesc(vk);
|
||||||
}
|
}
|
||||||
@ -1949,31 +1774,6 @@ 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)
|
||||||
{
|
{
|
||||||
@ -2254,7 +2054,7 @@ GetDrawImageFormat(Vulkan* vk)
|
|||||||
format,
|
format,
|
||||||
VK_IMAGE_TYPE_2D,
|
VK_IMAGE_TYPE_2D,
|
||||||
VK_IMAGE_TILING_OPTIMAL,
|
VK_IMAGE_TILING_OPTIMAL,
|
||||||
IU.Draw,
|
VK_DRAW_IMAGE_USAGE_FLAGS,
|
||||||
0,
|
0,
|
||||||
&props
|
&props
|
||||||
);
|
);
|
||||||
@ -2280,14 +2080,91 @@ CreateDrawImages(Vulkan* vk)
|
|||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
Format draw_format = cast(Format)GetDrawImageFormat(vk);
|
VkFormat draw_format = GetDrawImageFormat(vk);
|
||||||
Format depth_format = cast(Format)VK_FORMAT_D32_SFLOAT;
|
VkFormat depth_format = VK_FORMAT_D32_SFLOAT;
|
||||||
|
|
||||||
u32 w = vk.swapchain_extent.width;
|
VmaAllocationCreateInfo alloc_info = {
|
||||||
u32 h = vk.swapchain_extent.height;
|
usage: VMA_MEMORY_USAGE_GPU_ONLY,
|
||||||
|
requiredFlags: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
CreateImageView(vk, &vk.draw_image, w, h, draw_format, IU.Draw, false);
|
VkImageCreateInfo image_info = {
|
||||||
CreateImageView(vk, &vk.depth_image, w, h, depth_format, IU.Depth, true);
|
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,
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@ -2341,7 +2218,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: IU.Swapchain,
|
imageUsage: VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
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,
|
||||||
@ -2529,7 +2406,6 @@ 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,
|
||||||
@ -2551,7 +2427,6 @@ InitDevice(Vulkan* vk)
|
|||||||
shaderStorageBufferArrayDynamicIndexing: VK_TRUE,
|
shaderStorageBufferArrayDynamicIndexing: VK_TRUE,
|
||||||
shaderStorageImageArrayDynamicIndexing: VK_TRUE,
|
shaderStorageImageArrayDynamicIndexing: VK_TRUE,
|
||||||
samplerAnisotropy: VK_TRUE,
|
samplerAnisotropy: VK_TRUE,
|
||||||
fragmentStoresAndAtomics: VK_TRUE,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2621,7 +2496,6 @@ 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;
|
||||||
@ -2631,7 +2505,6 @@ 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;
|
||||||
@ -2916,21 +2789,6 @@ 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,7 +58,6 @@ 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;
|
||||||
@ -155,7 +154,6 @@ 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,6 +1,7 @@
|
|||||||
#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;
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ 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)
|
||||||
@ -43,6 +45,7 @@ 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)
|
||||||
@ -50,6 +53,7 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
#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, index = 0) out vec4 FragColor;
|
layout (location = 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,57 +25,10 @@ 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);
|
||||||
|
|
||||||
vec4 out_col = CalculateDirectionalLight(col, tex_col, G.light_color, G.light_direction, FragData.normal);
|
FragColor = 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,8 +2,6 @@
|
|||||||
// **** 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;
|
||||||
@ -22,20 +20,6 @@ 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 {
|
||||||
@ -45,13 +29,10 @@ 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,13 +73,10 @@ 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