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 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[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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 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[static_cast<uint32_t>(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 (uint32_t 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 glBindVertexArray(vao);
804
805 state = {};
806
807 setBlendState(BlendStateHandle::NoHandle, nullptr);
808 setDepthStencilState(DepthStencilStateHandle::NoHandle);
809 setRasterizerState(RasterizerStateHandle::NoHandle);
810
811 setEffect(EffectHandle::NoHandle);
812}
813
814Cogs::EffectHandle Cogs::ContextGL20::getEffect() const
815{
816 return this->currentEffect;
817}
818
819void Cogs::ContextGL20::readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer /*framebuffer*/)
820{
821 auto & buffer = this->buffers->buffers[bufferHandle];
822
823 if (buffer.size < width * height * sizeof(float)) {
824 LOG_ERROR(logger, "Cannot read depth buffer into buffer of smaller size.");
825
826 return;
827 }
828
829 glReadBuffer(GL_BACK);
830
831 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
832
833 glReadPixels(x, y, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
834
835 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
836}
837
838void * Cogs::ContextGL20::map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *)
839{
840 auto & buffer = this->buffers->buffers[bufferHandle];
841
842 if (this->enableMappingWorkaround && (mapMode == MapMode::WriteDiscard)) {
843 buffer.mapFlags = mapMode;
844
845 if (buffer.mappedData.size() != buffer.size) {
846 buffer.mappedData.resize(buffer.size);
847 }
848
849 return buffer.mappedData.data();
850 } else {
851 glBindBuffer(buffer.target, buffer.bufferId);
852
853 GLbitfield access = 0;
854 access |= (mapMode == MapMode::Read) ? GL_MAP_READ_BIT : 0;
855 access |= (mapMode == MapMode::Write) ? GL_MAP_WRITE_BIT : 0;
856 access |= (mapMode == MapMode::WriteDiscard) ? GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT : 0;
857
858 return glMapBufferRange(buffer.target, 0, static_cast<GLsizeiptr>(buffer.size), access);
859 }
860}
861
863{
864 auto & buffer = this->buffers->buffers[bufferHandle];
865
866 glBindBuffer(buffer.target, buffer.bufferId);
867
868 if (this->enableMappingWorkaround && (buffer.mapFlags == MapMode::WriteDiscard)) {
869 glBufferData(buffer.target, static_cast<GLsizeiptr>(buffer.mappedData.size()), buffer.mappedData.data(), GL_STREAM_DRAW);
870 } else {
871 GLboolean result = glUnmapBuffer(buffer.target);
872
873 if (!result) {
874 LOG_WARNING(logger, "Unmapping the buffer was unsuccessful.");
875 }
876 }
877
878 glBindBuffer(buffer.target, GL_ZERO);
879}
880
881void Cogs::ContextGL20::updateSubTexture(TextureHandle textureHandle, const size_t level, const void * data)
882{
883 assert(HandleIsValid(textureHandle) && "Texture handle must be valid.");
884
885 const auto & texture = this->textures->textures[textureHandle];
886
887 const GLenum pixelType = OpenGL20::PixelTypes[(int)texture.format];
888 const GLenum pixelFormat = OpenGL20::PixelFormats[(int)texture.format];
889 const GLboolean isCompressed = OpenGL20::CompressedFormats[(int)texture.format];
890 if (isCompressed)
891 {
892 LOG_WARNING(logger, "Updating subtexture is unsupported for compressed textures.");
893 }
894 else {
895 glBindTexture(texture.type, texture.textureId);
896
897 glTexSubImage2D(texture.type, static_cast<GLint>(level), 0, 0, texture.width, texture.height, pixelFormat, pixelType, data);
898 }
899}
900
901void Cogs::ContextGL20::updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void * data)
902{
903 assert(HandleIsValid(bufferHandle) && "Buffer handle must be valid.");
904
905 const auto & buffer = this->buffers->buffers[bufferHandle];
906
907 assert(buffer.size >= offset + size && "Buffer size not sufficient to hold new data.");
908
909 glBindBuffer(buffer.target, buffer.bufferId);
910 glBufferSubData(buffer.target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
911 glBindBuffer(buffer.target, 0);
912}
913
914void Cogs::ContextGL20::copyResource(BufferHandle destinationHandle, BufferHandle sourceHandle)
915{
916 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
917 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
918
919 assert(HandleIsValid(sourceHandle) && "Source buffer handle must be valid.");
920 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
921
922 assert(sourceBuffer.size == destinationBuffer.size);
923
924 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, 0,
925 sourceBuffer.target, sourceBuffer.bufferId, 0,
926 static_cast<GLsizeiptr>(sourceBuffer.size));
927}
928
929void Cogs::ContextGL20::copyResource(TextureHandle /*destinationHandle*/, TextureHandle /*sourceHandle*/)
930{
931
932}
933
934void Cogs::ContextGL20::copySubResource(BufferHandle destinationHandle, size_t destinationOffset, BufferHandle sourceHandle, size_t sourceOffset, size_t size)
935{
936 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
937 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
938 assert(destinationOffset + size <= destinationBuffer.size);
939
940 assert(HandleIsValid(sourceHandle) && "Source buffer handle must be valid.");
941 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
942 assert(sourceOffset + size <= sourceBuffer.size);
943
944 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, static_cast<GLintptr>(destinationOffset),
945 sourceBuffer.target, sourceBuffer.bufferId, static_cast<GLintptr>(sourceOffset),
946 static_cast<GLsizeiptr>(size));
947}
948
949void Cogs::ContextGL20::readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer framebuffer)
950{
951 auto & buffer = this->buffers->buffers[bufferHandle];
952
953 if (buffer.size < static_cast<size_t>(width) * static_cast<size_t>(height) * 4) {
954 //TODO: Get actual frame buffer size.
955 LOG_ERROR(logger, "Cannot read color buffer into buffer of smaller size.");
956
957 return;
958 }
959
960 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
961
962 if (currentRenderTarget == RenderTargetHandle::NoHandle) {
963 glReadBuffer(OpenGL20::Framebuffers[static_cast<uint32_t>(framebuffer)]);
964 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
965 } else {
966 // If a render target is currently bound, we read from the color attachment of this target.
967 auto & renderTarget = this->renderTargets->renderTargets[this->currentRenderTarget];
968 auto & texture = this->textures->textures[renderTarget.textures[0]];
969
970 glReadBuffer(GL_COLOR_ATTACHMENT0);
971
972 glReadPixels(x, y, width, height, OpenGL20::PixelFormats[(int)texture.format], OpenGL20::PixelTypes[(int)texture.format], nullptr);
973 }
974
975 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
976}
977
979{
980}
981
982void Cogs::ContextGL20::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
983{
984 ContextCommon::updateConstantBuffers();
985
986 if (!HandleIsValid(currentEffect)) return;
987
988 auto & effect = effects->effects[currentEffect];
989
990 for (auto & constantBuffer : effect.computeShader.reflection.constantBuffers) {
991 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.csCBs[constantBuffer.slot]) {
992 auto & buffer = buffers->buffers[constantBuffer.buffer];
993 if (constantBuffer.index != GL_INVALID_INDEX) {
994 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
995 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
996 }
997 state.csCBs[constantBuffer.slot] = constantBuffer.buffer;
998 }
999 }
1000
1001#ifndef __APPLE__
1002 glDispatchCompute(threadGroupsX, threadGroupsY, threadGroupsZ);
1003#else
1004 (void)threadGroupsX;
1005 (void)threadGroupsY;
1006 (void)threadGroupsZ;
1007 assert(false);
1008#endif
1009 postDraw();
1010
1011}
1012
1013void Cogs::ContextGL20::setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle)
1014{
1015
1016 if (HandleIsValid(bufferHandle)) {
1017 auto & buffer = buffers->buffers[bufferHandle];
1018
1019 if (HandleIsValid(bufferBindingHandle)) {
1020
1021 if (HandleIsValid(currentEffect)) {
1022 auto & effect = this->effects->effects[currentEffect];
1023
1024 auto binding = static_cast<GLint>(bufferBindingHandle.handle >> 32) - 1;
1025 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, buffer.bufferId);
1026
1027 if (buffer.counterBufferId != GL_INVALID_INDEX) {
1028 auto index = static_cast<GLint>(bufferBindingHandle.handle & 0xFFFFFFFF) - 1;
1029 if (size_t(index) < effect.atomicCounterVariables.size()) {
1030 AtomicCounterMapGL20 mapping;
1031 mapping.backingBuffer = buffer.counterBufferId;
1032 mapping.effectAtomicCounterVariableIndex = index;
1033 this->atomicCounterMappings.push_back(mapping);
1034
1035 syncCounterToEffect(mapping);
1036 }
1037 }
1038 }
1039 }
1040 }
1041}
1042
1043void Cogs::ContextGL20::syncCounterToEffect(const AtomicCounterMapGL20 mapping)
1044{
1045 const auto & effect = this->effects->effects[currentEffect];
1046 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1047 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1048
1049 glBindBuffer(GL_COPY_READ_BUFFER, mapping.backingBuffer);
1050 glBindBuffer(GL_COPY_WRITE_BUFFER, effects->backingBuffers[effectBuffer.backingBuffer]);
1051 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, effectVariable.bufferOffset, static_cast<GLsizei>(sizeof(GLuint)));
1052 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1053 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1054}
1055
1056void Cogs::ContextGL20::syncCounterFromEffect(const AtomicCounterMapGL20 mapping)
1057{
1058 const auto & effect = this->effects->effects[currentEffect];
1059 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1060 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1061 auto effectBackingBuffer = effects->backingBuffers[effectBuffer.backingBuffer];
1062
1063 glBindBuffer(GL_COPY_READ_BUFFER, effectBackingBuffer);
1064 glBindBuffer(GL_COPY_WRITE_BUFFER, mapping.backingBuffer);
1065 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, effectVariable.bufferOffset, 0, static_cast<GLsizei>(sizeof(GLuint)));
1066 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1067 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1068}
1069
1070
1071void Cogs::ContextGL20::setBufferCounter(BufferHandle bufferHandle, uint32_t value)
1072{
1073 auto & buffer = buffers->buffers[bufferHandle];
1074 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1075 return;
1076 }
1077
1078 // Store in buffer's atomic counter backing store.
1079 GLuint v = value;
1080 glBindBuffer(GL_COPY_READ_BUFFER, buffer.counterBufferId);
1081 glBufferData(GL_COPY_READ_BUFFER, static_cast<GLsizeiptr>(sizeof(GLuint)), &v, GL_DYNAMIC_COPY);
1082 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1083
1084 // And update effect's backing store if the counter is in use.
1085 if (HandleIsValid(currentEffect)) {
1086 for (const auto & mapping : atomicCounterMappings) {
1087 if (mapping.backingBuffer == buffer.counterBufferId) {
1088 syncCounterToEffect(mapping);
1089 }
1090 }
1091 }
1092}
1093
1095{
1096 assert(HandleIsValid(sourceBufferHandle) && "Destination buffer handle must be valid.");
1097 const auto & sourceBuffer = this->buffers->buffers[sourceBufferHandle];
1098 assert(sizeof(GLuint) <= sourceBuffer.size);
1099
1100 auto & buffer = buffers->buffers[bufferHandle];
1101 assert(buffer.counterBufferId != GL_INVALID_INDEX);
1102
1103 copySubBuffer(GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1104 GL_ARRAY_BUFFER, sourceBuffer.bufferId, 0,
1105 sizeof(GLuint));
1106
1107 // And update effect's backing store if the counter is in use.
1108 if (HandleIsValid(currentEffect)) {
1109 for (const auto & mapping : atomicCounterMappings) {
1110 if (mapping.backingBuffer == buffer.counterBufferId) {
1111 syncCounterToEffect(mapping);
1112 }
1113 }
1114 }
1115}
1116
1118{
1119 auto & buffer = buffers->buffers[bufferHandle];
1120
1121 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1122 return 0;
1123 }
1124
1125 // Update buffer's backing store if the counter is used by the current effect.
1126 if (HandleIsValid(currentEffect)) {
1127 for (const auto & mapping : atomicCounterMappings) {
1128 if (mapping.backingBuffer == buffer.counterBufferId) {
1129 syncCounterFromEffect(mapping);
1130 }
1131 }
1132 }
1133
1134 GLuint v;
1135 glBindBuffer(GL_COPY_WRITE_BUFFER, buffer.counterBufferId);
1136 glGetBufferSubData(GL_COPY_WRITE_BUFFER, static_cast<GLintptr>(0), static_cast<GLsizeiptr>(sizeof(GLuint)), &v);
1137 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1138
1139 return v;
1140}
1141
1142
1143void Cogs::ContextGL20::getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
1144{
1145 assert(HandleIsValid(destinationBufferHandle) && "Destination buffer handle must be valid.");
1146 const auto & destinationBuffer = this->buffers->buffers[destinationBufferHandle];
1147 assert(sizeof(GLuint) <= destinationBuffer.size);
1148
1149 auto & buffer = buffers->buffers[bufferHandle];
1150
1151 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1152 return;
1153 }
1154
1155 // Update buffer's backing store if the counter is used by the current effect.
1156 if (HandleIsValid(currentEffect)) {
1157 for (const auto & mapping : atomicCounterMappings) {
1158 if (mapping.backingBuffer == buffer.counterBufferId) {
1159 syncCounterFromEffect(mapping);
1160 }
1161 }
1162 }
1163
1164 copySubBuffer(GL_ARRAY_BUFFER, destinationBuffer.bufferId, 0,
1165 GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1166 sizeof(GLuint));
1167}
1168void Cogs::ContextGL20::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle srcHandle, unsigned srcSub)
1169{
1170#ifndef __APPLE__
1171 TextureGL20 & srcTexture = this->textures->textures[srcHandle];
1172 TextureGL20 & dstTexture = this->textures->textures[dstHandle];
1173
1174 unsigned srcLevel = srcSub; // TODO srcSub%LevelCount
1175 unsigned srcLayer = 0; // TODO srcSub/LevelCount
1176 unsigned dstLevel = dstSub; // TODO dstSub%LevelCount
1177 unsigned dstLayer = 0; // TODO dstSub/LevelCount
1178
1179 glCopyImageSubData(srcTexture.textureId,
1180 srcTexture.type,
1181 srcLevel,
1182 0, 0, srcLayer,
1183 dstTexture.textureId,
1184 dstTexture.type,
1185 dstLevel,
1186 dstX, dstY, dstZ+dstLayer,
1187 srcTexture.width, srcTexture.height, 1);
1188#else
1189 (void)dstHandle;
1190 (void)dstSub;
1191 (void)dstX;
1192 (void)dstY;
1193 (void)dstZ;
1194 (void)srcHandle;
1195 (void)srcSub;
1196 assert(false);
1197#endif
1198}
1199void Cogs::ContextGL20::clearResource(BufferHandle destinationHandle, uint32_t *Values)
1200{
1201 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
1202#ifndef __APPLE__
1203 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1204
1205 GLenum internalformat = GL_R32UI;
1206 GLenum format = GL_RED_INTEGER;
1207 GLenum type = GL_UNSIGNED_INT;
1208
1209 if (glClearNamedBufferData) {
1210 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1211 }
1212 else if(glClearBufferData){
1213 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1214 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1215 glBindBuffer(destinationBuffer.target, 0);
1216 }
1217 else
1218#else
1219 (void)Values;
1220#endif
1221 {
1222 assert(false); // TODO
1223 }
1224}
1225void Cogs::ContextGL20::clearResource(BufferHandle destinationHandle, float *Values)
1226{
1227 assert(HandleIsValid(destinationHandle) && "Destination buffer handle must be valid.");
1228#ifndef __APPLE__
1229 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1230
1231 GLenum internalformat = GL_R32F;
1232 GLenum format = GL_RED;
1233 GLenum type = GL_FLOAT;
1234
1235 if (glClearNamedBufferData) {
1236 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1237 }
1238 else if(glClearBufferData){
1239 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1240 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1241 glBindBuffer(destinationBuffer.target, 0);
1242 }
1243 else
1244#else
1245 (void)Values;
1246#endif
1247 {
1248 assert(false); // TODO
1249 }
1250}
1251
1252void Cogs::ContextGL20::preDraw()
1253{
1254 ContextCommon::updateConstantBuffers();
1255
1256 if (!HandleIsValid(currentEffect)) return;
1257
1258 auto & effect = effects->effects[currentEffect];
1259
1260 for (auto & constantBuffer : effect.vertexShader.reflection.constantBuffers) {
1261 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.vsCBs[constantBuffer.slot]) {
1262 auto & buffer = buffers->buffers[constantBuffer.buffer];
1263 if (constantBuffer.index != GL_INVALID_INDEX) {
1264 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1265 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1266 }
1267 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
1268 }
1269 }
1270
1271 for (auto & constantBuffer : effect.pixelShader.reflection.constantBuffers) {
1272 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.psCBs[constantBuffer.slot]) {
1273 auto & buffer = buffers->buffers[constantBuffer.buffer];
1274 if (constantBuffer.index != GL_INVALID_INDEX) {
1275 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1276 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1277 }
1278 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1279 }
1280 }
1281}
1282
1283void Cogs::ContextGL20::postDraw()
1284{
1285 if (unorderedMemoryAcccess) {
1286#ifndef __APPLE__
1287 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1288#else
1289 assert(false);
1290#endif
1291 unorderedMemoryAcccess = false;
1292 }
1293}
1294
1296{
1297#ifndef __APPLE__
1298 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, static_cast<GLsizei>(name.size()), name.data());
1299#else
1300 (void)name;
1301#endif
1302}
1304{
1305#ifndef __APPLE__
1306 glPopDebugGroup();
1307#endif
1308}
1310{
1311#ifndef __APPLE__
1312 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1, GL_DEBUG_SEVERITY_HIGH, static_cast<GLsizei>(name.size()), name.data());
1313#else
1314 (void)name;
1315#endif
1316}
Log implementation class.
Definition: LogManager.h:140
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:181
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
Framebuffer
Framebuffers to select from when doing framebuffer operations.
Definition: Common.h:147
@ InstanceData
Per instance data.
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
Definition: Common.h:112
@ 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 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 drawInstanced(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances) override
Draws non-indexed, instanced primitives.
void draw(PrimitiveType primitiveType, const size_t startVertex, const size_t numPrimitives) override
Draws non-indexed, non-instanced primitives.
void readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer framebuffer) override
Reads data from the current depth target into the given bufferHandle.
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 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 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 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 readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer framebuffer) override
Reads data from the current render target into the given bufferHandle.
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 drawIndexed(PrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0) override
Draws indexed, non-instanced primitives.
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 drawInstancedIndexed(PrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes) override
Draws indexed, instanced primitives.
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 resolveResource(TextureHandle source, TextureHandle destination) override
Resolves the given source resource target into the given destination texture.
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:78
handle_type handle
Internal resource handle.
Definition: Common.h:75
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
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