Skip to content

Commit

Permalink
Rendering is now multithreaded, using SDL_Threads.
Browse files Browse the repository at this point in the history
Removed OpenMP implementation.
  • Loading branch information
silvematt committed Sep 24, 2024
1 parent 2d7ac7e commit e10fa5f
Show file tree
Hide file tree
Showing 6 changed files with 575 additions and 270 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LIBRARY_PATHS = -LC:\Lib\SDL2-2.30.1\lib\x86
COMPILER_FLAGS = -O2 -Wl,--subsystem,windows -mwindows

#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 -lws2_32 -fopenmp
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 -lws2_32

#OBJ_NAME specifies the name of our exectuable
OBJ_NAME = bin/TomentOnline
Expand Down
50 changes: 50 additions & 0 deletions src/Engine/A_Application.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ unsigned int* raycast_pixels;
bool isInMenu; // True if the player is in a menu
bool isInGame; // True if the player is in game

// Look at .h for explaination of data
int cpuCount;
SDL_Thread** threads;
thread_data_t** threadsdata;
bool** threadDone;
int extingThreads = 0;
bool threadIterationFinished;

thread_job_e currentThreadJob = TS_RAYCAST;

SDL_mutex* threadDataMutex;
SDL_cond* condThreadWait;
SDL_sem* renderingThreadSemaphore;
SDL_sem* mainThreadWaitSem;
SDL_sem* renderingThreadSemaphore;

SDL_mutex* rayDataMutex;

//-------------------------------------
// Initializes the application and subsystems
//-------------------------------------
Expand All @@ -39,6 +57,38 @@ void A_InitApplication(void)

win_width = win_surface->w;
pixels = win_surface->pixels;

// Initialize CPU Count
cpuCount = SDL_GetCPUCount();

printf("CPU Count: %d\n", cpuCount);

printf("Creating multithread structures...\n");
threadIterationFinished = false;

mainThreadWaitSem = SDL_CreateSemaphore(0);
renderingThreadSemaphore = SDL_CreateSemaphore(0);
threadDataMutex = SDL_CreateMutex();
condThreadWait = SDL_CreateCond();

rayDataMutex = SDL_CreateMutex();

printf("Creating threads...\n");
threads = malloc(cpuCount * sizeof(SDL_Thread*));
threadsdata = malloc(cpuCount * sizeof(thread_data_t*));
threadDone = malloc(cpuCount * sizeof(bool*));

for(int i = 0; i < cpuCount; i++)
{
threadsdata[i] = malloc(sizeof(thread_data_t));
threadsdata[i]->localID = i;

threadDone[i] = malloc(sizeof(bool));

threads[i] = SDL_CreateThread(R_ThreadRoutine, "THREAD", threadsdata[i]);
}

currentThreadJob = TS_RAYCAST;

// Init Renderer
R_InitRendering();
Expand Down
31 changes: 31 additions & 0 deletions src/Engine/A_Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <stdlib.h>

#include "SDL.h"
#include "SDL_thread.h"

// Defines
#define SCREEN_WIDTH 800
Expand Down Expand Up @@ -44,6 +45,36 @@ extern unsigned int* pixels; // pixels of the surface
extern SDL_Surface* raycast_surface; // the surface the raycasting is written to
extern unsigned int* raycast_pixels; // pixels of the surface

// Multithreading rendering
extern int cpuCount; // Number of threads to spawn
extern SDL_Thread** threads; // all threads

// Per-thread data
typedef struct thread_data_s
{
int localID;
} thread_data_t;

typedef enum thread_job_e
{
TS_RAYCAST = 0,
TS_FLOORCAST,
TS_CEILINGCAST
} thread_job_e;

extern bool** threadDone; // array of booleans, threadDone[i] tellls if the i-th thread has finished the computation (but doesn't mean it ended the loop)
extern bool threadIterationFinished; // if true, the current iteration is finished
extern int extingThreads; // how many threads finished and exited the current iteration and are ready for the next

extern thread_job_e currentThreadJob;

extern SDL_mutex* threadDataMutex; // Mutex to access and modify the data defined above (threadDone, threadIterationFinished, extingThreads)
extern SDL_cond* condThreadWait; // When one thread is done (but not all of them), he will wait on this condition
extern SDL_sem* renderingThreadSemaphore; // When a thread is ready to work, he will wait on this semaphore before going inside the function, when the main thread wants to start the work of the threads, he will post on this semaphore
extern SDL_sem* mainThreadWaitSem; // When all threads are done and extingThreads = cpuCount, means the iteration is definitely finished, so we can wake up the main thread and continue

extern SDL_mutex* rayDataMutex; // Mutex to access and modify the data filled while raycasting (AddToThinWall, AddDynamicSprites, etc)

//-------------------------------------
// Initializes the application
//-------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/Engine/G_MainMenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void G_RenderCurrentMenuBackground(void)
case MENU_ABOUT:
{
T_DisplayTextScaled(FONT_BLKCRY, "About", 210, 80, 2.0f);
T_DisplayTextScaled(FONT_BLKCRY, "Programmer: Mattia Silvestro ( silvematt)\nVersion: 1.1 OpenMP", 80, 200, 1.0f);
T_DisplayTextScaled(FONT_BLKCRY, "Programmer: Mattia Silvestro ( silvematt)\nVersion: 1.2", 80, 200, 1.0f);

break;
}
Expand Down
Loading

0 comments on commit e10fa5f

Please sign in to comment.