aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2017-07-26 17:43:38 +0200
committerAndre Weissflog <floooh@gmail.com>2017-07-26 17:43:38 +0200
commit2b67a23a7515a0e063cec2ff3a6ba160a7717d16 (patch)
tree201a548c2aa87f2c418eb8c2aca3a4a96ea1e03a
parentb17ad1f6687648f02d5e1954d9a81c65d22cdcb1 (diff)
MRT begin_pass, new begin_default_pass, new shader uniform declaration
-rw-r--r--.gitignore6
-rw-r--r--_sokol_gfx.impl.h133
-rw-r--r--_sokol_gfx_gl.impl.h107
-rw-r--r--sokol_gfx.h15
4 files changed, 189 insertions, 72 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..3f19db91
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.vscode/
+#>fips
+# this area is managed by fips, do not edit
+.fips-*
+*.pyc
+#<fips
diff --git a/_sokol_gfx.impl.h b/_sokol_gfx.impl.h
index c09d647f..5ce010a7 100644
--- a/_sokol_gfx.impl.h
+++ b/_sokol_gfx.impl.h
@@ -87,19 +87,22 @@ void sg_init_image_desc(sg_image_desc* desc) {
static void _sg_init_shader_stage_desc(sg_shader_stage_desc* desc) {
SOKOL_ASSERT(desc);
desc->source = 0;
+ desc->num_ubs = 0;
+ desc->num_images = 0;
for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
sg_shader_uniform_block_desc* ub_desc = &desc->ub[ub_index];
ub_desc->size = 0;
+ ub_desc->num_uniforms = 0;
for (int u_index = 0; u_index < SG_MAX_UNIFORMS; u_index++) {
sg_shader_uniform_desc* u_desc = &ub_desc->u[u_index];
u_desc->name = 0;
u_desc->offset = 0;
u_desc->type = SG_UNIFORMTYPE_INVALID;
- u_desc->count = 1;
+ u_desc->array_count = 1;
}
}
for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {
- sg_shader_image_desc* img_desc = &desc->images[img_index];
+ sg_shader_image_desc* img_desc = &desc->image[img_index];
img_desc->name = 0;
img_desc->type = SG_IMAGETYPE_INVALID;
}
@@ -112,22 +115,32 @@ void sg_init_shader_desc(sg_shader_desc* desc) {
_sg_init_shader_stage_desc(&desc->fs);
}
-void sg_init_uniform_block(sg_shader_uniform_block_desc* desc, int ub_size) {
+void sg_init_uniform_block(sg_shader_desc* desc, sg_shader_stage stage, int ub_size) {
SOKOL_ASSERT(desc);
+ SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS));
SOKOL_ASSERT(ub_size > 0);
- desc->size = ub_size;
+ sg_shader_stage_desc* s = (stage == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;
+ SOKOL_ASSERT(s->num_ubs < SG_MAX_SHADERSTAGE_UBS);
+ SOKOL_ASSERT(s->ub[s->num_ubs].size == 0);
+ s->ub[s->num_ubs++].size = ub_size;
}
-void sg_init_named_uniform(sg_shader_uniform_desc* desc, const char* name, int ub_offset, sg_uniform_type type, int array_count) {
+void sg_init_named_uniform(sg_shader_desc* desc, sg_shader_stage stage, const char* name, int ub_offset, sg_uniform_type type, int array_count) {
SOKOL_ASSERT(desc);
+ SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS));
SOKOL_ASSERT(name);
SOKOL_ASSERT(ub_offset >= 0);
SOKOL_ASSERT(type != SG_UNIFORMTYPE_INVALID);
SOKOL_ASSERT(array_count >= 1);
- desc->name = name;
- desc->offset = ub_offset;
- desc->type = type;
- desc->count = array_count;
+ sg_shader_stage_desc* s = (stage == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;
+ SOKOL_ASSERT(s->num_ubs >= 1);
+ sg_shader_uniform_block_desc* ub = &(s->ub[s->num_ubs-1]);
+ SOKOL_ASSERT(ub->num_uniforms < SG_MAX_UNIFORMS);
+ sg_shader_uniform_desc* u_desc = &(ub->u[ub->num_uniforms++]);
+ u_desc->name = name;
+ u_desc->offset = ub_offset;
+ u_desc->type = type;
+ u_desc->array_count = array_count;
}
static void _sg_init_vertex_layout_desc(sg_vertex_layout_desc* layout) {
@@ -751,34 +764,22 @@ static void _sg_validate_shader_desc(const sg_shader_desc* desc) {
SOKOL_ASSERT(desc->fs.source);
#endif
#ifdef SOKOL_DEBUG
- bool ub_range_valid = true;
for (int i = 0; i < SG_NUM_SHADER_STAGES; i++) {
const sg_shader_stage_desc* stage_desc = (i == 0)? &desc->vs : &desc->fs;
- for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
+ SOKOL_ASSERT((stage_desc->num_ubs >= 0) && (stage_desc->num_ubs <= SG_MAX_SHADERSTAGE_UBS));
+ for (int ub_index = 0; ub_index < stage_desc->num_ubs; ub_index++) {
const sg_shader_uniform_block_desc* ub_desc = &stage_desc->ub[ub_index];
- if (ub_desc->size > 0) {
- SOKOL_ASSERT(ub_range_valid);
- bool u_range_valid = true;
- for (int u_index = 0; u_index < SG_MAX_UNIFORMS; u_index++) {
- const sg_shader_uniform_desc* u_desc = &ub_desc->u[u_index];
- if (u_desc->type != SG_UNIFORMTYPE_INVALID) {
- SOKOL_ASSERT(u_range_valid);
- #ifdef SOKOL_USE_GLES2
- SOKOL_ASSERT(u_desc->name);
- #endif
- SOKOL_ASSERT(u_desc->count >= 1);
- SOKOL_ASSERT(u_desc->offset >= 0);
- SOKOL_ASSERT((u_desc->offset + _sg_uniform_size(u_desc->type, u_desc->count)) <= ub_desc->size);
- }
- else {
- /* uniforms must use consecutive slots */
- u_range_valid = false;
- }
- }
- }
- else {
- /* uniform blocks must use consecutive slots */
- ub_range_valid = false;
+ SOKOL_ASSERT(ub_desc->size > 0);
+ SOKOL_ASSERT((ub_desc->num_uniforms > 0) && (ub_desc->num_uniforms <= SG_MAX_UNIFORMS));
+ for (int u_index = 0; u_index < ub_desc->num_uniforms; u_index++) {
+ const sg_shader_uniform_desc* u_desc = &ub_desc->u[u_index];
+ SOKOL_ASSERT(u_desc->type != SG_UNIFORMTYPE_INVALID);
+ #ifdef SOKOL_USE_GLES2
+ SOKOL_ASSERT(u_desc->name);
+ #endif
+ SOKOL_ASSERT(u_desc->array_count >= 1);
+ SOKOL_ASSERT(u_desc->offset >= 0);
+ SOKOL_ASSERT((u_desc->offset + _sg_uniform_size(u_desc->type, u_desc->array_count)) <= ub_desc->size);
}
}
}
@@ -808,6 +809,54 @@ static void _sg_validate_draw_state(const sg_draw_state* ds) {
SOKOL_ASSERT(ds->vertex_buffers[0]);
}
+static void _sg_validate_begin_pass(const _sg_pass* pass, const sg_pass_action* pass_action) {
+ SOKOL_ASSERT(pass && pass_action);
+ /* must have at least one color attachment */
+ SOKOL_ASSERT(pass->color_atts[0].image);
+ /* check color attachments */
+ #if defined(SOKOL_DEBUG)
+ const _sg_image* img = pass->color_atts[0].image;
+ bool img_continuous = true;
+ for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
+ const _sg_attachment* att = &pass->color_atts[i];
+ if (att->image) {
+ SOKOL_ASSERT(img_continuous);
+ /* pass valid? */
+ SOKOL_ASSERT(att->image->slot.state == SG_RESOURCESTATE_VALID);
+ /* pass still exists? */
+ SOKOL_ASSERT(att->image->slot.id == att->image_id);
+ /* all images must be render target */
+ SOKOL_ASSERT(att->image->render_target);
+ /* all images must be immutable */
+ SOKOL_ASSERT(att->image->usage == SG_USAGE_IMMUTABLE);
+ /* all images must have same size */
+ SOKOL_ASSERT(att->image->width == img->width);
+ SOKOL_ASSERT(att->image->height == img->height);
+ /* all images must have same pixel format */
+ SOKOL_ASSERT(att->image->color_format == img->color_format);
+ /* must be a valid color render target pixel format */
+ SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(att->image->color_format));
+ /* all images must have same sample count */
+ SOKOL_ASSERT(att->image->sample_count == img->sample_count);
+ }
+ else {
+ img_continuous = false;
+ }
+ }
+ /* check depth-stencil attachment */
+ const _sg_attachment* ds_att = &pass->ds_att;
+ if (ds_att->image) {
+ SOKOL_ASSERT(ds_att->image->slot.state == SG_RESOURCESTATE_VALID);
+ SOKOL_ASSERT(ds_att->image->slot.id == ds_att->image_id);
+ SOKOL_ASSERT(ds_att->image->render_target);
+ SOKOL_ASSERT(ds_att->image->usage == SG_USAGE_IMMUTABLE);
+ SOKOL_ASSERT(ds_att->image->width == img->width);
+ SOKOL_ASSERT(ds_att->image->height == img->height);
+ SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_att->image->depth_format));
+ }
+ #endif /* SOKOL_DEBUG */
+}
+
static bool _sg_validate_draw(_sg_pipeline* pip,
_sg_buffer** vbs, int num_vbs, const _sg_buffer* ib,
_sg_image** vs_imgs, int num_vs_imgs,
@@ -1045,11 +1094,21 @@ void sg_destroy_pass(sg_id pass_id) {
}
}
-void sg_begin_pass(sg_id pass_id, const sg_pass_action* pass_action, int width, int height) {
+void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height) {
+ SOKOL_ASSERT(_sg && pass_action);
+ SOKOL_ASSERT(pass_action->_init_guard == _SG_INIT_GUARD);
+ _sg_begin_pass(&_sg->backend, 0, pass_action, width, height);
+}
+
+void sg_begin_pass(sg_id pass_id, const sg_pass_action* pass_action) {
SOKOL_ASSERT(_sg && pass_action);
SOKOL_ASSERT(pass_action->_init_guard == _SG_INIT_GUARD);
- _sg_pass* pass = _sg_lookup_pass(&_sg->pools, pass_id); // can be 0
- _sg_begin_pass(&_sg->backend, pass, pass_action, width, height);
+ _sg_pass* pass = _sg_lookup_pass(&_sg->pools, pass_id);
+ SOKOL_ASSERT(pass && pass->slot.state == SG_RESOURCESTATE_VALID);
+ _sg_validate_begin_pass(pass, pass_action);
+ const int w = pass->color_atts[0].image->width;
+ const int h = pass->color_atts[0].image->height;
+ _sg_begin_pass(&_sg->backend, pass, pass_action, w, h);
}
void sg_apply_draw_state(const sg_draw_state* ds) {
diff --git a/_sokol_gfx_gl.impl.h b/_sokol_gfx_gl.impl.h
index 93770291..5d2a00e0 100644
--- a/_sokol_gfx_gl.impl.h
+++ b/_sokol_gfx_gl.impl.h
@@ -656,6 +656,8 @@ typedef struct {
uint32_t frame_index;
GLenum cur_primitive_type;
GLenum cur_index_type;
+ int cur_pass_width;
+ int cur_pass_height;
_sg_pipeline* cur_pipeline;
sg_id cur_pipeline_id;
_sg_state_cache cache;
@@ -676,6 +678,8 @@ static void _sg_setup_backend(_sg_backend* state) {
state->frame_index = 1;
state->cur_primitive_type = GL_TRIANGLES;
state->cur_index_type = 0;
+ state->cur_pass_width = 0;
+ state->cur_pass_height = 0;
state->cur_pipeline = 0;
state->cur_pipeline_id = SG_INVALID_ID;
state->valid = true;
@@ -1046,23 +1050,19 @@ static void _sg_create_shader(_sg_backend* state, _sg_shader* shd, const sg_shad
const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &desc->vs : &desc->fs;
_sg_shader_stage* stage = &shd->stage[stage_index];
SOKOL_ASSERT(stage->num_uniform_blocks == 0);
- for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
+ stage->num_uniform_blocks = stage_desc->num_ubs;
+ for (int ub_index = 0; ub_index < stage_desc->num_ubs; ub_index++) {
const sg_shader_uniform_block_desc* ub_desc = &stage_desc->ub[ub_index];
- if (ub_desc->size == 0) {
- break;
- }
- _sg_uniform_block* ub = &stage->uniform_blocks[stage->num_uniform_blocks++];
+ _sg_uniform_block* ub = &stage->uniform_blocks[ub_index];
ub->size = ub_desc->size;
SOKOL_ASSERT(ub->num_uniforms == 0);
- for (int u_index = 0; u_index < SG_MAX_UNIFORMS; u_index++) {
+ ub->num_uniforms = ub_desc->num_uniforms;
+ for (int u_index = 0; u_index < ub_desc->num_uniforms; u_index++) {
const sg_shader_uniform_desc* u_desc = &ub_desc->u[u_index];
- if (u_desc->type == SG_UNIFORMTYPE_INVALID) {
- break;
- }
- _sg_uniform* u = &ub->uniforms[ub->num_uniforms++];
+ _sg_uniform* u = &ub->uniforms[u_index];
u->type = u_desc->type;
u->offset = u_desc->offset;
- u->count = u_desc->count;
+ u->count = u_desc->array_count;
if (u_desc->name) {
u->gl_loc = glGetUniformLocation(gl_prog, u_desc->name);
}
@@ -1287,9 +1287,32 @@ static void _sg_begin_pass(_sg_backend* state, _sg_pass* pass, const sg_pass_act
SOKOL_ASSERT(state);
SOKOL_ASSERT(action);
SOKOL_ASSERT(!state->in_pass);
+ _SG_GL_CHECK_ERROR();
state->in_pass = true;
+ state->cur_pass_width = w;
+ state->cur_pass_height = h;
if (pass) {
-
+ /* offscreen pass */
+ SOKOL_ASSERT(pass->gl_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, pass->gl_fb);
+ #if !defined(SOKOL_USE_GLES2)
+ GLenum att[SG_MAX_COLOR_ATTACHMENTS] = {
+ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3
+ };
+ int num_attrs = 0;
+ for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
+ if (pass->color_atts[num_attrs].image) {
+ num_attrs++;
+ }
+ else {
+ break;
+ }
+ }
+ glDrawBuffers(num_attrs, att);
+ #endif
}
else {
/* default pass */
@@ -1313,26 +1336,50 @@ static void _sg_begin_pass(_sg_backend* state, _sg_pass* pass, const sg_pass_act
state->cache.ds.stencil_write_mask = 0xFF;
glStencilMask(0xFF);
}
- /* FIXME: multiple-render-target! */
- GLbitfield clear_mask = 0;
- if (action->actions & SG_PASSACTION_CLEAR_COLOR0) {
- clear_mask |= GL_COLOR_BUFFER_BIT;
- const float* c = action->color[0];
- glClearColor(c[0], c[1], c[2], c[3]);
- }
- if (action->actions & SG_PASSACTION_CLEAR_DEPTH_STENCIL) {
- /* FIXME: hmm separate depth/stencil clear? */
- clear_mask |= GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT;
- #ifdef SOKOL_USE_GLCORE33
- glClearDepth(action->depth);
- #else
- glClearDepthf(action->depth);
- #endif
- glClearStencil(action->stencil);
+ bool use_mrt_clear = (0 != pass);
+ #if defined(SOKOL_USE_GLES2)
+ use_mrt_clear = false;
+ #endif
+ if (!use_mrt_clear) {
+ GLbitfield clear_mask = 0;
+ if (action->actions & SG_PASSACTION_CLEAR_COLOR0) {
+ clear_mask |= GL_COLOR_BUFFER_BIT;
+ const float* c = action->color[0];
+ glClearColor(c[0], c[1], c[2], c[3]);
+ }
+ if (action->actions & SG_PASSACTION_CLEAR_DEPTH_STENCIL) {
+ /* FIXME: hmm separate depth/stencil clear? */
+ clear_mask |= GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT;
+ #ifdef SOKOL_USE_GLCORE33
+ glClearDepth(action->depth);
+ #else
+ glClearDepthf(action->depth);
+ #endif
+ glClearStencil(action->stencil);
+ }
+ if (0 != clear_mask) {
+ glClear(clear_mask);
+ }
}
- if (0 != clear_mask) {
- glClear(clear_mask);
+ #if !defined SOKOL_USE_GLES2
+ else {
+ SOKOL_ASSERT(pass);
+ for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
+ if (pass->color_atts[i].image) {
+ if (action->actions & (SG_PASSACTION_CLEAR_COLOR0<<i)) {
+ glClearBufferfv(GL_COLOR, i, action->color[i]);
+ }
+ }
+ else {
+ break;
+ }
+ }
+ if (pass->ds_att.image && (action->actions & SG_PASSACTION_CLEAR_DEPTH_STENCIL)) {
+ glClearBufferfi(GL_DEPTH_STENCIL, 0, action->depth, action->stencil);
+ }
}
+ #endif
+ _SG_GL_CHECK_ERROR();
}
static void _sg_end_pass(_sg_backend* state) {
diff --git a/sokol_gfx.h b/sokol_gfx.h
index 1c41f7da..a6d588fb 100644
--- a/sokol_gfx.h
+++ b/sokol_gfx.h
@@ -416,11 +416,12 @@ typedef struct {
const char* name;
int offset;
sg_uniform_type type; /* SG_UNIFORMTYPE_INVALID if not used */
- int count;
+ int array_count;
} sg_shader_uniform_desc;
typedef struct {
int size;
+ int num_uniforms;
sg_shader_uniform_desc u[SG_MAX_UNIFORMS];
} sg_shader_uniform_block_desc;
@@ -433,9 +434,11 @@ typedef struct {
/* source code (only used in GL backends) */
const char* source;
/* uniform block descriptions */
+ int num_ubs;
sg_shader_uniform_block_desc ub[SG_MAX_SHADERSTAGE_UBS];
/* image descriptions */
- sg_shader_image_desc images[SG_MAX_SHADERSTAGE_IMAGES];
+ int num_images;
+ sg_shader_image_desc image[SG_MAX_SHADERSTAGE_IMAGES];
} sg_shader_stage_desc;
typedef struct {
@@ -501,8 +504,9 @@ extern void sg_init_desc(sg_desc* desc);
extern void sg_init_buffer_desc(sg_buffer_desc* desc);
extern void sg_init_image_desc(sg_image_desc* desc);
extern void sg_init_shader_desc(sg_shader_desc* desc);
-extern void sg_init_uniform_block(sg_shader_uniform_block_desc* desc, int ub_size);
-extern void sg_init_named_uniform(sg_shader_uniform_desc* desc, const char* name, int ub_offset, sg_uniform_type type, int array_count);
+extern void sg_init_uniform_block(sg_shader_desc* desc, sg_shader_stage stage, int ub_size);
+extern void sg_init_named_uniform(sg_shader_desc* desc, sg_shader_stage stage, const char* name, int ub_offset, sg_uniform_type type, int array_count);
+extern void sg_init_named_image(sg_shader_desc* desc, sg_shader_stage stage, const char* name, sg_image_type type);
extern void sg_init_pipeline_desc(sg_pipeline_desc* desc);
extern void sg_init_named_vertex_attr(sg_pipeline_desc* desc, int input_layout, const char* name, sg_vertex_format format);
extern void sg_init_indexed_vertex_attr(sg_pipeline_desc* desc, int input_layout, int attr_index, sg_vertex_format format);
@@ -532,7 +536,8 @@ extern void sg_update_buffer(sg_id buf, const void* data_ptr, int data_size);
extern void sg_update_image(sg_id img, int num_data_items, const void** data_ptrs, int* data_sizes);
/* rendering */
-extern void sg_begin_pass(sg_id pass, const sg_pass_action* pass_action, int width, int height);
+extern void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height);
+extern void sg_begin_pass(sg_id pass, const sg_pass_action* pass_action);
extern void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);
extern void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left);
extern void sg_apply_draw_state(const sg_draw_state* ds);