mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Separate the face buffer based on LOD (#1609)
- reduces allocator overhead (less items in the free list of each buffer) - reduces the chance to run out of fake GPU memory (we can now effectively store 50% more faces than before) - reduces the chance to run out of actual GPU memory - reduces height of lag spikes of buffer resizes (but increases their frequency) - makes it more clear in which LOD (LOD1) the main memory bottlenecks are - reduces the occlusion culling lag (#1161) after disocclusion of parts of the screen (roughly halving the impact). It however does decrease the granularity of timing information, since I can no longer look at the passes separately, but I think that's a fair price to pay - [x] cleanup
This commit is contained in:
parent
b1af1be3d2
commit
bf7d20f11e
@ -2610,9 +2610,11 @@ pub fn generateBlockTexture(blockType: u16) Texture {
|
|||||||
face.position.lightIndex = 0;
|
face.position.lightIndex = 0;
|
||||||
}
|
}
|
||||||
var allocation: SubAllocation = .{.start = 0, .len = 0};
|
var allocation: SubAllocation = .{.start = 0, .len = 0};
|
||||||
main.renderer.chunk_meshing.faceBuffer.uploadData(faceData.items, &allocation);
|
main.renderer.chunk_meshing.faceBuffers[0].uploadData(faceData.items, &allocation);
|
||||||
|
defer main.renderer.chunk_meshing.faceBuffers[0].free(allocation);
|
||||||
var lightAllocation: SubAllocation = .{.start = 0, .len = 0};
|
var lightAllocation: SubAllocation = .{.start = 0, .len = 0};
|
||||||
main.renderer.chunk_meshing.lightBuffer.uploadData(&.{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, &lightAllocation);
|
main.renderer.chunk_meshing.lightBuffers[0].uploadData(&.{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, &lightAllocation);
|
||||||
|
defer main.renderer.chunk_meshing.lightBuffers[0].free(lightAllocation);
|
||||||
|
|
||||||
{
|
{
|
||||||
const i = 6; // Easily switch between the 8 rotations.
|
const i = 6; // Easily switch between the 8 rotations.
|
||||||
@ -2671,7 +2673,6 @@ pub fn generateBlockTexture(blockType: u16) Texture {
|
|||||||
|
|
||||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0);
|
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
main.renderer.chunk_meshing.faceBuffer.free(allocation);
|
|
||||||
c.glViewport(0, 0, main.Window.width, main.Window.height);
|
c.glViewport(0, 0, main.Window.width, main.Window.height);
|
||||||
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
return texture;
|
return texture;
|
||||||
|
@ -83,28 +83,18 @@ pub fn render() void {
|
|||||||
}
|
}
|
||||||
draw.print("Mesh Queue size: {}", .{main.renderer.mesh_storage.updatableList.items.len}, 0, y, 8, .left);
|
draw.print("Mesh Queue size: {}", .{main.renderer.mesh_storage.updatableList.items.len}, 0, y, 8, .left);
|
||||||
y += 8;
|
y += 8;
|
||||||
{
|
for(0..main.settings.highestLod + 1) |lod| {
|
||||||
const faceDataSize: usize = @sizeOf(main.renderer.chunk_meshing.FaceData);
|
const faceDataSize: usize = @sizeOf(main.renderer.chunk_meshing.FaceData);
|
||||||
const size: usize = main.renderer.chunk_meshing.faceBuffer.capacity*faceDataSize;
|
const size: usize = main.renderer.chunk_meshing.faceBuffers[lod].capacity*faceDataSize;
|
||||||
const used: usize = main.renderer.chunk_meshing.faceBuffer.used*faceDataSize;
|
const used: usize = main.renderer.chunk_meshing.faceBuffers[lod].used*faceDataSize;
|
||||||
var largestFreeBlock: usize = 0;
|
draw.print("ChunkMesh memory LOD{}: {} MiB / {} MiB", .{lod, used >> 20, size >> 20}, 0, y, 8, .left);
|
||||||
for(main.renderer.chunk_meshing.faceBuffer.freeBlocks.items) |freeBlock| {
|
|
||||||
largestFreeBlock = @max(largestFreeBlock, freeBlock.len);
|
|
||||||
}
|
|
||||||
const fragmentation = size - used - largestFreeBlock*faceDataSize;
|
|
||||||
draw.print("ChunkMesh memory: {} MiB / {} MiB (fragmentation: {} MiB)", .{used >> 20, size >> 20, fragmentation >> 20}, 0, y, 8, .left);
|
|
||||||
y += 8;
|
y += 8;
|
||||||
}
|
}
|
||||||
{
|
for(0..main.settings.highestLod + 1) |lod| {
|
||||||
const lightDataSize: usize = @sizeOf(u32);
|
const lightDataSize: usize = @sizeOf(u32);
|
||||||
const size: usize = main.renderer.chunk_meshing.lightBuffer.capacity*lightDataSize;
|
const size: usize = main.renderer.chunk_meshing.lightBuffers[lod].capacity*lightDataSize;
|
||||||
const used: usize = main.renderer.chunk_meshing.lightBuffer.used*lightDataSize;
|
const used: usize = main.renderer.chunk_meshing.lightBuffers[lod].used*lightDataSize;
|
||||||
var largestFreeBlock: usize = 0;
|
draw.print("Light memory LOD{}: {} MiB / {} MiB", .{lod, used >> 20, size >> 20}, 0, y, 8, .left);
|
||||||
for(main.renderer.chunk_meshing.lightBuffer.freeBlocks.items) |freeBlock| {
|
|
||||||
largestFreeBlock = @max(largestFreeBlock, freeBlock.len);
|
|
||||||
}
|
|
||||||
const fragmentation = size - used - largestFreeBlock*lightDataSize;
|
|
||||||
draw.print("Light memory: {} MiB / {} MiB (fragmentation: {} MiB)", .{used >> 20, size >> 20, fragmentation >> 20}, 0, y, 8, .left);
|
|
||||||
y += 8;
|
y += 8;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -17,14 +17,11 @@ pub const Samples = enum(u8) {
|
|||||||
skybox,
|
skybox,
|
||||||
animation,
|
animation,
|
||||||
chunk_rendering_preparation,
|
chunk_rendering_preparation,
|
||||||
chunk_rendering_previous_visible,
|
chunk_rendering,
|
||||||
chunk_rendering_occlusion_test,
|
|
||||||
chunk_rendering_new_visible,
|
|
||||||
entity_rendering,
|
entity_rendering,
|
||||||
block_entity_rendering,
|
block_entity_rendering,
|
||||||
particle_rendering,
|
particle_rendering,
|
||||||
transparent_rendering_preparation,
|
transparent_rendering_preparation,
|
||||||
transparent_rendering_occlusion_test,
|
|
||||||
transparent_rendering,
|
transparent_rendering,
|
||||||
bloom_extract_downsample,
|
bloom_extract_downsample,
|
||||||
bloom_first_pass,
|
bloom_first_pass,
|
||||||
@ -39,14 +36,11 @@ const names = [_][]const u8{
|
|||||||
"Skybox",
|
"Skybox",
|
||||||
"Pre-processing Block Animations",
|
"Pre-processing Block Animations",
|
||||||
"Chunk Rendering Preparation",
|
"Chunk Rendering Preparation",
|
||||||
"Chunk Rendering Previous Visible",
|
"Chunk Rendering",
|
||||||
"Chunk Rendering Occlusion Test",
|
|
||||||
"Chunk Rendering New Visible",
|
|
||||||
"Entity Rendering",
|
"Entity Rendering",
|
||||||
"Block Entity Rendering",
|
"Block Entity Rendering",
|
||||||
"Particle Rendering",
|
"Particle Rendering",
|
||||||
"Transparent Rendering Preparation",
|
"Transparent Rendering Preparation",
|
||||||
"Transparent Rendering Occlusion Test",
|
|
||||||
"Transparent Rendering",
|
"Transparent Rendering",
|
||||||
"Bloom - Extract color and downsample",
|
"Bloom - Extract color and downsample",
|
||||||
"Bloom - First Pass",
|
"Bloom - First Pass",
|
||||||
|
@ -225,15 +225,15 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
|||||||
|
|
||||||
chunk_meshing.beginRender();
|
chunk_meshing.beginRender();
|
||||||
|
|
||||||
var chunkList = main.List(u32).init(main.stackAllocator);
|
var chunkLists: [main.settings.highestSupportedLod + 1]main.List(u32) = @splat(main.List(u32).init(main.stackAllocator));
|
||||||
defer chunkList.deinit();
|
defer for(chunkLists) |list| list.deinit();
|
||||||
for(meshes) |mesh| {
|
for(meshes) |mesh| {
|
||||||
mesh.prepareRendering(&chunkList);
|
mesh.prepareRendering(&chunkLists);
|
||||||
}
|
}
|
||||||
gpu_performance_measuring.stopQuery();
|
gpu_performance_measuring.stopQuery();
|
||||||
if(chunkList.items.len != 0) {
|
gpu_performance_measuring.startQuery(.chunk_rendering);
|
||||||
chunk_meshing.drawChunksIndirect(chunkList.items, game.projectionMatrix, ambientLight, playerPos, false);
|
chunk_meshing.drawChunksIndirect(&chunkLists, game.projectionMatrix, ambientLight, playerPos, false);
|
||||||
}
|
gpu_performance_measuring.stopQuery();
|
||||||
|
|
||||||
gpu_performance_measuring.startQuery(.entity_rendering);
|
gpu_performance_measuring.startQuery(.entity_rendering);
|
||||||
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, playerPos);
|
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, playerPos);
|
||||||
@ -264,17 +264,17 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
|||||||
c.glTextureBarrier();
|
c.glTextureBarrier();
|
||||||
|
|
||||||
{
|
{
|
||||||
chunkList.clearRetainingCapacity();
|
for(&chunkLists) |*list| list.clearRetainingCapacity();
|
||||||
var i: usize = meshes.len;
|
var i: usize = meshes.len;
|
||||||
while(true) {
|
while(true) {
|
||||||
if(i == 0) break;
|
if(i == 0) break;
|
||||||
i -= 1;
|
i -= 1;
|
||||||
meshes[i].prepareTransparentRendering(playerPos, &chunkList);
|
meshes[i].prepareTransparentRendering(playerPos, &chunkLists);
|
||||||
}
|
}
|
||||||
gpu_performance_measuring.stopQuery();
|
gpu_performance_measuring.stopQuery();
|
||||||
if(chunkList.items.len != 0) {
|
gpu_performance_measuring.startQuery(.transparent_rendering);
|
||||||
chunk_meshing.drawChunksIndirect(chunkList.items, game.projectionMatrix, ambientLight, playerPos, true);
|
chunk_meshing.drawChunksIndirect(&chunkLists, game.projectionMatrix, ambientLight, playerPos, true);
|
||||||
}
|
gpu_performance_measuring.stopQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
c.glDepthRange(0, 0.001);
|
c.glDepthRange(0, 0.001);
|
||||||
|
@ -64,8 +64,8 @@ pub var occlusionTestUniforms: struct {
|
|||||||
} = undefined;
|
} = undefined;
|
||||||
pub var vao: c_uint = undefined;
|
pub var vao: c_uint = undefined;
|
||||||
var vbo: c_uint = undefined;
|
var vbo: c_uint = undefined;
|
||||||
pub var faceBuffer: graphics.LargeBuffer(FaceData) = undefined;
|
pub var faceBuffers: [settings.highestSupportedLod + 1]graphics.LargeBuffer(FaceData) = undefined;
|
||||||
pub var lightBuffer: graphics.LargeBuffer(u32) = undefined;
|
pub var lightBuffers: [settings.highestSupportedLod + 1]graphics.LargeBuffer(u32) = undefined;
|
||||||
pub var chunkBuffer: graphics.LargeBuffer(ChunkData) = undefined;
|
pub var chunkBuffer: graphics.LargeBuffer(ChunkData) = undefined;
|
||||||
pub var commandBuffer: graphics.LargeBuffer(IndirectData) = undefined;
|
pub var commandBuffer: graphics.LargeBuffer(IndirectData) = undefined;
|
||||||
pub var chunkIDBuffer: graphics.LargeBuffer(u32) = undefined;
|
pub var chunkIDBuffer: graphics.LargeBuffer(u32) = undefined;
|
||||||
@ -133,8 +133,10 @@ pub fn init() void {
|
|||||||
c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, rawData.len*@sizeOf(u32), &rawData, c.GL_STATIC_DRAW);
|
c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, rawData.len*@sizeOf(u32), &rawData, c.GL_STATIC_DRAW);
|
||||||
c.glBindVertexArray(0);
|
c.glBindVertexArray(0);
|
||||||
|
|
||||||
faceBuffer.init(main.globalAllocator, 1 << 20, 3);
|
for(0..settings.highestSupportedLod + 1) |i| {
|
||||||
lightBuffer.init(main.globalAllocator, 1 << 20, 10);
|
faceBuffers[i].init(main.globalAllocator, 1 << 20, 3);
|
||||||
|
lightBuffers[i].init(main.globalAllocator, 1 << 20, 10);
|
||||||
|
}
|
||||||
chunkBuffer.init(main.globalAllocator, 1 << 20, 6);
|
chunkBuffer.init(main.globalAllocator, 1 << 20, 6);
|
||||||
commandBuffer.init(main.globalAllocator, 1 << 20, 8);
|
commandBuffer.init(main.globalAllocator, 1 << 20, 8);
|
||||||
chunkIDBuffer.init(main.globalAllocator, 1 << 20, 9);
|
chunkIDBuffer.init(main.globalAllocator, 1 << 20, 9);
|
||||||
@ -148,24 +150,30 @@ pub fn deinit() void {
|
|||||||
commandPipeline.deinit();
|
commandPipeline.deinit();
|
||||||
c.glDeleteVertexArrays(1, &vao);
|
c.glDeleteVertexArrays(1, &vao);
|
||||||
c.glDeleteBuffers(1, &vbo);
|
c.glDeleteBuffers(1, &vbo);
|
||||||
faceBuffer.deinit();
|
for(0..settings.highestSupportedLod + 1) |i| {
|
||||||
lightBuffer.deinit();
|
faceBuffers[i].deinit();
|
||||||
|
lightBuffers[i].deinit();
|
||||||
|
}
|
||||||
chunkBuffer.deinit();
|
chunkBuffer.deinit();
|
||||||
commandBuffer.deinit();
|
commandBuffer.deinit();
|
||||||
chunkIDBuffer.deinit();
|
chunkIDBuffer.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn beginRender() void {
|
pub fn beginRender() void {
|
||||||
faceBuffer.beginRender();
|
for(0..settings.highestSupportedLod + 1) |i| {
|
||||||
lightBuffer.beginRender();
|
faceBuffers[i].beginRender();
|
||||||
|
lightBuffers[i].beginRender();
|
||||||
|
}
|
||||||
chunkBuffer.beginRender();
|
chunkBuffer.beginRender();
|
||||||
commandBuffer.beginRender();
|
commandBuffer.beginRender();
|
||||||
chunkIDBuffer.beginRender();
|
chunkIDBuffer.beginRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endRender() void {
|
pub fn endRender() void {
|
||||||
faceBuffer.endRender();
|
for(0..settings.highestSupportedLod + 1) |i| {
|
||||||
lightBuffer.endRender();
|
faceBuffers[i].endRender();
|
||||||
|
lightBuffers[i].endRender();
|
||||||
|
}
|
||||||
chunkBuffer.endRender();
|
chunkBuffer.endRender();
|
||||||
commandBuffer.endRender();
|
commandBuffer.endRender();
|
||||||
chunkIDBuffer.endRender();
|
chunkIDBuffer.endRender();
|
||||||
@ -212,7 +220,20 @@ pub fn bindTransparentShaderAndUniforms(projMatrix: Mat4f, ambient: Vec3f, playe
|
|||||||
c.glBindVertexArray(vao);
|
c.glBindVertexArray(vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d, transparent: bool) void {
|
fn bindBuffers(lod: usize) void {
|
||||||
|
faceBuffers[lod].ssbo.bind(faceBuffers[lod].binding);
|
||||||
|
lightBuffers[lod].ssbo.bind(lightBuffers[lod].binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawChunksIndirect(chunkIds: *const [main.settings.highestSupportedLod + 1]main.List(u32), projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d, transparent: bool) void {
|
||||||
|
for(0..chunkIds.len) |i| {
|
||||||
|
const lod = if(transparent) main.settings.highestSupportedLod - i else i;
|
||||||
|
bindBuffers(lod);
|
||||||
|
drawChunksOfLod(chunkIds[lod].items, projMatrix, ambient, playerPos, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawChunksOfLod(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec3f, playerPos: Vec3d, transparent: bool) void {
|
||||||
const drawCallsEstimate: u31 = @intCast(if(transparent) chunkIDs.len else chunkIDs.len*8);
|
const drawCallsEstimate: u31 = @intCast(if(transparent) chunkIDs.len else chunkIDs.len*8);
|
||||||
var chunkIDAllocation: main.graphics.SubAllocation = .{.start = 0, .len = 0};
|
var chunkIDAllocation: main.graphics.SubAllocation = .{.start = 0, .len = 0};
|
||||||
chunkIDBuffer.uploadData(chunkIDs, &chunkIDAllocation);
|
chunkIDBuffer.uploadData(chunkIDs, &chunkIDAllocation);
|
||||||
@ -227,7 +248,6 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
c.glUniform1i(commandUniforms.isTransparent, @intFromBool(transparent));
|
c.glUniform1i(commandUniforms.isTransparent, @intFromBool(transparent));
|
||||||
c.glUniform3i(commandUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
c.glUniform3i(commandUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
||||||
if(!transparent) {
|
if(!transparent) {
|
||||||
gpu_performance_measuring.startQuery(.chunk_rendering_previous_visible);
|
|
||||||
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 0);
|
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 0);
|
||||||
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
||||||
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT | c.GL_COMMAND_BARRIER_BIT);
|
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT | c.GL_COMMAND_BARRIER_BIT);
|
||||||
@ -239,11 +259,9 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
}
|
}
|
||||||
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
||||||
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
||||||
gpu_performance_measuring.stopQuery();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Occlusion tests:
|
// Occlusion tests:
|
||||||
gpu_performance_measuring.startQuery(if(transparent) .transparent_rendering_occlusion_test else .chunk_rendering_occlusion_test);
|
|
||||||
occlusionTestPipeline.bind(null);
|
occlusionTestPipeline.bind(null);
|
||||||
c.glUniform3i(occlusionTestUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
c.glUniform3i(occlusionTestUniforms.playerPositionInteger, @intFromFloat(@floor(playerPos[0])), @intFromFloat(@floor(playerPos[1])), @intFromFloat(@floor(playerPos[2])));
|
||||||
c.glUniform3f(occlusionTestUniforms.playerPositionFraction, @floatCast(@mod(playerPos[0], 1)), @floatCast(@mod(playerPos[1], 1)), @floatCast(@mod(playerPos[2], 1)));
|
c.glUniform3f(occlusionTestUniforms.playerPositionFraction, @floatCast(@mod(playerPos[0], 1)), @floatCast(@mod(playerPos[1], 1)), @floatCast(@mod(playerPos[2], 1)));
|
||||||
@ -252,10 +270,8 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
c.glBindVertexArray(vao);
|
c.glBindVertexArray(vao);
|
||||||
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(6*6*chunkIDs.len), c.GL_UNSIGNED_INT, null, chunkIDAllocation.start*24);
|
c.glDrawElementsBaseVertex(c.GL_TRIANGLES, @intCast(6*6*chunkIDs.len), c.GL_UNSIGNED_INT, null, chunkIDAllocation.start*24);
|
||||||
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT);
|
c.glMemoryBarrier(c.GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
gpu_performance_measuring.stopQuery();
|
|
||||||
|
|
||||||
// Draw again:
|
// Draw again:
|
||||||
gpu_performance_measuring.startQuery(if(transparent) .transparent_rendering else .chunk_rendering_new_visible);
|
|
||||||
commandPipeline.bind();
|
commandPipeline.bind();
|
||||||
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 1);
|
c.glUniform1i(commandUniforms.onlyDrawPreviouslyInvisible, 1);
|
||||||
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
c.glDispatchCompute(@intCast(@divFloor(chunkIDs.len + 63, 64)), 1, 1); // TODO: Replace with @divCeil once available
|
||||||
@ -268,7 +284,6 @@ pub fn drawChunksIndirect(chunkIDs: []const u32, projMatrix: Mat4f, ambient: Vec
|
|||||||
}
|
}
|
||||||
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
c.glBindBuffer(c.GL_DRAW_INDIRECT_BUFFER, commandBuffer.ssbo.bufferID);
|
||||||
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
c.glMultiDrawElementsIndirect(c.GL_TRIANGLES, c.GL_UNSIGNED_INT, @ptrFromInt(allocation.start*@sizeOf(IndirectData)), drawCallsEstimate, 0);
|
||||||
gpu_performance_measuring.stopQuery();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FaceData = extern struct {
|
pub const FaceData = extern struct {
|
||||||
@ -347,9 +362,10 @@ pub const PrimitiveMesh = struct { // MARK: PrimitiveMesh
|
|||||||
wasChanged: bool = false,
|
wasChanged: bool = false,
|
||||||
min: Vec3f = undefined,
|
min: Vec3f = undefined,
|
||||||
max: Vec3f = undefined,
|
max: Vec3f = undefined,
|
||||||
|
lod: u3,
|
||||||
|
|
||||||
fn deinit(self: *PrimitiveMesh) void {
|
fn deinit(self: *PrimitiveMesh) void {
|
||||||
faceBuffer.free(self.bufferAllocation);
|
faceBuffers[self.lod].free(self.bufferAllocation);
|
||||||
self.completeList.deinit(main.globalAllocator);
|
self.completeList.deinit(main.globalAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,8 +589,8 @@ pub const PrimitiveMesh = struct { // MARK: PrimitiveMesh
|
|||||||
len += list[i].len;
|
len += list[i].len;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullBuffer = faceBuffer.allocateAndMapRange(len, &self.bufferAllocation);
|
const fullBuffer = faceBuffers[self.lod].allocateAndMapRange(len, &self.bufferAllocation);
|
||||||
defer faceBuffer.unmapRange(fullBuffer);
|
defer faceBuffers[self.lod].unmapRange(fullBuffer);
|
||||||
// Sort the faces by normal to allow for backface culling on the GPU:
|
// Sort the faces by normal to allow for backface culling on the GPU:
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
var iStart = i;
|
var iStart = i;
|
||||||
@ -679,8 +695,12 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
|||||||
self.* = ChunkMesh{
|
self.* = ChunkMesh{
|
||||||
.pos = pos,
|
.pos = pos,
|
||||||
.size = chunk.chunkSize*pos.voxelSize,
|
.size = chunk.chunkSize*pos.voxelSize,
|
||||||
.opaqueMesh = .{},
|
.opaqueMesh = .{
|
||||||
.transparentMesh = .{},
|
.lod = @intCast(std.math.log2_int(u32, pos.voxelSize)),
|
||||||
|
},
|
||||||
|
.transparentMesh = .{
|
||||||
|
.lod = @intCast(std.math.log2_int(u32, pos.voxelSize)),
|
||||||
|
},
|
||||||
.chunk = ch,
|
.chunk = ch,
|
||||||
.lightingData = .{
|
.lightingData = .{
|
||||||
lighting.ChannelChunk.init(ch, false),
|
lighting.ChannelChunk.init(ch, false),
|
||||||
@ -705,7 +725,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
|||||||
self.blockBreakingFaces.deinit();
|
self.blockBreakingFaces.deinit();
|
||||||
main.globalAllocator.free(self.blockBreakingFacesSortingData);
|
main.globalAllocator.free(self.blockBreakingFacesSortingData);
|
||||||
main.globalAllocator.free(self.lightList);
|
main.globalAllocator.free(self.lightList);
|
||||||
lightBuffer.free(self.lightAllocation);
|
lightBuffers[std.math.log2_int(u32, self.pos.voxelSize)].free(self.lightAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn increaseRefCount(self: *ChunkMesh) void {
|
pub fn increaseRefCount(self: *ChunkMesh) void {
|
||||||
@ -1355,7 +1375,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
|||||||
|
|
||||||
if(self.lightListNeedsUpload) {
|
if(self.lightListNeedsUpload) {
|
||||||
self.lightListNeedsUpload = false;
|
self.lightListNeedsUpload = false;
|
||||||
lightBuffer.uploadData(self.lightList, &self.lightAllocation);
|
lightBuffers[std.math.log2_int(u32, self.pos.voxelSize)].uploadData(self.lightList, &self.lightAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.uploadChunkPosition();
|
self.uploadChunkPosition();
|
||||||
@ -1555,15 +1575,15 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
|||||||
}}, &self.chunkAllocation);
|
}}, &self.chunkAllocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepareRendering(self: *ChunkMesh, chunkList: *main.List(u32)) void {
|
pub fn prepareRendering(self: *ChunkMesh, chunkLists: *[main.settings.highestSupportedLod + 1]main.List(u32)) void {
|
||||||
if(self.opaqueMesh.vertexCount == 0) return;
|
if(self.opaqueMesh.vertexCount == 0) return;
|
||||||
|
|
||||||
chunkList.append(self.chunkAllocation.start);
|
chunkLists[std.math.log2_int(u32, self.pos.voxelSize)].append(self.chunkAllocation.start);
|
||||||
|
|
||||||
quadsDrawn += self.opaqueMesh.vertexCount/6;
|
quadsDrawn += self.opaqueMesh.vertexCount/6;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepareTransparentRendering(self: *ChunkMesh, playerPosition: Vec3d, chunkList: *main.List(u32)) void {
|
pub fn prepareTransparentRendering(self: *ChunkMesh, playerPosition: Vec3d, chunkLists: *[main.settings.highestSupportedLod + 1]main.List(u32)) void {
|
||||||
if(self.transparentMesh.vertexCount == 0 and self.blockBreakingFaces.items.len == 0) return;
|
if(self.transparentMesh.vertexCount == 0 and self.blockBreakingFaces.items.len == 0) return;
|
||||||
|
|
||||||
var needsUpdate: bool = false;
|
var needsUpdate: bool = false;
|
||||||
@ -1696,11 +1716,11 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
|||||||
}
|
}
|
||||||
self.culledSortingCount += @intCast(self.blockBreakingFaces.items.len);
|
self.culledSortingCount += @intCast(self.blockBreakingFaces.items.len);
|
||||||
// Upload:
|
// Upload:
|
||||||
faceBuffer.uploadData(self.sortingOutputBuffer[0..self.culledSortingCount], &self.transparentMesh.bufferAllocation);
|
faceBuffers[std.math.log2_int(u32, self.pos.voxelSize)].uploadData(self.sortingOutputBuffer[0..self.culledSortingCount], &self.transparentMesh.bufferAllocation);
|
||||||
self.uploadChunkPosition();
|
self.uploadChunkPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkList.append(self.chunkAllocation.start);
|
chunkLists[std.math.log2_int(u32, self.pos.voxelSize)].append(self.chunkAllocation.start);
|
||||||
transparentQuadsDrawn += self.culledSortingCount;
|
transparentQuadsDrawn += self.culledSortingCount;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user