FCT
载入中...
搜索中...
未找到
layout.cpp
浏览该文件的文档.
1#include "layout.h"
2#include "layout.hpp"
3#include "./PixelShader.h"
4#include "./VertexShader.h"
5#include "Context.hpp"
6#include "PassResource.h"
7#include "../RHI/BlendState.h"
11
12namespace FCT
13{
15 {
17 {
18 m_pixelLayout = m_vertexLayouts.begin()->second;
19 }
20 }
21
23 {
24 m_ctx = ctx;
25 }
26
27 void Layout::setFixedImage(std::string name, FCT::Image* image)
28 {
29 m_fixedImages[name] = image;
30 }
31
33 {
34 m_resourceLayout.addTexture(element);
36 {
37 m_vertexResourceLayout.addTexture(element);
38 }
40 {
41 m_pixelResourceLayout.addTexture(element);
42 }
46 }
47 void Layout::addUniformSlot(const UniformSlot& uniformSlot)
48 {
49 m_uniformLayouts[uniformSlot.getName()] = uniformSlot;
53
54 }
55
57 {
58 TextureElement element(
60 slot.name.c_str(),
62 addTextureSlot(element);
63 }
64
65 void Layout::addSamplerSlot(const SamplerSlot& samplerSlot)
66 {
67 // 检查是否已存在相同名字的SamplerSlot,避免重复添加
68 auto existingSampler = m_resourceLayout.findSampler(samplerSlot.getName());
69 if (existingSampler.getName() != nullptr && existingSampler.getName()[0] != '\0') {
70 return; // 已存在,不重复添加
71 }
72
73 m_resourceLayout.addSampler(samplerSlot);
74
75 if (samplerSlot.getShaderStages() & FCT::ShaderStage::Vertex)
76 {
77 m_vertexResourceLayout.addSampler(samplerSlot);
78 }
80 {
81 m_pixelResourceLayout.addSampler(samplerSlot);
82 }
83
87
88 }
89
91 {
92 uint32_t index = findNextAvailableIndex();
93 m_vertexLayouts[index] = vertexLayout;
94 m_hasVertexLayout = true;
98 }
99
101 {
102 m_pixelLayout = pixelLayout;
103 m_hasPixelLayout = true;
107 }
108
109
110 void Layout::removeTextureSlot(const char* name)
111 {
112 m_resourceLayout.removeTexture(name);
113
114 m_vertexResourceLayout.removeTexture(name);
115
116 m_pixelResourceLayout.removeTexture(name);
117
118 auto it = m_fixedImages.find(name);
119 if (it != m_fixedImages.end()) {
120 m_fixedImages.erase(it);
121 }
122
123 auto nameIt = m_textureNames.find(name);
124 if (nameIt != m_textureNames.end()) {
125 m_textureNames.erase(nameIt);
126 }
130 }
131
132 void Layout::attachPass(std::string passName)
133 {
134 m_ctx->pipeHub()
135 .passPipe.
136 subscribe<PassInfo>(
137 passName,
138 [this](PassInfo& info)
139 {
140 m_pass = &info.pass;
142 for (auto& texture : m_textureFromPass)
143 {
144 FCT::TextureElement element(
146 texture.first.c_str(),
147 getAllAfterTheStage(info.textureSlot[texture.first]),
149 addTextureSlot(element);
150 setFixedImage(texture.first,
151 texture.second);
152 }
153 },
154 [this]()
155 {
156 for (auto& texture : m_textureFromPass)
157 {
158 removeTextureSlot(texture.first.c_str());
159 }
160 m_textureFromPass.clear();
164 });
165 }
166
168 {
169 return std::move(Uniform(m_ctx,m_uniformLayouts[name]));
170 }
171
173 {
174 auto ret = m_ctx->createResource<FCT::ContextResource::VertexShader>();
175 for (auto& layout : m_vertexLayouts)
176 {
177 ret->addLayout(layout.first,layout.second);
178 }
179 ret->pixelLayout(m_pixelLayout);
180 for (auto& uniform : m_uniformLayouts)
181 {
182 ret->addUniform(uniform.second);
183 }
184 ret->resourceLayout(m_vertexResourceLayout);
185 ret->code(code);
186 ret->create();
187 return ret;
188 }
189
191 {
192 auto ret = m_ctx->createResource<FCT::ContextResource::PixelShader>();
193
194 for (auto& layout : m_uniformLayouts)
195 {
196 ret->addUniform(layout.second);
197 }
198 ret->pixelLayout(m_pixelLayout);
199 ret->resourceLayout(m_pixelResourceLayout);
200 ret->code(code);
201 ret->create();
202 return ret;
203 }
204
206 {
207 m_passResourceState.clear();
208
209 for (const auto& fixedImage : m_fixedImages)
210 {
211 m_passResourceState.bindTexture(fixedImage.first, fixedImage.second);
212 }
213
215 }
216
217 void Layout::bindUniform(const Uniform& uniform)
218 {
219 FCT::RHI::ConstBuffer* constBuffer = uniform;
220 std::string name = constBuffer->layout().getName();
221 m_passResourceState.bindUniform(name, uniform);
222 }
224 {
225 m_passResourceState.bindUniform(uniform->getConstBuffer()->layout().getName(), uniform);
226 }
227
228 void Layout::bindTexture(std::string name, FCT::Image* image)
229 {
230 m_passResourceState.bindTexture(name, image);
231 }
232
233 void Layout::bindSampler(std::string name, FCT::Sampler* sampler)
234 {
235 m_passResourceState.bindSampler(name, sampler);
236 }
237
239 {
240 m_pipelineState.vertexShader = shader;
241 }
242
244 {
245 m_pipelineState.pixelShader = shader;
246 }
247
248
250 {
251
252 }
253
255 {
256 size_t hash = 0;
257 boost::hash_combine(hash, vertexShader);
258 boost::hash_combine(hash, pixelShader);
259 boost::hash_combine(hash, blendState);
260 boost::hash_combine(hash, rasterizationState);
261 boost::hash_combine(hash, depthStencilState);
262 return hash;
263 }
264
273
275 {
276 boundTextures.clear();
277 boundSamplers.clear();
278 boundUniforms.clear();
279 }
280
281 void Layout::PassResourceState::bindTexture(const std::string& name, FCT::Image* image)
282 {
283 boundTextures[name] = image;
284 }
285
286 void Layout::PassResourceState::bindSampler(const std::string& name, FCT::Sampler* sampler)
287 {
288 boundSamplers[name] = sampler;
289 }
290
291 void Layout::PassResourceState::bindUniform(const std::string& name, const Uniform& uniform)
292 {
293 boundUniforms[name] = uniform;
294 }
295 void Layout::PassResourceState::bindUniform(const std::string& name, Uniform* uniform)
296 {
297 boundUniforms[name] = uniform->getConstBuffer();
298 }
299
301 {
302 size_t hash = 0;
303
304 for (const auto& tex : boundTextures) {
305 boost::hash_combine(hash, tex.first);
306 boost::hash_combine(hash, tex.second);
307 }
308
309 for (const auto& samp : boundSamplers) {
310 boost::hash_combine(hash, samp.first);
311 boost::hash_combine(hash, samp.second);
312 }
313
314 for (const auto& uni : boundUniforms) {
315 boost::hash_combine(hash, uni.first);
316 boost::hash_combine(hash, uni.second);
317 }
318
319 return hash;
320 }
321
323 {
324 for (auto& pair : m_passResources)
325 {
326 pair.second->release();
327 }
328 }
329
331 const std::function<FCT::PassResource*(const PassResourceState& state)>& creator)
332 {
333 auto hash = state.hash();
334 if (m_passResources.count(hash))
335 {
336 return m_passResources[hash];
337 } else
338 {
339 auto passResource = creator(state);
340 m_passResources[hash] = passResource;
341 return passResource;
342 }
343 }
344
346 {
347 for (auto& pair : m_pipelines)
348 {
349 pair.second->release();
350 }
351 }
352
354 const std::function<FCT::RHI::RasterizationPipeline*(const TraditionPipelineState& state)>& creator)
355 {
356 auto hash = state.hash();
357 if (m_pipelines.count(hash))
358 {
359 return m_pipelines[hash];
360 } else
361 {
362 auto pipeline = creator(state);
363 m_pipelines[hash] = pipeline;
364 return pipeline;
365 }
366 }
367
369 {
370 auto it = m_unhandledTextureSlots.begin();
371 while (it != m_unhandledTextureSlots.end())
372 {
373 FCT::ShaderStages usage;
374
376 {
377 ++it;
378 continue;
379 }
381 {
383 }
385 {
387 }
388 else
389 {
391 }
392 m_textureNames[it->name] = nullptr;
393 m_textureNames[it->name] = m_textureNames.find(it->name)->first.c_str();
395 addTextureSlot(element);
396
397 it = m_unhandledTextureSlots.erase(it);
398 }
399 }
400
402 {
405 }
406 return m_nextAvailableIndex++;
407 }
408
410 {
411 return m_passResourceCache.get(m_passResourceState, [this](const PassResourceState& state)
412 {
413 auto ret = m_ctx->createResource<FCT::PassResource>();
414 for (const auto& tex : state.boundTextures) {
415 ret->addTexture( tex.second,m_resourceLayout.findTexture(tex.first.c_str()));
416 }
417 for (const auto& samp : state.boundSamplers) {
418 ret->addSampler(samp.second,m_resourceLayout.findSampler(samp.first.c_str()));
419 }
420 for (const auto& uni : state.boundUniforms) {
421 ret->addConstBuffer(uni.second);
422 }
423 ret->create();
424 return ret;
425 });
426 }
427
429 {
430 return m_pipelineCache.get(m_pipelineState, [this](const TraditionPipelineState& state)
431 {
432 auto ret = m_ctx->createTraditionPipeline();
433
434 for (auto& layout : m_vertexLayouts)
435 {
436 ret->vertexLayout(layout.second);
437 }
438
439 ret->pixelLayout(m_pixelLayout);
440
441 if (state.vertexShader) {
442 ret->addResources(state.vertexShader);
443 }
444 if (state.pixelShader) {
445 ret->addResources(state.pixelShader);
446 }
447
448 if (state.blendState) {
449 ret->addResources(state.blendState);
450 }
451 if (state.rasterizationState) {
452 ret->addResources(state.rasterizationState);
453 }
454 if (state.depthStencilState) {
455 ret->addResources(state.depthStencilState);
456 }
457
458 if (m_pass) {
459 ret->bindPass(m_pass);
460 }
461
462 ret->create();
463 return ret;
464 });
465 }
466
467
469 {
470 for (auto& pair : m_vertexShaders) {
471 pair.second->release();
472 }
473 for (auto& pair : m_pixelShaders) {
474 pair.second->release();
475 }
476 }
477
479 const std::function<FCT::VertexShader*(const std::string& code)>& creator)
480 {
481 auto hash = std::hash<std::string>{}(code);
482 if (m_vertexShaders.count(hash))
483 {
484 return m_vertexShaders[hash];
485 }
486 else
487 {
488 auto shader = creator(code);
489 m_vertexShaders[hash] = shader;
490 return shader;
491 }
492 }
493
495 const std::function<FCT::PixelShader*(const std::string& code)>& creator)
496 {
497 auto hash = std::hash<std::string>{}(code);
498 if (m_pixelShaders.count(hash))
499 {
500 return m_pixelShaders[hash];
501 }
502 else
503 {
504 auto shader = creator(code);
505 m_pixelShaders[hash] = shader;
506 return shader;
507 }
508 }
509
511 const std::function<FCT::VertexShader*(const ShaderRef& ref)>& creator)
512 {
513 auto hash = ref.hash;
514 if (m_vertexShaders.count(hash))
515 {
516 return m_vertexShaders[hash];
517 }
518 else
519 {
520 auto shader = creator(ref);
521 m_vertexShaders[hash] = shader;
522 return shader;
523 }
524 }
525
527 const std::function<FCT::PixelShader*(const ShaderRef& ref)>& creator)
528 {
529 auto hash = ref.hash;
530 if (m_pixelShaders.count(hash))
531 {
532 return m_pixelShaders[hash];
533 }
534 else
535 {
536 auto shader = creator(ref);
537 m_pixelShaders[hash] = shader;
538 return shader;
539 }
540 }
541
542
544 {
545 return m_shaderCache.getVertexShader(code, [this](const std::string& code) -> FCT::VertexShader*
546 {
547 return allocateVertexShader(code);
548 });
549 }
550
552 {
553 return m_shaderCache.getPixelShader(code, [this](const std::string& code) -> FCT::PixelShader*
554 {
555 return allocatePixelShader(code);
556 });
557 }
558
560 {
561 return m_shaderCache.getVertexShader(ref, [this](const ShaderRef& ref) -> FCT::VertexShader*
562 {
563 return allocateVertexShader(ref.code);
564 });
565 }
566
568 {
569 return m_shaderCache.getPixelShader(ref, [this](const ShaderRef& ref) -> FCT::PixelShader*
570 {
571 return allocatePixelShader(ref.code);
572 });
573 }
574
575 ShaderRef Layout::cacheVertexShader(const std::string& code)
576 {
577 ShaderRef ref;
578 ref.code = code;
579 ref.hash = std::hash<std::string>{}(code);
582 return ref;
583 }
584
585 ShaderRef Layout::cachePixelShader(const std::string& code)
586 {
587 ShaderRef ref;
588 ref.code = code;
589 ref.hash = std::hash<std::string>{}(code);
592 return ref;
593 }
594
595 void Layout::bindVertexShader(std::string code)
596 {
597 auto shader = getCacheVertexShader(code);
598 bindVertexShader(shader);
599 }
600
601 void Layout::bindPixelShader(std::string code)
602 {
603 auto shader = getCachePixelShader(code);
604 bindPixelShader(shader);
605 }
606
608 {
609 auto shader = getCacheVertexShader(ref);
610 bindVertexShader(shader);
611 }
612
614 {
615 auto shader = getCachePixelShader(ref);
616 bindPixelShader(shader);
617 }
619 {
620 for (auto& shader : m_vertexShaders) {
621 if (shader.second) {
622 shader.second->release();
623 }
624 }
625 for (auto& shader : m_pixelShaders) {
626 if (shader.second) {
627 shader.second->release();
628 }
629 }
630 m_vertexShaders.clear();
631 m_pixelShaders.clear();
632 }
633
635 {
636 for (auto& resource : m_passResourceCache.m_passResources) {
637 if (resource.second) {
638 resource.second->release();
639 }
640 }
641 m_passResourceCache.m_passResources.clear();
642 }
643
645 {
646 for (auto& pipeline : m_pipelineCache.m_pipelines) {
647 if (pipeline.second) {
648 pipeline.second->release();
649 }
650 }
651 m_pipelineCache.m_pipelines.clear();
652 }
653
655 {
656 m_shaderCache.clear();
657 }
658}
constexpr const char * getName() const noexcept
std::map< std::string, FCT::ConstLayout > m_uniformLayouts
ShaderRef cachePixelShader(const std::string &code)
预缓存一个像素着色器并返回其引用。
ShaderCache m_shaderCache
void bindUniform(const Uniform &uniform)
绑定一个 Uniform 常量缓冲区。
std::unordered_map< std::string, const char * > m_textureNames
void clearPassResourceCache()
清空所有已缓存的 PassResource。
void removeTextureSlot(const char *name)
移除一个纹理资源槽位。
void setFixedImage(std::string name, FCT::Image *image)
设置一个固定的图像资源,该资源不会在 begin/end 之间被清除。
void processUnhandledTextureSlots()
FCT::ResourceLayout m_pixelResourceLayout
void begin()
开始一个渲染批次。
void attachPass(std::string passName)
将此 Layout 附加到一个渲染通道。
void setPixelLayout(const FCT::PixelLayout &pixelLayout)
设置像素(片元)着色器的输出布局。
bool m_hasVertexLayout
FCT::Context * m_ctx
void addVertexLayout(const FCT::VertexLayout &vertexLayout)
添加一个顶点布局。
void proccessArgs()
void bindSampler(std::string name, FCT::Sampler *sampler)
绑定一个采样器。
void clearPipelineCache()
清空所有已缓存的渲染管线。
uint32_t m_nextAvailableIndex
uint32_t findNextAvailableIndex()
void bindTexture(std::string name, FCT::Image *image)
绑定一个纹理。
FCT::ResourceLayout m_vertexResourceLayout
ShaderRef cacheVertexShader(const std::string &code)
预缓存一个顶点着色器并返回其引用。
std::map< std::string, Image * > m_textureFromPass
void end()
结束渲染批次。
VertexShader * getCacheVertexShader(std::string code)
std::unordered_map< std::string, FCT::Image * > m_fixedImages
TraditionPipelineState m_pipelineState
void bindVertexShader(std::string code)
绑定顶点着色器。
FCT::ResourceLayout m_resourceLayout
std::map< uint32_t, FCT::VertexLayout > m_vertexLayouts
FCT::RHI::RasterizationPipeline * getCurrentPipeline()
PassResourceState m_passResourceState
void addTextureSlot(const FCT::TextureSlot &element)
PassResourceCache m_passResourceCache
FCT::PixelLayout m_pixelLayout
PipelineCache m_pipelineCache
void bindPixelShader(std::string code)
绑定像素着色器。
bool m_hasPixelLayout
void addSamplerSlot(const SamplerSlot &samplerSlot)
添加一个采样器资源槽位。
FCT::RHI::Pass * m_pass
void ctx(FCT::Context *ctx)
重新设置 FCT 上下文。
void clearShaderCache()
清空所有已缓存的着色器。
FCT::PixelShader * allocatePixelShader(std::string code)
PixelShader * getCachePixelShader(std::string code)
Uniform allocateUniform(std::string name)
根据已定义的 UniformSlot 分配一个 Uniform 实例。
FCT::VertexShader * allocateVertexShader(std::string code)
FCT::PassResource * getCurrentPassResource()
void addUniformSlot(const UniformSlot &uniformSlot)
添加一个常量缓冲区(Uniform Buffer)的布局槽位。
std::vector< TextureSlot > m_unhandledTextureSlots
virtual void create()=0
void layout(const ConstLayout &layout)
constexpr ShaderStages getShaderStages() const noexcept
constexpr const char * getName() const noexcept
constexpr ShaderStages getShaderStages() const noexcept
FCT::PixelShader PixelShader
FCT::VertexShader VertexShader
FCT::SamplerElement SamplerSlot
FCT::ConstLayout UniformSlot
FCT::ShaderStages getAllAfterTheStage(FCT::ShaderStage stages)
FCT::PassResource * get(const PassResourceState &state, const std::function< FCT::PassResource *(const PassResourceState &state)> &creator)
std::unordered_map< size_t, FCT::PassResource * > m_passResources
std::unordered_map< std::string, FCT::RHI::ConstBuffer * > boundUniforms
void bindUniform(const std::string &name, const Uniform &uniform)
void bindTexture(const std::string &name, FCT::Image *image)
std::unordered_map< std::string, FCT::Image * > boundTextures
std::unordered_map< std::string, FCT::Sampler * > boundSamplers
void bindSampler(const std::string &name, FCT::Sampler *sampler)
std::unordered_map< size_t, FCT::RHI::RasterizationPipeline * > m_pipelines
FCT::RHI::RasterizationPipeline * get(const TraditionPipelineState &state, const std::function< FCT::RHI::RasterizationPipeline *(const TraditionPipelineState &state)> &creator)
FCT::VertexShader * getVertexShader(const std::string &code, const std::function< FCT::VertexShader *(const std::string &code)> &creator)
std::unordered_map< size_t, FCT::VertexShader * > m_vertexShaders
FCT::PixelShader * getPixelShader(const std::string &code, const std::function< FCT::PixelShader *(const std::string &code)> &creator)
std::unordered_map< size_t, FCT::PixelShader * > m_pixelShaders
FCT::DepthStencilState * depthStencilState
FCT::RasterizationState * rasterizationState
bool operator==(const TraditionPipelineState &other) const
std::map< std::string, Image * > textures
RHI::Pass & pass
std::map< std::string, ShaderStage > textureSlot
定义着色器代码的引用,包含代码本身、哈希值和类型。
std::string code
ShaderKind kind
定义一个纹理槽位,用于在着色器中绑定纹理。
std::string name
FCT::RHI::ConstBuffer * getConstBuffer() const