Cogs.Core
PipelineStatesWebGPU.cpp
1#include "PipelineStatesWebGPU.h"
2
3#include "GraphicsDeviceWebGPU.h"
4
5#include "Foundation/Logging/Logger.h"
6
7namespace{
8 Cogs::Logging::Log logger = Cogs::Logging::getLogger("PipelineStatesWebGPU");
9
10 WGPUBlendOperation wgpu(Cogs::BlendState::BlendOperation opp)
11 {
12 if(opp == Cogs::BlendState::BlendOperation::Add)
13 return WGPUBlendOperation_Add;
14 if(opp == Cogs::BlendState::BlendOperation::Subtract)
15 return WGPUBlendOperation_Subtract;
16 if(opp == Cogs::BlendState::BlendOperation::ReverseSubtract)
17 return WGPUBlendOperation_ReverseSubtract;
18 if(opp == Cogs::BlendState::BlendOperation::Min)
19 return WGPUBlendOperation_Min;
20 if(opp == Cogs::BlendState::BlendOperation::Max)
21 return WGPUBlendOperation_Max;
22 assert(false);
23 return WGPUBlendOperation_Add;
24 }
25
26 WGPUBlendFactor wgpu(Cogs::BlendState::Blend blend)
27 {
28 if(blend == Cogs::BlendState::Blend::Zero)
29 return WGPUBlendFactor_Zero;
30 if(blend == Cogs::BlendState::Blend::One)
31 return WGPUBlendFactor_One;
32 if(blend == Cogs::BlendState::Blend::SourceColor)
33 return WGPUBlendFactor_Src;
34 if(blend == Cogs::BlendState::Blend::InverseSourceColor)
35 return WGPUBlendFactor_OneMinusSrc;
36 if(blend == Cogs::BlendState::Blend::SourceAlpha)
37 return WGPUBlendFactor_SrcAlpha;
38 if(blend == Cogs::BlendState::Blend::InverseSourceAlpha)
39 return WGPUBlendFactor_OneMinusSrcAlpha;
40 if(blend == Cogs::BlendState::Blend::DestinationAlpha)
41 return WGPUBlendFactor_DstAlpha;
42 if(blend == Cogs::BlendState::Blend::InverseDestinationAlpha)
43 return WGPUBlendFactor_OneMinusDstAlpha;
44 if(blend == Cogs::BlendState::Blend::DestinationColor)
45 return WGPUBlendFactor_Dst;
46 if(blend == Cogs::BlendState::Blend::InverseDestinationColor)
47 return WGPUBlendFactor_OneMinusDst;
48 if(blend == Cogs::BlendState::Blend::SourceAlphaSaturate)
49 return WGPUBlendFactor_SrcAlphaSaturated;
50 if(blend == Cogs::BlendState::Blend::BlendFactor)
51 return WGPUBlendFactor_Constant;
52 if(blend == Cogs::BlendState::Blend::InverseBlendFactor)
53 return WGPUBlendFactor_OneMinusConstant;
54 assert(false);
55 return WGPUBlendFactor_Zero;
56 }
57}
58
59namespace Cogs{
60
61 void PipelineStatesWebGPU::initialize(GraphicsDeviceWebGPU *device)
62 {
63 graphics_device = device;
64 }
65
66 size_t PipelineStatesWebGPU::renderPipelineHash(EffectHandle effectHandle,
67 InputLayoutHandle inputLayoutHandle,
68 PrimitiveType primitiveType,
69 RasterizerStateHandle rasterizeStateHandle,
70 DepthStencilStateHandle depthStencilStateHandle,
71 BlendStateHandle blendStateHandle,
72 RenderTargetHandle renderTargetHandle,
73 DepthStencilHandle depthStencilHandle,
74 WGPUIndexFormat stripIndexFormat)
75 {
76 EffectsWebGPU &effects = graphics_device->effects;
77 BuffersWebGPU &buffers = graphics_device->buffers;
78 RenderTargetsWebGPU &render_targets = graphics_device->renderTargets;
79
80 size_t pso_hash = Cogs::hash();
81 if (HandleIsValid(effectHandle)) {
82 EffectWebGPU& effect = effects.effects[effectHandle];
83 pso_hash = effect.hash(pso_hash);
84 }
85 if (HandleIsValid(inputLayoutHandle)) {
86 InputLayoutWebGPU& layout = buffers.inputLayouts[inputLayoutHandle];
87 pso_hash = layout.hash(pso_hash);
88 }
89 pso_hash = Cogs::hash(primitiveType, pso_hash);
90 pso_hash = Cogs::hash(rasterizeStateHandle.handle, pso_hash);
91 pso_hash = Cogs::hash(depthStencilStateHandle.handle, pso_hash);
92 pso_hash = Cogs::hash(blendStateHandle.handle, pso_hash);
93 if (HandleIsValid(renderTargetHandle)) {
94 RenderTargetWebGPU& render_target = render_targets.render_targets[renderTargetHandle];
95 pso_hash = Cogs::hash(render_target.count, pso_hash);
96 pso_hash = Cogs::hash(render_target.samples, pso_hash);
97 for(uint32_t i=0; i<render_target.count; i++){
98 pso_hash = Cogs::hash(render_target.format[i], pso_hash);
99 }
100 //pso_hash = render_target.hash(pso_hash);
101 }
102 if (HandleIsValid(depthStencilHandle)) {
103 DepthStencilTargetWebGPU& depth_target = render_targets.depth_stencil_targets[depthStencilHandle];
104 pso_hash = Cogs::hash(depth_target.samples, pso_hash);
105 pso_hash = Cogs::hash(depth_target.format, pso_hash);
106 //pso_hash = depth_target.hash(pso_hash);
107 }
108 pso_hash = Cogs::hash(static_cast<int>(stripIndexFormat), pso_hash);
109 return pso_hash;
110 }
111 RenderPipelineHandle PipelineStatesWebGPU::loadRenderPipeline(EffectHandle effectHandle,
112 InputLayoutHandle inputLayoutHandle,
113 PrimitiveType primitiveType,
114 RasterizerStateHandle rasterizeStateHandle,
115 DepthStencilStateHandle depthStencilStateHandle,
116 BlendStateHandle blendStateHandle,
117 RenderTargetHandle renderTargetHandle,
118 DepthStencilHandle depthStencilHandle,
119 WGPUIndexFormat stripIndexFormat)
120 {
121 WGPUDevice device = graphics_device->device;
122 BuffersWebGPU &buffers = graphics_device->buffers;
123 ResourceCountersWebGPU &counters = graphics_device->counters;
124 RenderTargetsWebGPU &renderTargets = graphics_device->renderTargets;
125
126 size_t pso_hash = renderPipelineHash(effectHandle,
127 inputLayoutHandle,
128 primitiveType,
129 rasterizeStateHandle,
130 depthStencilStateHandle,
131 blendStateHandle,
132 renderTargetHandle,
133 depthStencilHandle,
134 stripIndexFormat);
135 auto iter = renderPipelineHashMap.find(pso_hash);
136 if(iter != renderPipelineHashMap.end()){
137 return iter->second;
138 }
139
140 EffectWebGPU &effect = graphics_device->effects.effects[effectHandle];
141 const RasterizerState &rs =
142 rasterizeStateHandle ?
143 *reinterpret_cast<RasterizerState*>(rasterizeStateHandle.handle):
145 // assert(rs.wireFrame == false); // TODO
146 // assert(rs.multiSample == true); // TODO
147 // assert(rs.scissor == true); // TODO
148 // assert(rs.noDepthClip == false); // TODO O requres optional feature "depth-clip-control"
149 const DepthStencilState &ds =
150 depthStencilStateHandle ?
151 *reinterpret_cast<DepthStencilState*>(depthStencilStateHandle.handle) :
153 const BlendState &bsc =
154 blendStateHandle ?
155 reinterpret_cast<BlendState*>(blendStateHandle.handle)[0] :
157 const BlendState &bsa =
158 blendStateHandle ?
159 reinterpret_cast<BlendState*>(blendStateHandle.handle)[1] :
161
162 LOG_INFO(logger, "PipelineStateLoad %s", effect.name.c_str());
163
164 WGPURenderPipelineDescriptor desc = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT;
165 desc.label = {effect.name.c_str(), WGPU_STRLEN};
166 desc.layout = nullptr;
167 WGPUPipelineLayout pipeline_layout;
168 WGPUBindGroupLayout bind_group_layout;
169 {
170 WGPUBindGroupLayoutEntry layoutEntryList[EffectWebGPU::maxConstantBuffers];
171 size_t numConstantBufferBindings = 0;
172 const WebGPUConstantBufferBinding* bindings;
173 bindings = graphics_device->effects.getConstantBufferBindings(effectHandle, numConstantBufferBindings);
174 for (size_t i = 0; i < numConstantBufferBindings; i++) {
175 assert(bindings[i].group == 0);
176 layoutEntryList[i] = bindings[i].bg_ent;
177 }
178 WGPUBindGroupLayoutDescriptor bind_group_layout_desc = WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT;
179 bind_group_layout_desc.label = {effect.name.c_str(), WGPU_STRLEN};
180 bind_group_layout_desc.entryCount = numConstantBufferBindings;
181 bind_group_layout_desc.entries = layoutEntryList;
182 bind_group_layout = wgpuDeviceCreateBindGroupLayout(device, &bind_group_layout_desc);
183 counters.bind_group_layout++;
184
185 WGPUPipelineLayoutDescriptor pipeline_layout_desc = WGPU_PIPELINE_LAYOUT_DESCRIPTOR_INIT;
186 pipeline_layout_desc.bindGroupLayoutCount = 1;
187 pipeline_layout_desc.bindGroupLayouts = &bind_group_layout;
188 pipeline_layout = wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_desc);
189 counters.pipeline_layout++;
190 desc.label = {effect.name.c_str(), WGPU_STRLEN};
191 desc.layout = pipeline_layout;
192 }
193
194 WGPUPrimitiveState &primitive_state = desc.primitive;
195 {
196 assert(primitiveType < PrimitiveType::TriangleListAdjacency); // WebGPU does not support advanced primitives
197 if(primitiveType == PrimitiveType::PointList){
198 primitive_state.topology = WGPUPrimitiveTopology_PointList;
199 primitive_state.stripIndexFormat = WGPUIndexFormat_Undefined;
200 }
201 else if(primitiveType == PrimitiveType::LineList){
202 primitive_state.topology = WGPUPrimitiveTopology_LineList;
203 primitive_state.stripIndexFormat = WGPUIndexFormat_Undefined;
204 }
205 else if(primitiveType == PrimitiveType::LineStrip){
206 primitive_state.topology = WGPUPrimitiveTopology_LineStrip;
207 primitive_state.stripIndexFormat = stripIndexFormat != WGPUIndexFormat_Undefined ? stripIndexFormat : WGPUIndexFormat_Uint32;
208 }
209 else if(primitiveType == PrimitiveType::TriangleList){
210 primitive_state.topology = WGPUPrimitiveTopology_TriangleList;
211 primitive_state.stripIndexFormat = WGPUIndexFormat_Undefined;
212 }
213 else if(primitiveType == PrimitiveType::TriangleStrip){
214 primitive_state.topology = WGPUPrimitiveTopology_TriangleStrip;
215 primitive_state.stripIndexFormat = stripIndexFormat != WGPUIndexFormat_Undefined ? stripIndexFormat : WGPUIndexFormat_Uint32;
216 }
217 else{
218 assert(false);
219 }
220
221 if(rs.frontCounterClockwise)
222 primitive_state.frontFace = WGPUFrontFace_CCW;
223 else
224 primitive_state.frontFace = WGPUFrontFace_CW;
225 if(rs.cullMode == RasterizerState::Front)
226 primitive_state.cullMode = WGPUCullMode_Front;
227 else if(rs.cullMode == RasterizerState::Back)
228 primitive_state.cullMode = WGPUCullMode_Back;
229 else
230 primitive_state.cullMode = WGPUCullMode_None;
231 }
232
233 WGPUVertexState &vertex_state = desc.vertex;
234 {
235 vertex_state.module = effect.vs_module;
236 vertex_state.entryPoint = {effect.vs_entry.c_str(), WGPU_STRLEN};
237 vertex_state.constantCount = 0;
238 vertex_state.constants = nullptr;
239 if (HandleIsValid(inputLayoutHandle)) {
240 InputLayoutWebGPU& layout = buffers.inputLayouts[inputLayoutHandle];
241 vertex_state.bufferCount = (uint32_t)layout.vertex_buffer_layout.size();
242 vertex_state.buffers = layout.vertex_buffer_layout.data();
243 }
244 }
245
246 bool use_swap_chain = !HandleIsValid(renderTargetHandle) && !HandleIsValid(depthStencilHandle);
247
248 uint32_t samples = 0;
249 WGPUDepthStencilState depthStencil = WGPU_DEPTH_STENCIL_STATE_INIT;
250 if(HandleIsValid(depthStencilHandle) || use_swap_chain){
251 if(use_swap_chain){
252 SwapChainWebGPU &defaultSwapChain = graphics_device->defaultSwapChain;
253 depthStencil.format = defaultSwapChain.depth_format;
254 samples = defaultSwapChain.samples;
255 }
256 else{
257 DepthStencilTargetWebGPU &dst = renderTargets.depth_stencil_targets[depthStencilHandle];
258 depthStencil.format = dst.format;
259 samples = dst.samples;
260 }
261
262 if(ds.depthEnabled){
263 depthStencil.depthWriteEnabled = static_cast<WGPUOptionalBool>(ds.writeEnabled);
264
265 if(ds.depthFunction == DepthStencilState::Never)
266 depthStencil.depthCompare = WGPUCompareFunction_Never;
267 else if(ds.depthFunction == DepthStencilState::Less)
268 depthStencil.depthCompare = WGPUCompareFunction_Less;
269 else if(ds.depthFunction == DepthStencilState::LessOrEqual)
270 depthStencil.depthCompare = WGPUCompareFunction_LessEqual;
271 else if(ds.depthFunction == DepthStencilState::Equal)
272 depthStencil.depthCompare = WGPUCompareFunction_Equal;
273 else if(ds.depthFunction == DepthStencilState::GreaterOrEqual)
274 depthStencil.depthCompare = WGPUCompareFunction_GreaterEqual;
275 else if(ds.depthFunction == DepthStencilState::Greater)
276 depthStencil.depthCompare = WGPUCompareFunction_Greater;
277 else if(ds.depthFunction == DepthStencilState::NotEqual)
278 depthStencil.depthCompare = WGPUCompareFunction_NotEqual;
279 else if(ds.depthFunction == DepthStencilState::Always)
280 depthStencil.depthCompare = WGPUCompareFunction_Always;
281 else
282 assert(false);
283 }
284 else{
285 depthStencil.depthWriteEnabled = WGPUOptionalBool(false);
286 depthStencil.depthCompare = WGPUCompareFunction_Always;
287 }
288
289 depthStencil.stencilFront.compare = WGPUCompareFunction_Always;
290 depthStencil.stencilFront.failOp = WGPUStencilOperation_Keep;
291 depthStencil.stencilFront.depthFailOp = WGPUStencilOperation_Keep;
292 depthStencil.stencilFront.passOp = WGPUStencilOperation_Keep;
293
294 depthStencil.stencilBack.compare = WGPUCompareFunction_Always;
295 depthStencil.stencilBack.failOp = WGPUStencilOperation_Keep;
296 depthStencil.stencilBack.depthFailOp = WGPUStencilOperation_Keep;
297 depthStencil.stencilBack.passOp = WGPUStencilOperation_Keep;
298
299 depthStencil.stencilReadMask = 0;
300 depthStencil.stencilWriteMask = 0;
301
302 depthStencil.depthBias = (int32_t)rs.depthBias;
303 depthStencil.depthBiasSlopeScale = rs.slopeScaledDepthBias;
304 depthStencil.depthBiasClamp = rs.depthBiasClamp;
305
306 if(primitiveType == PrimitiveType::PointList ||
307 primitiveType == PrimitiveType::LineList ||
308 primitiveType == PrimitiveType::LineStrip){
309 if(depthStencil.depthBias != 0){
310 depthStencil.depthBias = 0;
311 LOG_INFO_ONCE(logger, "Setting depthBias to 0 for points and lines (%s).", effect.name.c_str());
312 }
313 if(depthStencil.depthBiasSlopeScale != 0.0f){
314 depthStencil.depthBiasSlopeScale = 0.0f;
315 LOG_INFO_ONCE(logger, "Setting depthBiasSlopeScale to 0.0 for points and lines (%s).", effect.name.c_str());
316 }
317 if(depthStencil.depthBiasClamp != 0.0f){
318 depthStencil.depthBiasClamp = 0.0f;
319 LOG_INFO_ONCE(logger, "Setting depthBiasClamp to 0.0 for points and lines (%s).", effect.name.c_str());
320 }
321 }
322
323 desc.depthStencil = &depthStencil;
324 }
325
326 WGPUColorTargetState color_target[8] = {};
327 for(uint32_t i=0; i<sizeof(color_target)/sizeof(color_target[0]); i++){
328 color_target[i] = WGPU_COLOR_TARGET_STATE_INIT;
329 }
330 uint32_t color_target_count = 0;
331 if(HandleIsValid(renderTargetHandle)){
332 RenderTargetWebGPU &rt = renderTargets.render_targets[renderTargetHandle];
333 samples = glm::max(rt.samples, samples);
334 color_target_count = rt.count;
335 for(uint32_t i=0; i<rt.count; i++){
336 color_target[i].format = rt.format[i];
337 color_target[i].writeMask = WGPUColorWriteMask_All;
338 }
339 }
340 else if(use_swap_chain){
341 SwapChainWebGPU &defaultSwapChain = graphics_device->defaultSwapChain;
342 color_target_count = 1;
343 color_target[0].format = defaultSwapChain.color_format;
344 color_target[0].writeMask = WGPUColorWriteMask_All;
345 }
346
347 WGPUBlendState blend_state = WGPU_BLEND_STATE_INIT;
348 if(bsc.enabled || bsa.enabled){
349// assert(bsc.enabled && bsa.enabled);
350 blend_state.color.operation = wgpu(bsc.operation);
351 blend_state.color.srcFactor = wgpu(bsc.sourceBlend);
352 blend_state.color.dstFactor = wgpu(bsc.destinationBlend);
353 blend_state.alpha.operation = wgpu(bsa.operation);
354 blend_state.alpha.srcFactor = wgpu(bsa.sourceBlend);
355 blend_state.alpha.dstFactor = wgpu(bsa.destinationBlend);
356 for(uint32_t i=0; i<color_target_count; i++){
357 color_target[i].blend = &blend_state; // TODO different blend states?
358 }
359 }
360
361 WGPUFragmentState fragment = WGPU_FRAGMENT_STATE_INIT;
362 if(effect.fs_module){
363 fragment.module = effect.fs_module;
364 fragment.entryPoint = {effect.fs_entry.c_str(), WGPU_STRLEN};
365 fragment.constantCount = 0;
366 fragment.constants = nullptr;
367 if(color_target_count > 0){
368 fragment.targetCount = color_target_count;
369 fragment.targets = color_target;
370 }
371 desc.fragment = &fragment;
372 }
373
374 WGPUMultisampleState &multisample = desc.multisample;
375 {
376 // WebGPU only supports sample counts 1 and 4.
377 multisample.count = samples > 1 ? 4 : 1;
378 multisample.mask = ~0x00000000u;
379 multisample.alphaToCoverageEnabled = false;
380 }
381
382 WGPURenderPipeline pipeline = wgpuDeviceCreateRenderPipeline(device, &desc);
383 counters.render_pipeline++;
384 // TODO async pipeline creation
385
386 RenderPipelineWebGPU pipelineState = {};
387 pipelineState.hash = pso_hash;
388 pipelineState.effect = effectHandle;
389 pipelineState.inputLayoutHandle = inputLayoutHandle;
390 pipelineState.primitiveType = primitiveType;
391 pipelineState.rasterizeStateHandle = rasterizeStateHandle;
392 pipelineState.depthStencilStateHandle = depthStencilStateHandle;
393 pipelineState.blendStateHandle = blendStateHandle;
394 pipelineState.renderTargetHandle = renderTargetHandle;
395 pipelineState.depthStencilHandle = depthStencilHandle;
396
397 pipelineState.pipeline = pipeline;
398 pipelineState.pipeline_layout = pipeline_layout;
399 pipelineState.bind_group_layout = bind_group_layout;
400
401 auto handle = this->renderPipeline.addResource(std::move(pipelineState));
402 renderPipelineHashMap.insert({pso_hash, handle});
403 return handle;
404 }
405
406 ComputePipelineHandle PipelineStatesWebGPU::loadComputePipeline(EffectHandle effectHandle)
407 {
408 WGPUDevice device = graphics_device->device;
409
410 size_t pso_hash = Cogs::hash();
411 pso_hash = Cogs::hash(effectHandle.handle, pso_hash);
412 auto iter = computePipelineHashMap.find(pso_hash);
413 if(iter != computePipelineHashMap.end()){
414 return iter->second;
415 }
416
417 ResourceCountersWebGPU &counters = graphics_device->counters;
418 EffectWebGPU &effect = graphics_device->effects.effects[effectHandle];
419
420 LOG_INFO(logger, "PipelineStateLoad %s", effect.name.c_str());
421
422 WGPUComputePipelineDescriptor desc = WGPU_COMPUTE_PIPELINE_DESCRIPTOR_INIT;
423 desc.label = {effect.name.c_str(), WGPU_STRLEN};
424 desc.layout = nullptr; // Let WebGPU figure out layout?
425 WGPUComputeState &compute = desc.compute;
426 compute.module = effect.cs_module;
427 compute.entryPoint = {effect.cs_entry.c_str(), WGPU_STRLEN};
428 compute.constantCount = 0; // TODO
429 compute.constants = nullptr; // TODO
430 WGPUComputePipeline pipeline = wgpuDeviceCreateComputePipeline(device, &desc);
431 counters.compute_pipeline++;
432 // TODO async pipeline creation
433
434 uint32_t groupIndex = 0;
435 WGPUBindGroupLayout layout = wgpuComputePipelineGetBindGroupLayout(pipeline, groupIndex);
436 // TODO create our own bind groups?
437
438 ComputePipelineWebGPU pipelineState = {};
439 pipelineState.hash = pso_hash;
440 pipelineState.effect = effectHandle;
441
442 pipelineState.pipeline = pipeline;
443 pipelineState.layout = layout;
444
445 auto handle = this->computePipeline.addResource(std::move(pipelineState));
446 computePipelineHashMap.insert({pso_hash, handle});
447 return handle;
448 }
449
450 void PipelineStatesWebGPU::releaseRenderPipeline(RenderPipelineHandle handle)
451 {
452 ResourceCountersWebGPU &counters = graphics_device->counters;
453 RenderPipelineWebGPU &pipeline = renderPipeline[handle];
454
455 wgpuRenderPipelineRelease(pipeline.pipeline);
456 counters.render_pipeline--;
457 wgpuPipelineLayoutRelease(pipeline.pipeline_layout);
458 counters.pipeline_layout--;
459 wgpuBindGroupLayoutRelease(pipeline.bind_group_layout);
460 counters.bind_group_layout--;
461
462 size_t hash = pipeline.hash;
463 renderPipelineHashMap.erase(hash);
464 renderPipeline.removeResource(handle);
465 }
466
467 void PipelineStatesWebGPU::releaseComputePipeline(ComputePipelineHandle handle)
468 {
469 ResourceCountersWebGPU &counters = graphics_device->counters;
470 ComputePipelineWebGPU &pipeline = computePipeline[handle];
471
472 wgpuBindGroupLayoutRelease(pipeline.layout);
473 wgpuComputePipelineRelease(pipeline.pipeline);
474 counters.compute_pipeline--;
475
476 size_t hash = pipeline.hash;
477 computePipelineHashMap.erase(hash);
478 computePipeline.removeResource(handle);
479 }
480
481 void PipelineStatesWebGPU::releaseResources()
482 {
483 std::vector<RenderPipelineHandle> renderPipelineHandles;
484 renderPipelineHandles.reserve(renderPipelineHashMap.size());
485 for(auto &tmp : renderPipelineHashMap){
486 renderPipelineHandles.push_back(tmp.second);
487 }
488 for(auto &tmp : renderPipelineHandles){
489 releaseRenderPipeline(tmp);
490 }
491
492 std::vector<ComputePipelineHandle> computePipelineHandles;
493 computePipelineHandles.reserve(computePipelineHashMap.size());
494 for(auto &tmp : computePipelineHashMap){
495 computePipelineHandles.push_back(tmp.second);
496 }
497 for(auto &tmp : computePipelineHandles){
498 releaseComputePipeline(tmp);
499 }
500 }
501
502}
Log implementation class.
Definition: LogManager.h:140
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
Definition: Common.h:112
@ PointList
List of points.
@ TriangleStrip
Triangle strip.
@ LineList
List of lines.
@ TriangleListAdjacency
List of triangles with adjacency.
@ LineStrip
Line strip.
@ TriangleList
List of triangles.
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
Definition: BlendState.h:55
Blend
Options for blend functions.
Definition: BlendState.h:14
@ Never
Never evaluates to true. When using this, all objects will fail depth testing.
@ GreaterOrEqual
Greater or equal depth.
@ NotEqual
Depth not equal evaluates to true.
@ Always
Always evaluates to true.
@ LessOrEqual
Less or equal depth.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
@ Back
Cull back facing primitives.
@ Front
Cull front facing primitives.