1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "Material/BsShader.h" |
4 | #include "Material/BsTechnique.h" |
5 | #include "Error/BsException.h" |
6 | #include "Debug/BsDebug.h" |
7 | #include "Private/RTTI/BsShaderRTTI.h" |
8 | #include "Resources/BsResources.h" |
9 | #include "RenderAPI/BsGpuParams.h" |
10 | #include "Material/BsPass.h" |
11 | #include "RenderAPI/BsSamplerState.h" |
12 | #include "Image/BsTexture.h" |
13 | |
14 | namespace bs |
15 | { |
16 | RTTITypeBase* SubShader::getRTTIStatic() |
17 | { |
18 | return SubShaderRTTI::instance(); |
19 | } |
20 | |
21 | RTTITypeBase* SubShader::getRTTI() const |
22 | { |
23 | return SubShader::getRTTIStatic(); |
24 | } |
25 | |
26 | template<bool Core> |
27 | TSHADER_DESC<Core>::TSHADER_DESC() |
28 | :queueSortType(QueueSortType::None), queuePriority(0), separablePasses(false), flags(0) |
29 | { |
30 | |
31 | } |
32 | |
33 | template<bool Core> |
34 | void TSHADER_DESC<Core>::addParameter(SHADER_DATA_PARAM_DESC paramDesc, UINT8* defaultValue) |
35 | { |
36 | if(paramDesc.type == GPDT_STRUCT && paramDesc.elementSize <= 0) |
37 | { |
38 | LOGERR("You need to provide a non-zero element size for a struct parameter." ); |
39 | return; |
40 | } |
41 | |
42 | const auto iterFind = dataParams.find(paramDesc.name); |
43 | if(iterFind != dataParams.end()) |
44 | return; |
45 | |
46 | if (defaultValue != nullptr) |
47 | { |
48 | paramDesc.defaultValueIdx = (UINT32)dataDefaultValues.size(); |
49 | UINT32 defaultValueSize = Shader::getDataParamSize(paramDesc.type); |
50 | |
51 | dataDefaultValues.resize(paramDesc.defaultValueIdx + defaultValueSize); |
52 | memcpy(&dataDefaultValues[paramDesc.defaultValueIdx], defaultValue, defaultValueSize); |
53 | } |
54 | else |
55 | paramDesc.defaultValueIdx = (UINT32)-1; |
56 | |
57 | dataParams[paramDesc.name] = paramDesc; |
58 | } |
59 | |
60 | template<bool Core> |
61 | void TSHADER_DESC<Core>::addParameter(SHADER_OBJECT_PARAM_DESC paramDesc) |
62 | { |
63 | UINT32 defaultValueIdx = (UINT32)-1; |
64 | |
65 | addParameterInternal(std::move(paramDesc), defaultValueIdx); |
66 | } |
67 | |
68 | template<bool Core> |
69 | void TSHADER_DESC<Core>::addParameter(SHADER_OBJECT_PARAM_DESC paramDesc, const SamplerStateType& defaultValue) |
70 | { |
71 | UINT32 defaultValueIdx = (UINT32)-1; |
72 | if (Shader::isSampler(paramDesc.type) && defaultValue != nullptr) |
73 | { |
74 | defaultValueIdx = (UINT32)samplerDefaultValues.size(); |
75 | samplerDefaultValues.push_back(defaultValue); |
76 | } |
77 | |
78 | addParameterInternal(std::move(paramDesc), defaultValueIdx); |
79 | } |
80 | |
81 | template<bool Core> |
82 | void TSHADER_DESC<Core>::addParameter(SHADER_OBJECT_PARAM_DESC paramDesc, const TextureType& defaultValue) |
83 | { |
84 | UINT32 defaultValueIdx = (UINT32)-1; |
85 | if (Shader::isTexture(paramDesc.type) && defaultValue != nullptr) |
86 | { |
87 | defaultValueIdx = (UINT32)textureDefaultValues.size(); |
88 | textureDefaultValues.push_back(defaultValue); |
89 | } |
90 | |
91 | addParameterInternal(std::move(paramDesc), defaultValueIdx); |
92 | } |
93 | |
94 | template<bool Core> |
95 | void TSHADER_DESC<Core>::addParameterInternal(SHADER_OBJECT_PARAM_DESC paramDesc, UINT32 defaultValueIdx) |
96 | { |
97 | Map<String, SHADER_OBJECT_PARAM_DESC>* DEST_LOOKUP[] = { &textureParams, &bufferParams, &samplerParams }; |
98 | UINT32 destIdx = 0; |
99 | if (Shader::isBuffer(paramDesc.type)) |
100 | destIdx = 1; |
101 | else if (Shader::isSampler(paramDesc.type)) |
102 | destIdx = 2; |
103 | |
104 | Map<String, SHADER_OBJECT_PARAM_DESC>& paramsMap = *DEST_LOOKUP[destIdx]; |
105 | |
106 | auto iterFind = paramsMap.find(paramDesc.name); |
107 | if (iterFind == paramsMap.end()) |
108 | { |
109 | paramDesc.defaultValueIdx = defaultValueIdx; |
110 | paramsMap[paramDesc.name] = paramDesc; |
111 | } |
112 | else |
113 | { |
114 | SHADER_OBJECT_PARAM_DESC& desc = iterFind->second; |
115 | |
116 | // If same name but different properties, we ignore this param |
117 | if (desc.type != paramDesc.type || desc.rendererSemantic != paramDesc.rendererSemantic) |
118 | return; |
119 | |
120 | Vector<String>& gpuVariableNames = desc.gpuVariableNames; |
121 | bool found = false; |
122 | for (UINT32 i = 0; i < (UINT32)gpuVariableNames.size(); i++) |
123 | { |
124 | if (gpuVariableNames[i] == paramDesc.gpuVariableName) |
125 | { |
126 | found = true; |
127 | break; |
128 | } |
129 | } |
130 | |
131 | if (!found) |
132 | gpuVariableNames.push_back(paramDesc.gpuVariableName); |
133 | } |
134 | } |
135 | |
136 | template<bool Core> |
137 | void TSHADER_DESC<Core>::setParameterAttribute(const String& name, const SHADER_PARAM_ATTRIBUTE& attrib) |
138 | { |
139 | SHADER_DATA_PARAM_DESC* paramDescData = nullptr; |
140 | |
141 | const auto findIterData = dataParams.find(name); |
142 | if (findIterData != dataParams.end()) |
143 | paramDescData = &findIterData->second; |
144 | |
145 | SHADER_OBJECT_PARAM_DESC* paramDescObj = nullptr; |
146 | if(!paramDescData) |
147 | { |
148 | const auto findIterTexture = textureParams.find(name); |
149 | if (findIterTexture != textureParams.end()) |
150 | paramDescObj = &findIterTexture->second; |
151 | |
152 | if (!paramDescObj) |
153 | { |
154 | const auto findIterSampler = samplerParams.find(name); |
155 | if (findIterSampler != samplerParams.end()) |
156 | paramDescObj = &findIterSampler->second; |
157 | } |
158 | |
159 | if (!paramDescObj) |
160 | { |
161 | const auto findIterBuffer = bufferParams.find(name); |
162 | if (findIterBuffer != bufferParams.end()) |
163 | paramDescObj = &findIterBuffer->second; |
164 | } |
165 | } |
166 | |
167 | SHADER_PARAM_COMMON* paramDesc = paramDescData; |
168 | if(!paramDesc) |
169 | paramDesc = paramDescObj; |
170 | |
171 | if(!paramDesc) |
172 | { |
173 | LOGWRN("Attempting to apply a shader parameter attribute to a non-existing parameter." ); |
174 | return; |
175 | } |
176 | |
177 | if(attrib.type == ShaderParamAttributeType::SpriteUV) |
178 | { |
179 | if(paramDescObj) |
180 | { |
181 | LOGWRN("Attempting to apply SpriteUV attribute to an object parameter is not supported." ); |
182 | return; |
183 | } |
184 | |
185 | if(paramDescData->type != GPDT_FLOAT4) |
186 | { |
187 | LOGWRN("SpriteUV attribute can only be applied to 4D vectors." ); |
188 | return; |
189 | } |
190 | } |
191 | |
192 | // Look for duplicate attributes |
193 | UINT32 curAttribIdx = paramDesc->attribIdx; |
194 | bool found = false; |
195 | while(curAttribIdx != (UINT32)-1) |
196 | { |
197 | SHADER_PARAM_ATTRIBUTE& curAttrib = paramAttributes[curAttribIdx]; |
198 | if(curAttrib.type == attrib.type) |
199 | { |
200 | curAttrib = attrib; |
201 | |
202 | found = true; |
203 | break; |
204 | } |
205 | |
206 | curAttribIdx = curAttrib.nextParamIdx; |
207 | } |
208 | |
209 | if(!found) |
210 | { |
211 | const auto attribIdx = (UINT32)paramAttributes.size(); |
212 | paramAttributes.emplace_back(attrib); |
213 | |
214 | if (paramDesc->attribIdx != (UINT32)-1) |
215 | paramAttributes.back().nextParamIdx = paramDesc->attribIdx; |
216 | |
217 | paramDesc->attribIdx = attribIdx; |
218 | } |
219 | } |
220 | |
221 | template<bool Core> |
222 | void TSHADER_DESC<Core>::setParamBlockAttribs(const String& name, bool shared, GpuBufferUsage usage, |
223 | StringID rendererSemantic) |
224 | { |
225 | SHADER_PARAM_BLOCK_DESC desc; |
226 | desc.name = name; |
227 | desc.shared = shared; |
228 | desc.usage = usage; |
229 | desc.rendererSemantic = rendererSemantic; |
230 | |
231 | paramBlocks[name] = desc; |
232 | } |
233 | |
234 | template struct TSHADER_DESC<false>; |
235 | template struct TSHADER_DESC<true>; |
236 | |
237 | template<bool Core> |
238 | TShader<Core>::TShader(UINT32 id) |
239 | :mId(id) |
240 | { } |
241 | |
242 | template<bool Core> |
243 | TShader<Core>::TShader(const String& name, const TSHADER_DESC<Core>& desc, UINT32 id) |
244 | :mName(name), mDesc(desc), mId(id) |
245 | { } |
246 | |
247 | template<bool Core> |
248 | TShader<Core>::~TShader() |
249 | { } |
250 | |
251 | template<bool Core> |
252 | GpuParamType TShader<Core>::getParamType(const String& name) const |
253 | { |
254 | auto findIterData = mDesc.dataParams.find(name); |
255 | if (findIterData != mDesc.dataParams.end()) |
256 | return GPT_DATA; |
257 | |
258 | auto findIterTexture = mDesc.textureParams.find(name); |
259 | if (findIterTexture != mDesc.textureParams.end()) |
260 | return GPT_TEXTURE; |
261 | |
262 | auto findIterBuffer = mDesc.bufferParams.find(name); |
263 | if (findIterBuffer != mDesc.bufferParams.end()) |
264 | return GPT_BUFFER; |
265 | |
266 | auto findIterSampler = mDesc.samplerParams.find(name); |
267 | if (findIterSampler != mDesc.samplerParams.end()) |
268 | return GPT_SAMPLER; |
269 | |
270 | BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name); |
271 | return GPT_DATA; |
272 | } |
273 | |
274 | template<bool Core> |
275 | const SHADER_DATA_PARAM_DESC& TShader<Core>::getDataParamDesc(const String& name) const |
276 | { |
277 | auto findIterData = mDesc.dataParams.find(name); |
278 | if (findIterData != mDesc.dataParams.end()) |
279 | return findIterData->second; |
280 | |
281 | BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name); |
282 | static SHADER_DATA_PARAM_DESC dummy; |
283 | return dummy; |
284 | } |
285 | |
286 | template<bool Core> |
287 | const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getTextureParamDesc(const String& name) const |
288 | { |
289 | auto findIterObject = mDesc.textureParams.find(name); |
290 | if (findIterObject != mDesc.textureParams.end()) |
291 | return findIterObject->second; |
292 | |
293 | BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name); |
294 | static SHADER_OBJECT_PARAM_DESC dummy; |
295 | return dummy; |
296 | } |
297 | |
298 | template<bool Core> |
299 | const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getSamplerParamDesc(const String& name) const |
300 | { |
301 | auto findIterObject = mDesc.samplerParams.find(name); |
302 | if (findIterObject != mDesc.samplerParams.end()) |
303 | return findIterObject->second; |
304 | |
305 | BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name); |
306 | static SHADER_OBJECT_PARAM_DESC dummy; |
307 | return dummy; |
308 | } |
309 | |
310 | template<bool Core> |
311 | const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getBufferParamDesc(const String& name) const |
312 | { |
313 | auto findIterObject = mDesc.bufferParams.find(name); |
314 | if (findIterObject != mDesc.bufferParams.end()) |
315 | return findIterObject->second; |
316 | |
317 | BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name); |
318 | static SHADER_OBJECT_PARAM_DESC dummy; |
319 | return dummy; |
320 | } |
321 | |
322 | template<bool Core> |
323 | bool TShader<Core>::hasDataParam(const String& name) const |
324 | { |
325 | auto findIterData = mDesc.dataParams.find(name); |
326 | if (findIterData != mDesc.dataParams.end()) |
327 | return true; |
328 | |
329 | return false; |
330 | } |
331 | |
332 | template<bool Core> |
333 | bool TShader<Core>::hasTextureParam(const String& name) const |
334 | { |
335 | auto findIterObject = mDesc.textureParams.find(name); |
336 | if (findIterObject != mDesc.textureParams.end()) |
337 | return true; |
338 | |
339 | return false; |
340 | } |
341 | |
342 | template<bool Core> |
343 | bool TShader<Core>::hasSamplerParam(const String& name) const |
344 | { |
345 | auto findIterObject = mDesc.samplerParams.find(name); |
346 | if (findIterObject != mDesc.samplerParams.end()) |
347 | return true; |
348 | |
349 | return false; |
350 | } |
351 | |
352 | template<bool Core> |
353 | bool TShader<Core>::hasBufferParam(const String& name) const |
354 | { |
355 | auto findIterObject = mDesc.bufferParams.find(name); |
356 | if (findIterObject != mDesc.bufferParams.end()) |
357 | return true; |
358 | |
359 | return false; |
360 | } |
361 | |
362 | template<bool Core> |
363 | bool TShader<Core>::hasParamBlock(const String& name) const |
364 | { |
365 | auto findIterObject = mDesc.paramBlocks.find(name); |
366 | if (findIterObject != mDesc.paramBlocks.end()) |
367 | return true; |
368 | |
369 | return false; |
370 | } |
371 | |
372 | template<bool Core> |
373 | typename TShader<Core>::TextureType TShader<Core>::getDefaultTexture(UINT32 index) const |
374 | { |
375 | if (index < (UINT32)mDesc.textureDefaultValues.size()) |
376 | return mDesc.textureDefaultValues[index]; |
377 | |
378 | return TextureType(); |
379 | } |
380 | |
381 | template<bool Core> |
382 | typename TShader<Core>::SamplerStateType TShader<Core>::getDefaultSampler(UINT32 index) const |
383 | { |
384 | if (index < (UINT32)mDesc.samplerDefaultValues.size()) |
385 | return mDesc.samplerDefaultValues[index]; |
386 | |
387 | return SamplerStateType(); |
388 | } |
389 | |
390 | template<bool Core> |
391 | UINT8* TShader<Core>::getDefaultValue(UINT32 index) const |
392 | { |
393 | if (index < (UINT32)mDesc.dataDefaultValues.size()) |
394 | return (UINT8*)&mDesc.dataDefaultValues[index]; |
395 | |
396 | return nullptr; |
397 | } |
398 | |
399 | template<bool Core> |
400 | Vector<SPtr<typename TShader<Core>::TechniqueType>> TShader<Core>::getCompatibleTechniques() const |
401 | { |
402 | Vector<SPtr<TechniqueType>> output; |
403 | for (auto& technique : mDesc.techniques) |
404 | { |
405 | if (technique->isSupported()) |
406 | output.push_back(technique); |
407 | } |
408 | |
409 | return output; |
410 | } |
411 | |
412 | template<bool Core> |
413 | Vector<SPtr<typename TShader<Core>::TechniqueType>> TShader<Core>::getCompatibleTechniques( |
414 | const ShaderVariation& variation, bool exact) const |
415 | { |
416 | Vector<SPtr<TechniqueType>> output; |
417 | for (auto& technique : mDesc.techniques) |
418 | { |
419 | if (technique->isSupported() && technique->getVariation().matches(variation, exact)) |
420 | output.push_back(technique); |
421 | } |
422 | |
423 | return output; |
424 | } |
425 | |
426 | template class TShader < false > ; |
427 | template class TShader < true >; |
428 | |
429 | Shader::Shader(const String& name, const SHADER_DESC& desc, UINT32 id) |
430 | :TShader(name, desc, id) |
431 | { |
432 | mMetaData = bs_shared_ptr_new<ShaderMetaData>(); |
433 | } |
434 | |
435 | Shader::Shader(UINT32 id) |
436 | :TShader(id) |
437 | { } |
438 | |
439 | SPtr<ct::Shader> Shader::getCore() const |
440 | { |
441 | return std::static_pointer_cast<ct::Shader>(mCoreSpecific); |
442 | } |
443 | |
444 | void Shader::setIncludeFiles(const Vector<String>& includes) |
445 | { |
446 | SPtr<ShaderMetaData> meta = std::static_pointer_cast<ShaderMetaData>(getMetaData()); |
447 | meta->includes = includes; |
448 | } |
449 | |
450 | SPtr<ct::CoreObject> Shader::createCore() const |
451 | { |
452 | Vector<SPtr<ct::Technique>> techniques; |
453 | for (auto& technique : mDesc.techniques) |
454 | techniques.push_back(technique->getCore()); |
455 | |
456 | ct::Shader* shaderCore = new (bs_alloc<ct::Shader>()) ct::Shader(mName, convertDesc(mDesc), mId); |
457 | SPtr<ct::Shader> shaderCorePtr = bs_shared_ptr<ct::Shader>(shaderCore); |
458 | shaderCorePtr->_setThisPtr(shaderCorePtr); |
459 | |
460 | return shaderCorePtr; |
461 | } |
462 | |
463 | ct::SHADER_DESC Shader::convertDesc(const SHADER_DESC& desc) const |
464 | { |
465 | ct::SHADER_DESC output; |
466 | output.dataParams = desc.dataParams; |
467 | output.textureParams = desc.textureParams; |
468 | output.samplerParams = desc.samplerParams; |
469 | output.bufferParams = desc.bufferParams; |
470 | output.paramBlocks = desc.paramBlocks; |
471 | output.paramAttributes = desc.paramAttributes; |
472 | |
473 | output.dataDefaultValues = desc.dataDefaultValues; |
474 | |
475 | output.samplerDefaultValues.resize(desc.samplerDefaultValues.size()); |
476 | for (UINT32 i = 0; i < (UINT32)desc.samplerDefaultValues.size(); i++) |
477 | { |
478 | if (desc.samplerDefaultValues[i] != nullptr) |
479 | output.samplerDefaultValues[i] = desc.samplerDefaultValues[i]->getCore(); |
480 | else |
481 | output.samplerDefaultValues[i] = nullptr; |
482 | } |
483 | |
484 | output.textureDefaultValues.resize(desc.textureDefaultValues.size()); |
485 | for (UINT32 i = 0; i < (UINT32)desc.textureDefaultValues.size(); i++) |
486 | { |
487 | if (desc.textureDefaultValues[i].isLoaded()) |
488 | output.textureDefaultValues[i] = desc.textureDefaultValues[i]->getCore(); |
489 | else |
490 | output.textureDefaultValues[i] = nullptr; |
491 | } |
492 | |
493 | output.queuePriority = desc.queuePriority; |
494 | output.queueSortType = desc.queueSortType; |
495 | output.separablePasses = desc.separablePasses; |
496 | output.flags = desc.flags; |
497 | |
498 | for(auto& entry : desc.techniques) |
499 | { |
500 | if(entry) |
501 | output.techniques.push_back(entry->getCore()); |
502 | } |
503 | |
504 | for(auto& entry : desc.subShaders) |
505 | { |
506 | ct::SubShader subShader; |
507 | subShader.name = entry.name; |
508 | |
509 | if(entry.shader) |
510 | subShader.shader = entry.shader->getCore(); |
511 | |
512 | output.subShaders.push_back(subShader); |
513 | } |
514 | |
515 | output.variationParams = desc.variationParams; |
516 | |
517 | // Ignoring default values as they are not needed for syncing since |
518 | // they're initialized through the material. |
519 | return output; |
520 | } |
521 | |
522 | void Shader::getCoreDependencies(Vector<CoreObject*>& dependencies) |
523 | { |
524 | for (auto& technique : mDesc.techniques) |
525 | dependencies.push_back(technique.get()); |
526 | } |
527 | |
528 | bool Shader::isSampler(GpuParamObjectType type) |
529 | { |
530 | switch(type) |
531 | { |
532 | case GPOT_SAMPLER1D: |
533 | case GPOT_SAMPLER2D: |
534 | case GPOT_SAMPLER3D: |
535 | case GPOT_SAMPLERCUBE: |
536 | case GPOT_SAMPLER2DMS: |
537 | return true; |
538 | default: |
539 | return false; |
540 | } |
541 | } |
542 | |
543 | bool Shader::isTexture(GpuParamObjectType type) |
544 | { |
545 | switch(type) |
546 | { |
547 | case GPOT_TEXTURE1D: |
548 | case GPOT_TEXTURE2D: |
549 | case GPOT_TEXTURE3D: |
550 | case GPOT_TEXTURECUBE: |
551 | case GPOT_TEXTURE2DMS: |
552 | case GPOT_TEXTURE1DARRAY: |
553 | case GPOT_TEXTURE2DARRAY: |
554 | case GPOT_TEXTURE2DMSARRAY: |
555 | case GPOT_TEXTURECUBEARRAY: |
556 | return true; |
557 | default: |
558 | return false; |
559 | } |
560 | } |
561 | |
562 | bool Shader::isLoadStoreTexture(GpuParamObjectType type) |
563 | { |
564 | switch (type) |
565 | { |
566 | case GPOT_RWTEXTURE1D: |
567 | case GPOT_RWTEXTURE2D: |
568 | case GPOT_RWTEXTURE3D: |
569 | case GPOT_RWTEXTURE2DMS: |
570 | case GPOT_RWTEXTURE1DARRAY: |
571 | case GPOT_RWTEXTURE2DARRAY: |
572 | case GPOT_RWTEXTURE2DMSARRAY: |
573 | return true; |
574 | default: |
575 | return false; |
576 | } |
577 | } |
578 | |
579 | bool Shader::isBuffer(GpuParamObjectType type) |
580 | { |
581 | switch(type) |
582 | { |
583 | case GPOT_BYTE_BUFFER: |
584 | case GPOT_STRUCTURED_BUFFER: |
585 | case GPOT_RWBYTE_BUFFER: |
586 | case GPOT_RWAPPEND_BUFFER: |
587 | case GPOT_RWCONSUME_BUFFER: |
588 | case GPOT_RWSTRUCTURED_BUFFER: |
589 | case GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER: |
590 | case GPOT_RWTYPED_BUFFER: |
591 | return true; |
592 | default: |
593 | return false; |
594 | } |
595 | } |
596 | |
597 | UINT32 Shader::getDataParamSize(GpuParamDataType type) |
598 | { |
599 | static const GpuDataParamInfos PARAM_SIZES; |
600 | |
601 | UINT32 idx = (UINT32)type; |
602 | if (idx < sizeof(GpuParams::PARAM_SIZES.lookup)) |
603 | return GpuParams::PARAM_SIZES.lookup[idx].size; |
604 | |
605 | return 0; |
606 | } |
607 | |
608 | HShader Shader::create(const String& name, const SHADER_DESC& desc) |
609 | { |
610 | SPtr<Shader> newShader = _createPtr(name, desc); |
611 | |
612 | return static_resource_cast<Shader>(gResources()._createResourceHandle(newShader)); |
613 | } |
614 | |
615 | SPtr<Shader> Shader::_createPtr(const String& name, const SHADER_DESC& desc) |
616 | { |
617 | UINT32 id = ct::Shader::mNextShaderId.fetch_add(1, std::memory_order_relaxed); |
618 | assert(id < std::numeric_limits<UINT32>::max() && "Created too many shaders, reached maximum id." ); |
619 | |
620 | SPtr<Shader> newShader = bs_core_ptr<Shader>(new (bs_alloc<Shader>()) Shader(name, desc, id)); |
621 | newShader->_setThisPtr(newShader); |
622 | newShader->initialize(); |
623 | |
624 | return newShader; |
625 | } |
626 | |
627 | SPtr<Shader> Shader::createEmpty() |
628 | { |
629 | UINT32 id = ct::Shader::mNextShaderId.fetch_add(1, std::memory_order_relaxed); |
630 | assert(id < std::numeric_limits<UINT32>::max() && "Created too many shaders, reached maximum id." ); |
631 | |
632 | SPtr<Shader> newShader = bs_core_ptr<Shader>(new (bs_alloc<Shader>()) Shader(id)); |
633 | newShader->_setThisPtr(newShader); |
634 | |
635 | return newShader; |
636 | } |
637 | |
638 | RTTITypeBase* Shader::getRTTIStatic() |
639 | { |
640 | return ShaderRTTI::instance(); |
641 | } |
642 | |
643 | RTTITypeBase* Shader::getRTTI() const |
644 | { |
645 | return Shader::getRTTIStatic(); |
646 | } |
647 | |
648 | RTTITypeBase* ShaderMetaData::getRTTIStatic() |
649 | { |
650 | return ShaderMetaDataRTTI::instance(); |
651 | } |
652 | |
653 | RTTITypeBase* ShaderMetaData::getRTTI() const |
654 | { |
655 | return ShaderMetaData::getRTTIStatic(); |
656 | } |
657 | |
658 | namespace ct |
659 | { |
660 | std::atomic<UINT32> Shader::mNextShaderId; |
661 | |
662 | Shader::Shader(const String& name, const SHADER_DESC& desc, UINT32 id) |
663 | :TShader(name, desc, id) |
664 | { |
665 | |
666 | } |
667 | |
668 | SPtr<Shader> Shader::create(const String& name, const SHADER_DESC& desc) |
669 | { |
670 | UINT32 id = mNextShaderId.fetch_add(1, std::memory_order_relaxed); |
671 | assert(id < std::numeric_limits<UINT32>::max() && "Created too many shaders, reached maximum id." ); |
672 | |
673 | Shader* shaderCore = new (bs_alloc<Shader>()) Shader(name, desc, id); |
674 | SPtr<Shader> shaderCorePtr = bs_shared_ptr<Shader>(shaderCore); |
675 | shaderCorePtr->_setThisPtr(shaderCorePtr); |
676 | shaderCorePtr->initialize(); |
677 | |
678 | return shaderCorePtr; |
679 | } |
680 | } |
681 | } |