1#include "ContextGL20.h"
3#include "BuffersGL20.h"
4#include "TexturesGL20.h"
5#include "EffectsGL20.h"
6#include "RenderTargetsGL20.h"
7#include "FormatsGL20.h"
9#include "Foundation/Logging/Logger.h"
21 GL_ONE_MINUS_SRC_COLOR,
23 GL_ONE_MINUS_SRC_ALPHA,
25 GL_ONE_MINUS_DST_ALPHA,
27 GL_ONE_MINUS_DST_COLOR,
28 GL_SRC_ALPHA_SATURATE,
30 GL_ONE_MINUS_CONSTANT_COLOR
32 static_assert(
sizeof(Blends) ==
sizeof(Blends[0]) * size_t(Cogs::BlendState::Blend::Count));
34 GLenum BlendOperations[] = {
37 GL_FUNC_REVERSE_SUBTRACT,
41 static_assert(
sizeof(BlendOperations) ==
sizeof(BlendOperations[0]) * size_t(Cogs::BlendState::BlendOperation::Count));
50 GLenum DepthFunctions[] = {
61 const GLenum Framebuffers[] = {
66 GLenum MappingModes[] = {
74 void copySubBuffer(GLenum , GLuint dstBuffer, GLintptr dstOffset,
75 GLenum , GLuint srcBuffer, GLintptr srcOffset, GLsizeiptr size)
78 if (glCopyNamedBufferSubData) {
79 glCopyNamedBufferSubData(srcBuffer, dstBuffer, srcOffset, dstOffset, size);
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);
92Cogs::ContextGL20::ContextGL20() :
97 for (
size_t i = 0; i <
sizeof(boundTextures)/
sizeof(boundTextures[0]); ++i) {
101 for (
size_t i = 0; i <
sizeof(boundSamplerStates)/
sizeof(boundSamplerStates[0]); ++i) {
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);
116void Cogs::ContextGL20::releaseResources() {
117 glDeleteVertexArrays(1, &vao);
124#pragma warning(disable : 4312)
129 syncObjects->signal(fenceHandle);
132void Cogs::ContextGL20::setupVertexAttributes()
134 for (
size_t b = 0; b < iaState.numVertexBuffers; ++b) {
135 BufferGL20 &buffer = *iaState.currentVertexBuffers[b];
137 const GLsizei structSize =
static_cast<GLsizei
>(iaState.strides[b]);
138 const GLuint bufferId =
static_cast<GLuint
>(buffer.bufferId);
140 glBindBuffer(GL_ARRAY_BUFFER, bufferId);
142 for (
size_t i = 0; i < vertexFormat.
elements.size(); ++i) {
144 const GLint index =
static_cast<GLint
>(element.
semanticIndex * NumAttributeSemanticsGL20 +
static_cast<int>(element.
semantic));
146 assert(this->currentAttributeMap &&
"Attribute map not valid.");
147 const GLint attributeIndex = this->currentAttributeMap[index];
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;
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);
161 this->enabledAttributes.push_back(attributeIndex);
164 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
165 glEnableVertexAttribArray(attributeIndex);
166 glVertexAttribDivisor(attributeIndex, element.
instanceStep);
167 this->enabledAttributes.push_back(attributeIndex);
170 if(format == GL_UNSIGNED_INT_2_10_10_10_REV)
171 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
173 glVertexAttribPointer(attributeIndex, size, format, GLboolean(GL_TRUE), structSize, offset);
174 glEnableVertexAttribArray(attributeIndex);
175 this->enabledAttributes.push_back(attributeIndex);
177 glVertexAttribDivisor(attributeIndex, element.
instanceStep);
183 if(iaState.currentIndexBuffer)
184 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iaState.currentIndexBuffer->bufferId);
186 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
188 this->needVertexAttributeSetup =
false;
199 iaState.currentIndexBuffer =
nullptr;
200 iaState.indexBufferStride = 0;
203 auto & buffer = this->buffers->buffers[indexBufferHandle];
204 iaState.currentIndexBuffer = &buffer;
205 iaState.indexBufferStride = stride ? stride : buffer.indexSize;
211 auto & effect = effects->effects[currentEffect];
213 const auto index =
static_cast<GLuint
>(bufferBindingHandle.
handle & 0xFFFFFFFF);
215 if (HandleIsValid(bufferHandle) && index != GL_INVALID_INDEX) {
216 auto & buffer = this->buffers->buffers[bufferHandle];
218 glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.bufferId);
219 glUniformBlockBinding(this->currentProgramId, index, index);
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;
229 if (index != GL_INVALID_INDEX) {
230 glBindBufferBase(GL_UNIFORM_BUFFER, index, 0);
231 glUniformBlockBinding(this->currentProgramId, index, index);
238 if(!HandleIsValid(this->currentEffect)){
239 LOG_INFO(logger,
"Draw with no effect active.");
242 if (this->needVertexAttributeSetup) {
243 this->setupVertexAttributes();
245 assert(iaState.currentIndexBuffer);
247 GLenum indexType = GL_UNSIGNED_INT;
248 if (iaState.indexBufferStride == 2) {
249 indexType = GL_UNSIGNED_SHORT;
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)));
257 glDrawElementsBaseVertex(glPrimitiveType, count, indexType, (
void*)indexOffset,
static_cast<GLint
>(startVertex));
260 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(count,
true); }
265 if(!HandleIsValid(this->currentEffect)){
266 LOG_INFO(logger,
"Draw with no effect active.");
269 if (this->needVertexAttributeSetup) {
270 this->setupVertexAttributes();
273 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[
static_cast<uint32_t
>(primitiveType)];
276 glDrawArrays(glPrimitiveType,
static_cast<GLint
>(startVertex),
static_cast<GLsizei
>(numVertexes));
279 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes,
false); }
284 if(!HandleIsValid(this->currentEffect)){
285 LOG_INFO(logger,
"Draw with no effect active.");
288 if (this->needVertexAttributeSetup) {
289 this->setupVertexAttributes();
292 const GLenum glPrimitiveType = OpenGL20::PrimitiveFormats[
static_cast<uint32_t
>(primitiveType)];
296 if (glDrawArraysInstancedBaseInstance) {
297 glDrawArraysInstancedBaseInstance(glPrimitiveType,
static_cast<GLint
>(startVertex),
static_cast<GLsizei
>(numVertexes),
static_cast<GLsizei
>(numInstances),
static_cast<GLuint
>(startInstance));
301 assert(startInstance == 0);
302 glDrawArraysInstanced(glPrimitiveType,
static_cast<GLint
>(startVertex),
static_cast<GLsizei
>(numVertexes),
static_cast<GLsizei
>(numInstances));
306 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(numVertexes * numInstances,
false); }
311 if(!HandleIsValid(this->currentEffect)){
312 LOG_INFO(logger,
"Draw with no effect active.");
315 if (this->needVertexAttributeSetup) {
316 this->setupVertexAttributes();
318 assert(iaState.currentIndexBuffer);
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;
327 if (glDrawElementsInstancedBaseInstance) {
328 glDrawElementsInstancedBaseInstance(glPrimitiveType, count, indexType, indexOffset,
static_cast<GLsizei
>(numInstances),
static_cast<GLuint
>(startInstance));
332 assert(startInstance == 0);
333 glDrawElementsInstanced(glPrimitiveType, count, indexType, indexOffset,
static_cast<GLsizei
>(numInstances));
337 if (frameStatisticsEnabled) { frameStatisticsAccountDrawCall(count * numInstances,
true); }
342 uint32_t strides[kMaxVertexInputSlots];
343 uint32_t offsets[kMaxVertexInputSlots];
345 for (
size_t i = 0; i < count; i++) {
346 auto & buffer = buffers->buffers[
BufferHandle(handles[i].handle)];
348 assert(buffer.vertexFormat &&
"Vertex buffer must have been created with format information attached.");
350 strides[i] = getSize(*buffer.vertexFormat);
354 setVertexBuffers(handles, count, strides, offsets);
361 iaState.numVertexBuffers = count;
363 for (
size_t i = 0; i < count; i++) {
365 iaState.currentVertexBuffers[i] = &buffer;
366 iaState.strides[i] = strides[i];
367 iaState.offsets[i] = offsets ? offsets[i] : 0;
370 needVertexAttributeSetup =
true;
375 if (!HandleIsValid(handle)) {
380 const BlendStateGL20 & blendState = renderTargets->blendStates[handle];
384 glBlendFuncSeparate(Blends[
size_t(blendState.color.
enabled ? blendState.color.
sourceBlend : BlendState::Blend::One)],
386 Blends[
size_t(blendState.alpha.
enabled ? blendState.alpha.
sourceBlend : BlendState::Blend::One)],
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)]);
391 glBlendColor(constant[0], constant[1], constant[2], constant[3]);
403 return this->currentEffect;
406Cogs::IEffects * Cogs::ContextGL20::getEffects() {
return effects; }
410 assert(!inRenderPass);
411 setRenderTarget(info.renderTargetHandle, info.depthStencilHandle);
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]);
420 if(info.depthLoadOp == LoadOp::Clear){
421 glClearBufferfv(GL_DEPTH, 0, &info.depthClearValue);
424 renderPassInfo = info;
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));
438 inRenderPass =
false;
445 this->currentRenderTarget = handle;
447 static GLenum buffers[OpenGL20::kMaxRenderTargets];
448 if (HandleIsValid(handle)) {
449 const RenderTargetGL20 & renderTarget = this->renderTargets->renderTargets[handle];
451 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
453 if (renderTarget.numTextures) {
454 for (GLint i = 0; i < static_cast<GLint>(renderTarget.numTextures); ++i) {
455 buffers[i] = GL_COLOR_ATTACHMENT0 + i;
458 glDrawBuffers(
static_cast<GLsizei
>(renderTarget.numTextures), buffers);
460 buffers[0] = GL_NONE;
461 glDrawBuffers(1, buffers);
463 }
else if(HandleIsValid(depthStencilHandle)) {
465 const RenderTargetGL20 & renderTarget = this->renderTargets->renderTargets[depthTarget.renderTarget];
466 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
468 buffers[0] = GL_NONE;
469 glDrawBuffers(1, buffers);
472 glBindFramebuffer(GL_FRAMEBUFFER, 0);
474 glDrawBuffer(GL_BACK);
480 glViewport(
static_cast<GLint
>(x),
static_cast<GLint
>(y),
static_cast<GLint
>(width),
static_cast<GLint
>(height));
485 glScissor(x, y, width, height);
490 glClearColor(color[0], color[1], color[2], color[3]);
492 glClear(GL_COLOR_BUFFER_BIT);
497 auto color = colors[0];
499 glClearColor(color[0], color[1], color[2], color[3]);
501 glClear(GL_COLOR_BUFFER_BIT);
506 if (HandleIsValid(currentDepthStencilState)) {
507 const auto & depthState = renderTargets->depthStencilStates[currentDepthStencilState];
509 if (!depthState.writeEnabled) {
511 glDepthMask(GLboolean(GL_TRUE));
517 glClear(GL_DEPTH_BUFFER_BIT);
522 if (!textureBindingHandle)
return;
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;
528 glActiveTexture(GL_TEXTURE0 + slot);
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;
539 assert(slot < maxImageUnits);
540 glBindImageTexture(slot, texture.textureId, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
544 if(boundTarget[slot])
545 glBindTexture(boundTarget[slot], 0);
547 if (glBindImageTexture && slot<maxImageUnits) {
548 glBindImageTexture(slot, 0, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
553 this->boundTextures[slot] = textureHandle;
561 if (!samplerStateBindingHandle)
return;
566 auto & effect = effects->effects[effectHandle];
567 auto hash = ptr->name;
569 auto &samplers = effect.real_sampler[
hash];
570 for(
auto h2 : samplers){
571 if (!effect.samplers.count(h2)) {
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;
585 if (HandleIsValid(samplerStateHandle)) {
586 sampler =
static_cast<GLuint
>(samplerStateHandle.
handle);
591 sampler =
static_cast<GLuint
>(defaultSamplerStateHandle.handle);
593 glBindSampler(slot, sampler);
602 glPolygonMode(GL_FRONT_AND_BACK, rasterizerState.
wireFrame ? GL_LINE : GL_FILL);
607 glDisable(GL_CULL_FACE);
611 glEnable(GL_CULL_FACE);
612 glCullFace(GL_FRONT);
616 glEnable(GL_CULL_FACE);
622 glEnable(GL_POLYGON_OFFSET_FILL);
625 glDisable(GL_POLYGON_OFFSET_FILL);
628 rasterizerState.
scissor ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
630 rasterizerState.
noDepthClip ? glEnable(GL_DEPTH_CLAMP) : glDisable(GL_DEPTH_CLAMP);
635 currentDepthStencilState = handle;
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]);
646 if (effectHandle == currentEffect)
return;
651 if (HandleIsValid(currentEffect)) {
652 for (
const auto & mapping : atomicCounterMappings) {
653 syncCounterFromEffect(mapping);
656 atomicCounterMappings.clear();
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));
662 glBindTexture(boundTarget[i], 0);
664 if(glBindImageTexture && i < maxImageUnits) {
665 glBindImageTexture(
static_cast<GLuint
>(i), 0, 0, GLboolean(GL_FALSE), 0, GL_READ_WRITE, GL_RGBA8);
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);
678 this->currentEffect = effectHandle;
680 if (HandleIsValid(effectHandle)) {
681 auto & effect = this->effects->effects[effectHandle];
682 ContextCommon::setCurrentEffect(&effect);
684 glUseProgram(this->effects->effects[effectHandle].programId);
686 this->currentAttributeMap = effect.attributeMap;
687 this->currentProgramId = effect.programId;
689 atomicCounterMappings.clear();
690 for (
const auto & b : effect.atomicCounterBuffers) {
691 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, b.binding, effects->backingBuffers[b.backingBuffer]);
697 this->currentAttributeMap =
nullptr;
698 this->currentProgramId = GL_INVALID_INDEX;
701 this->needVertexAttributeSetup =
true;
706 if(HandleIsValid(inputLayoutHandle)){
707 InputLayoutGL20 &inputLayout = buffers->inputLayouts[inputLayoutHandle];
709 this->clearInputState();
711 iaState.numVertexBuffers = inputLayout.numFormats;
712 for (
size_t i = 0; i < inputLayout.numFormats; ++i) {
713 iaState.formats[i] = inputLayout.formats[i];
716 this->needVertexAttributeSetup =
true;
719 this->clearInputState();
723void Cogs::ContextGL20::clearInputState()
725 for (
size_t i = 0; i < this->enabledAttributes.size(); ++i) {
726 glDisableVertexAttribArray(this->enabledAttributes[i]);
728 this->enabledAttributes.clear();
730 this->needVertexAttributeSetup =
true;
737 auto & sourceTexture = this->textures->textures[source];
738 auto & targetTexture = this->textures->textures[destination];
742 for (
auto & rt : renderTargets->renderTargets) {
743 for (
size_t i = 0; i < rt.numTextures; ++i) {
744 if (rt.textures[i] == source) {
751 if (!sourceTarget)
return;
753 assert(targetTexture.numSamples == 1 &&
"Cannot resolve to multisample target.");
754 glBindTexture(GL_TEXTURE_2D, targetTexture.textureId);
756 GLuint targetFrameBuffer = 0;
757 glGenFramebuffers(1, &targetFrameBuffer);
759 assert(sourceTexture.width == targetTexture.width &&
"Source and target texture dimensions not equal.");
761 glDisable(GL_SCISSOR_TEST);
763 if (sourceTexture.numSamples > 1 && !depth) {
764 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceTarget->frameBuffer);
765 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFrameBuffer);
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);
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);
776 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
777 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
779 else if (sourceTexture.numSamples > 1 && depth) {
781 assert(depth ==
false &&
"Cannot resolve from multisample depth target.");
784 glBindFramebuffer(GL_FRAMEBUFFER, sourceTarget->frameBuffer);
787 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture.textureId, 0);
790 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, sourceTexture.textureId, 0);
793 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sourceTexture.width, sourceTexture.height);
794 glBindFramebuffer(GL_FRAMEBUFFER, 0);
797 glBindTexture(GL_TEXTURE_2D, 0);
798 glDeleteFramebuffers(1, &targetFrameBuffer);
801void Cogs::ContextGL20::setDefaults()
803 glBindVertexArray(vao);
816 return this->currentEffect;
821 auto & buffer = this->buffers->buffers[bufferHandle];
823 if (buffer.size < width * height *
sizeof(
float)) {
824 LOG_ERROR(logger,
"Cannot read depth buffer into buffer of smaller size.");
829 glReadBuffer(GL_BACK);
831 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
833 glReadPixels(x, y, width, height, GL_DEPTH_COMPONENT, GL_FLOAT,
nullptr);
835 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
840 auto & buffer = this->buffers->buffers[bufferHandle];
843 buffer.mapFlags = mapMode;
845 if (buffer.mappedData.size() != buffer.size) {
846 buffer.mappedData.resize(buffer.size);
849 return buffer.mappedData.data();
851 glBindBuffer(buffer.target, buffer.bufferId);
853 GLbitfield access = 0;
858 return glMapBufferRange(buffer.target, 0,
static_cast<GLsizeiptr
>(buffer.size), access);
864 auto & buffer = this->buffers->buffers[bufferHandle];
866 glBindBuffer(buffer.target, buffer.bufferId);
869 glBufferData(buffer.target,
static_cast<GLsizeiptr
>(buffer.mappedData.size()), buffer.mappedData.data(), GL_STREAM_DRAW);
871 GLboolean result = glUnmapBuffer(buffer.target);
874 LOG_WARNING(logger,
"Unmapping the buffer was unsuccessful.");
878 glBindBuffer(buffer.target, GL_ZERO);
883 assert(HandleIsValid(textureHandle) &&
"Texture handle must be valid.");
885 const auto & texture = this->textures->textures[textureHandle];
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];
892 LOG_WARNING(logger,
"Updating subtexture is unsupported for compressed textures.");
895 glBindTexture(texture.type, texture.textureId);
897 glTexSubImage2D(texture.type,
static_cast<GLint
>(level), 0, 0, texture.width, texture.height, pixelFormat, pixelType, data);
903 assert(HandleIsValid(bufferHandle) &&
"Buffer handle must be valid.");
905 const auto & buffer = this->buffers->buffers[bufferHandle];
907 assert(buffer.size >= offset + size &&
"Buffer size not sufficient to hold new data.");
909 glBindBuffer(buffer.target, buffer.bufferId);
910 glBufferSubData(buffer.target,
static_cast<GLintptr
>(offset),
static_cast<GLsizeiptr
>(size), data);
911 glBindBuffer(buffer.target, 0);
916 assert(HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
917 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
919 assert(HandleIsValid(sourceHandle) &&
"Source buffer handle must be valid.");
920 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
922 assert(sourceBuffer.size == destinationBuffer.size);
924 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, 0,
925 sourceBuffer.target, sourceBuffer.bufferId, 0,
926 static_cast<GLsizeiptr
>(sourceBuffer.size));
934void Cogs::ContextGL20::copySubResource(
BufferHandle destinationHandle,
size_t destinationOffset,
BufferHandle sourceHandle,
size_t sourceOffset,
size_t size)
936 assert(
HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
937 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
938 assert(destinationOffset + size <= destinationBuffer.size);
940 assert(
HandleIsValid(sourceHandle) &&
"Source buffer handle must be valid.");
941 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
942 assert(sourceOffset + size <= sourceBuffer.size);
944 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId,
static_cast<GLintptr
>(destinationOffset),
945 sourceBuffer.target, sourceBuffer.bufferId,
static_cast<GLintptr
>(sourceOffset),
946 static_cast<GLsizeiptr
>(size));
951 auto & buffer = this->buffers->buffers[bufferHandle];
953 if (buffer.size <
static_cast<size_t>(width) *
static_cast<size_t>(height) * 4) {
955 LOG_ERROR(logger,
"Cannot read color buffer into buffer of smaller size.");
960 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
963 glReadBuffer(OpenGL20::Framebuffers[
static_cast<uint32_t
>(framebuffer)]);
964 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
967 auto & renderTarget = this->renderTargets->renderTargets[this->currentRenderTarget];
968 auto & texture = this->textures->textures[renderTarget.textures[0]];
970 glReadBuffer(GL_COLOR_ATTACHMENT0);
972 glReadPixels(x, y, width, height, OpenGL20::PixelFormats[(
int)texture.format], OpenGL20::PixelTypes[(
int)texture.format],
nullptr);
975 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
984 ContextCommon::updateConstantBuffers();
986 if (!HandleIsValid(currentEffect))
return;
988 auto & effect = effects->effects[currentEffect];
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);
997 state.csCBs[constantBuffer.slot] = constantBuffer.buffer;
1002 glDispatchCompute(threadGroupsX, threadGroupsY, threadGroupsZ);
1004 (void)threadGroupsX;
1005 (void)threadGroupsY;
1006 (void)threadGroupsZ;
1016 if (HandleIsValid(bufferHandle)) {
1017 auto & buffer = buffers->buffers[bufferHandle];
1019 if (HandleIsValid(bufferBindingHandle)) {
1021 if (HandleIsValid(currentEffect)) {
1022 auto & effect = this->effects->effects[currentEffect];
1024 auto binding =
static_cast<GLint
>(bufferBindingHandle.
handle >> 32) - 1;
1025 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, buffer.bufferId);
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()) {
1031 mapping.backingBuffer = buffer.counterBufferId;
1032 mapping.effectAtomicCounterVariableIndex = index;
1033 this->atomicCounterMappings.push_back(mapping);
1035 syncCounterToEffect(mapping);
1045 const auto & effect = this->effects->effects[currentEffect];
1046 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1047 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
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);
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];
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);
1073 auto & buffer = buffers->buffers[bufferHandle];
1074 if (buffer.counterBufferId == GL_INVALID_INDEX) {
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);
1085 if (HandleIsValid(currentEffect)) {
1086 for (
const auto & mapping : atomicCounterMappings) {
1087 if (mapping.backingBuffer == buffer.counterBufferId) {
1088 syncCounterToEffect(mapping);
1096 assert(HandleIsValid(sourceBufferHandle) &&
"Destination buffer handle must be valid.");
1097 const auto & sourceBuffer = this->buffers->buffers[sourceBufferHandle];
1098 assert(
sizeof(GLuint) <= sourceBuffer.size);
1100 auto & buffer = buffers->buffers[bufferHandle];
1101 assert(buffer.counterBufferId != GL_INVALID_INDEX);
1103 copySubBuffer(GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1104 GL_ARRAY_BUFFER, sourceBuffer.bufferId, 0,
1108 if (HandleIsValid(currentEffect)) {
1109 for (
const auto & mapping : atomicCounterMappings) {
1110 if (mapping.backingBuffer == buffer.counterBufferId) {
1111 syncCounterToEffect(mapping);
1119 auto & buffer = buffers->buffers[bufferHandle];
1121 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1126 if (HandleIsValid(currentEffect)) {
1127 for (
const auto & mapping : atomicCounterMappings) {
1128 if (mapping.backingBuffer == buffer.counterBufferId) {
1129 syncCounterFromEffect(mapping);
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);
1145 assert(HandleIsValid(destinationBufferHandle) &&
"Destination buffer handle must be valid.");
1146 const auto & destinationBuffer = this->buffers->buffers[destinationBufferHandle];
1147 assert(
sizeof(GLuint) <= destinationBuffer.size);
1149 auto & buffer = buffers->buffers[bufferHandle];
1151 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1156 if (HandleIsValid(currentEffect)) {
1157 for (
const auto & mapping : atomicCounterMappings) {
1158 if (mapping.backingBuffer == buffer.counterBufferId) {
1159 syncCounterFromEffect(mapping);
1164 copySubBuffer(GL_ARRAY_BUFFER, destinationBuffer.bufferId, 0,
1165 GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1168void Cogs::ContextGL20::copyTexture(
TextureHandle dstHandle,
unsigned dstSub,
unsigned dstX,
unsigned dstY,
unsigned dstZ,
TextureHandle srcHandle,
unsigned srcSub)
1171 TextureGL20 & srcTexture = this->textures->textures[srcHandle];
1172 TextureGL20 & dstTexture = this->textures->textures[dstHandle];
1174 unsigned srcLevel = srcSub;
1175 unsigned srcLayer = 0;
1176 unsigned dstLevel = dstSub;
1177 unsigned dstLayer = 0;
1179 glCopyImageSubData(srcTexture.textureId,
1183 dstTexture.textureId,
1186 dstX, dstY, dstZ+dstLayer,
1187 srcTexture.width, srcTexture.height, 1);
1199void Cogs::ContextGL20::clearResource(
BufferHandle destinationHandle, uint32_t *Values)
1201 assert(HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
1203 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1205 GLenum internalformat = GL_R32UI;
1206 GLenum format = GL_RED_INTEGER;
1207 GLenum type = GL_UNSIGNED_INT;
1209 if (glClearNamedBufferData) {
1210 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1212 else if(glClearBufferData){
1213 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1214 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1215 glBindBuffer(destinationBuffer.target, 0);
1225void Cogs::ContextGL20::clearResource(
BufferHandle destinationHandle,
float *Values)
1227 assert(
HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
1229 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1231 GLenum internalformat = GL_R32F;
1232 GLenum format = GL_RED;
1233 GLenum type = GL_FLOAT;
1235 if (glClearNamedBufferData) {
1236 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1238 else if(glClearBufferData){
1239 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1240 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1241 glBindBuffer(destinationBuffer.target, 0);
1252void Cogs::ContextGL20::preDraw()
1254 ContextCommon::updateConstantBuffers();
1258 auto & effect = effects->effects[currentEffect];
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);
1267 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
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);
1278 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1283void Cogs::ContextGL20::postDraw()
1285 if (unorderedMemoryAcccess) {
1287 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1291 unorderedMemoryAcccess =
false;
1298 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1,
static_cast<GLsizei
>(name.
size()), name.
data());
1312 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 1, GL_DEBUG_SEVERITY_HIGH,
static_cast<GLsizei
>(name.
size()), name.
data());
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
constexpr size_t size() const noexcept
Get the size of the string.
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
Contains all Cogs related functionality.
@ 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.
Framebuffer
Framebuffers to select from when doing framebuffer operations.
@ InstanceData
Per instance data.
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
@ InstanceMatrix
Instance matrix semantic.
uint8_t enabled
If blending is enabled.
Blend destinationBlend
Blend option for the blend destination data.
BlendOperation operation
How the two blend values are combined.
Blend sourceBlend
Blend option for the blend source data.
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.
static const Handle_t NoHandle
Represents a handle to nothing.
handle_type handle
Internal resource handle.
Provides effects and shader management functionality.
EMapMode
Mapping mode enumeration.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
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.
@ ReadWriteTexture
The texture can be used as a read/write texture. Can be used to output data from compute shaders.
Vertex element structure used to describe a single data element in a vertex for the input assembler.
InputType inputType
Input type of the element, vertex or instance data.
DataFormat format
Format of the element.
uint16_t offset
Offset in bytes from the vertex position in memory.
uint16_t semanticIndex
Index for the semantic mapping.
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).
uint16_t instanceStep
Instance step factor.