Add dll reloading

This commit is contained in:
Doyle Thai 2017-05-08 22:59:44 +10:00
parent 7f62ce23d0
commit e6d198b232
8 changed files with 826 additions and 453 deletions

View File

@ -1,29 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26403.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "drenderer", "bin\drenderer.exe", "{25476A47-63FF-426D-A4A2-73AB789B9916}"
ProjectSection(DebuggerProjectSystem) = preProject
PortSupplier = 00000000-0000-0000-0000-000000000000
Executable = C:\git\drenderer\bin\drenderer.exe
RemoteMachine = THAI-PC
StartingDirectory = C:\git\drenderer\bin
Environment = Default
LaunchingEngine = 00000000-0000-0000-0000-000000000000
UseLegacyDebugEngines = No
LaunchSQLEngine = No
AttachLaunchAction = No
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25476A47-63FF-426D-A4A2-73AB789B9916}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,6 +1,22 @@
#include "DRenderer.h"
#include "DRendererPlatform.h"
void DR_Update(PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input, PlatformMemory *const memory)
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input,
PlatformMemory *const memory)
{
u32 *bitmapPtr = (u32 *)renderBuffer->memory;
for (i32 y = 0; y < renderBuffer->height; y++)
{
for (i32 x = 0; x < renderBuffer->width; x++)
{
u8 red = 255;
u8 green = 0;
u8 blue = 0;
u32 color = (red << 16) | (green << 8) | (blue << 0);
bitmapPtr[x + (y * renderBuffer->width)] = color;
}
}
}

View File

@ -1,8 +1,7 @@
#ifndef DRENDERER_H
#define DRENDERER_H
void DR_Update(struct PlatformRenderBuffer *const renderBuffer,
struct PlatformInput *const input,
struct PlatformMemory *const memory);
typedef void DR_UpdateFunction(struct PlatformRenderBuffer *const renderBuffer,
struct PlatformInput *const input,
struct PlatformMemory *const memory);
#endif

View File

@ -44,9 +44,6 @@ typedef struct PlatformInput
{
f32 deltaForFrame;
bool loadNewRom;
wchar_t rom[260];
union {
KeyState key[key_count];
struct
@ -91,6 +88,8 @@ typedef struct PlatformRenderBuffer
i32 width;
i32 height;
i32 bytesPerPixel;
// Pixel Format: XX RR GG BB
void *memory;
} PlatformRenderBuffer;

View File

@ -1,2 +1 @@
#include "..\DRenderer.cpp"
#include "..\Win32DRenderer.cpp"

View File

@ -8,6 +8,7 @@
#define UNICODE
#define _UNICODE
#include <Pathcch.h>
#include <Windows.h>
typedef struct Win32RenderBitmap
{
@ -22,33 +23,13 @@ typedef struct Win32RenderBitmap
FILE_SCOPE Win32RenderBitmap globalRenderBitmap;
FILE_SCOPE bool globalRunning;
FILE_SCOPE void Win32DisplayRenderBitmap(Win32RenderBitmap renderBitmap,
HDC deviceContext, LONG width,
LONG height)
typedef struct Win32ExternalCode
{
HDC stretchDC = CreateCompatibleDC(deviceContext);
SelectObject(stretchDC, renderBitmap.handle);
DQN_ASSERT(renderBitmap.width == width);
DQN_ASSERT(renderBitmap.height == height);
StretchBlt(deviceContext, 0, 0, width, height, stretchDC, 0, 0,
renderBitmap.width, renderBitmap.height, SRCCOPY);
HMODULE dll;
FILETIME lastWriteTime;
// NOTE: Win32 AlphaBlend requires the RGB components to be premultiplied
// with alpha.
#if 0
BLENDFUNCTION blend = {};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
if (!AlphaBlend(deviceContext, 0, 0, width, height, deviceContext, 0, 0,
width, height, blend))
{
OutputDebugString(L"AlphaBlend() failed.");
}
#endif
DeleteDC(stretchDC);
}
DR_UpdateFunction *DR_Update;
} Win32ExternalCode;
enum Win32Menu
{
@ -56,6 +37,62 @@ enum Win32Menu
Win32Menu_FileExit,
};
FILE_SCOPE void Win32DisplayRenderBitmap(Win32RenderBitmap renderBitmap,
HDC deviceContext, LONG width,
LONG height)
{
HDC stretchDC = CreateCompatibleDC(deviceContext);
SelectObject(stretchDC, renderBitmap.handle);
// DQN_ASSERT(renderBitmap.width == width);
// DQN_ASSERT(renderBitmap.height == height);
StretchBlt(deviceContext, 0, 0, width, height, stretchDC, 0, 0,
renderBitmap.width, renderBitmap.height, SRCCOPY);
DeleteDC(stretchDC);
}
FILETIME Win32GetLastWriteTime(const char *const srcName)
{
WIN32_FIND_DATA findData = {};
FILETIME lastWriteTime = {};
HANDLE findHandle = FindFirstFileA(srcName, &findData);
if (findHandle != INVALID_HANDLE_VALUE)
{
lastWriteTime = findData.ftLastWriteTime;
FindClose(findHandle);
}
return lastWriteTime;
}
FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath,
const char *const tmpPath,
const FILETIME lastWriteTime)
{
Win32ExternalCode result = {};
result.lastWriteTime = lastWriteTime;
CopyFile(srcPath, tmpPath, false);
DR_UpdateFunction *updateFunction = NULL;
result.dll = LoadLibraryA(tmpPath);
if (result.dll)
{
updateFunction =
(DR_UpdateFunction *)GetProcAddress(result.dll, "DR_Update");
if (updateFunction) result.DR_Update = updateFunction;
}
return result;
}
FILE_SCOPE void Win32UnloadExternalDLL(Win32ExternalCode *externalCode)
{
if (externalCode->dll) FreeLibrary(externalCode->dll);
externalCode->dll = NULL;
externalCode->DR_Update = NULL;
}
FILE_SCOPE void Win32CreateMenu(HWND window)
{
HMENU menuBar = CreateMenu();
@ -229,6 +266,35 @@ FILE_SCOPE void Win32ProcessMessages(HWND window, PlatformInput *input)
}
}
// Return the index of the last slash
i32 Win32GetModuleDirectory(char *const buf, const u32 bufLen)
{
if (!buf || bufLen == 0) return 0;
u32 copiedLen = GetModuleFileName(NULL, buf, bufLen);
if (copiedLen == bufLen)
{
DQN_WIN32_ERROR_BOX(
"GetModuleFileName() buffer maxed: Len of copied text is len "
"of supplied buffer.",
NULL);
DQN_ASSERT(DQN_INVALID_CODE_PATH);
}
// NOTE: Should always work if GetModuleFileName works and we're running an
// executable.
i32 lastSlashIndex = 0;
for (i32 i = copiedLen; i > 0; i--)
{
if (buf[i] == '\\')
{
lastSlashIndex = i;
break;
}
}
return lastSlashIndex;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nShowCmd)
{
@ -268,14 +334,13 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
RECT rect = {};
rect.right = MIN_WIDTH;
rect.bottom = MIN_HEIGHT;
DWORD windowStyle =
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
AdjustWindowRect(&rect, windowStyle, true);
HWND mainWindow = CreateWindowExW(
WS_EX_COMPOSITED, wc.lpszClassName, L"DRenderer", windowStyle,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left,
rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr);
0, wc.lpszClassName, L"DRenderer", windowStyle, CW_USEDEFAULT,
CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, nullptr,
nullptr, hInstance, nullptr);
if (!mainWindow)
{
@ -291,11 +356,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
header.biPlanes = 1;
header.biBitCount = 32;
header.biCompression = BI_RGB; // uncompressed bitmap
header.biSizeImage = 0;
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biClrUsed = 0;
header.biClrImportant = 0;
globalRenderBitmap.info.bmiHeader = header;
globalRenderBitmap.width = header.biWidth;
@ -315,6 +375,26 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
DqnWin32_DisplayLastError("CreateDIBSection() failed");
return -1;
}
////////////////////////////////////////////////////////////////////////////
// Make DLL Path
////////////////////////////////////////////////////////////////////////////
Win32ExternalCode dllCode = {};
char dllPath[MAX_PATH] = {};
char dllTmpPath[MAX_PATH] = {};
{
char exeDir[MAX_PATH] = {};
i32 lastSlashIndex =
Win32GetModuleDirectory(exeDir, DQN_ARRAY_COUNT(exeDir));
DQN_ASSERT(lastSlashIndex + 1 < DQN_ARRAY_COUNT(exeDir));
exeDir[lastSlashIndex + 1] = 0;
u32 numCopied = Dqn_sprintf(dllPath, "%s%s", exeDir, "drenderer.dll");
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
numCopied =
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
}
////////////////////////////////////////////////////////////////////////////
// Update Loop
@ -328,13 +408,20 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
f64 frameTimeInS = 0.0f;
globalRunning = true;
SetWindowTextA(mainWindow, "test");
while (globalRunning)
{
////////////////////////////////////////////////////////////////////////
// Update State
////////////////////////////////////////////////////////////////////////
f64 startFrameTimeInS = DqnTime_NowInS();
FILETIME lastWriteTime = Win32GetLastWriteTime(dllPath);
if (CompareFileTime(&lastWriteTime, &dllCode.lastWriteTime) != 0)
{
Win32UnloadExternalDLL(&dllCode);
dllCode = Win32LoadExternalDLL(dllPath, dllTmpPath, lastWriteTime);
}
{
PlatformInput platformInput = {};
platformInput.deltaForFrame = (f32)frameTimeInS;
@ -345,7 +432,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
platformBuffer.height = globalRenderBitmap.height;
platformBuffer.width = globalRenderBitmap.width;
platformBuffer.bytesPerPixel = globalRenderBitmap.bytesPerPixel;
DR_Update(&platformBuffer, &platformInput, &platformMemory);
if (dllCode.DR_Update)
{
dllCode.DR_Update(&platformBuffer, &platformInput,
&platformMemory);
}
}
////////////////////////////////////////////////////////////////////////
@ -386,7 +478,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
Dqn_sprintf(windowTitleBuffer, "drenderer - dev - %5.2f ms/f",
msPerFrame);
SetWindowTextA(mainWindow, windowTitleBuffer);
#endif
}
return 0;

View File

@ -37,12 +37,9 @@ REM wd4201 nonstandard extension used: nameless struct/union
REM wd4189 local variable is initialised but not referenced
REM wd4505 unreferenced local function not used will be removed
set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
set Defines=
REM ////////////////////////////////////////////////////////////////////////////
REM Include Directories/Link Libraries
REM ////////////////////////////////////////////////////////////////////////////
set IncludeFiles=
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
set Win32Flags=/FmWin32DRenderer /FeWin32DRenderer
set TimeStamp=%date:~10,4%%date:~7,2%%date:~4,2%_%time:~0,2%%time:~3,2%%time:~6,2%
REM Link libraries
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
@ -54,9 +51,9 @@ set LinkFlags=-incremental:no -opt:ref -subsystem:WINDOWS -machine:x64 -nologo
REM ////////////////////////////////////////////////////////////////////////////
REM Compile
REM ////////////////////////////////////////////////////////////////////////////
cl %CompileFlags% %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles% /link %LinkLibraries% %LinkFlags% /out:%ProjectName%.exe
REM cl %CompileFlags% /P %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles%
del *.pdb >NUL 2>NUL
cl %CompileFlags% %Win32Flags% ..\src\Win32DRenderer.cpp /link %LinkLibraries% %LinkFlags%
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DR_Update %LinkFlags%
popd
set LastError=%ERRORLEVEL%
ctime -end %ProjectName%.ctm %LastError%

1035
src/dqn.h

File diff suppressed because it is too large Load Diff