Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
struct VertexAttrib;
namespace glsl {
// Type holding group of scalars interpolated across rasterized rows and spans,
// shuttling values between vertex shaders and fragment shaders.
// GCC requires power-of-two vector sizes, so must use glsl type as workaround
// to operate in Float-sized chunks.
typedef vec3 Interpolants;
// Clip distances, if enabled, are always stored in the first SIMD chunk of the
// interpolants.
static ALWAYS_INLINE Float get_clip_distances(const Interpolants& interp) {
return interp.x;
}
struct VertexShaderImpl;
struct FragmentShaderImpl;
struct ProgramImpl {
virtual ~ProgramImpl() {}
virtual int get_uniform(const char* name) const = 0;
virtual void bind_attrib(const char* name, int index) = 0;
virtual int get_attrib(const char* name) const = 0;
virtual size_t interpolants_size() const = 0;
virtual VertexShaderImpl* get_vertex_shader() = 0;
virtual FragmentShaderImpl* get_fragment_shader() = 0;
virtual const char* get_name() const = 0;
};
typedef ProgramImpl* (*ProgramLoader)();
// The maximum size of the gl_ClipDistance array.
constexpr int32_t gl_MaxClipDistances = 4;
struct VertexShaderImpl {
typedef void (*SetUniform1iFunc)(VertexShaderImpl*, int index, int value);
typedef void (*SetUniform4fvFunc)(VertexShaderImpl*, int index,
const float* value);
typedef void (*SetUniformMatrix4fvFunc)(VertexShaderImpl*, int index,
const float* value);
typedef void (*InitBatchFunc)(VertexShaderImpl*);
typedef void (*LoadAttribsFunc)(VertexShaderImpl*, VertexAttrib* attribs,
uint32_t start, int instance, int count);
typedef void (*RunPrimitiveFunc)(VertexShaderImpl*, char* interps,
size_t interp_stride);
SetUniform1iFunc set_uniform_1i_func = nullptr;
SetUniform4fvFunc set_uniform_4fv_func = nullptr;
SetUniformMatrix4fvFunc set_uniform_matrix4fv_func = nullptr;
InitBatchFunc init_batch_func = nullptr;
LoadAttribsFunc load_attribs_func = nullptr;
RunPrimitiveFunc run_primitive_func = nullptr;
enum FLAGS {
CLIP_DISTANCE = 1 << 0,
};
int flags = 0;
void enable_clip_distance() { flags |= CLIP_DISTANCE; }
ALWAYS_INLINE bool use_clip_distance() const {
return (flags & CLIP_DISTANCE) != 0;
}
vec4 gl_Position;
Float gl_ClipDistance[gl_MaxClipDistances];
void set_uniform_1i(int index, int value) {
(*set_uniform_1i_func)(this, index, value);
}
void set_uniform_4fv(int index, const float* value) {
(*set_uniform_4fv_func)(this, index, value);
}
void set_uniform_matrix4fv(int index, const float* value) {
(*set_uniform_matrix4fv_func)(this, index, value);
}
void init_batch() { (*init_batch_func)(this); }
ALWAYS_INLINE void load_attribs(VertexAttrib* attribs, uint32_t start,
int instance, int count) {
(*load_attribs_func)(this, attribs, start, instance, count);
}
ALWAYS_INLINE void run_primitive(char* interps, size_t interp_stride) {
(*run_primitive_func)(this, interps, interp_stride);
}
};
// The number of pixels in a step.
constexpr int32_t swgl_StepSize = 4;
struct FragmentShaderImpl {
typedef void (*InitSpanFunc)(FragmentShaderImpl*, const void* interps,
const void* step);
typedef void (*RunFunc)(FragmentShaderImpl*);
typedef void (*SkipFunc)(FragmentShaderImpl*, int steps);
typedef void (*InitSpanWFunc)(FragmentShaderImpl*, const void* interps,
const void* step);
typedef void (*RunWFunc)(FragmentShaderImpl*);
typedef void (*SkipWFunc)(FragmentShaderImpl*, int steps);
typedef int (*DrawSpanRGBA8Func)(FragmentShaderImpl*);
typedef int (*DrawSpanR8Func)(FragmentShaderImpl*);
InitSpanFunc init_span_func = nullptr;
RunFunc run_func = nullptr;
SkipFunc skip_func = nullptr;
InitSpanWFunc init_span_w_func = nullptr;
RunWFunc run_w_func = nullptr;
SkipWFunc skip_w_func = nullptr;
DrawSpanRGBA8Func draw_span_RGBA8_func = nullptr;
DrawSpanR8Func draw_span_R8_func = nullptr;
enum FLAGS {
DISCARD = 1 << 0,
PERSPECTIVE = 1 << 1,
};
int flags = 0;
void enable_discard() { flags |= DISCARD; }
void enable_perspective() { flags |= PERSPECTIVE; }
ALWAYS_INLINE bool use_discard() const { return (flags & DISCARD) != 0; }
ALWAYS_INLINE bool use_perspective() const {
return (flags & PERSPECTIVE) != 0;
}
vec4 gl_FragCoord;
vec4 gl_FragColor;
vec4 gl_SecondaryFragColor;
vec2_scalar swgl_StepZW;
Bool swgl_IsPixelDiscarded = false;
// The current buffer position for committing span output.
uint32_t* swgl_OutRGBA8 = nullptr;
uint8_t* swgl_OutR8 = nullptr;
// The remaining number of pixels in the span.
int32_t swgl_SpanLength = 0;
ALWAYS_INLINE void step_fragcoord(int steps = 4) { gl_FragCoord.x += steps; }
ALWAYS_INLINE void step_perspective(int steps = 4) {
gl_FragCoord.z += swgl_StepZW.x * steps;
gl_FragCoord.w += swgl_StepZW.y * steps;
}
template <bool W = false>
ALWAYS_INLINE void init_span(const void* interps, const void* step) {
(*(W ? init_span_w_func : init_span_func))(this, interps, step);
}
template <bool W = false>
ALWAYS_INLINE void run() {
(*(W ? run_w_func : run_func))(this);
}
template <bool W = false>
ALWAYS_INLINE void skip(int steps = 4) {
(*(W ? skip_w_func : skip_func))(this, steps);
}
ALWAYS_INLINE int draw_span(uint32_t* buf, int len) {
swgl_OutRGBA8 = buf;
swgl_SpanLength = len;
return (*draw_span_RGBA8_func)(this);
}
ALWAYS_INLINE bool has_draw_span(uint32_t*) {
return draw_span_RGBA8_func != nullptr;
}
ALWAYS_INLINE int draw_span(uint8_t* buf, int len) {
swgl_OutR8 = buf;
swgl_SpanLength = len;
return (*draw_span_R8_func)(this);
}
ALWAYS_INLINE bool has_draw_span(uint8_t*) {
return draw_span_R8_func != nullptr;
}
};
} // namespace glsl