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[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[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[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[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 (
int 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()
804 glBindVertexArray(vao);
817 return this->currentEffect;
822 auto & buffer = this->buffers->buffers[bufferHandle];
824 if (buffer.size < width * height *
sizeof(
float)) {
825 LOG_ERROR(logger,
"Cannot read depth buffer into buffer of smaller size.");
830 glReadBuffer(GL_BACK);
832 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
834 glReadPixels(x, y, width, height, GL_DEPTH_COMPONENT, GL_FLOAT,
nullptr);
836 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
841 auto & buffer = this->buffers->buffers[bufferHandle];
844 buffer.mapFlags = mapMode;
846 if (buffer.mappedData.size() != buffer.size) {
847 buffer.mappedData.resize(buffer.size);
850 return buffer.mappedData.data();
852 glBindBuffer(buffer.target, buffer.bufferId);
854 GLbitfield access = 0;
859 return glMapBufferRange(buffer.target, 0,
static_cast<GLsizeiptr
>(buffer.size), access);
865 auto & buffer = this->buffers->buffers[bufferHandle];
867 glBindBuffer(buffer.target, buffer.bufferId);
870 glBufferData(buffer.target,
static_cast<GLsizeiptr
>(buffer.mappedData.size()), buffer.mappedData.data(), GL_STREAM_DRAW);
872 GLboolean result = glUnmapBuffer(buffer.target);
875 LOG_WARNING(logger,
"Unmapping the buffer was unsuccessful.");
879 glBindBuffer(buffer.target, GL_ZERO);
884 assert(HandleIsValid(textureHandle) &&
"Texture handle must be valid.");
886 const auto & texture = this->textures->textures[textureHandle];
888 const GLenum pixelType = OpenGL20::PixelTypes[(int)texture.format];
889 const GLenum pixelFormat = OpenGL20::PixelFormats[(
int)texture.format];
890 const GLboolean isCompressed = OpenGL20::CompressedFormats[(int)texture.format];
893 LOG_WARNING(logger,
"Updating subtexture is unsupported for compressed textures.");
896 glBindTexture(texture.type, texture.textureId);
898 glTexSubImage2D(texture.type,
static_cast<GLint
>(level), 0, 0, texture.width, texture.height, pixelFormat, pixelType, data);
904 assert(HandleIsValid(bufferHandle) &&
"Buffer handle must be valid.");
906 const auto & buffer = this->buffers->buffers[bufferHandle];
908 assert(buffer.size >= offset + size &&
"Buffer size not sufficient to hold new data.");
910 glBindBuffer(buffer.target, buffer.bufferId);
911 glBufferSubData(buffer.target,
static_cast<GLintptr
>(offset),
static_cast<GLsizeiptr
>(size), data);
912 glBindBuffer(buffer.target, 0);
917 assert(HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
918 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
920 assert(HandleIsValid(sourceHandle) &&
"Source buffer handle must be valid.");
921 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
923 assert(sourceBuffer.size == destinationBuffer.size);
925 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId, 0,
926 sourceBuffer.target, sourceBuffer.bufferId, 0,
927 static_cast<GLsizeiptr
>(sourceBuffer.size));
935void Cogs::ContextGL20::copySubResource(
BufferHandle destinationHandle,
size_t destinationOffset,
BufferHandle sourceHandle,
size_t sourceOffset,
size_t size)
937 assert(
HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
938 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
939 assert(destinationOffset + size <= destinationBuffer.size);
941 assert(
HandleIsValid(sourceHandle) &&
"Source buffer handle must be valid.");
942 const auto & sourceBuffer = this->buffers->buffers[sourceHandle];
943 assert(sourceOffset + size <= sourceBuffer.size);
945 copySubBuffer(destinationBuffer.target, destinationBuffer.bufferId,
static_cast<GLintptr
>(destinationOffset),
946 sourceBuffer.target, sourceBuffer.bufferId,
static_cast<GLintptr
>(sourceOffset),
947 static_cast<GLsizeiptr
>(size));
952 auto & buffer = this->buffers->buffers[bufferHandle];
954 if (buffer.size <
static_cast<size_t>(width) *
static_cast<size_t>(height) * 4) {
956 LOG_ERROR(logger,
"Cannot read color buffer into buffer of smaller size.");
961 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer.bufferId);
964 glReadBuffer(OpenGL20::Framebuffers[framebuffer]);
965 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
968 auto & renderTarget = this->renderTargets->renderTargets[this->currentRenderTarget];
969 auto & texture = this->textures->textures[renderTarget.textures[0]];
971 glReadBuffer(GL_COLOR_ATTACHMENT0);
973 glReadPixels(x, y, width, height, OpenGL20::PixelFormats[(
int)texture.format], OpenGL20::PixelTypes[(
int)texture.format],
nullptr);
976 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
986 ContextCommon::updateConstantBuffers();
988 if (!HandleIsValid(currentEffect))
return;
990 auto & effect = effects->effects[currentEffect];
992 for (
auto & constantBuffer : effect.computeShader.reflection.constantBuffers) {
993 if (HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.csCBs[constantBuffer.slot]) {
994 auto & buffer = buffers->buffers[constantBuffer.buffer];
995 if (constantBuffer.index != GL_INVALID_INDEX) {
996 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
997 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
999 state.csCBs[constantBuffer.slot] = constantBuffer.buffer;
1004 glDispatchCompute(threadGroupsX, threadGroupsY, threadGroupsZ);
1006 (void)threadGroupsX;
1007 (void)threadGroupsY;
1008 (void)threadGroupsZ;
1018 if (HandleIsValid(bufferHandle)) {
1019 auto & buffer = buffers->buffers[bufferHandle];
1021 if (HandleIsValid(bufferBindingHandle)) {
1023 if (HandleIsValid(currentEffect)) {
1024 auto & effect = this->effects->effects[currentEffect];
1026 auto binding =
static_cast<GLint
>(bufferBindingHandle.
handle >> 32) - 1;
1027 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, buffer.bufferId);
1029 if (buffer.counterBufferId != GL_INVALID_INDEX) {
1030 auto index =
static_cast<GLint
>(bufferBindingHandle.
handle & 0xFFFFFFFF) - 1;
1031 if (
size_t(index) < effect.atomicCounterVariables.size()) {
1033 mapping.backingBuffer = buffer.counterBufferId;
1034 mapping.effectAtomicCounterVariableIndex = index;
1035 this->atomicCounterMappings.push_back(mapping);
1037 syncCounterToEffect(mapping);
1047 const auto & effect = this->effects->effects[currentEffect];
1048 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1049 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1051 glBindBuffer(GL_COPY_READ_BUFFER, mapping.backingBuffer);
1052 glBindBuffer(GL_COPY_WRITE_BUFFER, effects->backingBuffers[effectBuffer.backingBuffer]);
1053 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, effectVariable.bufferOffset,
static_cast<GLsizei
>(
sizeof(GLuint)));
1054 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1055 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1060 const auto & effect = this->effects->effects[currentEffect];
1061 const auto & effectVariable = effect.atomicCounterVariables[mapping.effectAtomicCounterVariableIndex];
1062 const auto & effectBuffer = effect.atomicCounterBuffers[effectVariable.bufferIndex];
1063 auto effectBackingBuffer = effects->backingBuffers[effectBuffer.backingBuffer];
1065 glBindBuffer(GL_COPY_READ_BUFFER, effectBackingBuffer);
1066 glBindBuffer(GL_COPY_WRITE_BUFFER, mapping.backingBuffer);
1067 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, effectVariable.bufferOffset, 0,
static_cast<GLsizei
>(
sizeof(GLuint)));
1068 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1069 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1075 auto & buffer = buffers->buffers[bufferHandle];
1076 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1082 glBindBuffer(GL_COPY_READ_BUFFER, buffer.counterBufferId);
1083 glBufferData(GL_COPY_READ_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(GLuint)), &v, GL_DYNAMIC_COPY);
1084 glBindBuffer(GL_COPY_READ_BUFFER, 0);
1087 if (HandleIsValid(currentEffect)) {
1088 for (
const auto & mapping : atomicCounterMappings) {
1089 if (mapping.backingBuffer == buffer.counterBufferId) {
1090 syncCounterToEffect(mapping);
1098 assert(HandleIsValid(sourceBufferHandle) &&
"Destination buffer handle must be valid.");
1099 const auto & sourceBuffer = this->buffers->buffers[sourceBufferHandle];
1100 assert(
sizeof(GLuint) <= sourceBuffer.size);
1102 auto & buffer = buffers->buffers[bufferHandle];
1103 assert(buffer.counterBufferId != GL_INVALID_INDEX);
1105 copySubBuffer(GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1106 GL_ARRAY_BUFFER, sourceBuffer.bufferId, 0,
1110 if (HandleIsValid(currentEffect)) {
1111 for (
const auto & mapping : atomicCounterMappings) {
1112 if (mapping.backingBuffer == buffer.counterBufferId) {
1113 syncCounterToEffect(mapping);
1121 auto & buffer = buffers->buffers[bufferHandle];
1123 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1128 if (HandleIsValid(currentEffect)) {
1129 for (
const auto & mapping : atomicCounterMappings) {
1130 if (mapping.backingBuffer == buffer.counterBufferId) {
1131 syncCounterFromEffect(mapping);
1137 glBindBuffer(GL_COPY_WRITE_BUFFER, buffer.counterBufferId);
1138 glGetBufferSubData(GL_COPY_WRITE_BUFFER,
static_cast<GLintptr
>(0),
static_cast<GLsizeiptr
>(
sizeof(GLuint)), &v);
1139 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1147 assert(HandleIsValid(destinationBufferHandle) &&
"Destination buffer handle must be valid.");
1148 const auto & destinationBuffer = this->buffers->buffers[destinationBufferHandle];
1149 assert(
sizeof(GLuint) <= destinationBuffer.size);
1151 auto & buffer = buffers->buffers[bufferHandle];
1153 if (buffer.counterBufferId == GL_INVALID_INDEX) {
1158 if (HandleIsValid(currentEffect)) {
1159 for (
const auto & mapping : atomicCounterMappings) {
1160 if (mapping.backingBuffer == buffer.counterBufferId) {
1161 syncCounterFromEffect(mapping);
1166 copySubBuffer(GL_ARRAY_BUFFER, destinationBuffer.bufferId, 0,
1167 GL_ARRAY_BUFFER, buffer.counterBufferId, 0,
1170void Cogs::ContextGL20::copyTexture(
TextureHandle dstHandle,
unsigned dstSub,
unsigned dstX,
unsigned dstY,
unsigned dstZ,
TextureHandle srcHandle,
unsigned srcSub)
1173 TextureGL20 & srcTexture = this->textures->textures[srcHandle];
1174 TextureGL20 & dstTexture = this->textures->textures[dstHandle];
1176 unsigned srcLevel = srcSub;
1177 unsigned srcLayer = 0;
1178 unsigned dstLevel = dstSub;
1179 unsigned dstLayer = 0;
1181 glCopyImageSubData(srcTexture.textureId,
1185 dstTexture.textureId,
1188 dstX, dstY, dstZ+dstLayer,
1189 srcTexture.width, srcTexture.height, 1);
1201void Cogs::ContextGL20::clearResource(
BufferHandle destinationHandle, uint32_t *Values)
1203 assert(HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
1205 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1207 GLenum internalformat = GL_R32UI;
1208 GLenum format = GL_RED_INTEGER;
1209 GLenum type = GL_UNSIGNED_INT;
1211 if (glClearNamedBufferData) {
1212 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1214 else if(glClearBufferData){
1215 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1216 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1217 glBindBuffer(destinationBuffer.target, 0);
1227void Cogs::ContextGL20::clearResource(
BufferHandle destinationHandle,
float *Values)
1229 assert(
HandleIsValid(destinationHandle) &&
"Destination buffer handle must be valid.");
1231 const auto & destinationBuffer = this->buffers->buffers[destinationHandle];
1233 GLenum internalformat = GL_R32F;
1234 GLenum format = GL_RED;
1235 GLenum type = GL_FLOAT;
1237 if (glClearNamedBufferData) {
1238 glClearNamedBufferData(destinationBuffer.bufferId, internalformat, format, type, Values);
1240 else if(glClearBufferData){
1241 glBindBuffer(destinationBuffer.target, destinationBuffer.bufferId);
1242 glClearBufferData(destinationBuffer.target, internalformat, format, type, Values);
1243 glBindBuffer(destinationBuffer.target, 0);
1254void Cogs::ContextGL20::preDraw()
1256 ContextCommon::updateConstantBuffers();
1260 auto & effect = effects->effects[currentEffect];
1262 for (
auto & constantBuffer : effect.vertexShader.reflection.constantBuffers) {
1263 if (
HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.vsCBs[constantBuffer.slot]) {
1264 auto & buffer = buffers->buffers[constantBuffer.buffer];
1265 if (constantBuffer.index != GL_INVALID_INDEX) {
1266 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1267 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1269 state.vsCBs[constantBuffer.slot] = constantBuffer.buffer;
1273 for (
auto & constantBuffer : effect.pixelShader.reflection.constantBuffers) {
1274 if (
HandleIsValid(constantBuffer.buffer) && !constantBuffer.manual && constantBuffer.buffer != state.psCBs[constantBuffer.slot]) {
1275 auto & buffer = buffers->buffers[constantBuffer.buffer];
1276 if (constantBuffer.index != GL_INVALID_INDEX) {
1277 glBindBufferBase(GL_UNIFORM_BUFFER, constantBuffer.index, buffer.bufferId);
1278 glUniformBlockBinding(currentProgramId, constantBuffer.index, constantBuffer.index);
1280 state.psCBs[constantBuffer.slot] = constantBuffer.buffer;
1285void Cogs::ContextGL20::postDraw()
1287 if (unorderedMemoryAcccess) {
1289 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1293 unorderedMemoryAcccess =
false;
1300 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1,
static_cast<GLsizei
>(name.
size()), name.
data());
1314 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.
@ InstanceData
Per instance data.
@ 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 drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances) override
Draws non-indexed, instanced primitives.
void getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle) override
Get the associated counter of a buffer.
void unmap(BufferHandle bufferHandle) override
Unmaps the given buffer, applying any synchronization necessary to reflect changes in the mapped memo...
void clearDepth(const float depth=1.0f) override
Clear the currently set depth/stencil target to the given depth.
void setViewport(const float x, const float y, const float width, const float height) override
Sets the current viewport to the given location and dimensions.
void setBlendState(const BlendStateHandle handle, const float *constant) override
Set the current blend state.
void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0) override
Draws indexed, non-instanced primitives.
void updateSubTexture(TextureHandle textureHandle, const size_t level, const void *data) override
Update the data of a level in the given texture.
void dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ) override
Dispatch computing work on the graphics device using the desired thread group count.
void readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current depth target into the given bufferHandle.
void reset() override
Resets all state changes made to the GPU since the last call to beginFrame.
void setBuffer(const BufferBindingHandle bufferBindingHandle, BufferHandle bufferHandle) override
Sets a buffer to bind to the given binding.
void draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numPrimitives) override
Draws non-indexed, non-instanced primitives.
void signal(FenceHandle fenceHandle) override
Insert a fence in the command stream that will signal when all commands before the fence are complete...
void setRasterizerState(const RasterizerStateHandle handle) override
Set the current rasterizer state.
void endRenderPass() override
End a render pass.
void setConstantBuffer(const ConstantBufferBindingHandle bufferBinding, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size) override
Sets a constant buffer to the given constant buffer binding.
void setAnnotationMarker(const StringView &name) override
Add a tag in the sequence of commands in graphics debugger.
void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets) override
Sets the current vertex buffers.
void setDepthStencilState(const DepthStencilStateHandle handle) override
Set the current depth stencil state.
void popCommandGroupAnnotation() override
End to tag a sequence of commands as a group in graphics debugger.
void setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle) override
Sets the sampler state binding given to the given sampler state.
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle) override
Sets the texture given to the binding given by textureBindingHandle.
void * map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *stride) override
Maps the given buffer so it can be accessed.
void setInputLayout(const InputLayoutHandle inputLayoutHandle) override
Sets the current input layout.
void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
void beginRenderPass(const RenderPassInfo &info) override
Begin a render pass.
void setEffect(EffectHandle effectHandle) override
Set the current effect.
void updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void *data) override
Update a region of data in a buffer.
void setScissor(const int x, const int y, const int width, const int height) override
Sets the current scissor rectangle.
void readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current render target into the given bufferHandle.
void resolveResource(TextureHandle source, TextureHandle destination) override
Resolves the given source resource target into the given destination texture.
void drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes) override
Draws indexed, instanced primitives.
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
bool depthEnabled
If depth testing is enabled/disabled. Default is true.
DepthFunction depthFunction
The depth function to use for depth testing.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
bool writeEnabled
If writes to the depth buffer are enabled/disabled. Default is true.
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.
EPrimitiveType
Primitive type enumeration.
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.