win32: Move frame throttle into drivers for precision.
This commit is contained in:
parent
309f9e650d
commit
803125ffe9
@ -63,10 +63,10 @@ void ShaderChain::construct_buffer_objects()
|
||||
break;
|
||||
}
|
||||
|
||||
auto write_size = [&location](float width, float height) {
|
||||
auto write_size = [&location](int width, int height) {
|
||||
std::array<float, 4> size;
|
||||
size[0] = width;
|
||||
size[1] = height;
|
||||
size[0] = (float)width;
|
||||
size[1] = (float)height;
|
||||
size[2] = 1.0f / size[0];
|
||||
size[3] = 1.0f / size[1];
|
||||
memcpy(location, size.data(), sizeof(float) * 4);
|
||||
@ -104,7 +104,7 @@ void ShaderChain::construct_buffer_objects()
|
||||
if (uniform.specifier < (int)lookup_textures.size())
|
||||
write_size(lookup_textures[uniform.specifier]->image_width, lookup_textures[uniform.specifier]->image_height);
|
||||
else
|
||||
write_size(1.0f, 1.0f);
|
||||
write_size(1, 1);
|
||||
break;
|
||||
|
||||
case SlangShader::Uniform::MVP:
|
||||
@ -389,16 +389,18 @@ void ShaderChain::update_descriptor_set(vk::CommandBuffer cmd, int pipe_num, int
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderChain::do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
bool ShaderChain::do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
{
|
||||
do_frame_without_swap(data, width, height, stride, format, viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
if (!do_frame_without_swap(data, width, height, stride, format, viewport_x, viewport_y, viewport_width, viewport_height))
|
||||
return false;
|
||||
context->swapchain->swap();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
bool ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
{
|
||||
if (!context->swapchain->begin_frame())
|
||||
return;
|
||||
return false;
|
||||
|
||||
current_frame_index = context->swapchain->get_current_frame();
|
||||
|
||||
@ -518,6 +520,7 @@ void ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, in
|
||||
|
||||
last_frame_index = current_frame_index;
|
||||
frame_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderChain::upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format)
|
||||
|
@ -19,8 +19,8 @@ class ShaderChain
|
||||
bool load_shader_preset(std::string filename);
|
||||
void update_and_propagate_sizes(int original_width_, int original_height_, int viewport_width_, int viewport_height_);
|
||||
bool load_lookup_textures();
|
||||
void do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
void do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
bool do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
bool do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
void upload_original(uint8_t *data, int width, int height, int stride, vk::Format format);
|
||||
void upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format);
|
||||
void construct_buffer_objects();
|
||||
|
@ -215,13 +215,13 @@ void SimpleOutput::set_filter(bool on)
|
||||
filter = on;
|
||||
}
|
||||
|
||||
void SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
bool SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (!swapchain->begin_frame())
|
||||
return;
|
||||
return false;
|
||||
|
||||
auto &tex = textures[swapchain->get_current_frame()];
|
||||
auto &cmd = swapchain->get_cmd();
|
||||
@ -253,12 +253,16 @@ void SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height,
|
||||
|
||||
swapchain->end_render_pass();
|
||||
swapchain->end_frame_without_swap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimpleOutput::do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
bool SimpleOutput::do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||
{
|
||||
do_frame_without_swap(buffer, width, height, byte_stride, viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
if (!do_frame_without_swap(buffer, width, height, byte_stride, viewport_x, viewport_y, viewport_width, viewport_height))
|
||||
return false;
|
||||
swapchain->swap();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
@ -10,8 +10,8 @@ class SimpleOutput
|
||||
public:
|
||||
SimpleOutput(Vulkan::Context *context, vk::Format format);
|
||||
~SimpleOutput();
|
||||
void do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
void do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
bool do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
bool do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||
void set_filter(bool on);
|
||||
|
||||
private:
|
||||
|
@ -199,14 +199,14 @@ bool Swapchain::begin_frame()
|
||||
|
||||
auto &frame = frames[current_frame];
|
||||
|
||||
auto result = device.waitForFences(frame.fence.get(), true, 33000000);
|
||||
auto result = device.waitForFences(frame.fence.get(), true, UINT64_MAX);
|
||||
if (result != vk::Result::eSuccess)
|
||||
{
|
||||
printf("Failed fence\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result_value = device.acquireNextImageKHR(swapchain_object.get(), 33000000, frame.acquire.get());
|
||||
auto result_value = device.acquireNextImageKHR(swapchain_object.get(), UINT64_MAX, frame.acquire.get());
|
||||
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
||||
result_value.result == vk::Result::eSuboptimalKHR)
|
||||
{
|
||||
@ -217,7 +217,7 @@ bool Swapchain::begin_frame()
|
||||
|
||||
if (result_value.result != vk::Result::eSuccess)
|
||||
{
|
||||
printf("Timeout waiting for frame. Running too slow.\n");
|
||||
printf("Unable to acquire swapchain image: %s\n", vk::to_string(result_value.result).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -334,6 +334,7 @@ void CDirect3D::Render(SSurface Src)
|
||||
pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);
|
||||
pDevice->EndScene();
|
||||
|
||||
WinThrottleFramerate();
|
||||
pDevice->Present(NULL, NULL, NULL, NULL);
|
||||
|
||||
if (GUI.ReduceInputLag)
|
||||
|
@ -369,6 +369,9 @@ void COpenGL::Render(SSurface Src)
|
||||
}
|
||||
|
||||
glFlush();
|
||||
|
||||
WinThrottleFramerate();
|
||||
|
||||
SwapBuffers(hDC);
|
||||
if (GUI.ReduceInputLag)
|
||||
glFinish();
|
||||
|
@ -61,9 +61,6 @@ void CVulkan::Render(SSurface Src)
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
if (GUI.ReduceInputLag)
|
||||
context->wait_idle();
|
||||
|
||||
SSurface Dst{};
|
||||
|
||||
RECT dstRect = GetFilterOutputSize(Src);
|
||||
@ -87,14 +84,27 @@ void CVulkan::Render(SSurface Src)
|
||||
//Get maximum rect respecting AR setting
|
||||
displayRect = CalculateDisplayRect(Dst.Width, Dst.Height, windowSize.right, windowSize.bottom);
|
||||
|
||||
bool result;
|
||||
|
||||
if (shaderchain)
|
||||
{
|
||||
shaderchain->do_frame(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, vk::Format::eR5G6B5UnormPack16, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||
return;
|
||||
result = shaderchain->do_frame_without_swap(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, vk::Format::eR5G6B5UnormPack16, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||
}
|
||||
else if (simple_output)
|
||||
{
|
||||
simple_output->set_filter(Settings.BilinearFilter);
|
||||
result = simple_output->do_frame_without_swap(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||
}
|
||||
|
||||
simple_output->set_filter(Settings.BilinearFilter);
|
||||
simple_output->do_frame(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||
WinThrottleFramerate();
|
||||
|
||||
if (result)
|
||||
{
|
||||
context->swapchain->swap();
|
||||
|
||||
if (GUI.ReduceInputLag)
|
||||
context->wait_idle();
|
||||
}
|
||||
}
|
||||
|
||||
bool CVulkan::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
|
||||
|
@ -449,7 +449,6 @@
|
||||
<ClInclude Include="..\vulkan\vulkan_slang_pipeline.hpp" />
|
||||
<ClInclude Include="..\vulkan\vulkan_swapchain.hpp" />
|
||||
<ClInclude Include="..\vulkan\vulkan_texture.hpp" />
|
||||
<ClInclude Include="..\vulkan\std_chrono_throttle.hpp" />
|
||||
<ClInclude Include="AVIOutput.h" />
|
||||
<ClInclude Include="CCGShader.h" />
|
||||
<ClInclude Include="CD3DCG.h" />
|
||||
@ -613,7 +612,6 @@
|
||||
<ClCompile Include="..\vulkan\vulkan_slang_pipeline.cpp" />
|
||||
<ClCompile Include="..\vulkan\vulkan_swapchain.cpp" />
|
||||
<ClCompile Include="..\vulkan\vulkan_texture.cpp" />
|
||||
<ClCompile Include="..\vulkan\std_chrono_throttle.cpp" />
|
||||
<ClCompile Include="AVIOutput.cpp" />
|
||||
<ClCompile Include="CCGShader.cpp" />
|
||||
<ClCompile Include="CD3DCG.cpp" />
|
||||
|
@ -675,6 +675,49 @@ int WinGetAutomaticInputRate(void)
|
||||
return (int)newInputRate;
|
||||
}
|
||||
|
||||
void WinThrottleFramerate()
|
||||
{
|
||||
static HANDLE throttle_timer = nullptr;
|
||||
static int64_t PCBase, PCFrameTime, PCFrameTimeNTSC, PCFrameTimePAL, PCStart, PCEnd;
|
||||
|
||||
if (Settings.SkipFrames != AUTO_FRAMERATE)
|
||||
return;
|
||||
|
||||
if (!throttle_timer)
|
||||
{
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *)&PCBase);
|
||||
|
||||
PCFrameTimeNTSC = (int64_t)(PCBase / NTSC_PROGRESSIVE_FRAME_RATE);
|
||||
PCFrameTimePAL = (int64_t)(PCBase / PAL_PROGRESSIVE_FRAME_RATE);
|
||||
|
||||
throttle_timer = CreateWaitableTimer(NULL, true, NULL);
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&PCStart);
|
||||
}
|
||||
|
||||
if (Settings.PAL)
|
||||
PCFrameTime = PCBase / PAL_PROGRESSIVE_FRAME_RATE;
|
||||
else
|
||||
PCFrameTime = PCBase / NTSC_PROGRESSIVE_FRAME_RATE;
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&PCEnd);
|
||||
int64_t time_left_us = ((PCFrameTime - (PCEnd - PCStart)) * 1000000) / PCBase;
|
||||
|
||||
int64_t PCFrameTime_us = (int64_t)(PCFrameTime * 1000000.0 / PCBase);
|
||||
if (time_left_us < -PCFrameTime_us / 10)
|
||||
{
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&PCStart);
|
||||
return;
|
||||
}
|
||||
if (time_left_us > 0)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -time_left_us * 10;
|
||||
SetWaitableTimer(throttle_timer, &li, 0, NULL, NULL, false);
|
||||
WaitForSingleObject(throttle_timer, INFINITE);
|
||||
}
|
||||
PCStart += PCFrameTime;
|
||||
}
|
||||
|
||||
std::vector<GLSLParam> *WinGetShaderParameters()
|
||||
{
|
||||
if (GUI.outputMethod == OPENGL)
|
||||
|
@ -42,6 +42,7 @@ char *ReadShaderFileContents(const TCHAR *filename);
|
||||
void ReduceToPath(TCHAR *filename);
|
||||
double WinGetRefreshRate();
|
||||
int WinGetAutomaticInputRate();
|
||||
void WinThrottleFramerate();
|
||||
std::vector<GLSLParam> *WinGetShaderParameters();
|
||||
std::function<void(const char*)> WinGetShaderSaveFunction();
|
||||
|
||||
|
@ -2802,35 +2802,6 @@ VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWO
|
||||
}
|
||||
}
|
||||
|
||||
bool ThrottleTimer()
|
||||
{
|
||||
bool run_frame = false;
|
||||
do_frame_adjust = false;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&PCEnd);
|
||||
|
||||
if (Settings.TurboMode || Settings.FrameAdvance || Settings.SkipFrames != AUTO_FRAMERATE
|
||||
#ifdef NETPLAY_SUPPORT
|
||||
|| Settings.NetPlay
|
||||
#endif
|
||||
)
|
||||
{
|
||||
PCStart = PCEnd;
|
||||
return true;
|
||||
}
|
||||
|
||||
while ((PCEnd - PCStart) >= PCFrameTime)
|
||||
{
|
||||
if ((PCEnd - PCStart) >= (PCFrameTime * 2))
|
||||
do_frame_adjust = true;
|
||||
|
||||
run_frame = true;
|
||||
|
||||
PCStart += PCFrameTime;
|
||||
}
|
||||
|
||||
return run_frame;
|
||||
}
|
||||
|
||||
static void EnsureInputDisplayUpdated()
|
||||
{
|
||||
if(GUI.FrameAdvanceJustPressed==1 && Settings.Paused && Settings.DisplayPressedKeys==2 && GUI.ControllerOption != SNES_JOYPAD && GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MULTIPLAYER8)
|
||||
@ -3369,8 +3340,6 @@ int WINAPI WinMain(
|
||||
|
||||
MSG msg;
|
||||
|
||||
HANDLE throttle_timer = CreateWaitableTimer(NULL, true, NULL);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
EnsureInputDisplayUpdated();
|
||||
@ -3443,43 +3412,32 @@ int WINAPI WinMain(
|
||||
if(GUI.FrameAdvanceJustPressed)
|
||||
GUI.FrameAdvanceJustPressed--;
|
||||
|
||||
if(ThrottleTimer())
|
||||
{
|
||||
ProcessInput();
|
||||
ProcessInput();
|
||||
|
||||
if(GUI.rewindBufferSize
|
||||
if (GUI.rewindBufferSize
|
||||
#ifdef NETPLAY_SUPPORT
|
||||
&&!Settings.NetPlay
|
||||
&& !Settings.NetPlay
|
||||
#endif
|
||||
) {
|
||||
if(Settings.Rewinding) {
|
||||
Settings.Rewinding = stateMan.pop();
|
||||
} else {
|
||||
if(IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0)
|
||||
stateMan.push();
|
||||
}
|
||||
}
|
||||
|
||||
S9xMainLoop();
|
||||
GUI.FrameCount++;
|
||||
if (GUI.CursorTimer)
|
||||
{
|
||||
if (--GUI.CursorTimer == 0)
|
||||
{
|
||||
if (GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_JUSTIFIER && GUI.ControllerOption != SNES_JUSTIFIER_2 && GUI.ControllerOption != SNES_MACSRIFLE)
|
||||
SetCursor(NULL);
|
||||
}
|
||||
) {
|
||||
if (Settings.Rewinding) {
|
||||
Settings.Rewinding = stateMan.pop();
|
||||
}
|
||||
else {
|
||||
if (IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0)
|
||||
stateMan.push();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto time_left = ((PCFrameTime - (PCEnd - PCStart)) * 100000 / PCBase);
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -time_left;
|
||||
SetWaitableTimer(throttle_timer, &li, 0, NULL, NULL, false);
|
||||
WaitForSingleObject(throttle_timer, INFINITE);
|
||||
}
|
||||
|
||||
S9xMainLoop();
|
||||
GUI.FrameCount++;
|
||||
if (GUI.CursorTimer)
|
||||
{
|
||||
if (--GUI.CursorTimer == 0)
|
||||
{
|
||||
if (GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_JUSTIFIER && GUI.ControllerOption != SNES_JUSTIFIER_2 && GUI.ControllerOption != SNES_MACSRIFLE)
|
||||
SetCursor(NULL);
|
||||
}
|
||||
}
|
||||
#ifdef NETPLAY_SUPPORT
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user