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/BsPass.h" |
4 | #include "RenderAPI/BsRasterizerState.h" |
5 | #include "RenderAPI/BsBlendState.h" |
6 | #include "RenderAPI/BsDepthStencilState.h" |
7 | #include "Private/RTTI/BsPassRTTI.h" |
8 | #include "Material/BsMaterial.h" |
9 | #include "RenderAPI/BsGpuParams.h" |
10 | #include "RenderAPI/BsGpuProgram.h" |
11 | #include "RenderAPI/BsGpuPipelineState.h" |
12 | #include "CoreThread/BsCoreObjectSync.h" |
13 | |
14 | namespace bs |
15 | { |
16 | template<bool Core> |
17 | TPass<Core>::TPass() |
18 | { |
19 | mData.stencilRefValue = 0; |
20 | } |
21 | |
22 | template<bool Core> |
23 | TPass<Core>::TPass(const PASS_DESC& data) |
24 | :mData(data) |
25 | { |
26 | |
27 | } |
28 | |
29 | template<bool Core> |
30 | bool TPass<Core>::hasBlending() const |
31 | { |
32 | bool transparent = false; |
33 | |
34 | for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++) |
35 | { |
36 | // Transparent if destination color is taken into account |
37 | if (mData.blendStateDesc.renderTargetDesc[i].dstBlend != BF_ZERO || |
38 | mData.blendStateDesc.renderTargetDesc[i].srcBlend == BF_DEST_COLOR || |
39 | mData.blendStateDesc.renderTargetDesc[i].srcBlend == BF_INV_DEST_COLOR || |
40 | mData.blendStateDesc.renderTargetDesc[i].srcBlend == BF_DEST_ALPHA || |
41 | mData.blendStateDesc.renderTargetDesc[i].srcBlend == BF_INV_DEST_ALPHA) |
42 | { |
43 | transparent = true; |
44 | } |
45 | } |
46 | |
47 | return transparent; |
48 | } |
49 | |
50 | template<bool Core> |
51 | const GPU_PROGRAM_DESC& TPass<Core>::getProgramDesc(bs::GpuProgramType type) const |
52 | { |
53 | switch(type) |
54 | { |
55 | default: |
56 | case GPT_VERTEX_PROGRAM: |
57 | return mData.vertexProgramDesc; |
58 | case GPT_FRAGMENT_PROGRAM: |
59 | return mData.fragmentProgramDesc; |
60 | case GPT_GEOMETRY_PROGRAM: |
61 | return mData.geometryProgramDesc; |
62 | case GPT_HULL_PROGRAM: |
63 | return mData.hullProgramDesc; |
64 | case GPT_DOMAIN_PROGRAM: |
65 | return mData.domainProgramDesc; |
66 | case GPT_COMPUTE_PROGRAM: |
67 | return mData.computeProgramDesc; |
68 | } |
69 | } |
70 | |
71 | template<bool Core> |
72 | void TPass<Core>::createPipelineState() |
73 | { |
74 | if (isCompute()) |
75 | { |
76 | SPtr<GpuProgramType> program = GpuProgramType::create(mData.computeProgramDesc); |
77 | mComputePipelineState = ComputePipelineStateType::create(program); |
78 | } |
79 | else |
80 | { |
81 | PipelineStateDescType desc; |
82 | |
83 | if(!mData.vertexProgramDesc.source.empty()) |
84 | desc.vertexProgram = GpuProgramType::create(mData.vertexProgramDesc); |
85 | |
86 | if(!mData.fragmentProgramDesc.source.empty()) |
87 | desc.fragmentProgram = GpuProgramType::create(mData.fragmentProgramDesc); |
88 | |
89 | if(!mData.geometryProgramDesc.source.empty()) |
90 | desc.geometryProgram = GpuProgramType::create(mData.geometryProgramDesc); |
91 | |
92 | if(!mData.hullProgramDesc.source.empty()) |
93 | desc.hullProgram = GpuProgramType::create(mData.hullProgramDesc); |
94 | |
95 | if(!mData.domainProgramDesc.source.empty()) |
96 | desc.domainProgram = GpuProgramType::create(mData.domainProgramDesc); |
97 | |
98 | desc.blendState = BlendStateType::create(mData.blendStateDesc); |
99 | desc.rasterizerState = RasterizerStateType::create(mData.rasterizerStateDesc); |
100 | desc.depthStencilState = DepthStencilStateType::create(mData.depthStencilStateDesc); |
101 | |
102 | mGraphicsPipelineState = GraphicsPipelineStateType::create(desc); |
103 | } |
104 | } |
105 | |
106 | template <bool Core> |
107 | template <class P> |
108 | void TPass<Core>::rttiEnumFields(P p) |
109 | { |
110 | p(mGraphicsPipelineState); |
111 | p(mComputePipelineState); |
112 | } |
113 | |
114 | template class TPass < false > ; |
115 | template class TPass < true >; |
116 | |
117 | Pass::Pass(const PASS_DESC& desc) |
118 | :TPass(desc) |
119 | { } |
120 | |
121 | SPtr<ct::Pass> Pass::getCore() const |
122 | { |
123 | return std::static_pointer_cast<ct::Pass>(mCoreSpecific); |
124 | } |
125 | |
126 | SPtr<ct::CoreObject> Pass::createCore() const |
127 | { |
128 | ct::Pass* pass = new (bs_alloc<ct::Pass>()) ct::Pass(mData); |
129 | |
130 | SPtr<ct::Pass> passPtr = bs_shared_ptr(pass); |
131 | passPtr->_setThisPtr(passPtr); |
132 | |
133 | return passPtr; |
134 | } |
135 | |
136 | void Pass::compile() |
137 | { |
138 | if(mComputePipelineState || mGraphicsPipelineState) |
139 | return; // Already compiled |
140 | |
141 | // Note: It's possible (and quite likely) the pass has already been compiled on the core thread, so this will |
142 | // unnecessarily recompile it. However syncing them in a clean way is not trivial hard and this method is currently |
143 | // not being used much (at all) to warrant a complex solution. Something to keep in mind for later though. |
144 | createPipelineState(); |
145 | |
146 | markCoreDirty(); |
147 | CoreObject::syncToCore(); |
148 | } |
149 | |
150 | CoreSyncData Pass::syncToCore(FrameAlloc* allocator) |
151 | { |
152 | UINT32 size = coreSyncGetElemSize(*this); |
153 | |
154 | UINT8* data = allocator->alloc(size); |
155 | |
156 | char* dataPtr = (char*)data; |
157 | dataPtr = coreSyncWriteElem(*this, dataPtr); |
158 | |
159 | return CoreSyncData(data, size); |
160 | } |
161 | |
162 | SPtr<Pass> Pass::create(const PASS_DESC& desc) |
163 | { |
164 | Pass* newPass = new (bs_alloc<Pass>()) Pass(desc); |
165 | SPtr<Pass> newPassPtr = bs_core_ptr<Pass>(newPass); |
166 | newPassPtr->_setThisPtr(newPassPtr); |
167 | newPassPtr->initialize(); |
168 | |
169 | return newPassPtr; |
170 | } |
171 | |
172 | SPtr<Pass> Pass::createEmpty() |
173 | { |
174 | Pass* newPass = new (bs_alloc<Pass>()) Pass(); |
175 | SPtr<Pass> newPassPtr = bs_core_ptr<Pass>(newPass); |
176 | newPassPtr->_setThisPtr(newPassPtr); |
177 | |
178 | return newPassPtr; |
179 | } |
180 | |
181 | RTTITypeBase* Pass::getRTTIStatic() |
182 | { |
183 | return PassRTTI::instance(); |
184 | } |
185 | |
186 | RTTITypeBase* Pass::getRTTI() const |
187 | { |
188 | return Pass::getRTTIStatic(); |
189 | } |
190 | |
191 | namespace ct |
192 | { |
193 | Pass::Pass(const PASS_DESC& desc) |
194 | :TPass(desc) |
195 | { } |
196 | |
197 | void Pass::compile() |
198 | { |
199 | if(mComputePipelineState || mGraphicsPipelineState) |
200 | return; // Already compiled |
201 | |
202 | createPipelineState(); |
203 | } |
204 | |
205 | void Pass::syncToCore(const CoreSyncData& data) |
206 | { |
207 | char* dataPtr = (char*)data.getBuffer(); |
208 | dataPtr = coreSyncReadElem(*this, dataPtr); |
209 | } |
210 | |
211 | SPtr<Pass> Pass::create(const PASS_DESC& desc) |
212 | { |
213 | Pass* newPass = new (bs_alloc<Pass>()) Pass(desc); |
214 | SPtr<Pass> newPassPtr = bs_shared_ptr<Pass>(newPass); |
215 | newPassPtr->_setThisPtr(newPassPtr); |
216 | newPassPtr->initialize(); |
217 | |
218 | return newPassPtr; |
219 | } |
220 | } |
221 | } |
222 |