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];
}
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)
{
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)
{
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];
for (; height > 0; --height)
{
for (int x = width; x > 0; --x)
*bmpPtr++ = color;
*bmpPtr++ = fillColor;
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)
{
@ -242,13 +297,6 @@ void gdrv::CreatePreview(gdrv_bitmap8& bmp)
if (bmp.Texture)
return;
auto texture = SDL_CreateTexture
(
winmain::Renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC,
bmp.Width, bmp.Height
);
SDL_UpdateTexture(texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
bmp.Texture = texture;
bmp.CreateTexture("nearest", SDL_TEXTUREACCESS_STATIC);
SDL_UpdateTexture(bmp.Texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
}

View file

@ -19,14 +19,20 @@ struct Rgba
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;
explicit ColorRgba(uint32_t color)
explicit constexpr ColorRgba(uint32_t color)
: Color(color)
{
}
explicit ColorRgba(Rgba rgba)
explicit constexpr ColorRgba(Rgba rgba)
: rgba(rgba)
{
}
@ -43,6 +49,8 @@ struct gdrv_bitmap8
gdrv_bitmap8(const struct dat8BitBmpHeader& header);
~gdrv_bitmap8();
void ScaleIndexed(float scaleX, float scaleY);
void CreateTexture(const char* scaleHint, int access);
void BlitToTexture();
ColorRgba* BmpBufPtr1;
char* IndexedBmpPtr;
int Width;
@ -62,10 +70,12 @@ class gdrv
public:
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, ColorRgba fillColor);
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
int srcXOff, int srcYOff);
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
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 ApplyPalette(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;
gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20];
zmap_header_type* render::zscreen;
SDL_Texture* render::vScreenTex = nullptr;
SDL_Rect render::DestinationRect{};
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height)
@ -58,26 +57,11 @@ void render::uninit()
ball_list.clear();
dirty_list.clear();
sprite_list.clear();
SDL_DestroyTexture(vScreenTex);
vScreenTex = nullptr;
}
void render::recreate_screen_texture()
{
if (vScreenTex != nullptr)
{
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);
vscreen->CreateTexture(options::Options.LinearFiltering ? "linear" : "nearest", SDL_TEXTUREACCESS_STREAMING);
}
void render::update()
@ -535,31 +519,13 @@ void render::SpriteViewer(bool* show)
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()
{
BlitVScreen();
vscreen->BlitToTexture();
if (offset_x == 0 && offset_y == 0)
{
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect);
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, nullptr, &DestinationRect);
}
else
{
@ -591,8 +557,8 @@ void render::PresentVScreen()
DestinationRect.w - dstSeparationX, static_cast<float>(DestinationRect.h)
};
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect);
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect);
SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
#else
// SDL_RenderCopy cannot express sub pixel offset.
// Vscreen shift is required for that.
@ -615,8 +581,8 @@ void render::PresentVScreen()
DestinationRect.w - dstSeparationX, DestinationRect.h
};
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect);
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect);
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
#endif
}
}

View file

@ -60,10 +60,8 @@ private:
static rectangle_type vscreen_rect;
static gdrv_bitmap8 *ball_bitmap[20];
static zmap_header_type* zscreen;
static SDL_Texture* vScreenTex;
static void repaint(struct render_sprite_type_struct* sprite);
static void paint_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::activated = false;
int winmain::DispFrameRate = 0;
int winmain::DispGRhistory = 0;
bool winmain::DispGRhistory = false;
bool winmain::single_step = false;
bool winmain::has_focus = true;
int winmain::last_mouse_x;
@ -185,7 +185,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
else
pb::replay_level(0);
unsigned dtHistoryCounter = 300u, updateCounter = 0, frameCounter = 0;
unsigned updateCounter = 0, frameCounter = 0;
auto frameStart = Clock::now();
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)
break;
@ -262,18 +232,30 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (!single_step && !no_time_loss)
{
auto dt = static_cast<float>(frameDuration.count());
auto dtWhole = static_cast<int>(std::round(dt));
pb::frame(dt);
if (gfr_display)
if (DispGRhistory)
{
auto deltaTPal = dtWhole + 10;
auto fillChar = static_cast<uint8_t>(deltaTPal);
if (deltaTPal > 236)
auto width = 300;
auto height = 64;
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++;
}
@ -327,6 +309,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
}
delete gfr_display;
gfr_display = nullptr;
options::uninit();
midi::music_shutdown();
pb::uninit();
@ -561,6 +544,10 @@ void winmain::RenderUi()
pause();
ShowSpriteViewer ^= true;
}
if (pb::cheat_mode && ImGui::MenuItem("Frame Times", nullptr, DispGRhistory))
{
DispGRhistory ^= true;
}
if (ImGui::BeginMenu("Cheats"))
{
if (ImGui::MenuItem("hidden test", nullptr, pb::cheat_mode))
@ -599,6 +586,8 @@ void winmain::RenderUi()
if (ShowSpriteViewer)
render::SpriteViewer(&ShowSpriteViewer);
options::RenderControlDialog();
if (DispGRhistory)
RenderFrameTimeDialog();
}
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)
{
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;
case SDLK_y:
SDL_SetWindowTitle(MainWindow, "Pinball");
@ -925,3 +933,23 @@ void winmain::UpdateFrameRate()
UpdateToFrameRatio = static_cast<double>(ups) / fps;
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 void UpdateFrameRate();
private:
static int return_value, DispFrameRate, DispGRhistory;
static int return_value, DispFrameRate;
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 std::string FpsDetails;
static bool restart;
@ -77,4 +77,5 @@ private:
static struct optionsStruct& Options;
static void RenderUi();
static void RenderFrameTimeDialog();
};