Improved frame time diagnostic tool.

Split overdraw palette from frame time tool.
This commit is contained in:
Muzychenko Andrey 2021-11-11 14:30:56 +03:00
parent 16b527e3cf
commit f3e4211226
6 changed files with 150 additions and 99 deletions

View file

@ -111,6 +111,44 @@ void gdrv_bitmap8::ScaleIndexed(float scaleX, float scaleY)
BmpBufPtr1 = new ColorRgba[Stride * Height]; BmpBufPtr1 = new ColorRgba[Stride * Height];
} }
void gdrv_bitmap8::CreateTexture(const char* scaleHint, int access)
{
if (Texture != nullptr)
{
SDL_DestroyTexture(Texture);
}
UsingSdlHint hint{ SDL_HINT_RENDER_SCALE_QUALITY, scaleHint };
Texture = SDL_CreateTexture
(
winmain::Renderer,
SDL_PIXELFORMAT_ARGB8888,
access,
Width, Height
);
SDL_SetTextureBlendMode(Texture, SDL_BLENDMODE_NONE);
}
void gdrv_bitmap8::BlitToTexture()
{
assertm(Texture, "Updating null texture");
int pitch = 0;
ColorRgba* lockedPixels;
auto result = SDL_LockTexture
(
Texture,
nullptr,
reinterpret_cast<void**>(&lockedPixels),
&pitch
);
assertm(result == 0, "Updating non-streaming texture");
assertm(static_cast<unsigned>(pitch) == Width * sizeof(ColorRgba), "Padding on vScreen texture");
std::memcpy(lockedPixels, BmpBufPtr1, Width * Height * sizeof(ColorRgba));
SDL_UnlockTexture(Texture);
}
int gdrv::display_palette(ColorRgba* plt) int gdrv::display_palette(ColorRgba* plt)
{ {
const uint32_t sysPaletteColors[] const uint32_t sysPaletteColors[]
@ -168,12 +206,16 @@ int gdrv::display_palette(ColorRgba* plt)
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar) void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar)
{ {
auto color = current_palette[fillChar]; fill_bitmap(bmp, width, height, xOff, yOff, current_palette[fillChar]);
}
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, ColorRgba fillColor)
{
auto bmpPtr = &bmp->BmpBufPtr1[bmp->Width * yOff + xOff]; auto bmpPtr = &bmp->BmpBufPtr1[bmp->Width * yOff + xOff];
for (; height > 0; --height) for (; height > 0; --height)
{ {
for (int x = width; x > 0; --x) for (int x = width; x > 0; --x)
*bmpPtr++ = color; *bmpPtr++ = fillColor;
bmpPtr += bmp->Stride - width; bmpPtr += bmp->Stride - width;
} }
} }
@ -213,6 +255,19 @@ void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int heigh
} }
} }
void gdrv::ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart)
{
auto srcPtr = bmp->BmpBufPtr1;
auto startOffset = xStart >= 0 ? 0 : -xStart;
auto endOffset = xStart >= 0 ? xStart : 0;
auto length = bmp->Width - std::abs(xStart);
for (int y = bmp->Height; y > 0; --y)
{
std::memmove(srcPtr + endOffset, srcPtr + startOffset, length * sizeof(ColorRgba));
srcPtr += bmp->Stride;
}
}
void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6) void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6)
{ {
@ -242,13 +297,6 @@ void gdrv::CreatePreview(gdrv_bitmap8& bmp)
if (bmp.Texture) if (bmp.Texture)
return; return;
auto texture = SDL_CreateTexture bmp.CreateTexture("nearest", SDL_TEXTUREACCESS_STATIC);
( SDL_UpdateTexture(bmp.Texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
winmain::Renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC,
bmp.Width, bmp.Height
);
SDL_UpdateTexture(texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
bmp.Texture = texture;
} }

View file

@ -19,14 +19,20 @@ struct Rgba
union ColorRgba union ColorRgba
{ {
static constexpr ColorRgba Black() { return ColorRgba{ Rgba{0, 0, 0, 255} }; }
static constexpr ColorRgba White() { return ColorRgba{ Rgba{255, 255, 255, 255} }; }
static constexpr ColorRgba Red() { return ColorRgba{ Rgba{0, 0, 255, 255} }; }
static constexpr ColorRgba Green() { return ColorRgba{ Rgba{0, 255,0, 255} }; }
static constexpr ColorRgba Blue() { return ColorRgba{ Rgba{255, 0, 0, 255} }; }
ColorRgba() = default; ColorRgba() = default;
explicit ColorRgba(uint32_t color) explicit constexpr ColorRgba(uint32_t color)
: Color(color) : Color(color)
{ {
} }
explicit ColorRgba(Rgba rgba) explicit constexpr ColorRgba(Rgba rgba)
: rgba(rgba) : rgba(rgba)
{ {
} }
@ -43,6 +49,8 @@ struct gdrv_bitmap8
gdrv_bitmap8(const struct dat8BitBmpHeader& header); gdrv_bitmap8(const struct dat8BitBmpHeader& header);
~gdrv_bitmap8(); ~gdrv_bitmap8();
void ScaleIndexed(float scaleX, float scaleY); void ScaleIndexed(float scaleX, float scaleY);
void CreateTexture(const char* scaleHint, int access);
void BlitToTexture();
ColorRgba* BmpBufPtr1; ColorRgba* BmpBufPtr1;
char* IndexedBmpPtr; char* IndexedBmpPtr;
int Width; int Width;
@ -62,10 +70,12 @@ class gdrv
public: public:
static int display_palette(ColorRgba* plt); static int display_palette(ColorRgba* plt);
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar); static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, ColorRgba fillColor);
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp, static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
int srcXOff, int srcYOff); int srcXOff, int srcYOff);
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff); gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
static void ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart);
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6); static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
static void ApplyPalette(gdrv_bitmap8& bmp); static void ApplyPalette(gdrv_bitmap8& bmp);
static void CreatePreview(gdrv_bitmap8& bmp); static void CreatePreview(gdrv_bitmap8& bmp);

View file

@ -16,7 +16,6 @@ float render::zscaler, render::zmin, render::zmax;
rectangle_type render::vscreen_rect; rectangle_type render::vscreen_rect;
gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20]; gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20];
zmap_header_type* render::zscreen; zmap_header_type* render::zscreen;
SDL_Texture* render::vScreenTex = nullptr;
SDL_Rect render::DestinationRect{}; SDL_Rect render::DestinationRect{};
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height) void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height)
@ -58,26 +57,11 @@ void render::uninit()
ball_list.clear(); ball_list.clear();
dirty_list.clear(); dirty_list.clear();
sprite_list.clear(); sprite_list.clear();
SDL_DestroyTexture(vScreenTex);
vScreenTex = nullptr;
} }
void render::recreate_screen_texture() void render::recreate_screen_texture()
{ {
if (vScreenTex != nullptr) vscreen->CreateTexture(options::Options.LinearFiltering ? "linear" : "nearest", SDL_TEXTUREACCESS_STREAMING);
{
SDL_DestroyTexture(vScreenTex);
}
UsingSdlHint hint{ SDL_HINT_RENDER_SCALE_QUALITY, options::Options.LinearFiltering ? "linear" : "nearest" };
vScreenTex = SDL_CreateTexture
(
winmain::Renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
vscreen_rect.Width, vscreen_rect.Height
);
SDL_SetTextureBlendMode(vScreenTex, SDL_BLENDMODE_NONE);
} }
void render::update() void render::update()
@ -535,31 +519,13 @@ void render::SpriteViewer(bool* show)
ImGui::End(); ImGui::End();
} }
void render::BlitVScreen()
{
int pitch = 0;
ColorRgba* lockedPixels;
SDL_LockTexture
(
vScreenTex,
nullptr,
reinterpret_cast<void**>(&lockedPixels),
&pitch
);
assertm(static_cast<unsigned>(pitch) == vscreen->Width * sizeof(ColorRgba), "Padding on vScreen texture");
std::memcpy(lockedPixels, vscreen->BmpBufPtr1, vscreen->Width * vscreen->Height * sizeof(ColorRgba));
SDL_UnlockTexture(vScreenTex);
}
void render::PresentVScreen() void render::PresentVScreen()
{ {
BlitVScreen(); vscreen->BlitToTexture();
if (offset_x == 0 && offset_y == 0) if (offset_x == 0 && offset_y == 0)
{ {
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect); SDL_RenderCopy(winmain::Renderer, vscreen->Texture, nullptr, &DestinationRect);
} }
else else
{ {
@ -591,8 +557,8 @@ void render::PresentVScreen()
DestinationRect.w - dstSeparationX, static_cast<float>(DestinationRect.h) DestinationRect.w - dstSeparationX, static_cast<float>(DestinationRect.h)
}; };
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect); SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect); SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
#else #else
// SDL_RenderCopy cannot express sub pixel offset. // SDL_RenderCopy cannot express sub pixel offset.
// Vscreen shift is required for that. // Vscreen shift is required for that.
@ -615,8 +581,8 @@ void render::PresentVScreen()
DestinationRect.w - dstSeparationX, DestinationRect.h DestinationRect.w - dstSeparationX, DestinationRect.h
}; };
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect); SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect); SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
#endif #endif
} }
} }

View file

@ -60,10 +60,8 @@ private:
static rectangle_type vscreen_rect; static rectangle_type vscreen_rect;
static gdrv_bitmap8 *ball_bitmap[20]; static gdrv_bitmap8 *ball_bitmap[20];
static zmap_header_type* zscreen; static zmap_header_type* zscreen;
static SDL_Texture* vScreenTex;
static void repaint(struct render_sprite_type_struct* sprite); static void repaint(struct render_sprite_type_struct* sprite);
static void paint_balls(); static void paint_balls();
static void unpaint_balls(); static void unpaint_balls();
static void BlitVScreen();
}; };

View file

@ -18,7 +18,7 @@ int winmain::return_value = 0;
bool winmain::bQuit = false; bool winmain::bQuit = false;
bool winmain::activated = false; bool winmain::activated = false;
int winmain::DispFrameRate = 0; int winmain::DispFrameRate = 0;
int winmain::DispGRhistory = 0; bool winmain::DispGRhistory = false;
bool winmain::single_step = false; bool winmain::single_step = false;
bool winmain::has_focus = true; bool winmain::has_focus = true;
int winmain::last_mouse_x; int winmain::last_mouse_x;
@ -185,7 +185,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
else else
pb::replay_level(0); pb::replay_level(0);
unsigned dtHistoryCounter = 300u, updateCounter = 0, frameCounter = 0; unsigned updateCounter = 0, frameCounter = 0;
auto frameStart = Clock::now(); auto frameStart = Clock::now();
double UpdateToFrameCounter = 0; double UpdateToFrameCounter = 0;
@ -209,36 +209,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
} }
} }
if (DispGRhistory)
{
if (!gfr_display)
{
auto plt = static_cast<ColorRgba*>(malloc(1024u));
auto pltPtr = &plt[10]; // first 10 entries are system colors hardcoded in display_palette()
for (int i1 = 0, i2 = 0; i1 < 256 - 10; ++i1, i2 += 8)
{
unsigned char blue = i2, redGreen = i2;
if (i2 > 255)
{
blue = 255;
redGreen = i1;
}
*pltPtr++ = ColorRgba{Rgba{redGreen, redGreen, blue, 0}};
}
gdrv::display_palette(plt);
free(plt);
gfr_display = new gdrv_bitmap8(400, 15, false);
}
if (!dtHistoryCounter)
{
dtHistoryCounter = 300;
gdrv::copy_bitmap(render::vscreen, 300, 10, 0, 30, gfr_display, 0, 0);
gdrv::fill_bitmap(gfr_display, 300, 10, 0, 0, 0);
}
}
if (!ProcessWindowMessages() || bQuit) if (!ProcessWindowMessages() || bQuit)
break; break;
@ -262,18 +232,30 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (!single_step && !no_time_loss) if (!single_step && !no_time_loss)
{ {
auto dt = static_cast<float>(frameDuration.count()); auto dt = static_cast<float>(frameDuration.count());
auto dtWhole = static_cast<int>(std::round(dt));
pb::frame(dt); pb::frame(dt);
if (gfr_display) if (DispGRhistory)
{ {
auto deltaTPal = dtWhole + 10; auto width = 300;
auto fillChar = static_cast<uint8_t>(deltaTPal); auto height = 64;
if (deltaTPal > 236) if (!gfr_display)
{ {
fillChar = 1; gfr_display = new gdrv_bitmap8(width, height, false);
gfr_display->CreateTexture("nearest", SDL_TEXTUREACCESS_STREAMING);
} }
gdrv::fill_bitmap(gfr_display, 1, 10, 300 - dtHistoryCounter, 0, fillChar);
--dtHistoryCounter; gdrv::ScrollBitmapHorizontal(gfr_display, -1);
auto target = static_cast<float>(TargetFrameTime.count());
auto scale = height / target / 2;
gdrv::fill_bitmap(gfr_display, 1, height, width - 1, 0, ColorRgba::Black()); // Background
auto targetVal = dt < target ? dt : target;
auto targetHeight = std::min(static_cast<int>(std::round(targetVal * scale)), width);
gdrv::fill_bitmap(gfr_display, 1, targetHeight, width - 1, height - targetHeight, ColorRgba::White()); // Target
auto diffVal = dt < target ? target - dt : dt - target;
auto diffHeight = std::min(static_cast<int>(std::round(diffVal * scale)), width);
gdrv::fill_bitmap(gfr_display, 1, diffHeight, width - 1, height - targetHeight - diffHeight, ColorRgba::Red()); // Target diff
} }
updateCounter++; updateCounter++;
} }
@ -327,6 +309,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
} }
delete gfr_display; delete gfr_display;
gfr_display = nullptr;
options::uninit(); options::uninit();
midi::music_shutdown(); midi::music_shutdown();
pb::uninit(); pb::uninit();
@ -561,6 +544,10 @@ void winmain::RenderUi()
pause(); pause();
ShowSpriteViewer ^= true; ShowSpriteViewer ^= true;
} }
if (pb::cheat_mode && ImGui::MenuItem("Frame Times", nullptr, DispGRhistory))
{
DispGRhistory ^= true;
}
if (ImGui::BeginMenu("Cheats")) if (ImGui::BeginMenu("Cheats"))
{ {
if (ImGui::MenuItem("hidden test", nullptr, pb::cheat_mode)) if (ImGui::MenuItem("hidden test", nullptr, pb::cheat_mode))
@ -599,6 +586,8 @@ void winmain::RenderUi()
if (ShowSpriteViewer) if (ShowSpriteViewer)
render::SpriteViewer(&ShowSpriteViewer); render::SpriteViewer(&ShowSpriteViewer);
options::RenderControlDialog(); options::RenderControlDialog();
if (DispGRhistory)
RenderFrameTimeDialog();
} }
int winmain::event_handler(const SDL_Event* event) int winmain::event_handler(const SDL_Event* event)
@ -687,7 +676,26 @@ int winmain::event_handler(const SDL_Event* event)
switch (event->key.keysym.sym) switch (event->key.keysym.sym)
{ {
case SDLK_g: case SDLK_g:
DispGRhistory = 1; DispGRhistory ^= true;
break;
case SDLK_o:
{
auto plt = new ColorRgba[4 * 256];
auto pltPtr = &plt[10]; // first 10 entries are system colors hardcoded in display_palette()
for (int i1 = 0, i2 = 0; i1 < 256 - 10; ++i1, i2 += 8)
{
unsigned char blue = i2, redGreen = i2;
if (i2 > 255)
{
blue = 255;
redGreen = i1;
}
*pltPtr++ = ColorRgba{ Rgba{redGreen, redGreen, blue, 0} };
}
gdrv::display_palette(plt);
delete[] plt;
}
break; break;
case SDLK_y: case SDLK_y:
SDL_SetWindowTitle(MainWindow, "Pinball"); SDL_SetWindowTitle(MainWindow, "Pinball");
@ -925,3 +933,23 @@ void winmain::UpdateFrameRate()
UpdateToFrameRatio = static_cast<double>(ups) / fps; UpdateToFrameRatio = static_cast<double>(ups) / fps;
TargetFrameTime = DurationMs(1000.0 / ups); TargetFrameTime = DurationMs(1000.0 / ups);
} }
void winmain::RenderFrameTimeDialog()
{
if (!gfr_display)
return;
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{ 300, 70 });
if (ImGui::Begin("Frame Times", &DispGRhistory, ImGuiWindowFlags_NoScrollbar))
{
auto target = static_cast<float>(TargetFrameTime.count());
auto scale = 1 / (64 / 2 / target);
ImGui::Text("Target frame time:%03.04fms, 1px:%03.04fms", target, scale);
gfr_display->BlitToTexture();
auto region = ImGui::GetContentRegionAvail();
ImGui::Image(gfr_display->Texture, region);
}
ImGui::End();
ImGui::PopStyleVar();
}

View file

@ -63,9 +63,9 @@ public:
static bool RestartRequested() { return restart; } static bool RestartRequested() { return restart; }
static void UpdateFrameRate(); static void UpdateFrameRate();
private: private:
static int return_value, DispFrameRate, DispGRhistory; static int return_value, DispFrameRate;
static int mouse_down, last_mouse_x, last_mouse_y; static int mouse_down, last_mouse_x, last_mouse_y;
static bool no_time_loss, activated, bQuit, has_focus; static bool no_time_loss, activated, bQuit, has_focus, DispGRhistory;
static gdrv_bitmap8* gfr_display; static gdrv_bitmap8* gfr_display;
static std::string FpsDetails; static std::string FpsDetails;
static bool restart; static bool restart;
@ -77,4 +77,5 @@ private:
static struct optionsStruct& Options; static struct optionsStruct& Options;
static void RenderUi(); static void RenderUi();
static void RenderFrameTimeDialog();
}; };