#include "BsGpuParams.h" #include "BsGpuParamDesc.h" #include "BsGpuParamBlockBuffer.h" #include "BsVector2.h" #include "BsTexture.h" #include "BsSamplerState.h" #include "BsFrameAlloc.h" #include "BsDebug.h" #include "BsException.h" #include "BsVectorNI.h" #include "BsMatrixNxM.h" namespace BansheeEngine { GpuParamsBase::GpuParamsBase(const GpuParamDescPtr& paramDesc, bool transposeMatrices) :mParamDesc(paramDesc), mTransposeMatrices(transposeMatrices), mNumParamBlocks(0), mNumSamplerStates(0), mNumTextures(0), mTextureInfo(nullptr) { for (auto& paramBlock : mParamDesc->paramBlocks) { if ((paramBlock.second.slot + 1) > mNumParamBlocks) mNumParamBlocks = paramBlock.second.slot + 1; } for (auto& texture : mParamDesc->textures) { if ((texture.second.slot + 1) > mNumTextures) mNumTextures = texture.second.slot + 1; } for (auto& sampler : mParamDesc->samplers) { if ((sampler.second.slot + 1) > mNumSamplerStates) mNumSamplerStates = sampler.second.slot + 1; } mTextureInfo = bs_newN(mNumTextures); } GpuParamsBase::~GpuParamsBase() { bs_deleteN(mTextureInfo, mNumTextures); } UINT32 GpuParamsBase::getDataParamSize(const String& name) const { GpuParamDataDesc* desc = getParamDesc(name); if(desc != nullptr) return desc->elementSize * 4; return 0; } bool GpuParamsBase::hasParam(const String& name) const { return getParamDesc(name) != nullptr; } bool GpuParamsBase::hasTexture(const String& name) const { auto paramIter = mParamDesc->textures.find(name); if(paramIter != mParamDesc->textures.end()) return true; return false; } bool GpuParamsBase::hasSamplerState(const String& name) const { auto paramIter = mParamDesc->samplers.find(name); if(paramIter != mParamDesc->samplers.end()) return true; return false; } bool GpuParamsBase::hasParamBlock(const String& name) const { auto paramBlockIter = mParamDesc->paramBlocks.find(name); if(paramBlockIter != mParamDesc->paramBlocks.end()) return true; return false; } GpuParamDataDesc* GpuParamsBase::getParamDesc(const String& name) const { auto paramIter = mParamDesc->params.find(name); if (paramIter != mParamDesc->params.end()) return ¶mIter->second; return nullptr; } bool GpuParamsBase::isLoadStoreTexture(UINT32 slot) const { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } return mTextureInfo[slot].isLoadStore; } void GpuParamsBase::setIsLoadStoreTexture(UINT32 slot, bool isLoadStore) { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } mTextureInfo[slot].isLoadStore = isLoadStore; } const TextureSurface& GpuParamsBase::getLoadStoreSurface(UINT32 slot) const { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } return mTextureInfo[slot].surface; } void GpuParamsBase::setLoadStoreSurface(UINT32 slot, const TextureSurface& surface) const { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } mTextureInfo[slot].surface = surface; } template TGpuParams::TGpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices) :GpuParamsBase(paramDesc, transposeMatrices), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr) { if (mNumParamBlocks > 0) mParamBlockBuffers = bs_newN(mNumParamBlocks); if (mNumTextures > 0) mTextures = bs_newN(mNumTextures); if (mNumSamplerStates > 0) mSamplerStates = bs_newN(mNumSamplerStates); } template TGpuParams::~TGpuParams() { if (mParamBlockBuffers != nullptr) bs_deleteN(mParamBlockBuffers, mNumParamBlocks); if (mTextures != nullptr) bs_deleteN(mTextures, mNumTextures); if (mSamplerStates != nullptr) bs_deleteN(mSamplerStates, mNumSamplerStates); } template void TGpuParams::setParamBlockBuffer(UINT32 slot, const ParamsBufferType& paramBlockBuffer) { if (slot < 0 || slot >= mNumParamBlocks) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot)); } mParamBlockBuffers[slot] = paramBlockBuffer; _markCoreDirty(); } template void TGpuParams::setParamBlockBuffer(const String& name, const ParamsBufferType& paramBlockBuffer) { auto iterFind = mParamDesc->paramBlocks.find(name); if (iterFind == mParamDesc->paramBlocks.end()) { LOGWRN("Cannot find parameter block with the name: " + name); return; } mParamBlockBuffers[iterFind->second.slot] = paramBlockBuffer; _markCoreDirty(); } template template void TGpuParams::getParam(const String& name, TGpuDataParam& output) const { auto iterFind = mParamDesc->params.find(name); if (iterFind == mParamDesc->params.end()) { output = TGpuDataParam(nullptr, nullptr); LOGWRN("Cannot find parameter with the name '" + name + "'"); } else output = TGpuDataParam(&iterFind->second, _getThisPtr()); } template void TGpuParams::getStructParam(const String& name, TGpuParamStruct& output) const { auto iterFind = mParamDesc->params.find(name); if (iterFind == mParamDesc->params.end() || iterFind->second.type != GPDT_STRUCT) { output = TGpuParamStruct(nullptr, nullptr); LOGWRN("Cannot find struct parameter with the name '" + name + "'"); } else output = TGpuParamStruct(&iterFind->second, _getThisPtr()); } template void TGpuParams::getTextureParam(const String& name, TGpuParamTexture& output) const { auto iterFind = mParamDesc->textures.find(name); if (iterFind == mParamDesc->textures.end()) { output = TGpuParamTexture(nullptr, nullptr); LOGWRN("Cannot find texture parameter with the name '" + name + "'"); } else output = TGpuParamTexture(&iterFind->second, _getThisPtr()); } template void TGpuParams::getLoadStoreTextureParam(const String& name, TGpuParamLoadStoreTexture& output) const { auto iterFind = mParamDesc->textures.find(name); if (iterFind == mParamDesc->textures.end()) { output = TGpuParamLoadStoreTexture(nullptr, nullptr); LOGWRN("Cannot find texture parameter with the name '" + name + "'"); } else output = TGpuParamLoadStoreTexture(&iterFind->second, _getThisPtr()); } template void TGpuParams::getSamplerStateParam(const String& name, TGpuParamSampState& output) const { auto iterFind = mParamDesc->samplers.find(name); if (iterFind == mParamDesc->samplers.end()) { output = TGpuParamSampState(nullptr, nullptr); LOGWRN("Cannot find sampler state parameter with the name '" + name + "'"); } else output = TGpuParamSampState(&iterFind->second, _getThisPtr()); } template typename TGpuParams::ParamsBufferType TGpuParams::getParamBlockBuffer(UINT32 slot) const { if (slot < 0 || slot >= mNumParamBlocks) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot)); } return mParamBlockBuffers[slot]; } template typename TGpuParams::TextureType TGpuParams::getTexture(UINT32 slot) { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } return mTextures[slot]; } template typename TGpuParams::SamplerType TGpuParams::getSamplerState(UINT32 slot) { if (slot < 0 || slot >= mNumSamplerStates) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot)); } return mSamplerStates[slot]; } template void TGpuParams::setTexture(UINT32 slot, const TextureType& texture) { if (slot < 0 || slot >= mNumTextures) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumTextures - 1) + ". Requested: " + toString(slot)); } mTextures[slot] = texture; _markResourcesDirty(); _markCoreDirty(); } template void TGpuParams::setSamplerState(UINT32 slot, const SamplerType& sampler) { if (slot < 0 || slot >= mNumSamplerStates) { BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " + toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot)); } mSamplerStates[slot] = sampler; _markResourcesDirty(); _markCoreDirty(); } template class TGpuParams < false > ; template class TGpuParams < true > ; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; template BS_CORE_EXPORT void TGpuParams::getParam(const String&, TGpuDataParam&) const; GpuParamsCore::GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices) : TGpuParams(paramDesc, transposeMatrices) { } SPtr GpuParamsCore::_getThisPtr() const { return std::static_pointer_cast(getThisPtr()); } void GpuParamsCore::updateHardwareBuffers() { for (UINT32 i = 0; i < mNumParamBlocks; i++) { if (mParamBlockBuffers[i] != nullptr) { mParamBlockBuffers[i]->flushToGPU(); } } } void GpuParamsCore::syncToCore(const CoreSyncData& data) { UINT32 textureInfoSize = mNumTextures * sizeof(BoundTextureInfo); UINT32 paramBufferSize = mNumParamBlocks * sizeof(SPtr); UINT32 textureArraySize = mNumTextures * sizeof(SPtr); UINT32 samplerArraySize = mNumSamplerStates * sizeof(SPtr); UINT32 totalSize = textureInfoSize + paramBufferSize + textureArraySize + samplerArraySize; UINT32 textureInfoOffset = 0; UINT32 paramBufferOffset = textureInfoOffset + textureInfoSize; UINT32 textureArrayOffset = paramBufferOffset + paramBufferSize; UINT32 samplerArrayOffset = textureArrayOffset + textureArraySize; assert(data.getBufferSize() == totalSize); UINT8* dataPtr = data.getBuffer(); BoundTextureInfo* textureInfos = (BoundTextureInfo*)(dataPtr + textureInfoOffset); SPtr* paramBuffers = (SPtr*)(dataPtr + paramBufferOffset); SPtr* textures = (SPtr*)(dataPtr + textureArrayOffset); SPtr* samplers = (SPtr*)(dataPtr + samplerArrayOffset); // Copy & destruct for (UINT32 i = 0; i < mNumParamBlocks; i++) { mParamBlockBuffers[i] = paramBuffers[i]; paramBuffers[i].~SPtr(); } for (UINT32 i = 0; i < mNumTextures; i++) { mTextureInfo[i] = textureInfos[i]; textureInfos[i].~BoundTextureInfo(); mTextures[i] = textures[i]; textures[i].~SPtr(); } for (UINT32 i = 0; i < mNumSamplerStates; i++) { mSamplerStates[i] = samplers[i]; samplers[i].~SPtr(); } } SPtr GpuParamsCore::create(const GpuParamDescPtr& paramDesc, bool transposeMatrices) { GpuParamsCore* params = new (bs_alloc()) GpuParamsCore(paramDesc, transposeMatrices); SPtr paramsPtr = bs_shared_ptr(params); paramsPtr->_setThisPtr(paramsPtr); return paramsPtr; } const GpuDataParamInfos GpuParams::PARAM_SIZES; GpuParams::GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices) : TGpuParams(paramDesc, transposeMatrices) { } SPtr GpuParams::_getThisPtr() const { return std::static_pointer_cast(getThisPtr()); } SPtr GpuParams::getCore() const { return std::static_pointer_cast(mCoreSpecific); } SPtr GpuParams::createCore() const { GpuParamsCore* obj = new (bs_alloc()) GpuParamsCore(mParamDesc, mTransposeMatrices); SPtr coreObj = bs_shared_ptr(obj); coreObj->_setThisPtr(coreObj); return coreObj; } void GpuParams::_markCoreDirty() { markCoreDirty(); } void GpuParams::_markResourcesDirty() { markListenerResourcesDirty(); } SPtr GpuParams::create(const GpuParamDescPtr& paramDesc, bool transposeMatrices) { GpuParams* params = new (bs_alloc()) GpuParams(paramDesc, transposeMatrices); SPtr paramsPtr = bs_core_ptr(params); paramsPtr->_setThisPtr(paramsPtr); paramsPtr->initialize(); return paramsPtr; } CoreSyncData GpuParams::syncToCore(FrameAlloc* allocator) { UINT32 textureInfoSize = mNumTextures * sizeof(BoundTextureInfo); UINT32 paramBufferSize = mNumParamBlocks * sizeof(SPtr); UINT32 textureArraySize = mNumTextures * sizeof(SPtr); UINT32 samplerArraySize = mNumSamplerStates * sizeof(SPtr); UINT32 totalSize = textureInfoSize + paramBufferSize + textureArraySize + samplerArraySize; UINT32 textureInfoOffset = 0; UINT32 paramBufferOffset = textureInfoOffset + textureInfoSize; UINT32 textureArrayOffset = paramBufferOffset + paramBufferSize; UINT32 samplerArrayOffset = textureArrayOffset + textureArraySize; UINT8* data = allocator->alloc(totalSize); BoundTextureInfo* textureInfos = (BoundTextureInfo*)(data + textureInfoOffset); SPtr* paramBuffers = (SPtr*)(data + paramBufferOffset); SPtr* textures = (SPtr*)(data + textureArrayOffset); SPtr* samplers = (SPtr*)(data + samplerArrayOffset); // Construct & copy for (UINT32 i = 0; i < mNumParamBlocks; i++) { new (¶mBuffers[i]) SPtr(); if (mParamBlockBuffers[i] != nullptr) paramBuffers[i] = mParamBlockBuffers[i]->getCore(); } for (UINT32 i = 0; i < mNumTextures; i++) { new (&textureInfos[i]) BoundTextureInfo(); textureInfos[i] = mTextureInfo[i]; new (&textures[i]) SPtr(); if (mTextures[i].isLoaded()) textures[i] = mTextures[i]->getCore(); else textures[i] = nullptr; } for (UINT32 i = 0; i < mNumSamplerStates; i++) { new (&samplers[i]) SPtr(); if (mSamplerStates[i] != nullptr) samplers[i] = mSamplerStates[i]->getCore(); else samplers[i] = nullptr; } return CoreSyncData(data, totalSize); } void GpuParams::getListenerResources(Vector& resources) { for (UINT32 i = 0; i < mNumTextures; i++) { if (mTextures[i] != nullptr) resources.push_back(mTextures[i]); } } }