void CClientTools::StartRecording(wchar_t const * fileName) { EndRecording(); m_Recording = true; Dictionary_Clear(); m_File = 0; m_HiddenFileOffset = 0; m_Hidden.clear(); _wfopen_s(&m_File, fileName, L"wb"); if (m_File) { fputs("afxGameRecord", m_File); fputc('\0', m_File); int version = 4; fwrite(&version, sizeof(version), 1, m_File); } else Tier0_Warning("ERROR opening file \"%s\" for writing.\n", fileName); if (!EnableRecordingMode_get() && !SuppotsAutoEnableRecordingMode()) { Tier0_Warning( "WARNING: The recording needs to be enabled with [...] enabled 1 before loading the demo!\n" "(This is required, because this game leaks memory when recording mode is enabled.)\n" "Enabling the recording (but it might be too late already).\n" ); EnableRecordingMode_set(true); } }
void QVX_Sim::EndSim() { StopSim = true; SimThread.wait(); //wait until it actually exits... EndRecording(); //stops any recording we may have running VoxMesh.Clear(); ReqGLUpdate(); }
// Queue management functions void DeviceVulkanw::Flush( std::uint32_t queue ) { if(false == m_is_command_buffer_recording) { StartRecording(); } EndRecording(true, nullptr); }
ECode CPicture::Draw( /* [in] */ ICanvas* canvas) { Boolean is = FALSE; if (canvas->IsHardwareAccelerated(&is), is) { // throw new IllegalArgumentException( // "Picture playback is only supported on software canvas."); return E_ILLEGAL_ARGUMENT_EXCEPTION; } if (mRecordingCanvas != NULL) { EndRecording(); } NativeDraw(((Canvas*)canvas)->mNativeCanvas, mNativePicture); return NOERROR; }
void QVX_Sim::ResetSim() { EndRecording(); //stops any recording we may have running ResetSimulation(); ReqGLUpdate(); }
void QVX_Sim::CatchInternalSimEnding(QString Msg) { EndRecording(); ReqGLUpdate(); if (Msg != "") QMessageBox::warning(NULL, "Simulation Error", Msg); }
// WINDOWS MAIN FUNCTION // hInst = current instance of the program // hPrevInst = previous instance which is not used anymore. // cmdLine = holds command line arguments to be passed in to the program // cmdShow = holds an integer to specify if we want to show this window. int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int cmdShow) { WNDCLASS wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = hInst; wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = wndClassName; wc.hCursor = 0; //TODO: Add cursors and icons to this program. wc.hIcon = 0; wc.lpfnWndProc = (WNDPROC)wndProc; RegisterClass(&wc); HWND window = CreateWindow(wndClassName, wndTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, wndWidth, wndHeight, 0, 0, hInst, 0); if(window) { ShowWindow(window, SW_SHOW); UpdateWindow(window); // NOTE: Initializing SDL if(SDL_Init(SDL_INIT_VIDEO) != 0 ) { DestroyWindow(window); return -2; } IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG); sdlWindow = SDL_CreateWindowFrom((void*)window); char error[MAX_PATH]; stringCopy(error, SDL_GetError()); OutputDebugStringA(error); if(!sdlWindow) { SDL_Quit(); DestroyWindow(window); return -3; } renderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if(!renderer) { SDL_DestroyWindow(sdlWindow); SDL_Quit(); DestroyWindow(window); return -4; } i32 RefreshRate = 0; HDC dc = GetDC(window); i32 winRefreshRate = GetDeviceCaps(dc, VREFRESH); if( winRefreshRate > 1 ) { RefreshRate = winRefreshRate / 2; } else { RefreshRate = 30; } r32 targetSecsPerFrame = 1.0f / RefreshRate; GameMemory memory = {}; memory.permanentSize = Megabytes(64); memory.transientSize = Megabytes(64); memory.totalSize = memory.permanentSize + memory.transientSize; gameMemoryBlock = VirtualAlloc( 0, memory.totalSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(!gameMemoryBlock) { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(sdlWindow); SDL_Quit(); DestroyWindow(window); return -5; } memory.permanentBlock = gameMemoryBlock; memory.transientBlock = (i8*)gameMemoryBlock + memory.permanentSize; memory.readEntireFile = ReadEntireFile; memory.freeFile = FreeFile; memory.writeEntireFile = WriteEntireFile; Win32Dims windowDims = GetWindowDimensions(window); Render render = {}; render.renderer = renderer; render.screenW = windowDims.width; render.screenH = windowDims.height; GameController input = {0}; input.dt = targetSecsPerFrame; Win32State state = {0}; state.memoryBlock = gameMemoryBlock; state.memorySize = memory.totalSize; GameCodeDLL gameCode = Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp"); isRunning = true; r32 sleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR); LARGE_INTEGER lastCounter = Win32GetClock(); i64 lastCycles = __rdtsc(); LARGE_INTEGER performanceFreqPerSecRes; QueryPerformanceFrequency(&performanceFreqPerSecRes); globalPerformanceCountFreq = performanceFreqPerSecRes.QuadPart; // NOTE: PROGRAM LOOP!! while(isRunning) { // NOTE: compare File times for us to be able to reload the new game code FILETIME currentFileTime = Win32GetLastWriteTime("Game.dll"); if(CompareFileTime(¤tFileTime, &gameCode.lastWriteTime) != 0) { Win32UnloadGameCode(&gameCode); gameCode = Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp"); } MSG msg = {0}; while(PeekMessage(&msg, window, 0, 0, PM_REMOVE)) { switch(msg.message) { case WM_CLOSE: { isRunning = false; }break; case WM_KEYUP: case WM_KEYDOWN: case WM_SYSKEYUP: case WM_SYSKEYDOWN: { u32 vkCode = (u32)msg.wParam; // This contains the keycode for the key that the user pressed. bool isDown = ((msg.lParam & (1 << 31)) == 0); // Check to see if the key is down now. bool wasDown = ((msg.lParam & (1 << 30)) != 0); // Check to see if the key was down previously. if(isDown != wasDown) { if(vkCode == 'W') { input.moveUp.isDown = isDown; } else if(vkCode == 'S') { input.moveDown.isDown = isDown; } else if(vkCode == 'A') { input.moveLeft.isDown = isDown; } else if(vkCode == 'D') { input.moveRight.isDown = isDown; } if(vkCode == VK_UP) { input.actionUp.isDown = isDown; } else if(vkCode == VK_DOWN) { input.actionDown.isDown = isDown; } else if(vkCode == VK_LEFT) { input.actionLeft.isDown = isDown; } else if(vkCode == VK_RIGHT) { input.actionRight.isDown = isDown; } else if(vkCode == VK_ESCAPE) { input.back.isDown = isDown; } else if(vkCode == 'O') { if(isDown) { if(state.recordingIndex == 0) { BeginRecording(&state, 1); } else { EndRecording(&state); BeginPlayback(&state, 1); } } } else if(vkCode == 'P') { if(isDown) { if(state.playbackIndex > 0) { EndPlayback(&state); ZeroMemory(&input, sizeof(input)); } } } } if(isDown) { bool AltKeyWasDown = ((msg.lParam & (1 << 29)) != 0); if(vkCode == VK_RETURN && AltKeyWasDown) { if(msg.hwnd) { isFullscreen = !isFullscreen; Win32FullscreenToggle(msg.hwnd); } } } }break; default: { TranslateMessage(&msg); DispatchMessage(&msg); } } } if(input.back.isDown) { isRunning = false; PostQuitMessage(0); } if(state.recordingIndex > 0) { RecordingInput(&state, &input); } else if(state.playbackIndex > 0) { PlaybackInput(&state, &input); } Win32Dims windowDims = GetWindowDimensions(window); Win32UpdateWindow(windowDims, (i32*)&render.screenW, (i32*)&render.screenH); if(gameCode.UpdateRender) { gameCode.UpdateRender(&memory, &input, &render); } LARGE_INTEGER workCounter = Win32GetClock(); r32 workSecsElapsed = Win32GetSecondsElapsed(lastCounter, workCounter); r32 secondsElapsed = workSecsElapsed; if(secondsElapsed < targetSecsPerFrame) { if(sleepIsGranular) { DWORD sleepMS = (DWORD)(1000.0f * (targetSecsPerFrame - secondsElapsed)); if(sleepMS > 0) { Sleep(sleepMS); } } r32 testSecsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock()); if(testSecsElapsed < targetSecsPerFrame) { //TODO: LOG MISSED SLEEP HERE!! } while(secondsElapsed < targetSecsPerFrame) { secondsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock()); } } else { //TODO: MISSED FRAME RATE!! } LARGE_INTEGER endCounter = Win32GetClock(); i64 endCycles = __rdtsc(); r64 elapsedCounts = (r64)(endCounter.QuadPart - lastCounter.QuadPart); r64 elapsedCycles = (r64)(endCycles - lastCycles); r32 MSperFrame = ((1000.0f * Win32GetSecondsElapsed(lastCounter, endCounter))); r32 FPS = (r32)(globalPerformanceCountFreq / elapsedCounts); r32 MegaCyclesPerFrame = (r32)(elapsedCycles / (1000.0f * 1000.0f)); char buffer[256]; sprintf_s(buffer, "%.02fms, %.02ffps, %.02fmcpf\n", MSperFrame, FPS, MegaCyclesPerFrame); OutputDebugStringA(buffer); lastCounter = endCounter; lastCycles = endCycles; } // NOTE: END OF WHILE LOOP //IMPORTANT: Unload this when we exit the program. Win32UnloadGameCode(&gameCode); } else { // TODO: Handle Error Loggin here!! return -1; } if(gameMemoryBlock) { VirtualFree(gameMemoryBlock, 0, MEM_RELEASE); } //Close SDL_DestroyRenderer(renderer); SDL_DestroyWindow(sdlWindow); IMG_Quit(); SDL_Quit(); DestroyWindow(window); return 0; }
// Execution Not thread safe void DeviceVulkanw::Execute( Function const* func, std::uint32_t queue, size_t global_size, size_t local_size, Event** e ) { FunctionVulkan* vulkan_function = ConstCast<FunctionVulkan>( func ); uint32_t number_of_parameters = (uint32_t)( vulkan_function->GetParameters().size() ); // get the Function's descriptor set group Anvil::DescriptorSetGroup* new_descriptor_set = vulkan_function->GetDescriptorSetGroup(); // if it's empty, this is 1st run of the Function so we have to create it if ( nullptr == new_descriptor_set ) { // allocate it through Anvil new_descriptor_set = new Anvil::DescriptorSetGroup( m_anvil_device, false, 1 ); // add bindings and items (Buffers) to the new DSG for ( uint32_t i = 0; i < number_of_parameters; ++i ) { const Buffer* parameter = vulkan_function->GetParameters()[ i ]; BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter ); new_descriptor_set->add_binding( 0, i, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT ); } // set it to the Function to be reused during any subsequent run vulkan_function->SetDescriptorSetGroup( new_descriptor_set ); } // bind new items (Buffers), releasing the old ones for ( uint32_t i = 0; i < number_of_parameters; ++i ) { const Buffer* parameter = vulkan_function->GetParameters()[ i ]; BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter ); new_descriptor_set->set_binding_item( 0, i, buffer->GetAnvilBuffer() ); } // get the Function's pipeline Anvil::ComputePipelineID pipeline_id = vulkan_function->GetPipelineID(); // if it is invalid, this is 1st run of the Function so we have to create it if ( ~0u == pipeline_id ) { // create the pipeline through Anvil with the shader module as a parameter m_anvil_device->get_compute_pipeline_manager()->add_regular_pipeline( false, false, vulkan_function->GetFunctionEntryPoint(), &pipeline_id ); // attach the DSG to it m_anvil_device->get_compute_pipeline_manager()->attach_dsg_to_pipeline( pipeline_id, new_descriptor_set ); // remember the pipeline for any seubsequent run vulkan_function->SetPipelineID( pipeline_id ); } // indicate we'll be recording Vulkan commands to the CommandBuffer from now on StartRecording(); // attach pipeline m_command_buffer->record_bind_pipeline( VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_id ); Anvil::PipelineLayout* pipeline_layout = m_anvil_device->get_compute_pipeline_manager()->get_compute_pipeline_layout( pipeline_id ); Anvil::DescriptorSet* descriptor_set = new_descriptor_set->get_descriptor_set( 0 ); // attach layout and 0 descriptor set (we don't use any other set currently) m_command_buffer->record_bind_descriptor_sets( VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr ); // set memory barriers for ( uint32_t i = 0; i < number_of_parameters; ++i ) { const Buffer* parameter = vulkan_function->GetParameters()[ i ]; BufferVulkan* buffer = ConstCast<BufferVulkan>( parameter ); Anvil::BufferBarrier bufferBarrier( VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, GetQueue()->get_queue_family_index(), GetQueue()->get_queue_family_index(), buffer->GetAnvilBuffer(), 0, buffer->GetSize() ); m_command_buffer->record_pipeline_barrier( VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_FALSE, 0, nullptr, 1, &bufferBarrier, 0, nullptr ); // tell buffer that we are used by this submit buffer->SetFenceId( GetFenceId() ); } // dispatch the Function's shader module m_command_buffer->record_dispatch( (uint32_t)global_size, 1, 1 ); // end recording EndRecording( false, e ); // remove references to buffers. they were already referenced by the CommandBuffer. vulkan_function->UnreferenceParametersBuffers(); }