Skip to content

Commit

Permalink
graphics: Implement drawSceneNormals3D.
Browse files Browse the repository at this point in the history
  • Loading branch information
fubark committed Jun 18, 2022
1 parent 97f20dd commit ab43d93
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 34 deletions.
18 changes: 17 additions & 1 deletion graphics/src/backend/gpu/batcher.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const ShaderType = enum(u3) {
Wireframe = 4,
Custom = 5,
Anim3D = 6,
Normal = 7,
};

const PreFlushTask = struct {
Expand Down Expand Up @@ -225,6 +226,14 @@ pub const Batcher = struct {
self.setTexture(image);
}

pub fn beginNormal(self: *Self, cam_loc: stdx.math.Vec3) void {
if (self.cur_shader_type != .Normal) {
self.endCmd();
self.cur_shader_type = .Normal;
return;
}
}

pub fn beginTex3D(self: *Self, image: ImageTex) void {
if (self.cur_shader_type != .Tex3D) {
self.endCmd();
Expand Down Expand Up @@ -464,12 +473,19 @@ pub const Batcher = struct {
self.inner.cur_tex_desc_set,
self.inner.joints_desc_set,
};
vk.cmdBindDescriptorSets(cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 2, &desc_sets, 0, null);
vk.cmdBindDescriptorSets(cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, desc_sets.len, &desc_sets, 0, null);
vk.cmdPushConstants(cmd_buf, pipeline.layout, vk.VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * 4, &self.mvp.mat);
},
.Wireframe => {
const pipeline = self.inner.pipelines.wireframe_pipeline;
vk.cmdBindPipeline(cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
// Must bind even though it does not use the texture since the pipeline was created with the descriptor layout.
vk.cmdBindDescriptorSets(cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, &self.inner.cur_tex_desc_set, 0, null);
vk.cmdPushConstants(cmd_buf, pipeline.layout, vk.VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * 4, &self.mvp.mat);
},
.Normal => {
const pipeline = self.inner.pipelines.norm_pipeline;
vk.cmdBindPipeline(cmd_buf, vk.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
vk.cmdPushConstants(cmd_buf, pipeline.layout, vk.VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * 4, &self.mvp.mat);
},
.Tex => {
Expand Down
56 changes: 48 additions & 8 deletions graphics/src/backend/gpu/graphics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,15 @@ pub const Graphics = struct {
}

pub fn initVK(self: *Self, alloc: std.mem.Allocator, dpr: f32, vk_ctx: VkContext) void {
const physical = vk_ctx.physical;
const device = vk_ctx.device;
const fb_size = vk_ctx.framebuffer_size;
const pass = vk_ctx.pass;

self.initDefault(alloc, dpr);
self.inner.ctx = vk_ctx;
self.inner.tex_desc_set_layout = gvk.createTexDescriptorSetLayout(vk_ctx.device);
self.inner.desc_pool = gvk.createDescriptorPool(vk_ctx.device);
self.inner.tex_desc_set_layout = gvk.createTexDescriptorSetLayout(device);
self.inner.desc_pool = gvk.createDescriptorPool(device);
self.initCommon(alloc);

const vert_buf = gvk.buffer.createVertexBuffer(vk_ctx.physical, vk_ctx.device, 40 * 20000);
Expand All @@ -182,12 +187,13 @@ pub const Graphics = struct {
const joints_desc_set = gvk.descriptor.createDescriptorSet(vk_ctx.device, self.inner.desc_pool, self.inner.joints_desc_set_layout);
gvk.descriptor.updateStorageBufferDescriptorSet(vk_ctx.device, joints_desc_set, storage_buf.buf, 1, 0, 4*16 * 1000);

self.inner.pipelines.tex_pipeline = gvk.createTexPipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size, self.inner.tex_desc_set_layout, true, false);
self.inner.pipelines.tex_pipeline_2d = gvk.createTexPipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size, self.inner.tex_desc_set_layout, false, false);
self.inner.pipelines.anim_pipeline = gvk.createAnimPipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size, self.inner.joints_desc_set_layout, self.inner.tex_desc_set_layout);
self.inner.pipelines.wireframe_pipeline = gvk.createTexPipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size, self.inner.tex_desc_set_layout, true, true);
self.inner.pipelines.gradient_pipeline_2d = gvk.createGradientPipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size);
self.inner.pipelines.plane_pipeline = gvk.createPlanePipeline(vk_ctx.device, vk_ctx.pass, vk_ctx.framebuffer_size);
self.inner.pipelines.tex_pipeline = gvk.createTexPipeline(device, pass, fb_size, self.inner.tex_desc_set_layout, true, false);
self.inner.pipelines.tex_pipeline_2d = gvk.createTexPipeline(device, pass, fb_size, self.inner.tex_desc_set_layout, false, false);
self.inner.pipelines.norm_pipeline = gvk.createNormPipeline(device, pass, fb_size);
self.inner.pipelines.anim_pipeline = gvk.createAnimPipeline(device, pass, fb_size, self.inner.joints_desc_set_layout, self.inner.tex_desc_set_layout);
self.inner.pipelines.wireframe_pipeline = gvk.createTexPipeline(device, pass, fb_size, self.inner.tex_desc_set_layout, true, true);
self.inner.pipelines.gradient_pipeline_2d = gvk.createGradientPipeline(device, pass, fb_size);
self.inner.pipelines.plane_pipeline = gvk.createPlanePipeline(device, pass, fb_size);

self.batcher = Batcher.initVK(alloc, vert_buf, index_buf, storage_buf, joints_desc_set, vk_ctx, self.inner.pipelines, &self.image_store);
}
Expand Down Expand Up @@ -1774,6 +1780,40 @@ pub const Graphics = struct {
self.batcher.beginMvp(cur_mvp);
}

pub fn drawSceneNormals3D(self: *Self, xform: Transform, scene: graphics.GLTFscene) void {
for (scene.mesh_nodes) |id| {
const node = scene.nodes[id];
self.drawMeshNormals3D(xform, node.mesh);
}
}

pub fn drawMeshNormals3D(self: *Self, xform: Transform, mesh: graphics.Mesh3D) void {
self.batcher.beginNormal(self.cur_cam_world_pos);
const cur_mvp = self.batcher.mvp;
// Create temp mvp.
const vp = self.view_transform.getAppliedTransform(self.cur_proj_transform);
const mvp = xform.getAppliedTransform(vp);
self.batcher.beginMvp(mvp);

if (!self.batcher.ensureUnusedBuffer(mesh.verts.len*2, mesh.verts.len*2)) {
self.batcher.endCmd();
}
const vert_start = self.batcher.mesh.getNextIndexId();
const norm_len = 1;
for (mesh.verts) |vert, i| {
var new_vert = vert;
new_vert.setColor(Color.Blue);
self.batcher.mesh.addVertex(&new_vert);
new_vert.setColor(Color.Red);
new_vert.setXYZ(new_vert.pos_x + new_vert.norm_x * norm_len, new_vert.pos_y + new_vert.norm_y * norm_len, new_vert.pos_z + new_vert.norm_z * norm_len);
self.batcher.mesh.addVertex(&new_vert);
self.batcher.mesh.addIndex(vert_start + 2*@intCast(u16, i));
self.batcher.mesh.addIndex(vert_start + 2*@intCast(u16, i) + 1);
}

self.batcher.beginMvp(cur_mvp);
}

pub fn drawMesh3D(self: *Self, xform: Transform, mesh: graphics.Mesh3D) void {
if (mesh.image_id) |image_id| {
const img = self.image_store.images.getNoCheck(image_id);
Expand Down
16 changes: 11 additions & 5 deletions graphics/src/backend/gpu/vertex.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ pub const TexShaderVertex = packed struct {
pos_x: f32,
pos_y: f32,
pos_z: f32,
// TODO: Might be able to remove w and set to 1 in shader.
pos_w: f32,
/// Used for lighting.
norm_x: f32,
norm_y: f32,
norm_z: f32,
uv_x: f32,
uv_y: f32,
color_r: f32,
Expand Down Expand Up @@ -65,10 +70,11 @@ pub const TexShaderVertex = packed struct {
};

test "TexShaderVertex" {
try t.eq(@sizeOf(TexShaderVertex), 4*4 + 4*2 + 4*4 + 2*4 + 4);
try t.eq(@sizeOf(TexShaderVertex), 4*4 + 4*3 + 4*2 + 4*4 + 2*4 + 4);
try t.eq(@offsetOf(TexShaderVertex, "pos_x"), 0);
try t.eq(@offsetOf(TexShaderVertex, "uv_x"), 4*4);
try t.eq(@offsetOf(TexShaderVertex, "color_r"), 4*4 + 4*2);
try t.eq(@offsetOf(TexShaderVertex, "joints"), 4*4 + 4*2 + 4*4);
try t.eq(@offsetOf(TexShaderVertex, "weights"), 4*4 + 4*2 + 4*4 + 2*4);
try t.eq(@offsetOf(TexShaderVertex, "norm_x"), 4*4);
try t.eq(@offsetOf(TexShaderVertex, "uv_x"), 4*4 + 4*3);
try t.eq(@offsetOf(TexShaderVertex, "color_r"), 4*4 + 4*3 + 4*2);
try t.eq(@offsetOf(TexShaderVertex, "joints"), 4*4 + 4*3 + 4*2 + 4*4);
try t.eq(@offsetOf(TexShaderVertex, "weights"), 4*4 + 4*3 + 4*2 + 4*4 + 2*4);
}
87 changes: 82 additions & 5 deletions graphics/src/backend/vk/graphics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,11 @@ pub fn createPlanePipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_dim:

const vert_src align(4) = shaders.plane_vert_spv;
const frag_src align(4) = shaders.plane_frag_spv;
return pipeline.createDefaultPipeline(device, pass, view_dim, &vert_src, &frag_src, pvis_info, pl_info, .{ .depth_test = true });
return pipeline.createDefaultPipeline(device, pass, view_dim, pvis_info, pl_info, .{
.vert_spv = &vert_src,
.frag_spv = &frag_src,
.depth_test = true,
});
}

pub fn createGradientPipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_dim: vk.VkExtent2D) Pipeline {
Expand Down Expand Up @@ -414,7 +418,9 @@ pub fn createGradientPipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_d

const vert_src align(4) = shaders.gradient_vert_spv;
const frag_src align(4) = shaders.gradient_frag_spv;
return pipeline.createDefaultPipeline(device, pass, view_dim, &vert_src, &frag_src, pvis_info, pl_info, .{
return pipeline.createDefaultPipeline(device, pass, view_dim, pvis_info, pl_info, .{
.vert_spv = &vert_src,
.frag_spv = &frag_src,
.depth_test = false,
});
}
Expand Down Expand Up @@ -501,7 +507,9 @@ pub fn createAnimPipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_dim:

const vert_src align(4) = shaders.anim_vert_spv;
const frag_src align(4) = shaders.anim_frag_spv;
return pipeline.createDefaultPipeline(device, pass, view_dim, &vert_src, &frag_src, pvis_info, pl_info, .{
return pipeline.createDefaultPipeline(device, pass, view_dim, pvis_info, pl_info, .{
.vert_spv = &vert_src,
.frag_spv = &frag_src,
.depth_test = true,
.line_mode = false,
});
Expand Down Expand Up @@ -564,12 +572,74 @@ pub fn createTexPipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_dim: v

const vert_src align(4) = shaders.tex_vert_spv;
const frag_src align(4) = shaders.tex_frag_spv;
return pipeline.createDefaultPipeline(device, pass, view_dim, &vert_src, &frag_src, pvis_info, pl_info, .{
return pipeline.createDefaultPipeline(device, pass, view_dim, pvis_info, pl_info, .{
.vert_spv = &vert_src,
.frag_spv = &frag_src,
.depth_test = depth_test,
.line_mode = wireframe,
});
}

pub fn createNormPipeline(device: vk.VkDevice, pass: vk.VkRenderPass, view_dim: vk.VkExtent2D) Pipeline {
const bind_descriptors = [_]vk.VkVertexInputBindingDescription{
vk.VkVertexInputBindingDescription{
.binding = 0,
.stride = @sizeOf(gpu.TexShaderVertex),
.inputRate = vk.VK_VERTEX_INPUT_RATE_VERTEX,
},
};
const attr_descriptors = [_]vk.VkVertexInputAttributeDescription{
vk.VkVertexInputAttributeDescription{
.binding = 0,
.location = 0,
.format = vk.VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = @offsetOf(gpu.TexShaderVertex, "pos_x"),
},
vk.VkVertexInputAttributeDescription{
.binding = 0,
.location = 1,
.format = vk.VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = @offsetOf(gpu.TexShaderVertex, "color_r"),
},
};
const pvis_info = vk.VkPipelineVertexInputStateCreateInfo{
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = bind_descriptors.len,
.pVertexBindingDescriptions = &bind_descriptors,
.vertexAttributeDescriptionCount = attr_descriptors.len,
.pVertexAttributeDescriptions = &attr_descriptors,
.pNext = null,
.flags = 0,
};

const push_const_range = [_]vk.VkPushConstantRange{
vk.VkPushConstantRange{
.offset = 0,
.size = @sizeOf(stdx.math.Mat4),
.stageFlags = vk.VK_SHADER_STAGE_VERTEX_BIT,
},
};
const pl_info = vk.VkPipelineLayoutCreateInfo{
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 0,
.pSetLayouts = null,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_const_range,
.pNext = null,
.flags = 0,
};

const vert_src align(4) = shaders.norm_vert_spv;
const frag_src align(4) = shaders.norm_frag_spv;
return pipeline.createDefaultPipeline(device, pass, view_dim, pvis_info, pl_info, .{
.topology = vk.VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
.vert_spv = &vert_src,
.frag_spv = &frag_src,
.depth_test = false,
.line_mode = false,
});
}

// TODO: Implement a list of pools. Once a pool runs out of space a new one is created.
/// Currently a fixed max of 100 textures.
pub fn createDescriptorPool(device: vk.VkDevice) vk.VkDescriptorPool {
Expand All @@ -579,9 +649,14 @@ pub fn createDescriptorPool(device: vk.VkDevice) vk.VkDescriptorPool {
.@"type" = vk.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 100,
},
// For joints.
// Joints + materials buffer.
vk.VkDescriptorPoolSize{
.@"type" = vk.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 2,
},
// For Camera struct.
vk.VkDescriptorPoolSize{
.@"type" = vk.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
},
};
Expand Down Expand Up @@ -612,6 +687,7 @@ pub const Pipelines = struct {
anim_pipeline: Pipeline,
gradient_pipeline_2d: Pipeline,
plane_pipeline: Pipeline,
norm_pipeline: Pipeline,

pub fn deinit(self: Pipelines, device: vk.VkDevice) void {
self.wireframe_pipeline.deinit(device);
Expand All @@ -620,6 +696,7 @@ pub const Pipelines = struct {
self.anim_pipeline.deinit(device);
self.gradient_pipeline_2d.deinit(device);
self.plane_pipeline.deinit(device);
self.norm_pipeline.deinit(device);
}
};

Expand Down
49 changes: 39 additions & 10 deletions graphics/src/backend/vk/pipeline.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,29 @@ pub const Pipeline = struct {
};

const PipelineOptions = struct {
topology: vk.VkPrimitiveTopology = vk.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
vert_spv: []align(4) const u8,
frag_spv: []align(4) const u8,
geom_spv: []align(4) const u8 = "",

depth_test: bool = true,

// Draw line vs filling triangles.
// Only for drawing lines over a triangle topology. eg. LINES topology doesn't need this.
line_mode: bool = false,
};

pub fn createDefaultPipeline(
device: vk.VkDevice,
pass: vk.VkRenderPass,
view_dim: vk.VkExtent2D,
vert_spv: []align(4) const u8,
frag_spv: []align(4) const u8,
pvis_info: vk.VkPipelineVertexInputStateCreateInfo,
pl_info: vk.VkPipelineLayoutCreateInfo,
opts: PipelineOptions,
) Pipeline {
const vert_mod = gvk.shader.createShaderModule(device, vert_spv);
const frag_mod = gvk.shader.createShaderModule(device, frag_spv);
const vert_mod = gvk.shader.createShaderModule(device, opts.vert_spv);
defer vk.destroyShaderModule(device, vert_mod, null);
const frag_mod = gvk.shader.createShaderModule(device, opts.frag_spv);
defer vk.destroyShaderModule(device, frag_mod, null);

// ShaderStages
const vert_pss_info = vk.VkPipelineShaderStageCreateInfo{
Expand All @@ -51,12 +56,38 @@ pub fn createDefaultPipeline(
.flags = 0,
.pSpecializationInfo = null,
};
const stages = [_]vk.VkPipelineShaderStageCreateInfo{ vert_pss_info, frag_pss_info };

var stages: []const vk.VkPipelineShaderStageCreateInfo = &.{
vert_pss_info,
frag_pss_info,
};
var geom_mod: vk.VkShaderModule = undefined;
if (opts.geom_spv.len > 0) {
geom_mod = gvk.shader.createShaderModule(device, opts.geom_spv);
stages = &[_]vk.VkPipelineShaderStageCreateInfo{
vert_pss_info,
frag_pss_info,
vk.VkPipelineShaderStageCreateInfo{
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = vk.VK_SHADER_STAGE_GEOMETRY_BIT,
.module = geom_mod,
.pName = "main",
.pNext = null,
.flags = 0,
.pSpecializationInfo = null,
},
};
}
defer {
if (opts.geom_spv.len > 0) {
defer vk.destroyShaderModule(device, geom_mod, null);
}
}

// InputAssemblyState
const pias_info = vk.VkPipelineInputAssemblyStateCreateInfo{
.sType = vk.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = vk.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.topology = opts.topology,
.primitiveRestartEnable = vk.VK_FALSE,
.pNext = null,
.flags = 0,
Expand Down Expand Up @@ -184,7 +215,7 @@ pub fn createDefaultPipeline(
const g_pipelines = [_]vk.VkGraphicsPipelineCreateInfo{vk.VkGraphicsPipelineCreateInfo{
.sType = vk.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = @intCast(u32, stages.len),
.pStages = &stages,
.pStages = stages.ptr,
.pVertexInputState = &pvis_info,
.pInputAssemblyState = &pias_info,
.pViewportState = &pvs_info,
Expand All @@ -206,8 +237,6 @@ pub fn createDefaultPipeline(
var pipeln: vk.VkPipeline = undefined;
res = vk.createGraphicsPipelines(device, null, @intCast(u32, g_pipelines.len), &g_pipelines, null, &pipeln);
vk.assertSuccess(res);
vk.destroyShaderModule(device, vert_mod, null);
vk.destroyShaderModule(device, frag_mod, null);
return .{
.pipeline = pipeln,
.layout = pipeline_layout,
Expand Down
Loading

0 comments on commit ab43d93

Please sign in to comment.