Skip to content

Instantly share code, notes, and snippets.

@kig
Last active March 9, 2020 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kig/918e87715086b945cb4ae937876360f9 to your computer and use it in GitHub Desktop.
Save kig/918e87715086b945cb4ae937876360f9 to your computer and use it in GitHub Desktop.
#version 450
#extension GL_ARB_separate_shader_objects : enable
#define WORKER_SIZE 16
#define WORKGROUP_SIZE 4
layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1 ) in;
struct Pixel{
vec4 value;
};
layout(std430, binding = 0) buffer inputs
{
float dimensions[];
};
layout(std430, binding = 1) buffer outputs
{
Pixel imageData[];
};
void main() {
int width = int(dimensions[0]);
int height = int(dimensions[1]);
for (uint iy = 0; iy < WORKER_SIZE; iy++)
for (uint ix = 0; ix < WORKER_SIZE; ix++)
{
uint px = gl_GlobalInvocationID.x * WORKER_SIZE + ix;
uint py = gl_GlobalInvocationID.y * WORKER_SIZE + iy;
/*
In order to fit the work into workgroups, some unnecessary threads are launched.
We terminate those threads here.
*/
if(px >= width || py >= height)
continue;
float x = float(px) / float(width);
float y = float(py) / float(height);
/*
What follows is code for rendering the mandelbrot set.
*/
vec2 uv = vec2(x,y);
float n = 0.0;
vec2 c = vec2(-.445, 0.0) + (uv - 0.5)*(2.0+ 1.7*0.2 ),
z = vec2(0.0);
const int M = 128;
for (int i = 0; i < M; i++)
{
z = vec2(z.x*z.x - z.y*z.y, 2.*z.x*z.y) + c;
if (dot(z, z) > 2) break;
n++;
}
// we use a simple cosine palette to determine color:
// http://iquilezles.org/www/articles/palettes/palettes.htm
float t = float(n) / float(M);
vec3 d = vec3(0.3, 0.3 ,0.5);
vec3 e = vec3(-0.2, -0.3 ,-0.5);
vec3 f = vec3(2.1, 2.0, 3.0);
vec3 g = vec3(0.0, 0.1, 0.0);
vec4 color = vec4( d + e*cos( 6.28318*(f*t+g) ) ,1.0);
// store the rendered mandelbrot set into a storage buffer:
imageData[width * py + px].value = color;
}
}
//
//////////////////////////////
// This ISPC kernel is autogenerated by spirv-cross.
// Mon Mar 9 04:46:50 2020
//////////////////////////////
//
#include "spirvcross_stdlib.ispc"
//////////////////////////////
// Work Group
//////////////////////////////
static uniform int3 gl_WorkGroupSize = {4, 4, 1};
//////////////////////////////
// Resources
//////////////////////////////
struct Pixel
{
float4 value;
};
struct inputs
{
float dimensions[];
};
struct outputs
{
struct Pixel imageData[];
};
//////////////////////////////
// Shader Code
//////////////////////////////
static SPIRV_INLINE void mandel_ispc_main(varying int3 gl_GlobalInvocationID, uniform struct outputs& _196, uniform struct inputs& _13)
{
uniform float _17 = _13.dimensions[0];
uniform int width = int_cast(_17);
uniform float _22 = _13.dimensions[1];
uniform int height = int_cast(_22);
for (uniform int iy = 0u; iy < 16u; iy += (int)(1))
{
for (uniform int ix = 0u; ix < 16u; ix += (int)(1))
{
varying int _51 = gl_GlobalInvocationID.x;
varying int px = (_51 * 16u) + ix;
varying int _58 = gl_GlobalInvocationID.y;
varying int py = (_58 * 16u) + iy;
varying int _62 = px;
uniform int _63 = width;
varying bool _65 = _62 >= int_cast(_63);
varying bool _73;
if (!_65)
{
_73 = py >= int_cast(height);
}
else
{
_73 = _65;
}
if (_73)
{
continue;
}
varying float x = float_cast(px) / float_cast(width);
varying float y = float_cast(py) / float_cast(height);
varying float2 uv = float2(x, y);
varying float n = 0.0f;
varying float2 c = float2(-0.444999992847442626953125f, 0.0f) + ((uv - float2(0.5f)) * 2.3399999141693115234375f);
varying float2 z = float2(0.0f);
for (uniform int i = 0; i < 128; i++)
{
varying float _120 = z.x;
varying float _122 = z.x;
varying float _125 = z.y;
varying float _127 = z.y;
varying float _132 = z.x;
varying float _135 = z.y;
z = float2((_120 * _122) - (_125 * _127), (2.0f * _132) * _135) + c;
if (dot(z, z) > 2.0f)
{
break;
}
n += 1.0f;
}
varying float t = n / 128.0f;
uniform float3 d = float3(0.300000011920928955078125f, 0.300000011920928955078125f, 0.5f);
uniform float3 e = float3(-0.20000000298023223876953125f, -0.300000011920928955078125f, -0.5f);
uniform float3 f = float3(2.099999904632568359375f, 2.0f, 3.0f);
uniform float3 g = float3(0.0f, 0.100000001490116119384765625f, 0.0f);
varying float3 _187 = d + (e * cos(((f * t) + g) * 6.28318023681640625f));
varying float4 color = float4(_187.x, _187.y, _187.z, 1.0f);
_196.imageData[(int_cast(width) * py) + px].value = color;
}
}
}
task
void runner_tiled(uniform int3 gl_NumWorkGroups, uniform struct inputs& input, uniform struct outputs& output)
{
uniform int3 gl_WorkGroupID = int3(taskIndex0, taskIndex1, taskIndex2);
// Vectorise the workgroup
foreach(lz = 0 ... gl_WorkGroupSize.z, ly = 0 ... gl_WorkGroupSize.y, lx = 0 ... gl_WorkGroupSize.x)
{
varying int3 gl_LocalInvocationID = int3(lx, ly, lz);
varying int3 gl_GlobalInvocationID = gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;
varying int gl_LocalInvocationIndex = gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + gl_LocalInvocationID.y * gl_WorkGroupSize.x + gl_LocalInvocationID.x;
mandel_ispc_main(gl_GlobalInvocationID, output, input);
}
}
export void runner_main(uniform int work_groups[3], uniform struct inputs& input, uniform struct outputs& output)
{
uniform int3 gl_NumWorkGroups = int3(work_groups[0], work_groups[1], work_groups[2]);
launch[work_groups[0], work_groups[1], work_groups[2]]
runner_tiled(gl_NumWorkGroups, input, output);
}
// This C++ shader is autogenerated by spirv-cross. (#line annotations pointing to the glsl file)
#include "spirv_cross/internal_interface.hpp"
#include "spirv_cross/external_interface.h"
#include <array>
#include <stdint.h>
using namespace spirv_cross;
using namespace glm;
namespace Impl
{
struct Shader
{
struct Pixel
{
vec4 value;
};
struct Resources : ComputeResources
{
struct inputs
{
float dimensions[1];
};
internal::Resource<inputs> _14__;
#define _14 __res->_14__.get()
struct outputs
{
struct Pixel imageData[1];
};
internal::Resource<outputs> _197__;
#define _197 __res->_197__.get()
inline void init(spirv_cross_shader& s)
{
ComputeResources::init(s);
s.register_resource(_14__, 0, 0);
s.register_resource(_197__, 0, 1);
}
};
Resources* __res;
ComputePrivateResources __priv_res;
#line 32 "mandel.comp"
inline void main()
{
#line 32 "mandel.comp"
int32_t width = int32_t(_14.dimensions[0]);
#line 33 "mandel.comp"
int32_t height = int32_t(_14.dimensions[1]);
#line 35 "mandel.comp"
for (uint32_t iy = 0u; iy < 16u; iy += uint32_t(1))
{
#line 36 "mandel.comp"
for (uint32_t ix = 0u; ix < 16u; ix += uint32_t(1))
{
#line 39 "mandel.comp"
uint32_t px = (gl_GlobalInvocationID.x * 16u) + ix;
#line 40 "mandel.comp"
uint32_t py = (gl_GlobalInvocationID.y * 16u) + iy;
#line 46 "mandel.comp"
bool _66 = px >= uint32_t(width);
bool _74;
if (!_66)
{
_74 = py >= uint32_t(height);
}
else
{
_74 = _66;
}
if (_74)
{
#line 47 "mandel.comp"
continue;
}
#line 49 "mandel.comp"
float x = float(px) / float(width);
#line 50 "mandel.comp"
float y = float(py) / float(height);
#line 55 "mandel.comp"
vec2 uv = vec2(x, y);
#line 56 "mandel.comp"
float n = 0.0f;
#line 57 "mandel.comp"
vec2 c = vec2(-0.444999992847442626953125f, 0.0f) + ((uv - vec2(0.5f)) * 2.3399999141693115234375f);
#line 58 "mandel.comp"
vec2 z = vec2(0.0f);
#line 60 "mandel.comp"
for (int32_t i = 0; i < 128; i++)
{
#line 62 "mandel.comp"
z = vec2((z.x * z.x) - (z.y * z.y), (2.0f * z.x) * z.y) + c;
#line 63 "mandel.comp"
if (dot(z, z) > 2.0f)
{
break;
}
#line 64 "mandel.comp"
n += 1.0f;
}
#line 68 "mandel.comp"
float t = n / 128.0f;
#line 69 "mandel.comp"
vec3 d = vec3(0.300000011920928955078125f, 0.300000011920928955078125f, 0.5f);
#line 70 "mandel.comp"
vec3 e = vec3(-0.20000000298023223876953125f, -0.300000011920928955078125f, -0.5f);
#line 71 "mandel.comp"
vec3 f = vec3(2.099999904632568359375f, 2.0f, 3.0f);
#line 72 "mandel.comp"
vec3 g = vec3(0.0f, 0.100000001490116119384765625f, 0.0f);
#line 73 "mandel.comp"
vec4 color = vec4(d + (e * cos(((f * t) + g) * 6.28318023681640625f)), 1.0f);
#line 76 "mandel.comp"
_197.imageData[(uint32_t(width) * py) + px].value = color;
}
}
}
};
}
spirv_cross_shader_t *spirv_cross_construct(void)
{
return new ComputeShader<Impl::Shader, Impl::Shader::Resources, 4, 4, 1>();
}
void spirv_cross_destruct(spirv_cross_shader_t *shader)
{
delete static_cast<ComputeShader<Impl::Shader, Impl::Shader::Resources, 4, 4, 1>*>(shader);
}
void spirv_cross_invoke(spirv_cross_shader_t *shader)
{
static_cast<ComputeShader<Impl::Shader, Impl::Shader::Resources, 4, 4, 1>*>(shader)->invoke();
}
static const struct spirv_cross_interface vtable =
{
spirv_cross_construct,
spirv_cross_destruct,
spirv_cross_invoke,
};
const struct spirv_cross_interface *spirv_cross_get_interface(void)
{
return &vtable;
}
static inline unsigned int8
mandel(float c_re, float c_im, int count) {
float z_re = c_re, z_im = c_im;
int i;
for (i = 0; i < count; ++i) {
if (z_re * z_re + z_im * z_im > 4.)
break;
float new_re = z_re*z_re - z_im*z_im;
float new_im = 2.f * z_re * z_im;
unmasked {
z_re = c_re + new_re;
z_im = c_im + new_im;
}
}
return i;
}
/* Task to compute the Mandelbrot iterations for a single scanline.
*/
task void
mandelbrot_scanline(uniform float x0, uniform float dx,
uniform float y0, uniform float dy,
uniform int width, uniform int height,
uniform int xspan, uniform int yspan,
uniform int maxIterations, uniform unsigned int8 output[]) {
const uniform int xstart = taskIndex0 * xspan;
const uniform int xend = min(xstart + xspan, width);
const uniform int ystart = taskIndex1 * yspan;
const uniform int yend = min(ystart + yspan, height);
foreach (yi = ystart ... yend, xi = xstart ... xend) {
float x = x0 + xi * dx;
float y = y0 + yi * dy;
int index = yi * width + xi;
output[index] = mandel(x, y, maxIterations);
}
}
export void
main_ispc(uniform float input[], uniform unsigned int8 output[]) {
uniform float x0 = input[0];
uniform float y0 = input[1];
uniform float x1 = x0+input[2];
uniform float y1 = y0+input[3];
uniform int width = input[4];
uniform int height = input[5];
uniform int maxIterations = input[6];
uniform float dx = (x1 - x0) / width;
uniform float dy = (y1 - y0) / height;
const uniform int xspan = width / 4;
const uniform int yspan = 4;
launch [width/xspan, height/yspan]
mandelbrot_scanline(x0, dx, y0, dy, width, height, xspan, yspan,
maxIterations, output);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment