#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" 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; } GpuParamsCore::GpuParamsCore(const GpuParamDescPtr& paramDesc, bool transposeMatrices) : TGpuParams(paramDesc, transposeMatrices) { } 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; } GpuParams::GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices) : TGpuParams(paramDesc, transposeMatrices) { } 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(); } 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].isLoaded()) samplers[i] = mSamplerStates[i]->getCore(); else samplers[i] = nullptr; } return CoreSyncData(data, totalSize); } }