This commit is contained in:
2025-06-23 20:15:55 +01:00
parent f788c86ce7
commit 0f70ffad8d
16 changed files with 393 additions and 3863 deletions
-52
View File
@@ -1,52 +0,0 @@
use std::{
env, fs,
fs::File,
io,
io::{BufRead, BufReader},
path::Path,
};
fn main() -> io::Result<()> {
println!("cargo:rerun-if-changed=src/instructionset.glsl");
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("instructionset.rs");
let f = File::open("src/instructionset.glsl")?;
let f = BufReader::new(f);
let mut out = "
#[repr(u8)]
#[allow(non_snake_case)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum InstructionSet{
"
.to_owned();
for l in f.lines() {
let line = l?;
if line.starts_with("#") {
continue;
}
let entries = line.split("//").map(str::trim).collect::<Vec<&str>>();
if entries[0].is_empty() {
continue;
}
let before_equals = entries[0]
.split("=uint8_t")
.map(str::trim)
.collect::<Vec<&str>>();
let name = &before_equals[0][14..];
let value = &before_equals[1][..before_equals[1].len() - 1];
let comment = entries[1];
out += &format!(
"#[allow(non_snake_case)]\n#[allow(dead_code)]\n/// {comment}\n{name}={value},\n"
);
}
out += "}";
fs::write(dest_path, out).unwrap();
println!("cargo:rerun-if-changed=build.rs");
Ok(())
}
+1
View File
@@ -0,0 +1 @@
nightly
-174
View File
@@ -1,174 +0,0 @@
// global fragment shader
#version 460
#extension GL_EXT_mesh_shader:require
#extension GL_GOOGLE_include_directive:require
#define DescriptionIndex gl_PrimitiveID>>11
#include "include.glsl"
#ifdef implicit
layout(location = 0) in VertexInput
{
vec4 position;
} vertexInput;
layout(depth_greater) out float gl_FragDepth;
#else
layout(location = 0) in vec3 tri_normal;
layout(location = 1) in vec4 tri_pos;
#endif
layout(location = 0) out vec4 f_color;
/// SHARED CODE ///
vec3 shading(vec3 normal, vec4 position)
{
vec3 accum = vec3(0., 0., 0.);
mat3 rotation = mat3(pc.world[0].xyz, pc.world[1].xyz, pc.world[2].xyz);
//vec3 position=pc.world[3].xyz;
for (int i = 0; (i < light_uniforms.light_count) && (i < 32); i++)
{
accum += light_uniforms.col[i].xyz * ((dot(normalize(rotation * normal), normalize(light_uniforms.pos[i].xyz - position.xyz)) * .5) + .5);
}
return accum;
}
/// IMPLICIT CODE ///
#ifdef implicit
//#define debug 1
#ifdef debug
const float EPSILON = .0001;
const uint MAX_STEPS = 1;
#define NEARPLANE 0.
#define FARPLANE length(vec3(10))
#define gl_GlobalInvocationID uvec3(1)
#else
const float EPSILON = .0001;
const uint MAX_STEPS = 50;
#define NEARPLANE 0.
float FARPLANE;
#define gl_GlobalInvocationID uvec3(1)
#endif
#define interval_frags
#include "interpreter.glsl"
#ifdef debug
vec3 getNormal(vec3 p, float dens) {
vec3 n;
n.x = scene(vec3(p.x + EPSILON, p.y, p.z), false).x;
n.y = scene(vec3(p.x, p.y + EPSILON, p.z), false).x;
n.z = scene(vec3(p.x, p.y, p.z + EPSILON), false).x;
return normalize(n - (scene(p, false).x));
}
vec2 spheretracing(vec3 ori, vec3 dir, out vec3 p) {
vec2 td = vec2(NEARPLANE, 1.);
p = ori;
td.y = scene(p, false).x;
td.x += (td.y) * .9;
p = ori + dir * td.x;
for (int i = 0; i < MAX_STEPS && td.y > EPSILON && td.x < FARPLANE; i++) {
td.y = scene(p, false).x;
td.x += (td.y) * .9;
p = ori + dir * td.x;
}
return td;
}
#else
vec3 getNormal(vec3 p, float dens) {
vec3 n;
n.x = scene(vec3(p.x + EPSILON, p.y, p.z), false).x;
n.y = scene(vec3(p.x, p.y + EPSILON, p.z), false).x;
n.z = scene(vec3(p.x, p.y, p.z + EPSILON), false).x;
return normalize(n - (scene(p, false)));
}
vec2 spheretracing(vec3 ori, vec3 dir, out vec3 p) {
vec2 td = vec2(NEARPLANE, 1.);
p = ori;
td.y = scene(p, false).x * .9;
td.x += td.y;
p = ori + dir * td.x;
for (int i = 0; i < MAX_STEPS && td.y > EPSILON && td.x < FARPLANE; i++) {
td.y = scene(p, false).x * .9;
td.x += td.y;
p = ori + dir * td.x;
}
return td;
}
#endif
//Implicit Surface Entrypoint
void main() {
//default_mask();
if (BRUTE_FORCE)
{
default_mask();
}
else {
mask = fragmentpassmasks.masks[gl_PrimitiveID];
}
#ifndef debug
desc = scene_description.desc[(DescriptionIndex) + 1];
vec3 bottomleft = vec3(desc.bounds[3], desc.bounds[4], desc.bounds[5]);
vec3 topright = vec3(desc.bounds[0], desc.bounds[1], desc.bounds[2]);
if (BRUTE_FORCE)
{
FARPLANE = length((topright - bottomleft));
}
else {
FARPLANE = length((topright - bottomleft) * vec3(0.25 * 0.25, 0.25 * 0.25, 0.25 * 0.5));
}
#endif
vec3 raypos = vertexInput.position.xyz;
vec3 p;
vec3 raydir = normalize(raypos - (inverse(pc.world) * vec4(camera_uniforms.campos, 1)).xyz);
//f_color=vec4(raydir,1.);
if (BOUNDING_BOXES) {
f_color = vertexInput.position;
return;
}
#ifdef debug
f_color = vec4(scene(raypos, false), 1);
return;
#endif
vec2 td = spheretracing(raypos, raydir, p);
if (td.y < EPSILON)
{
vec3 n = getNormal(p, td.y);
//f_color=vec4(1.);
f_color = vec4(shading(n, inverse(pc.world) * vec4(p, 1.)), 1.);
vec4 tpoint = camera_uniforms.proj * camera_uniforms.view * pc.world * vec4(p, 1);
gl_FragDepth = (tpoint.z / tpoint.w);
}
else
{
discard;
}
}
#else
/// TRIANGLE CODE ///
//Mesh Surface Entrypoint
void main() {
f_color = vec4(shading(tri_normal, tri_pos), 1.);
}
#endif
-30
View File
@@ -1,30 +0,0 @@
#version 460
uint DescriptionIndex;
//#include "include.glsl"
//#include "intervals.glsl"
#include "interpreter.glsl"
struct Results {
uint code;
uint stat;
};
layout(set = 1, binding = 30, std430) buffer ResultsArray {
Results r[];
} results;
layout(local_size_x = 500, local_size_y = 1, local_size_z = 1) in;
void main()
{
DescriptionIndex = 0;
default_mask();
program_counter = gl_LocalInvocationID.x;
desc = scene_description.desc[(DescriptionIndex) + 1];
results.r[program_counter].code = next_opcode();
//results.r[program_counter].stat = STATIC_OPCODE_ARRAY[program_counter];
}
-217
View File
@@ -1,217 +0,0 @@
// Implicit Mesh shader
#version 460
#extension GL_EXT_mesh_shader:require
uint DescriptionIndex;
#include "include.glsl"
#include "intervals.glsl"
layout(local_size_x=32,local_size_y=1,local_size_z=1)in;
layout(triangles,max_vertices=256,max_primitives=192)out;
layout(location=0)out VertexOutput
{
vec4 position;
}vertexOutput[];
void main()
{
//clear_stacks();
//default_mask();
mat4 mvp=camera_uniforms.proj*camera_uniforms.view*pc.world;
uint vindex = gl_LocalInvocationID.x*8;
uint pindex = gl_LocalInvocationID.x*6;
if (BRUTE_FORCE)
{
SetMeshOutputsEXT(8,6);
float[6]bounds=scene_description.desc[gl_WorkGroupID.x+1].bounds;
vec3 bottomleft = vec3(bounds[3],bounds[4],bounds[5]);
vec3 topright = vec3(bounds[0],bounds[1],bounds[2]);
vec4[8]positions={
vec4(bottomleft,1.),
vec4(bottomleft.x,bottomleft.y,topright.z,1.),
vec4(bottomleft.x,topright.y,bottomleft.z,1.),
vec4(bottomleft.x,topright.y,topright.z,1.),
vec4(topright.x,bottomleft.y,bottomleft.z,1.),
vec4(topright.x,bottomleft.y,topright.z,1.),
vec4(topright.x,topright.y,bottomleft.z,1.),
vec4(topright,1.),
};
bvec3 signingvec=greaterThan((inverse(pc.world)*vec4(camera_uniforms.campos,1)).xyz,(topright+bottomleft)/2);
gl_MeshVerticesEXT[0].gl_Position=mvp*(positions[0]);
gl_MeshVerticesEXT[1].gl_Position=mvp*(positions[1]);
gl_MeshVerticesEXT[2].gl_Position=mvp*(positions[2]);
gl_MeshVerticesEXT[3].gl_Position=mvp*(positions[3]);
gl_MeshVerticesEXT[4].gl_Position=mvp*(positions[4]);
gl_MeshVerticesEXT[5].gl_Position=mvp*(positions[5]);
gl_MeshVerticesEXT[6].gl_Position=mvp*(positions[6]);
gl_MeshVerticesEXT[7].gl_Position=mvp*(positions[7]);
vertexOutput[0].position=(positions[0]);
vertexOutput[1].position=(positions[1]);
vertexOutput[2].position=(positions[2]);
vertexOutput[3].position=(positions[3]);
vertexOutput[4].position=(positions[4]);
vertexOutput[5].position=(positions[5]);
vertexOutput[6].position=(positions[6]);
vertexOutput[7].position=(positions[7]);
if(signingvec.x){
gl_PrimitiveTriangleIndicesEXT[0]=uvec3(4,5,6);
gl_PrimitiveTriangleIndicesEXT[1]=uvec3(5,6,7);
}else{
gl_PrimitiveTriangleIndicesEXT[0]=uvec3(0,1,2);
gl_PrimitiveTriangleIndicesEXT[1]=uvec3(1,2,3);
}
if(signingvec.y){
gl_PrimitiveTriangleIndicesEXT[2]=uvec3(2,3,6);
gl_PrimitiveTriangleIndicesEXT[3]=uvec3(7,3,6);
}else{
gl_PrimitiveTriangleIndicesEXT[2]=uvec3(0,1,4);
gl_PrimitiveTriangleIndicesEXT[3]=uvec3(5,1,4);
}
if(signingvec.z){
gl_PrimitiveTriangleIndicesEXT[4]=uvec3(1,3,5);
gl_PrimitiveTriangleIndicesEXT[5]=uvec3(3,5,7);
}else{
gl_PrimitiveTriangleIndicesEXT[4]=uvec3(0,2,4);
gl_PrimitiveTriangleIndicesEXT[5]=uvec3(2,4,6);
}
return;
}
//This can be optimised
SetMeshOutputsEXT(256,192);
vec3 bottomleft = meshmasks.bottomleft;
vec3 topright = meshmasks.topright;
vec3 center = (topright + bottomleft) / 2.;
vec4[8]positions={
vec4(bottomleft,1.),
vec4(bottomleft.x,bottomleft.y,topright.z,1.),
vec4(bottomleft.x,topright.y,bottomleft.z,1.),
vec4(bottomleft.x,topright.y,topright.z,1.),
vec4(topright.x,bottomleft.y,bottomleft.z,1.),
vec4(topright.x,bottomleft.y,topright.z,1.),
vec4(topright.x,topright.y,bottomleft.z,1.),
vec4(topright,1.),
};
uint localindex = uint(meshmasks.enabled[gl_WorkGroupID.x]);
DescriptionIndex = meshmasks.globalindex/2;
mask = meshmasks.masks[gl_WorkGroupID.x];
int GlobalInvocationIndex = int((meshmasks.globalindex*32+localindex)*32+gl_LocalInvocationID.x);
//adjust scale and position
if (!DISABLE_MESHSCALING1) {
for (int i = 0; i<8; i++)
{
positions[i] *= vec4(0.25,0.25,0.5,1.);
positions[i].x += (topright.x-bottomleft.x)*0.25 * (mod(localindex,4.)-1.5) + (topright.x+bottomleft.x)*0.375;
positions[i].y += (topright.y-bottomleft.y)*0.25 * (mod(floor(localindex/4.),4.)-1.5) + (topright.y+bottomleft.y)*0.375;
positions[i].z += ((topright.z-bottomleft.z)*0.5 * (floor(localindex/16.)-0.5) + (topright.z+bottomleft.z)*0.25);
}
}
vec4 localtopright=positions[0];
vec4 localbottomleft=positions[7];
if (!DISABLE_MESHSCALING2) {
for (int i = 0; i<8; i++)
{
positions[i] *= vec4(0.25,0.25,0.5,1.);
positions[i].x += (localtopright.x-localbottomleft.x)*(0.25) * (mod(gl_LocalInvocationID.x,4.)-1.5) + (localtopright.x+localbottomleft.x)*0.375;
positions[i].y += (localtopright.y-localbottomleft.y)*(0.25) * (mod(floor(gl_LocalInvocationID.x/4.),4.)-1.5) + (localtopright.y+localbottomleft.y)*0.375;
positions[i].z += (localtopright.z-localbottomleft.z)*(0.5) * (floor(gl_LocalInvocationID.x/16.)-0.5) + (localtopright.z+localbottomleft.z)*0.25;
}
}
bvec3 signingvec=greaterThan((inverse(pc.world)*vec4(camera_uniforms.campos,1)).xyz,(positions[0].xyz+positions[7].xyz)/2);
gl_MeshPrimitivesEXT[pindex+0].gl_PrimitiveID=GlobalInvocationIndex;
gl_MeshPrimitivesEXT[pindex+1].gl_PrimitiveID=GlobalInvocationIndex;
gl_MeshPrimitivesEXT[pindex+2].gl_PrimitiveID=GlobalInvocationIndex;
gl_MeshPrimitivesEXT[pindex+3].gl_PrimitiveID=GlobalInvocationIndex;
gl_MeshPrimitivesEXT[pindex+4].gl_PrimitiveID=GlobalInvocationIndex;
gl_MeshPrimitivesEXT[pindex+5].gl_PrimitiveID=GlobalInvocationIndex;
bool triangle_fine;
if (!DISABLE_MESHCULL) {
float[2] check = scene(vec3[2](vec3(positions[0].xyz),vec3(positions[7].xyz)), true);
triangle_fine = (check[0] <= 0) && (check[1] >= 0);
} else {
triangle_fine = true;
}
if (triangle_fine)
{
fragmentpassmasks.masks[GlobalInvocationIndex]=mask;
gl_MeshVerticesEXT[vindex+0].gl_Position=mvp*(positions[0]);
gl_MeshVerticesEXT[vindex+1].gl_Position=mvp*(positions[1]);
gl_MeshVerticesEXT[vindex+2].gl_Position=mvp*(positions[2]);
gl_MeshVerticesEXT[vindex+3].gl_Position=mvp*(positions[3]);
gl_MeshVerticesEXT[vindex+4].gl_Position=mvp*(positions[4]);
gl_MeshVerticesEXT[vindex+5].gl_Position=mvp*(positions[5]);
gl_MeshVerticesEXT[vindex+6].gl_Position=mvp*(positions[6]);
gl_MeshVerticesEXT[vindex+7].gl_Position=mvp*(positions[7]);
vertexOutput[vindex+0].position=(positions[0]);
vertexOutput[vindex+1].position=(positions[1]);
vertexOutput[vindex+2].position=(positions[2]);
vertexOutput[vindex+3].position=(positions[3]);
vertexOutput[vindex+4].position=(positions[4]);
vertexOutput[vindex+5].position=(positions[5]);
vertexOutput[vindex+6].position=(positions[6]);
vertexOutput[vindex+7].position=(positions[7]);
if(signingvec.x){
gl_PrimitiveTriangleIndicesEXT[pindex+0]=uvec3(4,5,6)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+1]=uvec3(5,6,7)+uvec3(vindex);
}else{
gl_PrimitiveTriangleIndicesEXT[pindex+0]=uvec3(0,1,2)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+1]=uvec3(1,2,3)+uvec3(vindex);
}
if(signingvec.y){
gl_PrimitiveTriangleIndicesEXT[pindex+2]=uvec3(2,3,6)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+3]=uvec3(7,3,6)+uvec3(vindex);
}else{
gl_PrimitiveTriangleIndicesEXT[pindex+2]=uvec3(0,1,4)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+3]=uvec3(5,1,4)+uvec3(vindex);
}
if(signingvec.z){
gl_PrimitiveTriangleIndicesEXT[pindex+4]=uvec3(1,3,5)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+5]=uvec3(3,5,7)+uvec3(vindex);
}else{
gl_PrimitiveTriangleIndicesEXT[pindex+4]=uvec3(0,2,4)+uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+5]=uvec3(2,4,6)+uvec3(vindex);
}
} else
{
gl_MeshVerticesEXT[vindex+0].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+1].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+2].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+3].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+4].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+5].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+6].gl_Position=mvp*(vec4(0,0,0,1));
gl_MeshVerticesEXT[vindex+7].gl_Position=mvp*(vec4(0,0,0,1));
gl_PrimitiveTriangleIndicesEXT[pindex+0]=uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+1]=uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+2]=uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+3]=uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+4]=uvec3(vindex);
gl_PrimitiveTriangleIndicesEXT[pindex+5]=uvec3(vindex);
}
}
-69
View File
@@ -1,69 +0,0 @@
// Implicit Mesh shader
#version 460
#extension GL_EXT_mesh_shader:require
#define DescriptionIndex gl_WorkGroupID.x
#include "include.glsl"
#include "intervals.glsl"
layout(local_size_x=32,local_size_y=1,local_size_z=1)in;
shared uint index;
void main()
{
//clear_stacks();
default_mask();
meshmasks.masks[gl_LocalInvocationID.x] = mask;
if (gl_LocalInvocationID.x==0)
{
index=0;
}
float[6]bounds=scene_description.desc[gl_WorkGroupID.x+1].bounds;
vec3 bottomleft = vec3(bounds[3],bounds[4],bounds[5]);
vec3 topright = vec3(bounds[0],bounds[1],bounds[2]);
#define adjust(var) \
var *= vec3(0.25,0.25,0.25);\
var.x += ((bounds[0]-bounds[3]) * 0.25 * (mod(gl_LocalInvocationID.x,4.)-1.5)) + ((bounds[0]+bounds[3])*0.375) ;\
var.y += ((bounds[1]-bounds[4]) * 0.25 * (mod(floor(gl_LocalInvocationID.x/4.),4.)-1.5)) + ((bounds[1]+bounds[4])*0.375) ;\
var.z += ((bounds[2]-bounds[5]) * 0.25 * (floor(gl_LocalInvocationID.x/16.)-1.5+gl_WorkGroupID.z*2.)) + ((bounds[2]+bounds[5])*0.375) ;\
adjust(bottomleft);
adjust(topright);
barrier();
bool triangle_fine;
if (!DISABLE_TASKCULL) {
float[2] check = scene(vec3[2](bottomleft,topright), true);
triangle_fine = (check[0] <= 0) && (check[1] >= 0);
} else {
triangle_fine = true;
}
if (triangle_fine)
{
uint localindex = atomicAdd(index, 1);
meshmasks.masks[localindex]=mask;
meshmasks.enabled[localindex]=uint8_t(gl_LocalInvocationID.x);
}
if (gl_LocalInvocationID.x==0)
{
meshmasks.bottomleft = vec3(bounds[3],bounds[4],(bounds[5]*0.5) + ((bounds[2]-bounds[5])*0.5 * (-0.5+gl_WorkGroupID.z)) + ((bounds[2]+bounds[5])*0.25));
meshmasks.topright = vec3(bounds[0],bounds[1],(bounds[2]*0.5) + ((bounds[2]-bounds[5])*0.5 * (-0.5+gl_WorkGroupID.z)) + ((bounds[2]+bounds[5])*0.25));
meshmasks.globalindex = gl_WorkGroupID.x*2+gl_WorkGroupID.z;
}
barrier();
if (gl_LocalInvocationID.x==0)
{
EmitMeshTasksEXT(index,1,1);
}
}
@@ -2,14 +2,11 @@
#include "include.glsl"
layout(location=0)in vec3 position;
layout(location=1)in vec3 normal;
layout(location=0)out vec3 v_normal;
layout(location=1)out vec4 pos;
void main(){
mat4 worldview=camera_uniforms.view*pc.world;
v_normal=normal;//normalize(transpose(inverse(mat3(worldview))) * normal);
pos = worldview*vec4(position,1.);
gl_Position=camera_uniforms.proj*pos;
}
+219
View File
@@ -0,0 +1,219 @@
#[repr(u8)]
#[allow(non_snake_case)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum InstructionSet {
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the input. Useful for copying registers.
OPCopy = (1),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Adds a vector to a vector component-wise.
OPAdd = (2),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Subtracts a vector from a vector component-wise.
OPSub = (3),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Multiplies a vector and a vector component-wise.
OPMul = (4),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Divides a vector by a vector component-wise.
OPDiv = (5),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates a vector Atan2 a vector component-wise.
OPAtan2 = (6),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates the minimum of a vector and a vector component-wise.
OPMin = (7),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates the maximum of a vector and a vector component-wise.
OPMax = (8),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Threeway comparison operator.
OPCompare = (9),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates a vector modulo a vector component-wise.
OPMod = (10),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// If both arguments are non-zero, returns the right-hand argument.
/// Otherwise, returns zero.
OPAnd = (11),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// If the left-hand argument is non-zero, it is returned. Otherwise, the
/// right-hand argument is returned.
OPOr = (12),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the negation of all components of a vector.
OPNegate = (13),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the absolute value of all components of a vector.
OPAbs = (14),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns 1 over all components of a vector.
OPRecip = (15),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the square root of all components of a vector.
OPSqrt = (16),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the square of all components of a vector.
OPSquare = (17),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the floor of all components of a vector.
OPFloor = (18),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the ceiling of all components of a vector.
OPCeil = (19),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns all components of a vector rounded to the nearest integer, 0.5
/// away from zero.
OPRound = (20),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the sine of all components of a vector.
OPSin = (21),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the cosine of all components of a vector.
OPCos = (22),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the tangent of all components of a vector.
OPTan = (23),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the arc sine of all components of a vector.
OPAsin = (24),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the arc cosine of all components of a vector.
OPAcos = (25),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the arc tangent of all components of a vector.
OPAtan = (26),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns e raised to all components of a vector.
OPExp = (27),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the natural logarithm of all components of a vector.
OPLog = (28),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// The output is 1 if the argument is 0, and 0 otherwise.
OPNot = (29),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the fractional part of all components of a vector.
OPFract = (30),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the cube of all components of a vector.
OPCube = (31),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the smooth minimum between a vector and a vector, varied by a
/// vector.
OPSmoothMin = (32),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the smooth maximum between a vector and a vector, varied by a
/// vector.
OPSmoothMax = (33),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Clamps a vector between a vector and a vector.
OPClamp = (34),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Mixes between a vector and a vector, varied by a vector.
OPMix = (35),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates a vector multiplied by a vector, then adds a vector.
OPFMA = (36),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the length (magnitude) of a vector.
OPLength = (37),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the normalised version of a vector.
OPNormalize = (38),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the dot product of two vectors.
OPDot = (39),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the length (magnitude) of the vector between two vectors.
OPDistance = (40),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// No operation.
OPNop = ((3 * 64) + 63),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Stops execution of the tape and returns a single value.
OPReturn = ((2 * 64) + 63),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the current position being sampled.
OPPosition = ((1 * 64) + 63),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates the minimum of two Vec1s, and also carries over the relevant
/// material metadata.
OPMinMaterial = ((0 * 64) + 63),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Calculates the maximum of two Vec1s, and also carries over the relevant
/// material metadata.
OPMaxMaterial = ((3 * 64) + 62),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the smooth minimum between a Vec1 and a Vec1, varied by a Vec1,
/// and also carries over the relevant material metadata.
OPSmoothMinMaterial = ((2 * 64) + 62),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the smooth maximum between a Vec1 and a Vec1, varied by a Vec1,
/// and also carries over the relevant material metadata.
OPSmoothMaxMaterial = ((1 * 64) + 62),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the cross product of two Vec3s.
OPCross = ((0 * 64) + 62),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the distance to a sphere.
OPSDFSphere = ((3 * 64) + 61),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the distance to a box.
OPSDFBox = ((2 * 64) + 61),
#[allow(non_snake_case)]
#[allow(dead_code)]
/// Returns the distance to a torus.
OPSDFTorus = ((1 * 64) + 61),
}
-75
View File
@@ -1,75 +0,0 @@
#ifndef instruction_set
#define instruction_set
// Element wise
const uint8_t OPCopy =uint8_t(1); // Returns the input. Useful for copying registers.
// Fidget VM compat
// Two parameter
const uint8_t OPAdd =uint8_t(2); // Adds a vector to a vector component-wise.
const uint8_t OPSub =uint8_t(3); // Subtracts a vector from a vector component-wise.
const uint8_t OPMul =uint8_t(4); // Multiplies a vector and a vector component-wise.
const uint8_t OPDiv =uint8_t(5); // Divides a vector by a vector component-wise.
const uint8_t OPAtan2 =uint8_t(6); // Calculates a vector Atan2 a vector component-wise.
const uint8_t OPMin =uint8_t(7); // Calculates the minimum of a vector and a vector component-wise.
const uint8_t OPMax =uint8_t(8); // Calculates the maximum of a vector and a vector component-wise.
const uint8_t OPCompare =uint8_t(9); // Threeway comparison operator.
const uint8_t OPMod =uint8_t(10); // Calculates a vector modulo a vector component-wise.
const uint8_t OPAnd =uint8_t(11); // If both arguments are non-zero, returns the right-hand argument. Otherwise, returns zero.
const uint8_t OPOr =uint8_t(12); // If the left-hand argument is non-zero, it is returned. Otherwise, the right-hand argument is returned.
// One parameter
const uint8_t OPNegate =uint8_t(13); // Returns the negation of all components of a vector.
const uint8_t OPAbs =uint8_t(14); // Returns the absolute value of all components of a vector.
const uint8_t OPRecip =uint8_t(15); // Returns 1 over all components of a vector.
const uint8_t OPSqrt =uint8_t(16); // Returns the square root of all components of a vector.
const uint8_t OPSquare =uint8_t(17); // Returns the square of all components of a vector.
const uint8_t OPFloor =uint8_t(18); // Returns the floor of all components of a vector.
const uint8_t OPCeil =uint8_t(19); // Returns the ceiling of all components of a vector.
const uint8_t OPRound =uint8_t(20); // Returns all components of a vector rounded to the nearest integer, 0.5 away from zero.
const uint8_t OPSin =uint8_t(21); // Returns the sine of all components of a vector.
const uint8_t OPCos =uint8_t(22); // Returns the cosine of all components of a vector.
const uint8_t OPTan =uint8_t(23); // Returns the tangent of all components of a vector.
const uint8_t OPAsin =uint8_t(24); // Returns the arc sine of all components of a vector.
const uint8_t OPAcos =uint8_t(25); // Returns the arc cosine of all components of a vector.
const uint8_t OPAtan =uint8_t(26); // Returns the arc tangent of all components of a vector.
const uint8_t OPExp =uint8_t(27); // Returns e raised to all components of a vector.
const uint8_t OPLog =uint8_t(28); // Returns the natural logarithm of all components of a vector.
const uint8_t OPNot =uint8_t(29); // The output is 1 if the argument is 0, and 0 otherwise.
// Additional
// One Parameter
const uint8_t OPFract =uint8_t(30); // Returns the fractional part of all components of a vector.
const uint8_t OPCube =uint8_t(31); // Returns the cube of all components of a vector.
// Three parameter
const uint8_t OPSmoothMin =uint8_t(32); // Returns the smooth minimum between a vector and a vector, varied by a vector.
const uint8_t OPSmoothMax =uint8_t(33); // Returns the smooth maximum between a vector and a vector, varied by a vector.
const uint8_t OPClamp =uint8_t(34); // Clamps a vector between a vector and a vector.
const uint8_t OPMix =uint8_t(35); // Mixes between a vector and a vector, varied by a vector.
const uint8_t OPFMA =uint8_t(36); // Calculates a vector multiplied by a vector, then adds a vector.
// Non-element wise
// One parameter
const uint8_t OPLength =uint8_t(37); // Returns the length (magnitude) of a vector.
const uint8_t OPNormalize =uint8_t(38); // Returns the normalised version of a vector.
// Two parameter
const uint8_t OPDot =uint8_t(39); // Returns the dot product of two vectors.
const uint8_t OPDistance =uint8_t(40); // Returns the length (magnitude) of the vector between two vectors.
// Bookkeeping
const uint8_t OPNop =uint8_t((3*64)+63); // No operation.
const uint8_t OPReturn =uint8_t((2*64)+63); // Stops execution of the tape and returns a single value.
const uint8_t OPPosition =uint8_t((1*64)+63); // Returns the current position being sampled.
// Special
const uint8_t OPMinMaterial =uint8_t((0*64)+63); // Calculates the minimum of two Vec1s, and also carries over the relevant material metadata.
const uint8_t OPMaxMaterial =uint8_t((3*64)+62); // Calculates the maximum of two Vec1s, and also carries over the relevant material metadata.
const uint8_t OPSmoothMinMaterial =uint8_t((2*64)+62); // Returns the smooth minimum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
const uint8_t OPSmoothMaxMaterial =uint8_t((1*64)+62); // Returns the smooth maximum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
const uint8_t OPCross =uint8_t((0*64)+62); // Returns the cross product of two Vec3s.
// SDFs
const uint8_t OPSDFSphere =uint8_t((3*64)+61); // Returns the distance to a sphere.
const uint8_t OPSDFBox =uint8_t((2*64)+61); // Returns the distance to a box.
const uint8_t OPSDFTorus =uint8_t((1*64)+61); // Returns the distance to a torus.
#endif
-87
View File
@@ -26,90 +26,3 @@ Steps:
4. each subgroup outputs 4 verts and 2 triangles, for a total 16/8 per workgroup.
For a mesh that takes up 1024x1024 pixel on screen, each quad takes up 16x16 pixels.
# instruction set
## arithmetic
### duo types
- VecXVecX (returns vecx)
- VecXVec1 (returns vecx)
- Vec1VecX (returns vecx)
### duo instructions
- Add
- Sub
- Mul
- Div
- Mod
- Rem
- Pow
- Atan2
- Min
- Max
### trio types
- VecXVecXVecX (returns vecx)
- VecXVecXVec1 (returns vecx)
- VecXVec1VecX (returns vecx)
- VecXVec1Vec1 (returns vecx)
- Vec1VecXVecX (returns vecx)
- Vec1VecXVec1 (returns vecx)
- Vec1Vec1VecX (returns vecx)
### trio instructions
- SmoothMin
- SmoothMax
- Clamp
- Mix
- Step
- SmoothStep
- FMA
### unary types
- VecX
### unary instructions
- negate
- round
- roundeven
- trunc
- abs
- sign
- floor
- ceil
- fract
- sin
- cos
- tan
- asin
- acos
- atan
- sinh
- cosh
- tanh
- asinh
- acosh
- atanh
- exp
- log
- exp2
- log2
- sqrt
- inversesqrt
- square
- cube
### Extra Matrix
- MulVec2Mat2 (returns vec2)
- MulVec3Mat3 (returns vec3)
- MulVec4Mat4 (returns vec4)
### Extra Vector
- CrossVec3Vec3 (returns vec3)
- DotVecX (returns vecx)
- LengthVecX (returns vec1)
- DistanceVecX (returns vec1)
- NormaliseVecX (returns vec1)
## Data manipulation
### Instructions
- CopyVecX
## SDF
- SDFSphere
- SDFBox
- SDFTorus
## Extra
- Stop
- Nop
- Position
-743
View File
@@ -1,743 +0,0 @@
#extension GL_EXT_shader_explicit_arithmetic_types:require
#extension GL_EXT_shader_explicit_arithmetic_types_int8:require
#ifndef interpreter
#define interpreter 1
#include "instructionset.glsl"
#include "scene_bindings.glsl"
float registers[14] = float[14](0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
void clear_registers()
{
registers = float[14](0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
}
float load(uint8_t reg) {
if (reg == 0) {
return 0.;
} else if (reg == 15) {
return next_const();
} else {
return registers[reg - 1];
}
}
void store(uint8_t reg, float value) {
if (reg > 0 && reg < 15) {
registers[reg - 1] = value;
}
}
float input_float() {
return load(next_register());
}
vec2 input_vec2() {
return vec2(load(next_register()), load(next_register()));
}
vec3 input_vec3() {
return vec3(load(next_register()), load(next_register()), load(next_register()));
}
vec4 input_vec4() {
return vec4(load(next_register()), load(next_register()), load(next_register()), load(next_register()));
}
void output_float(float v) {
store(next_register(), v);
}
void output_vec2(vec2 v) {
store(next_register(), v.x);
store(next_register(), v.y);
}
void output_vec3(vec3 v) {
store(next_register(), v.x);
store(next_register(), v.y);
store(next_register(), v.z);
}
void output_vec4(vec4 v) {
store(next_register(), v.x);
store(next_register(), v.y);
store(next_register(), v.z);
store(next_register(), v.w);
}
#define ewise_one(len, func) for (int i = 0; i < len; i++) { \
switch ((mask[program_counter] >> (i * 4)) & 3) { \
case MASK_EXECUTE: \
output_float(func(input_float())); \
break; \
case MASK_COPY_LEFT: \
output_float(input_float()); \
break; \
case MASK_COPY_RIGHT : \
case MASK_DO_NOTHING : \
jump_registers(2); \
jump_const(uint(mask[program_counter]>>((i*4)+2))&3); \
break ; \
} \
}
#define ewise_two(len, func) for (int i = 0; i < len; i++) { \
switch ((mask[program_counter] >> (i * 4)) & 3) { \
case MASK_EXECUTE: \
output_float(func(input_float(), input_float())); \
break; \
case MASK_COPY_LEFT: \
float inp = input_float(); \
jump_registers(1); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
output_float(inp); \
break; \
case MASK_COPY_RIGHT: \
jump_registers(1); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
output_float(input_float()); \
break; \
case MASK_DO_NOTHING: \
jump_registers(3); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
break; \
} \
}
#define ewise_three(len, func) for (int i = 0; i < len; i++) { \
switch ((mask[program_counter] >> (i * 4)) & 3) { \
case MASK_EXECUTE: \
output_float(func(input_float(), input_float(), input_float())); \
break; \
case MASK_COPY_LEFT: {\
float inp = input_float(); \
jump_registers(2); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
output_float(inp); }\
break; \
case MASK_COPY_RIGHT: {\
input_float(); \
float inp = input_float(); \
input_float(); \
output_float(inp); }\
break; \
case MASK_DO_NOTHING: \
jump_registers(4); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
break; \
} \
}
#define ewise_four(len, func) for (int i = 0; i < len; i++) { \
switch ((mask[program_counter] >> (i * 4)) & 3) { \
case MASK_EXECUTE: \
output_float(func(input_float(), input_float(), input_float(), input_float())); \
break; \
case MASK_COPY_LEFT: {\
float inp = input_float(); \
jump_registers(3); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
output_float(inp); }\
break; \
case MASK_COPY_RIGHT: {\
input_float(); \
float inp = input_float(); \
input_float(); \
input_float(); \
output_float(inp); }\
break; \
case MASK_DO_NOTHING: \
jump_registers(5); \
jump_const(uint(mask[program_counter] >> ((i * 4) + 2)) & 3); \
break; \
} \
}
#define ewise_all(opcode, count, func) \
case opcode ## Vec1: {ewise_ ## count(1, func);} break; \
case opcode ## Vec2: {ewise_ ## count(2, func);} break; \
case opcode ## Vec3: {ewise_ ## count(3, func);} break; \
case opcode ## Vec4: {ewise_ ## count(4, func);} break; \
//monotonic
float copyof(float in1)
{
return in1;
}
//monotonic
float mulof(float in1, float in2)
{
return in1 * in2;
}
//monotonic
float divof(float in1, float in2)
{
return in1 / in2;
}
//monotonic
float addof(float in1, float in2)
{
return in1 + in2;
}
//monotonic
float subof(float in1, float in2)
{
return in1 - in2;
}
float modof(float in1, float in2)
{
return mod(in1, in2);
}
//always monotonic for x>0
float powof(float in1, float in2)
{
return pow(in1, in2);
}
float opSmoothUnion(float d1, float d2, float k)
{
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
return mix(d2, d1, h) - k * h * (1.0 - h);
}
float opSmoothSubtraction(float d1, float d2, float k)
{
float h = clamp(0.5 - 0.5 * (d2 + d1) / k, 0.0, 1.0);
return mix(d2, -d1, h) + k * h * (1.0 - h);
}
float opSmoothIntersection(float d1, float d2, float k)
{
float h = clamp(0.5 - 0.5 * (d2 - d1) / k, 0.0, 1.0);
return mix(d2, d1, h) + k * h * (1.0 - h);
}
//monotonic
float stepof(float d1, float d2)
{
return step(d1, d2);
}
//monotonic
float smoothstepof(float d1, float d2, float k)
{
return smoothstep(d1, d2, k);
}
//monotonic
float clampof(float in1, float in2, float in3)
{
return clamp(in1, in2, in3);
}
//monotonic
float mixof(float in1, float in2, float in3)
{
return mix(in1, in2, in3);
}
//monotonic
float fmaof(float in1, float in2, float in3)
{
return fma(in1, in2, in3);
}
//variable
float squareof(float in1)
{
return in1 * in1;
}
//monotonic
float cubeof(float in1)
{
return in1 * in1 * in1;
}
//handled
float absof(float in1)
{
return abs(in1);
}
//monotonic
float signof(float in1)
{
return sign(in1);
}
//monotonic
float floorof(float in1)
{
return floor(in1);
}
//monotonic
float ceilof(float in1)
{
return ceil(in1);
}
//handled
float fractof(float in1)
{
return fract(in1);
}
//monotonic
float sqrtof(float in1)
{
return sqrt(in1);
}
//monotonic
float inversesqrtof(float in1)
{
return inversesqrt(in1);
}
//monotonic
float expof(float in1)
{
return exp(in1);
}
//monotonic
float exp2of(float in1)
{
return exp2(in1);
}
//monotonic
float logof(float in1)
{
return log(in1);
}
//monotonic
float log2of(float in1)
{
return log2(in1);
}
const float PI = 3.1415926536;
//handled
float sinof(float in1)
{
return sin(in1);
}
//handled
float cosof(float in1)
{
return cos(in1);
}
//handled
float tanof(float in1)
{
return tan(in1);
}
//monotonic
float asinof(float in1)
{
return asin(in1);
}
//negatively monotonic
float acosof(float in1)
{
return acos(in1);
}
//monotonic
float atanof(float in1)
{
return atan(in1);
}
//monotonic
float atan2of(float in1, float in2)
{
return atan(in1, in2);
}
//monotonic
float sinhof(float in1)
{
return sinh(in1);
}
//handled
float coshof(float in1)
{
return cosh(in1);
}
//monotonic
float tanhof(float in1)
{
return tanh(in1);
}
//monotonic
float asinhof(float in1)
{
return asinh(in1);
}
//monotonic
float acoshof(float in1)
{
return acosh(in1);
}
//monotonic
float atanhof(float in1)
{
return atanh(in1);
}
//obvious
float minof(float in1, float in2)
{
return min(in1, in2);
}
//obvious
float maxof(float in1, float in2)
{
return max(in1, in2);
}
//negatively monotonic
float negateof(float in1)
{
return -in1;
}
//monotonic
float roundof(float in1)
{
return round(in1);
}
//monotonic
float roundevenof(float in1)
{
return roundEven(in1);
}
//truncate
float truncof(float in1)
{
return trunc(in1);
}
//handled
float recipof(float in1)
{
return 1.0 / in1;
}
//handled
float compareof(float in1, float in2)
{
if (isnan(in1)) {
return in1;
}
if (isnan(in2)) {
return in2;
}
if (in1 < in2) {
return -1.;
}
if (in1 > in2) {
return 1.;
}
return 0.;
}
//handled
float orof(float in1, float in2)
{
return mix(in2, in1, in1 == 0.);
}
//handled
float andof(float in1, float in2)
{
return mix(in1, in2, in1 == 0.);
}
//handled
float notof(float in1)
{
return mix(1., 0., in1 == 0.);
}
vec3 scene(vec3 p, bool materials)
{
uint program_counter = 0;
uint io_counter = 0;
uint const_counter = 0;
desc = scene_description.desc[(DescriptionIndex) + 1];
clear_registers();
while (program_counter < EXECUTION_LIMIT) {
uint8_t code = next_opcode();
uint[2] elements = reg_elementwise(code);
if (elements[0] == 0 && (mask[program_counter] & 3) != MASK_EXECUTE) {
uint io = uint(reg_input(code) + reg_output(code));
jump_registers(io);
jump_const(uint(mask[program_counter] >> 2));
continue;
}
switch (uint32_t(code))
{
ewise_all(OPCopy, one, copyof);
ewise_all(OPAdd, two, addof);
ewise_all(OPSub, two, subof);
ewise_all(OPMul, two, mulof);
ewise_all(OPDiv, two, divof);
ewise_all(OPAtan2, two, atan2of);
ewise_all(OPMin, two, minof);
ewise_all(OPMax, two, maxof);
ewise_all(OPCompare, two, compareof);
ewise_all(OPMod, two, modof);
ewise_all(OPAnd, two, andof);
ewise_all(OPOr, two, orof);
ewise_all(OPNegate, one, negateof);
ewise_all(OPAbs, one, absof);
ewise_all(OPRecip, one, recipof);
ewise_all(OPSqrt, one, sqrtof);
ewise_all(OPSquare, one, squareof);
ewise_all(OPFloor, one, floorof);
ewise_all(OPCeil, one, ceilof);
ewise_all(OPRound, one, roundof);
ewise_all(OPSin, one, sinof);
ewise_all(OPCos, one, cosof);
ewise_all(OPTan, one, tanof);
ewise_all(OPAsin, one, asinof);
ewise_all(OPAcos, one, acosof);
ewise_all(OPAtan, one, atanof);
ewise_all(OPExp, one, expof);
ewise_all(OPLog, one, logof);
ewise_all(OPNot, one, notof);
ewise_all(OPFract, one, fractof);
ewise_all(OPCube, one, cubeof);
ewise_all(OPSmoothMin, three, opSmoothUnion);
ewise_all(OPSmoothMax, three, opSmoothIntersection);
ewise_all(OPClamp, three, clampof);
ewise_all(OPMix, three, mixof);
ewise_all(OPFMA, three, fmaof);
case OPDotVec1:
{
float in1 = input_float();
float in2 = input_float();
output_float(in1 * in2);
}
break;
case OPDotVec2:
{
vec2 in1 = input_vec2();
vec2 in2 = input_vec2();
output_float(dot(in1, in2));
}
break;
case OPDotVec3:
{
vec3 in1 = input_vec3();
vec3 in2 = input_vec3();
output_float(dot(in1, in2));
}
break;
case OPDotVec4:
{
vec4 in1 = input_vec4();
vec4 in2 = input_vec4();
output_float(dot(in1, in2));
}
break;
case OPLengthVec1:
{
float in1 = input_float();
output_float(in1);
}
break;
case OPLengthVec2:
{
vec2 in1 = input_vec2();
output_float(length(in1));
}
break;
case OPLengthVec3:
{
vec3 in1 = input_vec3();
output_float(length(in1));
}
break;
case OPLengthVec4:
{
vec4 in1 = input_vec4();
output_float(length(in1));
}
break;
case OPDistanceVec1:
{
float in1 = input_float();
float in2 = input_float();
output_float(in2 - in1);
}
break;
case OPDistanceVec2:
{
vec2 in1 = input_vec2();
vec2 in2 = input_vec2();
output_float(distance(in1, in2));
}
break;
case OPDistanceVec3:
{
vec3 in1 = input_vec3();
vec3 in2 = input_vec3();
output_float(distance(in1, in2));
}
break;
case OPDistanceVec4:
{
vec4 in1 = input_vec4();
vec4 in2 = input_vec4();
output_float(distance(in1, in2));
}
break;
case OPNormalizeVec1:
{
float in1 = input_float();
output_float(1);
}
break;
case OPNormalizeVec2:
{
vec2 in1 = input_vec2();
output_vec2(normalize(in1));
}
break;
case OPNormalizeVec3:
{
vec3 in1 = input_vec3();
output_vec3(normalize(in1));
}
break;
case OPNormalizeVec4:
{
vec4 in1 = input_vec4();
output_vec4(normalize(in1));
}
break;
case OPCross:
{
vec3 in1 = input_vec3();
vec3 in2 = input_vec3();
output_vec3(cross(in1, in2));
}
break;
case OPSmoothMinMaterial:
{
ewise_three(1, opSmoothUnion);
}
break;
case OPSmoothMaxMaterial:
{
ewise_three(1, opSmoothIntersection);
}
break;
case OPMinMaterial:
{
ewise_two(1, minof);
}
break;
case OPMaxMaterial:
{
ewise_two(1, maxof);
}
break;
case OPSDFSphere:
{
vec3 in1 = input_vec3();
float in2 = input_float();
output_float(length(in1) - in2);
}
break;
case OPSDFTorus:
{
vec3 p = input_vec3();
vec2 t = input_vec2();
vec2 q = vec2(length(p.xz) - t.x, p.y);
output_float(length(q) - t.y);
}
break;
//this doesn't work internally but it's probably fiiiine
case OPSDFBox:
{
vec3 p = input_vec3();
vec3 b = input_vec3();
vec3 q = abs(p) - b;
output_float(length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0));
}
break;
case OPNop:
break;
case OPReturn:
return vec3(input_float());
case OPPosition:
{
output_vec3(p);
}
break;
default:
#ifdef debug
return vec3(float(code));
#else
return vec3(-1.);
#endif
}
}
return vec3(input_float());
}
#endif//ifndef interpreter
-1439
View File
File diff suppressed because it is too large Load Diff
+88 -544
View File
@@ -11,19 +11,18 @@ use std::{
};
const DYNAMIC_STATE: bool = true;
const COMPUTE_FUZZING: bool = false;
const MSAA_ENABLE: bool = false;
const MSAA_SAMPLES: u32 = 4;
const SAMPLE_RATE_SHADING: f32 = 1.0;
const MSAA_SAMPLES_ACTUAL: u32 = if MSAA_ENABLE { MSAA_SAMPLES } else { 1 };
use bytemuck::{Pod, Zeroable};
use egui_winit_vulkano::{Gui, GuiConfig};
use foldhash::{HashMap, HashMapExt, HashSet};
use glam::{self, EulerRot, Mat3, Mat4, Vec3, vec3};
use log::{error, info, trace};
use rayon::prelude::*;
use rspirv::binary::Disassemble;
use simplelog::{CombinedLogger, Config, TermLogger, WriteLogger};
use ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape};
use vulkano::{
@@ -51,10 +50,9 @@ use vulkano::{
AllocationCreateInfo, MemoryAllocatePreference, MemoryTypeFilter, StandardMemoryAllocator,
},
pipeline::{
ComputePipeline, DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint,
PipelineLayout, PipelineShaderStageCreateInfo,
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
PipelineShaderStageCreateInfo,
cache::{PipelineCache, PipelineCacheCreateInfo},
compute::ComputePipelineCreateInfo,
graphics::{
GraphicsPipelineCreateInfo,
color_blend::{ColorBlendAttachmentState, ColorBlendState},
@@ -90,11 +88,7 @@ use crate::objects::*;
mod ssa;
mod instruction_set {
include!(concat!(env!("OUT_DIR"), "/instructionset.rs"));
}
use crate::instruction_set::InstructionSet;
mod instruction_set;
mod interpreter;
@@ -150,6 +144,31 @@ impl Default for CState {
}
}
const VERTEX_COUNT: usize = 3 * 2 * 6;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
pub(crate) struct IVertex {
#[format(R32G32B32_SFLOAT)]
position: [f32; 3],
}
#[rustfmt::skip]
const CUBE_VERTEX: [IVertex; VERTEX_COUNT] = [
IVertex { position: [0.0, 1.0, 0.0]}, IVertex { position: [0.0, 0.0, 0.0]}, IVertex { position: [1.0, 0.0, 0.0]}, // s1 t1
IVertex { position: [1.0, 1.0, 0.0]}, IVertex { position: [0.0, 1.0, 0.0]}, IVertex { position: [1.0, 0.0, 0.0]}, // s1 t2
IVertex { position: [1.0, 1.0, 0.0]}, IVertex { position: [1.0, 0.0, 0.0]}, IVertex { position: [1.0, 0.0, 1.0]}, // s2 t1
IVertex { position: [1.0, 1.0, 1.0]}, IVertex { position: [1.0, 1.0, 0.0]}, IVertex { position: [1.0, 0.0, 1.0]}, // s2 t2
IVertex { position: [0.0, 0.0, 1.0]}, IVertex { position: [0.0, 1.0, 1.0]}, IVertex { position: [1.0, 0.0, 1.0]}, // s3 t1
IVertex { position: [0.0, 1.0, 1.0]}, IVertex { position: [1.0, 1.0, 1.0]}, IVertex { position: [1.0, 0.0, 1.0]}, // s3 t2
IVertex { position: [0.0, 0.0, 0.0]}, IVertex { position: [0.0, 1.0, 0.0]}, IVertex { position: [0.0, 0.0, 1.0]}, // s4 t1
IVertex { position: [0.0, 1.0, 0.0]}, IVertex { position: [0.0, 1.0, 1.0]}, IVertex { position: [0.0, 0.0, 1.0]}, // s4 t2
IVertex { position: [0.0, 0.0, 0.0]}, IVertex { position: [0.0, 0.0, 1.0]}, IVertex { position: [1.0, 0.0, 0.0]}, // s5 t1
IVertex { position: [0.0, 0.0, 1.0]}, IVertex { position: [1.0, 0.0, 1.0]}, IVertex { position: [1.0, 0.0, 0.0]}, // s5 t2
IVertex { position: [0.0, 1.0, 1.0]}, IVertex { position: [0.0, 1.0, 0.0]}, IVertex { position: [1.0, 1.0, 0.0]}, // s6 t1
IVertex { position: [1.0, 1.0, 1.0]}, IVertex { position: [0.0, 1.0, 1.0]}, IVertex { position: [1.0, 1.0, 0.0]}, // s6 t2
];
struct App {
instance: Arc<Instance>,
device: Arc<Device>,
@@ -163,16 +182,13 @@ struct App {
gstate: GState,
previous_debug: PreviousDebug,
cstate: CState,
vertex_buffer: Subbuffer<[IVertex; VERTEX_COUNT]>,
rcx: Option<RenderContext>,
}
struct ShaderModules {
mesh_vs: Arc<ShaderModule>,
mesh_fs: Arc<ShaderModule>,
implicit_ts: Arc<ShaderModule>,
implicit_ms: Arc<ShaderModule>,
implicit_fs: Arc<ShaderModule>,
compute_shader: Arc<ShaderModule>,
implicit_vs: Arc<ShaderModule>,
implicit_fs: Arc<ShaderModule>,
}
struct RenderContext {
@@ -181,8 +197,6 @@ struct RenderContext {
render_pass: Arc<RenderPass>,
framebuffers: Vec<Arc<Framebuffer>>,
shader_modules: ShaderModules,
compute_pipeline: Arc<ComputePipeline>,
mesh_pipeline: Arc<GraphicsPipeline>,
implicit_pipeline: Arc<GraphicsPipeline>,
viewport: Viewport,
recreate_swapchain: bool,
@@ -190,8 +204,6 @@ struct RenderContext {
previous_frame_end: Option<Box<dyn GpuFuture>>,
gui: Gui,
render_start: Instant,
subbuffers: Subbuffers,
scene: Vec<[u32; 4]>,
}
fn app_version() -> Version {
@@ -344,7 +356,9 @@ impl App {
let uniform_buffer_allocator = SubbufferAllocator::new(
memory_allocator.clone(),
SubbufferAllocatorCreateInfo {
buffer_usage: BufferUsage::UNIFORM_BUFFER | BufferUsage::STORAGE_BUFFER,
buffer_usage: BufferUsage::UNIFORM_BUFFER
| BufferUsage::STORAGE_BUFFER
| BufferUsage::VERTEX_BUFFER,
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
@@ -437,6 +451,11 @@ impl App {
.lights
.push(Light::new([-4., 6., -8.], [8., 4., 1.], 0.05));
let vertex_buffer: Subbuffer<[IVertex; VERTEX_COUNT]> =
uniform_buffer_allocator.allocate_sized().unwrap();
*vertex_buffer.write().unwrap() = CUBE_VERTEX;
App {
instance,
device,
@@ -450,46 +469,16 @@ impl App {
gstate,
previous_debug: PreviousDebug::default(),
cstate,
vertex_buffer,
rcx: None,
}
}
}
mod mesh_vs {
mod implicit_vs {
vulkano_shaders::shader! {
ty: "vertex",
path: "src/triangle.vert.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
custom_derives: [Debug, Clone, Copy],
}
}
mod mesh_fs {
vulkano_shaders::shader! {
ty: "fragment",
path: "src/frag.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
define: [("triangle","1")],
custom_derives: [Debug, Clone, Copy],
}
}
mod implicit_ms {
vulkano_shaders::shader! {
ty: "mesh",
path: "src/implicit.mesh.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
custom_derives: [Debug, Clone, Copy],
}
}
mod implicit_ts {
vulkano_shaders::shader! {
ty: "task",
path: "src/implicit.task.glsl",
path: "src/implicit.vert.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
custom_derives: [Debug, Clone, Copy],
@@ -499,18 +488,7 @@ mod implicit_ts {
mod implicit_fs {
vulkano_shaders::shader! {
ty: "fragment",
path: "src/frag.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
define: [("implicit","1")],
custom_derives: [Debug, Clone, Copy, Default],
}
}
mod cs {
vulkano_shaders::shader! {
ty: "compute",
path: "src/fuzz.comp.glsl",
path: "src/trace.frag.glsl",
vulkan_version: "1.3",
spirv_version: "1.6",
custom_derives: [Debug, Clone, Copy],
@@ -603,28 +581,7 @@ impl ApplicationHandler for App {
::vulkano::Validated<::vulkano::VulkanError>,
>,
> = vec![
((mesh_vs::load)
as fn(
::std::sync::Arc<::vulkano::device::Device>,
) -> Result<
::std::sync::Arc<::vulkano::shader::ShaderModule>,
::vulkano::Validated<::vulkano::VulkanError>,
>),
((mesh_fs::load)
as fn(
::std::sync::Arc<::vulkano::device::Device>,
) -> Result<
::std::sync::Arc<::vulkano::shader::ShaderModule>,
::vulkano::Validated<::vulkano::VulkanError>,
>),
((implicit_ms::load)
as fn(
::std::sync::Arc<::vulkano::device::Device>,
) -> Result<
::std::sync::Arc<::vulkano::shader::ShaderModule>,
::vulkano::Validated<::vulkano::VulkanError>,
>),
((implicit_ts::load)
((implicit_vs::load)
as fn(
::std::sync::Arc<::vulkano::device::Device>,
) -> Result<
@@ -638,13 +595,6 @@ impl ApplicationHandler for App {
::std::sync::Arc<::vulkano::shader::ShaderModule>,
::vulkano::Validated<::vulkano::VulkanError>,
>),
((cs::load)
as fn(
::std::sync::Arc<::vulkano::device::Device>,
) -> Result<
::std::sync::Arc<::vulkano::shader::ShaderModule>,
::vulkano::Validated<::vulkano::VulkanError>,
>),
];
let pariter = loaders
@@ -653,44 +603,12 @@ impl ApplicationHandler for App {
.collect::<Vec<_>>();
let shader_modules = ShaderModules {
mesh_vs: pariter[0].clone(),
mesh_fs: pariter[1].clone(),
implicit_ms: pariter[2].clone(),
implicit_ts: pariter[3].clone(),
implicit_fs: pariter[4].clone(),
compute_shader: pariter[5].clone(),
implicit_vs: pariter[0].clone(),
implicit_fs: pariter[1].clone(),
};
drop(pariter);
let compute_stage = PipelineShaderStageCreateInfo::new(
shader_modules.compute_shader.entry_point("main").unwrap(),
);
use vulkano::pipeline::ComputePipeline;
let compute_pipeline_layout = PipelineLayout::new(
self.device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([&compute_stage])
.into_pipeline_layout_create_info(self.device.clone())
.unwrap(),
)
.unwrap();
trace!(
"descriptor set: {:?}",
compute_pipeline_layout.set_layouts()
);
let compute_pipeline = ComputePipeline::new(
self.device.clone(),
None,
ComputePipelineCreateInfo::stage_layout(compute_stage, compute_pipeline_layout.clone()),
)
.expect("failed to create compute pipeline");
let render_pass = if MSAA_ENABLE {
vulkano::ordered_passes_renderpass!(
self.device.clone(),
@@ -755,13 +673,6 @@ impl ApplicationHandler for App {
}
.unwrap();
let (subbuffers, scene) = object_size_dependent_setup(
self.memory_allocator.clone(),
&self.gstate.csg,
self.command_buffer_allocator.clone(),
self.transfer_queue.clone(),
);
let viewport = Viewport {
offset: [0.0, window_size.height as f32],
extent: [window_size.width as f32, window_size.height as f32 * -1.],
@@ -770,12 +681,11 @@ impl ApplicationHandler for App {
let framebuffers = framebuffer_generation(&images, &render_pass, &self.memory_allocator);
let (mesh_pipeline, implicit_pipeline) = pipeline_recompile(
let implicit_pipeline = pipeline_recompile(
&render_pass,
&self.pipeline_cache,
&shader_modules,
&self.gstate.debug,
&scene,
if DYNAMIC_STATE { None } else { Some(&viewport) },
);
@@ -801,8 +711,6 @@ impl ApplicationHandler for App {
render_pass,
framebuffers,
shader_modules,
compute_pipeline,
mesh_pipeline,
implicit_pipeline,
viewport,
recreate_swapchain: false,
@@ -810,8 +718,6 @@ impl ApplicationHandler for App {
previous_frame_end,
gui,
render_start: Instant::now(),
subbuffers,
scene,
});
}
@@ -886,6 +792,9 @@ impl ApplicationHandler for App {
PhysicalKey::Code(KeyCode::KeyD) => {
self.cstate.keys.d = input.state == ElementState::Pressed;
},
PhysicalKey::Code(KeyCode::ShiftLeft) => {
self.cstate.looking = input.state == ElementState::Pressed;
}
_ => {},
},
WindowEvent::RedrawRequested => {
@@ -949,12 +858,11 @@ impl App {
}
if rcx.recreate_pipelines {
(rcx.mesh_pipeline, rcx.implicit_pipeline) = pipeline_recompile(
rcx.implicit_pipeline = pipeline_recompile(
&rcx.render_pass,
&self.pipeline_cache,
&rcx.shader_modules,
&self.gstate.debug,
&rcx.scene,
if DYNAMIC_STATE {
None
} else {
@@ -1016,11 +924,11 @@ impl App {
//* Mat4::from_rotation_z(std::f32::consts::PI)
* Mat4::from_translation(Vec3::ZERO - self.cstate.position);
let pc = mesh_vs::PushConstantData {
let pc = implicit_vs::PushConstantData {
world: Mat4::IDENTITY.to_cols_array_2d(),
};
let uniform_data = implicit_fs::Camera {
let uniform_data = implicit_vs::Camera {
view: view.to_cols_array_2d(),
proj: proj.to_cols_array_2d(),
campos: self.cstate.position.to_array(),
@@ -1052,7 +960,7 @@ impl App {
col[i][2] = light.colour.z;
}
let uniform_data = mesh_fs::Lights {
let uniform_data = implicit_vs::Lights {
pos,
col,
light_count: self.gstate.lights.len() as u32,
@@ -1063,10 +971,10 @@ impl App {
sub
};
let mesh_layout = &rcx.mesh_pipeline.layout().set_layouts()[0];
let mesh_set = DescriptorSet::new(
let implicit_layout = &rcx.implicit_pipeline.layout().set_layouts()[0];
let implicit_set = DescriptorSet::new(
self.descriptor_set_allocator.clone(),
mesh_layout.clone(),
implicit_layout.clone(),
[
WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer.clone()),
WriteDescriptorSet::buffer(1, cam_set.clone()),
@@ -1075,133 +983,6 @@ impl App {
)
.unwrap();
let implicit_layout = &rcx.implicit_pipeline.layout().set_layouts()[0];
let implicit_set = DescriptorSet::new(
self.descriptor_set_allocator.clone(),
implicit_layout.clone(),
[
WriteDescriptorSet::buffer(0, rcx.subbuffers.desc.clone()),
WriteDescriptorSet::buffer(1, rcx.subbuffers.scene.clone()),
WriteDescriptorSet::buffer(2, rcx.subbuffers.masks.clone()),
],
[],
)
.unwrap();
if COMPUTE_FUZZING {
let (compute_subbuffers, scene) = object_size_dependent_setup(
self.memory_allocator.clone(),
&self.gstate.csg,
self.command_buffer_allocator.clone(),
self.transfer_queue.clone(),
);
let compute_result_buffer: Subbuffer<[cs::Results]> = self
.uniform_buffer_allocator
.allocate_slice((scene.len() * 4) as u64)
.unwrap();
const EXECUTION_LIMIT: u32 = 900;
const STATIC_OPCODES: u32 = 901;
let mut spec_constants = HashMap::with_capacity(32);
spec_constants.insert(STATIC_OPCODES, SpecializationConstant::Bool(true));
spec_constants.insert(
EXECUTION_LIMIT,
SpecializationConstant::U32((scene.len() * 4) as u32),
);
for (i, val) in scene.iter().skip(1).take(32).enumerate() {
for (y, code) in val.iter().enumerate() {
spec_constants.insert(
(1000 + (i * 8) + (y * 2)) as u32,
SpecializationConstant::U32(code & 0xFFFF),
);
spec_constants.insert(
(1000 + (i * 8) + (y * 2) + 1) as u32,
SpecializationConstant::U32(code >> 16),
);
}
}
let compute_stage = PipelineShaderStageCreateInfo::new(
rcx.shader_modules
.compute_shader
.specialize(spec_constants)
.unwrap()
.single_entry_point()
.unwrap(),
);
use vulkano::pipeline::ComputePipeline;
let compute_pipeline_layout = PipelineLayout::new(
self.device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([&compute_stage])
.into_pipeline_layout_create_info(self.device.clone())
.unwrap(),
)
.unwrap();
let compute_pipeline = ComputePipeline::new(
self.device.clone(),
None,
ComputePipelineCreateInfo::stage_layout(
compute_stage,
compute_pipeline_layout.clone(),
),
)
.expect("failed to create compute pipeline");
let compute_layout = &compute_pipeline.layout().set_layouts()[0];
let compute_set = DescriptorSet::new(
self.descriptor_set_allocator.clone(),
compute_layout.clone(),
[
WriteDescriptorSet::buffer(0, compute_subbuffers.desc.clone()),
WriteDescriptorSet::buffer(1, compute_subbuffers.scene.clone()),
WriteDescriptorSet::buffer(30, compute_result_buffer.clone()),
],
[],
)
.unwrap();
let mut builder = AutoCommandBufferBuilder::primary(
self.command_buffer_allocator.clone(),
self.graphics_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.bind_pipeline_compute(compute_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Compute,
compute_pipeline.layout().clone(),
1,
compute_set,
)
.unwrap();
unsafe { builder.dispatch([1, 1, 1]) }.unwrap();
let command_buffer = builder.build().unwrap();
let future = sync::now(self.device.clone())
.then_execute(self.graphics_queue.clone(), command_buffer)
.unwrap()
.then_signal_fence_and_flush()
.unwrap();
future.wait(None).unwrap();
let content = compute_result_buffer.read().unwrap();
for val in content.iter() {
trace!("{val:?}");
}
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(rcx.swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
@@ -1258,37 +1039,6 @@ impl App {
.unwrap();
}
builder
.bind_pipeline_graphics(rcx.mesh_pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
rcx.mesh_pipeline.layout().clone(),
0,
mesh_set.clone(),
)
.unwrap();
for object in &self.gstate.meshes {
push_constants.world = (Mat4::from_translation(object.pos * 0.01)
* Mat4::from_euler(
EulerRot::XYZ,
object.rot.x.to_radians(),
object.rot.y.to_radians(),
object.rot.z.to_radians(),
)
* Mat4::from_scale(object.scale))
.to_cols_array_2d();
builder
.bind_vertex_buffers(0, object.vertices.clone())
.unwrap()
.bind_index_buffer(object.indices.clone())
.unwrap()
.push_constants(rcx.mesh_pipeline.layout().clone(), 0, push_constants)
.unwrap();
unsafe { builder.draw_indexed(object.indices.len() as u32, 1, 0, 0, 0) }.unwrap();
}
builder
.bind_pipeline_graphics(rcx.implicit_pipeline.clone())
.unwrap()
@@ -1296,8 +1046,10 @@ impl App {
PipelineBindPoint::Graphics,
rcx.implicit_pipeline.layout().clone(),
0,
(mesh_set, implicit_set),
implicit_set,
)
.unwrap()
.bind_vertex_buffers(0, self.vertex_buffer.clone())
.unwrap();
for csg in &self.gstate.csg {
@@ -1314,7 +1066,7 @@ impl App {
.push_constants(rcx.implicit_pipeline.layout().clone(), 0, push_constants)
.unwrap();
unsafe { builder.draw_mesh_tasks([1, 1, 2]) }.unwrap();
unsafe { builder.draw(VERTEX_COUNT as u32, (VERTEX_COUNT / 3) as u32, 0, 0) }.unwrap();
}
builder
@@ -1444,9 +1196,8 @@ fn pipeline_recompile(
cache: &Arc<PipelineCache>,
shader_modules: &ShaderModules,
debug: &PreviousDebug,
scene: &[[u32; 4]],
viewport: Option<&Viewport>,
) -> (Arc<GraphicsPipeline>, Arc<GraphicsPipeline>) {
) -> Arc<GraphicsPipeline> {
let device = cache.device();
const SPEC_BOUNDING_BOXES: u32 = 0;
@@ -1456,9 +1207,6 @@ fn pipeline_recompile(
const SPEC_DISABLE_TASKCULL: u32 = 4;
const SPEC_BRUTE_FORCE: u32 = 5;
const EXECUTION_LIMIT: u32 = 900;
const STATIC_OPCODES: u32 = 901;
let mut spec_constants = HashMap::with_capacity(6);
spec_constants.insert(
SPEC_BOUNDING_BOXES,
@@ -1489,40 +1237,18 @@ fn pipeline_recompile(
let specs = spec_constants;
let mesh_vs_entry = shader_modules
.mesh_vs
let implicit_vs_entry = shader_modules
.implicit_vs
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap();
let vertex_input_state = [OVertex::per_vertex()].definition(&mesh_vs_entry).unwrap();
let vertex_input_state = [IVertex::per_vertex()]
.definition(&implicit_vs_entry)
.unwrap();
let mesh_vs_info = PipelineShaderStageCreateInfo::new(mesh_vs_entry);
let mesh_fs_info = PipelineShaderStageCreateInfo::new(
shader_modules
.mesh_fs
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap(),
);
let implicit_ts_info = PipelineShaderStageCreateInfo::new(
shader_modules
.implicit_ts
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap(),
);
let implicit_ms_info = PipelineShaderStageCreateInfo::new(
shader_modules
.implicit_ms
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap(),
);
let implicit_vs_info = PipelineShaderStageCreateInfo::new(implicit_vs_entry);
let implicit_fs_info = PipelineShaderStageCreateInfo::new(
shader_modules
.implicit_fs
@@ -1534,15 +1260,9 @@ fn pipeline_recompile(
let layout = PipelineLayout::new(
device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([
&mesh_vs_info,
&mesh_fs_info,
&implicit_ts_info,
&implicit_ms_info,
&implicit_fs_info,
])
.into_pipeline_layout_create_info(device.clone())
.unwrap(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([&implicit_vs_info, &implicit_fs_info])
.into_pipeline_layout_create_info(device.clone())
.unwrap(),
)
.unwrap();
@@ -1565,11 +1285,15 @@ fn pipeline_recompile(
)
};
let mesh_pipeline = {
let stages = [mesh_vs_info, mesh_fs_info].into_iter().collect();
info!("Recompiling implicit pipeline... (may take up to 10 minutes)");
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let stages = [implicit_vs_info, implicit_fs_info].into_iter().collect();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let render_start = Instant::now();
let implicit_pipeline = {
GraphicsPipeline::new(
device.clone(),
Some(cache.clone()),
@@ -1577,57 +1301,11 @@ fn pipeline_recompile(
stages,
vertex_input_state: Some(vertex_input_state),
input_assembly_state: Some(InputAssemblyState::default()),
dynamic_state: dynamic_state.clone(),
viewport_state: Some(viewport_state.clone()),
rasterization_state: Some(RasterizationState {
front_face: FrontFace::CounterClockwise,
cull_mode: CullMode::Back,
..RasterizationState::default()
}),
depth_stencil_state: Some(DepthStencilState {
depth: Some(DepthState::simple()),
..Default::default()
}),
multisample_state: Some(MultisampleState {
rasterization_samples: subpass.num_samples().unwrap(),
..Default::default()
}),
color_blend_state: Some(ColorBlendState::with_attachment_states(
subpass.num_color_attachments(),
ColorBlendAttachmentState::default(),
)),
subpass: Some(subpass.into()),
..GraphicsPipelineCreateInfo::layout(layout.clone())
},
)
.unwrap()
};
info!("Recompiling implicit pipeline... (may take up to 10 minutes)");
let implicit_pipeline = {
let stages = if debug.brute_force {
[implicit_ms_info, implicit_fs_info].into_iter().collect()
} else {
[implicit_ts_info, implicit_ms_info, implicit_fs_info]
.into_iter()
.collect()
};
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
GraphicsPipeline::new(
device.clone(),
Some(cache.clone()),
GraphicsPipelineCreateInfo {
stages,
vertex_input_state: None,
input_assembly_state: None,
dynamic_state,
viewport_state: Some(viewport_state),
rasterization_state: Some(RasterizationState {
//front_face: Clockwise,
//cull_mode: CullMode::Back,
front_face: FrontFace::Clockwise,
cull_mode: CullMode::Back,
..RasterizationState::default()
}),
depth_stencil_state: Some(DepthStencilState {
@@ -1650,17 +1328,17 @@ fn pipeline_recompile(
.unwrap()
};
let render_end = Instant::now();
info!("Implicit pipeline compiled");
info!(
"Implicit pipeline took {} milliseconds",
(render_end - render_start).as_secs_f64() * 1000.0
);
dump_pipeline_cache(cache.clone());
(mesh_pipeline, implicit_pipeline)
}
struct Subbuffers {
masks: Subbuffer<[[u8; 500]]>,
scene: Subbuffer<[[u32; 4]]>,
desc: Subbuffer<[implicit_fs::Description]>,
implicit_pipeline
}
fn gpu_buffer<T>(
@@ -1722,140 +1400,6 @@ where
buffer
}
fn object_size_dependent_setup(
allocator: Arc<StandardMemoryAllocator>,
state: &Vec<CSG>,
command_allocator: Arc<StandardCommandBufferAllocator>,
queue: Arc<Queue>,
) -> (Subbuffers, Vec<[u32; 4]>) {
let mut scene: Vec<[u32; 4]> = vec![];
let mut desc: Vec<implicit_fs::Description> = vec![Default::default()];
for csg in state {
let tape = csg.parts.compile_to_gpu();
let tape2 = csg.parts.compile_to_spirv();
let mut description = implicit_fs::Description::default();
description.scene = (scene.len() / 4) as u32;
let chunks = tape.instructions.array_chunks::<16>();
for opcode in chunks.clone() {
scene.push(
opcode
.array_chunks::<4>()
.map(|smol| u32::from_le_bytes(*smol))
.collect::<Vec<_>>()
.try_into()
.unwrap(),
);
}
if chunks.remainder().len() > 0 {
let mut remainder = [0; 4];
for (i, item) in chunks.remainder().iter().enumerate() {
remainder[i / 4] |= (*item as u32) << ((i % 4) * 8);
}
scene.push(remainder);
}
description.io = (scene.len() / 4) as u32;
let chunks = tape.io.array_chunks::<16>();
for reg in chunks.clone() {
scene.push(
reg.array_chunks::<4>()
.map(|smol| u32::from_le_bytes(*smol))
.collect::<Vec<_>>()
.try_into()
.unwrap(),
);
}
if chunks.remainder().len() > 0 {
let mut remainder = [0; 4];
for (i, item) in chunks.remainder().iter().enumerate() {
remainder[i / 4] |= (*item as u32) << ((i % 4) * 8);
}
scene.push(remainder);
}
description.constants = (scene.len() / 4) as u32;
let chunks = tape.constants.array_chunks::<4>();
for reg in chunks.clone() {
scene.push(reg.map(|f| f.to_bits()));
}
if chunks.remainder().len() > 0 {
let mut remainder = [0; 4];
for (i, item) in chunks.remainder().iter().enumerate() {
remainder[i] = item.to_bits();
}
scene.push(remainder);
}
let mut interpret = interpreter::Interpreter::new(csg);
description.bounds[0] = interpret.scene(vec3(-10000., 0., 0.)) - 10000.0;
description.bounds[1] = interpret.scene(vec3(0., -10000., 0.)) - 10000.0;
description.bounds[2] = interpret.scene(vec3(0., 0., -10000.)) - 10000.0;
description.bounds[3] = 10000.0 - interpret.scene(vec3(10000., 0., 0.));
description.bounds[4] = 10000.0 - interpret.scene(vec3(0., 10000., 0.));
description.bounds[5] = 10000.0 - interpret.scene(vec3(0., 0., 10000.));
desc.push(description);
}
trace!("scene: {scene:?}");
trace!("desc: {desc:?}");
let fragment_masks_buffer = Buffer::new_slice(
allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::STORAGE_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE,
allocate_preference: MemoryAllocatePreference::AlwaysAllocate,
..Default::default()
},
((desc.len() - 1) * (4 * 4 * 4) * (4 * 4 * 2) * 500) as u64,
)
.unwrap();
let staging = SubbufferAllocator::new(
allocator.clone(),
SubbufferAllocatorCreateInfo {
buffer_usage: BufferUsage::TRANSFER_SRC,
memory_type_filter: MemoryTypeFilter::PREFER_HOST
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
);
let csg_scene = gpu_buffer(
&[&scene],
allocator.clone(),
&staging,
command_allocator.clone(),
queue.clone(),
);
let csg_desc = gpu_buffer(
&[&desc],
allocator.clone(),
&staging,
command_allocator.clone(),
queue.clone(),
);
(
Subbuffers {
masks: fragment_masks_buffer,
scene: csg_scene,
desc: csg_desc,
},
scene,
)
}
fn dump_pipeline_cache(cache: Arc<PipelineCache>) {
if let Ok(data) = cache.get_data() {
info!("Dumping pipeline cache...");
-415
View File
@@ -1,415 +0,0 @@
#ifndef scene_bindings
#define scene_bindings
#include "spec_constants.glsl"
struct Description {
uint scene;
uint constants;
uint io;
float[6] bounds;
} desc;
layout(set = 1, binding = 0, std430) restrict readonly buffer SceneDescription {
Description desc[];
} scene_description;
layout(set = 1, binding = 1, std430) restrict readonly buffer SceneBuf {
u32vec4 data[];
} scenes;
#ifdef interval_frags
#define fragmentmasks_layout readonly
#else
#define fragmentmasks_layout // writeonly
#endif
layout(set = 1, binding = 2, std430) restrict fragmentmasks_layout buffer fragmentMasks {
uint16_t masks[][MASK_ARRAY_LENGTH];
} fragmentpassmasks;
// each mask:
// CCPP CCPP CCPP CCPP
// CC = how many constants to skip
// PP = which input to return: execute, do nothing, copy left, copy right
const uint16_t MASK_EXECUTE = uint16_t(0);
const uint16_t MASK_COPY_LEFT = uint16_t(1);
const uint16_t MASK_COPY_RIGHT = uint16_t(2);
const uint16_t MASK_DO_NOTHING = uint16_t(3);
uint16_t mask[MASK_ARRAY_LENGTH];
void default_mask()
{
for (int i = 0; i < MASK_ARRAY_LENGTH; i++) {
mask[i] = uint16_t(0);
}
}
/// increments once for each opcode
uint program_counter = 0;
/// increments once for each nibble
uint io_counter = 0;
/// increments for each constant
uint const_counter = 0;
u32vec4 major_opcode_unpack;
u32vec4 major_io_unpack;
u32vec4 major_const_unpack;
float load_const(bool reverse) {
if ((reverse && ((const_counter % 4) == 3)) || (!reverse && ((const_counter % 4) == 0))) {
major_const_unpack = scenes.data[desc.constants + (const_counter / 4)];
}
switch (const_counter % 4) {
case 0:
return uintBitsToFloat(major_const_unpack.x);
case 1:
return uintBitsToFloat(major_const_unpack.y);
case 2:
return uintBitsToFloat(major_const_unpack.z);
case 3:
return uintBitsToFloat(major_const_unpack.w);
}
}
uint8_t load_opcode(bool reverse) {
if ((reverse && ((program_counter % 16) == 15)) || (!reverse && ((program_counter % 16) == 0))) {
major_opcode_unpack = scenes.data[desc.scene + (program_counter / 16)];
}
switch (program_counter % 16) {
case 0:
return uint8_t((major_opcode_unpack.x >> 0) & 255);
case 1:
return uint8_t((major_opcode_unpack.x >> 8) & 255);
case 2:
return uint8_t((major_opcode_unpack.x >> 16) & 255);
case 3:
return uint8_t((major_opcode_unpack.x >> 24) & 255);
case 4:
return uint8_t((major_opcode_unpack.y >> 0) & 255);
case 5:
return uint8_t((major_opcode_unpack.y >> 8) & 255);
case 6:
return uint8_t((major_opcode_unpack.y >> 16) & 255);
case 7:
return uint8_t((major_opcode_unpack.y >> 24) & 255);
case 8:
return uint8_t((major_opcode_unpack.z >> 0) & 255);
case 9:
return uint8_t((major_opcode_unpack.z >> 8) & 255);
case 10:
return uint8_t((major_opcode_unpack.z >> 16) & 255);
case 11:
return uint8_t((major_opcode_unpack.z >> 24) & 255);
case 12:
return uint8_t((major_opcode_unpack.w >> 0) & 255);
case 13:
return uint8_t((major_opcode_unpack.w >> 8) & 255);
case 14:
return uint8_t((major_opcode_unpack.w >> 16) & 255);
case 15:
return uint8_t((major_opcode_unpack.w >> 24) & 255);
}
}
uint8_t load_input(bool reverse) {
if ((reverse && ((io_counter % 32) == 31)) || (!reverse && ((io_counter % 32) == 0))) {
major_io_unpack = scenes.data[desc.io + (io_counter / 32)];
}
switch (io_counter % 32) {
case 0:
return uint8_t((major_io_unpack.x >> 0) & 15);
case 1:
return uint8_t((major_io_unpack.x >> 4) & 15);
case 2:
return uint8_t((major_io_unpack.x >> 8) & 15);
case 3:
return uint8_t((major_io_unpack.x >> 12) & 15);
case 4:
return uint8_t((major_io_unpack.x >> 16) & 15);
case 5:
return uint8_t((major_io_unpack.x >> 20) & 15);
case 6:
return uint8_t((major_io_unpack.x >> 24) & 15);
case 7:
return uint8_t((major_io_unpack.x >> 28) & 15);
case 8:
return uint8_t((major_io_unpack.y >> 0) & 15);
case 9:
return uint8_t((major_io_unpack.y >> 4) & 15);
case 10:
return uint8_t((major_io_unpack.y >> 8) & 15);
case 11:
return uint8_t((major_io_unpack.y >> 12) & 15);
case 12:
return uint8_t((major_io_unpack.y >> 16) & 15);
case 13:
return uint8_t((major_io_unpack.y >> 20) & 15);
case 14:
return uint8_t((major_io_unpack.y >> 24) & 15);
case 15:
return uint8_t((major_io_unpack.y >> 28) & 15);
case 16:
return uint8_t((major_io_unpack.z >> 0) & 15);
case 17:
return uint8_t((major_io_unpack.z >> 4) & 15);
case 18:
return uint8_t((major_io_unpack.z >> 8) & 15);
case 19:
return uint8_t((major_io_unpack.z >> 12) & 15);
case 20:
return uint8_t((major_io_unpack.z >> 16) & 15);
case 21:
return uint8_t((major_io_unpack.z >> 20) & 15);
case 22:
return uint8_t((major_io_unpack.z >> 24) & 15);
case 23:
return uint8_t((major_io_unpack.z >> 28) & 15);
case 24:
return uint8_t((major_io_unpack.w >> 0) & 15);
case 25:
return uint8_t((major_io_unpack.w >> 4) & 15);
case 26:
return uint8_t((major_io_unpack.w >> 8) & 15);
case 27:
return uint8_t((major_io_unpack.w >> 12) & 15);
case 28:
return uint8_t((major_io_unpack.w >> 16) & 15);
case 29:
return uint8_t((major_io_unpack.w >> 20) & 15);
case 30:
return uint8_t((major_io_unpack.w >> 24) & 15);
case 31:
return uint8_t((major_io_unpack.w >> 28) & 15);
}
}
uint8_t prev_opcode() {
program_counter -= 1;
return load_opcode(false);
}
uint8_t next_opcode() {
uint8_t t = load_opcode(true);
program_counter += 1;
return t;
}
uint8_t prev_register() {
io_counter -= 1;
return load_input(false);
}
uint8_t next_register() {
uint8_t t = load_input(true);
io_counter += 1;
return t;
}
void jump_registers(uint dist) {
bool reload_cache = (io_counter / 32) != ((io_counter + dist) / 32);
io_counter += dist;
if (reload_cache) {
major_io_unpack = scenes.data[desc.io + (io_counter / 32)];
}
}
float prev_const() {
const_counter -= 1;
return load_const(false);
}
float next_const() {
float t = load_const(true);
const_counter += 1;
return t;
}
void jump_const(uint dist) {
bool reload_cache = (const_counter / 4) != ((const_counter + dist) / 4);
const_counter += dist;
if (reload_cache) {
major_const_unpack = scenes.data[desc.constants + (const_counter / 4)];
}
}
#define unroll_instruction_set(index, name) \
const uint8_t OPCopy##name = uint8_t(OPCopy+(index<<6));\
const uint8_t OPAdd##name = uint8_t(OPAdd+(index<<6));\
const uint8_t OPSub##name = uint8_t(OPSub+(index<<6));\
const uint8_t OPMul##name = uint8_t(OPMul+(index<<6));\
const uint8_t OPDiv##name = uint8_t(OPDiv+(index<<6));\
const uint8_t OPAtan2##name = uint8_t(OPAtan2+(index<<6));\
const uint8_t OPMin##name = uint8_t(OPMin+(index<<6));\
const uint8_t OPMax##name = uint8_t(OPMax+(index<<6));\
const uint8_t OPCompare##name = uint8_t(OPCompare+(index<<6));\
const uint8_t OPMod##name = uint8_t(OPMod+(index<<6));\
const uint8_t OPAnd##name = uint8_t(OPAnd+(index<<6));\
const uint8_t OPOr##name = uint8_t(OPOr+(index<<6));\
const uint8_t OPNegate##name = uint8_t(OPNegate+(index<<6));\
const uint8_t OPAbs##name = uint8_t(OPAbs+(index<<6));\
const uint8_t OPRecip##name = uint8_t(OPRecip+(index<<6));\
const uint8_t OPSqrt##name = uint8_t(OPSqrt+(index<<6));\
const uint8_t OPSquare##name = uint8_t(OPSquare+(index<<6));\
const uint8_t OPFloor##name = uint8_t(OPFloor+(index<<6));\
const uint8_t OPCeil##name = uint8_t(OPCeil+(index<<6));\
const uint8_t OPRound##name = uint8_t(OPRound+(index<<6));\
const uint8_t OPSin##name = uint8_t(OPSin+(index<<6));\
const uint8_t OPCos##name = uint8_t(OPCos+(index<<6));\
const uint8_t OPTan##name = uint8_t(OPTan+(index<<6));\
const uint8_t OPAsin##name = uint8_t(OPAsin+(index<<6));\
const uint8_t OPAcos##name = uint8_t(OPAcos+(index<<6));\
const uint8_t OPAtan##name = uint8_t(OPAtan+(index<<6));\
const uint8_t OPExp##name = uint8_t(OPExp+(index<<6));\
const uint8_t OPLog##name = uint8_t(OPLog+(index<<6));\
const uint8_t OPNot##name = uint8_t(OPNot+(index<<6));\
const uint8_t OPFract##name = uint8_t(OPFract+(index<<6));\
const uint8_t OPCube##name = uint8_t(OPCube+(index<<6));\
const uint8_t OPSmoothMin##name = uint8_t(OPSmoothMin+(index<<6));\
const uint8_t OPSmoothMax##name = uint8_t(OPSmoothMax+(index<<6));\
const uint8_t OPClamp##name = uint8_t(OPClamp+(index<<6));\
const uint8_t OPMix##name = uint8_t(OPMix+(index<<6));\
const uint8_t OPFMA##name = uint8_t(OPFMA+(index<<6));\
const uint8_t OPLength##name = uint8_t(OPLength+(index<<6));\
const uint8_t OPNormalize##name = uint8_t(OPNormalize+(index<<6)); \
const uint8_t OPDot##name = uint8_t(OPDot+(index<<6));\
const uint8_t OPDistance##name = uint8_t(OPDistance+(index<<6));\
unroll_instruction_set(0, Vec1)
unroll_instruction_set(1, Vec2)
unroll_instruction_set(2, Vec3)
unroll_instruction_set(3, Vec4)
uint reg_output(uint8_t opcode) {
switch (uint(opcode)) {
case OPNop:
return 0;
case OPReturn:
return 0;
case OPPosition:
return 3;
case OPMinMaterial:
return 1;
case OPMaxMaterial:
return 1;
case OPSmoothMinMaterial:
return 1;
case OPSmoothMaxMaterial:
return 1;
case OPCross:
return 3;
case OPDistance:
return 1;
case OPLength:
return 1;
case OPDot:
return 1;
case OPSDFSphere:
return 1;
case OPSDFBox:
return 1;
case OPSDFTorus:
return 1;
default:
return (opcode >> 6) + 1;
}
}
uint reg_input(uint8_t opcode) {
switch (uint(opcode)) {
case OPNop:
return 0;
case OPReturn:
return 1;
case OPPosition:
return 0;
case OPMinMaterial:
return 2;
case OPMaxMaterial:
return 2;
case OPSmoothMinMaterial:
return 3;
case OPSmoothMaxMaterial:
return 3;
case OPCross:
return 3 + 3;
case OPSDFSphere:
return 3 + 1;
case OPSDFBox:
return 3 + 3;
case OPSDFTorus:
return 3 + 2;
case OPAdd:
case OPSub:
case OPMul:
case OPDiv:
case OPAtan2:
case OPMin:
case OPMax:
case OPCompare:
case OPMod:
case OPAnd:
case OPOr:
case OPDot:
case OPDistance:
return ((opcode >> 6) + 1) * 2;
case OPSmoothMin:
case OPSmoothMax:
case OPClamp:
case OPMix:
case OPFMA:
return ((opcode >> 6) + 1) * 3;
default:
return ((opcode >> 6) + 1);
}
}
uint[2] reg_elementwise(uint8_t opcode) {
switch (uint(opcode)) {
case OPNop:
case OPReturn:
case OPPosition:
case OPMinMaterial:
case OPMaxMaterial:
case OPSmoothMinMaterial:
case OPSmoothMaxMaterial:
case OPCross:
case OPSDFSphere:
case OPSDFBox:
case OPSDFTorus:
case OPDot:
case OPDistance:
case OPLength:
case OPNormalize:
return uint[2](0, 0);
case OPAdd:
case OPSub:
case OPMul:
case OPDiv:
case OPAtan2:
case OPMin:
case OPCompare:
case OPMod:
case OPAnd:
case OPOr:
return uint[2](2, 1);
case OPSmoothMin:
case OPSmoothMax:
case OPClamp:
case OPMix:
case OPFMA:
return uint[2](3, 1);
default:
return uint[2](1, 1);
}
}
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef spec_constants
#define spec_constants
layout(constant_id = 0) const bool BOUNDING_BOXES = false;
layout(constant_id = 1) const bool DISABLE_MESHCULL = false;
layout(constant_id = 2) const bool DISABLE_MESHSCALING1 = false;
layout(constant_id = 3) const bool DISABLE_MESHSCALING2 = false;
layout(constant_id = 4) const bool DISABLE_TASKCULL = false;
layout(constant_id = 5) const bool BRUTE_FORCE = false;
const uint MASK_ARRAY_LENGTH = 500;
layout(constant_id = 7) const uint EXECUTION_LIMIT = 500;
//#include "static_opcode_array.glsl"
#endif
+85
View File
@@ -0,0 +1,85 @@
// global fragment shader
#version 460
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
layout(location = 1) in vec4 pos;
layout(depth_greater) out float gl_FragDepth;
layout(location = 0) out vec4 f_color;
/// SHARED CODE ///
vec3 shading(vec3 normal, vec4 position)
{
vec3 accum = vec3(0., 0., 0.);
mat3 rotation = mat3(pc.world[0].xyz, pc.world[1].xyz, pc.world[2].xyz);
//vec3 position=pc.world[3].xyz;
for (int i = 0; (i < light_uniforms.light_count) && (i < 32); i++)
{
accum += light_uniforms.col[i].xyz * ((dot(normalize(rotation * normal), normalize(light_uniforms.pos[i].xyz - position.xyz)) * .5) + .5);
}
return accum;
}
float scene(vec3 p) {
return length(p) - 1.0;
}
const float EPSILON = .0001;
const uint MAX_STEPS = 50;
#define NEARPLANE 0.
float FARPLANE;
#define gl_GlobalInvocationID uvec3(1)
vec3 getNormal(vec3 p, float dens) {
vec3 n;
n.x = scene(vec3(p.x + EPSILON, p.y, p.z)).x;
n.y = scene(vec3(p.x, p.y + EPSILON, p.z)).x;
n.z = scene(vec3(p.x, p.y, p.z + EPSILON)).x;
return normalize(n - (scene(p)));
}
vec2 spheretracing(vec3 ori, vec3 dir, out vec3 p) {
vec2 td = vec2(NEARPLANE, 1.);
p = ori;
td.y = scene(p).x * .9;
td.x += td.y;
p = ori + dir * td.x;
for (int i = 0; i < MAX_STEPS && td.y > EPSILON && td.x < FARPLANE; i++) {
td.y = scene(p).x * .9;
td.x += td.y;
p = ori + dir * td.x;
}
return td;
}
//Implicit Surface Entrypoint
void main() {
vec3 raypos = pos.xyz;
vec3 p;
vec3 raydir = normalize(raypos - (inverse(pc.world) * vec4(camera_uniforms.campos, 1)).xyz);
vec2 td = spheretracing(raypos, raydir, p);
if (td.y < EPSILON)
{
vec3 n = getNormal(p, td.y);
//f_color=vec4(1.);
f_color = vec4(shading(n, inverse(pc.world) * vec4(p, 1.)), 1.);
vec4 tpoint = camera_uniforms.proj * camera_uniforms.view * pc.world * vec4(p, 1);
gl_FragDepth = (tpoint.z / tpoint.w);
}
else
{
// discard;
}
f_color = vec4(1.0, 0.0, 1.0, 1.0);
return;
}