//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #include "Managers/BsRenderStateManager.h" #include "RenderAPI/BsSamplerState.h" #include "RenderAPI/BsDepthStencilState.h" #include "RenderAPI/BsRasterizerState.h" #include "RenderAPI/BsBlendState.h" namespace bs { SPtr RenderStateManager::createSamplerState(const SAMPLER_STATE_DESC& desc) const { SPtr state = _createSamplerStatePtr(desc); state->initialize(); return state; } SPtr RenderStateManager::createDepthStencilState(const DEPTH_STENCIL_STATE_DESC& desc) const { SPtr state = _createDepthStencilStatePtr(desc); state->initialize(); return state; } SPtr RenderStateManager::createRasterizerState(const RASTERIZER_STATE_DESC& desc) const { SPtr state = _createRasterizerStatePtr(desc); state->initialize(); return state; } SPtr RenderStateManager::createBlendState(const BLEND_STATE_DESC& desc) const { SPtr state = _createBlendStatePtr(desc); state->initialize(); return state; } SPtr RenderStateManager::createGraphicsPipelineState(const PIPELINE_STATE_DESC& desc) const { SPtr state = _createGraphicsPipelineState(desc); state->initialize(); return state; } SPtr RenderStateManager::createComputePipelineState(const SPtr& program) const { SPtr state = _createComputePipelineState(program); state->initialize(); return state; } SPtr RenderStateManager::_createSamplerStatePtr(const SAMPLER_STATE_DESC& desc) const { SPtr samplerState = bs_core_ptr(new (bs_alloc()) SamplerState(desc)); samplerState->_setThisPtr(samplerState); return samplerState; } SPtr RenderStateManager::_createDepthStencilStatePtr(const DEPTH_STENCIL_STATE_DESC& desc) const { SPtr depthStencilState = bs_core_ptr(new (bs_alloc()) DepthStencilState(desc)); depthStencilState->_setThisPtr(depthStencilState); return depthStencilState; } SPtr RenderStateManager::_createRasterizerStatePtr(const RASTERIZER_STATE_DESC& desc) const { SPtr rasterizerState = bs_core_ptr(new (bs_alloc()) RasterizerState(desc)); rasterizerState->_setThisPtr(rasterizerState); return rasterizerState; } SPtr RenderStateManager::_createBlendStatePtr(const BLEND_STATE_DESC& desc) const { SPtr blendState = bs_core_ptr(new (bs_alloc()) BlendState(desc)); blendState->_setThisPtr(blendState); return blendState; } SPtr RenderStateManager::_createGraphicsPipelineState(const PIPELINE_STATE_DESC& desc) const { SPtr pipelineState = bs_core_ptr(new (bs_alloc()) GraphicsPipelineState(desc)); pipelineState->_setThisPtr(pipelineState); return pipelineState; } SPtr RenderStateManager::_createComputePipelineState(const SPtr& program) const { SPtr pipelineState = bs_core_ptr(new (bs_alloc()) ComputePipelineState(program)); pipelineState->_setThisPtr(pipelineState); return pipelineState; } const SPtr& RenderStateManager::getDefaultSamplerState() const { if(mDefaultSamplerState == nullptr) mDefaultSamplerState = createSamplerState(SAMPLER_STATE_DESC()); return mDefaultSamplerState; } const SPtr& RenderStateManager::getDefaultBlendState() const { if(mDefaultBlendState == nullptr) mDefaultBlendState = createBlendState(BLEND_STATE_DESC()); return mDefaultBlendState; } const SPtr& RenderStateManager::getDefaultRasterizerState() const { if(mDefaultRasterizerState == nullptr) mDefaultRasterizerState = createRasterizerState(RASTERIZER_STATE_DESC()); return mDefaultRasterizerState; } const SPtr& RenderStateManager::getDefaultDepthStencilState() const { if(mDefaultDepthStencilState == nullptr) mDefaultDepthStencilState = createDepthStencilState(DEPTH_STENCIL_STATE_DESC()); return mDefaultDepthStencilState; } namespace ct { RenderStateManager::RenderStateManager() :mNextBlendStateId(0), mNextRasterizerStateId(0), mNextDepthStencilStateId(0) { } SPtr RenderStateManager::createSamplerState(const SAMPLER_STATE_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr state = findCachedState(desc); if (state == nullptr) { state = createSamplerStateInternal(desc, deviceMask); state->initialize(); notifySamplerStateCreated(desc, state); } return state; } SPtr RenderStateManager::createDepthStencilState(const DEPTH_STENCIL_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createDepthStencilStateInternal(desc, id); state->initialize(); CachedDepthStencilState cachedData(id); cachedData.state = state; notifyDepthStencilStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::createRasterizerState(const RASTERIZER_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createRasterizerStateInternal(desc, id); state->initialize(); CachedRasterizerState cachedData(id); cachedData.state = state; notifyRasterizerStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::createBlendState(const BLEND_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createBlendStateInternal(desc, id); state->initialize(); CachedBlendState cachedData(id); cachedData.state = state; notifyBlendStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::createGraphicsPipelineState(const PIPELINE_STATE_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr state = _createGraphicsPipelineState(desc, deviceMask); state->initialize(); return state; } SPtr RenderStateManager::createComputePipelineState(const SPtr& program, GpuDeviceFlags deviceMask) const { SPtr state = _createComputePipelineState(program, deviceMask); state->initialize(); return state; } SPtr RenderStateManager::createPipelineParamInfo( const GPU_PIPELINE_PARAMS_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr paramInfo = _createPipelineParamInfo(desc, deviceMask); paramInfo->initialize(); return paramInfo; } SPtr RenderStateManager::_createSamplerState(const SAMPLER_STATE_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr state = findCachedState(desc); if (state == nullptr) { state = createSamplerStateInternal(desc, deviceMask); notifySamplerStateCreated(desc, state); } return state; } SPtr RenderStateManager::_createDepthStencilState(const DEPTH_STENCIL_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createDepthStencilStateInternal(desc, id); CachedDepthStencilState cachedData(id); cachedData.state = state; notifyDepthStencilStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::_createRasterizerState(const RASTERIZER_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createRasterizerStateInternal(desc, id); CachedRasterizerState cachedData(id); cachedData.state = state; notifyRasterizerStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::_createBlendState(const BLEND_STATE_DESC& desc) const { UINT32 id = 0; SPtr state = findCachedState(desc, id); if (state == nullptr) { state = createBlendStateInternal(desc, id); CachedBlendState cachedData(id); cachedData.state = state; notifyBlendStateCreated(desc, cachedData); } return state; } SPtr RenderStateManager::_createGraphicsPipelineState(const PIPELINE_STATE_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr pipelineState = bs_shared_ptr(new (bs_alloc()) GraphicsPipelineState(desc, deviceMask)); pipelineState->_setThisPtr(pipelineState); return pipelineState; } SPtr RenderStateManager::_createComputePipelineState(const SPtr& program, GpuDeviceFlags deviceMask) const { SPtr pipelineState = bs_shared_ptr(new (bs_alloc()) ComputePipelineState(program, deviceMask)); pipelineState->_setThisPtr(pipelineState); return pipelineState; } SPtr RenderStateManager::_createPipelineParamInfo( const GPU_PIPELINE_PARAMS_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr paramInfo = bs_shared_ptr(new (bs_alloc()) GpuPipelineParamInfo(desc, deviceMask)); paramInfo->_setThisPtr(paramInfo); return paramInfo; } void RenderStateManager::onShutDown() { mDefaultBlendState = nullptr; mDefaultDepthStencilState = nullptr; mDefaultRasterizerState = nullptr; mDefaultSamplerState = nullptr; } const SPtr& RenderStateManager::getDefaultSamplerState() const { if (mDefaultSamplerState == nullptr) mDefaultSamplerState = createSamplerState(SAMPLER_STATE_DESC()); return mDefaultSamplerState; } const SPtr& RenderStateManager::getDefaultBlendState() const { if (mDefaultBlendState == nullptr) mDefaultBlendState = createBlendState(BLEND_STATE_DESC()); return mDefaultBlendState; } const SPtr& RenderStateManager::getDefaultRasterizerState() const { if (mDefaultRasterizerState == nullptr) mDefaultRasterizerState = createRasterizerState(RASTERIZER_STATE_DESC()); return mDefaultRasterizerState; } const SPtr& RenderStateManager::getDefaultDepthStencilState() const { if (mDefaultDepthStencilState == nullptr) mDefaultDepthStencilState = createDepthStencilState(DEPTH_STENCIL_STATE_DESC()); return mDefaultDepthStencilState; } void RenderStateManager::notifySamplerStateCreated(const SAMPLER_STATE_DESC& desc, const SPtr& state) const { Lock lock(mMutex); mCachedSamplerStates[desc] = state; } void RenderStateManager::notifyBlendStateCreated(const BLEND_STATE_DESC& desc, const CachedBlendState& state) const { Lock lock(mMutex); mCachedBlendStates[desc] = state; } void RenderStateManager::notifyRasterizerStateCreated(const RASTERIZER_STATE_DESC& desc, const CachedRasterizerState& state) const { Lock lock(mMutex); mCachedRasterizerStates[desc] = state; } void RenderStateManager::notifyDepthStencilStateCreated(const DEPTH_STENCIL_STATE_DESC& desc, const CachedDepthStencilState& state) const { Lock lock(mMutex); mCachedDepthStencilStates[desc] = state; } void RenderStateManager::notifySamplerStateDestroyed(const SAMPLER_STATE_DESC& desc) const { Lock lock(mMutex); mCachedSamplerStates.erase(desc); } SPtr RenderStateManager::findCachedState(const SAMPLER_STATE_DESC& desc) const { Lock lock(mMutex); auto iterFind = mCachedSamplerStates.find(desc); if (iterFind != mCachedSamplerStates.end()) return iterFind->second.lock(); return nullptr; } SPtr RenderStateManager::findCachedState(const BLEND_STATE_DESC& desc, UINT32& id) const { Lock lock(mMutex); auto iterFind = mCachedBlendStates.find(desc); if (iterFind != mCachedBlendStates.end()) { id = iterFind->second.id; if (!iterFind->second.state.expired()) return iterFind->second.state.lock(); return nullptr; } id = mNextBlendStateId++; assert(id <= 0x3FF); // 10 bits maximum return nullptr; } SPtr RenderStateManager::findCachedState(const RASTERIZER_STATE_DESC& desc, UINT32& id) const { Lock lock(mMutex); auto iterFind = mCachedRasterizerStates.find(desc); if (iterFind != mCachedRasterizerStates.end()) { id = iterFind->second.id; if (!iterFind->second.state.expired()) return iterFind->second.state.lock(); return nullptr; } id = mNextRasterizerStateId++; assert(id <= 0x3FF); // 10 bits maximum return nullptr; } SPtr RenderStateManager::findCachedState(const DEPTH_STENCIL_STATE_DESC& desc, UINT32& id) const { Lock lock(mMutex); auto iterFind = mCachedDepthStencilStates.find(desc); if (iterFind != mCachedDepthStencilStates.end()) { id = iterFind->second.id; if (!iterFind->second.state.expired()) return iterFind->second.state.lock(); return nullptr; } id = mNextDepthStencilStateId++; assert(id <= 0x3FF); // 10 bits maximum return nullptr; } SPtr RenderStateManager::createSamplerStateInternal(const SAMPLER_STATE_DESC& desc, GpuDeviceFlags deviceMask) const { SPtr state = bs_shared_ptr(new (bs_alloc()) SamplerState(desc, deviceMask)); state->_setThisPtr(state); return state; } SPtr RenderStateManager::createDepthStencilStateInternal(const DEPTH_STENCIL_STATE_DESC& desc, UINT32 id) const { SPtr state = bs_shared_ptr(new (bs_alloc()) DepthStencilState(desc, id)); state->_setThisPtr(state); return state; } SPtr RenderStateManager::createRasterizerStateInternal(const RASTERIZER_STATE_DESC& desc, UINT32 id) const { SPtr state = bs_shared_ptr(new (bs_alloc()) RasterizerState(desc, id)); state->_setThisPtr(state); return state; } SPtr RenderStateManager::createBlendStateInternal(const BLEND_STATE_DESC& desc, UINT32 id) const { SPtr state = bs_shared_ptr(new (bs_alloc()) BlendState(desc, id)); state->_setThisPtr(state); return state; } } }