From 4bd5a37b5d51be1d9ed088c6461d0f2ab369c3e9 Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 7 May 2020 14:07:07 +0200 Subject: [PATCH] Demo update and start counting tests times -Fixed performance issue with multithreading and rendering -start making better shaders (by using many macros) -speed up rendeing when maximum objects count was reached -remove map rendering form Snake demo, and render entities by themself -start adding depth and color rendering parameters -added properly names to jobs (for debugging purpses) -starts adding multithreaded rendering -added some math to vectors -changes execute() to willExecute(). Probably should have different name. --- demos/assets/shaders/base.fp | 45 ++- demos/assets/shaders/base.vp | 57 +++- demos/external/sources/mmutils/thread_pool.d | 26 +- demos/source/app.d | 2 +- demos/source/demos/simple.d | 1 + demos/source/demos/snake.d | 319 ++++++++++--------- demos/source/demos/space_invaders.d | 11 +- demos/source/game_core/job_updater.d | 7 +- demos/utils/source/ecs_utils/gfx/renderer.d | 66 +++- demos/utils/source/ecs_utils/math/vector.d | 9 + source/bubel/ecs/manager.d | 4 +- tests/runner.d | 14 + tests/time.d | 66 ++++ 13 files changed, 429 insertions(+), 198 deletions(-) create mode 100644 tests/time.d diff --git a/demos/assets/shaders/base.fp b/demos/assets/shaders/base.fp index 043fa58..ca38c30 100644 --- a/demos/assets/shaders/base.fp +++ b/demos/assets/shaders/base.fp @@ -3,6 +3,31 @@ precision mediump float; precision lowp sampler2D; precision lowp samplerCube; + +#ifdef GLES + #define TEX(x,y) texture2D(x,y) + #if __VERSION__ >290 + #define M_IN in mediump + #define L_IN in lowp + #else + #define M_IN varying mediump + #define L_IN varying lowp + #endif +#else + #define TEX(x,y) texture(x,y) + #if __VERSION__ > 320 + #define M_IN in + #define L_IN in + #else + #define M_IN varying + #define L_IN varying + #endif +#endif + + +M_IN vec2 uv; +M_IN vec4 color; +/* #ifdef GLES #if __VERSION__ >290 in mediump vec2 uv; @@ -15,7 +40,7 @@ precision lowp samplerCube; #else varying vec2 uv; #endif -#endif +#endif*/ //layout(binding = 0)uniform sampler2D tex; @@ -23,20 +48,8 @@ uniform sampler2D tex; //layout(location = 0) out vec4 outColor; -void main() { - - #ifdef GLES - #if __VERSION__ >290 - gl_FragColor = texture(tex,uv); - #else - gl_FragColor = texture2D(tex,uv); - #endif - #else - #if __VERSION__ > 320 - gl_FragColor = texture(tex,uv); - #else - gl_FragColor = texture2D(tex,uv); - #endif - #endif +void main() +{ + gl_FragColor = TEX(tex,uv);// * color; if(gl_FragColor.a < 0.01)discard; } diff --git a/demos/assets/shaders/base.vp b/demos/assets/shaders/base.vp index 42ed4a7..d2d1af8 100644 --- a/demos/assets/shaders/base.vp +++ b/demos/assets/shaders/base.vp @@ -2,12 +2,37 @@ precision highp float; precision highp int; precision lowp sampler2D; precision lowp samplerCube; - #ifdef GLES #if __VERSION__ >290 - layout(location = 0) uniform vec4 matrix_1; - layout(location = 1) uniform vec4 matrix_2; - layout(location = 2) uniform vec4 uv_transform; + #define LOC(x) layout(location = x) + #define ATT in + #define M_OUT out mediump + #define L_OUT out lowp + #else + #define LOC(x) + #define ATT attribute + #define M_OUT varying mediump + #define L_OUT varying lowp + #endif +#else + #if __VERSION__ > 320 + #define LOC(x) layout(location = x) + #define ATT in + #define M_OUT out + #define L_OUT out + #else + #define LOC(x) + #define ATT attribute + #define M_OUT varying + #define L_OUT varying + #endif +#endif +/* +#ifdef GLES + #if __VERSION__ >290 + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; layout(location = 0) in vec2 positions; layout(location = 1) in vec2 tex_coords; @@ -43,13 +68,35 @@ precision lowp samplerCube; varying vec2 uv; #endif +#endif*/ + + + +M_OUT vec2 uv; +L_OUT vec4 color; + +LOC(0) ATT vec2 positions; +LOC(1) ATT vec2 tex_coords; + +#ifdef VBO_BATCH + LOC(2) ATT float depth; + LOC(3) ATT vec4 vcolor; +#else + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; + uniform vec4 vcolor; + + float depth = matrix_2.z; #endif void main() { vec3 position = mat3(matrix_1.x,matrix_1.y,0,matrix_1.z,matrix_1.w,0,matrix_2.xy,1) * vec3(positions,1.0); + position.z = depth; uv = tex_coords * uv_transform.zw + uv_transform.xy; - + color = vcolor; + gl_Position = vec4(position.xy,0,1.0); } diff --git a/demos/external/sources/mmutils/thread_pool.d b/demos/external/sources/mmutils/thread_pool.d index 161eb22..20491ef 100644 --- a/demos/external/sources/mmutils/thread_pool.d +++ b/demos/external/sources/mmutils/thread_pool.d @@ -9,7 +9,7 @@ import bubel.ecs.atomic; //import std.stdio; import std.algorithm : map; -version = MM_NO_LOGS; // Disable log creation +//version = MM_NO_LOGS; // Disable log creation //version = MM_USE_POSIX_THREADS; // Use posix threads insted of standard library, required for betterC version (Posix)version = MM_USE_POSIX_THREADS; @@ -1141,17 +1141,19 @@ public: foreach (ref log; logs) { - size += log.name.length; // size of name + size += log.name.length + 1; // size of name } char* buffer = cast(char*) malloc(size); foreach (ref log; logs) { - + char[100] name_buffer; + name_buffer[0 .. log.name.length] = log.name; + name_buffer[log.name.length] = 0; size_t charWritten = snprintf(buffer + used, size - used, `{"name":"%s", "pid":1, "tid":%lld, "ph":"X", "ts":%lld, "dur":%lld }, %s`, - log.name.ptr, threadData.threadId + 1, log.time, log.duration, "\n".ptr); + name_buffer.ptr, threadData.threadId + 1, log.time, log.duration, "\n".ptr); used += charWritten; } @@ -1447,7 +1449,21 @@ private void threadFunc(ThreadData* threadData) if (data is null) { // Thread does not have own job and can not steal it, so wait for a job - bool ok = threadData.semaphore.timedWait(1_000 + !acceptJobs * 10_000); + int tryWait = 0; + //bool ok = threadData.semaphore.timedWait(1_000 + !acceptJobs * 10_000); + bool ok = true; + while(!threadData.semaphore.tryWait()) + { + tryWait++; + if(tryWait>5000) + { + ok = false; + break; + } + static foreach(i;0..10)instructionPause(); + } + if(!ok)ok = threadData.semaphore.timedWait(1_000 + !acceptJobs * 10_000); + if (ok) { diff --git a/demos/source/app.d b/demos/source/app.d index acdc385..27c706d 100644 --- a/demos/source/app.d +++ b/demos/source/app.d @@ -253,7 +253,7 @@ void mainLoop(void* arg) if(launcher.tool && launcher.tool_repeat != 0 && launcher.mouse.left && !igIsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !igIsWindowFocused(ImGuiFocusedFlags_AnyWindow)) { float range = 500.0 / cast(float)launcher.tool_repeat; - launcher.repeat_time += launcher.delta_time; + launcher.repeat_time += launcher.delta_time*100; while(launcher.repeat_time > range) { launcher.repeat_time -= range; diff --git a/demos/source/demos/simple.d b/demos/source/demos/simple.d index 89fe801..8d6b0f2 100644 --- a/demos/source/demos/simple.d +++ b/demos/source/demos/simple.d @@ -58,6 +58,7 @@ struct DrawSystem void onUpdate(EntitiesData data) { + if(launcher.renderer.item_id >= launcher.renderer.MaxObjects)return;//simple leave loop if max visible objects count was reached foreach(i; 0..data.length) { launcher.renderer.draw(data.textures[i].tex, data.locations[i].location, vec2(16,16), vec4(0,0,1,1), 0, 0 , 0); diff --git a/demos/source/demos/snake.d b/demos/source/demos/snake.d index c4123ba..2606fd9 100644 --- a/demos/source/demos/snake.d +++ b/demos/source/demos/snake.d @@ -30,8 +30,9 @@ struct MapElement empty = 0, apple = 1, wall = 2, + snake = 3, - snake_head_up = 5, + /* snake_head_up = 5, snake_head_down = 6, snake_head_left = 7, snake_head_right = 8, @@ -44,13 +45,31 @@ struct MapElement snake_turn_rd = 15, snake_turn_ru = 16, snake_vertical = 17, - snake_horizontal = 18 + snake_horizontal = 18*/ } Type type; EntityID id; } +enum SnakePart : ubyte +{ + head_up = 0, + head_down = 1, + head_left = 2, + head_right = 3, + tail_up = 4, + tail_down = 5, + tail_left = 6, + tail_right = 7, + turn_ld = 8, + turn_lu = 9, + turn_rd = 10, + turn_ru = 11, + vertical = 12, + horizontal = 13 +} + struct Snake { __gshared const (char)* tips = "Use \"WASD\" keys to move."; @@ -104,39 +123,6 @@ struct Snake *location = random_pos; Entity* apple = launcher.manager.addEntity(apple_tmpl); } - - void drawMap() - { - foreach(x; 0 .. map_size) - { - foreach(y; 0 .. map_size) - { - switch(element(ivec2(x,y)).type) - { - case MapElement.Type.apple:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(0,32*px,16*px,16*px), 0, 0 , 0);break; - - case MapElement.Type.snake_head_up:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(48*px,112*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_head_down:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(48*px,144*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_head_left:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(0,128*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_head_right:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(32*px,128*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_tail_up:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(16*px,112*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_tail_down:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(0,112*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_tail_left:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(32*px,112*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_tail_right:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(0,144*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_turn_ld:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(64*px,128*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_turn_lu:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(32*px,144*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_turn_rd:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(16*px,144*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_turn_ru:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(64*px,112*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_vertical:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(16*px,128*px,16*px,16*px), 0, 0 , 0);break; - case MapElement.Type.snake_horizontal:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(48*px,128*px,16*px,16*px), 0, 0 , 0);break; - - case MapElement.Type.wall:launcher.renderer.draw(texture, vec2(x*16,y*16), vec2(16,16), vec4(0,0,1,1), 0, 0 , 0);break; - default:break; - } - } - } - } - } struct Animation @@ -184,6 +170,7 @@ struct CSnake mixin ECS.Component; + struct Parts { uint length = 0; @@ -217,6 +204,7 @@ struct CSnake } Parts parts; + CMovement.Direction direction; } struct CApple @@ -424,81 +412,19 @@ struct MoveSystem else .snake.element(MapElement(),location); } - static CMovement.Direction getDirection(ivec2 p1, ivec2 p2) - { - if(p1.x - p2.x == -1)return CMovement.direction.right; - else if(p1.x - p2.x == 1)return CMovement.direction.left; - else if(p1.y - p2.y == -1)return CMovement.direction.up; - else if(p1.y - p2.y == 1)return CMovement.direction.down; - else if(p1.x - p2.x > 1)return CMovement.direction.right; - else if(p1.x - p2.x < -1)return CMovement.direction.left; - else if(p1.y - p2.y > 1)return CMovement.direction.up; - else return CMovement.direction.down; - } - - static MapElement.Type snakePart(ivec2 p1, ivec2 p2, ivec2 p3) - { - CMovement.Direction direction = getDirection(p1, p2); - CMovement.Direction direction2 = getDirection(p1, p3); - uint case_ = direction*4 + direction2; - final switch(case_) - { - case 0:return MapElement.Type.snake_horizontal; - case 1:return MapElement.Type.snake_horizontal; - case 2:return MapElement.Type.snake_turn_lu; - case 3:return MapElement.Type.snake_turn_ru; - case 4:return MapElement.Type.snake_horizontal; - case 5:return MapElement.Type.snake_horizontal; - case 6:return MapElement.Type.snake_turn_ld; - case 7:return MapElement.Type.snake_turn_rd; - case 8:return MapElement.Type.snake_turn_lu; - case 9:return MapElement.Type.snake_turn_ld; - case 10:return MapElement.Type.snake_vertical; - case 11:return MapElement.Type.snake_vertical; - case 12:return MapElement.Type.snake_turn_ru; - case 13:return MapElement.Type.snake_turn_rd; - case 14:return MapElement.Type.snake_vertical; - case 15:return MapElement.Type.snake_vertical; - } - } - - static MapElement.Type snakeTail(ivec2 p1, ivec2 p2) - { - CMovement.Direction direction = getDirection(p1, p2); - final switch(direction) - { - case CMovement.Direction.up:return MapElement.Type.snake_tail_up; - case CMovement.Direction.down:return MapElement.Type.snake_tail_down; - case CMovement.Direction.left:return MapElement.Type.snake_tail_left; - case CMovement.Direction.right:return MapElement.Type.snake_tail_right; - } - } - void onUpdate(EntitiesData data) { if(data.snakes) { foreach(i; 0..data.length) { + data.snakes[i].direction = data.movement[i].direction; ivec2 new_location = data.location[i]; moveLocation(data.location[i], data.movement[i].direction); final switch(snake.element(data.location[i].location).type) { - case MapElement.Type.snake_head_up:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_head_down:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_head_left:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_head_right:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_tail_up:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_tail_down:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_tail_left:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_tail_right:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_turn_ld:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_turn_lu:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_turn_rd:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_turn_ru:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_vertical:goto case(MapElement.Type.snake_horizontal); - case MapElement.Type.snake_horizontal: - foreach(ivec2 loc; data.snakes[i].parts) + case MapElement.Type.snake: + foreach(loc; data.snakes[i].parts) { destroy_location.x = loc.x * 16; destroy_location.y = loc.y * 16; @@ -520,37 +446,20 @@ struct MoveSystem launcher.manager.addEntity(snake.snake_destroy_particle); launcher.manager.removeEntity(data.entities[i].id); break; + case MapElement.Type.wall:break; - //launcher.manager.removeEntity(data.entities[i].id); - //break; + case MapElement.Type.empty: moveSnake(data.snakes[i], new_location); - final switch(data.movement[i].direction) - { - case CMovement.Direction.up: - snake.element(MapElement(MapElement.Type.snake_head_up, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.right: - snake.element(MapElement(MapElement.Type.snake_head_right, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.down: - snake.element(MapElement(MapElement.Type.snake_head_down, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.left: - snake.element(MapElement(MapElement.Type.snake_head_left, data.entities[i].id),data.location[i].location); - break; - } + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.location[i].location); if(data.snakes[i].parts.length > 1) { - MapElement.Type elem_type = snakePart(data.snakes[i].parts[$-1],data.location[i],data.snakes[i].parts[$-2]); - snake.element(MapElement(elem_type, data.entities[i].id),data.snakes[i].parts[$-1]); - elem_type = snakeTail(data.snakes[i].parts[1], data.snakes[i].parts[0]); - snake.element(MapElement(elem_type, data.entities[i].id),data.snakes[i].parts[0]); + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.snakes[i].parts[$-1]); + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.snakes[i].parts[0]); } else if(data.snakes[i].parts.length == 1) { - MapElement.Type elem_type = snakeTail(data.location[i], data.snakes[i].parts[0]); - snake.element(MapElement(elem_type, data.entities[i].id),data.snakes[i].parts[0]); + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.snakes[i].parts[0]); } break; case MapElement.Type.apple: @@ -559,29 +468,13 @@ struct MoveSystem if(data.snakes[i].parts.length > 1) { - MapElement.Type elem_type = snakePart(data.snakes[i].parts[$-1],data.location[i],data.snakes[i].parts[$-2]); - snake.element(MapElement(elem_type, data.entities[i].id),data.snakes[i].parts[$-1]); + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.snakes[i].parts[$-1]); } else if(data.snakes[i].parts.length == 1) { - MapElement.Type elem_type = snakeTail(data.location[i], new_location); - snake.element(MapElement(elem_type, data.entities[i].id),new_location); - } - final switch(data.movement[i].direction) - { - case CMovement.Direction.up: - snake.element(MapElement(MapElement.Type.snake_head_up, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.right: - snake.element(MapElement(MapElement.Type.snake_head_right, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.down: - snake.element(MapElement(MapElement.Type.snake_head_down, data.entities[i].id),data.location[i].location); - break; - case CMovement.Direction.left: - snake.element(MapElement(MapElement.Type.snake_head_left, data.entities[i].id),data.location[i].location); - break; + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),new_location); } + snake.element(MapElement(MapElement.Type.snake, data.entities[i].id),data.location[i].location); snake.addApple(); break; } @@ -593,10 +486,10 @@ struct MoveSystem { final switch(data.movement[i].direction) { - case CMovement.Direction.down:data.location[i].location.y -= 1;break; - case CMovement.Direction.up:data.location[i].location.y += 1;break; - case CMovement.Direction.left:data.location[i].location.x -= 1;break; - case CMovement.Direction.right:data.location[i].location.x += 1;break; + case CMovement.Direction.down:data.location[i].y -= 1;break; + case CMovement.Direction.up:data.location[i].y += 1;break; + case CMovement.Direction.left:data.location[i].x -= 1;break; + case CMovement.Direction.right:data.location[i].x += 1;break; } } } @@ -699,6 +592,132 @@ struct FixSnakeDirectionSystem } } +struct DrawAppleSystem +{ + mixin ECS.System!1; + + struct EntitiesData + { + uint length; + @readonly CILocation[] location; + const (CApple)[] apple; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.location.length) + { + launcher.renderer.draw(snake.texture, vec2(data.location[i].x*16,data.location[i].y*16), vec2(16,16), vec4(0,32*px,16*px,16*px), 0, 0 , 0); + } + } +} + +struct DrawSnakeSystem +{ + mixin ECS.System!1; + + struct EntitiesData + { + uint length; + @readonly CILocation[] location; + const (CSnake)[] snake; + } + + static CMovement.Direction getDirection(ivec2 p1, ivec2 p2) + { + if(p1.x - p2.x == -1)return CMovement.direction.right; + else if(p1.x - p2.x == 1)return CMovement.direction.left; + else if(p1.y - p2.y == -1)return CMovement.direction.up; + else if(p1.y - p2.y == 1)return CMovement.direction.down; + else if(p1.x - p2.x > 1)return CMovement.direction.right; + else if(p1.x - p2.x < -1)return CMovement.direction.left; + else if(p1.y - p2.y > 1)return CMovement.direction.up; + else return CMovement.direction.down; + } + + static SnakePart snakePart(ivec2 p1, ivec2 p2, ivec2 p3) + { + CMovement.Direction direction = getDirection(p1, p2); + CMovement.Direction direction2 = getDirection(p1, p3); + uint case_ = direction*4 + direction2; + final switch(case_) + { + case 0:return SnakePart.horizontal; + case 1:return SnakePart.horizontal; + case 2:return SnakePart.turn_lu; + case 3:return SnakePart.turn_ru; + case 4:return SnakePart.horizontal; + case 5:return SnakePart.horizontal; + case 6:return SnakePart.turn_ld; + case 7:return SnakePart.turn_rd; + case 8:return SnakePart.turn_lu; + case 9:return SnakePart.turn_ld; + case 10:return SnakePart.vertical; + case 11:return SnakePart.vertical; + case 12:return SnakePart.turn_ru; + case 13:return SnakePart.turn_rd; + case 14:return SnakePart.vertical; + case 15:return SnakePart.vertical; + } + } + + static SnakePart snakeTail(ivec2 p1, ivec2 p2) + { + CMovement.Direction direction = getDirection(p1, p2); + final switch(direction) + { + case CMovement.Direction.up:return SnakePart.tail_up; + case CMovement.Direction.down:return SnakePart.tail_down; + case CMovement.Direction.left:return SnakePart.tail_left; + case CMovement.Direction.right:return SnakePart.tail_right; + } + } + + static void drawElement(ivec2 loc, SnakePart part) + { + final switch(cast(ubyte)part) + { + case SnakePart.tail_up:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(16,112,16,16)*px, 0, 0, 0);break; + case SnakePart.tail_down:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(0,112,16,16)*px, 0, 0, 0);break; + case SnakePart.tail_left:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(32,112,16,16)*px, 0, 0, 0);break; + case SnakePart.tail_right:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(0,144,16,16)*px, 0, 0, 0);break; + case SnakePart.turn_ld:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(64,128,16,16)*px, 0, 0, 0);break; + case SnakePart.turn_lu:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(32,144,16,16)*px, 0, 0, 0);break; + case SnakePart.turn_rd:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(16,144,16,16)*px, 0, 0, 0);break; + case SnakePart.turn_ru:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(64,112,16,16)*px, 0, 0, 0);break; + case SnakePart.vertical:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(16,128,16,16)*px, 0, 0, 0);break; + case SnakePart.horizontal:launcher.renderer.draw(.snake.texture, cast(vec2)loc, vec2(16,16), vec4(48,128,16,16)*px, 0, 0, 0);break; + } + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + const (CSnake)* snake = &data.snake[i]; + scope vec2 loc = cast(vec2)(data.location[i].location * 16); + final switch(snake.direction) + { + case CMovement.Direction.up:launcher.renderer.draw(.snake.texture, vec2(data.location[i].x*16,data.location[i].y*16), vec2(16,16), vec4(48,112,16,16)*px, 0, 0 , 0);break; + case CMovement.Direction.down:launcher.renderer.draw(.snake.texture, vec2(data.location[i].x*16,data.location[i].y*16), vec2(16,16), vec4(48,144,16,16)*px, 0, 0 , 0);break; + case CMovement.Direction.left:launcher.renderer.draw(.snake.texture, vec2(data.location[i].x*16,data.location[i].y*16), vec2(16,16), vec4(0,128,16,16)*px, 0, 0 , 0);break; + case CMovement.Direction.right:launcher.renderer.draw(.snake.texture, vec2(data.location[i].x*16,data.location[i].y*16), vec2(16,16), vec4(32,128,16,16)*px, 0, 0 , 0);break; + } + if(snake.parts.length >1) + { + foreach(j;1..snake.parts.length - 1)drawElement(snake.parts[j]*16, snakePart(snake.parts[j], snake.parts[j+1], snake.parts[j-1])); + drawElement(snake.parts[$-1]*16, snakePart(snake.parts[$-1], data.location[i], snake.parts[$-2])); + drawElement(snake.parts[0]*16, snakeTail(snake.parts[1], snake.parts[0])); + } + else if(snake.parts.length == 1) + { + drawElement(snake.parts[0]*16, snakeTail(data.location[i], snake.parts[0])); + } + + } + } +} + struct CleanSystem { mixin ECS.System!64; @@ -749,6 +768,8 @@ void snakeStart() launcher.manager.registerSystem!AnimationSystem(-1); launcher.manager.registerSystem!ParticleSystem(-1); launcher.manager.registerSystem!ParticleMovementSystem(-1); + launcher.manager.registerSystem!DrawAppleSystem(99); + launcher.manager.registerSystem!DrawSnakeSystem(101); launcher.manager.endRegister(); @@ -766,7 +787,7 @@ void snakeStart() ushort[4] components = [CILocation.component_id, CSnake.component_id, CMovement.component_id, CInput.component_id]; snake.snake_tmpl = launcher.manager.allocateTemplate(components); CILocation* loc_comp = snake.snake_tmpl.getComponent!CILocation; - loc_comp.location = ivec2(2,2); + *loc_comp = ivec2(2,2); launcher.manager.addEntity(snake.snake_tmpl); } @@ -794,7 +815,7 @@ void snakeStart() /*foreach(i; 0..10) foreach(j; 0..10) { - loc_comp.location = vec2(i*32+64,j*32+64); + loc_compation = vec2(i*32+64,j*32+64); launcher.manager.addEntity(simple.tmpl); }*/ } @@ -878,7 +899,7 @@ bool snakeLoop() launcher.manager.end(); - snake.drawMap(); + //snake.drawMap(); return true; } \ No newline at end of file diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index 92c4e15..6d86113 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -179,6 +179,13 @@ struct CSideMove byte group = -1; } +struct CDepth +{ + mixin ECS.Component; + + short depth; +} + /*####################################################################################################################### ------------------------------------------------ Events ------------------------------------------------------------------ #######################################################################################################################*/ @@ -620,7 +627,7 @@ struct InputMovementSystem return true; } //don't call system update because no key pressed - return true; + return false; } /** @@ -637,7 +644,7 @@ struct InputMovementSystem { data.textures[i].coords = vec4(0*px,80*px,48*px,32*px); } - return; + //return; } //move every entity using movement vector foreach(i; 0..data.length) diff --git a/demos/source/game_core/job_updater.d b/demos/source/game_core/job_updater.d index 6c20a83..47d2423 100644 --- a/demos/source/game_core/job_updater.d +++ b/demos/source/game_core/job_updater.d @@ -63,6 +63,7 @@ struct ECSJobUpdater JobData[1024] jobs; JobCaller[1024] callers; uint count = 0; + string name; void dependantOn(Group* dependency) { @@ -89,7 +90,7 @@ struct ECSJobUpdater void add(JobCaller caller) { callers[count] = caller; - jobs[count] = JobData(&callers[count].callJob,"hmm"); + jobs[count] = JobData(&callers[count].callJob,name); count++; } } @@ -216,6 +217,8 @@ struct ECSJobUpdater return; } + jobs[group.id].name = cast(string)group.caller.system.name; + foreach(ref job;group.jobs) { uint index = 0; @@ -233,7 +236,7 @@ struct ECSJobUpdater foreach(dep;group.dependencies) { - if(jobs[dep.id].count && dep.caller.system.execute && dep.caller.system.enabled)jobs[group.id].dependantOn(&jobs[dep.id]); + if(jobs[dep.id].count && dep.caller.system.willExecute && dep.caller.system.enabled)jobs[group.id].dependantOn(&jobs[dep.id]); else deps--; } diff --git a/demos/utils/source/ecs_utils/gfx/renderer.d b/demos/utils/source/ecs_utils/gfx/renderer.d index d56b5c8..8735d98 100644 --- a/demos/utils/source/ecs_utils/gfx/renderer.d +++ b/demos/utils/source/ecs_utils/gfx/renderer.d @@ -9,6 +9,9 @@ import ecs_utils.gfx.buffer; import ecs_utils.gfx.texture; import ecs_utils.math.vector; +import bubel.ecs.block_allocator; +import bubel.ecs.vector; + import glad.gl.gl; version = ver1; @@ -41,9 +44,10 @@ enum RenderTechnique struct Renderer { //static SDL_Renderer* main_sdl_renderer; + BlockAllocator allocator; enum MaxObjects = 1024 * 64 * 4; - enum BufferUsage = GL_STATIC_DRAW; + enum BufferUsage = GL_DYNAMIC_DRAW; //SDL_Window* sdl_window; //SDL_Renderer* sdl_renderer; @@ -53,8 +57,35 @@ struct Renderer vec2 view_pos = vec2(-1,-1); vec2 view_size = vec2(1,1); + const uint batch_size = 16_384; //uint[2] time_queries; + struct VertexBlock + { + float[] batch_vertices; + ushort[] batch_indices; + void* memory; + uint itmes = 0; + } + + VertexBlock getBlock() + { + VertexBlock block; + block.memory = allocator.getBlock(); + block.batch_vertices = (cast(float*)block.memory)[0 .. 1]; + return block; + } + + + struct Thread + { + + Vector!VertexBlock block; + RenderData[] render_list; + } + Thread[] threads; + + Buffer[2] ubos; int block_alignment = 1; int block_max_size = 16384; @@ -253,6 +284,8 @@ struct Renderer SDL_Log("Uniform block alignment: %u",block_alignment); SDL_Log("Uniform block max size: %u",block_max_size); SDL_Log("Data offset: %u",data_offset); + + allocator = BlockAllocator(1245184, 32); } } @@ -261,12 +294,13 @@ struct Renderer } - void draw(Texture tex, vec2 pos, vec2 size, vec4 coords, float angle = 0, uint material_id = 0, uint mesh_id = 0) + void draw(Texture tex, vec2 pos, vec2 size, vec4 coords, short depth = 0, uint color = uint.max, float angle = 0, uint material_id = 0, uint mesh_id = 0, uint thread_id = 0) { - __draw(this,tex,pos,size,coords,angle,material_id,mesh_id); + if(item_id >= MaxObjects)return; + __draw(this,tex,pos,size,coords,depth,color,angle,material_id,mesh_id,thread_id); } - private static void __draw_sdl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id) + private static void __draw_sdl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, short depth, uint color, float angle, uint material_id, uint mesh_id, uint thread_id) { /*with(this_) { @@ -286,7 +320,7 @@ struct Renderer }*/ } - private static void __draw_gl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id) + private static void __draw_gl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, short depth, uint color, float angle, uint material_id, uint mesh_id, uint thread_id) { //import core.stdc.string; with(this_) @@ -333,13 +367,13 @@ struct Renderer } } - private static void __draw_gl_vbo_batch(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id) + private static void __draw_gl_vbo_batch(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, short depth, uint color, float angle, uint material_id, uint mesh_id, uint thread_id = 0) { import ecs_utils.gfx.config; //import core.stdc.string; with(this_) { - if(item_id >= MaxObjects)return; + //if(item_id >= MaxObjects)return; //pos += view_pos; size.x *= view_size.x; size.y *= view_size.y; @@ -400,7 +434,7 @@ struct Renderer batch_vertices[item_id*16+14] = GfxConfig.meshes[mesh_id].vertices[14] * coords.z + coords.x; batch_vertices[item_id*16+15] = GfxConfig.meshes[mesh_id].vertices[15] * coords.w + coords.y; - uint ind_id = item_id % 16_384; + uint ind_id = item_id % batch_size; batch_indices[item_id*6] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[0] + ind_id*4); batch_indices[item_id*6+1] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[1] + ind_id*4); @@ -575,7 +609,7 @@ struct Renderer //glBeginQuery(GL_TIME_ELAPSED, time_queries[0]); if(technique == Technique.vbo_batch) { - uint items = item_id/16_384+1; + uint items = item_id/batch_size+1; foreach(i; 0..items) { if(material_id != render_list[i].material_id) @@ -591,16 +625,16 @@ struct Renderer render_list[i].texture.bind(); } - uint instance_count = 16_384; - if((i+1)*16_384 > item_id) + uint instance_count = batch_size; + if((i+1)*batch_size > item_id) { - instance_count = item_id%16_384; + instance_count = item_id%batch_size; } - glVertexAttribPointer(0,2,GL_FLOAT,false,16,cast(void*)(i*16_384*4*16)); - glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)(i*16_384*4*16+8)); + glVertexAttribPointer(0,2,GL_FLOAT,false,16,cast(void*)(i*batch_size*4*16)); + glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)(i*batch_size*4*16+8)); - glDrawElements(GL_TRIANGLES,instance_count*6,GL_UNSIGNED_SHORT,cast(void*)(i*16_384*6*2)); + glDrawElements(GL_TRIANGLES,instance_count*6,GL_UNSIGNED_SHORT,cast(void*)(i*batch_size*6*2)); //glDrawElementsBaseVertex(GL_TRIANGLES,instance_count*6,GL_UNSIGNED_SHORT,cast(void*)(i*16_384*6*2),i*16_384*4); } @@ -803,7 +837,7 @@ struct Renderer view_pos = (pos - size * 0.5) * view_size; } - __gshared void function(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id) __draw; + __gshared void function(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, short depth, uint color, float angle, uint material_id, uint mesh_id, uint thread_id) __draw; __gshared void function(ref Renderer this_) __present; __gshared void function(ref Renderer this_) __clear; __gshared void function(ref Renderer this_) __initialize; diff --git a/demos/utils/source/ecs_utils/math/vector.d b/demos/utils/source/ecs_utils/math/vector.d index 4b9f3af..a74b6db 100644 --- a/demos/utils/source/ecs_utils/math/vector.d +++ b/demos/utils/source/ecs_utils/math/vector.d @@ -97,6 +97,15 @@ struct ivec2 int[2] data; } + ivec2 opBinary(string op, T)(T v) + { + static if (op == "+") return ivec2(x + v, y + v); + else static if (op == "-") return ivec2(x - v, y - v); + else static if (op == "*") return ivec2(x * v, y * v); + else static if (op == "/") return ivec2(x / v, y / v); + else static assert(0, "Operator "~op~" not implemented"); + } + vec2 opCast() { return vec2(x,y); diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d index be4f37a..1b896db 100644 --- a/source/bubel/ecs/manager.d +++ b/source/bubel/ecs/manager.d @@ -1253,7 +1253,7 @@ export struct EntityManager foreach (caller; passes[pass].system_callers) { System* sys = &systems[caller.system_id]; - if (sys.enabled && sys.execute) + if (sys.enabled && sys.willExecute) { if (sys.m_empty) { @@ -1293,7 +1293,7 @@ export struct EntityManager foreach (caller; passes[pass].system_callers) { System* sys = &systems[caller.system_id]; - if (sys.enabled && sys.execute) + if (sys.enabled && sys.willExecute) { uint job_id = 0; void nextJob() diff --git a/tests/runner.d b/tests/runner.d index 7b8f6b5..4aa9bcb 100644 --- a/tests/runner.d +++ b/tests/runner.d @@ -9,6 +9,8 @@ import bubel.ecs.vector; import bubel.ecs.simple_vector; import bubel.ecs.std; +import tests.time; + enum int ASSERTED = 123; enum string OUT_FILE = "test_report.xml"; @@ -95,6 +97,8 @@ struct TestRunner(Args...) write(test.name); write("\" classname=\""); write(suite.name); + write("\" time=\""); + write(cast(double)test.time*0.000001); write("\">"); if (test.msg) { @@ -189,8 +193,10 @@ struct TestRunner(Args...) } else { + long time = Time.getUSecTime(); unittest_(); test.passed = true; + test.time = cast(int)(Time.getUSecTime() - time); } } else @@ -281,6 +287,14 @@ struct TestRunner(Args...) junit.add(cast(ubyte[]) txt); } + void write(double num) + { + ubyte[40] buffer; + int len; + len = sprintf(cast(char*) buffer.ptr, "%2.8lf", num); + junit.add(buffer[0 .. len]); + } + void write(uint num) { ubyte[20] buffer; diff --git a/tests/time.d b/tests/time.d new file mode 100644 index 0000000..e91b76e --- /dev/null +++ b/tests/time.d @@ -0,0 +1,66 @@ +module tests.time; + + +version (WebAssembly) +{ + alias int time_t; + alias int clockid_t; + enum CLOCK_REALTIME = 0; + + struct timespec + { + time_t tv_sec; + int tv_nsec; + } + + extern (C) int clock_gettime(clockid_t, timespec*) @nogc nothrow @system; + + struct Time + { + static long getUSecTime() + { + time_t time; + timespec spec; + + clock_gettime(CLOCK_REALTIME, &spec); + + //time = spec.tv_sec; + return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000; //time / 1000_000; + } + } +} +else version (Windows) +{ + import core.stdc.stdio : printf; + import core.sys.windows.windows; + + struct Time + { + static long getUSecTime() + { + LARGE_INTEGER time, freq; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&time); + return time.QuadPart / (freq.QuadPart / 1000_000); + } + } +} +else version (Posix) +{ + import core.stdc.stdio : printf; + import core.sys.posix.time; + + struct Time + { + static long getUSecTime() + { + time_t time; + timespec spec; + + clock_gettime(CLOCK_REALTIME, &spec); + + //time = spec.tv_sec; + return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000; //time / 1000_000; + } + } +} \ No newline at end of file