diff options
| author | Andre Weissflog <floooh@gmail.com> | 2017-07-26 17:43:38 +0200 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2017-07-26 17:43:38 +0200 |
| commit | 2b67a23a7515a0e063cec2ff3a6ba160a7717d16 (patch) | |
| tree | 201a548c2aa87f2c418eb8c2aca3a4a96ea1e03a | |
| parent | b17ad1f6687648f02d5e1954d9a81c65d22cdcb1 (diff) | |
MRT begin_pass, new begin_default_pass, new shader uniform declaration
| -rw-r--r-- | .gitignore | 6 | ||||
| -rw-r--r-- | _sokol_gfx.impl.h | 133 | ||||
| -rw-r--r-- | _sokol_gfx_gl.impl.h | 107 | ||||
| -rw-r--r-- | sokol_gfx.h | 15 |
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); |