Skip to content
Permalink
Browse files

MOD: Introduced dirty commands for the field_tile rendering, reducing…

… the cost of writing all of them to memory every tick. Instead, only the ones that have changed get sent to the buffer. This will reduce how store bound we were before.

RESULTS: As a result, Field_Tick got marginally slower, but game_gen_instance_buffer doubled in speed to 3ms instead of 6!
  • Loading branch information...
AlexSabourinDev committed Feb 10, 2019
1 parent 2951a48 commit 489adc96202f8c6a826d9aeb900498feec6f0136

Large diffs are not rendered by default.

Oops, something went wrong.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -104,6 +104,23 @@ typedef struct
Vec2 pos;
} Field_Tile;

typedef struct
{
uint32_t writeIndex;
float spriteIndex;
} Field_TileDrawCommand;

float Field_ImageTable[] =
{
[FieldStage_Arable] = 3.0f,
[FieldStage_Fallow] = 4.0f,
[FieldStage_Planted] = 5.0f,
[FieldStage_Grown] = 6.0f
};

static uint32_t Field_TileDrawCommandCount = 0;
static Field_TileDrawCommand* Field_TileDrawCommands = NULL;

const uint32_t Field_Width = 1000;
const uint32_t Field_Height = 1000;
static Field_Tile* Field_Tiles = NULL;
@@ -126,6 +143,13 @@ void field_tick(float delta)
Field_Tile* tile = &Field_Tiles[crop->tileIndex];
tile->stage = FieldStage_Grown;

Field_TileDrawCommands[Field_TileDrawCommandCount] = (Field_TileDrawCommand)
{
.writeIndex = crop->tileIndex,
.spriteIndex = Field_ImageTable[FieldStage_Grown]
};
Field_TileDrawCommandCount++;

SWAP(Field_Crop, *crop, Field_Crops[Field_CropCount - 1]);
Field_CropCount--;
i--;
@@ -279,6 +303,13 @@ void ai_tick(float delta)
Field_Tile* tile = &Field_Tiles[coldFarmer->tileIndex];
tile->stage = math_max((tile->stage + 1) % FieldState_Max, FieldStage_Fallow);

Field_TileDrawCommands[Field_TileDrawCommandCount] = (Field_TileDrawCommand)
{
.writeIndex = coldFarmer->tileIndex,
.spriteIndex = Field_ImageTable[tile->stage]
};
Field_TileDrawCommandCount++;

if (tile->stage == FieldStage_Planted)
{
Field_Crop* crop = &Field_Crops[Field_CropCount++];
@@ -313,15 +344,7 @@ const float FarmerState_Search = 0.0f;
const float FarmerState_Move = 1.0f;
const float FarmerState_Farm = 2.0f;

float Game_FieldImageTable[] =
{
[FieldStage_Arable] = 3.0f,
[FieldStage_Fallow] = 4.0f,
[FieldStage_Planted] = 5.0f,
[FieldStage_Grown] = 6.0f
};

void game_init(void)
void game_init(Game_InstanceBuffer* buffer)
{
MIST_PROFILE_BEGIN("Game", "Game-Init");

@@ -331,15 +354,22 @@ void game_init(void)

Field_Tiles = (Field_Tile*)malloc(sizeof(Field_Tile) * Field_Width * Field_Height);
memset(Field_Tiles, 0, sizeof(Field_Tile) * Field_Width * Field_Height);
Field_TileDrawCommands = (Field_TileDrawCommand*)malloc(sizeof(Field_TileDrawCommand) * Field_Width * Field_Height);

Field_Crops = (Field_Crop*)malloc(sizeof(Field_Crop) * Field_Width * Field_Height);

for (uint32_t y = 0; y < Field_Height; ++y)
{
for (uint32_t x = 0; x < Field_Width; ++x)
{
Field_Tiles[y * Field_Width + x].pos = (Vec2) { .x = (float)x / Field_Width, .y = (float)y / Field_Height };
Field_Tiles[y * Field_Width + x].pos = vec2_sub(vec2_mul(Field_Tiles[y * Field_Width + x].pos, 2.0f), (Vec2) { .x = 1.0f, .y = 1.0f });
uint32_t writeLoc = y * Field_Width + x;
Field_Tiles[writeLoc].pos = (Vec2) { .x = (float)x / Field_Width, .y = (float)y / Field_Height };
Field_Tiles[writeLoc].pos = vec2_sub(vec2_mul(Field_Tiles[writeLoc].pos, 2.0f), (Vec2) { .x = 1.0f, .y = 1.0f });

buffer->instances[writeLoc].spriteIndex = Field_ImageTable[0];
buffer->instances[writeLoc].scale = 2.0f / Field_Width;
buffer->instances[writeLoc].pos[0] = Field_Tiles[writeLoc].pos.x;
buffer->instances[writeLoc].pos[1] = Field_Tiles[writeLoc].pos.y;
}
}

@@ -383,6 +413,9 @@ void game_kill(void)
free(Field_Tiles);
Field_Tiles = NULL;

free(Field_TileDrawCommands);
Field_TileDrawCommands = NULL;

free(AI_FarmersMoveHot);
AI_FarmersMoveHot = NULL;
free(AI_FarmersMoveCold);
@@ -405,16 +438,14 @@ uint32_t game_gen_instance_buffer(Game_InstanceBuffer* buffer)
{
MIST_PROFILE_BEGIN("Game", "Game-GenInstanceBuffer");

uint32_t writeIndex = 0;
for (uint32_t i = 0; i < Field_Width * Field_Height; ++i)
for (uint32_t i = 0; i < Field_TileDrawCommandCount; ++i)
{
uint32_t writeLoc = writeIndex++;
buffer->instances[writeLoc].spriteIndex = Game_FieldImageTable[Field_Tiles[i].stage];
buffer->instances[writeLoc].scale = 2.0f / Field_Width;
buffer->instances[writeLoc].pos[0] = Field_Tiles[i].pos.x;
buffer->instances[writeLoc].pos[1] = Field_Tiles[i].pos.y;
Field_TileDrawCommand* command = &Field_TileDrawCommands[i];
buffer->instances[command->writeIndex].spriteIndex = command->spriteIndex;
}
Field_TileDrawCommandCount = 0;

uint32_t writeIndex = Field_Width * Field_Height;
for (uint32_t i = 0; i < Field_CropCount; i++)
{
uint32_t cropWriteIndex = writeIndex++;
@@ -4,21 +4,21 @@

#define PROFILE_MODE

void game_init(void);
void game_tick(float delta);
void game_kill(void);

#define GAME_MAX_INSTANCE_COUNT 50000000
typedef struct
{
float spriteIndex;
float scale;
float pos[2];
float spriteIndex;
float scale;
float pos[2];
} Game_Instance;

typedef struct
{
Game_Instance instances[GAME_MAX_INSTANCE_COUNT];
Game_Instance instances[GAME_MAX_INSTANCE_COUNT];
} Game_InstanceBuffer;

void game_init(Game_InstanceBuffer* buffer);
void game_tick(float delta);
void game_kill(void);

uint32_t game_gen_instance_buffer(Game_InstanceBuffer* buffer);
@@ -127,7 +127,7 @@ void core_init(void)
};

Render_InstanceBuffer = malloc(sizeof(Game_InstanceBuffer));
game_init();
game_init(Render_InstanceBuffer);
}

void core_frame(void)
@@ -174,7 +174,7 @@ void core_initProfile(void)

MIST_PROFILE_BEGIN("Core", "Init");
Render_InstanceBuffer = malloc(sizeof(Game_InstanceBuffer));
game_init();
game_init(Render_InstanceBuffer);
MIST_PROFILE_END("Core", "Init");
}

0 comments on commit 489adc9

Please sign in to comment.
You can’t perform that action at this time.