|
|
@@ -16,289 +16,54 @@
|
|
|
|
|
|
namespace BansheeEngine
|
|
|
{
|
|
|
- Material::Material()
|
|
|
- :Resource(false), mCoreDirtyFlags(0xFFFFFFFF)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- Material::~Material()
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- void Material::setShader(ShaderPtr shader)
|
|
|
+ struct ShaderBlockDesc
|
|
|
{
|
|
|
- mShader = shader;
|
|
|
+ String name;
|
|
|
+ GpuParamBlockUsage usage;
|
|
|
+ int size;
|
|
|
+ bool create;
|
|
|
+ };
|
|
|
|
|
|
- initBestTechnique();
|
|
|
- }
|
|
|
-
|
|
|
- void Material::initBestTechnique()
|
|
|
+ bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets)
|
|
|
{
|
|
|
- mBestTechnique = nullptr;
|
|
|
- mParametersPerPass.clear();
|
|
|
- freeParamBuffers();
|
|
|
-
|
|
|
- if(mShader)
|
|
|
- {
|
|
|
- mBestTechnique = mShader->getBestTechnique();
|
|
|
-
|
|
|
- if(mBestTechnique == nullptr)
|
|
|
- return;
|
|
|
-
|
|
|
- mValidShareableParamBlocks.clear();
|
|
|
- mValidParams.clear();
|
|
|
-
|
|
|
- Vector<GpuParamDescPtr> allParamDescs;
|
|
|
-
|
|
|
- // Make sure all gpu programs are fully loaded
|
|
|
- for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
|
|
|
- {
|
|
|
- PassPtr curPass = mBestTechnique->getPass(i);
|
|
|
-
|
|
|
- HGpuProgram vertProgram = curPass->getVertexProgram();
|
|
|
- if(vertProgram)
|
|
|
- {
|
|
|
- vertProgram.synchronize();
|
|
|
- allParamDescs.push_back(vertProgram->getParamDesc());
|
|
|
- }
|
|
|
-
|
|
|
- HGpuProgram fragProgram = curPass->getFragmentProgram();
|
|
|
- if(fragProgram)
|
|
|
- {
|
|
|
- fragProgram.synchronize();
|
|
|
- allParamDescs.push_back(fragProgram->getParamDesc());
|
|
|
- }
|
|
|
-
|
|
|
- HGpuProgram geomProgram = curPass->getGeometryProgram();
|
|
|
- if(geomProgram)
|
|
|
- {
|
|
|
- geomProgram.synchronize();
|
|
|
- allParamDescs.push_back(geomProgram->getParamDesc());
|
|
|
- }
|
|
|
-
|
|
|
- HGpuProgram hullProgram = curPass->getHullProgram();
|
|
|
- if(hullProgram)
|
|
|
- {
|
|
|
- hullProgram.synchronize();
|
|
|
- allParamDescs.push_back(hullProgram->getParamDesc());
|
|
|
- }
|
|
|
-
|
|
|
- HGpuProgram domainProgram = curPass->getDomainProgram();
|
|
|
- if(domainProgram)
|
|
|
- {
|
|
|
- domainProgram.synchronize();
|
|
|
- allParamDescs.push_back(domainProgram->getParamDesc());
|
|
|
- }
|
|
|
-
|
|
|
- HGpuProgram computeProgram = curPass->getComputeProgram();
|
|
|
- if(computeProgram)
|
|
|
- {
|
|
|
- computeProgram.synchronize();
|
|
|
- allParamDescs.push_back(computeProgram->getParamDesc());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Fill out various helper structures
|
|
|
- Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(allParamDescs);
|
|
|
- Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(allParamDescs);
|
|
|
-
|
|
|
- Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
|
|
|
- Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(allParamDescs);
|
|
|
- Map<String, GpuParamBlockBufferPtr> paramBlockBuffers;
|
|
|
-
|
|
|
- // Create param blocks
|
|
|
- const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc = mShader->getParamBlocks();
|
|
|
- for(auto iter = validShareableParamBlocks.begin(); iter != validShareableParamBlocks.end(); ++iter)
|
|
|
- {
|
|
|
- bool createBlockBuffer = true;
|
|
|
- GpuParamBlockUsage usage = GPBU_STATIC;
|
|
|
-
|
|
|
- auto iterFind = shaderDesc.find(*iter);
|
|
|
- if(iterFind != shaderDesc.end())
|
|
|
- {
|
|
|
- createBlockBuffer = !iterFind->second.shared && iterFind->second.rendererSemantic == 0;
|
|
|
- usage = iterFind->second.usage;
|
|
|
- }
|
|
|
-
|
|
|
- GpuParamBlockDesc blockDesc;
|
|
|
- for(auto iter2 = allParamDescs.begin(); iter2 != allParamDescs.end(); ++iter2)
|
|
|
- {
|
|
|
- auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
|
|
|
-
|
|
|
- if(findParamBlockDesc != (*iter2)->paramBlocks.end())
|
|
|
- {
|
|
|
- blockDesc = findParamBlockDesc->second;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- GpuParamBlockBufferPtr newParamBlockBuffer;
|
|
|
- if(createBlockBuffer)
|
|
|
- {
|
|
|
- newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(blockDesc.blockSize * sizeof(UINT32), usage);
|
|
|
- mParamBuffers.push_back(newParamBlockBuffer);
|
|
|
- }
|
|
|
-
|
|
|
- paramBlockBuffers[*iter] = newParamBlockBuffer;
|
|
|
- mValidShareableParamBlocks.insert(*iter);
|
|
|
- }
|
|
|
-
|
|
|
- // Create data param mappings
|
|
|
- const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDesc = mShader->getDataParams();
|
|
|
- for(auto iter = dataParamDesc.begin(); iter != dataParamDesc.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)
|
|
|
- {
|
|
|
- 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.");
|
|
|
-
|
|
|
- String& paramBlockName = findBlockIter->second;
|
|
|
- mValidParams[iter->first] = iter->second.gpuVariableName;
|
|
|
- }
|
|
|
-
|
|
|
- // Create object param mappings
|
|
|
- const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParamDesc = mShader->getObjectParams();
|
|
|
- for(auto iter = objectParamDesc.begin(); iter != objectParamDesc.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)
|
|
|
- {
|
|
|
- mValidParams[iter->first] = *iter2;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for(UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
|
|
|
- {
|
|
|
- PassPtr curPass = mBestTechnique->getPass(i);
|
|
|
- PassParametersPtr params = PassParametersPtr(new PassParameters());
|
|
|
-
|
|
|
- HGpuProgram vertProgram = curPass->getVertexProgram();
|
|
|
- if(vertProgram)
|
|
|
- params->mVertParams = vertProgram->createParameters();
|
|
|
-
|
|
|
- HGpuProgram fragProgram = curPass->getFragmentProgram();
|
|
|
- if(fragProgram)
|
|
|
- params->mFragParams = fragProgram->createParameters();
|
|
|
-
|
|
|
- HGpuProgram geomProgram = curPass->getGeometryProgram();
|
|
|
- if(geomProgram)
|
|
|
- params->mGeomParams = geomProgram->createParameters();
|
|
|
-
|
|
|
- HGpuProgram hullProgram = curPass->getHullProgram();
|
|
|
- if(hullProgram)
|
|
|
- params->mHullParams = hullProgram->createParameters();
|
|
|
-
|
|
|
- HGpuProgram domainProgram = curPass->getDomainProgram();
|
|
|
- if(domainProgram)
|
|
|
- params->mDomainParams = domainProgram->createParameters();
|
|
|
-
|
|
|
- HGpuProgram computeProgram = curPass->getComputeProgram();
|
|
|
- if(computeProgram)
|
|
|
- params->mComputeParams = computeProgram->createParameters();
|
|
|
-
|
|
|
- mParametersPerPass.push_back(params);
|
|
|
- }
|
|
|
-
|
|
|
- // Assign param block buffers
|
|
|
- for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
- {
|
|
|
- PassParametersPtr params = *iter;
|
|
|
-
|
|
|
- for(UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
- {
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if(paramPtr)
|
|
|
- {
|
|
|
- // Assign shareable buffers
|
|
|
- for(auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
|
|
|
- {
|
|
|
- const String& paramBlockName = *iterBlock;
|
|
|
- if(paramPtr->hasParamBlock(paramBlockName))
|
|
|
- {
|
|
|
- GpuParamBlockBufferPtr blockBuffer = paramBlockBuffers[paramBlockName];
|
|
|
-
|
|
|
- paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Create non-shareable ones
|
|
|
- const GpuParamDesc& desc = paramPtr->getParamDesc();
|
|
|
- for(auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
|
|
|
- {
|
|
|
- if(!iterBlockDesc->second.isShareable)
|
|
|
- {
|
|
|
- GpuParamBlockBufferPtr newParamBlockBuffer = HardwareBufferManager::instance().createGpuParamBlockBuffer(iterBlockDesc->second.blockSize * sizeof(UINT32));
|
|
|
- mParamBuffers.push_back(newParamBlockBuffer);
|
|
|
+ bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
|
|
|
+ && paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
|
|
|
|
|
|
- paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if (!ignoreBufferOffsets)
|
|
|
+ equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
|
|
|
|
|
|
- mCoreDirtyFlags = 0xFFFFFFFF;
|
|
|
+ return equal;
|
|
|
}
|
|
|
|
|
|
- Map<String, const GpuParamDataDesc*> Material::determineValidDataParameters(const Vector<GpuParamDescPtr>& paramDescs) const
|
|
|
+ Map<String, const GpuParamDataDesc*> determineValidDataParameters(const Vector<GpuParamDescPtr>& paramDescs)
|
|
|
{
|
|
|
Map<String, const GpuParamDataDesc*> foundDataParams;
|
|
|
Map<String, bool> validParams;
|
|
|
|
|
|
- for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ 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)
|
|
|
+ for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
|
|
|
{
|
|
|
bool isParameterValid = true;
|
|
|
const GpuParamDataDesc& curParam = iter2->second;
|
|
|
|
|
|
auto dataFindIter = validParams.find(iter2->first);
|
|
|
- if(dataFindIter == validParams.end())
|
|
|
+ if (dataFindIter == validParams.end())
|
|
|
{
|
|
|
validParams[iter2->first] = true;
|
|
|
foundDataParams[iter2->first] = &curParam;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if(validParams[iter2->first])
|
|
|
+ if (validParams[iter2->first])
|
|
|
{
|
|
|
auto dataFindIter2 = foundDataParams.find(iter2->first);
|
|
|
|
|
|
const GpuParamDataDesc* otherParam = dataFindIter2->second;
|
|
|
- if(!areParamsEqual(curParam, *otherParam, true))
|
|
|
+ if (!areParamsEqual(curParam, *otherParam, true))
|
|
|
{
|
|
|
validParams[iter2->first] = false;
|
|
|
foundDataParams.erase(dataFindIter2);
|
|
|
@@ -311,28 +76,28 @@ namespace BansheeEngine
|
|
|
return foundDataParams;
|
|
|
}
|
|
|
|
|
|
- Vector<const GpuParamObjectDesc*> Material::determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs) const
|
|
|
+ Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<GpuParamDescPtr>& paramDescs)
|
|
|
{
|
|
|
Vector<const GpuParamObjectDesc*> validParams;
|
|
|
|
|
|
- for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ 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)
|
|
|
+ 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)
|
|
|
+ for (auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
|
|
|
{
|
|
|
validParams.push_back(&iter2->second);
|
|
|
}
|
|
|
|
|
|
// Check buffer params
|
|
|
- for(auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
|
|
|
+ for (auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
|
|
|
{
|
|
|
validParams.push_back(&iter2->second);
|
|
|
}
|
|
|
@@ -341,25 +106,25 @@ namespace BansheeEngine
|
|
|
return validParams;
|
|
|
}
|
|
|
|
|
|
- Set<String> Material::determineValidShareableParamBlocks(const Vector<GpuParamDescPtr>& paramDescs) const
|
|
|
+ Set<String> determineValidShareableParamBlocks(const Vector<GpuParamDescPtr>& paramDescs)
|
|
|
{
|
|
|
// Make sure param blocks with the same name actually are the same
|
|
|
Map<String, std::pair<String, GpuParamDescPtr>> uniqueParamBlocks;
|
|
|
Map<String, bool> validParamBlocks;
|
|
|
|
|
|
- for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
{
|
|
|
const GpuParamDesc& curDesc = **iter;
|
|
|
- for(auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
|
|
|
+ for (auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
|
|
|
{
|
|
|
bool isBlockValid = true;
|
|
|
const GpuParamBlockDesc& curBlock = blockIter->second;
|
|
|
|
|
|
- if(!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
|
|
|
+ if (!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
|
|
|
continue;
|
|
|
|
|
|
auto iterFind = uniqueParamBlocks.find(blockIter->first);
|
|
|
- if(iterFind == uniqueParamBlocks.end())
|
|
|
+ if (iterFind == uniqueParamBlocks.end())
|
|
|
{
|
|
|
uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
|
|
|
validParamBlocks[blockIter->first] = true;
|
|
|
@@ -369,17 +134,17 @@ namespace BansheeEngine
|
|
|
String otherBlockName = iterFind->second.first;
|
|
|
GpuParamDescPtr otherDesc = iterFind->second.second;
|
|
|
|
|
|
- for(auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
|
|
|
+ for (auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
|
|
|
{
|
|
|
const GpuParamDataDesc& myParam = myParamIter->second;
|
|
|
|
|
|
- if(myParam.paramBlockSlot != curBlock.slot)
|
|
|
+ if (myParam.paramBlockSlot != curBlock.slot)
|
|
|
continue; // Param is in another block, so we will check it when its time for that block
|
|
|
|
|
|
auto otherParamFind = otherDesc->params.find(myParamIter->first);
|
|
|
|
|
|
// Cannot find other param, blocks aren't equal
|
|
|
- if(otherParamFind == otherDesc->params.end())
|
|
|
+ if (otherParamFind == otherDesc->params.end())
|
|
|
{
|
|
|
isBlockValid = false;
|
|
|
break;
|
|
|
@@ -387,16 +152,16 @@ namespace BansheeEngine
|
|
|
|
|
|
const GpuParamDataDesc& otherParam = otherParamFind->second;
|
|
|
|
|
|
- if(!areParamsEqual(myParam, otherParam) || curBlock.name != otherBlockName)
|
|
|
+ if (!areParamsEqual(myParam, otherParam, false) || curBlock.name != otherBlockName)
|
|
|
{
|
|
|
isBlockValid = false;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(!isBlockValid)
|
|
|
+ if (!isBlockValid)
|
|
|
{
|
|
|
- if(validParamBlocks[blockIter->first])
|
|
|
+ if (validParamBlocks[blockIter->first])
|
|
|
{
|
|
|
LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
|
|
|
validParamBlocks[blockIter->first] = false;
|
|
|
@@ -406,33 +171,33 @@ namespace BansheeEngine
|
|
|
}
|
|
|
|
|
|
Set<String> validParamBlocksReturn;
|
|
|
- for(auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
|
|
|
+ for (auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
|
|
|
{
|
|
|
- if(iter->second)
|
|
|
+ if (iter->second)
|
|
|
validParamBlocksReturn.insert(iter->first);
|
|
|
}
|
|
|
|
|
|
return validParamBlocksReturn;
|
|
|
}
|
|
|
|
|
|
- Map<String, String> Material::determineParameterToBlockMapping(const Vector<GpuParamDescPtr>& paramDescs)
|
|
|
+ Map<String, String> determineParameterToBlockMapping(const Vector<GpuParamDescPtr>& paramDescs)
|
|
|
{
|
|
|
Map<String, String> paramToParamBlock;
|
|
|
|
|
|
- for(auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
+ for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
|
|
|
{
|
|
|
const GpuParamDesc& curDesc = **iter;
|
|
|
- for(auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
|
|
|
+ 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())
|
|
|
+ if (iterFind != paramToParamBlock.end())
|
|
|
continue;
|
|
|
|
|
|
- for(auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
|
|
|
+ for (auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
|
|
|
{
|
|
|
- if(iterBlock->second.slot == curParam.paramBlockSlot)
|
|
|
+ if (iterBlock->second.slot == curParam.paramBlockSlot)
|
|
|
{
|
|
|
paramToParamBlock[curParam.name] = iterBlock->second.name;
|
|
|
break;
|
|
|
@@ -444,390 +209,338 @@ namespace BansheeEngine
|
|
|
return paramToParamBlock;
|
|
|
}
|
|
|
|
|
|
- bool Material::areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets) const
|
|
|
+ Map<String, String> determineParamMappings(const Vector<GpuParamDescPtr>& paramDescs, const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
|
|
|
+ const Map<String, SHADER_OBJECT_PARAM_DESC>& objectParam)
|
|
|
{
|
|
|
- bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
|
|
|
- && paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
|
|
|
+ Map<String, String> validParams;
|
|
|
|
|
|
- if(!ignoreBufferOffsets)
|
|
|
- equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
|
|
|
+ Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(paramDescs);
|
|
|
+ Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(paramDescs);
|
|
|
+ Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(paramDescs);
|
|
|
|
|
|
- return equal;
|
|
|
- }
|
|
|
-
|
|
|
- void Material::throwIfNotInitialized() const
|
|
|
- {
|
|
|
- if(mShader == nullptr)
|
|
|
+ // Create data param mappings
|
|
|
+ for (auto iter = dataParams.begin(); iter != dataParams.end(); ++iter)
|
|
|
{
|
|
|
- BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
|
|
|
- }
|
|
|
+ auto findIter = validDataParameters.find(iter->second.gpuVariableName);
|
|
|
|
|
|
- if(mBestTechnique == nullptr)
|
|
|
- {
|
|
|
- BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
|
|
|
- }
|
|
|
- }
|
|
|
+ // Not valid so we skip it
|
|
|
+ if (findIter == validDataParameters.end())
|
|
|
+ continue;
|
|
|
|
|
|
- void Material::setColor(const String& name, const Color& value, UINT32 arrayIdx)
|
|
|
- {
|
|
|
- return getParamVec4(name).set(Vector4(value.r, value.g, value.b, value.a), arrayIdx);
|
|
|
- }
|
|
|
+ if (findIter->second->type != iter->second.type)
|
|
|
+ {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- void Material::setParamBlockBuffer(const String& name, const GpuParamBlockBufferPtr& paramBlockBuffer)
|
|
|
- {
|
|
|
- auto iterFind = mValidShareableParamBlocks.find(name);
|
|
|
- if(iterFind == mValidShareableParamBlocks.end())
|
|
|
- {
|
|
|
- LOGWRN("Material doesn't have a parameter block named " + name);
|
|
|
- return;
|
|
|
+ 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.");
|
|
|
+
|
|
|
+ String& paramBlockName = findBlockIter->second;
|
|
|
+ validParams[iter->first] = iter->second.gpuVariableName;
|
|
|
}
|
|
|
|
|
|
- for(auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
+ // Create object param mappings
|
|
|
+ for (auto iter = objectParam.begin(); iter != objectParam.end(); ++iter)
|
|
|
{
|
|
|
- PassParametersPtr params = *iter;
|
|
|
-
|
|
|
- for(UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
+ const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
|
|
|
+ for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
|
|
|
{
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if(paramPtr)
|
|
|
+ for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
|
|
|
{
|
|
|
- if(paramPtr->hasParamBlock(name))
|
|
|
- paramPtr->setParamBlockBuffer(name, paramBlockBuffer);
|
|
|
+ if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
|
|
|
+ {
|
|
|
+ validParams[iter->first] = *iter2;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- UINT32 Material::getNumPasses() const
|
|
|
- {
|
|
|
- throwIfNotInitialized();
|
|
|
-
|
|
|
- return mShader->getBestTechnique()->getNumPasses();
|
|
|
+ return validParams;
|
|
|
}
|
|
|
|
|
|
- PassPtr Material::getPass(UINT32 passIdx) const
|
|
|
+ Vector<ShaderBlockDesc> determineShaderBlockData(const Set<String>& paramBlocks, const Vector<GpuParamDescPtr>& paramDescs,
|
|
|
+ const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc)
|
|
|
{
|
|
|
- if(passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
|
|
|
- BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
|
|
|
+ Vector<ShaderBlockDesc> output;
|
|
|
+ for (auto iter = paramBlocks.begin(); iter != paramBlocks.end(); ++iter)
|
|
|
+ {
|
|
|
+ ShaderBlockDesc shaderBlockDesc;
|
|
|
+ shaderBlockDesc.create = true;
|
|
|
+ shaderBlockDesc.usage = GPBU_STATIC;
|
|
|
+ shaderBlockDesc.size = 0;
|
|
|
+ shaderBlockDesc.name = *iter;
|
|
|
+
|
|
|
+ auto iterFind = shaderDesc.find(*iter);
|
|
|
+ if (iterFind != shaderDesc.end())
|
|
|
+ {
|
|
|
+ shaderBlockDesc.create = !iterFind->second.shared && iterFind->second.rendererSemantic == 0;
|
|
|
+ shaderBlockDesc.usage = iterFind->second.usage;
|
|
|
+ }
|
|
|
|
|
|
- return mShader->getBestTechnique()->getPass(passIdx);
|
|
|
- }
|
|
|
+ for (auto iter2 = paramDescs.begin(); iter2 != paramDescs.end(); ++iter2)
|
|
|
+ {
|
|
|
+ auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
|
|
|
|
|
|
- PassParametersPtr Material::getPassParameters(UINT32 passIdx) const
|
|
|
- {
|
|
|
- if(passIdx < 0 || passIdx >= mParametersPerPass.size())
|
|
|
- BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
|
|
|
+ if (findParamBlockDesc != (*iter2)->paramBlocks.end())
|
|
|
+ {
|
|
|
+ shaderBlockDesc.size = findParamBlockDesc->second.blockSize * sizeof(UINT32);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- PassParametersPtr params = mParametersPerPass[passIdx];
|
|
|
+ output.push_back(shaderBlockDesc);
|
|
|
+ }
|
|
|
|
|
|
- return params;
|
|
|
+ return output;
|
|
|
}
|
|
|
|
|
|
- Material::StructData Material::getStructData(const String& name, UINT32 arrayIdx) const
|
|
|
+ Vector<GpuParamDescPtr> MaterialBase::getAllParamDescs(const SPtr<Technique>& technique)
|
|
|
{
|
|
|
- MaterialParamStruct structParam = getParamStruct(name);
|
|
|
+ Vector<GpuParamDescPtr> allParamDescs;
|
|
|
|
|
|
- StructData data(structParam.getElementSize());
|
|
|
- structParam.get(data.data.get(), structParam.getElementSize(), arrayIdx);
|
|
|
+ // Make sure all gpu programs are fully loaded
|
|
|
+ for (UINT32 i = 0; i < technique->getNumPasses(); i++)
|
|
|
+ {
|
|
|
+ PassPtr curPass = technique->getPass(i);
|
|
|
|
|
|
- return data;
|
|
|
- }
|
|
|
+ HGpuProgram vertProgram = curPass->getVertexProgram();
|
|
|
+ if (vertProgram)
|
|
|
+ {
|
|
|
+ vertProgram.synchronize();
|
|
|
+ allParamDescs.push_back(vertProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- MaterialParamFloat Material::getParamFloat(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<float, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ HGpuProgram fragProgram = curPass->getFragmentProgram();
|
|
|
+ if (fragProgram)
|
|
|
+ {
|
|
|
+ fragProgram.synchronize();
|
|
|
+ allParamDescs.push_back(fragProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- return gpuParam;
|
|
|
- }
|
|
|
+ HGpuProgram geomProgram = curPass->getGeometryProgram();
|
|
|
+ if (geomProgram)
|
|
|
+ {
|
|
|
+ geomProgram.synchronize();
|
|
|
+ allParamDescs.push_back(geomProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- MaterialParamColor Material::getParamColor(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<Color, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ HGpuProgram hullProgram = curPass->getHullProgram();
|
|
|
+ if (hullProgram)
|
|
|
+ {
|
|
|
+ hullProgram.synchronize();
|
|
|
+ allParamDescs.push_back(hullProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- return gpuParam;
|
|
|
- }
|
|
|
+ HGpuProgram domainProgram = curPass->getDomainProgram();
|
|
|
+ if (domainProgram)
|
|
|
+ {
|
|
|
+ domainProgram.synchronize();
|
|
|
+ allParamDescs.push_back(domainProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- MaterialParamVec2 Material::getParamVec2(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<Vector2, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ HGpuProgram computeProgram = curPass->getComputeProgram();
|
|
|
+ if (computeProgram)
|
|
|
+ {
|
|
|
+ computeProgram.synchronize();
|
|
|
+ allParamDescs.push_back(computeProgram->getParamDesc());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return gpuParam;
|
|
|
+ return allParamDescs;
|
|
|
}
|
|
|
|
|
|
- MaterialParamVec3 Material::getParamVec3(const String& name) const
|
|
|
+ Vector<GpuParamDescPtr> MaterialBase::getAllParamDescs(const SPtr<TechniqueCore>& technique)
|
|
|
{
|
|
|
- TMaterialDataParam<Vector3, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ Vector<GpuParamDescPtr> allParamDescs;
|
|
|
|
|
|
- return gpuParam;
|
|
|
- }
|
|
|
+ // Make sure all gpu programs are fully loaded
|
|
|
+ for (UINT32 i = 0; i < technique->getNumPasses(); i++)
|
|
|
+ {
|
|
|
+ SPtr<PassCore> curPass = technique->getPass(i);
|
|
|
|
|
|
- MaterialParamVec4 Material::getParamVec4(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<Vector4, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ SPtr<GpuProgramCore> vertProgram = curPass->getVertexProgram();
|
|
|
+ if (vertProgram)
|
|
|
+ allParamDescs.push_back(vertProgram->getParamDesc());
|
|
|
|
|
|
- return gpuParam;
|
|
|
- }
|
|
|
+ SPtr<GpuProgramCore> fragProgram = curPass->getFragmentProgram();
|
|
|
+ if (fragProgram)
|
|
|
+ allParamDescs.push_back(fragProgram->getParamDesc());
|
|
|
|
|
|
- MaterialParamMat3 Material::getParamMat3(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<Matrix3, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ SPtr<GpuProgramCore> geomProgram = curPass->getGeometryProgram();
|
|
|
+ if (geomProgram)
|
|
|
+ allParamDescs.push_back(geomProgram->getParamDesc());
|
|
|
|
|
|
- return gpuParam;
|
|
|
- }
|
|
|
+ SPtr<GpuProgramCore> hullProgram = curPass->getHullProgram();
|
|
|
+ if (hullProgram)
|
|
|
+ allParamDescs.push_back(hullProgram->getParamDesc());
|
|
|
|
|
|
- MaterialParamMat4 Material::getParamMat4(const String& name) const
|
|
|
- {
|
|
|
- TMaterialDataParam<Matrix4, false> gpuParam;
|
|
|
- getParam(name, gpuParam);
|
|
|
+ SPtr<GpuProgramCore> domainProgram = curPass->getDomainProgram();
|
|
|
+ if (domainProgram)
|
|
|
+ allParamDescs.push_back(domainProgram->getParamDesc());
|
|
|
+
|
|
|
+ SPtr<GpuProgramCore> computeProgram = curPass->getComputeProgram();
|
|
|
+ if (computeProgram)
|
|
|
+ allParamDescs.push_back(computeProgram->getParamDesc());
|
|
|
+ }
|
|
|
|
|
|
- return gpuParam;
|
|
|
+ return allParamDescs;
|
|
|
}
|
|
|
|
|
|
- MaterialParamStruct Material::getParamStruct(const String& name) const
|
|
|
+ template<bool Core>
|
|
|
+ void TMaterial<Core>::initBestTechnique()
|
|
|
{
|
|
|
- throwIfNotInitialized();
|
|
|
-
|
|
|
- auto iterFind = mValidParams.find(name);
|
|
|
- if(iterFind == mValidParams.end())
|
|
|
- {
|
|
|
- LOGWRN("Material doesn't have a parameter named " + name);
|
|
|
- return MaterialParamStruct();
|
|
|
- }
|
|
|
-
|
|
|
- const String& gpuVarName = iterFind->second;
|
|
|
- Vector<GpuParamStruct> gpuParams;
|
|
|
+ mBestTechnique = nullptr;
|
|
|
+ mParametersPerPass.clear();
|
|
|
|
|
|
- for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
+ if (mShader)
|
|
|
{
|
|
|
- PassParametersPtr params = *iter;
|
|
|
-
|
|
|
- for (UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
- {
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if (paramPtr)
|
|
|
- {
|
|
|
- if (paramPtr->hasParam(gpuVarName))
|
|
|
- {
|
|
|
- gpuParams.push_back(GpuParamStruct());
|
|
|
- paramPtr->getStructParam(gpuVarName, gpuParams.back());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ mBestTechnique = mShader->getBestTechnique();
|
|
|
|
|
|
- return MaterialParamStruct(gpuParams);
|
|
|
- }
|
|
|
+ if (mBestTechnique == nullptr)
|
|
|
+ return;
|
|
|
|
|
|
- MaterialParamTexture Material::getParamTexture(const String& name) const
|
|
|
- {
|
|
|
- throwIfNotInitialized();
|
|
|
+ mValidShareableParamBlocks.clear();
|
|
|
+ Vector<GpuParamDescPtr> allParamDescs = getAllParamDescs(mBestTechnique);
|
|
|
|
|
|
- auto iterFind = mValidParams.find(name);
|
|
|
- if(iterFind == mValidParams.end())
|
|
|
- {
|
|
|
- LOGWRN("Material doesn't have a parameter named " + name);
|
|
|
- return MaterialParamTexture();
|
|
|
- }
|
|
|
+ mValidParams = determineParamMappings(allParamDescs, mShader->getDataParams(), mShader->getObjectParams());
|
|
|
|
|
|
- const String& gpuVarName = iterFind->second;
|
|
|
- Vector<GpuParamTexture> gpuParams;
|
|
|
+ // Fill out various helper structures
|
|
|
+ Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
|
|
|
+ Vector<ShaderBlockDesc> paramBlockData = determineShaderBlockData(validShareableParamBlocks, allParamDescs, mShader->getParamBlocks());
|
|
|
|
|
|
- for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
- {
|
|
|
- PassParametersPtr params = *iter;
|
|
|
+ Map<String, ParamBlockPtrType> paramBlockBuffers;
|
|
|
|
|
|
- for (UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
+ // Create param blocks
|
|
|
+ for (auto& paramBlock : paramBlockData)
|
|
|
{
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if (paramPtr)
|
|
|
+ ParamBlockPtrType newParamBlockBuffer;
|
|
|
+ if (paramBlock.create)
|
|
|
{
|
|
|
- if (paramPtr->hasTexture(gpuVarName))
|
|
|
- {
|
|
|
- gpuParams.push_back(GpuParamTexture());
|
|
|
- paramPtr->getTextureParam(gpuVarName, gpuParams.back());
|
|
|
- }
|
|
|
+ newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return MaterialParamTexture(gpuParams);
|
|
|
- }
|
|
|
|
|
|
- MaterialParamLoadStoreTexture Material::getParamLoadStoreTexture(const String& name) const
|
|
|
- {
|
|
|
- throwIfNotInitialized();
|
|
|
+ paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
|
|
|
+ mValidShareableParamBlocks.insert(paramBlock.name);
|
|
|
+ }
|
|
|
|
|
|
- auto iterFind = mValidParams.find(name);
|
|
|
- if (iterFind == mValidParams.end())
|
|
|
- {
|
|
|
- LOGWRN("Material doesn't have a parameter named " + name);
|
|
|
- return MaterialParamLoadStoreTexture();
|
|
|
- }
|
|
|
+ for (UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
|
|
|
+ {
|
|
|
+ PassType curPass = mBestTechnique->getPass(i);
|
|
|
+ SPtr<TPassParameters<Core>> params = SPtr<TPassParameters<Core>>(new TPassParameters<Core>());
|
|
|
|
|
|
- const String& gpuVarName = iterFind->second;
|
|
|
- Vector<GpuParamLoadStoreTexture> gpuParams;
|
|
|
+ GpuProgramType vertProgram = curPass->getVertexProgram();
|
|
|
+ if (vertProgram)
|
|
|
+ params->mVertParams = vertProgram->createParameters();
|
|
|
|
|
|
- for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
- {
|
|
|
- PassParametersPtr params = *iter;
|
|
|
+ GpuProgramType fragProgram = curPass->getFragmentProgram();
|
|
|
+ if (fragProgram)
|
|
|
+ params->mFragParams = fragProgram->createParameters();
|
|
|
|
|
|
- for (UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
- {
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if (paramPtr)
|
|
|
- {
|
|
|
- if (paramPtr->hasTexture(gpuVarName))
|
|
|
- {
|
|
|
- gpuParams.push_back(GpuParamLoadStoreTexture());
|
|
|
- paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams.back());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ GpuProgramType geomProgram = curPass->getGeometryProgram();
|
|
|
+ if (geomProgram)
|
|
|
+ params->mGeomParams = geomProgram->createParameters();
|
|
|
|
|
|
- return MaterialParamLoadStoreTexture(gpuParams);
|
|
|
- }
|
|
|
+ GpuProgramType hullProgram = curPass->getHullProgram();
|
|
|
+ if (hullProgram)
|
|
|
+ params->mHullParams = hullProgram->createParameters();
|
|
|
|
|
|
- MaterialParamSampState Material::getParamSamplerState(const String& name) const
|
|
|
- {
|
|
|
- throwIfNotInitialized();
|
|
|
+ GpuProgramType domainProgram = curPass->getDomainProgram();
|
|
|
+ if (domainProgram)
|
|
|
+ params->mDomainParams = domainProgram->createParameters();
|
|
|
|
|
|
- auto iterFind = mValidParams.find(name);
|
|
|
- if(iterFind == mValidParams.end())
|
|
|
- {
|
|
|
- LOGWRN("Material doesn't have a parameter named " + name);
|
|
|
- return MaterialParamSampState();
|
|
|
- }
|
|
|
+ GpuProgramType computeProgram = curPass->getComputeProgram();
|
|
|
+ if (computeProgram)
|
|
|
+ params->mComputeParams = computeProgram->createParameters();
|
|
|
|
|
|
- const String& gpuVarName = iterFind->second;
|
|
|
- Vector<GpuParamSampState> gpuParams;
|
|
|
- for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
- {
|
|
|
- PassParametersPtr params = *iter;
|
|
|
+ mParametersPerPass.push_back(params);
|
|
|
+ }
|
|
|
|
|
|
- for (UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
+ // Assign param block buffers
|
|
|
+ for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
|
|
|
{
|
|
|
- GpuParamsPtr& paramPtr = params->getParamByIdx(i);
|
|
|
- if (paramPtr)
|
|
|
+ SPtr<TPassParameters<Core>> params = *iter;
|
|
|
+
|
|
|
+ for (UINT32 i = 0; i < params->getNumParams(); i++)
|
|
|
{
|
|
|
- if (paramPtr->hasSamplerState(gpuVarName))
|
|
|
+ GpuParamsType& paramPtr = params->getParamByIdx(i);
|
|
|
+ if (paramPtr)
|
|
|
{
|
|
|
- gpuParams.push_back(GpuParamSampState());
|
|
|
- paramPtr->getSamplerStateParam(gpuVarName, gpuParams.back());
|
|
|
+ // Assign shareable buffers
|
|
|
+ for (auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
|
|
|
+ {
|
|
|
+ const String& paramBlockName = *iterBlock;
|
|
|
+ if (paramPtr->hasParamBlock(paramBlockName))
|
|
|
+ {
|
|
|
+ ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
|
|
|
+
|
|
|
+ paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create non-shareable ones
|
|
|
+ const GpuParamDesc& desc = paramPtr->getParamDesc();
|
|
|
+ for (auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
|
|
|
+ {
|
|
|
+ if (!iterBlockDesc->second.isShareable)
|
|
|
+ {
|
|
|
+ ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(iterBlockDesc->second.blockSize * sizeof(UINT32));
|
|
|
+
|
|
|
+ paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return MaterialParamSampState(gpuParams);
|
|
|
}
|
|
|
|
|
|
- bool Material::_isCoreDirty(MaterialDirtyFlag flag) const
|
|
|
- {
|
|
|
- return (mCoreDirtyFlags & (UINT32)flag) != 0;
|
|
|
- }
|
|
|
+ template class TMaterial < false > ;
|
|
|
+ template class TMaterial < true > ;
|
|
|
|
|
|
- void Material::_markCoreClean(MaterialDirtyFlag flag)
|
|
|
- {
|
|
|
- mCoreDirtyFlags &= ~(UINT32)flag;
|
|
|
- }
|
|
|
-
|
|
|
- MaterialProxyPtr Material::_createProxy()
|
|
|
+ Material::Material()
|
|
|
{
|
|
|
- throwIfNotInitialized();
|
|
|
-
|
|
|
- MaterialProxyPtr proxy = bs_shared_ptr<MaterialProxy>();
|
|
|
-
|
|
|
- UINT32 numPasses = mShader->getBestTechnique()->getNumPasses();
|
|
|
- for (UINT32 i = 0; i < numPasses; i++)
|
|
|
- {
|
|
|
- PassParametersPtr params = mParametersPerPass[i];
|
|
|
- PassPtr pass = mShader->getBestTechnique()->getPass(i);
|
|
|
-
|
|
|
- proxy->passes.push_back(MaterialProxyPass());
|
|
|
- MaterialProxyPass& passData = proxy->passes.back();
|
|
|
-
|
|
|
- if (pass->hasVertexProgram())
|
|
|
- {
|
|
|
- passData.vertexProg = pass->getVertexProgram();
|
|
|
- passData.vertexProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mVertParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.vertexProgParamsIdx = 0;
|
|
|
-
|
|
|
- if (pass->hasFragmentProgram())
|
|
|
- {
|
|
|
- passData.fragmentProg = pass->getFragmentProgram();
|
|
|
- passData.fragmentProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mFragParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.fragmentProgParamsIdx = 0;
|
|
|
-
|
|
|
- if (pass->hasGeometryProgram())
|
|
|
- {
|
|
|
- passData.geometryProg = pass->getGeometryProgram();
|
|
|
- passData.geometryProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mGeomParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.geometryProgParamsIdx = 0;
|
|
|
-
|
|
|
- if (pass->hasHullProgram())
|
|
|
- {
|
|
|
- passData.hullProg = pass->getHullProgram();
|
|
|
- passData.hullProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mHullParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.hullProgParamsIdx = 0;
|
|
|
|
|
|
- if (pass->hasDomainProgram())
|
|
|
- {
|
|
|
- passData.domainProg = pass->getDomainProgram();
|
|
|
- passData.domainProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mDomainParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.domainProgParamsIdx = 0;
|
|
|
+ }
|
|
|
|
|
|
- if (pass->hasComputeProgram())
|
|
|
- {
|
|
|
- passData.computeProg = pass->getComputeProgram();
|
|
|
- passData.computeProgParamsIdx = (UINT32)proxy->params.size();
|
|
|
- proxy->params.push_back(params->mComputeParams->getCore());
|
|
|
- }
|
|
|
- else
|
|
|
- passData.computeProgParamsIdx = 0;
|
|
|
+ Material::~Material()
|
|
|
+ {
|
|
|
|
|
|
- passData.blendState = pass->getBlendState();
|
|
|
- passData.rasterizerState = pass->getRasterizerState();
|
|
|
- passData.depthStencilState = pass->getDepthStencilState();
|
|
|
- passData.stencilRefValue = pass->getStencilRefValue();
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- proxy->shader = mShader->getCore();
|
|
|
+ void Material::_markCoreDirty()
|
|
|
+ {
|
|
|
+ markCoreDirty();
|
|
|
+ }
|
|
|
|
|
|
- return proxy;
|
|
|
+ SPtr<MaterialCore> Material::getCore() const
|
|
|
+ {
|
|
|
+ return std::static_pointer_cast<MaterialCore>(mCoreSpecific);
|
|
|
}
|
|
|
|
|
|
- void Material::destroy_internal()
|
|
|
+ SPtr<CoreObjectCore> Material::createCore() const
|
|
|
{
|
|
|
- freeParamBuffers();
|
|
|
+ MaterialCore* material = new (bs_alloc<MaterialCore>()) MaterialCore();
|
|
|
+ SPtr<MaterialCore> materialPtr = bs_shared_ptr<MaterialCore, GenAlloc>(material);
|
|
|
+ materialPtr->_setThisPtr(materialPtr);
|
|
|
|
|
|
- Resource::destroy_internal();
|
|
|
+ return materialPtr;
|
|
|
}
|
|
|
|
|
|
- void Material::freeParamBuffers()
|
|
|
+ void Material::_markCoreDirty()
|
|
|
{
|
|
|
- mParamBuffers.clear();
|
|
|
+ markCoreDirty();
|
|
|
}
|
|
|
|
|
|
HMaterial Material::create()
|