This commit is contained in:
mcrcortex
2025-07-18 13:12:56 +10:00
parent 94f2d03f90
commit aff34fb463
3 changed files with 200 additions and 36 deletions

View File

@@ -5,10 +5,8 @@
layout(binding = 0) uniform sampler2D blockModelAtlas; layout(binding = 0) uniform sampler2D blockModelAtlas;
layout(binding = 2) uniform sampler2D depthTex; layout(binding = 2) uniform sampler2D depthTex;
layout(location=1) perprimitiveNV in PerPrimData { perprimitiveNV in uvec4 primData;
uvec4 data; perprimitiveNV in vec4 uvData;
vec4 uvData;
} primIn;
layout(location = 0) out vec4 outColour; layout(location = 0) out vec4 outColour;
@@ -17,33 +15,33 @@ vec4 uint2vec4RGBA(uint colour) {
} }
bool useMipmaps() { bool useMipmaps() {
return (primIn.data.x&2u)==0u; return (primData.x&2u)==0u;
} }
bool useTinting() { bool useTinting() {
return (primIn.data.x&4u)!=0u; return (primData.x&4u)!=0u;
} }
bool useCutout() { bool useCutout() {
return (primIn.data.x&1u)==1u; return (primData.x&1u)==1u;
} }
vec4 computeColour(vec4 colour) { vec4 computeColour(vec4 colour) {
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha //Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
if (useTinting() && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) { if (useTinting() && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) {
colour *= uint2vec4RGBA(primIn.data.z).yzwx; colour *= uint2vec4RGBA(primData.z).yzwx;
} }
return (colour * uint2vec4RGBA(primIn.data.y)) + vec4(0,0,0,float(primIn.data.w&0xFFu)/255); return (colour * uint2vec4RGBA(primData.y)) + vec4(0,0,0,float(primData.w&0xFFu)/255);
} }
uint getFace() { uint getFace() {
return (primIn.data.w>>8)&7u; return (primData.w>>8)&7u;
} }
vec2 getBaseUV() { vec2 getBaseUV() {
uint face = getFace(); uint face = getFace();
uint modelId = primIn.data.x>>16; uint modelId = primData.x>>16;
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0)); vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
return modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0))); return modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
} }
@@ -62,7 +60,7 @@ void main() {
//vec2(0,gl_BaryCoordNV.x)+vec2(gl_BaryCoordNV.y,gl_BaryCoordNV.y)+vec2(gl_BaryCoordNV.z,0); //vec2(0,gl_BaryCoordNV.x)+vec2(gl_BaryCoordNV.y,gl_BaryCoordNV.y)+vec2(gl_BaryCoordNV.z,0);
vec2 uv = fma(mix(gl_BaryCoordNV.zx+gl_BaryCoordNV.y, gl_BaryCoordNV.yx, bvec2(tri0)), primIn.uvData.zw, primIn.uvData.xy); vec2 uv = fma(mix(gl_BaryCoordNV.zx+gl_BaryCoordNV.y, gl_BaryCoordNV.yx, bvec2(tri0)), uvData.zw, uvData.xy);
//Need to interpolate //Need to interpolate
//Tile is the tile we are in //Tile is the tile we are in
@@ -79,7 +77,7 @@ void main() {
colour = textureLod(blockModelAtlas, texPos, 0); colour = textureLod(blockModelAtlas, texPos, 0);
} }
if (any(notEqual(clamp(tile, vec2(0), vec2((primIn.data.x>>8)&0xFu, (primIn.data.x>>12)&0xFu)), tile))) { if (any(notEqual(clamp(tile, vec2(0), vec2((primData.x>>8)&0xFu, (primData.x>>12)&0xFu)), tile))) {
discard; discard;
} }

View File

@@ -27,11 +27,8 @@ layout(std430) taskNV in Task {
uint quadCount; uint quadCount;
} task; } task;
layout(location=1) perprimitiveNV out PerPrimData { perprimitiveNV out uvec4 primData[MESH_SIZE*2];
uvec4 data; perprimitiveNV out vec4 uvData[MESH_SIZE*2];
vec4 uvData;
} primOut[];
uint getQuadId() { uint getQuadId() {
uint mid = gl_GlobalInvocationID.x; uint mid = gl_GlobalInvocationID.x;
@@ -260,31 +257,44 @@ void main() {
Quad quad = quadData[qid]; Quad quad = quadData[qid];
setup(quad); setup(quad);
subgroupBarrier();
bool render = dot(faceNormal(face), cornerPos-cameraSubPos) <= 0; bool render = dot(faceNormal(face), cornerPos-cameraSubPos) <= 0;
subgroupBarrier();
uint qId = subgroupExclusiveAdd(render?1:0);
if (render) { if (render) {
vec4 p1 = emitVertexPos(1);
vec4 p2 = emitVertexPos(2);
vec4 p0 = emitVertexPos(0);
vec4 p3 = emitVertexPos(3);
uvec4 data = createQuadData(quad); uvec4 data = createQuadData(quad);
subgroupBarrier(); subgroupBarrier();
uint triId_ = subgroupExclusiveAdd(2); primData[qId*2] = data;
uint triId = triId_; uvData[qId*2] = vec4(faceSize.xz, axisFaceSize);
uint vertId_ = subgroupExclusiveAdd(4); primData[qId*2+1] = data;
uint vertId = vertId_; uvData[qId*2+1] = vec4(faceSize.xz, axisFaceSize);
uint idxId = triId*3;
#define VID(i) (gl_LocalInvocationIndex*4+i)
gl_MeshVerticesNV[VID(0)].gl_Position = emitVertexPos(1);
gl_MeshVerticesNV[VID(1)].gl_Position = emitVertexPos(2);
gl_MeshVerticesNV[VID(2)].gl_Position = emitVertexPos(0);
gl_MeshVerticesNV[VID(3)].gl_Position = emitVertexPos(3);
gl_PrimitiveIndicesNV[qId*6+0] = VID(0);
gl_PrimitiveIndicesNV[qId*6+1] = VID(1);
gl_PrimitiveIndicesNV[qId*6+2] = VID(2);
gl_PrimitiveIndicesNV[qId*6+3] = VID(0);
gl_PrimitiveIndicesNV[qId*6+4] = VID(3);
gl_PrimitiveIndicesNV[qId*6+5] = VID(1);
gl_MeshPrimitivesNV[qId*2].gl_PrimitiveID = int(qid|(0u<<31));
gl_MeshPrimitivesNV[qId*2+1].gl_PrimitiveID = int(qid|(1u<<31));
/*
//vec4 p1 = ;
//vec4 p2 = ;
//vec4 p0 = emitVertexPos(0);
//vec4 p3 = emitVertexPos(3);
//Emit common //Emit common
gl_MeshVerticesNV[vertId++].gl_Position = p1;
gl_MeshVerticesNV[vertId++].gl_Position = p2;
{ {
gl_PrimitiveIndicesNV[idxId++] = vertId_+0; gl_PrimitiveIndicesNV[idxId++] = vertId_+0;
@@ -309,11 +319,13 @@ void main() {
primOut[triId].uvData = vec4(faceSize.xz, axisFaceSize); primOut[triId].uvData = vec4(faceSize.xz, axisFaceSize);
gl_MeshPrimitivesNV[triId++].gl_PrimitiveID = int(qid|(1u<<31)); gl_MeshPrimitivesNV[triId++].gl_PrimitiveID = int(qid|(1u<<31));
} }
*/
subgroupBarrier(); subgroupBarrier();
uint count = subgroupMax(triId_+2); uint count = subgroupMax(qId);
if (subgroupElect()) { if (count != 0 && subgroupElect()) {
count = count *2+2;
gl_PrimitiveCountNV = count; gl_PrimitiveCountNV = count;
#ifdef HAS_STATISTICS #ifdef HAS_STATISTICS
atomicAdd(quadCounts[task.lodLvl], count); atomicAdd(quadCounts[task.lodLvl], count);

View File

@@ -0,0 +1,154 @@
#version 460 core
#extension GL_NV_mesh_shader : require
layout(local_size_x=4) in;
#import <voxy:lod/section.glsl>
bvec3 and(bvec3 a, bvec3 b) {
return bvec3(a.x&&b.x, a.y&&b.y, a.z&&b.z);
}
layout(binding = 0, std140) uniform SceneUniform {
mat4 MVP;
ivec3 baseSectionPos;
uint frameId;
vec3 cameraSubPos;
uint pad_;
vec2 screenSize;
};
layout(binding = 1, std430) restrict readonly buffer IndirectSectionLookupBuffer {
uint sectionCount;
uint indirectLookup[];
};
layout(binding = 2, std430) restrict readonly buffer SectionBuffer {
SectionMeta sectionData[];
};
layout(binding = 3, std430) restrict readonly buffer VisibilityBuffer {
uint visibilityData[];
};
#ifdef HAS_STATISTICS
layout(binding = STATISTICS_BUFFER_BINDING, std430) restrict buffer statisticsBuffer {
uint visibleSectionCounts[5];
uint quadCounts[5];
};
#endif
taskNV out Task {
uvec4 control;//the control vec it defines what subvector to use, it is effectivly the terminating ranges of each bin
uvec4 bins[4];//the bins for each section the last component of each bin is the quad offset
uint launchSize;
} task;
#define BIN(br, cnt) if (br) { if (!pset) {bin[i++] = (sum<<16)|off;} sum += cnt; } pset = br; off += cnt;
/*
void createBin(out uvec4 bin, out uint sum, out uint offset, uint dsc, bvec3 a, bvec3 b, uvec3 cA, uvec3 cB) {
bin = uvec4(-1);
bool pset = false;
uint i = 0;
sum = 0;
offset = counts.x&0xFFFFu;//translucent quads
uint dsc = counts.x>>16;//double sided quads
uint off = counts.x&0xFFFFu;//translucent quads
uint i = 0;
BIN(dsc!=0, dsc);//Double sided quads
BIN(a.x, cA.x);//Down
BIN(b.x, cB.x);//Up
BIN(a.y, cA.y);//North
BIN(b.y, cB.y);//South
BIN(a.z, cA.z);//West
BIN(b.z, cB.z);//East
}*/
uint fillBins(uvec4 counts, ivec3 relative) {//Returns quad count
uvec3 cA = counts.yzw&0xFFFFu;
uvec3 cB = counts.yzw>>16;
bvec3 a = and(notEqual(cA, uvec3(0)), lessThanEqual(ivec3(0), relative.yzx));
bvec3 b = and(notEqual(cB, uvec3(0)), lessThanEqual(relative.yzx, ivec3(0)));
//compute the merged bin values
uvec4 bin = uvec4(-1);
bool pset = false;
uint i = 0;
uint sum = 0;
uint offset = counts.x&0xFFFFu;//translucent quads
uint dsc = counts.x>>16;//double sided quads
uint off = counts.x&0xFFFFu;//translucent quads
uint i = 0;
BIN(dsc!=0, dsc);//Double sided quads
BIN(a.x, cA.x);//Down
BIN(b.x, cB.x);//Up
BIN(a.y, cA.y);//North
BIN(b.y, cB.y);//South
BIN(a.z, cA.z);//West
BIN(b.z, cB.z);//East
//bin contains filled bin data, non filled slots contain -1
return sum;
}
void main() {
if (sectionCount<=gl_GlobalInvocationID.x) {
return;
}
if (subgroupElect()) {
task.quadCount = 0;
}
uint secId = indirectLookup[gl_GlobalInvocationID.x];
uint vis = visibilityData[secId];
bool shouldRender = (vis&0x7fffffffu) == frameId-1;//-1 since we are technically in the next frame for the primary rasterization
bool renderTemporally = (vis&0x80000000u)==0;// If we are the temporal specialization, only render if marked as render temporally
if (shouldRender) {
SectionMeta section = sectionData[secId];
uint detail = extractDetail(section);
ivec3 ipos = extractPosition(section);
ivec3 relative = ipos-(baseSectionPos>>detail);
#ifdef HAS_STATISTICS
atomicAdd(visibleSectionCounts[detail], 1);
#endif
//TODO: here enqueue the id here for both translucent and temporal (if relevant) (* note technically dont need for temporal as can just check :tm: if we are in temporal render mode)
//TODO: in the temporal phase, extract the sections that are ment to be rendered and are also translucent
// enqueue them into a seperate buffer and increment the bin counters based on distance
// this should allow a massive simplificattion of the raster pipeline by eliminating all command gen shaders + prep shaders
task.baseQuad = extractQuadStart(section);
task.quadCount = fillBins(section.b, relative);
task.cameraOffset = vec3(((ipos<<detail) - baseSectionPos)<<5);
task.lodLvl = detail;
}
gl_TaskCountNV = (task.quadCount+(MESH_SIZE-1))/MESH_SIZE;
}