bool WrappedOpenGL::Serialise_glShaderSource(GLuint shader, GLsizei count, const GLchar *const *source, const GLint *length) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); SERIALISE_ELEMENT(uint32_t, Count, count); vector<string> srcs; for(uint32_t i = 0; i < Count; i++) { string s; if(source && source[i]) s = (length && length[i] > 0) ? string(source[i], source[i] + length[i]) : string(source[i]); m_pSerialiser->SerialiseString("source", s); if(m_State == READING) srcs.push_back(s); } if(m_State == READING) { size_t numStrings = srcs.size(); const char **strings = new const char *[numStrings]; for(size_t i = 0; i < numStrings; i++) strings[i] = srcs[i].c_str(); ResourceId liveId = GetResourceManager()->GetLiveID(id); m_Shaders[liveId].sources.clear(); m_Shaders[liveId].sources.reserve(Count); for(uint32_t i = 0; i < Count; i++) m_Shaders[liveId].sources.push_back(strings[i]); m_Real.glShaderSource(GetResourceManager()->GetLiveResource(id).name, Count, strings, NULL); delete[] strings; } return true; }
void WrappedID3D12CommandQueue::ClearAfterCapture() { // delete cmd buffers now - had to keep them alive until after serialiser flush. for(size_t i = 0; i < m_CmdListRecords.size(); i++) m_CmdListRecords[i]->Delete(GetResourceManager()); m_CmdListRecords.clear(); m_QueueRecord->DeleteChunks(); }
bool WrappedOpenGL::Serialise_glBindProgramPipeline(GLuint pipeline) { SERIALISE_ELEMENT(ResourceId, id, (pipeline ? GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), pipeline)) : ResourceId())); if(m_State <= EXECUTING) { if(id == ResourceId()) { m_Real.glBindProgramPipeline(0); } else { GLuint live = GetResourceManager()->GetLiveResource(id).name; m_Real.glBindProgramPipeline(live); } } return true; }
// needs to be separate so we don't erase from m_ImageLayouts in other destroy functions void WrappedVulkan::vkDestroyImage(VkDevice device, VkImage obj, const VkAllocationCallbacks* pAllocator) { { SCOPED_LOCK(m_ImageLayoutsLock); m_ImageLayouts.erase(GetResID(obj)); } VkImage unwrappedObj = Unwrap(obj); GetResourceManager()->ReleaseWrappedResource(obj, true); return ObjDisp(device)->DestroyImage(Unwrap(device), unwrappedObj, pAllocator); }
bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { ResourceId liveId = GetResourceManager()->GetLiveID(id); auto &shadDetails = m_Shaders[liveId]; bool pointSizeUsed = false, clipDistanceUsed = false; if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed); GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, NULL); if(sepProg == 0) { RDCERR("Couldn't make separable program for shader via patching - functionality will be broken."); } else { shadDetails.prog = sepProg; MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv); if(!shadDetails.spirv.empty()) DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s); shadDetails.reflection.Disassembly = s; create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) { shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i); shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i]; } } m_Real.glCompileShader(GetResourceManager()->GetLiveResource(id).name); } return true; }
bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( Serialiser *localSerialiser, VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { SERIALISE_ELEMENT(ResourceId, devId, GetResID(device)); SERIALISE_ELEMENT(ResourceId, cacheId, GetResID(pipelineCache)); SERIALISE_ELEMENT(VkGraphicsPipelineCreateInfo, info, *pCreateInfos); SERIALISE_ELEMENT(ResourceId, id, GetResID(*pPipelines)); if(m_State == READING) { VkPipeline pipe = VK_NULL_HANDLE; device = GetResourceManager()->GetLiveHandle<VkDevice>(devId); // don't use pipeline caches on replay pipelineCache = VK_NULL_HANDLE; // GetResourceManager()->GetLiveHandle<VkPipelineCache>(cacheId); VkResult ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, &info, NULL, &pipe); if(ret != VK_SUCCESS) { RDCERR("Failed on resource serialise-creation, VkResult: 0x%08x", ret); } else { ResourceId live; if(GetResourceManager()->HasWrapper(ToTypedHandle(pipe))) { live = GetResourceManager()->GetNonDispWrapper(pipe)->id; // destroy this instance of the duplicate, as we must have matching create/destroy // calls and there won't be a wrapped resource hanging around to destroy this one. ObjDisp(device)->DestroyPipeline(Unwrap(device), pipe, NULL); // whenever the new ID is requested, return the old ID, via replacements. GetResourceManager()->ReplaceResource(id, GetResourceManager()->GetOriginalID(live)); } else { live = GetResourceManager()->WrapResource(Unwrap(device), pipe); GetResourceManager()->AddLiveResource(id, pipe); m_CreationInfo.m_Pipeline[live].Init(GetResourceManager(), m_CreationInfo, &info); } } } return true; }
ResourcesPage::~ResourcesPage() { ResourceManager* res = GetResourceManager(); res->onResourcePrepared.Disconnect( this, &ResourcesPage::onResourcePrepared ); res->onResourceRemoved.Disconnect( this, &ResourcesPage::onResourceRemoved ); res->onResourceLoaded.Disconnect( this, &ResourcesPage::onResourceReloaded ); res->onResourceReloaded.Disconnect( this, &ResourcesPage::onResourceReloaded ); }
bool WrappedOpenGL::Serialise_glGenSamplers(GLsizei n, GLuint *samplers) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(SamplerRes(GetCtx(), *samplers))); if(m_State == READING) { GLuint real = 0; m_Real.glGenSamplers(1, &real); m_Real.glBindSampler(0, real); m_Real.glBindSampler(0, 0); GLResource res = SamplerRes(GetCtx(), real); ResourceId live = m_ResourceManager->RegisterResource(res); GetResourceManager()->AddLiveResource(id, res); } return true; }
bool WrappedID3D12Device::Serialise_CreatePlacedResource(ID3D12Heap *pHeap, UINT64 HeapOffset, const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialState, const D3D12_CLEAR_VALUE *pOptimizedClearValue, REFIID riid, void **ppvResource) { SERIALISE_ELEMENT(ResourceId, Heap, GetResID(pHeap)); SERIALISE_ELEMENT(UINT64, Offset, HeapOffset); SERIALISE_ELEMENT(D3D12_RESOURCE_DESC, desc, *pDesc); SERIALISE_ELEMENT(D3D12_RESOURCE_STATES, state, InitialState); SERIALISE_ELEMENT(bool, HasClearValue, pOptimizedClearValue != NULL); SERIALISE_ELEMENT_OPT(D3D12_CLEAR_VALUE, clearVal, *pOptimizedClearValue, HasClearValue); SERIALISE_ELEMENT(IID, guid, riid); SERIALISE_ELEMENT(ResourceId, Res, ((WrappedID3D12Resource *)*ppvResource)->GetResourceID()); if(m_State == READING) { pHeap = GetResourceManager()->GetLiveAs<ID3D12Heap>(Heap); pOptimizedClearValue = HasClearValue ? &clearVal : NULL; ID3D12Resource *ret = NULL; HRESULT hr = m_pDevice->CreatePlacedResource(Unwrap(pHeap), Offset, &desc, state, pOptimizedClearValue, guid, (void **)&ret); if(FAILED(hr)) { RDCERR("Failed on resource serialise-creation, HRESULT: 0x%08x", hr); } else { ret = new WrappedID3D12Resource(ret, this); GetResourceManager()->AddLiveResource(Res, ret); SubresourceStateVector &states = m_ResourceStates[GetResID(ret)]; states.resize(GetNumSubresources(&desc), state); } } return true; }
Parachute::Parachute() : Weapon(WEAPON_PARACHUTE, "parachute", new ParachuteConfig(), false) { UpdateTranslationStrings(); m_category = MOVE; m_initial_nb_ammo = 2; use_unit_on_first_shoot = false; m_used_this_turn = false; img = GetResourceManager().LoadSprite(weapons_res_profile, "parachute_sprite"); }
bool WrappedOpenGL::Serialise_glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(uint64_t, offs, (uint64_t)offset); SERIALISE_ELEMENT(uint64_t, Size, (uint64_t)size); SERIALISE_ELEMENT(GLenum, fmt, internalformat); SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture))); SERIALISE_ELEMENT(ResourceId, bufid, GetResourceManager()->GetID(TextureRes(buffer))); if(m_State == READING) { m_Real.glTextureBufferRangeEXT(GetResourceManager()->GetLiveResource(texid).name, Target, fmt, GetResourceManager()->GetLiveResource(bufid).name, (GLintptr)offs, (GLsizeiptr)Size); } return true; }
bool WrappedOpenGL::Serialise_glCreateProgram(GLuint program) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program))); if(m_State == READING) { GLuint real = m_Real.glCreateProgram(); GLResource res = ProgramRes(GetCtx(), real); ResourceId liveId = m_ResourceManager->RegisterResource(res); m_Programs[liveId].linked = false; GetResourceManager()->AddLiveResource(id, res); } return true; }
MultiTabs::MultiTabs(const Point2i& size) : Widget(size) , max_visible_tabs(50) , current_tab(-1) , first_tab(0) , nb_visible_tabs(1) , tab_header_width(TAB_MIN_WIDTH) { Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml",false); prev_tab_bt = new Button(res, "menu/really_big_minus", false); next_tab_bt = new Button(res, "menu/really_big_plus", false); tab_header_height = prev_tab_bt->GetSizeY() + 4; Widget::SetBorder(defaultOptionColorRect, BORDER); Widget::SetBackgroundColor(defaultOptionColorBox); GetResourceManager().UnLoadXMLProfile(res); }
BenchItem(BenchType t, const std::string& name, uint height) : HBox(height, false, false, true /* use full height */) , type(t) { Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml", false); bench = new Label(name, 0, Font::FONT_BIG, Font::FONT_BOLD, dark_gray_color, Text::ALIGN_CENTER); AddWidget(bench); score = new Label("N/A", 300, Font::FONT_BIG, Font::FONT_BOLD, primary_red_color, Text::ALIGN_CENTER); AddWidget(score); run = new Button(res, "menu/really_big_plus", true); AddWidget(run); GetResourceManager().UnLoadXMLProfile(res); }
VkResult WrappedVulkan::vkRegisterDeviceEventEXT(VkDevice device, const VkDeviceEventInfoEXT *pDeviceEventInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) { // for now we emulate this on replay as just a regular fence create, since we don't faithfully // replay sync events anyway. VkResult ret = ObjDisp(device)->RegisterDeviceEventEXT(Unwrap(device), pDeviceEventInfo, pAllocator, pFence); if(ret == VK_SUCCESS) { ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pFence); if(m_State >= WRITING) { Chunk *chunk = NULL; { CACHE_THREAD_SERIALISER(); VkFenceCreateInfo createInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, NULL, VK_FENCE_CREATE_SIGNALED_BIT, }; SCOPED_SERIALISE_CONTEXT(CREATE_FENCE); Serialise_vkCreateFence(localSerialiser, device, &createInfo, NULL, pFence); chunk = scope.Get(); } VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pFence); record->AddChunk(chunk); } else { GetResourceManager()->AddLiveResource(id, *pFence); } } return ret; }
// **************************************************************************** // // Function Name: AskUser::InformUser( ) // // Description: Ask the user a question with an inform icon and OK // button. // Retrieve the message from a resource file. // // Returns: kAlertYes // // Exceptions: None // // **************************************************************************** // YAlertValues RAlert::AskUser( YResourceId informId ) { RMBCString string = GetResourceManager().GetResourceString( informId ); #ifdef TPSDEBUG char buffer[128]; buffer[0] = '\0'; WinCode( wsprintf( buffer, " - %d", informId ) ); string += buffer; #endif return AskUser( (LPCSZ)string ); }
// **************************************************************************** // // Function Name: RAlert::AlertUser( ) // // Description: Alert the user of a problem with an Alert and an OK button // Retrieve the message from a resource file. // // Returns: Nothing // // Exceptions: None // // **************************************************************************** // void RAlert::AlertUser( YResourceId alertId ) { RMBCString string = GetResourceManager().GetResourceString( alertId ); #ifdef TPSDEBUG char buffer[128]; buffer[0] = '\0'; WinCode( wsprintf( buffer, " - %d", alertId ) ); string += buffer; #endif AlertUser( (LPCSZ)string ); }
bool WrappedOpenGL::Serialise_glTextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(uint32_t, Levels, levels); SERIALISE_ELEMENT(GLenum, Format, internalformat); SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); if(m_State == READING) { ResourceId liveId = GetResourceManager()->GetLiveID(id); m_Textures[liveId].width = Width; m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; m_Real.glTextureStorage1DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Levels, Format, Width); } return true; }
bool WrappedOpenGL::Serialise_glGenTextures(GLsizei n, GLuint* textures) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(*textures))); if(m_State == READING) { GLuint real = 0; m_Real.glGenTextures(1, &real); GLResource res = TextureRes(real); ResourceId live = m_ResourceManager->RegisterResource(res); GetResourceManager()->AddLiveResource(id, res); m_Textures[live].resource = res; m_Textures[live].curType = eGL_UNKNOWN_ENUM; } return true; }
bool WrappedOpenGL::Serialise_glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(GLenum, InternalFormat, internalformat); SERIALISE_ELEMENT(uint32_t, MinLevel, minlevel); SERIALISE_ELEMENT(uint32_t, NumLevels, numlevels); SERIALISE_ELEMENT(uint32_t, MinLayer, minlayer); SERIALISE_ELEMENT(uint32_t, NumLayers, numlayers); SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture))); SERIALISE_ELEMENT(ResourceId, origid, GetResourceManager()->GetID(TextureRes(origtexture))); if(m_State == READING) { GLResource tex = GetResourceManager()->GetLiveResource(texid); GLResource origtex = GetResourceManager()->GetLiveResource(origid); m_Real.glTextureView(tex.name, Target, origtex.name, InternalFormat, MinLevel, NumLevels, MinLayer, NumLayers); } return true; }
bool WrappedID3D11Device::Serialise_CreateTexture2D1(const D3D11_TEXTURE2D_DESC1 *pDesc, const D3D11_SUBRESOURCE_DATA *pInitialData, ID3D11Texture2D1 **ppTexture2D) { SERIALISE_ELEMENT_PTR(D3D11_TEXTURE2D_DESC1, Descriptor, pDesc); SERIALISE_ELEMENT(ResourceId, pTexture, GetIDForResource(*ppTexture2D)); SERIALISE_ELEMENT(bool, HasInitialData, pInitialData != NULL); vector<D3D11_SUBRESOURCE_DATA> descs = Serialise_CreateTextureData( ppTexture2D ? *ppTexture2D : NULL, pTexture, pInitialData, Descriptor.Width, Descriptor.Height, 1, Descriptor.Format, Descriptor.MipLevels, Descriptor.ArraySize, HasInitialData); if(m_State == READING) { ID3D11Texture2D1 *ret = NULL; HRESULT hr = E_NOINTERFACE; TextureDisplayType dispType = DispTypeForTexture(Descriptor); // unset flags that are unimportant/problematic in replay Descriptor.MiscFlags &= ~(D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_GDI_COMPATIBLE | D3D11_RESOURCE_MISC_SHARED_NTHANDLE); if(m_pDevice3) { if(HasInitialData) hr = m_pDevice3->CreateTexture2D1(&Descriptor, &descs[0], &ret); else hr = m_pDevice3->CreateTexture2D1(&Descriptor, NULL, &ret); } else { RDCERR("Replaying a D3D11.3 device without D3D11.3 available"); } if(FAILED(hr)) { RDCERR("Failed on resource serialise-creation, HRESULT: 0x%08x", hr); } else { ret = new WrappedID3D11Texture2D1((ID3D11Texture2D1 *)ret, this, dispType); GetResourceManager()->AddLiveResource(pTexture, ret); } } for(size_t i = 0; i < descs.size(); i++) SAFE_DELETE_ARRAY(descs[i].pSysMem); return true; }
// **************************************************************************** // // Function Name: RCursor::SetCursor( ) // // Description: Set the cursor to have the given ID // // Returns: Nothing // // Exceptions: None // // **************************************************************************** // void RCursor::SetCursor( YResourceId cursorId ) { // Assume that if the cursor is the same, it is already being used if (cursorId != m_CursorId) { YResourceCursor resource = GetResourceManager().GetResourceCursor( cursorId ); if (resource != NULL) MacWinDos( ::SetCursor( resource ), ::SetCursor( resource ), xxx ); m_CursorId = cursorId; } }
void WrappedOpenGL::glBindFramebuffer(GLenum target, GLuint framebuffer) { if(m_State == WRITING_CAPFRAME) { SCOPED_SERIALISE_CONTEXT(BIND_FRAMEBUFFER); Serialise_glBindFramebuffer(target, framebuffer); m_ContextRecord->AddChunk(scope.Get()); } if(framebuffer == 0 && m_State < WRITING) framebuffer = m_FakeBB_FBO; if(target == eGL_DRAW_FRAMEBUFFER || target == eGL_FRAMEBUFFER) m_DrawFramebufferRecord = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); else m_ReadFramebufferRecord = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); m_Real.glBindFramebuffer(target, framebuffer); }
bool WrappedOpenGL::Serialise_glBindFramebuffer(GLenum target, GLuint framebuffer) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(ResourceId, Id, (framebuffer ? GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)) : ResourceId())); if(m_State <= EXECUTING) { if(Id == ResourceId()) { m_Real.glBindFramebuffer(Target, m_FakeBB_FBO); } else { GLResource res = GetResourceManager()->GetLiveResource(Id); m_Real.glBindFramebuffer(Target, res.name); } } return true; }
void WrappedOpenGL::glCompileShader(GLuint shader) { m_Real.glCompileShader(shader); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(COMPILESHADER); Serialise_glCompileShader(shader); record->AddChunk(scope.Get()); } } else { m_Shaders[GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))].Compile(*this); } }
bool WrappedOpenGL::Serialise_glCreateShader(GLuint shader, GLenum type) { SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { GLuint real = m_Real.glCreateShader(Type); GLResource res = ShaderRes(GetCtx(), real); ResourceId liveId = GetResourceManager()->RegisterResource(res); m_Shaders[liveId].type = Type; GetResourceManager()->AddLiveResource(id, res); } return true; }
bool PushViewer::InitializeUniverse() { if (!Parent::InitializeUniverse()) { return (false); } UiCure::GravelEmitter* gravel_particle_emitter = new UiCure::GravelEmitter(GetResourceManager(), ui_manager_, 0.5f, 1, 10, 2); level_ = new life::Level(GetResourceManager(), "level_01", ui_manager_, gravel_particle_emitter); AddContextObject(level_, cure::kNetworkObjectRemoteControlled, 0); level_->EnableRootShadow(false); level_->SetAllowNetworkLogic(false); level_->StartLoading(); cure::ContextObject* vehicle = new UiCure::Machine(GetResourceManager(), "monster_02", ui_manager_); GetContext()->AddLocalObject(vehicle); vehicle->SetInitialTransform(xform(kIdentityQuaternionF, vec3(-23, -80, 53))); vehicle->StartLoading(); avatar_id_ = vehicle->GetInstanceId(); GetConsoleManager()->ExecuteCommand("fork execute-file data/steering.rec"); return (true); }
Blowtorch::Blowtorch() : Weapon(WEAPON_BLOWTORCH, "blowtorch", new BlowtorchConfig()), active(false) { UpdateTranslationStrings(); m_category = TOOL; m_time_between_each_shot = MIN_TIME_BETWEEN_DIG; m_weapon_fire = new Sprite(GetResourceManager().LoadImage(weapons_res_profile, "blowtorch_fire")); m_can_change_weapon = true; }
NAMESPACE_GRAPHICS_BEGIN //-----------------------------------// TextureManager::TextureManager() { ResourceManager* res = GetResourceManager(); res->onResourceLoaded.Connect( this, &TextureManager::onLoaded ); res->onResourceRemoved.Connect( this, &TextureManager::onUnloaded ); res->onResourceReloaded.Connect( this, &TextureManager::onReloaded ); }
bool WrappedVulkan::Serialise_vkDeviceWaitIdle(Serialiser* localSerialiser, VkDevice device) { SERIALISE_ELEMENT(ResourceId, id, GetResID(device)); if(m_State < WRITING) { device = GetResourceManager()->GetLiveHandle<VkDevice>(id); ObjDisp(device)->DeviceWaitIdle(Unwrap(device)); } return true; }