Cogs.Core
ContextGL20.cpp
1#include "ContextGL20.h"
2
3#include "BuffersGL20.h"
4#include "TexturesGL20.h"
5#include "EffectsGL20.h"
6#include "RenderTargetsGL20.h"
7#include "FormatsGL20.h"
8
9#include "Foundation/Logging/Logger.h"
10
11using namespace Cogs;
12
13namespace
14{
15 static Cogs::Logging::Log logger = Cogs::Logging::getLogger("ContextGL20");
16
17 GLenum Blends[] = {
18 GL_ZERO,
19 GL_ONE,
20 GL_SRC_COLOR,
21 GL_ONE_MINUS_SRC_COLOR,
22 GL_SRC_ALPHA,
23 GL_ONE_MINUS_SRC_ALPHA,
24 GL_DST_ALPHA,
25 GL_ONE_MINUS_DST_ALPHA,
26 GL_DST_COLOR,
27 GL_ONE_MINUS_DST_COLOR,
28 GL_SRC_ALPHA_SATURATE,
29 GL_CONSTANT_COLOR,
30 GL_ONE_MINUS_CONSTANT_COLOR
31 };
32 static_assert(sizeof(Blends) == sizeof(Blends[0]) * size_t(Cogs::BlendState::Blend::Count));
33
34 GLenum BlendOperations[] = {
35 GL_FUNC_ADD,
36 GL_FUNC_SUBTRACT,
37 GL_FUNC_REVERSE_SUBTRACT,
38 GL_MIN,
39 GL_MAX
40 };
41 static_assert(sizeof(BlendOperations) == sizeof(BlendOperations[0]) * size_t(Cogs::BlendState::BlendOperation::Count));
42
43}
44
45namespace Cogs
46{
47 namespace OpenGL20
48 {
49
50 GLenum DepthFunctions[] = {
51 GL_NEVER,
52 GL_LESS,
53 GL_LEQUAL,
54 GL_EQUAL,
55 GL_GEQUAL,
56 GL_GREATER,
57 GL_NOTEQUAL,
58 GL_ALWAYS,
59 };
60
61 const GLenum Framebuffers[] = {
62 GL_FRONT,
63 GL_BACK,
64 };
65
66 GLenum MappingModes[] = {
67 GL_READ_ONLY,
68 GL_WRITE_ONLY,
69 GL_READ_WRITE,
70 GL_INVALID_ENUM,
71 };
72 }
73
74 void copySubBuffer(GLenum /*dstTarget*/, GLuint dstBuffer, GLintptr dstOffset,
75 GLenum /*srcTarget*/, GLuint srcBuffer, GLintptr srcOffset, GLsizeiptr size)
76 {
77#ifndef __APPLE__
78 if (glCopyNamedBufferSubData) {
79 glCopyNamedBufferSubData(srcBuffer, dstBuffer, srcOffset, dstOffset, size);
80 } else
81#endif
82 {
83 glBindBuffer(GL_COPY_READ_BUFFER, srcBuffer);
84 glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
85 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, dstOffset, size);
86 glBindBuffer(GL_COPY_READ_BUFFER, 0);
87 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
88 }
89 }
90}
91
92Cogs::ContextGL20::ContextGL20() :
93 defaultSamplerStateHandle(SamplerStateHandle::NoHandle),
94 currentEffect(EffectHandle::NoHandle),
95 currentRenderTarget(RenderTargetHandle::NoHandle)
96{
97 for (size_t i = 0; i < sizeof(boundTextures)/sizeof(boundTextures[0]); ++i) {
98 boundTextures[i] = TextureHandle::NoHandle;
99 boundTarget[i] = 0;
100 }
101 for (size_t i = 0; i < sizeof(boundSamplerStates)/sizeof(boundSamplerStates[0]); ++i) {
102 boundSamplerStates[i] = SamplerStateHandle::NoHandle;
103 }
104}
105
106void Cogs::ContextGL20::initialize(CapabilitiesGL20 * capabilities, BuffersGL20 * buffers, TexturesGL20 * textures, EffectsGL20 * effects, RenderTargetsGL20 * renderTargets, GLSyncObjects* sync) {
107 this->capabilities = capabilities;
108 this->buffers = buffers;
109 this->textures = textures;
110 this->effects = effects;
111 this->renderTargets = renderTargets;
112 this->syncObjects = sync;
113 glGenVertexArrays(1, &vao);
114}
115
116void Cogs::ContextGL20::releaseResources() {
117 glDeleteVertexArrays(1, &vao);
118 vao = GL_ZERO;
119}
120
121// Avoid warnings from packing integer offset in GLvoid argument.
122#ifdef _WIN32
123#pragma warning(push)
124#pragma warning(disable : 4312)
125#endif
126
128{
129 syncObjects->signal(fenceHandle);
130}
131
132void Cogs::ContextGL20::setupVertexAttributes()
133{
134 for (size_t b = 0; b < iaState.numVertexBuffers; ++b) {
135 BufferGL20 &buffer = *iaState.currentVertexBuffers[b];
136 const VertexFormat &vertexFormat = *iaState.formats[b];
137 const GLsizei structSize = static_cast<GLsizei>(iaState.strides[b]);
138 const GLuint bufferId = static_cast<GLuint>(buffer.bufferId);
139
140 glBindBuffer(GL_ARRAY_BUFFER, bufferId);
141
142 for (size_t i = 0; i < vertexFormat.elements.size(); ++i) {
143 const VertexElement &element = vertexFormat.elements[i];
144 const GLint index = static_cast<GLint>(element.semanticIndex * NumAttributeSemanticsGL20 + static_cast<int>(element.semantic));
145
146 assert(this->currentAttributeMap && "Attribute map not valid.");
147 const GLint attributeIndex = this->currentAttributeMap[index];
148
149 if (attributeIndex != InvalidAttributeLocationGL20) {
150 const GLvoid * offset = reinterpret_cast<const GLvoid *>(element.offset);
151 const GLenum format = OpenGL20::ElementFormats[(int)element.format];
152 const unsigned int size = getFormatInfo(element.format)->elements;
153
154 if (element.inputType == InputType::InstanceData) {
156 for (GLuint a = 0; a < 4; ++a) {
157 glVertexAttribPointer(attributeIndex + a, 4, format, GLboolean(GL_TRUE), structSize, reinterpret_cast<const GLvoid *>(sizeof(GLfloat) * a * 4));
158 glEnableVertexAttribArray(attributeIndex + a);
159 glVertexAttribDivisor(attributeIndex + a, element.instanceStep);
160
161 this->enabledAttributes.push_back(attributeIndex);
162 }
163 } else {
164 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
165 glEnableVertexAttribArray(attributeIndex);
166 glVertexAttribDivisor(attributeIndex, element.instanceStep);
167 this->enabledAttributes.push_back(attributeIndex);
168 }
169 } else {
170 if(format == GL_UNSIGNED_INT_2_10_10_10_REV)
171 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
172 else
173 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
174 glEnableVertexAttribArray(attributeIndex);
175 this->enabledAttributes.push_back(attributeIndex);
176
177 glVertexAttribDivisor(attributeIndex, element.instanceStep);
178 }
179 }
180 }
181 }
182
183 if(iaState.currentIndexBuffer)
184 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iaState.currentIndexBuffer->bufferId);
185 else
186 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
187
188 this->needVertexAttributeSetup = false;
189}
190
191#ifdef _WIN32
192#pragma warning(pop)
193#endif
194
195void Cogs::ContextGL20::setIndexBuffer(IndexBufferHandle indexBufferHandle, uint32_t stride, uint32_t offset)
196{
197 assert(offset == 0);
198 if(indexBufferHandle == IndexBufferHandle::NoHandle){
199 iaState.currentIndexBuffer = nullptr;
200 iaState.indexBufferStride = 0;
201 return;
202 }
203 auto & buffer = this->buffers->buffers[indexBufferHandle];
204 iaState.currentIndexBuffer = &buffer;
205 iaState.indexBufferStride = stride ? stride : buffer.indexSize;
206}
207
208void Cogs::ContextGL20::setConstantBuffer(const ConstantBufferBindingHandle bufferBindingHandle, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t /*size*/)
209{
210 assert(offset == 0);
211 auto & effect = effects->effects[currentEffect];
212
213 const auto index = static_cast<GLuint>(bufferBindingHandle.handle & 0xFFFFFFFF);
214
215 if (HandleIsValid(bufferHandle) && index != GL_INVALID_INDEX) {
216 auto & buffer = this->buffers->buffers[bufferHandle];
217
218 glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.bufferId);
219 glUniformBlockBinding(this->currentProgramId, index, index);
220
221 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
222 for (auto & constantBuffer : effect.shaders[i].reflection.constantBuffers) {
223 if (constantBuffer.slot == index) {
224 constantBuffer.manual = true;
225 }
226 }
227 }
228 } else {
229 if (index != GL_INVALID_INDEX) {
230 glBindBufferBase(GL_UNIFORM_BUFFER, index, 0);
231 glUniformBlockBinding(this->currentProgramId, index, index);
232 }
233 }
234}
235
236void Cogs::ContextGL20::drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex)
237{
238 if(!HandleIsValid(this->currentEffect)){
239 LOG_INFO(logger, "Draw with no effect active.");
240 return;
241 }
242 if (this->needVertexAttributeSetup) {
243 this->setupVertexAttributes();
244 }
245 assert(iaState.currentIndexBuffer); // Must have index buffer bound
246
247 GLenum indexType = GL_UNSIGNED_INT;
248 if (iaState.indexBufferStride == 2) {
249 indexType = GL_UNSIGNED_SHORT;
250 }
251
252 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[primitiveType];
253 const GLsizei count = static_cast<GLsizei>(numIndexes ? numIndexes : iaState.currentIndexBuffer->count);
254 const GLvoid * indexOffset = reinterpret_cast<const GLvoid *>(startIndex * ((indexType == GL_UNSIGNED_INT) ? sizeof(GLuint) : sizeof(GLushort)));
255
256 preDraw();
257 glDrawElementsBaseVertex(glPrimitiveType, count, indexType, (void*)indexOffset, static_cast<GLint>(startVertex));
258 postDraw();
259
260 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(count, true); }
261}
262
263void Cogs::ContextGL20::draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
264{
265 if(!HandleIsValid(this->currentEffect)){
266 LOG_INFO(logger, "Draw with no effect active.");
267 return;
268 }
269 if (this->needVertexAttributeSetup) {
270 this->setupVertexAttributes();
271 }
272
273 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[primitiveType];
274
275 preDraw();
276 glDrawArrays(glPrimitiveType, static_cast<GLint>(startVertex), static_cast<GLsizei>(numVertexes));
277 postDraw();
278
279 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes, false); }
280}
281
282void Cogs::ContextGL20::drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
283{
284 if(!HandleIsValid(this->currentEffect)){
285 LOG_INFO(logger, "Draw with no effect active.");
286 return;
287 }
288 if (this->needVertexAttributeSetup) {
289 this->setupVertexAttributes();
290 }
291
292 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[primitiveType];
293
294 preDraw();
295#ifndef __APPLE__
296 if (glDrawArraysInstancedBaseInstance) {
297 glDrawArraysInstancedBaseInstance(glPrimitiveType, static_cast<GLint>(startVertex), static_cast<GLsizei>(numVertexes), static_cast<GLsizei>(numInstances), static_cast<GLuint>(startInstance));
298 } else
299#endif
300 {
301 assert(startInstance == 0);
302 glDrawArraysInstanced(glPrimitiveType, static_cast<GLint>(startVertex), static_cast<GLsizei>(numVertexes), static_cast<GLsizei>(numInstances));
303 }
304 postDraw();
305
306 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes * numInstances, false); }
307}
308
309void Cogs::ContextGL20::drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
310{
311 if(!HandleIsValid(this->currentEffect)){
312 LOG_INFO(logger, "Draw with no effect active.");
313 return;
314 }
315 if (this->needVertexAttributeSetup) {
316 this->setupVertexAttributes();
317 }
318 assert(iaState.currentIndexBuffer); // Must have index buffer bound
319
320 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[primitiveType];
321 const GLsizei count = static_cast<GLsizei>(numIndexes ? numIndexes : iaState.currentIndexBuffer->count);
322 const GLvoid * indexOffset = reinterpret_cast<const GLvoid *>(startIndex * iaState.indexBufferStride);
323 GLenum indexType = (iaState.indexBufferStride == 2) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
324
325 preDraw();
326#ifndef __APPLE__
327 if (glDrawElementsInstancedBaseInstance) {
328 glDrawElementsInstancedBaseInstance(glPrimitiveType, count, indexType, indexOffset, static_cast<GLsizei>(numInstances), static_cast<GLuint>(startInstance));
329 } else
330#endif
331 {
332 assert(startInstance == 0);
333 glDrawElementsInstanced(glPrimitiveType, count, indexType, indexOffset, static_cast<GLsizei>(numInstances));
334 }
335 postDraw();
336
337 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(count * numInstances, true); }
338}
339
340void Cogs::ContextGL20::setVertexBuffers(const VertexBufferHandle * handles, const size_t count)
341{
342 uint32_t strides[kMaxVertexInputSlots];
343 uint32_t offsets[kMaxVertexInputSlots];
344
345 for (size_t i = 0; i < count; i++) {
346 auto & buffer = buffers->buffers[BufferHandle(handles[i].handle)];
347
348 assert(buffer.vertexFormat && "Vertex buffer must have been created with format information attached.");
349
350 strides[i] = getSize(*buffer.vertexFormat);
351 offsets[i] = 0;
352 }
353
354 setVertexBuffers(handles, count, strides, offsets);
355}
356
357void Cogs::ContextGL20::setVertexBuffers(const VertexBufferHandle * handles, const size_t count, const uint32_t * strides, const uint32_t * offsets)
358{
359 clearInputState();
360
361 iaState.numVertexBuffers = count;
362
363 for (size_t i = 0; i < count; i++) {
364 BufferGL20 &buffer = buffers->buffers[BufferHandle(handles[i].handle)];
365 iaState.currentVertexBuffers[i] = &buffer;
366 iaState.strides[i] = strides[i];
367 iaState.offsets[i] = offsets ? offsets[i] : 0;
368 }
369
370 needVertexAttributeSetup = true;
371}
372
373void Cogs::ContextGL20::setBlendState(const BlendStateHandle handle, const float* constant)
374{
375 if (!HandleIsValid(handle)) {
376 glDisable(GL_BLEND);
377 return;
378 }
379
380 const BlendStateGL20 & blendState = renderTargets->blendStates[handle];
381
382 if (blendState.color.enabled || blendState.alpha.enabled) {
383 glEnable(GL_BLEND);
384 glBlendFuncSeparate(Blends[size_t(blendState.color.enabled ? blendState.color.sourceBlend : BlendState::Blend::One)],
385 Blends[size_t(blendState.color.enabled ? blendState.color.destinationBlend : BlendState::Blend::Zero)],
386 Blends[size_t(blendState.alpha.enabled ? blendState.alpha.sourceBlend : BlendState::Blend::One)],
387 Blends[size_t(blendState.alpha.enabled ? blendState.alpha.destinationBlend : BlendState::Blend::Zero)]);
388 glBlendEquationSeparate(BlendOperations[size_t(blendState.color.enabled ? blendState.color.operation : BlendState::BlendOperation::Add)],
389 BlendOperations[size_t(blendState.alpha.enabled ? blendState.alpha.operation : BlendState::BlendOperation::Add)]);
390 if (constant) {
391 glBlendColor(constant[0], constant[1], constant[2], constant[3]);
392 }
393 } else {
394 glDisable(GL_BLEND);
395 }
396}
397
398
399
400
401Cogs::EffectHandle Cogs::ContextGL20::getCurrentEffect()
402{
403 return this->currentEffect;
404}
405
406Cogs::IEffects * Cogs::ContextGL20::getEffects() { return effects; }
407
409{
410 assert(!inRenderPass);
411 setRenderTarget(info.renderTargetHandle, info.depthStencilHandle);
412 {
413 auto & renderTarget = renderTargets->renderTargets[currentRenderTarget];
414 for (int i = 0; i < renderTarget.numTextures; ++i) {
415 if(info.loadOp[i] == LoadOp::Clear){
416 glClearBufferfv(GL_COLOR, i, info.clearValue[i]);
417 }
418 }
419 }
420 if(info.depthLoadOp == LoadOp::Clear){
421 glClearBufferfv(GL_DEPTH, 0, &info.depthClearValue);
422 }
423 inRenderPass = true;
424 renderPassInfo = info;
425}
426
428{
429 assert(inRenderPass);
430 if(HandleIsValid(renderPassInfo.renderTargetHandle)){
431 RenderTargetGL20 &target = renderTargets->renderTargets[renderPassInfo.renderTargetHandle];
432 for(size_t i=0; i<target.numTextures; i++){
433 if(HandleIsValid(renderPassInfo.resolveHandle[i])){
434 resolveResource(target.textures[i], TextureHandle(renderPassInfo.resolveHandle[i].handle));
435 }
436 }
437 }
438 inRenderPass = false;
439 renderPassInfo = {};
440}
441
443{
444 // TODO: Here we need to generate combinations of RenderTargetHandle and DepthStencilHandle.
445 this->currentRenderTarget = handle;
446
447 static GLenum buffers[OpenGL20::kMaxRenderTargets];
448 if (HandleIsValid(handle)) {
449 const RenderTargetGL20 & renderTarget = this->renderTargets->renderTargets[handle];
450
451 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
452
453 if (renderTarget.numTextures) {
454 for (GLint i = 0; i < static_cast<GLint>(renderTarget.numTextures); ++i) {
455 buffers[i] = GL_COLOR_ATTACHMENT0 + i;
456 }
457
458 glDrawBuffers(static_cast<GLsizei>(renderTarget.numTextures), buffers);
459 } else {
460 buffers[0] = GL_NONE;
461 glDrawBuffers(1, buffers);
462 }
463 } else if(HandleIsValid(depthStencilHandle)) {
464 const DepthStencilTargetGL20 & depthTarget = this->renderTargets->depthStencils[depthStencilHandle];
465 const RenderTargetGL20 & renderTarget = this->renderTargets->renderTargets[depthTarget.renderTarget];
466 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
467 {
468 buffers[0] = GL_NONE;
469 glDrawBuffers(1, buffers);
470 }
471 } else {
472 glBindFramebuffer(GL_FRAMEBUFFER, 0);
473
474 glDrawBuffer(GL_BACK);
475 }
476}
477
478void Cogs::ContextGL20::setViewport(const float x, const float y, const float width, const float height)
479{
480 glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLint>(width), static_cast<GLint>(height));
481}
482
483void Cogs::ContextGL20::setScissor(const int x, const int y, const int width, const int height)
484{
485 glScissor(x, y, width, height);
486}
487
489{
490 glClearColor(color[0], color[1], color[2], color[3]);
491
492 glClear(GL_COLOR_BUFFER_BIT);
493}
494
495void Cogs::ContextGL20::clearRenderTarget(const float ** colors, const int /*count*/)
496{
497 auto color = colors[0];
498
499 glClearColor(color[0], color[1], color[2], color[3]);
500
501 glClear(GL_COLOR_BUFFER_BIT);
502}
503
504void Cogs::ContextGL20::clearDepth(const float depth)
505{
506 if (HandleIsValid(currentDepthStencilState)) {
507 const auto & depthState = renderTargets->depthStencilStates[currentDepthStencilState];
508
509 if (!depthState.writeEnabled) {
510 // Enable depth writes, since disabled depth writes makes glClearDepth ineffective.
511 glDepthMask(GLboolean(GL_TRUE));
512 }
513 }
514
515 glClearDepth(depth);
516
517 glClear(GL_DEPTH_BUFFER_BIT);
518}
519
520void Cogs::ContextGL20::setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
521{
522 if (!textureBindingHandle) return;
523
524 auto slot = static_cast<unsigned>(textureBindingHandle.handle & 0xFFFF);
525 assert(slot < sizeof(this->boundTextures)/sizeof(this->boundTextures[0]));
526 if (this->boundTextures[slot] == textureHandle) return;
527
528 glActiveTexture(GL_TEXTURE0 + slot);
529
530 if (HandleIsValid(textureHandle)) {
531 auto & texture = this->textures->textures[textureHandle];
532 if(boundTarget[slot] && (boundTarget[slot] != texture.type))
533 glBindTexture(boundTarget[slot], 0);
534 glBindTexture(texture.type, texture.textureId);
535 boundTarget[slot] = texture.type;
536
537#ifndef __APPLE__
538 if (glBindImageTexture && texture.flags & TextureFlags::ReadWriteTexture) {
539 assert(slot < maxImageUnits);
540 glBindImageTexture(slot, texture.textureId, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
541 }
542#endif
543 } else {
544 if(boundTarget[slot])
545 glBindTexture(boundTarget[slot], 0);
546#ifndef __APPLE__
547 if (glBindImageTexture && slot<maxImageUnits) {
548 glBindImageTexture(slot, 0, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
549 }
550#endif
551 }
552
553 this->boundTextures[slot] = textureHandle;
554}
555void Cogs::ContextGL20::setTexture(const TextureBindingHandle textureBindingHandle, TextureViewHandle textureViewHandle)
556{
557 setTexture(textureBindingHandle, TextureHandle(textureViewHandle.handle));
558}
559void Cogs::ContextGL20::setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle)
560{
561 if (!samplerStateBindingHandle) return;
562
563 auto ptr = (SamplerMapGL20*)(size_t)samplerStateBindingHandle.handle;
564
565 EffectHandle effectHandle = ptr->effectHandle;
566 auto & effect = effects->effects[effectHandle];
567 auto hash = ptr->name;
568
569 auto &samplers = effect.real_sampler[hash];
570 for(auto h2 : samplers){
571 if (!effect.samplers.count(h2)) {
572 continue;
573 }
574 auto tmp = effect.samplers[h2];
575 uint32_t base_slot = tmp.first;
576 uint32_t count = tmp.second;
577 for(uint32_t i=0; i<count; i++){
578 uint32_t slot = base_slot+i;
579 assert(slot < sizeof(this->boundSamplerStates)/sizeof(this->boundSamplerStates[0]));
580 if (HandleIsValid(samplerStateHandle) &&
581 samplerStateHandle == this->boundSamplerStates[slot]) continue;
582 this->boundSamplerStates[slot] = samplerStateHandle;
583
584 GLuint sampler;
585 if (HandleIsValid(samplerStateHandle)) {
586 sampler = static_cast<GLuint>(samplerStateHandle.handle);
587 } else {
588 if (defaultSamplerStateHandle == SamplerStateHandle::NoHandle) {
589 defaultSamplerStateHandle = this->textures->loadSamplerState(SamplerState::DefaultState());
590 }
591 sampler = static_cast<GLuint>(defaultSamplerStateHandle.handle);
592 }
593 glBindSampler(slot, sampler);
594 }
595 }
596}
597
599{
600 const RasterizerState & rasterizerState = (handle == RasterizerStateHandle::NoHandle) ? RasterizerState::DefaultState() : this->renderTargets->rasterizerStates[handle];
601
602 glPolygonMode(GL_FRONT_AND_BACK, rasterizerState.wireFrame ? GL_LINE : GL_FILL);
603 glFrontFace(rasterizerState.frontCounterClockwise ? GL_CCW : GL_CW);
604
605 switch (rasterizerState.cullMode) {
607 glDisable(GL_CULL_FACE);
608 break;
609
611 glEnable(GL_CULL_FACE);
612 glCullFace(GL_FRONT);
613 break;
614
615 default:
616 glEnable(GL_CULL_FACE);
617 glCullFace(GL_BACK);
618 break;
619 }
620
621 if (rasterizerState.depthBias != 0 || rasterizerState.slopeScaledDepthBias != 0) {
622 glEnable(GL_POLYGON_OFFSET_FILL);
623 glPolygonOffset(rasterizerState.slopeScaledDepthBias, rasterizerState.depthBias);
624 } else {
625 glDisable(GL_POLYGON_OFFSET_FILL);
626 }
627
628 rasterizerState.scissor ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
629
630 rasterizerState.noDepthClip ? glEnable(GL_DEPTH_CLAMP) : glDisable(GL_DEPTH_CLAMP);
631}
632
634{
635 currentDepthStencilState = handle;
636
637 const DepthStencilState & depthStencilState = (handle == DepthStencilStateHandle::NoHandle) ? DepthStencilState::DefaultState() : this->renderTargets->depthStencilStates[handle];
638
639 depthStencilState.depthEnabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
640 depthStencilState.writeEnabled ? glDepthMask(GLboolean(GL_TRUE)) : glDepthMask(GLboolean(GL_FALSE));
641 glDepthFunc(OpenGL20::DepthFunctions[depthStencilState.depthFunction]);
642}
643
645{
646 if (effectHandle == currentEffect) return;
647
648 state = {};
649
650 // Copy atomic counters from effect atomic counter store to buffer store.
651 if (HandleIsValid(currentEffect)) {
652 for (const auto & mapping : atomicCounterMappings) {
653 syncCounterFromEffect(mapping);
654 }
655 }
656 atomicCounterMappings.clear();
657
658 for (size_t i = 0; i < sizeof(boundTextures)/sizeof(boundTextures[0]); ++i) {
659 if (HandleIsValid(boundTextures[i])) {
660 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
661 if(boundTarget[i])
662 glBindTexture(boundTarget[i], 0);
663#ifndef __APPLE__
664 if(glBindImageTexture && i < maxImageUnits) {
665 glBindImageTexture(static_cast<GLuint>(i), 0, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
666 }
667#endif
668 boundTextures[i] = TextureHandle::NoHandle;
669 }
670 }
671 for (size_t i = 0; i < sizeof(boundSamplerStates)/sizeof(boundSamplerStates[0]); ++i) {
672 if (HandleIsValid(boundSamplerStates[i])) {
673 glBindSampler(static_cast<GLuint>(i), 0);
674 boundSamplerStates[i] = SamplerStateHandle::NoHandle;
675 }
676 }
677
678 this->currentEffect = effectHandle;
679
680 if (HandleIsValid(effectHandle)) {
681 auto & effect = this->effects->effects[effectHandle];
682 ContextCommon::setCurrentEffect(&effect);
683
684 glUseProgram(this->effects->effects[effectHandle].programId);
685
686 this->currentAttributeMap = effect.attributeMap;
687 this->currentProgramId = effect.programId;
688
689 atomicCounterMappings.clear();
690 for (const auto & b : effect.atomicCounterBuffers) {
691 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, b.binding, effects->backingBuffers[b.backingBuffer]);
692 }
693
694 } else {
695 glUseProgram(0);
696
697 this->currentAttributeMap = nullptr;
698 this->currentProgramId = GL_INVALID_INDEX;
699 }
700
701 this->needVertexAttributeSetup = true;
702}
703
705{
706 if(HandleIsValid(inputLayoutHandle)){
707 InputLayoutGL20 &inputLayout = buffers->inputLayouts[inputLayoutHandle];
708
709 this->clearInputState();
710
711 iaState.numVertexBuffers = inputLayout.numFormats;
712 for (size_t i = 0; i < inputLayout.numFormats; ++i) {
713 iaState.formats[i] = inputLayout.formats[i];
714 }
715
716 this->needVertexAttributeSetup = true;
717 }
718 else{
719 this->clearInputState();
720 }
721}
722
723void Cogs::ContextGL20::clearInputState()
724{
725 for (size_t i = 0; i < this->enabledAttributes.size(); ++i) {
726 glDisableVertexAttribArray(this->enabledAttributes[i]);
727 }
728 this->enabledAttributes.clear();
729
730 this->needVertexAttributeSetup = true;
731}
732
734{
735 bool depth = false;
736
737 auto & sourceTexture = this->textures->textures[source];
738 auto & targetTexture = this->textures->textures[destination];
739
740 RenderTargetGL20 * sourceTarget = nullptr;
741
742 for (auto & rt : renderTargets->renderTargets) {
743 for (size_t i = 0; i < rt.numTextures; ++i) {
744 if (rt.textures[i] == source) {
745 sourceTarget = &rt;
746 break;
747 }
748 }
749 }
750
751 if (!sourceTarget) return;
752
753 assert(targetTexture.numSamples == 1 && "Cannot resolve to multisample target.");
754 glBindTexture(GL_TEXTURE_2D, targetTexture.textureId);
755
756 GLuint targetFrameBuffer = 0;
757 glGenFramebuffers(1, &targetFrameBuffer);
758
759 assert(sourceTexture.width == targetTexture.width && "Source and target texture dimensions not equal.");
760
761 glDisable(GL_SCISSOR_TEST);
762
763 if (sourceTexture.numSamples > 1 && !depth) {
764 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceTarget->frameBuffer);
765 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFrameBuffer);
766
767 if (!depth) {
768 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture.textureId, 0);
769 glBlitFramebuffer(0, 0, sourceTexture.width, sourceTexture.height, 0, 0, targetTexture.width, targetTexture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
770 }
771 else {
772 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, targetTexture.textureId, 0);
773 glBlitFramebuffer(0, 0, sourceTexture.width, sourceTexture.height, 0, 0, targetTexture.width, targetTexture.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
774 }
775
776 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
777 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
778 }
779 else if (sourceTexture.numSamples > 1 && depth) {
780 // NOTE: Resolving multisampled depth textures are not supported.
781 assert(depth == false && "Cannot resolve from multisample depth target.");
782 }
783 else {
784 glBindFramebuffer(GL_FRAMEBUFFER, sourceTarget->frameBuffer);
785
786 if (!depth) {
787 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture.textureId, 0);
788 }
789 else {
790 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, sourceTexture.textureId, 0);
791 }
792
793 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sourceTexture.width, sourceTexture.height);
794 glBindFramebuffer(GL_FRAMEBUFFER, 0);
795 }
796
797 glBindTexture(GL_TEXTURE_2D, 0);
798 glDeleteFramebuffers(1, &targetFrameBuffer);
799}
800
801void Cogs::ContextGL20::setDefaults()
802{
803 glState.push();
804 glBindVertexArray(vao);
805
806 state = {};
807
808 setBlendState(BlendStateHandle::NoHandle, nullptr);
809 setDepthStencilState(DepthStencilStateHandle::NoHandle);
810 setRasterizerState(RasterizerStateHandle::NoHandle);
811
812 setEffect(EffectHandle::NoHandle);
813}
814
815Cogs::EffectHandle Cogs::ContextGL20::getEffect() const
816{
817 return this->currentEffect;
818}
819
820void Cogs::ContextGL20::readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer /*framebuffer*/)
821{
822 auto & buffer = this->buffers->buffers[bufferHandle];
823
824 if (buffer.size < width * height * sizeof(float)) {
825 LOG_ERROR(logger, "Cannot read depth buffer into buffer of smaller size.");
826
827 return;
828 }
829
830 glReadBuffer(GL_BACK);
831
832 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
833
834 glReadPixels(x, y, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
835
836 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
837}
838
839void * Cogs::ContextGL20::map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *)
840{
841 auto & buffer = this->buffers->buffers[bufferHandle];
842
843 if (this->enableMappingWorkaround && (mapMode == MapMode::WriteDiscard)) {
844 buffer.mapFlags = mapMode;
845
846 if (buffer.mappedData.size() != buffer.size) {
847 buffer.mappedData.resize(buffer.size);
848 }
849
850 return buffer.mappedData.data();
851 } else {
852 glBindBuffer(buffer.target, buffer.bufferId);
853
854 GLbitfield access = 0;
855 access |= (mapMode == MapMode::Read) ? GL_MAP_READ_BIT : 0;
856 access |= (mapMode == MapMode::Write) ? GL_MAP_WRITE_BIT : 0;
857 access |= (mapMode == MapMode::WriteDiscard) ? GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT : 0;
858
859 return glMapBufferRange(buffer.target, 0, static_cast<GLsizeiptr>(buffer.size), access);
860 }
861}
862
864{
865 auto & buffer = this->buffers->buffers[bufferHandle];
866
867 glBindBuffer(buffer.target, buffer.bufferId);
868
869 if (this->enableMappingWorkaround && (buffer.mapFlags == MapMode::WriteDiscard)) {
870 glBufferData(buffer.target, static_cast<GLsizeiptr>(buffer.mappedData.size()), buffer.mappedData.data(), GL_STREAM_DRAW);
871 } else {
872 GLboolean result = glUnmapBuffer(buffer.target);
873
874 if (!result) {
875 LOG_WARNING(logger, "Unmapping the buffer was unsuccessful.");
876 }
877 }
878
879 glBindBuffer(buffer.target, GL_ZERO);
880}
881
882void Cogs::ContextGL20::updateSubTexture(TextureHandle textureHandle, const size_t level, const void * data)
883{
884 assert(HandleIsValid(textureHandle) && "Texture handle must be valid.");
885
886 const auto & texture = this->textures->textures[textureHandle];
887
888 const GLenum pixelType = OpenGL20::PixelTypes[(int)texture.format];
889 const GLenum pixelFormat = OpenGL20::PixelFormats[(int)texture.format];
890 const GLboolean isCompressed = OpenGL20::CompressedFormats[(int)texture.format];
891 if (isCompressed)
892 {
893 LOG_WARNING(logger, "Updating subtexture is unsupported for compressed textures.");
894 }
895 else {
896 glBindTexture(texture.type, texture.textureId);
897
898 glTexSubImage2D(texture.type, static_cast<GLint>(level), 0, 0, texture.width, texture.height, pixelFormat, pixelType, data);
899 }
900}
901
902void Cogs::ContextGL20::updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void * data)
903{
904 assert(HandleIsValid(bufferHandle) && "Buffer handle must be valid.");
905
906 const auto & buffer = this->buffers->buffers[bufferHandle];
907
908 assert(buffer.size >= offset + size && "Buffer size not sufficient to hold new data.");
909
910 glBindBuffer(buffer.target, buffer.bufferId);
911 glBufferSubData(buffer.target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
912 glBindBuffer(buffer.target, 0);
913}
914
915void Cogs::ContextGL20::copyResource(BufferHandle destinationHandle, BufferHandle sourceHandle)
916{
917 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
918 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
919
920 assert(HandleIsValid(sourceHandle) && "Source buffer handle must be valid.");
921 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
922
923 assert(sourceBuffer.size == destinationBuffer.size);
924
925 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, 0,
926 sourceBuffer.target, sourceBuffer.bufferId, 0,
927 static_cast<GLsizeiptr>(sourceBuffer.size));
928}
929
930void Cogs::ContextGL20::copyResource(TextureHandle /*destinationHandle*/, TextureHandle /*sourceHandle*/)
931{
932
933}
934
935void Cogs::ContextGL20::copySubResource(BufferHandle destinationHandle, size_t destinationOffset, BufferHandle sourceHandle, size_t sourceOffset, size_t size)
936{
937 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
938 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
939 assert(destinationOffset + size <= destinationBuffer.size);
940
941 assert(HandleIsValid(sourceHandle) && "Source buffer handle must be valid.");
942 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
943 assert(sourceOffset + size <= sourceBuffer.size);
944
945 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, static_cast<GLintptr>(destinationOffset),
946 sourceBuffer.target, sourceBuffer.bufferId, static_cast<GLintptr>(sourceOffset),
947 static_cast<GLsizeiptr>(size));
948}
949
950void Cogs::ContextGL20::readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer)
951{
952 auto & buffer = this->buffers->buffers[bufferHandle];
953
954 if (buffer.size < static_cast<size_t>(width) * static_cast<size_t>(height) * 4) {
955 //TODO: Get actual frame buffer size.
956 LOG_ERROR(logger, "Cannot read color buffer into buffer of smaller size.");
957
958 return;
959 }
960
961 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
962
963 if (currentRenderTarget == RenderTargetHandle::NoHandle) {
964 glReadBuffer(OpenGL20::Framebuffers[framebuffer]);
965 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
966 } else {
967 // If a render target is currently bound, we read from the color attachment of this target.
968 auto & renderTarget = this->renderTargets->renderTargets[this->currentRenderTarget];
969 auto & texture = this->textures->textures[renderTarget.textures[0]];
970
971 glReadBuffer(GL_COLOR_ATTACHMENT0);
972
973 glReadPixels(x, y, width, height, OpenGL20::PixelFormats[(int)texture.format], OpenGL20::PixelTypes[(int)texture.format], nullptr);
974 }
975
976 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
977}
978
980{
981 glState.pop();
982}
983
984void Cogs::ContextGL20::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
985{
986 ContextCommon::updateConstantBuffers();
987
988 if (!HandleIsValid(currentEffect)) return;
989
990 auto & effect = effects->effects[currentEffect];
991
992 for (auto & constantBuffer : effect.computeShader.reflection.constantBuffers) {
993 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.csCBs[constantBuffer.slot]) {
994 auto & buffer = buffers->buffers[constantBuffer.buffer];
995 if (constantBuffer.index != GL_INVALID_INDEX) {
996 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
997 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
998 }
999 state.csCBs[constantBuffer.slot] = constantBuffer.buffer;
1000 }
1001 }
1002
1003#ifndef __APPLE__
1004 glDispatchCompute(threadGroupsX, threadGroupsY, threadGroupsZ);
1005#else
1006 (void)threadGroupsX;
1007 (void)threadGroupsY;
1008 (void)threadGroupsZ;
1009 assert(false);
1010#endif
1011 postDraw();
1012
1013}
1014
1015void Cogs::ContextGL20::setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle)
1016{
1017
1018 if (HandleIsValid(bufferHandle)) {
1019 auto & buffer = buffers->buffers[bufferHandle];
1020
1021 if (HandleIsValid(bufferBindingHandle)) {
1022
1023 if (HandleIsValid(currentEffect)) {
1024 auto & effect = this->effects->effects[currentEffect];
1025
1026 auto binding = static_cast<GLint>(bufferBindingHandle.handle >> 32) - 1;
1027 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, buffer.bufferId);
1028
1029 if (buffer.counterBufferId != GL_INVALID_INDEX) {
1030 auto index = static_cast<GLint>(bufferBindingHandle.handle & 0xFFFFFFFF) - 1;
1031 if (size_t(index) < effect.atomicCounterVariables.size()) {
1032 AtomicCounterMapGL20 mapping;
1033 mapping.backingBuffer = buffer.counterBufferId;
1034 mapping.effectAtomicCounterVariableIndex = index;
1035 this->atomicCounterMappings.push_back(mapping);
1036
1037 syncCounterToEffect(mapping);
1038 }
1039 }
1040 }
1041 }
1042 }
1043}
1044
1045void Cogs::ContextGL20::syncCounterToEffect(const AtomicCounterMapGL20 mapping)
1046{
1047 const auto & effect = this->effects->effects[currentEffect];
1048 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1049 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1050
1051 glBindBuffer(GL_COPY_READ_BUFFER, mapping.backingBuffer);
1052 glBindBuffer(GL_COPY_WRITE_BUFFER, effects->backingBuffers[effectBuffer.backingBuffer]);
1053 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, effectVariable.bufferOffset, static_cast<GLsizei>(sizeof(GLuint)));
1054 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1055 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1056}
1057
1058void Cogs::ContextGL20::syncCounterFromEffect(const AtomicCounterMapGL20 mapping)
1059{
1060 const auto & effect = this->effects->effects[currentEffect];
1061 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1062 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1063 auto effectBackingBuffer = effects->backingBuffers[effectBuffer.backingBuffer];
1064
1065 glBindBuffer(GL_COPY_READ_BUFFER, effectBackingBuffer);
1066 glBindBuffer(GL_COPY_WRITE_BUFFER, mapping.backingBuffer);
1067 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, effectVariable.bufferOffset, 0, static_cast<GLsizei>(sizeof(GLuint)));
1068 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1069 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1070}
1071
1072
1073void Cogs::ContextGL20::setBufferCounter(BufferHandle bufferHandle, uint32_t value)
1074{
1075 auto & buffer = buffers->buffers[bufferHandle];
1076 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1077 return;
1078 }
1079
1080 // Store in buffer's atomic counter backing store.
1081 GLuint v = value;
1082 glBindBuffer(GL_COPY_READ_BUFFER, buffer.counterBufferId);
1083 glBufferData(GL_COPY_READ_BUFFER, static_cast<GLsizeiptr>(sizeof(GLuint)), &v, GL_DYNAMIC_COPY);
1084 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1085
1086 // And update effect's backing store if the counter is in use.
1087 if (HandleIsValid(currentEffect)) {
1088 for (const auto & mapping : atomicCounterMappings) {
1089 if (mapping.backingBuffer == buffer.counterBufferId) {
1090 syncCounterToEffect(mapping);
1091 }
1092 }
1093 }
1094}
1095
1097{
1098 assert(HandleIsValid(sourceBufferHandle) && "Destination buffer handle must be valid.");
1099 const auto & sourceBuffer = this->buffers->buffers[sourceBufferHandle];
1100 assert(sizeof(GLuint) <= sourceBuffer.size);
1101
1102 auto & buffer = buffers->buffers[bufferHandle];
1103 assert(buffer.counterBufferId != GL_INVALID_INDEX);
1104
1105 copySubBuffer(GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1106 GL_ARRAY_BUFFER, sourceBuffer.bufferId, 0,
1107 sizeof(GLuint));
1108
1109 // And update effect's backing store if the counter is in use.
1110 if (HandleIsValid(currentEffect)) {
1111 for (const auto & mapping : atomicCounterMappings) {
1112 if (mapping.backingBuffer == buffer.counterBufferId) {
1113 syncCounterToEffect(mapping);
1114 }
1115 }
1116 }
1117}
1118
1120{
1121 auto & buffer = buffers->buffers[bufferHandle];
1122
1123 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1124 return 0;
1125 }
1126
1127 // Update buffer's backing store if the counter is used by the current effect.
1128 if (HandleIsValid(currentEffect)) {
1129 for (const auto & mapping : atomicCounterMappings) {
1130 if (mapping.backingBuffer == buffer.counterBufferId) {
1131 syncCounterFromEffect(mapping);
1132 }
1133 }
1134 }
1135
1136 GLuint v;
1137 glBindBuffer(GL_COPY_WRITE_BUFFER, buffer.counterBufferId);
1138 glGetBufferSubData(GL_COPY_WRITE_BUFFER, static_cast<GLintptr>(0), static_cast<GLsizeiptr>(sizeof(GLuint)), &v);
1139 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1140
1141 return v;
1142}
1143
1144
1145void Cogs::ContextGL20::getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
1146{
1147 assert(HandleIsValid(destinationBufferHandle) && "Destination buffer handle must be valid.");
1148 const auto & destinationBuffer = this->buffers->buffers[destinationBufferHandle];
1149 assert(sizeof(GLuint) <= destinationBuffer.size);
1150
1151 auto & buffer = buffers->buffers[bufferHandle];
1152
1153 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1154 return;
1155 }
1156
1157 // Update buffer's backing store if the counter is used by the current effect.
1158 if (HandleIsValid(currentEffect)) {
1159 for (const auto & mapping : atomicCounterMappings) {
1160 if (mapping.backingBuffer == buffer.counterBufferId) {
1161 syncCounterFromEffect(mapping);
1162 }
1163 }
1164 }
1165
1166 copySubBuffer(GL_ARRAY_BUFFER, destinationBuffer.bufferId, 0,
1167 GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1168 sizeof(GLuint));
1169}
1170void Cogs::ContextGL20::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle srcHandle, unsigned srcSub)
1171{
1172#ifndef __APPLE__
1173 TextureGL20 & srcTexture = this->textures->textures[srcHandle];
1174 TextureGL20 & dstTexture = this->textures->textures[dstHandle];
1175
1176 unsigned srcLevel = srcSub; // TODO srcSub%LevelCount
1177 unsigned srcLayer = 0; // TODO srcSub/LevelCount
1178 unsigned dstLevel = dstSub; // TODO dstSub%LevelCount
1179 unsigned dstLayer = 0; // TODO dstSub/LevelCount
1180
1181 glCopyImageSubData(srcTexture.textureId,
1182 srcTexture.type,
1183 srcLevel,
1184 0, 0, srcLayer,
1185 dstTexture.textureId,
1186 dstTexture.type,
1187 dstLevel,
1188 dstX, dstY, dstZ+dstLayer,
1189 srcTexture.width, srcTexture.height, 1);
1190#else
1191 (void)dstHandle;
1192 (void)dstSub;
1193 (void)dstX;
1194 (void)dstY;
1195 (void)dstZ;
1196 (void)srcHandle;
1197 (void)srcSub;
1198 assert(false);
1199#endif
1200}
1201void Cogs::ContextGL20::clearResource(BufferHandle destinationHandle, uint32_t *Values)
1202{
1203 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
1204#ifndef __APPLE__
1205 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1206
1207 GLenum internalformat = GL_R32UI;
1208 GLenum format = GL_RED_INTEGER;
1209 GLenum type = GL_UNSIGNED_INT;
1210
1211 if (glClearNamedBufferData) {
1212 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1213 }
1214 else if(glClearBufferData){
1215 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1216 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1217 glBindBuffer(destinationBuffer.target, 0);
1218 }
1219 else
1220#else
1221 (void)Values;
1222#endif
1223 {
1224 assert(false); // TODO
1225 }
1226}
1227void Cogs::ContextGL20::clearResource(BufferHandle destinationHandle, float *Values)
1228{
1229 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
1230#ifndef __APPLE__
1231 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1232
1233 GLenum internalformat = GL_R32F;
1234 GLenum format = GL_RED;
1235 GLenum type = GL_FLOAT;
1236
1237 if (glClearNamedBufferData) {
1238 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1239 }
1240 else if(glClearBufferData){
1241 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1242 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1243 glBindBuffer(destinationBuffer.target, 0);
1244 }
1245 else
1246#else
1247 (void)Values;
1248#endif
1249 {
1250 assert(false); // TODO
1251 }
1252}
1253
1254void Cogs::ContextGL20::preDraw()
1255{
1256 ContextCommon::updateConstantBuffers();
1257
1258 if (!HandleIsValid(currentEffect)) return;
1259
1260 auto & effect = effects->effects[currentEffect];
1261
1262 for (auto & constantBuffer : effect.vertexShader.reflection.constantBuffers) {
1263 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.vsCBs[constantBuffer.slot]) {
1264 auto & buffer = buffers->buffers[constantBuffer.buffer];
1265 if (constantBuffer.index != GL_INVALID_INDEX) {
1266 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1267 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1268 }
1269 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
1270 }
1271 }
1272
1273 for (auto & constantBuffer : effect.pixelShader.reflection.constantBuffers) {
1274 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.psCBs[constantBuffer.slot]) {
1275 auto & buffer = buffers->buffers[constantBuffer.buffer];
1276 if (constantBuffer.index != GL_INVALID_INDEX) {
1277 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1278 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1279 }
1280 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1281 }
1282 }
1283}
1284
1285void Cogs::ContextGL20::postDraw()
1286{
1287 if (unorderedMemoryAcccess) {
1288#ifndef __APPLE__
1289 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1290#else
1291 assert(false);
1292#endif
1293 unorderedMemoryAcccess = false;
1294 }
1295}
1296
1298{
1299#ifndef __APPLE__
1300 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, static_cast<GLsizei>(name.size()), name.data());
1301#else
1302 (void)name;
1303#endif
1304}
1306{
1307#ifndef __APPLE__
1308 glPopDebugGroup();
1309#endif
1310}
1312{
1313#ifndef __APPLE__
1314 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1, GL_DEBUG_SEVERITY_HIGH, static_cast<GLsizei>(name.size()), name.data());
1315#else
1316 (void)name;
1317#endif
1318}
Log implementation class.
Definition: LogManager.h:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Definition: StringView.h:171
constexpr size_t size() const noexcept
Get the size of the string.
Definition: StringView.h:178
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:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
@ InstanceData
Per instance data.
@ InstanceMatrix
Instance matrix semantic.
uint8_t enabled
If blending is enabled.
Definition: BlendState.h:41
Blend destinationBlend
Blend option for the blend destination data.
Definition: BlendState.h:47
BlendOperation operation
How the two blend values are combined.
Definition: BlendState.h:50
Blend sourceBlend
Blend option for the blend source data.
Definition: BlendState.h:44
void pushCommandGroupAnnotation(const StringView &name) override
Begin to tag a sequence of commands as a group in graphics debugger.
void setBufferCounter(BufferHandle bufferHandle, uint32_t value) override
Set the associated counter of a buffer.
void setIndexBuffer(IndexBufferHandle indexBufferHandle, uint32_t stride, uint32_t offset) override
Sets the current index buffer.
void clearRenderTarget(const float *color) override
Clear the currently set render target to the given value (4 component floating point RGBA).
void drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances) override
Draws non-indexed, instanced primitives.
void getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle) override
Get the associated counter of a buffer.
void unmap(BufferHandle bufferHandle) override
Unmaps the given buffer, applying any synchronization necessary to reflect changes in the mapped memo...
void clearDepth(const float depth=1.0f) override
Clear the currently set depth/stencil target to the given depth.
void setViewport(const float x, const float y, const float width, const float height) override
Sets the current viewport to the given location and dimensions.
void setBlendState(const BlendStateHandle handle, const float *constant) override
Set the current blend state.
void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0) override
Draws indexed, non-instanced primitives.
void updateSubTexture(TextureHandle textureHandle, const size_t level, const void *data) override
Update the data of a level in the given texture.
void dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ) override
Dispatch computing work on the graphics device using the desired thread group count.
void readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current depth target into the given bufferHandle.
void reset() override
Resets all state changes made to the GPU since the last call to beginFrame.
void setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle) override
Sets a buffer to bind to the given binding.
void draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numPrimitives) override
Draws non-indexed, non-instanced primitives.
void signal(FenceHandle fenceHandle) override
Insert a fence in the command stream that will signal when all commands before the fence are complete...
void setRasterizerState(const RasterizerStateHandle handle) override
Set the current rasterizer state.
void endRenderPass() override
End a render pass.
void setConstantBuffer(const ConstantBufferBindingHandle bufferBinding, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size) override
Sets a constant buffer to the given constant buffer binding.
void setAnnotationMarker(const StringView &name) override
Add a tag in the sequence of commands in graphics debugger.
void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets) override
Sets the current vertex buffers.
void setDepthStencilState(const DepthStencilStateHandle handle) override
Set the current depth stencil state.
void popCommandGroupAnnotation() override
End to tag a sequence of commands as a group in graphics debugger.
void setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle) override
Sets the sampler state binding given to the given sampler state.
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle) override
Sets the texture given to the binding given by textureBindingHandle.
void * map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *stride) override
Maps the given buffer so it can be accessed.
void setInputLayout(const InputLayoutHandle inputLayoutHandle) override
Sets the current input layout.
void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
void beginRenderPass(const RenderPassInfo &info) override
Begin a render pass.
void setEffect(EffectHandle effectHandle) override
Set the current effect.
void updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void *data) override
Update a region of data in a buffer.
void setScissor(const int x, const int y, const int width, const int height) override
Sets the current scissor rectangle.
void readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current render target into the given bufferHandle.
void resolveResource(TextureHandle source, TextureHandle destination) override
Resolves the given source resource target into the given destination texture.
void drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes) override
Draws indexed, instanced primitives.
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
bool depthEnabled
If depth testing is enabled/disabled. Default is true.
DepthFunction depthFunction
The depth function to use for depth testing.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
bool writeEnabled
If writes to the depth buffer are enabled/disabled. Default is true.
uint16_t elements
Number of channels in a data item.
Definition: DataFormat.h:259
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
handle_type handle
Internal resource handle.
Definition: Common.h:74
Provides effects and shader management functionality.
Definition: IEffects.h:148
EMapMode
Mapping mode enumeration.
Definition: Flags.h:93
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114
Encapsulates state for primitive rasterization in a state object.
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
bool scissor
Enable scissor rect.
bool frontCounterClockwise
If counter clockwise polygon winding is used to specify front facing polygons. Default is false.
bool noDepthClip
Clamp depth value instead of clipping against near and depth planes.
CullMode cullMode
Which face culling mode to apply to primitives before rasterization.
float depthBias
Depth bias to apply to depth values after initial rasterization before depth values are written.
float slopeScaledDepthBias
Slope scaled depth bias value controlling the depth bias value based on the area of the polygon on sc...
@ None
Do not perform any face culling.
@ Front
Cull front facing primitives.
bool wireFrame
If only wire frames should be rasterized. Default is false.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
Definition: SamplerState.h:85
@ ReadWriteTexture
The texture can be used as a read/write texture. Can be used to output data from compute shaders.
Definition: Flags.h:128
Vertex element structure used to describe a single data element in a vertex for the input assembler.
Definition: VertexFormat.h:38
InputType inputType
Input type of the element, vertex or instance data.
Definition: VertexFormat.h:43
DataFormat format
Format of the element.
Definition: VertexFormat.h:40
uint16_t offset
Offset in bytes from the vertex position in memory.
Definition: VertexFormat.h:39
uint16_t semanticIndex
Index for the semantic mapping.
Definition: VertexFormat.h:42
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).
Definition: VertexFormat.h:41
uint16_t instanceStep
Instance step factor.
Definition: VertexFormat.h:44
Vertex format structure used to describe a single vertex for the input assembler.
Definition: VertexFormat.h:60
std::vector< VertexElement > elements
Vector containing all vertex elements of this format.
Definition: VertexFormat.h:62