|
|
@@ -5,6 +5,7 @@
|
|
|
#include "BsTechnique.h"
|
|
|
#include "BsPass.h"
|
|
|
#include "BsGpuProgram.h"
|
|
|
+#include "BsMaterialParams.h"
|
|
|
#include "BsGpuParamDesc.h"
|
|
|
#include "BsGpuParamBlockBuffer.h"
|
|
|
|
|
|
@@ -16,6 +17,7 @@ namespace BansheeEngine
|
|
|
GpuParamBlockUsage usage;
|
|
|
int size;
|
|
|
bool external;
|
|
|
+ UINT32 sequentialIdx;
|
|
|
};
|
|
|
|
|
|
Vector<SPtr<GpuParamDesc>> getAllParamDescs(const SPtr<Technique>& technique)
|
|
|
@@ -233,12 +235,188 @@ namespace BansheeEngine
|
|
|
return output;
|
|
|
}
|
|
|
|
|
|
+ Map<String, const GpuParamDataDesc*> determineValidDataParameters(const Vector<SPtr<GpuParamDesc>>& paramDescs)
|
|
|
+ {
|
|
|
+ Map<String, const GpuParamDataDesc*> foundDataParams;
|
|
|
+ Map<String, bool> validParams;
|
|
|
+
|
|
|
+ for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ {
|
|
|
+ const GpuParamDesc& curDesc = **iter;
|
|
|
+
|
|
|
+ // Check regular data params
|
|
|
+ for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
|
|
|
+ {
|
|
|
+ const GpuParamDataDesc& curParam = iter2->second;
|
|
|
+
|
|
|
+ auto dataFindIter = validParams.find(iter2->first);
|
|
|
+ if (dataFindIter == validParams.end())
|
|
|
+ {
|
|
|
+ validParams[iter2->first] = true;
|
|
|
+ foundDataParams[iter2->first] = &curParam;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (validParams[iter2->first])
|
|
|
+ {
|
|
|
+ auto dataFindIter2 = foundDataParams.find(iter2->first);
|
|
|
+
|
|
|
+ const GpuParamDataDesc* otherParam = dataFindIter2->second;
|
|
|
+ if (!areParamsEqual(curParam, *otherParam, true))
|
|
|
+ {
|
|
|
+ validParams[iter2->first] = false;
|
|
|
+ foundDataParams.erase(dataFindIter2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return foundDataParams;
|
|
|
+ }
|
|
|
+
|
|
|
+ Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<SPtr<GpuParamDesc>>& paramDescs)
|
|
|
+ {
|
|
|
+ Vector<const GpuParamObjectDesc*> validParams;
|
|
|
+
|
|
|
+ for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ {
|
|
|
+ const GpuParamDesc& curDesc = **iter;
|
|
|
+
|
|
|
+ // Check sampler params
|
|
|
+ for (auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
|
|
|
+ {
|
|
|
+ validParams.push_back(&iter2->second);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check texture params
|
|
|
+ for (auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
|
|
|
+ {
|
|
|
+ validParams.push_back(&iter2->second);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check load-store texture params
|
|
|
+ for (auto iter2 = curDesc.loadStoreTextures.begin(); iter2 != curDesc.loadStoreTextures.end(); ++iter2)
|
|
|
+ {
|
|
|
+ validParams.push_back(&iter2->second);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check buffer params
|
|
|
+ for (auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
|
|
|
+ {
|
|
|
+ validParams.push_back(&iter2->second);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return validParams;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, String> determineParameterToBlockMapping(const Vector<SPtr<GpuParamDesc>>& paramDescs)
|
|
|
+ {
|
|
|
+ Map<String, String> paramToParamBlock;
|
|
|
+
|
|
|
+ for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ {
|
|
|
+ const GpuParamDesc& curDesc = **iter;
|
|
|
+ for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
|
|
|
+ {
|
|
|
+ const GpuParamDataDesc& curParam = iter2->second;
|
|
|
+
|
|
|
+ auto iterFind = paramToParamBlock.find(curParam.name);
|
|
|
+ if (iterFind != paramToParamBlock.end())
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for (auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
|
|
|
+ {
|
|
|
+ if (iterBlock->second.slot == curParam.paramBlockSlot)
|
|
|
+ {
|
|
|
+ paramToParamBlock[curParam.name] = iterBlock->second.name;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return paramToParamBlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ UnorderedSet<String> determineValidParameters(const Vector<SPtr<GpuParamDesc>>& paramDescs,
|
|
|
+ const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
|
|
|
+ const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
|
|
|
+ const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
|
|
|
+ const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams)
|
|
|
+ {
|
|
|
+ UnorderedSet<String> validParams;
|
|
|
+
|
|
|
+ Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(paramDescs);
|
|
|
+ Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(paramDescs);
|
|
|
+ Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(paramDescs);
|
|
|
+
|
|
|
+ // Create data param mappings
|
|
|
+ for (auto iter = dataParams.begin(); iter != dataParams.end(); ++iter)
|
|
|
+ {
|
|
|
+ auto findIter = validDataParameters.find(iter->second.gpuVariableName);
|
|
|
+
|
|
|
+ // Not valid so we skip it
|
|
|
+ if (findIter == validDataParameters.end())
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (findIter->second->type != iter->second.type && !(iter->second.type == GPDT_COLOR && findIter->second->type == GPDT_FLOAT4))
|
|
|
+ {
|
|
|
+ LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Type doesn't match the one defined in the gpu program. "
|
|
|
+ + "Shader defined type: " + toString(iter->second.type) + " - Gpu program defined type: " + toString(findIter->second->type));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (findIter->second->arraySize != iter->second.arraySize)
|
|
|
+ {
|
|
|
+ LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Array size doesn't match the one defined in the gpu program."
|
|
|
+ + "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
|
|
|
+
|
|
|
+ if (findBlockIter == paramToParamBlockMap.end())
|
|
|
+ BS_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
|
|
|
+
|
|
|
+ validParams.insert(iter->first);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create object param mappings
|
|
|
+ auto determineObjectMappings = [&](const Map<String, SHADER_OBJECT_PARAM_DESC>& params)
|
|
|
+ {
|
|
|
+ for (auto iter = params.begin(); iter != params.end(); ++iter)
|
|
|
+ {
|
|
|
+ const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
|
|
|
+ for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
|
|
|
+ {
|
|
|
+ for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
|
|
|
+ {
|
|
|
+ if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
|
|
|
+ {
|
|
|
+ validParams.insert(iter->first);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ determineObjectMappings(textureParams);
|
|
|
+ determineObjectMappings(samplerParams);
|
|
|
+ determineObjectMappings(bufferParams);
|
|
|
+
|
|
|
+ return validParams;
|
|
|
+ }
|
|
|
+
|
|
|
template<bool Core>
|
|
|
- const UINT32 TGpuParamsSet<Core>::NUM_PARAMS = 6;
|
|
|
+ const UINT32 TGpuParamsSet<Core>::NUM_STAGES = 6;
|
|
|
|
|
|
template<bool Core>
|
|
|
- TGpuParamsSet<Core>::TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader)
|
|
|
- :mPassParams(technique->getNumPasses())
|
|
|
+ TGpuParamsSet<Core>::TGpuParamsSet(const SPtr<TechniqueType>& technique, const ShaderType& shader, UINT32 techniqueIdx,
|
|
|
+ const SPtr<MaterialParamsType>& params)
|
|
|
+ :mPassParams(technique->getNumPasses()), mTechniqueIdx(techniqueIdx)
|
|
|
{
|
|
|
UINT32 numPasses = technique->getNumPasses();
|
|
|
|
|
|
@@ -277,6 +455,12 @@ namespace BansheeEngine
|
|
|
|
|
|
//// Fill out various helper structures
|
|
|
Vector<ShaderBlockDesc> paramBlockData = determineValidShareableParamBlocks(allParamDescs, shader->getParamBlocks());
|
|
|
+ UnorderedSet<String> validParams = determineValidParameters(
|
|
|
+ allParamDescs,
|
|
|
+ shader->getDataParams(),
|
|
|
+ shader->getTextureParams(),
|
|
|
+ shader->getBufferParams(),
|
|
|
+ shader->getSamplerParams());
|
|
|
|
|
|
Map<String, ParamBlockPtrType> paramBlockBuffers;
|
|
|
|
|
|
@@ -287,18 +471,22 @@ namespace BansheeEngine
|
|
|
if (!paramBlock.external)
|
|
|
newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
|
|
|
|
|
|
+ paramBlock.sequentialIdx = (UINT32)mBlocks.size();
|
|
|
+
|
|
|
paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
|
|
|
+ mBlocks.push_back(BlockInfo(paramBlock.name, newParamBlockBuffer, true));
|
|
|
}
|
|
|
|
|
|
- //// Assign param block buffers
|
|
|
+ //// Assign param block buffers and generate information about data parameters
|
|
|
for (UINT32 i = 0; i < numPasses; i++)
|
|
|
{
|
|
|
- for (UINT32 j = 0; j < NUM_PARAMS; j++)
|
|
|
+ for (UINT32 j = 0; j < NUM_STAGES; j++)
|
|
|
{
|
|
|
GpuParamsType paramPtr = getParamByIdx(j, i);
|
|
|
if (paramPtr != nullptr)
|
|
|
{
|
|
|
// Assign shareable buffers
|
|
|
+ UINT32 paramBlockIdx = 0;
|
|
|
for (auto& block : paramBlockData)
|
|
|
{
|
|
|
const String& paramBlockName = block.name;
|
|
|
@@ -308,22 +496,199 @@ namespace BansheeEngine
|
|
|
|
|
|
paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
|
|
|
}
|
|
|
+
|
|
|
+ paramBlockIdx++;
|
|
|
}
|
|
|
|
|
|
// Create non-shareable ones (these are buffers defined by default by the RHI usually)
|
|
|
const GpuParamDesc& desc = paramPtr->getParamDesc();
|
|
|
for (auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
|
|
|
{
|
|
|
- if (!iterBlockDesc->second.isShareable)
|
|
|
+ const GpuParamBlockDesc& blockDesc = iterBlockDesc->second;
|
|
|
+
|
|
|
+ UINT32 globalBlockIdx = (UINT32)-1;
|
|
|
+ if (!blockDesc.isShareable)
|
|
|
{
|
|
|
- ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(iterBlockDesc->second.blockSize * sizeof(UINT32));
|
|
|
+ ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(blockDesc.blockSize * sizeof(UINT32));
|
|
|
+
|
|
|
+ globalBlockIdx = (UINT32)mBlocks.size();
|
|
|
|
|
|
paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
|
|
|
+ mBlocks.push_back(BlockInfo(iterBlockDesc->first, newParamBlockBuffer, false));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ auto iterFind = std::find_if(paramBlockData.begin(), paramBlockData.end(), [&](const auto& x)
|
|
|
+ {
|
|
|
+ return x.name == iterBlockDesc->first;
|
|
|
+ });
|
|
|
+
|
|
|
+ if(iterFind != paramBlockData.end())
|
|
|
+ globalBlockIdx = iterFind->sequentialIdx;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If this parameter block is valid, create data/struct mappings for it
|
|
|
+ if (globalBlockIdx == (UINT32)-1)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for(auto& dataParam : desc.params)
|
|
|
+ {
|
|
|
+ if (dataParam.second.paramBlockSlot != blockDesc.slot)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (validParams.count(dataParam.first) == 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ UINT32 paramIdx = params->getParamIndex(dataParam.first);
|
|
|
+
|
|
|
+ // Parameter shouldn't be in the valid parameter list if it cannot be found
|
|
|
+ assert(paramIdx != (UINT32)-1);
|
|
|
+
|
|
|
+ mDataParamInfos.push_back(DataParamInfo());
|
|
|
+ DataParamInfo& paramInfo = mDataParamInfos.back();
|
|
|
+ paramInfo.paramIdx = paramIdx;
|
|
|
+ paramInfo.blockIdx = globalBlockIdx;
|
|
|
+ paramInfo.offset = dataParam.second.cpuMemOffset;
|
|
|
+
|
|
|
+ const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[(int)dataParam.second.type];
|
|
|
+ UINT32 paramSize = typeInfo.numColumns * typeInfo.numRows * typeInfo.baseTypeSize;
|
|
|
+
|
|
|
+ paramInfo.size = paramSize * dataParam.second.arraySize;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // Generate information about object parameters
|
|
|
+ bs_frame_mark();
|
|
|
+ {
|
|
|
+ FrameVector<ObjectParamInfo> objParamInfos;
|
|
|
+
|
|
|
+ UINT32 offsetsSize = numPasses * NUM_STAGES * 4 * sizeof(UINT32);
|
|
|
+ UINT32* offsets = (UINT32*)bs_frame_alloc(offsetsSize);
|
|
|
+ memset(offsets, 0, offsetsSize);
|
|
|
+
|
|
|
+ // First store all objects in temporary arrays since we don't know how many of them are
|
|
|
+ UINT32 totalNumObjects = 0;
|
|
|
+ UINT32* stageOffsets = offsets;
|
|
|
+ for (UINT32 i = 0; i < numPasses; i++)
|
|
|
+ {
|
|
|
+ for (UINT32 j = 0; j < NUM_STAGES; j++)
|
|
|
+ {
|
|
|
+ GpuParamsType paramPtr = getParamByIdx(j, i);
|
|
|
+ if (paramPtr == nullptr)
|
|
|
+ {
|
|
|
+ stageOffsets += sizeof(UINT32) * 4;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto processObjectParams = [&](const Map<String, GpuParamObjectDesc>& gpuParams,
|
|
|
+ UINT32 stageIdx, MaterialParams::ParamType paramType)
|
|
|
+ {
|
|
|
+ for (auto& param : gpuParams)
|
|
|
+ {
|
|
|
+ if (validParams.count(param.first) == 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ UINT32 paramIdx = params->getParamIndex(param.first);
|
|
|
+
|
|
|
+ // Parameter shouldn't be in the valid parameter list if it cannot be found
|
|
|
+ assert(paramIdx != (UINT32)-1);
|
|
|
+
|
|
|
+ objParamInfos.push_back(ObjectParamInfo());
|
|
|
+ ObjectParamInfo& paramInfo = objParamInfos.back();
|
|
|
+ paramInfo.paramIdx = paramIdx;
|
|
|
+ paramInfo.slotIdx = param.second.slot;
|
|
|
+
|
|
|
+ offsets[stageIdx]++;
|
|
|
+ totalNumObjects++;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const GpuParamDesc& desc = paramPtr->getParamDesc();
|
|
|
+ processObjectParams(desc.textures, 0, MaterialParams::ParamType::Texture);
|
|
|
+ processObjectParams(desc.loadStoreTextures, 1, MaterialParams::ParamType::Texture);
|
|
|
+ processObjectParams(desc.buffers, 2, MaterialParams::ParamType::Buffer);
|
|
|
+ processObjectParams(desc.samplers, 3, MaterialParams::ParamType::Sampler);
|
|
|
+
|
|
|
+ stageOffsets += sizeof(UINT32) * 4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Transfer all objects into their permanent storage
|
|
|
+ UINT32 objectParamInfosSize = totalNumObjects * sizeof(ObjectParamInfo) + numPasses * sizeof(PassParamInfo);
|
|
|
+ mPassParamInfos = (PassParamInfo*)bs_alloc(objectParamInfosSize);
|
|
|
+ memset(mPassParamInfos, 0, objectParamInfosSize);
|
|
|
+
|
|
|
+ StageParamInfo* stageInfos = (StageParamInfo*)mPassParamInfos;
|
|
|
+
|
|
|
+ ObjectParamInfo* objInfos = (ObjectParamInfo*)(mPassParamInfos + numPasses);
|
|
|
+ memcpy(objInfos, objParamInfos.data(), totalNumObjects * sizeof(ObjectParamInfo));
|
|
|
+
|
|
|
+ UINT32 objInfoOffset = 0;
|
|
|
+
|
|
|
+ stageOffsets = offsets;
|
|
|
+ for (UINT32 i = 0; i < numPasses; i++)
|
|
|
+ {
|
|
|
+ for (UINT32 j = 0; j < NUM_STAGES; j++)
|
|
|
+ {
|
|
|
+ StageParamInfo& stage = stageInfos[i * NUM_STAGES + j];
|
|
|
+
|
|
|
+ if(stageOffsets[0] > 0)
|
|
|
+ {
|
|
|
+ UINT32 numEntries = stageOffsets[0];
|
|
|
+
|
|
|
+ stage.textures = objInfos + objInfoOffset;
|
|
|
+ stage.numTextures = numEntries;
|
|
|
+
|
|
|
+ objInfoOffset += numEntries;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stageOffsets[1] > 0)
|
|
|
+ {
|
|
|
+ UINT32 numEntries = stageOffsets[1];
|
|
|
+
|
|
|
+ stage.loadStoreTextures = objInfos + objInfoOffset;
|
|
|
+ stage.numLoadStoreTextures = numEntries;
|
|
|
+
|
|
|
+ objInfoOffset += numEntries;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stageOffsets[2] > 0)
|
|
|
+ {
|
|
|
+ UINT32 numEntries = stageOffsets[2];
|
|
|
+
|
|
|
+ stage.buffers = objInfos + objInfoOffset;
|
|
|
+ stage.numBuffers = numEntries;
|
|
|
+
|
|
|
+ objInfoOffset += numEntries;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stageOffsets[3] > 0)
|
|
|
+ {
|
|
|
+ UINT32 numEntries = stageOffsets[3];
|
|
|
+
|
|
|
+ stage.samplerStates = objInfos + objInfoOffset;
|
|
|
+ stage.numSamplerStates = numEntries;
|
|
|
+
|
|
|
+ objInfoOffset += numEntries;
|
|
|
+ }
|
|
|
+
|
|
|
+ stageOffsets += sizeof(UINT32) * 4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bs_frame_free(offsets);
|
|
|
+ }
|
|
|
+ bs_frame_clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ template<bool Core>
|
|
|
+ TGpuParamsSet<Core>::~TGpuParamsSet()
|
|
|
+ {
|
|
|
+ // All allocations share the same memory, so we just clear it all at once
|
|
|
+ bs_free(mPassParamInfos);
|
|
|
}
|
|
|
|
|
|
template<bool Core>
|
|
|
@@ -354,10 +719,34 @@ namespace BansheeEngine
|
|
|
template<bool Core>
|
|
|
void TGpuParamsSet<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
|
|
|
{
|
|
|
+ UINT32 foundIdx = (UINT32)-1;
|
|
|
+ for(UINT32 i = 0; i < (UINT32)mBlocks.size(); i++)
|
|
|
+ {
|
|
|
+ BlockInfo& block = mBlocks[i];
|
|
|
+ if(block.name == name)
|
|
|
+ {
|
|
|
+ if (!block.shareable)
|
|
|
+ {
|
|
|
+ LOGERR("Cannot set parameter block buffer with the name \"" + name + "\". Buffer is not assignable. ");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foundIdx = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(foundIdx == (UINT32)-1)
|
|
|
+ {
|
|
|
+ LOGERR("Cannot set parameter block buffer with the name \"" + name + "\". Buffer name not found. ");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mBlocks[foundIdx].buffer = paramBlock;
|
|
|
+
|
|
|
UINT32 numPasses = (UINT32)mPassParams.size();
|
|
|
for (UINT32 j = 0; j < numPasses; j++)
|
|
|
{
|
|
|
- for (UINT32 i = 0; i < NUM_PARAMS; i++)
|
|
|
+ for (UINT32 i = 0; i < NUM_STAGES; i++)
|
|
|
{
|
|
|
GpuParamsType paramPtr = getParamByIdx(i);
|
|
|
if (paramPtr != nullptr)
|
|
|
@@ -369,6 +758,108 @@ namespace BansheeEngine
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ template<bool Core>
|
|
|
+ void TGpuParamsSet<Core>::update(const SPtr<MaterialParamsType>& params, bool updateAll)
|
|
|
+ {
|
|
|
+ // Note: Instead of iterating over every single parameter, it might be more efficient for @p params to keep
|
|
|
+ // a ring buffer and a version number. Then we could just iterate over the ring buffer and only access dirty
|
|
|
+ // parameters. If the version number is too high (larger than ring buffer can store), then we force update for all.
|
|
|
+
|
|
|
+ // Maximum of 31 techniques are supported. Bit 32 is reserved.
|
|
|
+ assert(mTechniqueIdx < 31);
|
|
|
+ UINT32 dirtyFlagCheck = 1 << mTechniqueIdx;
|
|
|
+
|
|
|
+ // Update data params
|
|
|
+ for(auto& paramInfo : mDataParamInfos)
|
|
|
+ {
|
|
|
+ ParamBlockPtrType paramBlock = mBlocks[paramInfo.blockIdx].buffer;
|
|
|
+ if (paramBlock != nullptr)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
|
|
|
+ if ((materialParamInfo->dirtyFlags & dirtyFlagCheck) == 0 && !updateAll)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ // TODO - Handle transposing matrices (POTENTIALLY add this to Material setters directly)
|
|
|
+ UINT8* data = params->getData(materialParamInfo->index);
|
|
|
+ paramBlock->write(paramInfo.offset, data, paramInfo.size);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update object params
|
|
|
+ UINT32 numPasses = (UINT32)mPassParams.size();
|
|
|
+
|
|
|
+ for(UINT32 i = 0; i < numPasses; i++)
|
|
|
+ {
|
|
|
+ for(UINT32 j = 0; j < NUM_STAGES; j++)
|
|
|
+ {
|
|
|
+ GpuParamsType paramsPtr = getParamByIdx(j, i);
|
|
|
+ if(paramsPtr != nullptr)
|
|
|
+ {
|
|
|
+ const StageParamInfo& stageInfo = mPassParamInfos[i].stages[j];
|
|
|
+
|
|
|
+ for(UINT32 k = 0; k < stageInfo.numTextures; k++)
|
|
|
+ {
|
|
|
+ const ObjectParamInfo& paramInfo = stageInfo.textures[k];
|
|
|
+
|
|
|
+ const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
|
|
|
+ if ((materialParamInfo->dirtyFlags & dirtyFlagCheck) == 0 && !updateAll)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ TextureType texture;
|
|
|
+ params->getTexture(materialParamInfo->index, texture);
|
|
|
+
|
|
|
+ paramsPtr->setTexture(paramInfo.slotIdx, texture);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (UINT32 k = 0; k < stageInfo.numLoadStoreTextures; k++)
|
|
|
+ {
|
|
|
+ const ObjectParamInfo& paramInfo = stageInfo.loadStoreTextures[k];
|
|
|
+
|
|
|
+ const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
|
|
|
+ if ((materialParamInfo->dirtyFlags & dirtyFlagCheck) == 0 && !updateAll)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ TextureSurface surface;
|
|
|
+ TextureType texture;
|
|
|
+ params->getLoadStoreTexture(materialParamInfo->index, texture, surface);
|
|
|
+
|
|
|
+ paramsPtr->setLoadStoreTexture(paramInfo.slotIdx, texture, surface);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (UINT32 k = 0; k < stageInfo.numBuffers; k++)
|
|
|
+ {
|
|
|
+ const ObjectParamInfo& paramInfo = stageInfo.buffers[k];
|
|
|
+
|
|
|
+ const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
|
|
|
+ if ((materialParamInfo->dirtyFlags & dirtyFlagCheck) == 0 && !updateAll)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ BufferType buffer;
|
|
|
+ params->getBuffer(materialParamInfo->index, buffer);
|
|
|
+
|
|
|
+ paramsPtr->setBuffer(paramInfo.slotIdx, buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (UINT32 k = 0; k < stageInfo.numSamplerStates; k++)
|
|
|
+ {
|
|
|
+ const ObjectParamInfo& paramInfo = stageInfo.samplerStates[k];
|
|
|
+
|
|
|
+ const MaterialParams::ParamData* materialParamInfo = params->getParamData(paramInfo.paramIdx);
|
|
|
+ if ((materialParamInfo->dirtyFlags & dirtyFlagCheck) == 0 && !updateAll)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ SamplerStateType samplerState;
|
|
|
+ params->getSamplerState(materialParamInfo->index, samplerState);
|
|
|
+
|
|
|
+ paramsPtr->setSamplerState(paramInfo.slotIdx, samplerState);
|
|
|
+ }
|
|
|
+
|
|
|
+ paramsPtr->_markCoreDirty();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
template class TGpuParamsSet <false>;
|
|
|
template class TGpuParamsSet <true>;
|
|
|
}
|