no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "profiler/Profiler.h"
namespace cc {
namespace gfx {
GLES2Buffer::GLES2Buffer() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Buffer::~GLES2Buffer() {
destroy();
}
void GLES2Buffer::doInit(const BufferInfo & /*info*/) {
_gpuBuffer = ccnew GLES2GPUBuffer;
_gpuBuffer->usage = _usage;
_gpuBuffer->memUsage = _memUsage;
_gpuBuffer->size = _size;
_gpuBuffer->stride = _stride;
_gpuBuffer->count = _count;
if (hasFlag(_usage, BufferUsageBit::INDIRECT)) {
_gpuBuffer->indirects.resize(_count);
}
cmdFuncGLES2CreateBuffer(GLES2Device::getInstance(), _gpuBuffer);
GLES2Device::getInstance()->getMemoryStatus().bufferSize += _size;
CC_PROFILE_MEMORY_INC(Buffer, _size);
}
void GLES2Buffer::doInit(const BufferViewInfo &info) {
auto *buffer = static_cast<GLES2Buffer *>(info.buffer);
_gpuBufferView = ccnew GLES2GPUBufferView;
_gpuBufferView->gpuBuffer = buffer->gpuBuffer();
_gpuBufferView->range = _size;
_gpuBufferView->offset = info.offset;
}
void GLES2Buffer::doDestroy() {
if (_gpuBuffer) {
GLES2Device::getInstance()->getMemoryStatus().bufferSize -= _size;
CC_PROFILE_MEMORY_DEC(Buffer, _size);
cmdFuncGLES2DestroyBuffer(GLES2Device::getInstance(), _gpuBuffer);
delete _gpuBuffer;
_gpuBuffer = nullptr;
}
CC_SAFE_DELETE(_gpuBufferView);
}
void GLES2Buffer::doResize(uint32_t size, uint32_t count) {
GLES2Device::getInstance()->getMemoryStatus().bufferSize -= _size;
CC_PROFILE_MEMORY_DEC(Buffer, _size);
_gpuBuffer->size = size;
_gpuBuffer->count = count;
cmdFuncGLES2ResizeBuffer(GLES2Device::getInstance(), _gpuBuffer);
GLES2Device::getInstance()->getMemoryStatus().bufferSize += size;
CC_PROFILE_MEMORY_INC(Buffer, size);
}
void GLES2Buffer::update(const void *buffer, uint32_t size) {
CC_PROFILE(GLES2BufferUpdate);
cmdFuncGLES2UpdateBuffer(GLES2Device::getInstance(), _gpuBuffer, buffer, 0U, size);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,57 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXBuffer.h"
namespace cc {
namespace gfx {
struct GLES2GPUBuffer;
struct GLES2GPUBufferView;
class CC_GLES2_API GLES2Buffer final : public Buffer {
public:
GLES2Buffer();
~GLES2Buffer() override;
void update(const void *buffer, uint32_t size) override;
inline GLES2GPUBuffer *gpuBuffer() const { return _gpuBuffer; }
inline GLES2GPUBufferView *gpuBufferView() const { return _gpuBufferView; }
protected:
void doInit(const BufferInfo &info) override;
void doInit(const BufferViewInfo &info) override;
void doDestroy() override;
void doResize(uint32_t size, uint32_t count) override;
GLES2GPUBuffer *_gpuBuffer = nullptr;
GLES2GPUBufferView *_gpuBufferView = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,424 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2CommandBuffer.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSet.h"
#include "GLES2Device.h"
#include "GLES2Framebuffer.h"
#include "GLES2InputAssembler.h"
#include "GLES2PipelineState.h"
#include "GLES2RenderPass.h"
#include "GLES2Texture.h"
#include "profiler/Profiler.h"
namespace cc {
namespace gfx {
GLES2CommandBuffer::GLES2CommandBuffer() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2CommandBuffer::~GLES2CommandBuffer() {
destroy();
}
void GLES2CommandBuffer::doInit(const CommandBufferInfo &info) {
_type = info.type;
_queue = info.queue;
_cmdAllocator = ccnew GLES2GPUCommandAllocator;
_curCmdPackage = ccnew GLES2CmdPackage;
size_t setCount = GLES2Device::getInstance()->bindingMappingInfo().setIndices.size();
_curGPUDescriptorSets.resize(setCount);
_curDynamicOffsets.resize(setCount);
}
void GLES2CommandBuffer::doDestroy() {
if (!_cmdAllocator) return;
_cmdAllocator->clearCmds(_curCmdPackage);
CC_SAFE_DELETE(_curCmdPackage);
while (!_pendingPackages.empty()) {
GLES2CmdPackage *package = _pendingPackages.front();
_cmdAllocator->clearCmds(package);
CC_SAFE_DELETE(package);
_pendingPackages.pop();
}
while (!_freePackages.empty()) {
GLES2CmdPackage *package = _freePackages.front();
_cmdAllocator->clearCmds(package);
CC_SAFE_DELETE(package);
_freePackages.pop();
}
_cmdAllocator->reset();
CC_SAFE_DELETE(_cmdAllocator);
}
void GLES2CommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass*/, Framebuffer * /*frameBuffer*/) {
_cmdAllocator->clearCmds(_curCmdPackage);
_curGPUPipelineState = nullptr;
_curGPUInputAssember = nullptr;
_curGPUDescriptorSets.assign(_curGPUDescriptorSets.size(), nullptr);
_numDrawCalls = 0;
_numInstances = 0;
_numTriangles = 0;
}
void GLES2CommandBuffer::end() {
if (_isStateInvalid) {
bindStates();
}
_pendingPackages.push(_curCmdPackage);
if (!_freePackages.empty()) {
_curCmdPackage = _freePackages.front();
_freePackages.pop();
} else {
_curCmdPackage = ccnew GLES2CmdPackage;
}
}
void GLES2CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const * /*secondaryCBs*/, uint32_t /*secondaryCBCount*/) {
_curSubpassIdx = 0U;
GLES2CmdBeginRenderPass *cmd = _cmdAllocator->beginRenderPassCmdPool.alloc();
cmd->subpassIdx = _curSubpassIdx;
cmd->gpuRenderPass = static_cast<GLES2RenderPass *>(renderPass)->gpuRenderPass();
cmd->gpuFBO = static_cast<GLES2Framebuffer *>(fbo)->gpuFBO();
cmd->renderArea = renderArea;
size_t numClearColors = cmd->gpuRenderPass->colorAttachments.size();
memcpy(cmd->clearColors, colors, numClearColors * sizeof(Color));
cmd->clearDepth = depth;
cmd->clearStencil = stencil;
_curCmdPackage->beginRenderPassCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::BEGIN_RENDER_PASS);
_curDynamicStates.viewport = {renderArea.x, renderArea.y, renderArea.width, renderArea.height};
_curDynamicStates.scissor = renderArea;
}
void GLES2CommandBuffer::endRenderPass() {
_curCmdPackage->cmds.push(GLESCmdType::END_RENDER_PASS);
}
void GLES2CommandBuffer::nextSubpass() {
_curCmdPackage->cmds.push(GLESCmdType::END_RENDER_PASS);
GLES2CmdBeginRenderPass *cmd = _cmdAllocator->beginRenderPassCmdPool.alloc();
cmd->subpassIdx = ++_curSubpassIdx;
_curCmdPackage->beginRenderPassCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::BEGIN_RENDER_PASS);
}
void GLES2CommandBuffer::insertMarker(const MarkerInfo &marker) {
std::ignore = marker;
}
void GLES2CommandBuffer::beginMarker(const MarkerInfo &marker) {
std::ignore = marker;
}
void GLES2CommandBuffer::endMarker() {
}
void GLES2CommandBuffer::bindPipelineState(PipelineState *pso) {
GLES2GPUPipelineState *gpuPipelineState = static_cast<GLES2PipelineState *>(pso)->gpuPipelineState();
if (_curGPUPipelineState != gpuPipelineState) {
_curGPUPipelineState = gpuPipelineState;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) {
CC_ASSERT(_curGPUDescriptorSets.size() > set);
GLES2GPUDescriptorSet *gpuDescriptorSet = static_cast<GLES2DescriptorSet *>(descriptorSet)->gpuDescriptorSet();
if (_curGPUDescriptorSets[set] != gpuDescriptorSet) {
_curGPUDescriptorSets[set] = gpuDescriptorSet;
_isStateInvalid = true;
}
if (dynamicOffsetCount) {
_curDynamicOffsets[set].assign(dynamicOffsets, dynamicOffsets + dynamicOffsetCount);
_isStateInvalid = true;
} else if (!_curDynamicOffsets[set].empty()) {
_curDynamicOffsets[set].assign(_curDynamicOffsets[set].size(), 0);
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::bindInputAssembler(InputAssembler *ia) {
_curGPUInputAssember = static_cast<GLES2InputAssembler *>(ia)->gpuInputAssembler();
_isStateInvalid = true;
}
void GLES2CommandBuffer::setViewport(const Viewport &vp) {
if ((_curDynamicStates.viewport.left != vp.left) ||
(_curDynamicStates.viewport.top != vp.top) ||
(_curDynamicStates.viewport.width != vp.width) ||
(_curDynamicStates.viewport.height != vp.height) ||
math::isNotEqualF(_curDynamicStates.viewport.minDepth, vp.minDepth) ||
math::isNotEqualF(_curDynamicStates.viewport.maxDepth, vp.maxDepth)) {
_curDynamicStates.viewport = vp;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setScissor(const Rect &rect) {
if ((_curDynamicStates.scissor.x != rect.x) ||
(_curDynamicStates.scissor.y != rect.y) ||
(_curDynamicStates.scissor.width != rect.width) ||
(_curDynamicStates.scissor.height != rect.height)) {
_curDynamicStates.scissor = rect;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setLineWidth(float width) {
if (math::isNotEqualF(_curDynamicStates.lineWidth, width)) {
_curDynamicStates.lineWidth = width;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setDepthBias(float constant, float clamp, float slope) {
if (math::isNotEqualF(_curDynamicStates.depthBiasConstant, constant) ||
math::isNotEqualF(_curDynamicStates.depthBiasClamp, clamp) ||
math::isNotEqualF(_curDynamicStates.depthBiasSlope, slope)) {
_curDynamicStates.depthBiasConstant = constant;
_curDynamicStates.depthBiasClamp = clamp;
_curDynamicStates.depthBiasSlope = slope;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setBlendConstants(const Color &constants) {
if (math::isNotEqualF(_curDynamicStates.blendConstant.x, constants.x) ||
math::isNotEqualF(_curDynamicStates.blendConstant.y, constants.y) ||
math::isNotEqualF(_curDynamicStates.blendConstant.z, constants.z) ||
math::isNotEqualF(_curDynamicStates.blendConstant.w, constants.w)) {
_curDynamicStates.blendConstant.x = constants.x;
_curDynamicStates.blendConstant.y = constants.y;
_curDynamicStates.blendConstant.z = constants.z;
_curDynamicStates.blendConstant.w = constants.w;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setDepthBound(float minBounds, float maxBounds) {
if (math::isNotEqualF(_curDynamicStates.depthMinBounds, minBounds) ||
math::isNotEqualF(_curDynamicStates.depthMaxBounds, maxBounds)) {
_curDynamicStates.depthMinBounds = minBounds;
_curDynamicStates.depthMaxBounds = maxBounds;
_isStateInvalid = true;
}
}
void GLES2CommandBuffer::setStencilWriteMask(StencilFace face, uint32_t mask) {
auto update = [&](DynamicStencilStates &stencilState) {
if (stencilState.writeMask != mask) {
stencilState.writeMask = mask;
_isStateInvalid = true;
}
};
if (hasFlag(face, StencilFace::FRONT)) update(_curDynamicStates.stencilStatesFront);
if (hasFlag(face, StencilFace::BACK)) update(_curDynamicStates.stencilStatesBack);
}
void GLES2CommandBuffer::setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) {
auto update = [&](DynamicStencilStates &stencilState) {
if ((stencilState.reference != ref) ||
(stencilState.compareMask != mask)) {
stencilState.reference = ref;
stencilState.compareMask = mask;
_isStateInvalid = true;
}
};
if (hasFlag(face, StencilFace::FRONT)) update(_curDynamicStates.stencilStatesFront);
if (hasFlag(face, StencilFace::BACK)) update(_curDynamicStates.stencilStatesBack);
}
void GLES2CommandBuffer::draw(const DrawInfo &info) {
CC_PROFILE(GLES2CommandBufferDraw);
if (_isStateInvalid) {
bindStates();
}
GLES2CmdDraw *cmd = _cmdAllocator->drawCmdPool.alloc();
cmd->drawInfo = info;
_curCmdPackage->drawCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::DRAW);
++_numDrawCalls;
_numInstances += info.instanceCount;
uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount;
if (_curGPUPipelineState) {
switch (_curGPUPipelineState->glPrimitive) {
case GL_TRIANGLES: {
_numTriangles += indexCount / 3 * std::max(info.instanceCount, 1U);
break;
}
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN: {
_numTriangles += (indexCount - 2) * std::max(info.instanceCount, 1U);
break;
}
default:
break;
}
}
}
void GLES2CommandBuffer::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
GLES2GPUBuffer *gpuBuffer = static_cast<GLES2Buffer *>(buff)->gpuBuffer();
if (gpuBuffer) {
GLES2CmdUpdateBuffer *cmd = _cmdAllocator->updateBufferCmdPool.alloc();
cmd->gpuBuffer = gpuBuffer;
cmd->size = size;
cmd->buffer = static_cast<const uint8_t *>(data);
_curCmdPackage->updateBufferCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::UPDATE_BUFFER);
}
}
void GLES2CommandBuffer::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
GLES2GPUTexture *gpuTexture = static_cast<GLES2Texture *>(texture)->gpuTexture();
if (gpuTexture) {
GLES2CmdCopyBufferToTexture *cmd = _cmdAllocator->copyBufferToTextureCmdPool.alloc();
cmd->gpuTexture = gpuTexture;
cmd->regions = regions;
cmd->count = count;
cmd->buffers = buffers;
_curCmdPackage->copyBufferToTextureCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::COPY_BUFFER_TO_TEXTURE);
}
}
void GLES2CommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
// should not copy texture in a secondary command buffer
}
void GLES2CommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
// should not copy texture in a secondary command buffer
}
void GLES2CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
GLES2CmdBlitTexture *cmd = _cmdAllocator->blitTextureCmdPool.alloc();
if (srcTexture) cmd->gpuTextureSrc = static_cast<GLES2Texture *>(srcTexture)->gpuTexture();
if (dstTexture) cmd->gpuTextureDst = static_cast<GLES2Texture *>(dstTexture)->gpuTexture();
cmd->regions = regions;
cmd->count = count;
cmd->filter = filter;
++_numDrawCalls; // blit is also seen as draw call in GLES2
_curCmdPackage->blitTextureCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::BLIT_TEXTURE);
}
void GLES2CommandBuffer::execute(CommandBuffer *const *cmdBuffs, uint32_t count) {
CC_ABORT(); // Command 'execute' must be recorded in primary command buffers.
for (uint32_t i = 0; i < count; ++i) {
auto *cmdBuff = static_cast<GLES2CommandBuffer *>(cmdBuffs[i]);
GLES2CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
for (uint32_t j = 0; j < cmdPackage->beginRenderPassCmds.size(); ++j) {
GLES2CmdBeginRenderPass *cmd = cmdPackage->beginRenderPassCmds[j];
++cmd->refCount;
_curCmdPackage->beginRenderPassCmds.push(cmd);
}
for (uint32_t j = 0; j < cmdPackage->bindStatesCmds.size(); ++j) {
GLES2CmdBindStates *cmd = cmdPackage->bindStatesCmds[j];
++cmd->refCount;
_curCmdPackage->bindStatesCmds.push(cmd);
}
for (uint32_t j = 0; j < cmdPackage->drawCmds.size(); ++j) {
GLES2CmdDraw *cmd = cmdPackage->drawCmds[j];
++cmd->refCount;
_curCmdPackage->drawCmds.push(cmd);
}
for (uint32_t j = 0; j < cmdPackage->updateBufferCmds.size(); ++j) {
GLES2CmdUpdateBuffer *cmd = cmdPackage->updateBufferCmds[j];
++cmd->refCount;
_curCmdPackage->updateBufferCmds.push(cmd);
}
for (uint32_t j = 0; j < cmdPackage->copyBufferToTextureCmds.size(); ++j) {
GLES2CmdCopyBufferToTexture *cmd = cmdPackage->copyBufferToTextureCmds[j];
++cmd->refCount;
_curCmdPackage->copyBufferToTextureCmds.push(cmd);
}
for (uint32_t j = 0; j < cmdPackage->blitTextureCmds.size(); ++j) {
GLES2CmdBlitTexture *cmd = cmdPackage->blitTextureCmds[j];
++cmd->refCount;
_curCmdPackage->blitTextureCmds.push(cmd);
}
_curCmdPackage->cmds.concat(cmdPackage->cmds);
_numDrawCalls += cmdBuff->_numDrawCalls;
_numInstances += cmdBuff->_numInstances;
_numTriangles += cmdBuff->_numTriangles;
cmdBuff->_pendingPackages.pop();
cmdBuff->_freePackages.push(cmdPackage);
// current cmd allocator strategy will not work here: (but it doesn't matter anyways)
// allocators are designed to only free the cmds they allocated
// but here we are essentially <20><>transfering' the owner ship
// cmdBuff->_cmdAllocator->clearCmds(cmdPackage);
}
}
void GLES2CommandBuffer::bindStates() {
GLES2CmdBindStates *cmd = _cmdAllocator->bindStatesCmdPool.alloc();
cmd->gpuPipelineState = _curGPUPipelineState;
cmd->gpuInputAssembler = _curGPUInputAssember;
cmd->gpuDescriptorSets = _curGPUDescriptorSets;
if (_curGPUPipelineState) {
ccstd::vector<uint32_t> &dynamicOffsetOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsetOffsets;
cmd->dynamicOffsets.resize(_curGPUPipelineState->gpuPipelineLayout->dynamicOffsetCount);
for (size_t i = 0U; i < _curDynamicOffsets.size(); i++) {
size_t count = dynamicOffsetOffsets[i + 1] - dynamicOffsetOffsets[i];
// CC_ASSERT(_curDynamicOffsets[i].size() >= count);
count = std::min(count, _curDynamicOffsets[i].size());
if (count) memcpy(&cmd->dynamicOffsets[dynamicOffsetOffsets[i]], _curDynamicOffsets[i].data(), count * sizeof(uint32_t));
}
}
cmd->dynamicStates = _curDynamicStates;
_curCmdPackage->bindStatesCmds.push(cmd);
_curCmdPackage->cmds.push(GLESCmdType::BIND_STATES);
_isStateInvalid = false;
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,100 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "base/std/container/queue.h"
#include "gfx-base/GFXCommandBuffer.h"
namespace cc {
namespace gfx {
struct GLES2CmdPackage;
struct GLES2GPUPipelineState;
struct GLES2GPUDescriptorSet;
struct GLES2GPUInputAssembler;
class GLES2GPUCommandAllocator;
class CC_GLES2_API GLES2CommandBuffer : public CommandBuffer {
public:
GLES2CommandBuffer();
~GLES2CommandBuffer() override;
friend class GLES2Queue;
void begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *frameBuffer) override;
void end() override;
void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override;
void endRenderPass() override;
void insertMarker(const MarkerInfo &marker) override;
void beginMarker(const MarkerInfo &marker) override;
void endMarker() override;
void bindPipelineState(PipelineState *pso) override;
void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override;
void bindInputAssembler(InputAssembler *ia) override;
void setViewport(const Viewport &vp) override;
void setScissor(const Rect &rect) override;
void setLineWidth(float width) override;
void setDepthBias(float constant, float clamp, float slope) override;
void setBlendConstants(const Color &constants) override;
void setDepthBound(float minBounds, float maxBounds) override;
void setStencilWriteMask(StencilFace face, uint32_t mask) override;
void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override;
void nextSubpass() override;
void draw(const DrawInfo &info) override;
void updateBuffer(Buffer *buff, const void *data, uint32_t size) override;
void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override;
void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override;
void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override;
void dispatch(const DispatchInfo &info) override {}
void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override {}
void beginQuery(QueryPool *queryPool, uint32_t id) override {}
void endQuery(QueryPool *queryPool, uint32_t id) override {}
void resetQueryPool(QueryPool *queryPool) override {}
protected:
void doInit(const CommandBufferInfo &info) override;
void doDestroy() override;
virtual void bindStates();
GLES2GPUCommandAllocator *_cmdAllocator = nullptr;
GLES2CmdPackage *_curCmdPackage = nullptr;
ccstd::queue<GLES2CmdPackage *> _pendingPackages, _freePackages;
uint32_t _curSubpassIdx = 0U;
GLES2GPUPipelineState *_curGPUPipelineState = nullptr;
ccstd::vector<GLES2GPUDescriptorSet *> _curGPUDescriptorSets;
ccstd::vector<ccstd::vector<uint32_t>> _curDynamicOffsets;
GLES2GPUInputAssembler *_curGPUInputAssember = nullptr;
DynamicStates _curDynamicStates;
bool _isStateInvalid = false;
};
} // namespace gfx
} // namespace cc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,256 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2GPUObjects.h"
namespace cc {
namespace gfx {
class GLES2Device;
class GLES2CmdBeginRenderPass final : public GLESCmd {
public:
GLES2GPURenderPass *gpuRenderPass = nullptr;
GLES2GPUFramebuffer *gpuFBO = nullptr;
Rect renderArea;
Color clearColors[MAX_ATTACHMENTS];
float clearDepth = 1.0F;
uint32_t clearStencil = 0;
uint32_t subpassIdx = 0U;
GLES2CmdBeginRenderPass() : GLESCmd(GLESCmdType::BEGIN_RENDER_PASS) {}
void clear() override {
gpuFBO = nullptr;
gpuRenderPass = nullptr;
}
};
class GLES2CmdBindStates final : public GLESCmd {
public:
GLES2GPUPipelineState *gpuPipelineState = nullptr;
GLES2GPUInputAssembler *gpuInputAssembler = nullptr;
ccstd::vector<GLES2GPUDescriptorSet *> gpuDescriptorSets;
ccstd::vector<uint32_t> dynamicOffsets;
DynamicStates dynamicStates;
GLES2CmdBindStates() : GLESCmd(GLESCmdType::BIND_STATES) {}
void clear() override {
gpuPipelineState = nullptr;
gpuInputAssembler = nullptr;
gpuDescriptorSets.clear();
dynamicOffsets.clear();
}
};
class GLES2CmdDraw final : public GLESCmd {
public:
DrawInfo drawInfo;
GLES2CmdDraw() : GLESCmd(GLESCmdType::DRAW) {}
void clear() override {}
};
class GLES2CmdUpdateBuffer final : public GLESCmd {
public:
GLES2GPUBuffer *gpuBuffer = nullptr;
const uint8_t *buffer = nullptr;
uint32_t size = 0;
uint32_t offset = 0;
GLES2CmdUpdateBuffer() : GLESCmd(GLESCmdType::UPDATE_BUFFER) {}
void clear() override {
gpuBuffer = nullptr;
buffer = nullptr;
}
};
class GLES2CmdCopyBufferToTexture final : public GLESCmd {
public:
GLES2GPUTexture *gpuTexture = nullptr;
const BufferTextureCopy *regions = nullptr;
uint32_t count = 0U;
const uint8_t *const *buffers = nullptr;
GLES2CmdCopyBufferToTexture() : GLESCmd(GLESCmdType::COPY_BUFFER_TO_TEXTURE) {}
void clear() override {
gpuTexture = nullptr;
regions = nullptr;
count = 0U;
buffers = nullptr;
}
};
class GLES2CmdBlitTexture final : public GLESCmd {
public:
GLES2GPUTexture *gpuTextureSrc = nullptr;
GLES2GPUTexture *gpuTextureDst = nullptr;
const TextureBlit *regions = nullptr;
uint32_t count = 0U;
Filter filter = Filter::POINT;
GLES2CmdBlitTexture() : GLESCmd(GLESCmdType::BLIT_TEXTURE) {}
void clear() override {
gpuTextureSrc = nullptr;
gpuTextureDst = nullptr;
regions = nullptr;
count = 0U;
}
};
struct GLES2CmdPackage {
CachedArray<GLESCmdType> cmds;
CachedArray<GLES2CmdBeginRenderPass *> beginRenderPassCmds;
CachedArray<GLES2CmdBindStates *> bindStatesCmds;
CachedArray<GLES2CmdDraw *> drawCmds;
CachedArray<GLES2CmdUpdateBuffer *> updateBufferCmds;
CachedArray<GLES2CmdCopyBufferToTexture *> copyBufferToTextureCmds;
CachedArray<GLES2CmdBlitTexture *> blitTextureCmds;
};
class GLES2GPUCommandAllocator final {
public:
CommandPool<GLES2CmdBeginRenderPass> beginRenderPassCmdPool;
CommandPool<GLES2CmdBindStates> bindStatesCmdPool;
CommandPool<GLES2CmdDraw> drawCmdPool;
CommandPool<GLES2CmdUpdateBuffer> updateBufferCmdPool;
CommandPool<GLES2CmdCopyBufferToTexture> copyBufferToTextureCmdPool;
CommandPool<GLES2CmdBlitTexture> blitTextureCmdPool;
void clearCmds(GLES2CmdPackage *cmdPackage) {
if (cmdPackage->beginRenderPassCmds.size()) {
beginRenderPassCmdPool.freeCmds(cmdPackage->beginRenderPassCmds);
}
if (cmdPackage->bindStatesCmds.size()) {
bindStatesCmdPool.freeCmds(cmdPackage->bindStatesCmds);
}
if (cmdPackage->drawCmds.size()) {
drawCmdPool.freeCmds(cmdPackage->drawCmds);
}
if (cmdPackage->updateBufferCmds.size()) {
updateBufferCmdPool.freeCmds(cmdPackage->updateBufferCmds);
}
if (cmdPackage->copyBufferToTextureCmds.size()) {
copyBufferToTextureCmdPool.freeCmds(cmdPackage->copyBufferToTextureCmds);
}
if (cmdPackage->blitTextureCmds.size()) {
blitTextureCmdPool.freeCmds(cmdPackage->blitTextureCmds);
}
cmdPackage->cmds.clear();
}
inline void reset() {
beginRenderPassCmdPool.release();
bindStatesCmdPool.release();
drawCmdPool.release();
updateBufferCmdPool.release();
copyBufferToTextureCmdPool.release();
blitTextureCmdPool.release();
}
};
void cmdFuncGLES2CreateBuffer(GLES2Device *device, GLES2GPUBuffer *gpuBuffer);
void cmdFuncGLES2DestroyBuffer(GLES2Device *device, GLES2GPUBuffer *gpuBuffer);
void cmdFuncGLES2ResizeBuffer(GLES2Device *device, GLES2GPUBuffer *gpuBuffer);
void cmdFuncGLES2CreateTexture(GLES2Device *device, GLES2GPUTexture *gpuTexture);
void cmdFuncGLES2DestroyTexture(GLES2Device *device, GLES2GPUTexture *gpuTexture);
void cmdFuncGLES2ResizeTexture(GLES2Device *device, GLES2GPUTexture *gpuTexture);
void cmdFuncGLES2CreateSampler(GLES2Device *device, GLES2GPUSampler *gpuSampler);
void cmdFuncGLES2DestroySampler(GLES2Device *device, GLES2GPUSampler *gpuSampler);
void cmdFuncGLES2CreateShader(GLES2Device *device, GLES2GPUShader *gpuShader);
void cmdFuncGLES2DestroyShader(GLES2Device *device, GLES2GPUShader *gpuShader);
void cmdFuncGLES2CreateRenderPass(GLES2Device *device, GLES2GPURenderPass *gpuRenderPass);
void cmdFuncGLES2DestroyRenderPass(GLES2Device *device, GLES2GPURenderPass *gpuRenderPass);
void cmdFuncGLES2CreateInputAssembler(GLES2Device *device, GLES2GPUInputAssembler *gpuInputAssembler);
void cmdFuncGLES2DestroyInputAssembler(GLES2Device *device, GLES2GPUInputAssembler *gpuInputAssembler);
void cmdFuncGLES2CreateFramebuffer(GLES2Device *device, GLES2GPUFramebuffer *gpuFBO);
void cmdFuncGLES2DestroyFramebuffer(GLES2Device *device, GLES2GPUFramebuffer *gpuFBO);
void cmdFuncGLES2BeginRenderPass(GLES2Device *device, uint32_t subpassIdx,
GLES2GPURenderPass *gpuRenderPass = nullptr,
GLES2GPUFramebuffer *gpuFramebuffer = nullptr,
const Rect *renderArea = nullptr,
const Color *clearColors = nullptr,
float clearDepth = 1.F,
uint32_t clearStencil = 0);
void cmdFuncGLES2EndRenderPass(GLES2Device *device);
void cmdFuncGLES2BindState(GLES2Device *device,
GLES2GPUPipelineState *gpuPipelineState,
GLES2GPUInputAssembler *gpuInputAssembler,
const GLES2GPUDescriptorSet *const *gpuDescriptorSets,
const uint32_t *dynamicOffsets = nullptr,
const DynamicStates *dynamicStates = nullptr);
void cmdFuncGLES2Draw(GLES2Device *device, const DrawInfo &drawInfo);
void cmdFuncGLES2UpdateBuffer(GLES2Device *device,
GLES2GPUBuffer *gpuBuffer,
const void *buffer,
uint32_t offset,
uint32_t size);
void cmdFuncGLES2CopyBuffersToTexture(GLES2Device *device,
const uint8_t *const *buffers,
GLES2GPUTexture *gpuTexture,
const BufferTextureCopy *regions,
uint32_t count);
void cmdFuncGLES2CopyTextureToBuffers(GLES2Device *device,
GLES2GPUTexture *gpuTexture,
uint8_t *const *buffers,
const BufferTextureCopy *regions,
uint32_t count);
void cmdFuncGLES2CopyTexture(GLES2Device *device,
GLES2GPUTexture *gpuTextureSrc,
GLES2GPUTexture *gpuTextureDst,
const TextureCopy *regions,
uint32_t count);
void cmdFuncGLES2BlitTexture(GLES2Device *device,
GLES2GPUTexture *gpuTextureSrc,
GLES2GPUTexture *gpuTextureDst,
const TextureBlit *regions,
uint32_t count,
Filter filter);
void cmdFuncGLES2ExecuteCmds(GLES2Device *device, GLES2CmdPackage *cmdPackage);
void cmdFuncGLES2InsertMarker(GLES2Device *device, GLsizei length, const char *marker);
void cmdFuncGLES2PushGroupMarker(GLES2Device *device, GLsizei length, const char *marker);
void cmdFuncGLES2PopGroupMarker(GLES2Device *device);
GLint cmdFuncGLES2GetMaxSampleCount();
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,102 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSet.h"
#include "GLES2DescriptorSetLayout.h"
#include "GLES2Texture.h"
#include "states/GLES2Sampler.h"
namespace cc {
namespace gfx {
GLES2DescriptorSet::GLES2DescriptorSet() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2DescriptorSet::~GLES2DescriptorSet() {
destroy();
}
void GLES2DescriptorSet::doInit(const DescriptorSetInfo & /*info*/) {
const GLES2GPUDescriptorSetLayout *gpuDescriptorSetLayout = static_cast<const GLES2DescriptorSetLayout *>(_layout)->gpuDescriptorSetLayout();
const size_t descriptorCount = gpuDescriptorSetLayout->descriptorCount;
const size_t bindingCount = gpuDescriptorSetLayout->bindings.size();
_buffers.resize(descriptorCount);
_textures.resize(descriptorCount);
_samplers.resize(descriptorCount);
_gpuDescriptorSet = ccnew GLES2GPUDescriptorSet;
_gpuDescriptorSet->gpuDescriptors.resize(descriptorCount);
for (size_t i = 0U, k = 0U; i < bindingCount; i++) {
const DescriptorSetLayoutBinding &binding = gpuDescriptorSetLayout->bindings[i];
for (uint32_t j = 0; j < binding.count; j++, k++) {
_gpuDescriptorSet->gpuDescriptors[k].type = binding.descriptorType;
}
}
_gpuDescriptorSet->descriptorIndices = &gpuDescriptorSetLayout->descriptorIndices;
}
void GLES2DescriptorSet::doDestroy() {
CC_SAFE_DELETE(_gpuDescriptorSet);
}
void GLES2DescriptorSet::update() {
if (_isDirty && _gpuDescriptorSet) {
auto &descriptors = _gpuDescriptorSet->gpuDescriptors;
for (size_t i = 0; i < descriptors.size(); i++) {
if (hasAnyFlags(descriptors[i].type, DESCRIPTOR_BUFFER_TYPE)) {
auto *buffer = static_cast<GLES2Buffer *>(_buffers[i].ptr);
if (buffer) {
if (buffer->gpuBuffer()) {
descriptors[i].gpuBuffer = buffer->gpuBuffer();
} else if (buffer->gpuBufferView()) {
descriptors[i].gpuBufferView = buffer->gpuBufferView();
}
}
} else if (hasAnyFlags(descriptors[i].type, DESCRIPTOR_TEXTURE_TYPE)) {
if (_textures[i].ptr) {
descriptors[i].gpuTexture = static_cast<GLES2Texture *>(_textures[i].ptr)->gpuTexture();
}
if (_samplers[i].ptr) {
descriptors[i].gpuSampler = static_cast<GLES2Sampler *>(_samplers[i].ptr)->gpuSampler();
}
}
}
_isDirty = false;
}
}
void GLES2DescriptorSet::forceUpdate() {
_isDirty = true;
update();
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXDescriptorSet.h"
namespace cc {
namespace gfx {
struct GLES2GPUDescriptorSet;
class CC_GLES2_API GLES2DescriptorSet final : public DescriptorSet {
public:
GLES2DescriptorSet();
~GLES2DescriptorSet() override;
void update() override;
void forceUpdate() override;
inline GLES2GPUDescriptorSet *gpuDescriptorSet() const { return _gpuDescriptorSet; }
protected:
void doInit(const DescriptorSetInfo &info) override;
void doDestroy() override;
GLES2GPUDescriptorSet *_gpuDescriptorSet = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSetLayout.h"
namespace cc {
namespace gfx {
GLES2DescriptorSetLayout::GLES2DescriptorSetLayout() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2DescriptorSetLayout::~GLES2DescriptorSetLayout() {
destroy();
}
void GLES2DescriptorSetLayout::doInit(const DescriptorSetLayoutInfo & /*info*/) {
_gpuDescriptorSetLayout = ccnew GLES2GPUDescriptorSetLayout;
_gpuDescriptorSetLayout->descriptorCount = _descriptorCount;
_gpuDescriptorSetLayout->bindingIndices = _bindingIndices;
_gpuDescriptorSetLayout->descriptorIndices = _descriptorIndices;
_gpuDescriptorSetLayout->bindings = _bindings;
for (auto &binding : _bindings) {
if (hasAnyFlags(binding.descriptorType, DESCRIPTOR_DYNAMIC_TYPE)) {
for (uint32_t j = 0U; j < binding.count; j++) {
_gpuDescriptorSetLayout->dynamicBindings.push_back(binding.binding);
}
}
}
}
void GLES2DescriptorSetLayout::doDestroy() {
CC_SAFE_DELETE(_gpuDescriptorSetLayout);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXDescriptorSetLayout.h"
namespace cc {
namespace gfx {
struct GLES2GPUDescriptorSetLayout;
class CC_GLES2_API GLES2DescriptorSetLayout final : public DescriptorSetLayout {
public:
GLES2DescriptorSetLayout();
~GLES2DescriptorSetLayout() override;
inline GLES2GPUDescriptorSetLayout *gpuDescriptorSetLayout() const { return _gpuDescriptorSetLayout; }
protected:
void doInit(const DescriptorSetLayoutInfo &info) override;
void doDestroy() override;
GLES2GPUDescriptorSetLayout *_gpuDescriptorSetLayout = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,550 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2CommandBuffer.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSet.h"
#include "GLES2DescriptorSetLayout.h"
#include "GLES2Device.h"
#include "GLES2Framebuffer.h"
#include "GLES2GPUObjects.h"
#include "GLES2InputAssembler.h"
#include "GLES2PipelineLayout.h"
#include "GLES2PipelineState.h"
#include "GLES2PrimaryCommandBuffer.h"
#include "GLES2QueryPool.h"
#include "GLES2Queue.h"
#include "GLES2RenderPass.h"
#include "GLES2Shader.h"
#include "GLES2Swapchain.h"
#include "GLES2Texture.h"
#include "base/memory/Memory.h"
#include "profiler/Profiler.h"
#include "states/GLES2Sampler.h"
// when capturing GLES commands (RENDERDOC_HOOK_EGL=1, default value)
// renderdoc doesn't support this extension during replay
#define ALLOW_MULTISAMPLED_RENDER_TO_TEXTURE_ON_DESKTOP 0
namespace cc {
namespace gfx {
GLES2Device *GLES2Device::instance = nullptr;
GLES2Device *GLES2Device::getInstance() {
return GLES2Device::instance;
}
GLES2Device::GLES2Device() {
_api = API::GLES2;
_deviceName = "GLES2";
GLES2Device::instance = this;
}
GLES2Device::~GLES2Device() {
GLES2Device::instance = nullptr;
}
bool GLES2Device::doInit(const DeviceInfo & /*info*/) {
_gpuContext = ccnew GLES2GPUContext;
_gpuStateCache = ccnew GLES2GPUStateCache;
_gpuBlitManager = ccnew GLES2GPUBlitManager;
_gpuFramebufferHub = ccnew GLES2GPUFramebufferHub;
_gpuConstantRegistry = ccnew GLES2GPUConstantRegistry;
_gpuFramebufferCacheMap = ccnew GLES2GPUFramebufferCacheMap(_gpuStateCache);
if (!_gpuContext->initialize(_gpuStateCache, _gpuConstantRegistry)) {
destroy();
return false;
};
_bindingMappings.blockOffsets.resize(_bindingMappingInfo.setIndices.size());
_bindingMappings.samplerTextureOffsets.resize(_bindingMappingInfo.setIndices.size());
for (size_t i = 0; i < _bindingMappingInfo.setIndices.size(); ++i) {
uint32_t curSet{_bindingMappingInfo.setIndices[i]};
uint32_t prevSet{i ? _bindingMappingInfo.setIndices[i - 1] : curSet};
// accumulate the per set offset according to the specified capacity
_bindingMappings.blockOffsets[curSet] = i ? static_cast<int32_t>(_bindingMappingInfo.maxBlockCounts[prevSet]) + _bindingMappings.blockOffsets[prevSet] : 0;
_bindingMappings.samplerTextureOffsets[curSet] = i ? static_cast<int32_t>(_bindingMappingInfo.maxSamplerTextureCounts[prevSet]) + _bindingMappings.samplerTextureOffsets[prevSet] : 0;
}
for (uint32_t curSet : _bindingMappingInfo.setIndices) {
// textures always come after UBOs
_bindingMappings.samplerTextureOffsets[curSet] -= static_cast<int32_t>(_bindingMappingInfo.maxBlockCounts[curSet]);
}
_bindingMappings.flexibleSet = _bindingMappingInfo.setIndices.back();
ccstd::string extStr = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
_extensions = StringUtil::split(extStr, " ");
_multithreadedCommandRecording = false;
initFormatFeature();
if (checkExtension("element_index_uint")) {
_features[toNumber(Feature::ELEMENT_INDEX_UINT)] = true;
}
if (checkExtension("draw_buffers")) {
_features[toNumber(Feature::MULTIPLE_RENDER_TARGETS)] = true;
glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, reinterpret_cast<GLint *>(&_caps.maxColorRenderTargets));
}
if (checkExtension("blend_minmax")) {
_features[toNumber(Feature::BLEND_MINMAX)] = true;
}
_gpuConstantRegistry->useVAO = checkExtension("vertex_array_object");
_gpuConstantRegistry->useDrawInstanced = checkExtension("draw_instanced");
_gpuConstantRegistry->useInstancedArrays = checkExtension("instanced_arrays");
_gpuConstantRegistry->useDiscardFramebuffer = checkExtension("discard_framebuffer");
_features[toNumber(Feature::INSTANCED_ARRAYS)] = _gpuConstantRegistry->useInstancedArrays;
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = false;
ccstd::string fbfLevelStr = "NONE";
// PVRVFrame has issues on their support
#ifndef ENABLE_GLES2_SUBPASS
_features[toNumber(Feature::INPUT_ATTACHMENT_BENEFIT)] = false;
_features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = false;
_features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = false;
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = false;
#elif CC_PLATFORM != CC_PLATFORM_WINDOWS
if (checkExtension("framebuffer_fetch")) {
ccstd::string nonCoherent = "framebuffer_fetch_non";
auto it = std::find_if(_extensions.begin(), _extensions.end(), [&nonCoherent](auto &ext) {
return ext.find(nonCoherent) != ccstd::string::npos;
});
if (it != _extensions.end()) {
if (*it == CC_TOSTR(GL_EXT_shader_framebuffer_fetch_non_coherent)) {
_gpuConstantRegistry->mFBF = FBFSupportLevel::NON_COHERENT_EXT;
fbfLevelStr = "NON_COHERENT_EXT";
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true;
} else if (*it == CC_TOSTR(GL_QCOM_shader_framebuffer_fetch_noncoherent)) {
_gpuConstantRegistry->mFBF = FBFSupportLevel::NON_COHERENT_QCOM;
fbfLevelStr = "NON_COHERENT_QCOM";
GL_CHECK(glEnable(GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM));
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true;
}
} else if (checkExtension(CC_TOSTR(GL_EXT_shader_framebuffer_fetch))) {
// we only care about EXT_shader_framebuffer_fetch, the ARM version does not support MRT
_gpuConstantRegistry->mFBF = FBFSupportLevel::COHERENT;
fbfLevelStr = "COHERENT";
}
_features[toNumber(Feature::INPUT_ATTACHMENT_BENEFIT)] = _gpuConstantRegistry->mFBF != FBFSupportLevel::NONE;
_features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = true;
}
if (checkExtension(CC_TOSTR(ARM_shader_framebuffer_fetch_depth_stencil))) {
_features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = true;
fbfLevelStr += "_DEPTH_STENCIL";
}
#endif
#if CC_PLATFORM != CC_PLATFORM_WINDOWS || ALLOW_MULTISAMPLED_RENDER_TO_TEXTURE_ON_DESKTOP
if (checkExtension("multisampled_render_to_texture")) {
if (checkExtension("multisampled_render_to_texture2")) {
_gpuConstantRegistry->mMSRT = MSRTSupportLevel::LEVEL2;
} else {
_gpuConstantRegistry->mMSRT = MSRTSupportLevel::LEVEL1;
}
}
#endif
_features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = false; // not implement yet.
if (checkExtension(CC_TOSTR(GL_EXT_debug_marker))) {
_gpuConstantRegistry->debugMarker = true;
}
ccstd::string compressedFmts;
if (getFormatFeatures(Format::ETC_RGB8) != FormatFeature::NONE) {
compressedFmts += "etc1 ";
}
if (getFormatFeatures(Format::PVRTC_RGB2) != FormatFeature::NONE) {
compressedFmts += "pvrtc ";
}
if (getFormatFeatures(Format::ASTC_RGBA_4X4) != FormatFeature::NONE) {
compressedFmts += "astc ";
}
_renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
_vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
_version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, reinterpret_cast<GLint *>(&_caps.maxVertexAttributes));
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, reinterpret_cast<GLint *>(&_caps.maxVertexUniformVectors));
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, reinterpret_cast<GLint *>(&_caps.maxFragmentUniformVectors));
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, reinterpret_cast<GLint *>(&_caps.maxTextureUnits));
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, reinterpret_cast<GLint *>(&_caps.maxVertexTextureUnits));
glGetIntegerv(GL_MAX_TEXTURE_SIZE, reinterpret_cast<GLint *>(&_caps.maxTextureSize));
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, reinterpret_cast<GLint *>(&_caps.maxCubeMapTextureSize));
_caps.uboOffsetAlignment = 16;
if (checkExtension("GL_OES_texture_3D")) {
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, reinterpret_cast<GLint *>(&_caps.max3DTextureSize));
// texture2DArray fallback to texture3DOES
_caps.maxArrayTextureLayers = _caps.max3DTextureSize;
} else {
_caps.max3DTextureSize = 0;
_caps.maxArrayTextureLayers = 0;
}
QueueInfo queueInfo;
queueInfo.type = QueueType::GRAPHICS;
_queue = createQueue(queueInfo);
QueryPoolInfo queryPoolInfo{QueryType::OCCLUSION, DEFAULT_MAX_QUERY_OBJECTS, true};
_queryPool = createQueryPool(queryPoolInfo);
CommandBufferInfo cmdBuffInfo;
cmdBuffInfo.type = CommandBufferType::PRIMARY;
cmdBuffInfo.queue = _queue;
_cmdBuff = createCommandBuffer(cmdBuffInfo);
_gpuStateCache->initialize(_caps.maxTextureUnits, _caps.maxVertexAttributes);
_gpuBlitManager->initialize();
CC_LOG_INFO("GLES2 device initialized.");
CC_LOG_INFO("RENDERER: %s", _renderer.c_str());
CC_LOG_INFO("VENDOR: %s", _vendor.c_str());
CC_LOG_INFO("VERSION: %s", _version.c_str());
CC_LOG_INFO("COMPRESSED_FORMATS: %s", compressedFmts.c_str());
CC_LOG_INFO("USE_VAO: %s", _gpuConstantRegistry->useVAO ? "true" : "false");
CC_LOG_INFO("FRAMEBUFFER_FETCH: %s", fbfLevelStr.c_str());
return true;
}
void GLES2Device::doDestroy() {
_gpuBlitManager->destroy();
CC_SAFE_DELETE(_stagingBuffer);
CC_SAFE_DELETE(_gpuFramebufferCacheMap)
CC_SAFE_DELETE(_gpuConstantRegistry)
CC_SAFE_DELETE(_gpuFramebufferHub)
CC_SAFE_DELETE(_gpuBlitManager)
CC_SAFE_DELETE(_gpuStateCache)
CC_ASSERT(!_memoryStatus.bufferSize); // Buffer memory leaked.
CC_ASSERT(!_memoryStatus.textureSize); // Texture memory leaked.
CC_SAFE_DESTROY_AND_DELETE(_cmdBuff)
CC_SAFE_DESTROY_AND_DELETE(_queryPool)
CC_SAFE_DESTROY_AND_DELETE(_queue)
CC_SAFE_DESTROY_AND_DELETE(_gpuContext)
}
void GLES2Device::acquire(Swapchain *const *swapchains, uint32_t count) {
_gpuContext->makeCurrent();
if (_onAcquire) _onAcquire->execute();
_swapchains.clear();
for (uint32_t i = 0; i < count; ++i) {
_swapchains.push_back(static_cast<GLES2Swapchain *>(swapchains[i])->gpuSwapchain());
}
}
void GLES2Device::present() {
CC_PROFILE(GLES2DevicePresent);
auto *queue = static_cast<GLES2Queue *>(_queue);
_numDrawCalls = queue->_numDrawCalls;
_numInstances = queue->_numInstances;
_numTriangles = queue->_numTriangles;
for (auto *swapchain : _swapchains) {
_gpuContext->present(swapchain);
}
// Clear queue stats
queue->_numDrawCalls = 0;
queue->_numInstances = 0;
queue->_numTriangles = 0;
}
void GLES2Device::bindContext(bool bound) {
_gpuContext->bindContext(bound);
}
void GLES2Device::initFormatFeature() {
_textureExclusive.fill(true);
const FormatFeature completeFeature = FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE | FormatFeature::LINEAR_FILTER;
// builtin formatFeatures
_formatFeatures[toNumber(Format::RGB8)] = completeFeature;
_formatFeatures[toNumber(Format::R5G6B5)] = completeFeature;
_textureExclusive[toNumber(Format::R5G6B5)] = false;
_formatFeatures[toNumber(Format::RGBA8)] = completeFeature;
_formatFeatures[toNumber(Format::RGBA4)] = completeFeature;
_textureExclusive[toNumber(Format::RGBA4)] = false;
_formatFeatures[toNumber(Format::RGB5A1)] = completeFeature;
_textureExclusive[toNumber(Format::RGB5A1)] = false;
_formatFeatures[toNumber(Format::R8)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG8)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB8)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA8)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::R8I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG8I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB8I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA8I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::R8UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG8UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB8UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA8UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::R16I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG16I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB16I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA16I)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::R16UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG16UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB16UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA16UI)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::R32F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG32F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB32F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA32F)] |= FormatFeature::VERTEX_ATTRIBUTE;
if (checkExtension("OES_vertex_half_float")) {
_formatFeatures[toNumber(Format::R16F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RG16F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGB16F)] |= FormatFeature::VERTEX_ATTRIBUTE;
_formatFeatures[toNumber(Format::RGBA16F)] |= FormatFeature::VERTEX_ATTRIBUTE;
}
_formatFeatures[toNumber(Format::DEPTH)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::DEPTH)] = false;
_formatFeatures[toNumber(Format::DEPTH_STENCIL)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::DEPTH_STENCIL)] = false;
if (checkExtension("EXT_sRGB")) {
_formatFeatures[toNumber(Format::SRGB8)] |= completeFeature;
_formatFeatures[toNumber(Format::SRGB8_A8)] |= completeFeature;
_textureExclusive[toNumber(Format::SRGB8_A8)] = false;
}
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R8)] |= completeFeature;
_formatFeatures[toNumber(Format::RG8)] |= completeFeature;
}
if (checkExtension("texture_float")) {
_formatFeatures[toNumber(Format::RGB32F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
_formatFeatures[toNumber(Format::RGBA32F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R32F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
_formatFeatures[toNumber(Format::RG32F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
}
}
if (checkExtension("texture_half_float")) {
_formatFeatures[toNumber(Format::RGB16F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
_formatFeatures[toNumber(Format::RGBA16F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R16F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
_formatFeatures[toNumber(Format::RG16F)] |= FormatFeature::RENDER_TARGET | FormatFeature::SAMPLED_TEXTURE;
}
}
if (checkExtension("color_buffer_half_float")) {
_formatFeatures[toNumber(Format::RGB16F)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::RGB16F)] = false;
_formatFeatures[toNumber(Format::RGBA16F)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::RGBA16F)] = false;
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R16F)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::R16F)] = false;
_formatFeatures[toNumber(Format::RG16F)] |= FormatFeature::RENDER_TARGET;
_textureExclusive[toNumber(Format::RG16F)] = false;
}
}
if (checkExtension("texture_float_linear")) {
_formatFeatures[toNumber(Format::RGB32F)] |= FormatFeature::LINEAR_FILTER;
_formatFeatures[toNumber(Format::RGBA32F)] |= FormatFeature::LINEAR_FILTER;
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R32F)] |= FormatFeature::LINEAR_FILTER;
_formatFeatures[toNumber(Format::RG32F)] |= FormatFeature::LINEAR_FILTER;
}
}
if (checkExtension("OES_texture_half_float_linear")) {
_formatFeatures[toNumber(Format::RGB16F)] |= FormatFeature::LINEAR_FILTER;
_formatFeatures[toNumber(Format::RGBA16F)] |= FormatFeature::LINEAR_FILTER;
if (checkExtension("texture_rg")) {
_formatFeatures[toNumber(Format::R16F)] |= FormatFeature::LINEAR_FILTER;
_formatFeatures[toNumber(Format::RG16F)] |= FormatFeature::LINEAR_FILTER;
}
}
if (checkExtension("depth_texture")) {
_formatFeatures[toNumber(Format::DEPTH)] |= completeFeature;
}
if (checkExtension("packed_depth_stencil")) {
_formatFeatures[toNumber(Format::DEPTH_STENCIL)] |= completeFeature;
}
// compressed texture feature
const FormatFeature compressedFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::LINEAR_FILTER;
if (checkExtension("compressed_ETC1")) {
_formatFeatures[toNumber(Format::ETC_RGB8)] |= compressedFeature;
}
if (checkExtension("texture_compression_pvrtc")) {
_formatFeatures[toNumber(Format::PVRTC_RGB2)] |= compressedFeature;
_formatFeatures[toNumber(Format::PVRTC_RGBA2)] |= compressedFeature;
_formatFeatures[toNumber(Format::PVRTC_RGB4)] |= compressedFeature;
_formatFeatures[toNumber(Format::PVRTC_RGBA4)] |= compressedFeature;
}
if (checkExtension("texture_compression_astc")) {
_formatFeatures[toNumber(Format::ASTC_RGBA_4X4)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_5X4)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_5X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_6X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_6X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_8X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_8X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_8X8)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_10X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_10X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_10X8)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_10X10)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_12X10)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_RGBA_12X12)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_4X4)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_5X4)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_5X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_6X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_6X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_8X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_8X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_8X8)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_10X5)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_10X6)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_10X8)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_10X10)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_12X10)] |= compressedFeature;
_formatFeatures[toNumber(Format::ASTC_SRGBA_12X12)] |= compressedFeature;
}
}
CommandBuffer *GLES2Device::createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) {
if (hasAgent || info.type == CommandBufferType::PRIMARY) return ccnew GLES2PrimaryCommandBuffer;
return ccnew GLES2CommandBuffer;
}
Queue *GLES2Device::createQueue() {
return ccnew GLES2Queue;
}
QueryPool *GLES2Device::createQueryPool() {
return ccnew GLES2QueryPool;
}
Swapchain *GLES2Device::createSwapchain() {
return ccnew GLES2Swapchain;
}
Buffer *GLES2Device::createBuffer() {
return ccnew GLES2Buffer;
}
Texture *GLES2Device::createTexture() {
return ccnew GLES2Texture;
}
Shader *GLES2Device::createShader() {
return ccnew GLES2Shader;
}
InputAssembler *GLES2Device::createInputAssembler() {
return ccnew GLES2InputAssembler;
}
RenderPass *GLES2Device::createRenderPass() {
return ccnew GLES2RenderPass;
}
Framebuffer *GLES2Device::createFramebuffer() {
return ccnew GLES2Framebuffer;
}
DescriptorSet *GLES2Device::createDescriptorSet() {
return ccnew GLES2DescriptorSet;
}
DescriptorSetLayout *GLES2Device::createDescriptorSetLayout() {
return ccnew GLES2DescriptorSetLayout;
}
PipelineLayout *GLES2Device::createPipelineLayout() {
return ccnew GLES2PipelineLayout;
}
PipelineState *GLES2Device::createPipelineState() {
return ccnew GLES2PipelineState;
}
Sampler *GLES2Device::createSampler(const SamplerInfo &info) {
return ccnew GLES2Sampler(info);
}
void GLES2Device::copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) {
CC_PROFILE(GLES2DeviceCopyBuffersToTexture);
cmdFuncGLES2CopyBuffersToTexture(this, buffers, static_cast<GLES2Texture *>(dst)->gpuTexture(), regions, count);
}
void GLES2Device::copyTextureToBuffers(Texture *src, uint8_t *const *buffers, const BufferTextureCopy *region, uint32_t count) {
CC_PROFILE(GLES2DeviceCopyTextureToBuffers);
cmdFuncGLES2CopyTextureToBuffers(this, static_cast<GLES2Texture *>(src)->gpuTexture(), buffers, region, count);
}
SampleCount GLES2Device::getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const {
std::ignore = format;
std::ignore = usage;
std::ignore = flags;
return static_cast<SampleCount>(cmdFuncGLES2GetMaxSampleCount());
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,153 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXDevice.h"
#include "gfx-base/GFXSwapchain.h"
#include "gfx-gles-common/GLESCommandPool.h"
namespace cc {
namespace gfx {
class GLES2GPUContext;
struct GLES2GPUSwapchain;
class GLES2GPUStateCache;
class GLES2GPUBlitManager;
class GLES2GPUFramebufferHub;
struct GLES2GPUConstantRegistry;
class GLES2GPUFramebufferCacheMap;
class CC_GLES2_API GLES2Device final : public Device {
public:
static GLES2Device *getInstance();
~GLES2Device() override;
using Device::copyBuffersToTexture;
using Device::createBuffer;
using Device::createCommandBuffer;
using Device::createDescriptorSet;
using Device::createDescriptorSetLayout;
using Device::createFramebuffer;
using Device::createGeneralBarrier;
using Device::createInputAssembler;
using Device::createPipelineLayout;
using Device::createPipelineState;
using Device::createQueryPool;
using Device::createQueue;
using Device::createRenderPass;
using Device::createSampler;
using Device::createShader;
using Device::createTexture;
using Device::createTextureBarrier;
void frameSync() override{};
void acquire(Swapchain *const *swapchains, uint32_t count) override;
void present() override;
inline const GLESBindingMapping &bindingMappings() const { return _bindingMappings; }
inline GLES2GPUContext *context() const { return _gpuContext; }
inline GLES2GPUStateCache *stateCache() const { return _gpuStateCache; }
inline GLES2GPUBlitManager *blitManager() const { return _gpuBlitManager; }
inline GLES2GPUFramebufferHub *framebufferHub() const { return _gpuFramebufferHub; }
inline GLES2GPUConstantRegistry *constantRegistry() const { return _gpuConstantRegistry; }
inline GLES2GPUFramebufferCacheMap *framebufferCacheMap() const { return _gpuFramebufferCacheMap; }
inline bool checkExtension(const ccstd::string &extension) const {
return std::any_of(_extensions.begin(), _extensions.end(), [&extension](auto &ext) {
return ext.find(extension) != ccstd::string::npos;
});
}
inline uint8_t *getStagingBuffer(uint32_t size = 0) {
if (size > _stagingBufferSize) {
CC_FREE(_stagingBuffer);
_stagingBuffer = static_cast<uint8_t *>(CC_MALLOC(size));
_stagingBufferSize = size;
}
return _stagingBuffer;
}
// check the specified format is texture-exclusive (no renderbuffers allowed)
inline bool isTextureExclusive(const Format &format) { return _textureExclusive[static_cast<size_t>(format)]; };
SampleCount getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const override;
protected:
static GLES2Device *instance;
friend class DeviceManager;
GLES2Device();
bool doInit(const DeviceInfo &info) override;
void doDestroy() override;
CommandBuffer *createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) override;
Queue *createQueue() override;
QueryPool *createQueryPool() override;
Swapchain *createSwapchain() override;
Buffer *createBuffer() override;
Texture *createTexture() override;
Shader *createShader() override;
InputAssembler *createInputAssembler() override;
RenderPass *createRenderPass() override;
Framebuffer *createFramebuffer() override;
DescriptorSet *createDescriptorSet() override;
DescriptorSetLayout *createDescriptorSetLayout() override;
PipelineLayout *createPipelineLayout() override;
PipelineState *createPipelineState() override;
Sampler *createSampler(const SamplerInfo &info) override;
void copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) override;
void copyTextureToBuffers(Texture *src, uint8_t *const *buffers, const BufferTextureCopy *region, uint32_t count) override;
void getQueryPoolResults(QueryPool *queryPool) override {}
void bindContext(bool bound) override;
void initFormatFeature();
GLES2GPUContext *_gpuContext{nullptr};
GLES2GPUStateCache *_gpuStateCache{nullptr};
GLES2GPUBlitManager *_gpuBlitManager{nullptr};
GLES2GPUFramebufferHub *_gpuFramebufferHub{nullptr};
GLES2GPUConstantRegistry *_gpuConstantRegistry{nullptr};
GLES2GPUFramebufferCacheMap *_gpuFramebufferCacheMap{nullptr};
ccstd::vector<GLES2GPUSwapchain *> _swapchains;
ccstd::array<bool, static_cast<size_t>(Format::COUNT)> _textureExclusive;
GLESBindingMapping _bindingMappings;
ccstd::vector<ccstd::string> _extensions;
uint8_t *_stagingBuffer{nullptr};
uint32_t _stagingBufferSize{0};
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,85 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2Framebuffer.h"
#include "GLES2RenderPass.h"
#include "GLES2Texture.h"
namespace cc {
namespace gfx {
GLES2Framebuffer::GLES2Framebuffer() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Framebuffer::~GLES2Framebuffer() {
destroy();
}
void GLES2Framebuffer::doInit(const FramebufferInfo & /*info*/) {
_gpuFBO = ccnew GLES2GPUFramebuffer;
_gpuFBO->gpuRenderPass = static_cast<GLES2RenderPass *>(_renderPass)->gpuRenderPass();
_gpuFBO->gpuColorTextures.resize(_colorTextures.size());
for (size_t i = 0; i < _colorTextures.size(); ++i) {
auto *colorTexture = static_cast<GLES2Texture *>(_colorTextures.at(i));
_gpuFBO->gpuColorTextures[i] = colorTexture->gpuTexture();
_gpuFBO->lodLevel = colorTexture->getViewInfo().baseLevel;
GLES2Device::getInstance()->framebufferHub()->connect(colorTexture->gpuTexture(), _gpuFBO);
}
if (_depthStencilTexture) {
auto *depthTexture = static_cast<GLES2Texture *>(_depthStencilTexture);
_gpuFBO->gpuDepthStencilTexture = depthTexture->gpuTexture();
_gpuFBO->lodLevel = depthTexture->getViewInfo().baseLevel;
GLES2Device::getInstance()->framebufferHub()->connect(depthTexture->gpuTexture(), _gpuFBO);
}
cmdFuncGLES2CreateFramebuffer(GLES2Device::getInstance(), _gpuFBO);
}
void GLES2Framebuffer::doDestroy() {
if (_gpuFBO) {
cmdFuncGLES2DestroyFramebuffer(GLES2Device::getInstance(), _gpuFBO);
for (auto &texture : _colorTextures) {
auto *colorTexture = static_cast<GLES2Texture *>(texture);
GLES2Device::getInstance()->framebufferHub()->disengage(colorTexture->gpuTexture(), _gpuFBO);
}
if (_depthStencilTexture) {
auto *depthTexture = static_cast<GLES2Texture *>(_depthStencilTexture);
GLES2Device::getInstance()->framebufferHub()->disengage(depthTexture->gpuTexture(), _gpuFBO);
}
delete _gpuFBO;
_gpuFBO = nullptr;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXFramebuffer.h"
namespace cc {
namespace gfx {
class GLES2GPUFramebuffer;
class CC_GLES2_API GLES2Framebuffer final : public Framebuffer {
public:
GLES2Framebuffer();
~GLES2Framebuffer() override;
inline GLES2GPUFramebuffer *gpuFBO() const { return _gpuFBO; }
protected:
void doInit(const FramebufferInfo &info) override;
void doDestroy() override;
GLES2GPUFramebuffer *_gpuFBO = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,424 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <thread>
#include "GLES2GPUObjects.h"
#include "base/StringUtil.h"
#if CC_SWAPPY_ENABLED
#include "swappy/swappyGL.h"
#endif
#define FORCE_DISABLE_VALIDATION 1
namespace cc {
namespace gfx {
#if CC_DEBUG > 0 && !FORCE_DISABLE_VALIDATION
constexpr uint32_t DISABLE_VALIDATION_ASSERTIONS = 1; // 0 for default behavior, otherwise assertions will be disabled
void GL_APIENTRY GLES2EGLDebugProc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
String sourceDesc;
switch (source) {
case GL_DEBUG_SOURCE_API_KHR: sourceDesc = "API"; break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_KHR: sourceDesc = "SHADER_COMPILER"; break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR: sourceDesc = "WINDOW_SYSTEM"; break;
case GL_DEBUG_SOURCE_THIRD_PARTY_KHR: sourceDesc = "THIRD_PARTY"; break;
case GL_DEBUG_SOURCE_APPLICATION_KHR: sourceDesc = "APPLICATION"; break;
default: sourceDesc = "OTHER";
}
String typeDesc;
switch (type) {
case GL_DEBUG_TYPE_ERROR_KHR: typeDesc = "ERROR"; break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR: typeDesc = "PEPRECATED_BEHAVIOR"; break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR: typeDesc = "UNDEFINED_BEHAVIOR"; break;
case GL_DEBUG_TYPE_PERFORMANCE_KHR: typeDesc = "PERFORMANCE"; break;
case GL_DEBUG_TYPE_PORTABILITY_KHR: typeDesc = "PORTABILITY"; break;
case GL_DEBUG_TYPE_MARKER_KHR: typeDesc = "MARKER"; break;
case GL_DEBUG_TYPE_PUSH_GROUP_KHR: typeDesc = "PUSH_GROUP"; break;
case GL_DEBUG_TYPE_POP_GROUP_KHR: typeDesc = "POP_GROUP"; break;
default: typeDesc = "OTHER";
}
String severityDesc;
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH_KHR: severityDesc = "HIGH"; break;
case GL_DEBUG_SEVERITY_MEDIUM_KHR: severityDesc = "MEDIUM"; break;
case GL_DEBUG_SEVERITY_LOW_KHR: severityDesc = "LOW"; break;
default: severityDesc = "NOTIFICATION";
}
String msg = StringUtil::format("source: %s, type: %s, severity: %s, message: %s",
sourceDesc.c_str(), typeDesc.c_str(), severityDesc.c_str(), message);
if (severity == GL_DEBUG_SEVERITY_HIGH_KHR) {
CC_LOG_ERROR(msg.c_str());
CC_ASSERT(DISABLE_VALIDATION_ASSERTIONS);
} else if (severity == GL_DEBUG_SEVERITY_MEDIUM_KHR) {
CC_LOG_WARNING(msg.c_str());
} else {
CC_LOG_DEBUG(msg.c_str());
}
}
#endif
bool GLES2GPUContext::initialize(GLES2GPUStateCache *stateCache, GLES2GPUConstantRegistry *constantRegistry) {
_stateCache = stateCache;
_constantRegistry = constantRegistry;
if (!gles2wInit()) {
return false;
}
EGL_CHECK(eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY));
if (eglDisplay == EGL_NO_DISPLAY) {
CC_LOG_ERROR("eglGetDisplay() - FAILED.");
return false;
}
EGLBoolean success{false};
EGL_CHECK(success = eglInitialize(eglDisplay, &eglMajorVersion, &eglMinorVersion));
if (!success) {
CC_LOG_ERROR("eglInitialize() - FAILED.");
return false;
}
EGL_CHECK(eglBindAPI(EGL_OPENGL_ES_API));
bool msaaEnabled{false};
bool qualityPreferred{false};
EGLint redSize{8};
EGLint greenSize{8};
EGLint blueSize{8};
EGLint alphaSize{8};
EGLint depthSize{24};
EGLint stencilSize{8};
EGLint sampleBufferSize{msaaEnabled ? EGL_DONT_CARE : 0};
EGLint sampleSize{msaaEnabled ? EGL_DONT_CARE : 0};
EGLint defaultAttribs[]{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_BLUE_SIZE, blueSize,
EGL_GREEN_SIZE, greenSize,
EGL_RED_SIZE, redSize,
EGL_ALPHA_SIZE, alphaSize,
EGL_DEPTH_SIZE, depthSize,
EGL_STENCIL_SIZE, stencilSize,
EGL_SAMPLE_BUFFERS, sampleBufferSize,
EGL_SAMPLES, sampleSize,
EGL_NONE};
int numConfig{0};
ccstd::vector<EGLConfig> eglConfigs;
EGL_CHECK(success = eglChooseConfig(eglDisplay, defaultAttribs, nullptr, 0, &numConfig));
if (success) {
eglConfigs.resize(numConfig);
} else {
CC_LOG_ERROR("Query GLES2 configuration failed.");
return false;
}
int count = numConfig;
EGL_CHECK(success = eglChooseConfig(eglDisplay, defaultAttribs, eglConfigs.data(), count, &numConfig));
if (!success || !numConfig) {
CC_LOG_ERROR("eglChooseConfig configuration failed.");
return false;
}
EGLint depth{0};
EGLint stencil{0};
EGLint sampleBuffers{0};
EGLint sampleCount{0};
EGLint params[8]{0};
uint64_t lastScore = qualityPreferred ? std::numeric_limits<uint64_t>::min() : std::numeric_limits<uint64_t>::max();
for (int i = 0; i < numConfig; i++) {
int depthValue{0};
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_RED_SIZE, &params[0]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_GREEN_SIZE, &params[1]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_BLUE_SIZE, &params[2]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_ALPHA_SIZE, &params[3]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_DEPTH_SIZE, &params[4]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_STENCIL_SIZE, &params[5]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_SAMPLE_BUFFERS, &params[6]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_SAMPLES, &params[7]);
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_DEPTH_ENCODING_NV, &depthValue);
int bNonLinearDepth = (depthValue == EGL_DEPTH_ENCODING_NONLINEAR_NV) ? 1 : 0;
/*------------------------------------------ANGLE's priority-----------------------------------------------*/
// Favor EGLConfigLists by RGB, then Depth, then Non-linear Depth, then Stencil, then Alpha
uint64_t currScore{0};
EGLint colorScore = std::abs(params[0] - redSize) + std::abs(params[1] - greenSize) + std::abs(params[2] - blueSize);
currScore |= static_cast<uint64_t>(std::min(std::max(params[6], 0), 15)) << 29;
currScore |= static_cast<uint64_t>(std::min(std::max(params[7], 0), 31)) << 24;
currScore |= static_cast<uint64_t>(std::min(colorScore, 127)) << 17;
currScore |= static_cast<uint64_t>(std::min(std::abs(params[4] - depthSize), 63)) << 11;
currScore |= static_cast<uint64_t>(std::min(std::abs(1 - bNonLinearDepth), 1)) << 10;
currScore |= static_cast<uint64_t>(std::min(std::abs(params[5] - stencilSize), 31)) << 6;
currScore |= static_cast<uint64_t>(std::min(std::abs(params[3] - alphaSize), 31)) << 0;
/*------------------------------------------ANGLE's priority-----------------------------------------------*/
// if msaaEnabled, sampleBuffers and sampleCount should be greater than 0, until iterate to the last one(can't find).
bool msaaLimit = (msaaEnabled ? (params[6] > 0 && params[7] > 0) : (params[6] == 0 && params[7] == 0));
// performancePreferred ? [>=] : [<] , egl configurations store in "ascending order"
bool filter = (currScore < lastScore) ^ qualityPreferred;
if ((filter && msaaLimit) || (!eglConfig && i == numConfig - 1)) {
eglConfig = eglConfigs[i];
depth = params[4];
stencil = params[5];
sampleBuffers = params[6];
sampleCount = params[7];
lastScore = currScore;
}
}
CC_LOG_INFO("Setup EGLConfig: depth [%d] stencil [%d] sampleBuffer [%d] sampleCount [%d]", depth, stencil, sampleBuffers, sampleCount);
EGL_CHECK(_extensions = StringUtil::split(eglQueryString(eglDisplay, EGL_EXTENSIONS), " "));
bool hasKHRCreateCtx = checkExtension(CC_TOSTR(EGL_KHR_create_context));
if (hasKHRCreateCtx) {
eglAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
eglAttributes.push_back(2);
eglAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
eglAttributes.push_back(0);
#if CC_DEBUG > 0 && !FORCE_DISABLE_VALIDATION
eglAttributes.push_back(EGL_CONTEXT_FLAGS_KHR);
eglAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR);
#endif
eglAttributes.push_back(EGL_NONE);
EGL_CHECK(eglDefaultContext = eglCreateContext(eglDisplay, eglConfig, nullptr, eglAttributes.data()));
} else {
eglAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
eglAttributes.push_back(2);
eglAttributes.push_back(EGL_NONE);
EGL_CHECK(eglDefaultContext = eglCreateContext(eglDisplay, eglConfig, nullptr, eglAttributes.data()));
}
if (!eglDefaultContext) {
CC_LOG_ERROR("Create EGL context failed.");
return false;
}
EGLint pbufferAttribs[]{
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE};
EGL_CHECK(eglDefaultSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs));
size_t threadID{std::hash<std::thread::id>{}(std::this_thread::get_id())};
_sharedContexts[threadID] = eglDefaultContext;
bindContext(true);
return true;
}
void GLES2GPUContext::destroy() {
if (eglDisplay) {
makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
if (eglDefaultSurface) {
EGL_CHECK(eglDestroySurface(eglDisplay, eglDefaultSurface));
eglDefaultSurface = EGL_NO_SURFACE;
}
for (auto pair : _sharedContexts) {
if (pair.second != eglDefaultContext) {
EGL_CHECK(eglDestroyContext(eglDisplay, pair.second));
}
}
_sharedContexts.clear();
if (eglDefaultContext) {
EGL_CHECK(eglDestroyContext(eglDisplay, eglDefaultContext));
eglDefaultContext = EGL_NO_SURFACE;
}
if (eglDisplay) {
EGL_CHECK(eglTerminate(eglDisplay));
eglDisplay = EGL_NO_DISPLAY;
}
gles2wExit();
}
void GLES2GPUContext::bindContext(bool bound) {
if (bound) {
makeCurrent(eglDefaultSurface, eglDefaultSurface, eglDefaultContext);
resetStates();
} else {
makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT, false);
_eglCurrentDrawSurface = EGL_NO_SURFACE;
_eglCurrentReadSurface = EGL_NO_SURFACE;
}
}
void GLES2GPUContext::makeCurrent(const GLES2GPUSwapchain *drawSwapchain, const GLES2GPUSwapchain *readSwapchain) {
EGLSurface drawSurface = drawSwapchain ? drawSwapchain->eglSurface : _eglCurrentDrawSurface;
EGLSurface readSurface = readSwapchain ? readSwapchain->eglSurface : _eglCurrentReadSurface;
EGLContext prevContext = eglGetCurrentContext();
if (_eglCurrentDrawSurface == drawSurface && _eglCurrentReadSurface == readSurface && _eglCurrentContext == prevContext) {
return;
}
makeCurrent(drawSurface, readSurface, _eglCurrentContext);
if (prevContext != _eglCurrentContext) {
resetStates();
}
}
void GLES2GPUContext::present(const GLES2GPUSwapchain *swapchain) {
#if CC_SWAPPY_ENABLED
if (swapchain->swappyEnabled) {
//fallback to normal eglswap if swappy_swap failed
if (SwappyGL_swap(eglDisplay, swapchain->eglSurface)) {
return;
}
}
#endif
if (_eglCurrentInterval != swapchain->eglSwapInterval) {
if (!eglSwapInterval(eglDisplay, swapchain->eglSwapInterval)) {
CC_LOG_ERROR("eglSwapInterval() - FAILED.");
}
_eglCurrentInterval = swapchain->eglSwapInterval;
}
EGL_CHECK(eglSwapBuffers(eglDisplay, swapchain->eglSurface));
}
EGLContext GLES2GPUContext::getSharedContext() {
size_t threadID{std::hash<std::thread::id>{}(std::this_thread::get_id())};
if (_sharedContexts.count(threadID)) return _sharedContexts[threadID];
EGLContext context = EGL_NO_CONTEXT;
EGL_CHECK(context = eglCreateContext(eglDisplay, eglConfig, eglDefaultContext, eglAttributes.data()));
if (!context) {
CC_LOG_ERROR("Create shared context failed.");
return EGL_NO_CONTEXT;
}
_sharedContexts[threadID] = context;
return context;
}
bool GLES2GPUContext::makeCurrent(EGLSurface drawSurface, EGLSurface readSurface, EGLContext context, bool updateCache) {
bool succeeded;
EGL_CHECK(succeeded = eglMakeCurrent(eglDisplay, drawSurface, readSurface, context));
if (succeeded && updateCache) {
_eglCurrentDrawSurface = drawSurface;
_eglCurrentReadSurface = readSurface;
_eglCurrentContext = context;
}
return succeeded;
}
void GLES2GPUContext::resetStates() const {
GL_CHECK(glPixelStorei(GL_PACK_ALIGNMENT, 1));
GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
GL_CHECK(glActiveTexture(GL_TEXTURE0));
//////////////////////////////////////////////////////////////////////////
GL_CHECK(glEnable(GL_SCISSOR_TEST));
GL_CHECK(glEnable(GL_CULL_FACE));
GL_CHECK(glCullFace(GL_BACK));
GL_CHECK(glFrontFace(GL_CCW));
GL_CHECK(glDisable(GL_SAMPLE_COVERAGE));
//////////////////////////////////////////////////////////////////////////
GL_CHECK(glEnable(GL_DEPTH_TEST));
GL_CHECK(glDepthMask(GL_TRUE));
GL_CHECK(glDepthFunc(GL_LESS));
GL_CHECK(glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 1, 0xffffffff));
GL_CHECK(glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP));
GL_CHECK(glStencilMaskSeparate(GL_FRONT, 0xffffffff));
GL_CHECK(glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 1, 0xffffffff));
GL_CHECK(glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP));
GL_CHECK(glStencilMaskSeparate(GL_BACK, 0xffffffff));
GL_CHECK(glDisable(GL_STENCIL_TEST));
//////////////////////////////////////////////////////////////////////////
GL_CHECK(glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE));
GL_CHECK(glDisable(GL_BLEND));
GL_CHECK(glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD));
GL_CHECK(glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO));
GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
GL_CHECK(glBlendColor(0.0F, 0.0F, 0.0F, 0.0F));
GL_CHECK(glUseProgram(0));
if (_constantRegistry->useVAO) {
GL_CHECK(glBindVertexArrayOES(0));
}
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
#if CC_DEBUG > 0 && !FORCE_DISABLE_VALIDATION
GL_CHECK(glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR));
if (glDebugMessageControlKHR) {
GL_CHECK(glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE));
}
if (glDebugMessageCallbackKHR) {
GL_CHECK(glDebugMessageCallbackKHR(GLES2EGLDebugProc, NULL));
}
#endif
if (_constantRegistry->mFBF == FBFSupportLevel::NON_COHERENT_QCOM) {
GL_CHECK(glEnable(GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM));
}
_stateCache->reset();
_constantRegistry->currentBoundThreadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
CC_LOG_DEBUG("EGL context bounded to thread %llx", _constantRegistry->currentBoundThreadID);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,597 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <algorithm>
#include "GLES2Std.h"
#include "GLES2Wrangler.h"
#include "base/std/container/unordered_map.h"
#include "gfx-base/GFXDef.h"
#include "gfx-gles-common/GLESCommandPool.h"
namespace cc {
namespace gfx {
struct GLES2GPUConstantRegistry {
size_t currentBoundThreadID{0U};
MSRTSupportLevel mMSRT{MSRTSupportLevel::NONE};
FBFSupportLevel mFBF{FBFSupportLevel::NONE};
bool useVAO = false;
bool useDrawInstanced = false;
bool useInstancedArrays = false;
bool useDiscardFramebuffer = false;
bool debugMarker = false;
};
class GLES2GPUStateCache;
struct GLES2GPUSwapchain;
class GLES2GPUContext final {
public:
bool initialize(GLES2GPUStateCache *stateCache, GLES2GPUConstantRegistry *constantRegistry);
void destroy();
EGLint eglMajorVersion{0};
EGLint eglMinorVersion{0};
EGLDisplay eglDisplay{EGL_NO_DISPLAY};
EGLConfig eglConfig{nullptr};
ccstd::vector<EGLint> eglAttributes;
EGLSurface eglDefaultSurface{EGL_NO_SURFACE};
EGLContext eglDefaultContext{EGL_NO_CONTEXT};
// pass nullptr to keep the current surface
void makeCurrent(const GLES2GPUSwapchain *drawSwapchain = nullptr, const GLES2GPUSwapchain *readSwapchain = nullptr);
void bindContext(bool bound); // for context switching between threads
void present(const GLES2GPUSwapchain *swapchain);
inline bool checkExtension(const ccstd::string &extension) const {
return std::find(_extensions.begin(), _extensions.end(), extension) != _extensions.end();
}
private:
bool makeCurrent(EGLSurface drawSurface, EGLSurface readSurface, EGLContext context, bool updateCache = true);
EGLContext getSharedContext();
void resetStates() const;
// state caches
EGLSurface _eglCurrentDrawSurface{EGL_NO_SURFACE};
EGLSurface _eglCurrentReadSurface{EGL_NO_SURFACE};
EGLContext _eglCurrentContext{EGL_NO_CONTEXT};
EGLint _eglCurrentInterval{0};
GLES2GPUStateCache *_stateCache{nullptr};
GLES2GPUConstantRegistry *_constantRegistry{nullptr};
ccstd::unordered_map<size_t, EGLContext> _sharedContexts;
ccstd::vector<ccstd::string> _extensions;
};
struct GLES2GPUBuffer {
BufferUsage usage = BufferUsage::NONE;
MemoryUsage memUsage = MemoryUsage::NONE;
uint32_t size = 0;
uint32_t stride = 0;
uint32_t count = 0;
GLenum glTarget = 0;
GLuint glBuffer = 0;
uint8_t *buffer = nullptr;
DrawInfoList indirects;
};
using GLES2GPUBufferList = ccstd::vector<GLES2GPUBuffer *>;
struct GLES2GPUBufferView {
GLES2GPUBuffer *gpuBuffer = nullptr;
uint32_t offset = 0U;
uint32_t range = 0U;
};
struct GLES2GPUTexture {
TextureType type{TextureType::TEX2D};
Format format{Format::UNKNOWN};
TextureUsage usage{TextureUsageBit::NONE};
uint32_t width{0};
uint32_t height{0};
uint32_t depth{1};
uint32_t size{0};
uint32_t arrayLayer{1};
uint32_t mipLevel{1};
SampleCount samples{SampleCount::X1};
TextureFlags flags{TextureFlagBit::NONE};
bool isPowerOf2{false};
bool memoryAllocated{true}; // false if swapchain image or implicit ms render buffer.
GLenum glTarget{0};
GLenum glInternalFmt{0};
GLenum glFormat{0};
GLenum glType{0};
GLenum glUsage{0};
GLint glSamples{0};
GLuint glTexture{0};
GLuint glRenderbuffer{0};
GLenum glWrapS{0};
GLenum glWrapT{0};
GLenum glMinFilter{0};
GLenum glMagFilter{0};
GLES2GPUSwapchain *swapchain{nullptr};
};
using GLES2GPUTextureList = ccstd::vector<GLES2GPUTexture *>;
struct GLES2GPUSwapchain {
#if CC_SWAPPY_ENABLED
bool swappyEnabled{false};
#endif
EGLSurface eglSurface{EGL_NO_SURFACE};
EGLint eglSwapInterval{0};
GLuint glFramebuffer{0};
GLES2GPUTexture *gpuColorTexture{nullptr};
};
struct GLES2GPUSampler {
Filter minFilter = Filter::NONE;
Filter magFilter = Filter::NONE;
Filter mipFilter = Filter::NONE;
Address addressU = Address::CLAMP;
Address addressV = Address::CLAMP;
Address addressW = Address::CLAMP;
GLenum glMinFilter = 0;
GLenum glMagFilter = 0;
GLenum glWrapS = 0;
GLenum glWrapT = 0;
GLenum glWrapR = 0;
};
struct GLES2GPUInput {
uint32_t binding = 0;
ccstd::string name;
Type type = Type::UNKNOWN;
uint32_t stride = 0;
uint32_t count = 0;
uint32_t size = 0;
GLenum glType = 0;
GLint glLoc = -1;
};
using GLES2GPUInputList = ccstd::vector<GLES2GPUInput>;
struct GLES2GPUUniform {
uint32_t binding = INVALID_BINDING;
ccstd::string name;
Type type = Type::UNKNOWN;
uint32_t stride = 0;
uint32_t count = 0;
uint32_t size = 0;
uint32_t offset = 0;
GLenum glType = 0;
GLint glLoc = -1;
ccstd::vector<uint8_t> buff;
};
using GLES2GPUUniformList = ccstd::vector<GLES2GPUUniform>;
struct GLES2GPUUniformBlock {
uint32_t set = 0;
uint32_t binding = 0;
uint32_t idx = 0;
ccstd::string name;
uint32_t size = 0;
GLES2GPUUniformList glUniforms;
GLES2GPUUniformList glActiveUniforms;
ccstd::vector<uint32_t> activeUniformIndices;
};
using GLES2GPUUniformBlockList = ccstd::vector<GLES2GPUUniformBlock>;
struct GLES2GPUUniformSamplerTexture {
uint32_t set = 0;
uint32_t binding = 0;
ccstd::string name;
Type type = Type::UNKNOWN;
uint32_t count = 0U;
ccstd::vector<GLint> units;
GLenum glType = 0;
GLint glLoc = -1;
};
using GLES2GPUUniformSamplerTextureList = ccstd::vector<GLES2GPUUniformSamplerTexture>;
struct GLES2GPUShaderStage {
ShaderStageFlagBit type = ShaderStageFlagBit::NONE;
ccstd::string source;
GLuint glShader = 0;
};
using GLES2GPUShaderStageList = ccstd::vector<GLES2GPUShaderStage>;
struct GLES2GPUShader {
ccstd::string name;
UniformBlockList blocks;
UniformSamplerTextureList samplerTextures;
UniformInputAttachmentList subpassInputs;
GLuint glProgram = 0;
GLES2GPUShaderStageList gpuStages;
GLES2GPUInputList glInputs;
GLES2GPUUniformBlockList glBlocks;
GLES2GPUUniformSamplerTextureList glSamplerTextures;
};
struct GLES2GPUAttribute {
ccstd::string name;
GLuint glBuffer = 0;
GLenum glType = 0;
uint32_t size = 0;
uint32_t count = 0;
uint32_t stride = 1;
uint32_t componentCount = 1;
bool isNormalized = false;
bool isInstanced = false;
uint32_t offset = 0;
};
using GLES2GPUAttributeList = ccstd::vector<GLES2GPUAttribute>;
struct GLES2GPUInputAssembler {
AttributeList attributes;
GLES2GPUBufferList gpuVertexBuffers;
GLES2GPUBuffer *gpuIndexBuffer = nullptr;
GLES2GPUBuffer *gpuIndirectBuffer = nullptr;
GLES2GPUAttributeList glAttribs;
GLenum glIndexType = 0;
ccstd::unordered_map<size_t, GLuint> glVAOs;
};
struct GLES2GPURenderPass {
struct AttachmentStatistics {
uint32_t loadSubpass{SUBPASS_EXTERNAL};
uint32_t storeSubpass{SUBPASS_EXTERNAL};
};
ColorAttachmentList colorAttachments;
DepthStencilAttachment depthStencilAttachment;
SubpassInfoList subpasses;
ccstd::vector<AttachmentStatistics> statistics; // per attachment
};
class GLES2GPUFramebufferCacheMap;
class GLES2GPUFramebuffer final {
public:
GLES2GPURenderPass *gpuRenderPass{nullptr};
GLES2GPUTextureList gpuColorTextures;
GLES2GPUTexture *gpuDepthStencilTexture{nullptr};
bool usesFBF{false};
uint32_t lodLevel{0};
struct GLFramebufferInfo {
GLuint glFramebuffer{0U};
uint32_t width{UINT_MAX};
uint32_t height{UINT_MAX};
};
struct GLFramebuffer {
inline void initialize(GLES2GPUSwapchain *sc) { swapchain = sc; }
inline void initialize(const GLFramebufferInfo &info) {
_glFramebuffer = info.glFramebuffer;
_width = info.width;
_height = info.height;
}
inline GLuint getFramebuffer() const { return swapchain ? swapchain->glFramebuffer : _glFramebuffer; }
inline uint32_t getWidth() const { return swapchain ? swapchain->gpuColorTexture->width : _width; }
inline uint32_t getHeight() const { return swapchain ? swapchain->gpuColorTexture->height : _height; }
void destroy(GLES2GPUStateCache *cache, GLES2GPUFramebufferCacheMap *framebufferCacheMap);
GLES2GPUSwapchain *swapchain{nullptr};
private:
GLuint _glFramebuffer{0U};
uint32_t _width{0U};
uint32_t _height{0U};
};
struct Framebuffer {
GLFramebuffer framebuffer;
// for blit-based manual resolving
GLbitfield resolveMask{0U};
GLFramebuffer resolveFramebuffer;
};
// one per subpass, if not using FBF
ccstd::vector<Framebuffer> instances;
ccstd::vector<uint32_t> uberColorAttachmentIndices;
uint32_t uberDepthStencil{INVALID_BINDING};
Framebuffer uberInstance;
// the assumed shader output, may differ from actual subpass output
// see Feature::INPUT_ATTACHMENT_BENEFIT for more
uint32_t uberOnChipOutput{INVALID_BINDING};
uint32_t uberFinalOutput{INVALID_BINDING};
};
struct GLES2GPUDescriptorSetLayout {
DescriptorSetLayoutBindingList bindings;
ccstd::vector<uint32_t> dynamicBindings;
ccstd::vector<uint32_t> bindingIndices;
ccstd::vector<uint32_t> descriptorIndices;
uint32_t descriptorCount = 0U;
};
using GLES2GPUDescriptorSetLayoutList = ccstd::vector<GLES2GPUDescriptorSetLayout *>;
struct GLES2GPUPipelineLayout {
GLES2GPUDescriptorSetLayoutList setLayouts;
// helper storages
ccstd::vector<ccstd::vector<int>> dynamicOffsetIndices;
ccstd::vector<uint32_t> dynamicOffsetOffsets;
ccstd::vector<uint32_t> dynamicOffsets;
uint32_t dynamicOffsetCount = 0U;
};
struct GLES2GPUPipelineState {
GLenum glPrimitive = GL_TRIANGLES;
GLES2GPUShader *gpuShader = nullptr;
RasterizerState rs;
DepthStencilState dss;
BlendState bs;
DynamicStateList dynamicStates;
GLES2GPUPipelineLayout *gpuLayout = nullptr;
GLES2GPURenderPass *gpuRenderPass = nullptr;
GLES2GPUPipelineLayout *gpuPipelineLayout = nullptr;
};
struct GLES2GPUDescriptor {
DescriptorType type = DescriptorType::UNKNOWN;
GLES2GPUBuffer *gpuBuffer = nullptr;
GLES2GPUBufferView *gpuBufferView = nullptr;
GLES2GPUTexture *gpuTexture = nullptr;
GLES2GPUSampler *gpuSampler = nullptr;
};
using GLES2GPUDescriptorList = ccstd::vector<GLES2GPUDescriptor>;
struct GLES2GPUDescriptorSet {
GLES2GPUDescriptorList gpuDescriptors;
const ccstd::vector<uint32_t> *descriptorIndices = nullptr;
};
class GLES2GPUFence final {
public:
};
struct GLES2ObjectCache {
uint32_t subpassIdx = 0U;
GLES2GPURenderPass *gpuRenderPass = nullptr;
GLES2GPUFramebuffer *gpuFramebuffer = nullptr;
GLES2GPUPipelineState *gpuPipelineState = nullptr;
GLES2GPUInputAssembler *gpuInputAssembler = nullptr;
GLenum glPrimitive = 0;
Rect renderArea;
ColorList clearColors;
float clearDepth = 1.F;
uint32_t clearStencil = 0U;
};
class GLES2GPUStateCache {
public:
GLuint glArrayBuffer = 0;
GLuint glElementArrayBuffer = 0;
GLuint glUniformBuffer = 0;
GLuint glVAO = 0;
uint32_t texUint = 0;
ccstd::vector<GLuint> glTextures;
GLuint glProgram = 0;
ccstd::vector<bool> glEnabledAttribLocs;
ccstd::vector<bool> glCurrentAttribLocs;
GLuint glFramebuffer = 0;
GLuint glRenderbuffer = 0;
GLuint glReadFBO = 0;
Viewport viewport;
Rect scissor;
RasterizerState rs;
DepthStencilState dss;
BlendState bs;
bool isCullFaceEnabled = true;
bool isStencilTestEnabled = false;
ccstd::unordered_map<ccstd::string, uint32_t> texUnitCacheMap;
GLES2ObjectCache gfxStateCache;
void initialize(size_t texUnits, size_t vertexAttributes) {
glTextures.resize(texUnits, 0U);
glEnabledAttribLocs.resize(vertexAttributes, false);
glCurrentAttribLocs.resize(vertexAttributes, false);
}
void reset() {
glArrayBuffer = 0;
glElementArrayBuffer = 0;
glUniformBuffer = 0;
glVAO = 0;
texUint = 0;
glTextures.assign(glTextures.size(), 0U);
glProgram = 0;
glEnabledAttribLocs.assign(glEnabledAttribLocs.size(), false);
glCurrentAttribLocs.assign(glCurrentAttribLocs.size(), false);
glFramebuffer = 0;
glReadFBO = 0;
isCullFaceEnabled = true;
isStencilTestEnabled = false;
viewport = Viewport();
scissor = Rect();
rs = RasterizerState();
dss = DepthStencilState();
bs = BlendState();
gfxStateCache.gpuRenderPass = nullptr;
gfxStateCache.gpuFramebuffer = nullptr;
gfxStateCache.gpuPipelineState = nullptr;
gfxStateCache.gpuInputAssembler = nullptr;
gfxStateCache.glPrimitive = 0U;
gfxStateCache.subpassIdx = 0U;
}
};
class GLES2GPUBlitManager final {
public:
void initialize();
void destroy();
void draw(GLES2GPUTexture *gpuTextureSrc, GLES2GPUTexture *gpuTextureDst, const TextureBlit *regions, uint32_t count, Filter filter);
private:
GLES2GPUShader _gpuShader;
GLES2GPUDescriptorSetLayout _gpuDescriptorSetLayout;
GLES2GPUPipelineLayout _gpuPipelineLayout;
GLES2GPUPipelineState _gpuPipelineState;
GLES2GPUBuffer _gpuVertexBuffer;
GLES2GPUInputAssembler _gpuInputAssembler;
GLES2GPUSampler _gpuPointSampler;
GLES2GPUSampler _gpuLinearSampler;
GLES2GPUBuffer _gpuUniformBuffer;
GLES2GPUDescriptorSet _gpuDescriptorSet;
DrawInfo _drawInfo;
float _uniformBuffer[8];
};
class GLES2GPUFramebufferCacheMap final {
public:
explicit GLES2GPUFramebufferCacheMap(GLES2GPUStateCache *cache) : _cache(cache) {}
void registerExternal(GLuint glFramebuffer, const GLES2GPUTexture *gpuTexture) {
bool isTexture = gpuTexture->glTexture;
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
if (!cacheMap[glResource].glFramebuffer) {
cacheMap[glResource] = {glFramebuffer, true};
}
}
void unregisterExternal(GLuint glFramebuffer) {
for (auto &fbos : _textureMap) {
if (fbos.second.glFramebuffer == glFramebuffer) {
fbos.second.glFramebuffer = 0;
return;
}
}
for (auto &fbos : _renderbufferMap) {
if (fbos.second.glFramebuffer == glFramebuffer) {
fbos.second.glFramebuffer = 0;
return;
}
}
}
GLuint getFramebufferFromTexture(const GLES2GPUTexture *gpuTexture) {
bool isTexture = gpuTexture->glTexture;
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
if (!cacheMap.count(glResource)) {
GLuint glFramebuffer = 0U;
GL_CHECK(glGenFramebuffers(1, &glFramebuffer));
if (_cache->glFramebuffer != glFramebuffer) {
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, glFramebuffer));
_cache->glFramebuffer = glFramebuffer;
}
const FormatInfo &info = GFX_FORMAT_INFOS[static_cast<uint32_t>(gpuTexture->format)];
if (isTexture) {
if (info.hasDepth) {
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, gpuTexture->glTarget, glResource, 0));
if (info.hasStencil) GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, gpuTexture->glTarget, glResource, 0));
} else {
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gpuTexture->glTarget, glResource, 0));
}
} else {
if (info.hasDepth) {
GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, gpuTexture->glTarget, glResource));
if (info.hasStencil) GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, gpuTexture->glTarget, glResource));
} else {
GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gpuTexture->glTarget, glResource));
}
}
GLenum status;
GL_CHECK(status = glCheckFramebufferStatus(GL_FRAMEBUFFER));
CC_ASSERT_EQ(status, GL_FRAMEBUFFER_COMPLETE);
cacheMap[glResource].glFramebuffer = glFramebuffer;
}
return cacheMap[glResource].glFramebuffer;
}
void onTextureDestroy(const GLES2GPUTexture *gpuTexture) {
bool isTexture = gpuTexture->glTexture;
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
if (cacheMap.count(glResource)) {
GLuint glFramebuffer = cacheMap[glResource].glFramebuffer;
if (!glFramebuffer) return;
if (_cache->glFramebuffer == glFramebuffer) {
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
_cache->glFramebuffer = 0;
}
GL_CHECK(glDeleteFramebuffers(1, &glFramebuffer));
cacheMap.erase(glResource);
}
}
private:
GLES2GPUStateCache *_cache = nullptr;
struct FramebufferRecord {
GLuint glFramebuffer{0};
bool isExternal{false};
};
using CacheMap = ccstd::unordered_map<GLuint, FramebufferRecord>;
CacheMap _renderbufferMap; // renderbuffer -> framebuffer
CacheMap _textureMap; // texture -> framebuffer
};
class GLES2GPUFramebufferHub final {
public:
void connect(GLES2GPUTexture *texture, GLES2GPUFramebuffer *framebuffer) {
_framebuffers[texture].push_back(framebuffer);
}
void disengage(GLES2GPUTexture *texture) {
_framebuffers.erase(texture);
}
void disengage(GLES2GPUTexture *texture, GLES2GPUFramebuffer *framebuffer) {
auto &pool = _framebuffers[texture];
pool.erase(std::remove(pool.begin(), pool.end(), framebuffer), pool.end());
}
void update(GLES2GPUTexture *texture);
private:
ccstd::unordered_map<GLES2GPUTexture *, ccstd::vector<GLES2GPUFramebuffer *>> _framebuffers;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,71 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2InputAssembler.h"
namespace cc {
namespace gfx {
GLES2InputAssembler::GLES2InputAssembler() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2InputAssembler::~GLES2InputAssembler() {
destroy();
}
void GLES2InputAssembler::doInit(const InputAssemblerInfo &info) {
_gpuInputAssembler = ccnew GLES2GPUInputAssembler;
_gpuInputAssembler->attributes = _attributes;
_gpuInputAssembler->gpuVertexBuffers.resize(_vertexBuffers.size());
for (size_t i = 0; i < _gpuInputAssembler->gpuVertexBuffers.size(); ++i) {
auto *vb = static_cast<GLES2Buffer *>(_vertexBuffers[i]);
_gpuInputAssembler->gpuVertexBuffers[i] = vb->gpuBuffer();
}
if (info.indexBuffer) {
_gpuInputAssembler->gpuIndexBuffer = static_cast<GLES2Buffer *>(info.indexBuffer)->gpuBuffer();
}
if (info.indirectBuffer) {
_gpuInputAssembler->gpuIndirectBuffer = static_cast<GLES2Buffer *>(info.indirectBuffer)->gpuBuffer();
}
cmdFuncGLES2CreateInputAssembler(GLES2Device::getInstance(), _gpuInputAssembler);
}
void GLES2InputAssembler::doDestroy() {
if (_gpuInputAssembler) {
cmdFuncGLES2DestroyInputAssembler(GLES2Device::getInstance(), _gpuInputAssembler);
delete _gpuInputAssembler;
_gpuInputAssembler = nullptr;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,51 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXInputAssembler.h"
namespace cc {
namespace gfx {
struct GLES2GPUInputAssembler;
class GLES2CmdDraw;
class CC_GLES2_API GLES2InputAssembler final : public InputAssembler {
public:
GLES2InputAssembler();
~GLES2InputAssembler() override;
inline GLES2GPUInputAssembler *gpuInputAssembler() const { return _gpuInputAssembler; }
protected:
void doInit(const InputAssemblerInfo &info) override;
void doDestroy() override;
GLES2GPUInputAssembler *_gpuInputAssembler = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,74 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "base/Utils.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSetLayout.h"
#include "GLES2PipelineLayout.h"
namespace cc {
namespace gfx {
GLES2PipelineLayout::GLES2PipelineLayout() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2PipelineLayout::~GLES2PipelineLayout() {
destroy();
}
void GLES2PipelineLayout::doInit(const PipelineLayoutInfo & /*info*/) {
_gpuPipelineLayout = ccnew GLES2GPUPipelineLayout;
uint32_t offset = 0U;
_gpuPipelineLayout->dynamicOffsetIndices.resize(_setLayouts.size());
for (uint32_t i = 0U; i < _setLayouts.size(); i++) {
DescriptorSetLayout *setLayout = _setLayouts[i];
GLES2GPUDescriptorSetLayout *gpuSetLayout = static_cast<GLES2DescriptorSetLayout *>(setLayout)->gpuDescriptorSetLayout();
uint32_t dynamicCount = utils::toUint(gpuSetLayout->dynamicBindings.size());
ccstd::vector<int> &indices = _gpuPipelineLayout->dynamicOffsetIndices[i];
indices.assign(setLayout->getBindingIndices().size(), -1);
for (uint32_t j = 0U; j < dynamicCount; j++) {
uint32_t binding = gpuSetLayout->dynamicBindings[j];
if (indices[binding] < 0) indices[binding] = offset + j;
}
_gpuPipelineLayout->dynamicOffsetOffsets.push_back(offset);
_gpuPipelineLayout->setLayouts.push_back(gpuSetLayout);
offset += dynamicCount;
}
_gpuPipelineLayout->dynamicOffsetOffsets.push_back(offset);
_gpuPipelineLayout->dynamicOffsetCount = offset;
_gpuPipelineLayout->dynamicOffsets.resize(offset);
}
void GLES2PipelineLayout::doDestroy() {
CC_SAFE_DELETE(_gpuPipelineLayout);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXPipelineLayout.h"
namespace cc {
namespace gfx {
struct GLES2GPUPipelineLayout;
class CC_GLES2_API GLES2PipelineLayout final : public PipelineLayout {
public:
GLES2PipelineLayout();
~GLES2PipelineLayout() override;
inline GLES2GPUPipelineLayout *gpuPipelineLayout() const { return _gpuPipelineLayout; }
protected:
void doInit(const PipelineLayoutInfo &info) override;
void doDestroy() override;
GLES2GPUPipelineLayout *_gpuPipelineLayout = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,83 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2PipelineLayout.h"
#include "GLES2PipelineState.h"
#include "GLES2RenderPass.h"
#include "GLES2Shader.h"
namespace cc {
namespace gfx {
const GLenum GLE_S2_PRIMITIVES[] = {
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_LINE_LOOP,
GL_NONE,
GL_NONE,
GL_NONE,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_NONE,
GL_NONE,
GL_NONE,
GL_NONE,
};
GLES2PipelineState::GLES2PipelineState() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2PipelineState::~GLES2PipelineState() {
destroy();
}
void GLES2PipelineState::doInit(const PipelineStateInfo & /*info*/) {
_gpuPipelineState = ccnew GLES2GPUPipelineState;
_gpuPipelineState->glPrimitive = GLE_S2_PRIMITIVES[static_cast<int>(_primitive)];
_gpuPipelineState->gpuShader = static_cast<GLES2Shader *>(_shader)->gpuShader();
_gpuPipelineState->rs = _rasterizerState;
_gpuPipelineState->dss = _depthStencilState;
_gpuPipelineState->bs = _blendState;
_gpuPipelineState->gpuPipelineLayout = static_cast<GLES2PipelineLayout *>(_pipelineLayout)->gpuPipelineLayout();
if (_renderPass) _gpuPipelineState->gpuRenderPass = static_cast<GLES2RenderPass *>(_renderPass)->gpuRenderPass();
for (uint32_t i = 0; i < 31; i++) {
if (static_cast<uint32_t>(_dynamicStates) & (1 << i)) {
_gpuPipelineState->dynamicStates.push_back(static_cast<DynamicStateFlagBit>(1 << i));
}
}
}
void GLES2PipelineState::doDestroy() {
CC_SAFE_DELETE(_gpuPipelineState);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXPipelineState.h"
namespace cc {
namespace gfx {
struct GLES2GPUPipelineState;
class CC_GLES2_API GLES2PipelineState final : public PipelineState {
public:
GLES2PipelineState();
~GLES2PipelineState() override;
inline GLES2GPUPipelineState *gpuPipelineState() const { return _gpuPipelineState; }
protected:
void doInit(const PipelineStateInfo &info) override;
void doDestroy() override;
GLES2GPUPipelineState *_gpuPipelineState = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,236 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Buffer.h"
#include "GLES2Commands.h"
#include "GLES2DescriptorSet.h"
#include "GLES2Device.h"
#include "GLES2Framebuffer.h"
#include "GLES2InputAssembler.h"
#include "GLES2PipelineState.h"
#include "GLES2PrimaryCommandBuffer.h"
#include "GLES2RenderPass.h"
#include "GLES2Texture.h"
#include "profiler/Profiler.h"
namespace cc {
namespace gfx {
GLES2PrimaryCommandBuffer::~GLES2PrimaryCommandBuffer() {
destroy();
}
void GLES2PrimaryCommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass*/, Framebuffer * /*frameBuffer*/) {
_curGPUPipelineState = nullptr;
_curGPUInputAssember = nullptr;
_curGPUDescriptorSets.assign(_curGPUDescriptorSets.size(), nullptr);
_numDrawCalls = 0;
_numInstances = 0;
_numTriangles = 0;
}
void GLES2PrimaryCommandBuffer::end() {
if (_isStateInvalid) {
bindStates();
}
}
void GLES2PrimaryCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const * /*secondaryCBs*/, uint32_t /*secondaryCBCount*/) {
_curSubpassIdx = 0U;
GLES2GPURenderPass *gpuRenderPass = static_cast<GLES2RenderPass *>(renderPass)->gpuRenderPass();
GLES2GPUFramebuffer *gpuFramebuffer = static_cast<GLES2Framebuffer *>(fbo)->gpuFBO();
cmdFuncGLES2BeginRenderPass(GLES2Device::getInstance(), _curSubpassIdx, gpuRenderPass, gpuFramebuffer,
&renderArea, colors, depth, stencil);
_curDynamicStates.viewport = {renderArea.x, renderArea.y, renderArea.width, renderArea.height};
_curDynamicStates.scissor = renderArea;
}
void GLES2PrimaryCommandBuffer::endRenderPass() {
cmdFuncGLES2EndRenderPass(GLES2Device::getInstance());
}
void GLES2PrimaryCommandBuffer::nextSubpass() {
cmdFuncGLES2EndRenderPass(GLES2Device::getInstance());
cmdFuncGLES2BeginRenderPass(GLES2Device::getInstance(), ++_curSubpassIdx);
}
void GLES2PrimaryCommandBuffer::insertMarker(const MarkerInfo &marker) {
cmdFuncGLES2InsertMarker(GLES2Device::getInstance(), marker.name.size(), marker.name.data());
}
void GLES2PrimaryCommandBuffer::beginMarker(const MarkerInfo &marker) {
cmdFuncGLES2PushGroupMarker(GLES2Device::getInstance(), marker.name.size(), marker.name.data());
}
void GLES2PrimaryCommandBuffer::endMarker() {
cmdFuncGLES2PopGroupMarker(GLES2Device::getInstance());
}
void GLES2PrimaryCommandBuffer::draw(const DrawInfo &info) {
CC_PROFILE(GLES2PrimaryCommandBufferDraw);
if (_isStateInvalid) {
ccstd::vector<uint32_t> &dynamicOffsetOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsetOffsets;
ccstd::vector<uint32_t> &dynamicOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsets;
for (size_t i = 0U; i < _curDynamicOffsets.size(); i++) {
size_t count = dynamicOffsetOffsets[i + 1] - dynamicOffsetOffsets[i];
// CC_ASSERT(_curDynamicOffsets[i].size() >= count);
count = std::min(count, _curDynamicOffsets[i].size());
if (count) memcpy(&dynamicOffsets[dynamicOffsetOffsets[i]], _curDynamicOffsets[i].data(), count * sizeof(uint32_t));
}
cmdFuncGLES2BindState(GLES2Device::getInstance(), _curGPUPipelineState, _curGPUInputAssember,
_curGPUDescriptorSets.data(), dynamicOffsets.data(), &_curDynamicStates);
_isStateInvalid = false;
}
cmdFuncGLES2Draw(GLES2Device::getInstance(), info);
++_numDrawCalls;
_numInstances += info.instanceCount;
uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount;
if (_curGPUPipelineState) {
switch (_curGPUPipelineState->glPrimitive) {
case GL_TRIANGLES: {
_numTriangles += indexCount / 3 * std::max(info.instanceCount, 1U);
break;
}
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN: {
_numTriangles += (indexCount - 2) * std::max(info.instanceCount, 1U);
break;
}
default:
break;
}
}
}
void GLES2PrimaryCommandBuffer::setViewport(const Viewport &vp) {
auto *cache = GLES2Device::getInstance()->stateCache();
if (cache->viewport != vp) {
cache->viewport = vp;
GL_CHECK(glViewport(vp.left, vp.top, vp.width, vp.height));
}
}
void GLES2PrimaryCommandBuffer::setScissor(const Rect &rect) {
auto *cache = GLES2Device::getInstance()->stateCache();
if (cache->scissor != rect) {
cache->scissor = rect;
GL_CHECK(glScissor(rect.x, rect.y, rect.width, rect.height));
}
}
void GLES2PrimaryCommandBuffer::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
GLES2GPUBuffer *gpuBuffer = static_cast<GLES2Buffer *>(buff)->gpuBuffer();
if (gpuBuffer) {
cmdFuncGLES2UpdateBuffer(GLES2Device::getInstance(), gpuBuffer, data, 0U, size);
}
}
void GLES2PrimaryCommandBuffer::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
GLES2GPUTexture *gpuTexture = static_cast<GLES2Texture *>(texture)->gpuTexture();
if (gpuTexture) {
cmdFuncGLES2CopyBuffersToTexture(GLES2Device::getInstance(), buffers, gpuTexture, regions, count);
}
}
void GLES2PrimaryCommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
copyTexture(srcTexture, dstTexture, regions, count);
}
void GLES2PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
GLES2GPUTexture *gpuTextureSrc = nullptr;
GLES2GPUTexture *gpuTextureDst = nullptr;
if (srcTexture) gpuTextureSrc = static_cast<GLES2Texture *>(srcTexture)->gpuTexture();
if (dstTexture) gpuTextureDst = static_cast<GLES2Texture *>(dstTexture)->gpuTexture();
ccstd::vector<TextureBlit> blitRegions(count);
for (uint32_t i = 0; i < count; ++i) {
auto &blit = blitRegions[i];
const auto &copy = regions[i];
blit.srcSubres = copy.srcSubres;
blit.dstSubres = copy.dstSubres;
blit.srcOffset = copy.srcOffset;
blit.dstOffset = copy.dstOffset;
blit.srcExtent = copy.extent;
blit.dstExtent = copy.extent;
}
cmdFuncGLES2BlitTexture(GLES2Device::getInstance(), gpuTextureSrc, gpuTextureDst, blitRegions.data(), count, Filter::POINT);
}
void GLES2PrimaryCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
GLES2GPUTexture *gpuTextureSrc = nullptr;
GLES2GPUTexture *gpuTextureDst = nullptr;
if (srcTexture) gpuTextureSrc = static_cast<GLES2Texture *>(srcTexture)->gpuTexture();
if (dstTexture) gpuTextureDst = static_cast<GLES2Texture *>(dstTexture)->gpuTexture();
cmdFuncGLES2BlitTexture(GLES2Device::getInstance(), gpuTextureSrc, gpuTextureDst, regions, count, filter);
}
void GLES2PrimaryCommandBuffer::execute(CommandBuffer *const *cmdBuffs, uint32_t count) {
for (uint32_t i = 0; i < count; ++i) {
auto *cmdBuff = static_cast<GLES2PrimaryCommandBuffer *>(cmdBuffs[i]);
if (!cmdBuff->_pendingPackages.empty()) {
GLES2CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
cmdFuncGLES2ExecuteCmds(GLES2Device::getInstance(), cmdPackage);
cmdBuff->_pendingPackages.pop();
cmdBuff->_freePackages.push(cmdPackage);
cmdBuff->_cmdAllocator->clearCmds(cmdPackage);
cmdBuff->_cmdAllocator->reset();
}
_numDrawCalls += cmdBuff->_numDrawCalls;
_numInstances += cmdBuff->_numInstances;
_numTriangles += cmdBuff->_numTriangles;
}
}
void GLES2PrimaryCommandBuffer::bindStates() {
if (_curGPUPipelineState) {
ccstd::vector<uint32_t> &dynamicOffsetOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsetOffsets;
ccstd::vector<uint32_t> &dynamicOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsets;
for (size_t i = 0U; i < _curDynamicOffsets.size(); i++) {
size_t count = dynamicOffsetOffsets[i + 1] - dynamicOffsetOffsets[i];
// CC_ASSERT(_curDynamicOffsets[i].size() >= count);
count = std::min(count, _curDynamicOffsets[i].size());
if (count) memcpy(&dynamicOffsets[dynamicOffsetOffsets[i]], _curDynamicOffsets[i].data(), count * sizeof(uint32_t));
}
cmdFuncGLES2BindState(GLES2Device::getInstance(), _curGPUPipelineState, _curGPUInputAssember, _curGPUDescriptorSets.data(), dynamicOffsets.data(), &_curDynamicStates);
}
_isStateInvalid = false;
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2CommandBuffer.h"
namespace cc {
namespace gfx {
class CC_GLES2_API GLES2PrimaryCommandBuffer final : public GLES2CommandBuffer {
public:
GLES2PrimaryCommandBuffer() = default;
~GLES2PrimaryCommandBuffer() override;
void begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *frameBuffer) override;
void end() override;
void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override;
void endRenderPass() override;
void nextSubpass() override;
void insertMarker(const MarkerInfo &marker) override;
void beginMarker(const MarkerInfo &marker) override;
void endMarker() override;
void draw(const DrawInfo &info) override;
void setViewport(const Viewport &vp) override;
void setScissor(const Rect &rect) override;
void updateBuffer(Buffer *buff, const void *data, uint32_t size) override;
void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override;
void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override;
void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override;
protected:
friend class GLES2Queue;
void bindStates() override;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2CommandBuffer.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2QueryPool.h"
namespace cc {
namespace gfx {
GLES2QueryPool::GLES2QueryPool() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2QueryPool::~GLES2QueryPool() {
destroy();
}
void GLES2QueryPool::doInit(const QueryPoolInfo &info) {
}
void GLES2QueryPool::doDestroy() {
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,46 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXQueryPool.h"
namespace cc {
namespace gfx {
class CC_GLES2_API GLES2QueryPool final : public QueryPool {
public:
GLES2QueryPool();
~GLES2QueryPool() override;
protected:
friend class GLES2Device;
void doInit(const QueryPoolInfo &info) override;
void doDestroy() override;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,71 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2CommandBuffer.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2Queue.h"
namespace cc {
namespace gfx {
GLES2Queue::GLES2Queue() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Queue::~GLES2Queue() {
destroy();
}
void GLES2Queue::doInit(const QueueInfo &info) {
}
void GLES2Queue::doDestroy() {
}
void GLES2Queue::submit(CommandBuffer *const *cmdBuffs, uint32_t count) {
for (uint32_t i = 0; i < count; ++i) {
auto *cmdBuff = static_cast<GLES2CommandBuffer *>(cmdBuffs[i]);
if (!cmdBuff->_pendingPackages.empty()) {
GLES2CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
cmdFuncGLES2ExecuteCmds(GLES2Device::getInstance(), cmdPackage);
cmdBuff->_pendingPackages.pop();
cmdBuff->_freePackages.push(cmdPackage);
cmdBuff->_cmdAllocator->clearCmds(cmdPackage);
cmdBuff->_cmdAllocator->reset();
}
_numDrawCalls += cmdBuff->_numDrawCalls;
_numInstances += cmdBuff->_numInstances;
_numTriangles += cmdBuff->_numTriangles;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,52 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXQueue.h"
namespace cc {
namespace gfx {
class CC_GLES2_API GLES2Queue final : public Queue {
public:
GLES2Queue();
~GLES2Queue() override;
void submit(CommandBuffer *const *cmdBuffs, uint32_t count) override;
protected:
friend class GLES2Device;
void doInit(const QueueInfo &info) override;
void doDestroy() override;
uint32_t _numDrawCalls = 0;
uint32_t _numInstances = 0;
uint32_t _numTriangles = 0;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,84 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2RenderPass.h"
namespace cc {
namespace gfx {
GLES2RenderPass::GLES2RenderPass() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2RenderPass::~GLES2RenderPass() {
destroy();
}
void GLES2RenderPass::doInit(const RenderPassInfo & /*info*/) {
_gpuRenderPass = ccnew GLES2GPURenderPass;
_gpuRenderPass->colorAttachments = _colorAttachments;
_gpuRenderPass->depthStencilAttachment = _depthStencilAttachment;
_gpuRenderPass->subpasses = _subpasses;
// assign a dummy subpass if not specified
uint32_t colorCount = utils::toUint(_gpuRenderPass->colorAttachments.size());
if (_gpuRenderPass->subpasses.empty()) {
_gpuRenderPass->subpasses.emplace_back();
auto &subpass = _gpuRenderPass->subpasses.back();
subpass.colors.resize(_colorAttachments.size());
for (uint32_t i = 0U; i < _colorAttachments.size(); ++i) {
subpass.colors[i] = i;
}
if (_depthStencilAttachment.format != Format::UNKNOWN) {
subpass.depthStencil = colorCount;
}
} else {
// unify depth stencil index
for (auto &subpass : _gpuRenderPass->subpasses) {
if (subpass.depthStencil != INVALID_BINDING && subpass.depthStencil > colorCount) {
subpass.depthStencil = colorCount;
}
if (subpass.depthStencilResolve != INVALID_BINDING && subpass.depthStencilResolve > colorCount) {
subpass.depthStencilResolve = colorCount;
}
}
}
cmdFuncGLES2CreateRenderPass(GLES2Device::getInstance(), _gpuRenderPass);
}
void GLES2RenderPass::doDestroy() {
if (_gpuRenderPass) {
cmdFuncGLES2CreateRenderPass(GLES2Device::getInstance(), _gpuRenderPass);
delete _gpuRenderPass;
_gpuRenderPass = nullptr;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXRenderPass.h"
namespace cc {
namespace gfx {
struct GLES2GPURenderPass;
class CC_GLES2_API GLES2RenderPass final : public RenderPass {
public:
GLES2RenderPass();
~GLES2RenderPass() override;
inline GLES2GPURenderPass *gpuRenderPass() const { return _gpuRenderPass; }
protected:
void doInit(const RenderPassInfo &info) override;
void doDestroy() override;
GLES2GPURenderPass *_gpuRenderPass = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,91 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2Shader.h"
namespace cc {
namespace gfx {
GLES2Shader::GLES2Shader() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Shader::~GLES2Shader() {
destroy();
}
namespace {
void initGpuShader(GLES2GPUShader *gpuShader) {
cmdFuncGLES2CreateShader(GLES2Device::getInstance(), gpuShader);
CC_ASSERT(gpuShader->glProgram);
// Clear shader source after they're uploaded to GPU
for (auto &stage : gpuShader->gpuStages) {
stage.source.clear();
stage.source.shrink_to_fit();
}
}
} // namespace
GLES2GPUShader *GLES2Shader::gpuShader() const {
if (!_gpuShader->glProgram) {
initGpuShader(_gpuShader);
}
return _gpuShader;
}
void GLES2Shader::doInit(const ShaderInfo & /*info*/) {
_gpuShader = ccnew GLES2GPUShader;
CC_ASSERT(!_gpuShader->glProgram);
_gpuShader->name = _name;
_gpuShader->blocks = _blocks;
_gpuShader->samplerTextures = _samplerTextures;
_gpuShader->subpassInputs = _subpassInputs;
for (const auto &stage : _stages) {
_gpuShader->gpuStages.push_back({stage.stage, stage.source});
}
for (auto &stage : _stages) {
stage.source.clear();
stage.source.shrink_to_fit();
}
}
void GLES2Shader::doDestroy() {
if (_gpuShader) {
cmdFuncGLES2DestroyShader(GLES2Device::getInstance(), _gpuShader);
delete _gpuShader;
_gpuShader = nullptr;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXShader.h"
namespace cc {
namespace gfx {
struct GLES2GPUShader;
class CC_GLES2_API GLES2Shader final : public Shader {
public:
GLES2Shader();
~GLES2Shader() override;
GLES2GPUShader *gpuShader() const;
protected:
void doInit(const ShaderInfo &info) override;
void doDestroy() override;
GLES2GPUShader *_gpuShader = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Log.h"
#if (CC_PLATFORM == CC_PLATFORM_WINDOWS)
#if defined(CC_STATIC)
#define CC_GLES2_API
#else
#ifdef CC_GLES2_EXPORTS
#define CC_GLES2_API __declspec(dllexport)
#else
#define CC_GLES2_API __declspec(dllimport)
#endif
#endif
#else
#define CC_GLES2_API
#endif
#if CC_DEBUG > 0
#define GL_CHECK(x) \
do { \
x; \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
CC_LOG_ERROR("%s returned GL error: 0x%x", #x, err); \
CC_ABORT(); \
} \
} while (0)
#define EGL_CHECK(x) \
do { \
x; \
EGLint err = eglGetError(); \
if (err != EGL_SUCCESS) { \
CC_LOG_ERROR("%s returned EGL error: 0x%x", #x, err); \
CC_ABORT(); \
} \
} while (0)
#else
#define GL_CHECK(x) x
#define EGL_CHECK(x) x
#endif

View File

@@ -0,0 +1,201 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Swapchain.h"
#include "GLES2Device.h"
#include "GLES2GPUObjects.h"
#include "GLES2Texture.h"
#if CC_SWAPPY_ENABLED
#include "platform/android/AndroidPlatform.h"
#include "swappy/swappyGL.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include "android/native_window.h"
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include <native_layer.h>
#include <native_layer_jni.h>
#endif
namespace cc {
namespace gfx {
GLES2Swapchain::GLES2Swapchain() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Swapchain::~GLES2Swapchain() {
destroy();
}
void GLES2Swapchain::doInit(const SwapchainInfo &info) {
const auto *context = GLES2Device::getInstance()->context();
_gpuSwapchain = ccnew GLES2GPUSwapchain;
auto window = reinterpret_cast<EGLNativeWindowType>(info.windowHandle); //NOLINT[readability-qualified-auto]
#if CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS
EGLint nFmt;
if (eglGetConfigAttrib(context->eglDisplay, context->eglConfig, EGL_NATIVE_VISUAL_ID, &nFmt) == EGL_FALSE) {
CC_LOG_ERROR("Getting configuration attributes failed.");
return;
}
#if CC_SWAPPY_ENABLED
bool enableSwappy = true;
auto *platform = static_cast<AndroidPlatform *>(cc::BasePlatform::getPlatform());
enableSwappy &= SwappyGL_init(static_cast<JNIEnv *>(platform->getEnv()), static_cast<jobject>(platform->getActivity()));
int32_t fps = cc::BasePlatform::getPlatform()->getFps();
if (enableSwappy) {
if (!fps)
SwappyGL_setSwapIntervalNS(SWAPPY_SWAP_60FPS);
else
SwappyGL_setSwapIntervalNS(1000000000L / fps); //ns
enableSwappy &= SwappyGL_setWindow(window);
_gpuSwapchain->swappyEnabled = enableSwappy;
} else {
CC_LOG_ERROR("Failed to enable Swappy in current GL swapchain, fallback instead.");
}
#endif
auto width = static_cast<int32_t>(info.width);
auto height = static_cast<int32_t>(info.height);
#if CC_PLATFORM == CC_PLATFORM_ANDROID
ANativeWindow_setBuffersGeometry(window, width, height, nFmt);
#elif CC_PLATFORM == CC_PLATFORM_OHOS
NativeLayerHandle(window, NativeLayerOps::SET_WIDTH_AND_HEIGHT, width, height);
NativeLayerHandle(window, NativeLayerOps::SET_FORMAT, nFmt);
#endif
#endif
EGL_CHECK(_gpuSwapchain->eglSurface = eglCreateWindowSurface(context->eglDisplay, context->eglConfig, window, nullptr));
if (_gpuSwapchain->eglSurface == EGL_NO_SURFACE) {
CC_LOG_ERROR("Create window surface failed.");
return;
}
switch (_vsyncMode) {
case VsyncMode::OFF: _gpuSwapchain->eglSwapInterval = 0; break;
case VsyncMode::ON:
case VsyncMode::RELAXED: _gpuSwapchain->eglSwapInterval = 1; break;
case VsyncMode::MAILBOX: _gpuSwapchain->eglSwapInterval = 0; break;
case VsyncMode::HALF: _gpuSwapchain->eglSwapInterval = 2; break;
default: break;
}
///////////////////// Texture Creation /////////////////////
_colorTexture = ccnew GLES2Texture;
_depthStencilTexture = ccnew GLES2Texture;
SwapchainTextureInfo textureInfo;
textureInfo.swapchain = this;
textureInfo.format = Format::RGBA8;
textureInfo.width = info.width;
textureInfo.height = info.height;
initTexture(textureInfo, _colorTexture);
textureInfo.format = Format::DEPTH_STENCIL;
initTexture(textureInfo, _depthStencilTexture);
_gpuSwapchain->gpuColorTexture = static_cast<GLES2Texture *>(_colorTexture.get())->gpuTexture();
}
void GLES2Swapchain::doDestroy() {
if (!_gpuSwapchain) return;
#if CC_SWAPPY_ENABLED
if (_gpuSwapchain->swappyEnabled) {
SwappyGL_destroy();
}
#endif
CC_SAFE_DESTROY(_depthStencilTexture)
CC_SAFE_DESTROY(_colorTexture)
doDestroySurface();
CC_SAFE_DELETE(_gpuSwapchain);
}
void GLES2Swapchain::doResize(uint32_t width, uint32_t height, SurfaceTransform /*transform*/) {
_colorTexture->resize(width, height);
_depthStencilTexture->resize(width, height);
if (_windowHandle) {
doCreateSurface(_windowHandle);
}
}
void GLES2Swapchain::doDestroySurface() {
if (_gpuSwapchain->eglSurface != EGL_NO_SURFACE) {
auto *context = GLES2Device::getInstance()->context();
eglDestroySurface(context->eglDisplay, _gpuSwapchain->eglSurface);
_gpuSwapchain->eglSurface = EGL_NO_SURFACE;
context->bindContext(true);
}
}
void GLES2Swapchain::doCreateSurface(void *windowHandle) {
auto *context = GLES2Device::getInstance()->context();
auto window = reinterpret_cast<EGLNativeWindowType>(windowHandle); //NOLINT [readability-qualified-auto]
EGLint nFmt = 0;
if (eglGetConfigAttrib(context->eglDisplay, context->eglConfig, EGL_NATIVE_VISUAL_ID, &nFmt) == EGL_FALSE) {
CC_LOG_ERROR("Getting configuration attributes failed.");
return;
}
auto width = static_cast<int>(_colorTexture->getWidth());
auto height = static_cast<int>(_colorTexture->getHeight());
CC_UNUSED_PARAM(width);
CC_UNUSED_PARAM(height);
#if CC_SWAPPY_ENABLED
if (_gpuSwapchain->swappyEnabled) {
_gpuSwapchain->swappyEnabled &= SwappyGL_setWindow(window);
}
#endif
#if CC_PLATFORM == CC_PLATFORM_ANDROID
ANativeWindow_setBuffersGeometry(window, width, height, nFmt);
#elif CC_PLATFORM == CC_PLATFORM_OHOS
NativeLayerHandle(window, NativeLayerOps::SET_WIDTH_AND_HEIGHT, width, height);
NativeLayerHandle(window, SET_FORMAT, nFmt);
#endif
if (_gpuSwapchain->eglSurface == EGL_NO_SURFACE) {
EGL_CHECK(_gpuSwapchain->eglSurface = eglCreateWindowSurface(context->eglDisplay, context->eglConfig, window, nullptr));
if (_gpuSwapchain->eglSurface == EGL_NO_SURFACE) {
CC_LOG_ERROR("Recreate window surface failed.");
return;
}
}
context->makeCurrent(_gpuSwapchain, _gpuSwapchain);
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXSwapchain.h"
namespace cc {
namespace gfx {
struct GLES2GPUSwapchain;
class CC_GLES2_API GLES2Swapchain final : public Swapchain {
public:
GLES2Swapchain();
~GLES2Swapchain() override;
inline GLES2GPUSwapchain *gpuSwapchain() const { return _gpuSwapchain; }
protected:
void doInit(const SwapchainInfo &info) override;
void doDestroy() override;
void doResize(uint32_t width, uint32_t height, SurfaceTransform transform) override;
void doDestroySurface() override;
void doCreateSurface(void *windowHandle) override;
GLES2GPUSwapchain *_gpuSwapchain{nullptr};
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,143 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Std.h"
#include "GLES2Commands.h"
#include "GLES2Device.h"
#include "GLES2Swapchain.h"
#include "GLES2Texture.h"
#include "profiler/Profiler.h"
namespace cc {
namespace gfx {
GLES2Texture::GLES2Texture() {
_typedID = generateObjectID<decltype(this)>();
}
GLES2Texture::~GLES2Texture() {
destroy();
}
void GLES2Texture::doInit(const TextureInfo & /*info*/) {
_gpuTexture = ccnew GLES2GPUTexture;
_gpuTexture->type = _info.type;
_gpuTexture->format = _info.format;
_gpuTexture->usage = _info.usage;
_gpuTexture->width = _info.width;
_gpuTexture->height = _info.height;
_gpuTexture->depth = _info.depth;
_gpuTexture->arrayLayer = _info.layerCount;
_gpuTexture->mipLevel = _info.levelCount;
_gpuTexture->samples = _info.samples;
_gpuTexture->flags = _info.flags;
_gpuTexture->size = _size;
_gpuTexture->isPowerOf2 = math::isPowerOfTwo(_info.width) && math::isPowerOfTwo(_info.height);
_gpuTexture->glTexture = static_cast<GLuint>(reinterpret_cast<size_t>(_info.externalRes));
cmdFuncGLES2CreateTexture(GLES2Device::getInstance(), _gpuTexture);
if (_gpuTexture->memoryAllocated) {
GLES2Device::getInstance()->getMemoryStatus().textureSize += _size;
CC_PROFILE_MEMORY_INC(Texture, _size);
}
}
void GLES2Texture::doInit(const TextureViewInfo &info) {
_gpuTexture = static_cast<GLES2Texture *>(info.texture)->gpuTexture();
}
void GLES2Texture::doDestroy() {
if (_gpuTexture) {
if (!_isTextureView) {
if (_gpuTexture->memoryAllocated) {
GLES2Device::getInstance()->getMemoryStatus().textureSize -= _size;
CC_PROFILE_MEMORY_DEC(Texture, _size);
}
cmdFuncGLES2DestroyTexture(GLES2Device::getInstance(), _gpuTexture);
GLES2Device::getInstance()->framebufferHub()->disengage(_gpuTexture);
delete _gpuTexture;
}
_gpuTexture = nullptr;
}
}
void GLES2Texture::doResize(uint32_t width, uint32_t height, uint32_t size) {
if (_gpuTexture->memoryAllocated) {
GLES2Device::getInstance()->getMemoryStatus().textureSize -= _size;
CC_PROFILE_MEMORY_DEC(Texture, _size);
}
_gpuTexture->width = width;
_gpuTexture->height = height;
_gpuTexture->size = size;
_gpuTexture->mipLevel = _info.levelCount;
cmdFuncGLES2ResizeTexture(GLES2Device::getInstance(), _gpuTexture);
GLES2Device::getInstance()->framebufferHub()->update(_gpuTexture);
if (_gpuTexture->memoryAllocated) {
GLES2Device::getInstance()->getMemoryStatus().textureSize += size;
CC_PROFILE_MEMORY_INC(Texture, size);
}
}
uint32_t GLES2Texture::getGLTextureHandle() const noexcept {
const auto *gpuTexture = _gpuTexture;
if (!gpuTexture) {
return 0;
}
if (gpuTexture->glTexture) {
return gpuTexture->glTexture;
}
if (gpuTexture->glRenderbuffer) {
return gpuTexture->glRenderbuffer;
}
return 0;
}
///////////////////////////// Swapchain Specific /////////////////////////////
void GLES2Texture::doInit(const SwapchainTextureInfo & /*info*/) {
_gpuTexture = ccnew GLES2GPUTexture;
_gpuTexture->type = _info.type;
_gpuTexture->format = _info.format;
_gpuTexture->usage = _info.usage;
_gpuTexture->width = _info.width;
_gpuTexture->height = _info.height;
_gpuTexture->depth = _info.depth;
_gpuTexture->arrayLayer = _info.layerCount;
_gpuTexture->mipLevel = _info.levelCount;
_gpuTexture->samples = _info.samples;
_gpuTexture->flags = _info.flags;
_gpuTexture->size = _size;
_gpuTexture->memoryAllocated = false;
_gpuTexture->swapchain = static_cast<GLES2Swapchain *>(_swapchain)->gpuSwapchain();
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,55 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "GLES2Std.h"
#include "gfx-base/GFXTexture.h"
namespace cc {
namespace gfx {
struct GLES2GPUTexture;
class CC_GLES2_API GLES2Texture final : public Texture {
public:
GLES2Texture();
~GLES2Texture() override;
inline GLES2GPUTexture *gpuTexture() const { return _gpuTexture; }
uint32_t getGLTextureHandle() const noexcept override;
protected:
void doInit(const TextureInfo &info) override;
void doInit(const TextureViewInfo &info) override;
void doDestroy() override;
void doResize(uint32_t width, uint32_t height, uint32_t size) override;
void doInit(const SwapchainTextureInfo &info) override;
GLES2GPUTexture *_gpuTexture = nullptr;
};
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,119 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Wrangler.h"
#if defined(_WIN32) && !defined(ANDROID)
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
static HMODULE libegl = NULL;
static HMODULE libgles = NULL;
bool gles2wOpen() {
libegl = LoadLibraryA("libEGL.dll");
libgles = LoadLibraryA("libGLESv2.dll");
return (libegl && libgles);
}
bool gles2wClose() {
bool ret = true;
if (libegl) {
ret &= FreeLibrary(libegl) ? true : false;
libegl = NULL;
}
if (libgles) {
ret &= FreeLibrary(libgles) ? true : false;
libgles = NULL;
}
return ret;
}
void *gles2wLoad(const char *proc) {
void *res = nullptr;
if (eglGetProcAddress) res = (void *)eglGetProcAddress(proc);
if (!res) res = (void *)GetProcAddress(libegl, proc);
return res;
}
#elif defined(__EMSCRIPTEN__)
bool gles2wOpen() { return true; }
bool gles2wClose() { return true; }
void *gles2wLoad(const char *proc) {
return (void *)eglGetProcAddress(proc);
}
#else
#include <dlfcn.h>
static void *libegl = nullptr;
static void *libgles = nullptr;
bool gles2wOpen() {
libegl = dlopen("libEGL.so", RTLD_LAZY | RTLD_GLOBAL);
#if __OHOS__
libgles = dlopen("libGLESv3.so", RTLD_LAZY | RTLD_GLOBAL);
#else
libgles = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_GLOBAL);
#endif
return (libegl && libgles);
}
bool gles2wClose() {
bool ret = true;
if (libegl) {
ret &= dlclose(libegl) == 0;
libegl = nullptr;
}
if (libgles) {
ret &= dlclose(libgles) == 0;
libgles = nullptr;
}
return ret;
}
void *gles2wLoad(const char *proc) {
void *res = nullptr;
if (eglGetProcAddress) res = reinterpret_cast<void *>(eglGetProcAddress(proc));
if (!res) res = dlsym(libegl, proc);
return res;
}
#endif
bool gles2wInit() {
if (!gles2wOpen()) {
return false;
}
eglwLoadProcs(gles2wLoad);
gles2wLoadProcs(gles2wLoad);
return true;
}
bool gles2wExit() {
return gles2wClose();
}

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "../gfx-gles-common/eglw.h"
#include "../gfx-gles-common/gles2w.h"
bool gles2wInit();
bool gles2wExit();

View File

@@ -0,0 +1,55 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "GLES2Sampler.h"
#include "../GLES2Commands.h"
#include "../GLES2Device.h"
namespace cc {
namespace gfx {
GLES2Sampler::GLES2Sampler(const SamplerInfo &info) : Sampler(info) {
_typedID = generateObjectID<decltype(this)>();
_gpuSampler = ccnew GLES2GPUSampler;
_gpuSampler->minFilter = _info.minFilter;
_gpuSampler->magFilter = _info.magFilter;
_gpuSampler->mipFilter = _info.mipFilter;
_gpuSampler->addressU = _info.addressU;
_gpuSampler->addressV = _info.addressV;
_gpuSampler->addressW = _info.addressW;
cmdFuncGLES2CreateSampler(GLES2Device::getInstance(), _gpuSampler);
}
GLES2Sampler::~GLES2Sampler() {
if (_gpuSampler) {
cmdFuncGLES2DestroySampler(GLES2Device::getInstance(), _gpuSampler);
delete _gpuSampler;
_gpuSampler = nullptr;
}
}
} // namespace gfx
} // namespace cc

View File

@@ -0,0 +1,48 @@
/****************************************************************************
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "../GLES2Std.h"
#include "gfx-base/GFXDef-common.h"
#include "gfx-base/states/GFXSampler.h"
namespace cc {
namespace gfx {
struct GLES2GPUSampler;
class CC_GLES2_API GLES2Sampler final : public Sampler {
public:
explicit GLES2Sampler(const SamplerInfo &info);
~GLES2Sampler() override;
inline GLES2GPUSampler *gpuSampler() const { return _gpuSampler; }
protected:
GLES2GPUSampler *_gpuSampler = nullptr;
};
} // namespace gfx
} // namespace cc