optimisation

This commit is contained in:
Squishy Bloob 2024-03-30 04:16:07 +00:00
parent 2a5b777cd9
commit e83ed1172c
11 changed files with 72 additions and 74 deletions

View File

@ -162,9 +162,10 @@
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<OpenMPSupport>true</OpenMPSupport> <OpenMPSupport>true</OpenMPSupport>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers> <OmitFramePointers>false</OmitFramePointers>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -16,10 +16,12 @@ protected:
void cursor(image const* cursor); void cursor(image const* cursor);
template<typename T> template<typename T>
T const* get(std::string const& path); T const* get(std::string const& path);
int fps();
private: private:
vec2i _mouse_pos; vec2i _mouse_pos;
image const* _cursor; image const* _cursor;
resource_manager _rm; resource_manager _rm;
int _fps;
}; };
template<typename T> template<typename T>

View File

@ -35,6 +35,7 @@ struct image : resource {
void draw(std::string const& str, vec2i pos, font const* font, color color); void draw(std::string const& str, vec2i pos, font const* font, color color);
void draw(std::string const& str, vec2i pos, font const* font, color color1, color color2); void draw(std::string const& str, vec2i pos, font const* font, color color1, color color2);
private: private:
bool _alpha;
bool _borrowed_pointer; //to know if to free or not bool _borrowed_pointer; //to know if to free or not
color* _data; //not a vector so can wrap sdl surfaces color* _data; //not a vector so can wrap sdl surfaces
recti _bounds; recti _bounds;

View File

@ -12,6 +12,8 @@ struct rect {
rect<T> normal() const; //flip direction so size is positive rect<T> normal() const; //flip direction so size is positive
vec2<T> pos2() const; vec2<T> pos2() const;
bool operator==(rect<T> const& other) const;
static rect<T> from_points(vec2<T> pos1, vec2<T> pos2); static rect<T> from_points(vec2<T> pos1, vec2<T> pos2);
static rect<T> intersection(rect<T> const& a, rect<T> const& b); static rect<T> intersection(rect<T> const& a, rect<T> const& b);
}; };
@ -35,6 +37,11 @@ inline vec2<T> rect<T>::pos2() const {
return pos + size - vec2<T>::one; return pos + size - vec2<T>::one;
} }
template<typename T>
inline bool rect<T>::operator==(rect<T> const& other) const {
return pos == other.pos && size == other.size;
}
template<typename T> template<typename T>
inline rect<T> rect<T>::from_points(vec2<T> pos1, vec2<T> pos2) { inline rect<T> rect<T>::from_points(vec2<T> pos1, vec2<T> pos2) {
return rect<T>(pos1, pos2-pos1+vec2<T>::one).normal(); return rect<T>(pos1, pos2-pos1+vec2<T>::one).normal();

View File

@ -23,6 +23,10 @@ struct vec2 {
vec2<T> operator*(T a) const { return vec2(x * a, y * a); } vec2<T> operator*(T a) const { return vec2(x * a, y * a); }
vec2<T> operator/(T a) const { return vec2(x / a, y / a); } vec2<T> operator/(T a) const { return vec2(x / a, y / a); }
bool operator==(vec2<T> const& other) const {
return x == other.x && y == other.y;
}
static vec2<T> min(vec2<T> a, vec2<T> b); static vec2<T> min(vec2<T> a, vec2<T> b);
static vec2<T> max(vec2<T> a, vec2<T> b); static vec2<T> max(vec2<T> a, vec2<T> b);

View File

@ -11,13 +11,27 @@ void image::draw(image const* image, vec2i pos, recti src_rect) {
auto src_off = crop.pos - pos + src_rect.pos; auto src_off = crop.pos - pos + src_rect.pos;
auto start = crop.pos; auto start = crop.pos;
auto end = crop.pos2(); auto end = crop.pos2();
for(int y = start.y; y <= end.y; ++y) { if(image->_alpha) {
for(int x = start.x; x <= end.x; ++x) { for(int y = start.y; y <= end.y; ++y) {
auto color = image->_data[ for(int x = start.x; x <= end.x; ++x) {
x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x auto color = image->_data[
]; x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x
if(color & 0xff000000) ];
if(color & 0xff000000)
_data[x + y * _bounds.size.x] = color;
}
}
} else {
//#pragma omp parallel for
for(int y = start.y; y <= end.y; ++y) {
std::memcpy(_data + (y * _bounds.size.x), image->_data - start.x + src_off.x + (y-start.y + src_off.y) * image->_bounds.size.x, (end.x - start.x + 1)*4);
/* for(int x = start.x; x <= end.x; ++x) {
auto color = image->_data[
x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x
];
_data[x + y * _bounds.size.x] = color; _data[x + y * _bounds.size.x] = color;
}
*/
} }
} }
} }
@ -47,6 +61,11 @@ void image::draw(image const* image, vec2i pos, color color, recti src_rect) {
void image::draw_upscaled(image const* image) { void image::draw_upscaled(image const* image) {
if(image->bounds() == bounds()) {
std::memcpy(_data, image->_data, bounds().size.size() * 4);
return;
}
auto ratio = _bounds.size / image->_bounds.size; auto ratio = _bounds.size / image->_bounds.size;
auto scale = std::min(ratio.x, ratio.y); auto scale = std::min(ratio.x, ratio.y);
switch(scale) { switch(scale) {

View File

@ -62,6 +62,7 @@ void game::run() {
std::chrono::duration<int32_t, std::nano> second(1000000000ll); std::chrono::duration<int32_t, std::nano> second(1000000000ll);
auto frame_duration = second / settings.target_fps; auto frame_duration = second / settings.target_fps;
auto last_frame = last_second; auto last_frame = last_second;
_fps = settings.target_fps; //just visually nicer
auto running = true; auto running = true;
while(running) { while(running) {
@ -82,7 +83,8 @@ void game::run() {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
if(now - last_second >= std::chrono::seconds(1)) { if(now - last_second >= std::chrono::seconds(1)) {
std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0 / frames_since_last_second) << std::endl; _fps = frames_since_last_second;
std::cout << std::format("FPS: {:5} | mspf: {}", _fps, 1000.0 / _fps) << std::endl;
frames_since_last_second = 0; frames_since_last_second = 0;
last_second += std::chrono::seconds(1); last_second += std::chrono::seconds(1);
} }
@ -92,7 +94,11 @@ void game::run() {
render(screen); render(screen);
if(_cursor) if(_cursor)
screen.draw(_cursor, _mouse_pos); screen.draw(_cursor, _mouse_pos);
window_image.draw_upscaled(&screen); auto p = screen.raw_pointer();
if(screen.bounds() != window_image.bounds()) {
window_image.draw_upscaled(&screen);
p = window_image.raw_pointer();
}
BITMAPINFOHEADER bi{ sizeof(bi) }; BITMAPINFOHEADER bi{ sizeof(bi) };
bi.biWidth = window_image.size().x; bi.biWidth = window_image.size().x;
@ -112,7 +118,7 @@ void game::run() {
0, 0,
0, 0,
window_image.size().y, window_image.size().y,
window_image.raw_pointer(), p,
(BITMAPINFO*)&bi, (BITMAPINFO*)&bi,
DIB_RGB_COLORS DIB_RGB_COLORS
); );
@ -125,63 +131,6 @@ void game::run() {
} }
/*
void game::run() {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
settings settings;
init(settings);
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, "title");
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, settings.size.x * settings.scale);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, settings.size.y * settings.scale);
auto window = SDL_CreateWindowWithProperties(props);
auto screen = image(settings.size);
auto renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED);
auto window_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, settings.size.x * settings.scale, settings.size.y * settings.scale);
auto last_second = std::chrono::steady_clock::now();
auto frames_since_last_second = 0;
auto running = true;
while(running) {
auto event = SDL_Event{};
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_EVENT_QUIT:
running = false;
break;
}
}
auto now = std::chrono::steady_clock::now();
if(now - last_second >= std::chrono::seconds(1)) {
std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0/frames_since_last_second) << std::endl;
frames_since_last_second = 0;
last_second += std::chrono::seconds(1);
}
update();
render(screen);
++frames_since_last_second;
int pitch;
void* pixels = 0;
SDL_LockTexture(window_texture, 0, &pixels, &pitch);
auto window_image = image(settings.size * settings.scale, static_cast<color*>(pixels));
window_image.draw_upscaled(screen);
SDL_UnlockTexture(window_texture);
SDL_RenderTexture(renderer, window_texture, 0, 0);
SDL_RenderPresent(renderer);
}
SDL_Quit();
}
*/
void game::init(settings& settings) { void game::init(settings& settings) {
} }
@ -201,3 +150,7 @@ vec2i const& game::mouse_pos() const {
void game::cursor(image const* cursor) { void game::cursor(image const* cursor) {
_cursor = cursor; _cursor = cursor;
} }
int game::fps() {
return _fps;
}

View File

@ -3,11 +3,15 @@
#define STBI_ONLY_PNG #define STBI_ONLY_PNG
#include "stb_image.h" #include "stb_image.h"
image::image(resource_manager& rm, ini_category const* ini, std::string const& path, std::vector<uint8_t> const& data) { image::image(resource_manager& rm, ini_category const* ini, std::string const& path, std::vector<uint8_t> const& data) :
_alpha(false), _borrowed_pointer(false)
{
int w, h, n; int w, h, n;
auto d = reinterpret_cast<color*>(stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, 4)); auto d = reinterpret_cast<color*>(stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, 4));
_data = new color[w * h]; _data = new color[w * h];
for(int i = 0; i < w * h; ++i) { for(int i = 0; i < w * h; ++i) {
if((d[i] & 0xff000000u) == 0)
_alpha = true;
_data[i] = d[i]; _data[i] = d[i];
_data[i] = (d[i] & 0xff000000u) | _data[i] = (d[i] & 0xff000000u) |
((d[i] & 0x00ff0000u) >> 16) | ((d[i] & 0x00ff0000u) >> 16) |
@ -21,19 +25,22 @@ image::image(resource_manager& rm, ini_category const* ini, std::string const& p
image::image(vec2i size) : image::image(vec2i size) :
_borrowed_pointer(false), _borrowed_pointer(false),
_data(new color[size.size()]), _data(new color[size.size()]),
_bounds(vec2i::zero, size) _bounds(vec2i::zero, size),
_alpha(true)
{} {}
image::image(vec2i size, color* data) : image::image(vec2i size, color* data) :
_borrowed_pointer(true), _borrowed_pointer(true),
_data(data), _data(data),
_bounds(vec2i::zero, size) _bounds(vec2i::zero, size),
_alpha(true)
{} {}
image::image(image const& other) : image::image(image const& other) :
_borrowed_pointer(false), _borrowed_pointer(false),
_data(new color[other.size().size()]), _data(new color[other.size().size()]),
_bounds(other.bounds()) _bounds(other.bounds()),
_alpha(other._alpha)
{ {
std::memcpy(_data, other._data, size().size() * 4); std::memcpy(_data, other._data, size().size() * 4);
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 147 KiB

BIN
test/assets/test2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -16,8 +16,10 @@ struct my_game : game {
}; };
void my_game::init(settings& settings) { void my_game::init(settings& settings) {
settings.target_fps = 60; settings.target_fps = 60000;
//img = get<image>("test.png"); settings.scale = 1;
settings.size = vec2i(1920, 1080);
img = get<image>("test.png");
//ini = get<::ini>("test.ini"); //ini = get<::ini>("test.ini");
font = get<::font>("_/default-font-prop.png"); font = get<::font>("_/default-font-prop.png");
//cursor(&font['\\']); //cursor(&font['\\']);
@ -31,10 +33,12 @@ void my_game::render(image& target) {
target.clear(0xffdddd); target.clear(0xffdddd);
auto pos = vec2i(std::sin(time * TAU / 4) * 100, std::cos(time * TAU / 4) * 100); auto pos = vec2i(std::sin(time * TAU / 4) * 100, std::cos(time * TAU / 4) * 100);
//target.draw(img, vec2i(320, 180) + pos, recti(vec2i(8, 14), vec2i(8 * 4, 14 * 4))); //target.draw(img, vec2i(320, 180) + pos, recti(vec2i(8, 14), vec2i(8 * 4, 14 * 4)));
//target.draw(img, vec2i::zero); for(int i = 0; i < 1; ++i)
target.draw(img, vec2i::zero);
//target.draw(tileset[0xda], vec2i(320, 180) + pos, 0xff00ff); //target.draw(tileset[0xda], vec2i(320, 180) + pos, 0xff00ff);
auto str = "Can only be played if\nthere are no card in\nyour draw pile.\nDeal 50 damage to ALL\nenemies."; auto str = "Can only be played if\nthere are no card in\nyour draw pile.\nDeal 50 damage to ALL\nenemies.";
target.draw(str, vec2i(100, 100) + pos, font, 0xffffff, 0); target.draw(str, vec2i(100, 100) + pos, font, 0xffffff, 0);
target.draw(std::format("FPS: {}", fps()), vec2i(10, 10), font, 0xffffff, 0);
//target.draw("\\", mouse_pos(), font, 0xffffff, 0); //target.draw("\\", mouse_pos(), font, 0xffffff, 0);
} }