/*---------------------------------------------------------------------------* Project: NintendoWare File : demo_CommandListSwapper.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 23208 $ *---------------------------------------------------------------------------*/ #include #include #include #include namespace nw { namespace demo { CommandListSwapper* CommandListSwapper::s_CommandListSwapper = NULL; //---------------------------------------- CommandListSwapper* CommandListSwapper::Create( os::IAllocator* allocator, CommandListSwapper::Description& description) { void* memory = allocator->Alloc(sizeof(CommandListSwapper)); NW_NULL_ASSERT(memory); CommandListSwapper* swapper = new(memory) CommandListSwapper(allocator, description); return swapper; } //---------------------------------------- CommandListSwapper::CommandListSwapper( os::IAllocator* allocator, CommandListSwapper::Description& description) : m_Allocator(allocator), m_CommandLists(description.commandListCount, allocator), m_BoundIndex(0), m_RunningIndex(0), m_IsRunning(false), m_GpuProfilingEntries(description.maxGpuProfilingEntryCount, allocator), m_GpuProfilingResults(description.maxGpuProfilingEntryCount, allocator), m_ReusableCommandLists(), m_ReusableBufferOffset(0), m_ReusableBufferSize(0), m_ReusableRequestId(0), m_ReusableRequestSize(0) { m_CommandLists.resize(description.commandListCount); CommandListArray::iterator listEnd = m_CommandLists.end(); for (CommandListArray::iterator commandList = m_CommandLists.begin(); commandList != listEnd; ++commandList) { nngxGenCmdlists(1, &(*commandList)); nngxBindCmdlist(*commandList); nngxCmdlistStorage(description.bufferSize, description.requestCount); nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN); nngxSetCmdlistCallback(CommandListSwapper::CommandListCallback); } if (description.reusableBufferSize > 0 && description.reusableRequestCount > 0) { m_ReusableCommandLists = CommandListArray(description.commandListCount, allocator), m_ReusableCommandLists.resize(description.commandListCount); CommandListArray::iterator cacheEnd = m_ReusableCommandLists.end(); for (CommandListArray::iterator commandList = m_ReusableCommandLists.begin(); commandList != cacheEnd; ++commandList) { nngxGenCmdlists(1, &(*commandList)); nngxBindCmdlist(*commandList); nngxCmdlistStorage(description.reusableBufferSize, description.reusableRequestCount); nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN); } } s_CommandListSwapper = this; } //---------------------------------------- void CommandListSwapper::Destroy() { os::IAllocator* allocator = this->m_Allocator; void* memory = static_cast(this); this->~CommandListSwapper(); allocator->Free(memory); } //---------------------------------------- void CommandListSwapper::Bind() { nngxBindCmdlist(this->GetCommandListId()); } //---------------------------------------- void CommandListSwapper::RunAsync() { m_GpuProfilingEntries.swap( m_GpuProfilingResults ); m_RunningIndex = m_BoundIndex; m_IsRunning = true; if (! nw::demo::DebugUtility::IsCpuProfilingMode()) { nngxRunCmdlist(); } } //---------------------------------------- void CommandListSwapper::Swap() { ++this->m_BoundIndex; if (this->m_CommandLists.size() <= this->m_BoundIndex) { this->m_BoundIndex = 0; } if (this->m_CommandLists.size() > 1) { ResetGpuProfiling(); } } //---------------------------------------- void CommandListSwapper::WaitDone() { if (!m_IsRunning) { return; } nngxBindCmdlist(m_CommandLists[m_RunningIndex]); nngxSplitDrawCmdlist(); nngxWaitCmdlistDone(); nngxStopCmdlist(); nngxClearCmdlist(); Bind(); m_IsRunning = false; CalcGpuProfilingCostTime(); if (this->m_CommandLists.size() == 1) { ResetGpuProfiling(); } } //---------------------------------------- void CommandListSwapper::ResetGpuProfiling() { m_GpuProfilingEntries.clear(); } //---------------------------------------- s32 CommandListSwapper::AddGpuProfilingStartPoint(bool IsInTotal) { if (!m_GpuProfilingEntries.push_back( GpuProfilingEntry() )) { return -1; } GpuProfilingEntry& gpuProfilingEntry = m_GpuProfilingEntries.back(); GLuint id = RegisterCallback(); gpuProfilingEntry.beginId = id; gpuProfilingEntry.isInTotal = IsInTotal; return m_GpuProfilingEntries.size() - 1; } //---------------------------------------- void CommandListSwapper::SetGpuProfilingEndPoint(u32 profilingId) { NW_ASSERT(profilingId < m_GpuProfilingEntries.size()); m_GpuProfilingEntries[profilingId].endId = RegisterCallback(); } //---------------------------------------- GLuint CommandListSwapper::RegisterCallback() { GLint requestCount = 0; nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_REQCOUNT, &requestCount); if (requestCount == 0) { // コマンドリクエストが無い場合はコマンドバッファを区切ることでコマンドリクエストを追加する。 nngxSplitDrawCmdlist(); nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_REQCOUNT, &requestCount); } nngxEnableCmdlistCallback( requestCount ); return requestCount; } //---------------------------------------- void CommandListSwapper::CalcGpuProfilingCostTime() { GpuProfilingEntryArray::iterator end = m_GpuProfilingResults.end(); for (GpuProfilingEntryArray::iterator gpuProfilingEntry = m_GpuProfilingResults.begin(); gpuProfilingEntry != end; ++gpuProfilingEntry) { const s64 span = nn::os::Tick(gpuProfilingEntry->endTick - gpuProfilingEntry->beginTick) .ToTimeSpan() .GetMicroSeconds(); gpuProfilingEntry->costTime = static_cast(span) / 1000.0f; } } //---------------------------------------- f32 CommandListSwapper::GetGpuProfilingCostTime(u32 profilingId) { if (profilingId < m_GpuProfilingResults.size()) { return m_GpuProfilingResults[profilingId].costTime; } else { return 0.0f; } } //---------------------------------------- f32 CommandListSwapper::GetGpuProfilingTotalCostTime() { f32 total = 0.0f; GpuProfilingEntryArray::iterator end = m_GpuProfilingResults.end(); for (GpuProfilingEntryArray::iterator gpuProfilingEntry = m_GpuProfilingResults.begin(); gpuProfilingEntry != end; ++gpuProfilingEntry) { if (gpuProfilingEntry->isInTotal) { total += gpuProfilingEntry->costTime; } } return total; } //---------------------------------------- void CommandListSwapper::SetGpuProfilingTick(GLint id) { s64 tick = static_cast(nn::os::Tick::GetSystemCurrent()); size_t size = m_GpuProfilingResults.size(); for (u32 i = 0 ; i < size ; ++i) { if (m_GpuProfilingResults[i].beginId == id) { m_GpuProfilingResults[i].beginTick = tick; } if (m_GpuProfilingResults[i].endId == id) { m_GpuProfilingResults[i].endTick = tick; } } } //---------------------------------------- void CommandListSwapper::CommandListCallback(GLint id) { if ( s_CommandListSwapper ) { s_CommandListSwapper->SetGpuProfilingTick(id); } } //---------------------------------------- void CommandListSwapper::StartCommandSave() { NW_ASSERT( !m_ReusableCommandLists.empty() ); nngxBindCmdlist(m_ReusableCommandLists[m_BoundIndex]); nngxClearCmdlist(); nngxStartCmdlistSave(); NW_GL_ASSERT(); } //---------------------------------------- void CommandListSwapper::EndCommandSave() { NW_ASSERT( !m_ReusableCommandLists.empty() ); nngxSplitDrawCmdlist(); NW_GL_ASSERT(); nngxStopCmdlistSave( &m_ReusableBufferOffset, &m_ReusableBufferSize, &m_ReusableRequestId, &m_ReusableRequestSize); NW_GL_ASSERT(); Bind(); } //---------------------------------------- void CommandListSwapper::ReuseCommand(bool isCopyBuffer) { NW_ASSERT( !m_ReusableCommandLists.empty() ); nngxUseSavedCmdlist( m_ReusableCommandLists[m_BoundIndex], m_ReusableBufferOffset, m_ReusableBufferSize, m_ReusableRequestId, m_ReusableRequestSize, 0, isCopyBuffer ? GL_TRUE : GL_FALSE); NW_GL_ASSERT(); } //---------------------------------------- int CommandListSwapper::GetCommandBufferSize() const { GLint bufferSize; nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, &bufferSize); NW_GL_ASSERT(); return static_cast(bufferSize); } //---------------------------------------- int CommandListSwapper::GetReusableCommandBufferSize() const { GLint bufferSize; GLint boundId; nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, &boundId); nngxBindCmdlist(m_ReusableCommandLists[m_BoundIndex]); nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, &bufferSize); nngxBindCmdlist(boundId); NW_GL_ASSERT(); return static_cast(bufferSize); } } // demo } // nw