no message
This commit is contained in:
105
cocos/renderer/gfx-gles3/GLES3Buffer.cpp
Normal file
105
cocos/renderer/gfx-gles3/GLES3Buffer.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "profiler/Profiler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Buffer::GLES3Buffer() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Buffer::~GLES3Buffer() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3Buffer::doInit(const BufferInfo & /*info*/) {
|
||||
_gpuBuffer = ccnew GLES3GPUBuffer;
|
||||
_gpuBuffer->usage = _usage;
|
||||
_gpuBuffer->memUsage = _memUsage;
|
||||
_gpuBuffer->size = _size;
|
||||
_gpuBuffer->stride = _stride;
|
||||
_gpuBuffer->count = _count;
|
||||
|
||||
if (hasFlag(_usage, BufferUsageBit::INDIRECT)) {
|
||||
_gpuBuffer->indirects.resize(_count);
|
||||
}
|
||||
|
||||
cmdFuncGLES3CreateBuffer(GLES3Device::getInstance(), _gpuBuffer);
|
||||
GLES3Device::getInstance()->getMemoryStatus().bufferSize += _size;
|
||||
CC_PROFILE_MEMORY_INC(Buffer, _size);
|
||||
}
|
||||
|
||||
void GLES3Buffer::doInit(const BufferViewInfo &info) {
|
||||
auto *buffer = static_cast<GLES3Buffer *>(info.buffer);
|
||||
_gpuBuffer = ccnew GLES3GPUBuffer;
|
||||
_gpuBuffer->usage = _usage;
|
||||
_gpuBuffer->memUsage = _memUsage;
|
||||
_gpuBuffer->size = _size;
|
||||
_gpuBuffer->stride = _stride;
|
||||
_gpuBuffer->count = _count;
|
||||
_gpuBuffer->glTarget = buffer->_gpuBuffer->glTarget;
|
||||
_gpuBuffer->glBuffer = buffer->_gpuBuffer->glBuffer;
|
||||
_gpuBuffer->glOffset = info.offset;
|
||||
_gpuBuffer->buffer = buffer->_gpuBuffer->buffer;
|
||||
_gpuBuffer->indirects = buffer->_gpuBuffer->indirects;
|
||||
}
|
||||
|
||||
void GLES3Buffer::doDestroy() {
|
||||
if (_gpuBuffer) {
|
||||
if (!_isBufferView) {
|
||||
cmdFuncGLES3DestroyBuffer(GLES3Device::getInstance(), _gpuBuffer);
|
||||
GLES3Device::getInstance()->getMemoryStatus().bufferSize -= _size;
|
||||
CC_PROFILE_MEMORY_DEC(Buffer, _size);
|
||||
}
|
||||
delete _gpuBuffer;
|
||||
_gpuBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Buffer::doResize(uint32_t size, uint32_t count) {
|
||||
GLES3Device::getInstance()->getMemoryStatus().bufferSize -= _size;
|
||||
CC_PROFILE_MEMORY_DEC(Buffer, _size);
|
||||
|
||||
_gpuBuffer->size = size;
|
||||
_gpuBuffer->count = count;
|
||||
cmdFuncGLES3ResizeBuffer(GLES3Device::getInstance(), _gpuBuffer);
|
||||
|
||||
GLES3Device::getInstance()->getMemoryStatus().bufferSize += size;
|
||||
CC_PROFILE_MEMORY_INC(Buffer, size);
|
||||
}
|
||||
|
||||
void GLES3Buffer::update(const void *buffer, uint32_t size) {
|
||||
CC_PROFILE(GLES3BufferUpdate);
|
||||
cmdFuncGLES3UpdateBuffer(GLES3Device::getInstance(), _gpuBuffer, buffer, 0U, size);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
54
cocos/renderer/gfx-gles3/GLES3Buffer.h
Normal file
54
cocos/renderer/gfx-gles3/GLES3Buffer.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUBuffer;
|
||||
|
||||
class CC_GLES3_API GLES3Buffer final : public Buffer {
|
||||
public:
|
||||
GLES3Buffer();
|
||||
~GLES3Buffer() override;
|
||||
|
||||
void update(const void *buffer, uint32_t size) override;
|
||||
|
||||
inline GLES3GPUBuffer *gpuBuffer() const { return _gpuBuffer; }
|
||||
|
||||
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;
|
||||
|
||||
GLES3GPUBuffer *_gpuBuffer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
506
cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp
Normal file
506
cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp
Normal file
@@ -0,0 +1,506 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3CommandBuffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSet.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Framebuffer.h"
|
||||
#include "GLES3InputAssembler.h"
|
||||
#include "GLES3PipelineState.h"
|
||||
#include "GLES3QueryPool.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "GLES3Texture.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "states/GLES3GeneralBarrier.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3CommandBuffer::GLES3CommandBuffer() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3CommandBuffer::~GLES3CommandBuffer() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::doInit(const CommandBufferInfo & /*info*/) {
|
||||
_cmdAllocator = ccnew GLES3GPUCommandAllocator;
|
||||
_curCmdPackage = ccnew GLES3CmdPackage;
|
||||
|
||||
size_t setCount = GLES3Device::getInstance()->bindingMappingInfo().setIndices.size();
|
||||
_curGPUDescriptorSets.resize(setCount);
|
||||
_curDynamicOffsets.resize(setCount);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::doDestroy() {
|
||||
if (!_cmdAllocator) return;
|
||||
|
||||
_cmdAllocator->clearCmds(_curCmdPackage);
|
||||
CC_SAFE_DELETE(_curCmdPackage);
|
||||
|
||||
while (!_pendingPackages.empty()) {
|
||||
GLES3CmdPackage *package = _pendingPackages.front();
|
||||
_cmdAllocator->clearCmds(package);
|
||||
CC_SAFE_DELETE(package);
|
||||
_pendingPackages.pop();
|
||||
}
|
||||
|
||||
while (!_freePackages.empty()) {
|
||||
GLES3CmdPackage *package = _freePackages.front();
|
||||
_cmdAllocator->clearCmds(package);
|
||||
CC_SAFE_DELETE(package);
|
||||
_freePackages.pop();
|
||||
}
|
||||
|
||||
_cmdAllocator->reset();
|
||||
CC_SAFE_DELETE(_cmdAllocator);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass*/, Framebuffer * /*frameBuffer*/) {
|
||||
_curGPUPipelineState = nullptr;
|
||||
_curGPUInputAssember = nullptr;
|
||||
_curGPUDescriptorSets.assign(_curGPUDescriptorSets.size(), nullptr);
|
||||
|
||||
_numDrawCalls = 0;
|
||||
_numInstances = 0;
|
||||
_numTriangles = 0;
|
||||
|
||||
_cmdAllocator->clearCmds(_curCmdPackage);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::end() {
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
|
||||
_pendingPackages.push(_curCmdPackage);
|
||||
if (!_freePackages.empty()) {
|
||||
_curCmdPackage = _freePackages.front();
|
||||
_freePackages.pop();
|
||||
} else {
|
||||
_curCmdPackage = ccnew GLES3CmdPackage;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const * /*secondaryCBs*/, uint32_t /*secondaryCBCount*/) {
|
||||
_curSubpassIdx = 0U;
|
||||
|
||||
GLES3CmdBeginRenderPass *cmd = _cmdAllocator->beginRenderPassCmdPool.alloc();
|
||||
cmd->subpassIdx = _curSubpassIdx;
|
||||
cmd->gpuRenderPass = static_cast<GLES3RenderPass *>(renderPass)->gpuRenderPass();
|
||||
cmd->gpuFBO = static_cast<GLES3Framebuffer *>(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 GLES3CommandBuffer::endRenderPass() {
|
||||
_curCmdPackage->cmds.push(GLESCmdType::END_RENDER_PASS);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::nextSubpass() {
|
||||
_curCmdPackage->cmds.push(GLESCmdType::END_RENDER_PASS);
|
||||
GLES3CmdBeginRenderPass *cmd = _cmdAllocator->beginRenderPassCmdPool.alloc();
|
||||
cmd->subpassIdx = ++_curSubpassIdx;
|
||||
_curCmdPackage->beginRenderPassCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::BEGIN_RENDER_PASS);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::insertMarker(const MarkerInfo &marker) {
|
||||
std::ignore = marker;
|
||||
}
|
||||
void GLES3CommandBuffer::beginMarker(const MarkerInfo &marker) {
|
||||
std::ignore = marker;
|
||||
}
|
||||
void GLES3CommandBuffer::endMarker() {
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::bindPipelineState(PipelineState *pso) {
|
||||
GLES3GPUPipelineState *gpuPipelineState = static_cast<GLES3PipelineState *>(pso)->gpuPipelineState();
|
||||
if (_curGPUPipelineState != gpuPipelineState) {
|
||||
_curGPUPipelineState = gpuPipelineState;
|
||||
_isStateInvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) {
|
||||
CC_ASSERT(_curGPUDescriptorSets.size() > set);
|
||||
|
||||
GLES3GPUDescriptorSet *gpuDescriptorSet = static_cast<GLES3DescriptorSet *>(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 GLES3CommandBuffer::bindInputAssembler(InputAssembler *ia) {
|
||||
_curGPUInputAssember = static_cast<GLES3InputAssembler *>(ia)->gpuInputAssembler();
|
||||
_isStateInvalid = true;
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::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 GLES3CommandBuffer::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 GLES3CommandBuffer::setLineWidth(float width) {
|
||||
if (math::isNotEqualF(_curDynamicStates.lineWidth, width)) {
|
||||
_curDynamicStates.lineWidth = width;
|
||||
_isStateInvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::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 GLES3CommandBuffer::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 GLES3CommandBuffer::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 GLES3CommandBuffer::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 GLES3CommandBuffer::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 GLES3CommandBuffer::draw(const DrawInfo &info) {
|
||||
CC_PROFILE(GLES3CommandBufferDraw);
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
|
||||
GLES3CmdDraw *cmd = _cmdAllocator->drawCmdPool.alloc();
|
||||
cmd->drawInfo = info;
|
||||
_curCmdPackage->drawCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::DRAW);
|
||||
|
||||
++_numDrawCalls;
|
||||
_numInstances += info.instanceCount;
|
||||
if (_curGPUPipelineState) {
|
||||
uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount;
|
||||
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 GLES3CommandBuffer::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
|
||||
GLES3GPUBuffer *gpuBuffer = static_cast<GLES3Buffer *>(buff)->gpuBuffer();
|
||||
if (gpuBuffer) {
|
||||
GLES3CmdUpdateBuffer *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 GLES3CommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
// should not copy texture in a secondary command buffer
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
// should not resolve texture in a secondary command buffer
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
|
||||
GLES3CmdBlitTexture *cmd = _cmdAllocator->blitTextureCmdPool.alloc();
|
||||
if (srcTexture) cmd->gpuTextureSrcView = static_cast<GLES3Texture *>(srcTexture)->gpuTextureView();
|
||||
if (dstTexture) cmd->gpuTextureDstView = static_cast<GLES3Texture *>(dstTexture)->gpuTextureView();
|
||||
cmd->regions = regions;
|
||||
cmd->count = count;
|
||||
cmd->filter = filter;
|
||||
|
||||
_curCmdPackage->blitTextureCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::BLIT_TEXTURE);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
|
||||
GLES3GPUTexture *gpuTexture = static_cast<GLES3Texture *>(texture)->gpuTexture();
|
||||
if (gpuTexture) {
|
||||
GLES3CmdCopyBufferToTexture *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 GLES3CommandBuffer::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<GLES3CommandBuffer *>(cmdBuffs[i]);
|
||||
GLES3CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
|
||||
|
||||
for (uint32_t j = 0; j < cmdPackage->beginRenderPassCmds.size(); ++j) {
|
||||
GLES3CmdBeginRenderPass *cmd = cmdPackage->beginRenderPassCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->beginRenderPassCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->bindStatesCmds.size(); ++j) {
|
||||
GLES3CmdBindStates *cmd = cmdPackage->bindStatesCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->bindStatesCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->drawCmds.size(); ++j) {
|
||||
GLES3CmdDraw *cmd = cmdPackage->drawCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->drawCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->dispatchCmds.size(); ++j) {
|
||||
GLES3CmdDispatch *cmd = cmdPackage->dispatchCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->dispatchCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->barrierCmds.size(); ++j) {
|
||||
GLES3CmdBarrier *cmd = cmdPackage->barrierCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->barrierCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->updateBufferCmds.size(); ++j) {
|
||||
GLES3CmdUpdateBuffer *cmd = cmdPackage->updateBufferCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->updateBufferCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->copyBufferToTextureCmds.size(); ++j) {
|
||||
GLES3CmdCopyBufferToTexture *cmd = cmdPackage->copyBufferToTextureCmds[j];
|
||||
++cmd->refCount;
|
||||
_curCmdPackage->copyBufferToTextureCmds.push(cmd);
|
||||
}
|
||||
for (uint32_t j = 0; j < cmdPackage->blitTextureCmds.size(); ++j) {
|
||||
GLES3CmdBlitTexture *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 'transfering' the owner ship
|
||||
// cmdBuff->_cmdAllocator->clearCmds(cmdPackage);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::bindStates() {
|
||||
GLES3CmdBindStates *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;
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::dispatch(const DispatchInfo &info) {
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
|
||||
GLES3CmdDispatch *cmd = _cmdAllocator->dispatchCmdPool.alloc();
|
||||
if (info.indirectBuffer) {
|
||||
cmd->dispatchInfo.indirectBuffer = static_cast<GLES3Buffer *>(info.indirectBuffer)->gpuBuffer();
|
||||
cmd->dispatchInfo.indirectOffset = info.indirectOffset;
|
||||
} else {
|
||||
cmd->dispatchInfo.groupCountX = info.groupCountX;
|
||||
cmd->dispatchInfo.groupCountY = info.groupCountY;
|
||||
cmd->dispatchInfo.groupCountZ = info.groupCountZ;
|
||||
}
|
||||
_curCmdPackage->dispatchCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::DISPATCH);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::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*/) {
|
||||
if (!barrier) return;
|
||||
|
||||
const auto *gpuBarrier = static_cast<const GLES3GeneralBarrier *>(barrier)->gpuBarrier();
|
||||
|
||||
GLES3CmdBarrier *cmd = _cmdAllocator->barrierCmdPool.alloc();
|
||||
cmd->barriers = gpuBarrier->glBarriers;
|
||||
cmd->barriersByRegion = gpuBarrier->glBarriersByRegion;
|
||||
_curCmdPackage->barrierCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::BARRIER);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::beginQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
GLES3CmdQuery *cmd = _cmdAllocator->queryCmdPool.alloc();
|
||||
cmd->queryPool = gles3QueryPool;
|
||||
cmd->type = GLES3QueryType::BEGIN;
|
||||
cmd->id = id;
|
||||
|
||||
_curCmdPackage->queryCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::QUERY);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::endQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
GLES3CmdQuery *cmd = _cmdAllocator->queryCmdPool.alloc();
|
||||
cmd->queryPool = gles3QueryPool;
|
||||
cmd->type = GLES3QueryType::END;
|
||||
cmd->id = id;
|
||||
|
||||
_curCmdPackage->queryCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::QUERY);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::resetQueryPool(QueryPool *queryPool) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
GLES3CmdQuery *cmd = _cmdAllocator->queryCmdPool.alloc();
|
||||
cmd->queryPool = gles3QueryPool;
|
||||
cmd->type = GLES3QueryType::RESET;
|
||||
cmd->id = 0;
|
||||
|
||||
_curCmdPackage->queryCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::QUERY);
|
||||
}
|
||||
|
||||
void GLES3CommandBuffer::getQueryPoolResults(QueryPool *queryPool) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
GLES3CmdQuery *cmd = _cmdAllocator->queryCmdPool.alloc();
|
||||
cmd->queryPool = gles3QueryPool;
|
||||
cmd->type = GLES3QueryType::GET_RESULTS;
|
||||
cmd->id = 0;
|
||||
|
||||
_curCmdPackage->queryCmds.push(cmd);
|
||||
_curCmdPackage->cmds.push(GLESCmdType::QUERY);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
104
cocos/renderer/gfx-gles3/GLES3CommandBuffer.h
Normal file
104
cocos/renderer/gfx-gles3/GLES3CommandBuffer.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "base/std/container/queue.h"
|
||||
#include "gfx-base/GFXCommandBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GLES3GPUCommandAllocator;
|
||||
struct GLES3CmdPackage;
|
||||
struct GLES3GPUPipelineState;
|
||||
struct GLES3GPUInputAssembler;
|
||||
struct GLES3GPUDescriptorSet;
|
||||
struct GLES3GPURenderPass;
|
||||
|
||||
class CC_GLES3_API GLES3CommandBuffer : public CommandBuffer {
|
||||
public:
|
||||
GLES3CommandBuffer();
|
||||
~GLES3CommandBuffer() 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 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 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;
|
||||
void dispatch(const DispatchInfo &info) override;
|
||||
void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const * /*buffers*/, uint32_t bufferBarrierCount, 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:
|
||||
friend class GLES3Queue;
|
||||
friend class GLES3Device;
|
||||
|
||||
virtual void getQueryPoolResults(QueryPool *query);
|
||||
|
||||
void doInit(const CommandBufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
virtual void bindStates();
|
||||
|
||||
GLES3GPUCommandAllocator *_cmdAllocator = nullptr;
|
||||
GLES3CmdPackage *_curCmdPackage = nullptr;
|
||||
ccstd::queue<GLES3CmdPackage *> _pendingPackages, _freePackages;
|
||||
|
||||
uint32_t _curSubpassIdx = 0U;
|
||||
GLES3GPUPipelineState *_curGPUPipelineState = nullptr;
|
||||
GLES3GPUInputAssembler *_curGPUInputAssember = nullptr;
|
||||
ccstd::vector<GLES3GPUDescriptorSet *> _curGPUDescriptorSets;
|
||||
ccstd::vector<ccstd::vector<uint32_t>> _curDynamicOffsets;
|
||||
DynamicStates _curDynamicStates;
|
||||
|
||||
bool _isStateInvalid = false;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
3267
cocos/renderer/gfx-gles3/GLES3Commands.cpp
Normal file
3267
cocos/renderer/gfx-gles3/GLES3Commands.cpp
Normal file
File diff suppressed because it is too large
Load Diff
323
cocos/renderer/gfx-gles3/GLES3Commands.h
Normal file
323
cocos/renderer/gfx-gles3/GLES3Commands.h
Normal file
@@ -0,0 +1,323 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3GPUObjects.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GLES3Device;
|
||||
class GLES3QueryPool;
|
||||
|
||||
class GLES3CmdBeginRenderPass final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPURenderPass *gpuRenderPass = nullptr;
|
||||
GLES3GPUFramebuffer *gpuFBO = nullptr;
|
||||
Rect renderArea;
|
||||
Color clearColors[MAX_ATTACHMENTS];
|
||||
float clearDepth = 1.0F;
|
||||
uint32_t clearStencil = 0U;
|
||||
uint32_t subpassIdx = 0U;
|
||||
|
||||
GLES3CmdBeginRenderPass() : GLESCmd(GLESCmdType::BEGIN_RENDER_PASS) {}
|
||||
|
||||
void clear() override {
|
||||
gpuRenderPass = nullptr;
|
||||
gpuFBO = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdBindStates final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPUPipelineState *gpuPipelineState = nullptr;
|
||||
GLES3GPUInputAssembler *gpuInputAssembler = nullptr;
|
||||
ccstd::vector<GLES3GPUDescriptorSet *> gpuDescriptorSets;
|
||||
ccstd::vector<uint32_t> dynamicOffsets;
|
||||
DynamicStates dynamicStates;
|
||||
|
||||
GLES3CmdBindStates() : GLESCmd(GLESCmdType::BIND_STATES) {}
|
||||
|
||||
void clear() override {
|
||||
gpuPipelineState = nullptr;
|
||||
gpuInputAssembler = nullptr;
|
||||
gpuDescriptorSets.clear();
|
||||
dynamicOffsets.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdDraw final : public GLESCmd {
|
||||
public:
|
||||
DrawInfo drawInfo;
|
||||
|
||||
GLES3CmdDraw() : GLESCmd(GLESCmdType::DRAW) {}
|
||||
void clear() override {}
|
||||
};
|
||||
|
||||
class GLES3CmdDispatch final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPUDispatchInfo dispatchInfo;
|
||||
|
||||
GLES3CmdDispatch() : GLESCmd(GLESCmdType::DISPATCH) {}
|
||||
void clear() override {
|
||||
dispatchInfo.indirectBuffer = nullptr;
|
||||
dispatchInfo.indirectOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdBarrier final : public GLESCmd {
|
||||
public:
|
||||
GLbitfield barriers = 0U;
|
||||
GLbitfield barriersByRegion = 0U;
|
||||
|
||||
GLES3CmdBarrier() : GLESCmd(GLESCmdType::BARRIER) {}
|
||||
void clear() override {
|
||||
barriers = 0U;
|
||||
barriersByRegion = 0U;
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdUpdateBuffer final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPUBuffer *gpuBuffer = nullptr;
|
||||
const uint8_t *buffer = nullptr;
|
||||
uint32_t size = 0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
GLES3CmdUpdateBuffer() : GLESCmd(GLESCmdType::UPDATE_BUFFER) {}
|
||||
|
||||
void clear() override {
|
||||
gpuBuffer = nullptr;
|
||||
buffer = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdCopyBufferToTexture final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPUTexture *gpuTexture = nullptr;
|
||||
const BufferTextureCopy *regions = nullptr;
|
||||
uint32_t count = 0U;
|
||||
const uint8_t *const *buffers = nullptr;
|
||||
|
||||
GLES3CmdCopyBufferToTexture() : GLESCmd(GLESCmdType::COPY_BUFFER_TO_TEXTURE) {}
|
||||
|
||||
void clear() override {
|
||||
gpuTexture = nullptr;
|
||||
regions = nullptr;
|
||||
count = 0U;
|
||||
buffers = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class GLES3CmdBlitTexture final : public GLESCmd {
|
||||
public:
|
||||
GLES3GPUTextureView *gpuTextureSrcView = nullptr;
|
||||
GLES3GPUTextureView *gpuTextureDstView = nullptr;
|
||||
const TextureBlit *regions = nullptr;
|
||||
uint32_t count = 0U;
|
||||
Filter filter = Filter::POINT;
|
||||
|
||||
GLES3CmdBlitTexture() : GLESCmd(GLESCmdType::BLIT_TEXTURE) {}
|
||||
|
||||
void clear() override {
|
||||
gpuTextureSrcView = nullptr;
|
||||
gpuTextureDstView = nullptr;
|
||||
regions = nullptr;
|
||||
count = 0U;
|
||||
}
|
||||
};
|
||||
|
||||
enum class GLES3QueryType : uint8_t {
|
||||
BEGIN,
|
||||
END,
|
||||
RESET,
|
||||
GET_RESULTS,
|
||||
};
|
||||
|
||||
class GLES3CmdQuery final : public GLESCmd {
|
||||
public:
|
||||
GLES3QueryPool *queryPool = nullptr;
|
||||
GLES3QueryType type = GLES3QueryType::BEGIN;
|
||||
uint32_t id = 0U;
|
||||
|
||||
GLES3CmdQuery() : GLESCmd(GLESCmdType::QUERY) {}
|
||||
|
||||
void clear() override {
|
||||
queryPool = nullptr;
|
||||
type = GLES3QueryType::BEGIN;
|
||||
id = 0U;
|
||||
}
|
||||
};
|
||||
|
||||
struct GLES3CmdPackage {
|
||||
CachedArray<GLESCmdType> cmds;
|
||||
CachedArray<GLES3CmdBeginRenderPass *> beginRenderPassCmds;
|
||||
CachedArray<GLES3CmdBindStates *> bindStatesCmds;
|
||||
CachedArray<GLES3CmdDraw *> drawCmds;
|
||||
CachedArray<GLES3CmdDispatch *> dispatchCmds;
|
||||
CachedArray<GLES3CmdBarrier *> barrierCmds;
|
||||
CachedArray<GLES3CmdUpdateBuffer *> updateBufferCmds;
|
||||
CachedArray<GLES3CmdCopyBufferToTexture *> copyBufferToTextureCmds;
|
||||
CachedArray<GLES3CmdBlitTexture *> blitTextureCmds;
|
||||
CachedArray<GLES3CmdQuery *> queryCmds;
|
||||
};
|
||||
|
||||
class GLES3GPUCommandAllocator final {
|
||||
public:
|
||||
CommandPool<GLES3CmdBeginRenderPass> beginRenderPassCmdPool;
|
||||
CommandPool<GLES3CmdBindStates> bindStatesCmdPool;
|
||||
CommandPool<GLES3CmdDraw> drawCmdPool;
|
||||
CommandPool<GLES3CmdDispatch> dispatchCmdPool;
|
||||
CommandPool<GLES3CmdBarrier> barrierCmdPool;
|
||||
CommandPool<GLES3CmdUpdateBuffer> updateBufferCmdPool;
|
||||
CommandPool<GLES3CmdCopyBufferToTexture> copyBufferToTextureCmdPool;
|
||||
CommandPool<GLES3CmdBlitTexture> blitTextureCmdPool;
|
||||
CommandPool<GLES3CmdQuery> queryCmdPool;
|
||||
|
||||
void clearCmds(GLES3CmdPackage *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->dispatchCmds.size()) {
|
||||
dispatchCmdPool.freeCmds(cmdPackage->dispatchCmds);
|
||||
}
|
||||
if (cmdPackage->barrierCmds.size()) {
|
||||
barrierCmdPool.freeCmds(cmdPackage->barrierCmds);
|
||||
}
|
||||
if (cmdPackage->updateBufferCmds.size()) {
|
||||
updateBufferCmdPool.freeCmds(cmdPackage->updateBufferCmds);
|
||||
}
|
||||
if (cmdPackage->copyBufferToTextureCmds.size()) {
|
||||
copyBufferToTextureCmdPool.freeCmds(cmdPackage->copyBufferToTextureCmds);
|
||||
}
|
||||
if (cmdPackage->blitTextureCmds.size()) {
|
||||
blitTextureCmdPool.freeCmds(cmdPackage->blitTextureCmds);
|
||||
}
|
||||
if (cmdPackage->queryCmds.size()) {
|
||||
queryCmdPool.freeCmds(cmdPackage->queryCmds);
|
||||
}
|
||||
|
||||
cmdPackage->cmds.clear();
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
beginRenderPassCmdPool.release();
|
||||
bindStatesCmdPool.release();
|
||||
drawCmdPool.release();
|
||||
dispatchCmdPool.release();
|
||||
barrierCmdPool.release();
|
||||
updateBufferCmdPool.release();
|
||||
copyBufferToTextureCmdPool.release();
|
||||
blitTextureCmdPool.release();
|
||||
}
|
||||
};
|
||||
|
||||
void cmdFuncGLES3CreateBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer);
|
||||
void cmdFuncGLES3DestroyBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer);
|
||||
void cmdFuncGLES3ResizeBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer);
|
||||
void cmdFuncGLES3CreateTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture);
|
||||
void cmdFuncGLES3DestroyTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture);
|
||||
void cmdFuncGLES3ResizeTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture);
|
||||
void cmdFuncGLES3CreateTextureView(GLES3Device *device, GLES3GPUTextureView *gpuTextureView);
|
||||
void cmdFuncGLES3CreateShader(GLES3Device *device, GLES3GPUShader *gpuShader, GLES3GPUPipelineLayout *pipelineLayout);
|
||||
void cmdFuncGLES3DestroyShader(GLES3Device *device, GLES3GPUShader *gpuShader);
|
||||
void cmdFuncGLES3CreateRenderPass(GLES3Device *device, GLES3GPURenderPass *gpuRenderPass);
|
||||
void cmdFuncGLES3DestroyRenderPass(GLES3Device *device, GLES3GPURenderPass *gpuRenderPass);
|
||||
void cmdFuncGLES3CreateInputAssembler(GLES3Device *device, GLES3GPUInputAssembler *gpuInputAssembler);
|
||||
void cmdFuncGLES3DestroyInputAssembler(GLES3Device *device, GLES3GPUInputAssembler *gpuInputAssembler);
|
||||
void cmdFuncGLES3CreateFramebuffer(GLES3Device *device, GLES3GPUFramebuffer *gpuFBO);
|
||||
void cmdFuncGLES3DestroyFramebuffer(GLES3Device *device, GLES3GPUFramebuffer *gpuFBO);
|
||||
void cmdFuncGLES3CreateGeneralBarrier(GLES3Device *device, GLES3GPUGeneralBarrier *barrier);
|
||||
void cmdFuncGLES3CreateQueryPool(GLES3Device *device, GLES3GPUQueryPool *gpuQueryPool);
|
||||
void cmdFuncGLES3DestroyQueryPool(GLES3Device *device, GLES3GPUQueryPool *gpuQueryPool);
|
||||
void cmdFuncGLES3PrepareSamplerInfo(GLES3Device *device, GLES3GPUSampler *gpuSampler);
|
||||
|
||||
void completeBarrier(GLES3GPUGeneralBarrier *barrier);
|
||||
|
||||
void cmdFuncGLES3Query(GLES3Device *device, GLES3QueryPool *query, GLES3QueryType type, uint32_t id);
|
||||
|
||||
void cmdFuncGLES3BeginRenderPass(GLES3Device *device,
|
||||
GLES3GPURenderPass *gpuRenderPass = nullptr,
|
||||
GLES3GPUFramebuffer *gpuFramebuffer = nullptr,
|
||||
const Rect *renderArea = nullptr,
|
||||
const Color *clearColors = nullptr,
|
||||
float clearDepth = 1.F,
|
||||
uint32_t clearStencil = 0);
|
||||
|
||||
void cmdFuncGLES3EndRenderPass(GLES3Device *device);
|
||||
|
||||
void cmdFuncGLES3BindState(GLES3Device *device,
|
||||
GLES3GPUPipelineState *gpuPipelineState,
|
||||
GLES3GPUInputAssembler *gpuInputAssembler,
|
||||
const GLES3GPUDescriptorSet *const *gpuDescriptorSets,
|
||||
const uint32_t *dynamicOffsets = nullptr,
|
||||
const DynamicStates *dynamicStates = nullptr);
|
||||
|
||||
void cmdFuncGLES3Draw(GLES3Device *device, const DrawInfo &drawInfo);
|
||||
|
||||
void cmdFuncGLES3UpdateBuffer(GLES3Device *device,
|
||||
GLES3GPUBuffer *gpuBuffer,
|
||||
const void *buffer,
|
||||
uint32_t offset,
|
||||
uint32_t size);
|
||||
|
||||
void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device,
|
||||
const uint8_t *const *buffers,
|
||||
GLES3GPUTexture *gpuTexture,
|
||||
const BufferTextureCopy *regions,
|
||||
uint32_t count);
|
||||
void cmdFuncGLES3CopyTextureToBuffers(GLES3Device *device,
|
||||
GLES3GPUTextureView *gpuTextureView,
|
||||
uint8_t *const *buffers,
|
||||
const BufferTextureCopy *regions,
|
||||
uint32_t count);
|
||||
|
||||
void cmdFuncGLES3BlitTexture(GLES3Device *device,
|
||||
GLES3GPUTextureView *gpuTextureSrcView,
|
||||
GLES3GPUTextureView *gpuTextureDstView,
|
||||
const TextureBlit *regions,
|
||||
uint32_t count,
|
||||
Filter filter);
|
||||
|
||||
void cmdFuncGLES3ExecuteCmds(GLES3Device *device, GLES3CmdPackage *cmdPackage);
|
||||
|
||||
void cmdFuncGLES3Dispatch(GLES3Device *device, const GLES3GPUDispatchInfo &info);
|
||||
|
||||
void cmdFuncGLES3MemoryBarrier(GLES3Device *device, GLbitfield barriers, GLbitfield barriersByRegion);
|
||||
|
||||
void cmdFuncGLES3InsertMarker(GLES3Device *device, GLsizei length, const char *marker);
|
||||
void cmdFuncGLES3PushGroupMarker(GLES3Device *device, GLsizei length, const char *marker);
|
||||
void cmdFuncGLES3PopGroupMarker(GLES3Device *device);
|
||||
|
||||
GLint cmdFuncGLES3GetMaxSampleCount(const GLES3Device *device, Format format, TextureUsage usage, TextureFlags flags);
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
108
cocos/renderer/gfx-gles3/GLES3DescriptorSet.cpp
Normal file
108
cocos/renderer/gfx-gles3/GLES3DescriptorSet.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSet.h"
|
||||
#include "GLES3DescriptorSetLayout.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Texture.h"
|
||||
#include "gfx-gles3/GLES3GPUObjects.h"
|
||||
#include "states/GLES3Sampler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3DescriptorSet::GLES3DescriptorSet() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3DescriptorSet::~GLES3DescriptorSet() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3DescriptorSet::doInit(const DescriptorSetInfo & /*info*/) {
|
||||
const GLES3GPUDescriptorSetLayout *gpuDescriptorSetLayout = static_cast<const GLES3DescriptorSetLayout *>(_layout)->gpuDescriptorSetLayout();
|
||||
const size_t descriptorCount = gpuDescriptorSetLayout->descriptorCount;
|
||||
const size_t bindingCount = gpuDescriptorSetLayout->bindings.size();
|
||||
|
||||
_gpuDescriptorSet = ccnew GLES3GPUDescriptorSet;
|
||||
_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 GLES3DescriptorSet::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuDescriptorSet);
|
||||
}
|
||||
|
||||
void GLES3DescriptorSet::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)) {
|
||||
if (_buffers[i].ptr) {
|
||||
descriptors[i].gpuBuffer = static_cast<GLES3Buffer *>(_buffers[i].ptr)->gpuBuffer();
|
||||
}
|
||||
} else if (hasAnyFlags(descriptors[i].type, DESCRIPTOR_TEXTURE_TYPE)) {
|
||||
if (_samplers[i].ptr) {
|
||||
descriptors[i].gpuSampler = static_cast<GLES3Sampler *>(_samplers[i].ptr)->gpuSampler();
|
||||
}
|
||||
|
||||
if (_textures[i].ptr) {
|
||||
_gpuDescriptorSet->gpuDescriptors[i].gpuTextureView = static_cast<GLES3Texture *>(_textures[i].ptr)->gpuTextureView();
|
||||
|
||||
// work around for sample depth stencil texture, delete when rdg support set sampler.
|
||||
const FormatInfo &info = GFX_FORMAT_INFOS[toNumber(
|
||||
_textures[i].ptr->getFormat())];
|
||||
if (info.hasDepth || info.hasStencil) {
|
||||
gfx::SamplerInfo samplerInfo = {};
|
||||
samplerInfo.minFilter = gfx::Filter::POINT;
|
||||
samplerInfo.magFilter = gfx::Filter::POINT;
|
||||
descriptors[i].gpuSampler = static_cast<GLES3Sampler *>(Device::getInstance()->getSampler(
|
||||
samplerInfo))
|
||||
->gpuSampler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_isDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3DescriptorSet::forceUpdate() {
|
||||
_isDirty = true;
|
||||
update();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
53
cocos/renderer/gfx-gles3/GLES3DescriptorSet.h
Normal file
53
cocos/renderer/gfx-gles3/GLES3DescriptorSet.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXDescriptorSet.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUDescriptorSet;
|
||||
|
||||
class CC_GLES3_API GLES3DescriptorSet final : public DescriptorSet {
|
||||
public:
|
||||
GLES3DescriptorSet();
|
||||
~GLES3DescriptorSet() override;
|
||||
|
||||
void update() override;
|
||||
void forceUpdate() override;
|
||||
|
||||
inline GLES3GPUDescriptorSet *gpuDescriptorSet() const { return _gpuDescriptorSet; }
|
||||
|
||||
protected:
|
||||
void doInit(const DescriptorSetInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUDescriptorSet *_gpuDescriptorSet = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
72
cocos/renderer/gfx-gles3/GLES3DescriptorSetLayout.cpp
Normal file
72
cocos/renderer/gfx-gles3/GLES3DescriptorSetLayout.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSetLayout.h"
|
||||
#include "states/GLES3Sampler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3DescriptorSetLayout::GLES3DescriptorSetLayout() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3DescriptorSetLayout::~GLES3DescriptorSetLayout() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3DescriptorSetLayout::doInit(const DescriptorSetLayoutInfo & /*info*/) {
|
||||
_gpuDescriptorSetLayout = ccnew GLES3GPUDescriptorSetLayout;
|
||||
_gpuDescriptorSetLayout->descriptorCount = _descriptorCount;
|
||||
_gpuDescriptorSetLayout->bindingIndices = _bindingIndices;
|
||||
_gpuDescriptorSetLayout->descriptorIndices = _descriptorIndices;
|
||||
_gpuDescriptorSetLayout->bindings = _bindings;
|
||||
|
||||
auto &hash = _gpuDescriptorSetLayout->hash;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::hash_combine(hash, binding.binding);
|
||||
ccstd::hash_combine(hash, binding.descriptorType);
|
||||
ccstd::hash_combine(hash, binding.count);
|
||||
ccstd::hash_combine(hash, binding.stageFlags);
|
||||
for (auto &sampler : binding.immutableSamplers) {
|
||||
ccstd::hash_combine(hash, sampler->getHash());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3DescriptorSetLayout::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuDescriptorSetLayout);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-gles3/GLES3DescriptorSetLayout.h
Normal file
50
cocos/renderer/gfx-gles3/GLES3DescriptorSetLayout.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXDescriptorSetLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUDescriptorSetLayout;
|
||||
|
||||
class CC_GLES3_API GLES3DescriptorSetLayout final : public DescriptorSetLayout {
|
||||
public:
|
||||
GLES3DescriptorSetLayout();
|
||||
~GLES3DescriptorSetLayout() override;
|
||||
|
||||
inline GLES3GPUDescriptorSetLayout *gpuDescriptorSetLayout() const { return _gpuDescriptorSetLayout; }
|
||||
|
||||
protected:
|
||||
void doInit(const DescriptorSetLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUDescriptorSetLayout *_gpuDescriptorSetLayout = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
625
cocos/renderer/gfx-gles3/GLES3Device.cpp
Normal file
625
cocos/renderer/gfx-gles3/GLES3Device.cpp
Normal file
@@ -0,0 +1,625 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3CommandBuffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSet.h"
|
||||
#include "GLES3DescriptorSetLayout.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Framebuffer.h"
|
||||
#include "GLES3GPUObjects.h"
|
||||
#include "GLES3InputAssembler.h"
|
||||
#include "GLES3PipelineCache.h"
|
||||
#include "GLES3PipelineLayout.h"
|
||||
#include "GLES3PipelineState.h"
|
||||
#include "GLES3PrimaryCommandBuffer.h"
|
||||
#include "GLES3QueryPool.h"
|
||||
#include "GLES3Queue.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "GLES3Shader.h"
|
||||
#include "GLES3Swapchain.h"
|
||||
#include "GLES3Texture.h"
|
||||
#include "application/ApplicationManager.h"
|
||||
#include "platform/interfaces/modules/IXRInterface.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "states/GLES3GeneralBarrier.h"
|
||||
#include "states/GLES3Sampler.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 {
|
||||
|
||||
GLES3Device *GLES3Device::instance = nullptr;
|
||||
|
||||
GLES3Device *GLES3Device::getInstance() {
|
||||
return GLES3Device::instance;
|
||||
}
|
||||
|
||||
GLES3Device::GLES3Device() {
|
||||
_api = API::GLES3;
|
||||
_deviceName = "GLES3";
|
||||
|
||||
GLES3Device::instance = this;
|
||||
}
|
||||
|
||||
GLES3Device::~GLES3Device() {
|
||||
GLES3Device::instance = nullptr;
|
||||
}
|
||||
|
||||
bool GLES3Device::doInit(const DeviceInfo & /*info*/) {
|
||||
_xr = CC_GET_XR_INTERFACE();
|
||||
if (_xr) _xr->preGFXDeviceInitialize(_api);
|
||||
_gpuContext = ccnew GLES3GPUContext;
|
||||
_gpuStateCache = ccnew GLES3GPUStateCache;
|
||||
_gpuFramebufferHub = ccnew GLES3GPUFramebufferHub;
|
||||
_gpuConstantRegistry = ccnew GLES3GPUConstantRegistry;
|
||||
_gpuFramebufferCacheMap = ccnew GLES3GPUFramebufferCacheMap(_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, " ");
|
||||
|
||||
initFormatFeature();
|
||||
|
||||
_multithreadedCommandRecording = false;
|
||||
|
||||
_features[toNumber(Feature::INSTANCED_ARRAYS)] = true;
|
||||
_features[toNumber(Feature::MULTIPLE_RENDER_TARGETS)] = true;
|
||||
_features[toNumber(Feature::BLEND_MINMAX)] = true;
|
||||
_features[toNumber(Feature::ELEMENT_INDEX_UINT)] = true;
|
||||
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = false;
|
||||
|
||||
if (_gpuConstantRegistry->glMinorVersion) {
|
||||
_features[toNumber(Feature::COMPUTE_SHADER)] = true;
|
||||
}
|
||||
|
||||
ccstd::string fbfLevelStr = "NONE";
|
||||
// PVRVFrame has issues on their support
|
||||
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;
|
||||
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true;
|
||||
fbfLevelStr = "NON_COHERENT_EXT";
|
||||
} else if (*it == CC_TOSTR(GL_QCOM_shader_framebuffer_fetch_noncoherent)) {
|
||||
_gpuConstantRegistry->mFBF = FBFSupportLevel::NON_COHERENT_QCOM;
|
||||
fbfLevelStr = "NON_COHERENT_QCOM";
|
||||
_features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true;
|
||||
GL_CHECK(glEnable(GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM));
|
||||
}
|
||||
} 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(GL_EXT_debug_marker))) {
|
||||
_gpuConstantRegistry->debugMarker = true;
|
||||
}
|
||||
|
||||
if (checkExtension(CC_TOSTR(ARM_shader_framebuffer_fetch_depth_stencil))) {
|
||||
_features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = true;
|
||||
fbfLevelStr += "_DEPTH_STENCIL";
|
||||
}
|
||||
|
||||
ccstd::string msaaLevelStr = "NONE";
|
||||
#if CC_PLATFORM != CC_PLATFORM_WINDOWS || ALLOW_MULTISAMPLED_RENDER_TO_TEXTURE_ON_DESKTOP
|
||||
if (checkExtension("multisampled_render_to_texture")) {
|
||||
msaaLevelStr = "MSRT1";
|
||||
if (checkExtension("multisampled_render_to_texture2")) {
|
||||
_gpuConstantRegistry->mMSRT = MSRTSupportLevel::LEVEL2;
|
||||
msaaLevelStr = "MSRT2";
|
||||
} else {
|
||||
_gpuConstantRegistry->mMSRT = MSRTSupportLevel::LEVEL1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = true;
|
||||
|
||||
ccstd::string compressedFmts;
|
||||
|
||||
if (getFormatFeatures(Format::ETC_RGB8) != FormatFeature::NONE) {
|
||||
compressedFmts += "etc1 ";
|
||||
}
|
||||
|
||||
compressedFmts += "etc2 ";
|
||||
|
||||
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_UNIFORM_BUFFER_BINDINGS, reinterpret_cast<GLint *>(&_caps.maxUniformBufferBindings));
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, reinterpret_cast<GLint *>(&_caps.maxUniformBlockSize));
|
||||
glGetIntegerv(GL_MAX_DRAW_BUFFERS, reinterpret_cast<GLint *>(&_caps.maxColorRenderTargets));
|
||||
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));
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, reinterpret_cast<GLint *>(&_caps.uboOffsetAlignment));
|
||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, reinterpret_cast<GLint *>(&_caps.maxArrayTextureLayers));
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, reinterpret_cast<GLint *>(&_caps.max3DTextureSize));
|
||||
|
||||
if (_gpuConstantRegistry->glMinorVersion) {
|
||||
glGetIntegerv(GL_MAX_IMAGE_UNITS, reinterpret_cast<GLint *>(&_caps.maxImageUnits));
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, reinterpret_cast<GLint *>(&_caps.maxShaderStorageBlockSize));
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, reinterpret_cast<GLint *>(&_caps.maxShaderStorageBufferBindings));
|
||||
glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, reinterpret_cast<GLint *>(&_caps.maxComputeSharedMemorySize));
|
||||
glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupInvocations));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupSize.x));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupSize.y));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupSize.z));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupCount.x));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupCount.y));
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, reinterpret_cast<GLint *>(&_caps.maxComputeWorkGroupCount.z));
|
||||
}
|
||||
|
||||
if (checkExtension("occlusion_query_boolean")) {
|
||||
_caps.supportQuery = true;
|
||||
}
|
||||
|
||||
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.maxImageUnits, _caps.maxUniformBufferBindings, _caps.maxShaderStorageBufferBindings, _caps.maxVertexAttributes);
|
||||
|
||||
#if CC_USE_PIPELINE_CACHE
|
||||
_pipelineCache = std::make_unique<GLES3PipelineCache>();
|
||||
_pipelineCache->init();
|
||||
#endif
|
||||
|
||||
CC_LOG_INFO("GLES3 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("FRAMEBUFFER_FETCH: %s", fbfLevelStr.c_str());
|
||||
CC_LOG_INFO("MULTI_SAMPLE_RENDER_TO_TEXTURE: %s", msaaLevelStr.c_str());
|
||||
|
||||
if (_xr) {
|
||||
_xr->initializeGLESData(pfnGLES3wLoadProc(), GLES3Device::getInstance()->context());
|
||||
_xr->postGFXDeviceInitialize(_api);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLES3Device::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuFramebufferCacheMap)
|
||||
CC_SAFE_DELETE(_gpuConstantRegistry)
|
||||
CC_SAFE_DELETE(_gpuFramebufferHub)
|
||||
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)
|
||||
|
||||
_pipelineCache.reset();
|
||||
}
|
||||
|
||||
void GLES3Device::acquire(Swapchain *const *swapchains, uint32_t count) {
|
||||
_gpuContext->makeCurrent();
|
||||
|
||||
if (_onAcquire) _onAcquire->execute();
|
||||
|
||||
_swapchains.clear();
|
||||
if (_xr) {
|
||||
GLuint xrFramebuffer = 0;
|
||||
#if XR_OEM_HUAWEIVR
|
||||
stateCache()->glTextures[stateCache()->texUint] = 0;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint *>(&xrFramebuffer));
|
||||
stateCache()->glDrawFramebuffer = xrFramebuffer;
|
||||
#else
|
||||
xr::XRSwapchain xrSwapchain = _xr->doGFXDeviceAcquire(_api);
|
||||
xrFramebuffer = xrSwapchain.glDrawFramebuffer;
|
||||
#endif
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
GL_CHECK(_xr->attachGLESFramebufferTexture2D(););
|
||||
static_cast<GLES3Swapchain *>(swapchains[i])->gpuSwapchain()->glFramebuffer = xrFramebuffer;
|
||||
_swapchains.push_back(static_cast<GLES3Swapchain *>(swapchains[i])->gpuSwapchain());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
_swapchains.push_back(static_cast<GLES3Swapchain *>(swapchains[i])->gpuSwapchain());
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Device::present() {
|
||||
CC_PROFILE(GLES3DevicePresent);
|
||||
auto *queue = static_cast<GLES3Queue *>(_queue);
|
||||
_numDrawCalls = queue->_numDrawCalls;
|
||||
_numInstances = queue->_numInstances;
|
||||
_numTriangles = queue->_numTriangles;
|
||||
|
||||
bool isGFXDeviceNeedsPresent = _xr ? _xr->isGFXDeviceNeedsPresent(_api) : true;
|
||||
for (auto *swapchain : _swapchains) {
|
||||
if (isGFXDeviceNeedsPresent) _gpuContext->present(swapchain);
|
||||
}
|
||||
if (_xr) _xr->postGFXDevicePresent(_api);
|
||||
|
||||
// Clear queue stats
|
||||
queue->_numDrawCalls = 0;
|
||||
queue->_numInstances = 0;
|
||||
queue->_numTriangles = 0;
|
||||
}
|
||||
|
||||
void GLES3Device::bindContext(bool bound) {
|
||||
_gpuContext->bindContext(bound);
|
||||
}
|
||||
|
||||
void GLES3Device::initFormatFeature() {
|
||||
_textureExclusive.fill(true);
|
||||
|
||||
FormatFeature tempFeature = {};
|
||||
|
||||
// builtin
|
||||
tempFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::RENDER_TARGET | FormatFeature::LINEAR_FILTER | FormatFeature::STORAGE_TEXTURE | FormatFeature::VERTEX_ATTRIBUTE;
|
||||
|
||||
_formatFeatures[toNumber(Format::R8)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG8)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB8)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA8)] = tempFeature;
|
||||
|
||||
tempFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::RENDER_TARGET | FormatFeature::LINEAR_FILTER | FormatFeature::STORAGE_TEXTURE;
|
||||
|
||||
_formatFeatures[toNumber(Format::R8SN)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG8SN)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB8SN)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA8SN)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R5G6B5)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA4)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB5A1)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB10A2)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::SRGB8)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::SRGB8_A8)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::R11G11B10F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB9E5)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::DEPTH)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::DEPTH_STENCIL)] = tempFeature;
|
||||
|
||||
tempFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::RENDER_TARGET | FormatFeature::LINEAR_FILTER | FormatFeature::STORAGE_TEXTURE | FormatFeature::VERTEX_ATTRIBUTE;
|
||||
|
||||
_formatFeatures[toNumber(Format::R16F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG16F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB16F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA16F)] = tempFeature;
|
||||
|
||||
tempFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::STORAGE_TEXTURE | FormatFeature::VERTEX_ATTRIBUTE;
|
||||
|
||||
_formatFeatures[toNumber(Format::R32F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG32F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB32F)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA32F)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::RGB10A2UI)] = FormatFeature::RENDER_TARGET | FormatFeature::LINEAR_FILTER | FormatFeature::STORAGE_TEXTURE;
|
||||
|
||||
tempFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::RENDER_TARGET | FormatFeature::LINEAR_FILTER | FormatFeature::STORAGE_TEXTURE | FormatFeature::VERTEX_ATTRIBUTE;
|
||||
|
||||
_formatFeatures[toNumber(Format::R8I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R8UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R16I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R16UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R32I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::R32UI)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::RG8I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG8UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG16I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG16UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG32I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RG32UI)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::RGB8I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB8UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB16I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB16UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB32I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGB32UI)] = tempFeature;
|
||||
|
||||
_formatFeatures[toNumber(Format::RGBA8I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA8UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA16I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA16UI)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA32I)] = tempFeature;
|
||||
_formatFeatures[toNumber(Format::RGBA32UI)] = tempFeature;
|
||||
|
||||
_textureExclusive[toNumber(Format::R8)] = false;
|
||||
_textureExclusive[toNumber(Format::RG8)] = false;
|
||||
_textureExclusive[toNumber(Format::RGB8)] = false;
|
||||
_textureExclusive[toNumber(Format::R5G6B5)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA4)] = false;
|
||||
|
||||
_textureExclusive[toNumber(Format::RGB5A1)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA8)] = false;
|
||||
_textureExclusive[toNumber(Format::RGB10A2)] = false;
|
||||
_textureExclusive[toNumber(Format::RGB10A2UI)] = false;
|
||||
_textureExclusive[toNumber(Format::SRGB8_A8)] = false;
|
||||
|
||||
_textureExclusive[toNumber(Format::R8I)] = false;
|
||||
_textureExclusive[toNumber(Format::R8UI)] = false;
|
||||
_textureExclusive[toNumber(Format::R16I)] = false;
|
||||
_textureExclusive[toNumber(Format::R16UI)] = false;
|
||||
_textureExclusive[toNumber(Format::R32I)] = false;
|
||||
_textureExclusive[toNumber(Format::R32UI)] = false;
|
||||
|
||||
_textureExclusive[toNumber(Format::RG8I)] = false;
|
||||
_textureExclusive[toNumber(Format::RG8UI)] = false;
|
||||
_textureExclusive[toNumber(Format::RG16I)] = false;
|
||||
_textureExclusive[toNumber(Format::RG16UI)] = false;
|
||||
_textureExclusive[toNumber(Format::RG32I)] = false;
|
||||
_textureExclusive[toNumber(Format::RG32UI)] = false;
|
||||
|
||||
_textureExclusive[toNumber(Format::RGBA8I)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA8UI)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA16I)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA16UI)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA32I)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA32UI)] = false;
|
||||
|
||||
_textureExclusive[toNumber(Format::DEPTH)] = false;
|
||||
_textureExclusive[toNumber(Format::DEPTH_STENCIL)] = false;
|
||||
|
||||
if (checkExtension("render_snorm")) {
|
||||
// https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_render_snorm.txt
|
||||
// For 16, see https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_norm16.txt
|
||||
_textureExclusive[toNumber(Format::R8SN)] = false;
|
||||
_textureExclusive[toNumber(Format::RG8SN)] = false;
|
||||
_textureExclusive[toNumber(Format::RGB8SN)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA8SN)] = false;
|
||||
}
|
||||
|
||||
if (checkExtension("color_buffer_float")) {
|
||||
_formatFeatures[toNumber(Format::R32F)] |= FormatFeature::RENDER_TARGET;
|
||||
_formatFeatures[toNumber(Format::RG32F)] |= FormatFeature::RENDER_TARGET;
|
||||
_formatFeatures[toNumber(Format::RGBA32F)] |= FormatFeature::RENDER_TARGET;
|
||||
|
||||
_textureExclusive[toNumber(Format::R32F)] = false;
|
||||
_textureExclusive[toNumber(Format::RG32F)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA32F)] = false;
|
||||
}
|
||||
if (checkExtension("color_buffer_half_float")) {
|
||||
_textureExclusive[toNumber(Format::R16F)] = false;
|
||||
_textureExclusive[toNumber(Format::RG16F)] = false;
|
||||
_textureExclusive[toNumber(Format::RGB16F)] = false;
|
||||
_textureExclusive[toNumber(Format::RGBA16F)] = false;
|
||||
}
|
||||
|
||||
if (checkExtension("texture_float_linear")) {
|
||||
_formatFeatures[toNumber(Format::RGB32F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::RGBA32F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::R32F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::RG32F)] |= FormatFeature::LINEAR_FILTER;
|
||||
}
|
||||
|
||||
if (checkExtension("texture_half_float_linear")) {
|
||||
_formatFeatures[toNumber(Format::RGB16F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::RGBA16F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::R16F)] |= FormatFeature::LINEAR_FILTER;
|
||||
_formatFeatures[toNumber(Format::RG16F)] |= FormatFeature::LINEAR_FILTER;
|
||||
}
|
||||
|
||||
const FormatFeature compressedFeature = FormatFeature::SAMPLED_TEXTURE | FormatFeature::LINEAR_FILTER;
|
||||
|
||||
if (checkExtension("compressed_ETC1")) {
|
||||
_formatFeatures[toNumber(Format::ETC_RGB8)] = compressedFeature;
|
||||
}
|
||||
|
||||
_formatFeatures[toNumber(Format::ETC2_RGB8)] = compressedFeature;
|
||||
_formatFeatures[toNumber(Format::ETC2_RGBA8)] = compressedFeature;
|
||||
_formatFeatures[toNumber(Format::ETC2_SRGB8)] = compressedFeature;
|
||||
_formatFeatures[toNumber(Format::ETC2_SRGB8_A8)] = compressedFeature;
|
||||
_formatFeatures[toNumber(Format::ETC2_RGB8_A1)] = compressedFeature;
|
||||
_formatFeatures[toNumber(Format::ETC2_SRGB8_A1)] = 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 *GLES3Device::createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) {
|
||||
if (hasAgent || info.type == CommandBufferType::PRIMARY) return ccnew GLES3PrimaryCommandBuffer;
|
||||
return ccnew GLES3CommandBuffer;
|
||||
}
|
||||
|
||||
Queue *GLES3Device::createQueue() {
|
||||
return ccnew GLES3Queue;
|
||||
}
|
||||
|
||||
QueryPool *GLES3Device::createQueryPool() {
|
||||
return ccnew GLES3QueryPool;
|
||||
}
|
||||
|
||||
Swapchain *GLES3Device::createSwapchain() {
|
||||
if (_xr) {
|
||||
_xr->createXRSwapchains();
|
||||
}
|
||||
return ccnew GLES3Swapchain;
|
||||
}
|
||||
|
||||
Buffer *GLES3Device::createBuffer() {
|
||||
return ccnew GLES3Buffer;
|
||||
}
|
||||
|
||||
Texture *GLES3Device::createTexture() {
|
||||
return ccnew GLES3Texture;
|
||||
}
|
||||
|
||||
Shader *GLES3Device::createShader() {
|
||||
return ccnew GLES3Shader;
|
||||
}
|
||||
|
||||
InputAssembler *GLES3Device::createInputAssembler() {
|
||||
return ccnew GLES3InputAssembler;
|
||||
}
|
||||
|
||||
RenderPass *GLES3Device::createRenderPass() {
|
||||
return ccnew GLES3RenderPass;
|
||||
}
|
||||
|
||||
Framebuffer *GLES3Device::createFramebuffer() {
|
||||
return ccnew GLES3Framebuffer;
|
||||
}
|
||||
|
||||
DescriptorSet *GLES3Device::createDescriptorSet() {
|
||||
return ccnew GLES3DescriptorSet;
|
||||
}
|
||||
|
||||
DescriptorSetLayout *GLES3Device::createDescriptorSetLayout() {
|
||||
return ccnew GLES3DescriptorSetLayout;
|
||||
}
|
||||
|
||||
PipelineLayout *GLES3Device::createPipelineLayout() {
|
||||
return ccnew GLES3PipelineLayout;
|
||||
}
|
||||
|
||||
PipelineState *GLES3Device::createPipelineState() {
|
||||
return ccnew GLES3PipelineState;
|
||||
}
|
||||
|
||||
Sampler *GLES3Device::createSampler(const SamplerInfo &info) {
|
||||
return ccnew GLES3Sampler(info);
|
||||
}
|
||||
|
||||
GeneralBarrier *GLES3Device::createGeneralBarrier(const GeneralBarrierInfo &info) {
|
||||
return ccnew GLES3GeneralBarrier(info);
|
||||
}
|
||||
|
||||
void GLES3Device::copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) {
|
||||
CC_PROFILE(GLES3DeviceCopyBuffersToTexture);
|
||||
cmdFuncGLES3CopyBuffersToTexture(this, buffers, static_cast<GLES3Texture *>(dst)->gpuTexture(), regions, count);
|
||||
}
|
||||
|
||||
void GLES3Device::copyTextureToBuffers(Texture *srcTexture, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) {
|
||||
CC_PROFILE(GLES3DeviceCopyTextureToBuffers);
|
||||
cmdFuncGLES3CopyTextureToBuffers(this, static_cast<GLES3Texture *>(srcTexture)->gpuTextureView(), buffers, regions, count);
|
||||
}
|
||||
|
||||
void GLES3Device::getQueryPoolResults(QueryPool *queryPool) {
|
||||
CC_PROFILE(GLES3DeviceGetQueryPoolResults);
|
||||
auto *cmdBuff = static_cast<GLES3CommandBuffer *>(getCommandBuffer());
|
||||
cmdBuff->getQueryPoolResults(queryPool);
|
||||
}
|
||||
|
||||
SampleCount GLES3Device::getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const {
|
||||
return static_cast<SampleCount>(cmdFuncGLES3GetMaxSampleCount(this, format, usage, flags));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
157
cocos/renderer/gfx-gles3/GLES3Device.h
Normal file
157
cocos/renderer/gfx-gles3/GLES3Device.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "base/std/any.h"
|
||||
#include "gfx-base/GFXDevice.h"
|
||||
#include "gfx-gles-common/GLESCommandPool.h"
|
||||
|
||||
namespace cc {
|
||||
class IXRInterface;
|
||||
namespace gfx {
|
||||
|
||||
class GLES3GPUContext;
|
||||
struct GLES3GPUSwapchain;
|
||||
class GLES3GPUStateCache;
|
||||
class GLES3GPUFramebufferHub;
|
||||
struct GLES3GPUConstantRegistry;
|
||||
class GLES3GPUFramebufferCacheMap;
|
||||
class GLES3PipelineCache;
|
||||
|
||||
class CC_GLES3_API GLES3Device final : public Device {
|
||||
public:
|
||||
static GLES3Device *getInstance();
|
||||
|
||||
~GLES3Device() 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::createSwapchain;
|
||||
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 GLES3GPUContext *context() const { return _gpuContext; }
|
||||
inline GLES3GPUStateCache *stateCache() const { return _gpuStateCache; }
|
||||
inline GLES3GPUFramebufferHub *framebufferHub() const { return _gpuFramebufferHub; }
|
||||
inline GLES3GPUConstantRegistry *constantRegistry() const { return _gpuConstantRegistry; }
|
||||
inline GLES3GPUFramebufferCacheMap *framebufferCacheMap() const { return _gpuFramebufferCacheMap; }
|
||||
inline GLES3PipelineCache *pipelineCache() const { return _pipelineCache.get(); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline bool isTextureExclusive(const Format &format) const { return _textureExclusive[static_cast<size_t>(format)]; };
|
||||
SampleCount getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const override;
|
||||
protected:
|
||||
static GLES3Device *instance;
|
||||
|
||||
friend class DeviceManager;
|
||||
|
||||
GLES3Device();
|
||||
|
||||
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;
|
||||
GeneralBarrier *createGeneralBarrier(const GeneralBarrierInfo &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();
|
||||
|
||||
GLES3GPUContext *_gpuContext{nullptr};
|
||||
GLES3GPUStateCache *_gpuStateCache{nullptr};
|
||||
GLES3GPUFramebufferHub *_gpuFramebufferHub{nullptr};
|
||||
GLES3GPUConstantRegistry *_gpuConstantRegistry{nullptr};
|
||||
GLES3GPUFramebufferCacheMap *_gpuFramebufferCacheMap{nullptr};
|
||||
std::unique_ptr<GLES3PipelineCache> _pipelineCache;
|
||||
|
||||
ccstd::vector<GLES3GPUSwapchain *> _swapchains;
|
||||
|
||||
GLESBindingMapping _bindingMappings;
|
||||
|
||||
ccstd::vector<ccstd::string> _extensions;
|
||||
|
||||
ccstd::array<bool, static_cast<size_t>(Format::COUNT)> _textureExclusive;
|
||||
|
||||
uint8_t *_stagingBuffer{nullptr};
|
||||
uint32_t _stagingBufferSize{0};
|
||||
|
||||
IXRInterface *_xr{nullptr};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
108
cocos/renderer/gfx-gles3/GLES3Framebuffer.cpp
Normal file
108
cocos/renderer/gfx-gles3/GLES3Framebuffer.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Framebuffer.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "GLES3Texture.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Framebuffer::GLES3Framebuffer() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Framebuffer::~GLES3Framebuffer() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3Framebuffer::updateExtent() {
|
||||
if (!_colorTextures.empty()) {
|
||||
const auto *tex = _colorTextures[0];
|
||||
_gpuFBO->width = tex->getWidth();
|
||||
_gpuFBO->height = tex->getHeight();
|
||||
return;
|
||||
}
|
||||
if (_depthStencilTexture != nullptr) {
|
||||
_gpuFBO->width = _depthStencilTexture->getWidth();
|
||||
_gpuFBO->height = _depthStencilTexture->getHeight();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Framebuffer::doInit(const FramebufferInfo & /*info*/) {
|
||||
_gpuFBO = ccnew GLES3GPUFramebuffer;
|
||||
updateExtent();
|
||||
|
||||
_gpuFBO->gpuRenderPass = static_cast<GLES3RenderPass *>(_renderPass)->gpuRenderPass();
|
||||
_gpuFBO->gpuColorViews.resize(_colorTextures.size());
|
||||
for (size_t i = 0; i < _colorTextures.size(); ++i) {
|
||||
auto *colorTexture = static_cast<GLES3Texture *>(_colorTextures.at(i));
|
||||
_gpuFBO->gpuColorViews[i] = colorTexture->gpuTextureView();
|
||||
GLES3Device::getInstance()->framebufferHub()->connect(colorTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
|
||||
if (_depthStencilTexture) {
|
||||
auto *depthTexture = static_cast<GLES3Texture *>(_depthStencilTexture);
|
||||
_gpuFBO->gpuDepthStencilView = depthTexture->gpuTextureView();
|
||||
GLES3Device::getInstance()->framebufferHub()->connect(depthTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
|
||||
if (_depthStencilResolveTexture) {
|
||||
auto *depthTexture = static_cast<GLES3Texture *>(_depthStencilResolveTexture);
|
||||
_gpuFBO->gpuDepthStencilResolveView = depthTexture->gpuTextureView();
|
||||
GLES3Device::getInstance()->framebufferHub()->connect(depthTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
|
||||
cmdFuncGLES3CreateFramebuffer(GLES3Device::getInstance(), _gpuFBO);
|
||||
}
|
||||
|
||||
void GLES3Framebuffer::doDestroy() {
|
||||
if (_gpuFBO) {
|
||||
cmdFuncGLES3DestroyFramebuffer(GLES3Device::getInstance(), _gpuFBO);
|
||||
|
||||
for (auto &texture : _colorTextures) {
|
||||
auto *colorTexture = static_cast<GLES3Texture *>(texture);
|
||||
GLES3Device::getInstance()->framebufferHub()->disengage(colorTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
if (_depthStencilTexture) {
|
||||
auto *depthTexture = static_cast<GLES3Texture *>(_depthStencilTexture);
|
||||
GLES3Device::getInstance()->framebufferHub()->disengage(depthTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
if (_depthStencilResolveTexture) {
|
||||
auto *depthTexture = static_cast<GLES3Texture *>(_depthStencilResolveTexture);
|
||||
GLES3Device::getInstance()->framebufferHub()->disengage(depthTexture->gpuTexture(), _gpuFBO);
|
||||
}
|
||||
|
||||
delete _gpuFBO;
|
||||
_gpuFBO = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
51
cocos/renderer/gfx-gles3/GLES3Framebuffer.h
Normal file
51
cocos/renderer/gfx-gles3/GLES3Framebuffer.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXFramebuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GLES3GPUFramebuffer;
|
||||
|
||||
class CC_GLES3_API GLES3Framebuffer final : public Framebuffer {
|
||||
public:
|
||||
GLES3Framebuffer();
|
||||
~GLES3Framebuffer() override;
|
||||
|
||||
inline GLES3GPUFramebuffer *gpuFBO() const { return _gpuFBO; }
|
||||
|
||||
protected:
|
||||
void doInit(const FramebufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
void updateExtent();
|
||||
|
||||
GLES3GPUFramebuffer *_gpuFBO = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
453
cocos/renderer/gfx-gles3/GLES3GPUContext.cpp
Normal file
453
cocos/renderer/gfx-gles3/GLES3GPUContext.cpp
Normal file
@@ -0,0 +1,453 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3GPUObjects.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 GLES3EGLDebugProc(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 GLES3GPUContext::initialize(GLES3GPUStateCache *stateCache, GLES3GPUConstantRegistry *constantRegistry) {
|
||||
_stateCache = stateCache;
|
||||
_constantRegistry = constantRegistry;
|
||||
|
||||
if (!gles3wInit()) {
|
||||
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_ES3_BIT_KHR,
|
||||
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;
|
||||
|
||||
success = eglChooseConfig(eglDisplay, defaultAttribs, nullptr, 0, &numConfig);
|
||||
if (success) {
|
||||
eglConfigs.resize(numConfig);
|
||||
} else {
|
||||
CC_LOG_ERROR("Query GLES3 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++) {
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_RED_SIZE, ¶ms[0]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_GREEN_SIZE, ¶ms[1]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_BLUE_SIZE, ¶ms[2]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_ALPHA_SIZE, ¶ms[3]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_DEPTH_SIZE, ¶ms[4]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_STENCIL_SIZE, ¶ms[5]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_SAMPLE_BUFFERS, ¶ms[6]);
|
||||
eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_SAMPLES, ¶ms[7]);
|
||||
int bNonLinearDepth = 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(3);
|
||||
eglAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
|
||||
eglAttributes.push_back(2);
|
||||
#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);
|
||||
|
||||
for (int m = 2; m >= 0; --m) {
|
||||
eglAttributes[3] = m;
|
||||
eglDefaultContext = eglCreateContext(eglDisplay, eglConfig, nullptr, eglAttributes.data());
|
||||
EGLint err = eglGetError(); // QNX throws egl errors on mismatch
|
||||
if (eglDefaultContext && err == EGL_SUCCESS) {
|
||||
_constantRegistry->glMinorVersion = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eglAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
|
||||
eglAttributes.push_back(3);
|
||||
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 GLES3GPUContext::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;
|
||||
}
|
||||
|
||||
gles3wExit();
|
||||
}
|
||||
|
||||
void GLES3GPUContext::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 GLES3GPUContext::makeCurrent(const GLES3GPUSwapchain *drawSwapchain, const GLES3GPUSwapchain *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 GLES3GPUContext::present(const GLES3GPUSwapchain *swapchain) {
|
||||
#if CC_SWAPPY_ENABLED
|
||||
if (swapchain->swappyEnabled) {
|
||||
// fallback to normal eglswap if swappy swap failed.
|
||||
if (SwappyGL_swap(eglDisplay, swapchain->eglSurface)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// For an example, 2 windows changed to background will cause the eglSurface of both destroyed,
|
||||
// and then make one of them foreground, and the other window's eglSurface will stays EGL_NO_SURFACE.
|
||||
// But in GLES3Device::present it iterates all swapchains, and now the second window containing the invalid surface exists.
|
||||
if (swapchain->eglSurface == EGL_NO_SURFACE) {
|
||||
return;
|
||||
}
|
||||
if (_eglCurrentInterval != swapchain->eglSwapInterval) {
|
||||
if (!eglSwapInterval(eglDisplay, swapchain->eglSwapInterval)) {
|
||||
CC_LOG_ERROR("eglSwapInterval() - FAILED.");
|
||||
}
|
||||
|
||||
_eglCurrentInterval = swapchain->eglSwapInterval;
|
||||
}
|
||||
makeCurrent(swapchain, swapchain);
|
||||
EGL_CHECK(eglSwapBuffers(eglDisplay, swapchain->eglSurface));
|
||||
}
|
||||
|
||||
EGLContext GLES3GPUContext::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 GLES3GPUContext::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;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-readability-function-size, readability-function-size)
|
||||
void GLES3GPUContext::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));
|
||||
|
||||
GL_CHECK(glBindVertexArray(0));
|
||||
|
||||
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, 0));
|
||||
|
||||
if (_constantRegistry->glMinorVersion) {
|
||||
GL_CHECK(glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0));
|
||||
GL_CHECK(glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0));
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
|
||||
}
|
||||
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_3D, 0));
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, 0));
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
|
||||
GL_CHECK(glBindFramebuffer(GL_DRAW_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(GLES3EGLDebugProc, 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
|
||||
686
cocos/renderer/gfx-gles3/GLES3GPUObjects.h
Normal file
686
cocos/renderer/gfx-gles3/GLES3GPUObjects.h
Normal file
@@ -0,0 +1,686 @@
|
||||
/****************************************************************************
|
||||
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 <unordered_map>
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
#include "gfx-base/GFXDeviceObject.h"
|
||||
#include "gfx-gles-common/GLESCommandPool.h"
|
||||
|
||||
#include "GLES3Std.h"
|
||||
#include "GLES3Wrangler.h"
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUConstantRegistry {
|
||||
size_t currentBoundThreadID{0U};
|
||||
uint32_t glMinorVersion{0U};
|
||||
|
||||
MSRTSupportLevel mMSRT{MSRTSupportLevel::NONE};
|
||||
FBFSupportLevel mFBF{FBFSupportLevel::NONE};
|
||||
bool debugMarker = false;
|
||||
};
|
||||
|
||||
class GLES3GPUStateCache;
|
||||
struct GLES3GPUSwapchain;
|
||||
class GLES3GPUContext final {
|
||||
public:
|
||||
bool initialize(GLES3GPUStateCache *stateCache, GLES3GPUConstantRegistry *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 GLES3GPUSwapchain *drawSwapchain = nullptr, const GLES3GPUSwapchain *readSwapchain = nullptr);
|
||||
void bindContext(bool bound); // for context switching between threads
|
||||
|
||||
void present(const GLES3GPUSwapchain *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};
|
||||
|
||||
GLES3GPUStateCache *_stateCache{nullptr};
|
||||
GLES3GPUConstantRegistry *_constantRegistry{nullptr};
|
||||
|
||||
ccstd::unordered_map<size_t, EGLContext> _sharedContexts;
|
||||
|
||||
ccstd::vector<ccstd::string> _extensions;
|
||||
};
|
||||
|
||||
class GLES3GPUQueryPool final {
|
||||
public:
|
||||
QueryType type{QueryType::OCCLUSION};
|
||||
uint32_t maxQueryObjects{0};
|
||||
bool forceWait{true};
|
||||
ccstd::vector<GLuint> glQueryIds;
|
||||
|
||||
inline GLuint mapGLQueryId(uint32_t queryId) {
|
||||
if (queryId < maxQueryObjects) {
|
||||
return glQueryIds[queryId];
|
||||
}
|
||||
|
||||
return UINT_MAX;
|
||||
}
|
||||
};
|
||||
|
||||
struct GLES3GPUBuffer {
|
||||
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;
|
||||
GLuint glOffset = 0;
|
||||
uint8_t *buffer = nullptr;
|
||||
DrawInfoList indirects;
|
||||
};
|
||||
using GLES3GPUBufferList = ccstd::vector<GLES3GPUBuffer *>;
|
||||
|
||||
struct GLES3GPUTexture {
|
||||
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};
|
||||
TextureFlags flags{TextureFlagBit::NONE};
|
||||
bool immutable{true};
|
||||
bool isPowerOf2{false};
|
||||
bool useRenderBuffer{false};
|
||||
bool memoryAllocated{true}; // false if swapchain image or implicit ms render buffer.
|
||||
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};
|
||||
GLES3GPUSwapchain *swapchain{nullptr};
|
||||
};
|
||||
|
||||
struct GLES3GPUTextureView {
|
||||
GLES3GPUTexture *gpuTexture{nullptr};
|
||||
TextureType type = TextureType::TEX2D;
|
||||
Format format = Format::UNKNOWN;
|
||||
uint32_t baseLevel = 0U;
|
||||
uint32_t levelCount = 1U;
|
||||
uint32_t baseLayer = 0U;
|
||||
uint32_t layerCount = 1U;
|
||||
uint32_t basePlane = 0U;
|
||||
uint32_t planeCount = 0U;
|
||||
GLenum glTarget{0};
|
||||
};
|
||||
|
||||
using GLES3GPUTextureViewList = ccstd::vector<GLES3GPUTextureView *>;
|
||||
|
||||
struct GLES3GPUSwapchain {
|
||||
#if CC_SWAPPY_ENABLED
|
||||
bool swappyEnabled{false};
|
||||
#endif
|
||||
EGLSurface eglSurface{EGL_NO_SURFACE};
|
||||
EGLint eglSwapInterval{0};
|
||||
GLuint glFramebuffer{0};
|
||||
GLES3GPUTexture *gpuColorTexture{nullptr};
|
||||
bool isXR{false};
|
||||
};
|
||||
|
||||
class GLES3GPUSampler final {
|
||||
public:
|
||||
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;
|
||||
|
||||
~GLES3GPUSampler() {
|
||||
ccstd::vector<GLuint> glSampelrs;
|
||||
for (const auto &pair : _cache) {
|
||||
glSampelrs.push_back(pair.second);
|
||||
}
|
||||
GL_CHECK(glDeleteSamplers(static_cast<GLsizei>(glSampelrs.size()), glSampelrs.data()));
|
||||
}
|
||||
|
||||
GLuint getGLSampler(uint16_t minLod, uint16_t maxLod);
|
||||
|
||||
private:
|
||||
ccstd::unordered_map<uint32_t, GLuint> _cache;
|
||||
};
|
||||
|
||||
struct GLES3GPUInput {
|
||||
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 GLES3GPUInputList = ccstd::vector<GLES3GPUInput>;
|
||||
|
||||
struct GLES3GPUUniform {
|
||||
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;
|
||||
};
|
||||
using GLES3GPUUniformList = ccstd::vector<GLES3GPUUniform>;
|
||||
|
||||
struct GLES3GPUUniformBuffer {
|
||||
uint32_t set = INVALID_BINDING;
|
||||
uint32_t binding = INVALID_BINDING;
|
||||
ccstd::string name;
|
||||
uint32_t size = 0;
|
||||
uint32_t glBinding = 0xffffffff;
|
||||
bool isStorage = false;
|
||||
};
|
||||
using GLES3GPUUniformBufferList = ccstd::vector<GLES3GPUUniformBuffer>;
|
||||
|
||||
struct GLES3GPUUniformSamplerTexture {
|
||||
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 GLES3GPUUniformSamplerTextureList = ccstd::vector<GLES3GPUUniformSamplerTexture>;
|
||||
|
||||
struct GLES3GPUUniformStorageImage {
|
||||
uint32_t set = 0;
|
||||
uint32_t binding = 0;
|
||||
ccstd::string name;
|
||||
Type type = Type::UNKNOWN;
|
||||
uint32_t count = 0U;
|
||||
|
||||
ccstd::vector<int> units;
|
||||
GLenum glMemoryAccess = GL_READ_WRITE;
|
||||
GLint glLoc = -1;
|
||||
};
|
||||
using GLES3GPUUniformStorageImageList = ccstd::vector<GLES3GPUUniformStorageImage>;
|
||||
|
||||
struct GLES3GPUShaderStage {
|
||||
GLES3GPUShaderStage(ShaderStageFlagBit t, ccstd::string s, GLuint shader = 0)
|
||||
: type(t),
|
||||
source(std::move(std::move(s))),
|
||||
glShader(shader) {}
|
||||
ShaderStageFlagBit type;
|
||||
ccstd::string source;
|
||||
GLuint glShader = 0;
|
||||
};
|
||||
using GLES3GPUShaderStageList = ccstd::vector<GLES3GPUShaderStage>;
|
||||
|
||||
struct GLES3GPUShader {
|
||||
ccstd::string name;
|
||||
UniformBlockList blocks;
|
||||
UniformStorageBufferList buffers;
|
||||
UniformSamplerTextureList samplerTextures;
|
||||
UniformSamplerList samplers;
|
||||
UniformTextureList textures;
|
||||
UniformStorageImageList images;
|
||||
UniformInputAttachmentList subpassInputs;
|
||||
|
||||
GLES3GPUShaderStageList gpuStages;
|
||||
GLuint glProgram = 0;
|
||||
ccstd::hash_t hash = INVALID_SHADER_HASH;
|
||||
GLES3GPUInputList glInputs;
|
||||
GLES3GPUUniformBufferList glBuffers;
|
||||
GLES3GPUUniformSamplerTextureList glSamplerTextures;
|
||||
GLES3GPUUniformStorageImageList glImages;
|
||||
};
|
||||
|
||||
struct GLES3GPUAttribute {
|
||||
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 GLES3GPUAttributeList = ccstd::vector<GLES3GPUAttribute>;
|
||||
|
||||
struct GLES3GPUInputAssembler {
|
||||
AttributeList attributes;
|
||||
GLES3GPUBufferList gpuVertexBuffers;
|
||||
GLES3GPUBuffer *gpuIndexBuffer = nullptr;
|
||||
GLES3GPUBuffer *gpuIndirectBuffer = nullptr;
|
||||
GLES3GPUAttributeList glAttribs;
|
||||
GLenum glIndexType = 0;
|
||||
ccstd::unordered_map<size_t, GLuint> glVAOs;
|
||||
};
|
||||
|
||||
struct GLES3GPUGeneralBarrier {
|
||||
AccessFlags prevAccesses = AccessFlagBit::NONE;
|
||||
AccessFlags nextAccesses = AccessFlagBit::NONE;
|
||||
|
||||
GLbitfield glBarriers = 0U;
|
||||
GLbitfield glBarriersByRegion = 0U;
|
||||
};
|
||||
|
||||
using DrawBuffer = ccstd::vector<GLenum>;
|
||||
struct GLES3GPURenderPass {
|
||||
ColorAttachmentList colorAttachments;
|
||||
DepthStencilAttachment depthStencilAttachment;
|
||||
DepthStencilAttachment depthStencilResolveAttachment;
|
||||
SubpassInfoList subpasses;
|
||||
SubpassDependencyList dependencies;
|
||||
|
||||
ccstd::vector<uint32_t> colors;
|
||||
ccstd::vector<uint32_t> resolves;
|
||||
uint32_t depthStencil = INVALID_BINDING;
|
||||
uint32_t depthStencilResolve = INVALID_BINDING;
|
||||
ccstd::vector<uint32_t> indices; // offsets to GL_COLOR_ATTACHMENT_0
|
||||
ccstd::vector<DrawBuffer> drawBuffers;
|
||||
};
|
||||
|
||||
class GLES3GPUFramebufferCacheMap;
|
||||
struct GLES3GPUFramebufferObject {
|
||||
void initialize(GLES3GPUSwapchain *swc = nullptr);
|
||||
|
||||
void bindColor(const GLES3GPUTextureView *texture, uint32_t colorIndex, const ColorAttachment &attachment);
|
||||
void bindColorMultiSample(const GLES3GPUTextureView *texture, uint32_t colorIndex, GLint samples, const ColorAttachment &attachment);
|
||||
void bindDepthStencil(const GLES3GPUTextureView *texture, const DepthStencilAttachment &attachment);
|
||||
void bindDepthStencilMultiSample(const GLES3GPUTextureView *texture, GLint samples, const DepthStencilAttachment &attachment);
|
||||
|
||||
bool isActive() const;
|
||||
void finalize(GLES3GPUStateCache *cache);
|
||||
void processLoad(GLenum target);
|
||||
void processStore(GLenum target);
|
||||
void destroy(GLES3GPUStateCache *cache, GLES3GPUFramebufferCacheMap *framebufferCacheMap);
|
||||
GLuint getHandle() const { return swapchain != nullptr ? swapchain->glFramebuffer : handle; }
|
||||
|
||||
using Reference = std::pair<const GLES3GPUTextureView*, GLint>;
|
||||
|
||||
GLES3GPUSwapchain *swapchain{nullptr};
|
||||
|
||||
ccstd::vector<Reference> colors;
|
||||
Reference depthStencil{nullptr, 1};
|
||||
GLenum dsAttachment{GL_NONE};
|
||||
|
||||
ccstd::vector<GLenum> loadInvalidates;
|
||||
ccstd::vector<GLenum> storeInvalidates;
|
||||
private:
|
||||
GLuint handle{0};
|
||||
};
|
||||
|
||||
class GLES3GPUFramebuffer final {
|
||||
public:
|
||||
GLES3GPURenderPass *gpuRenderPass{nullptr};
|
||||
GLES3GPUTextureViewList gpuColorViews;
|
||||
GLES3GPUTextureView *gpuDepthStencilView{nullptr};
|
||||
GLES3GPUTextureView *gpuDepthStencilResolveView{nullptr};
|
||||
|
||||
uint32_t width{UINT_MAX};
|
||||
uint32_t height{UINT_MAX};
|
||||
GLbitfield dsResolveMask = 0;
|
||||
std::vector<std::pair<uint32_t, uint32_t>> colorBlitPairs;
|
||||
GLES3GPUFramebufferObject framebuffer;
|
||||
GLES3GPUFramebufferObject resolveFramebuffer;
|
||||
};
|
||||
|
||||
struct GLES3GPUDescriptorSetLayout {
|
||||
DescriptorSetLayoutBindingList bindings;
|
||||
ccstd::vector<uint32_t> dynamicBindings;
|
||||
|
||||
ccstd::vector<uint32_t> bindingIndices;
|
||||
ccstd::vector<uint32_t> descriptorIndices;
|
||||
uint32_t descriptorCount = 0U;
|
||||
ccstd::hash_t hash = 0U;
|
||||
};
|
||||
using GLES3GPUDescriptorSetLayoutList = ccstd::vector<GLES3GPUDescriptorSetLayout *>;
|
||||
|
||||
struct GLES3GPUPipelineLayout {
|
||||
GLES3GPUDescriptorSetLayoutList setLayouts;
|
||||
|
||||
// helper storages
|
||||
ccstd::vector<ccstd::vector<int>> dynamicOffsetIndices;
|
||||
ccstd::vector<uint32_t> dynamicOffsetOffsets;
|
||||
ccstd::vector<uint32_t> dynamicOffsets;
|
||||
uint32_t dynamicOffsetCount = 0U;
|
||||
ccstd::hash_t hash = 0U;
|
||||
};
|
||||
|
||||
struct GLES3GPUPipelineState {
|
||||
GLenum glPrimitive = GL_TRIANGLES;
|
||||
GLES3GPUShader *gpuShader = nullptr;
|
||||
RasterizerState rs;
|
||||
DepthStencilState dss;
|
||||
BlendState bs;
|
||||
DynamicStateList dynamicStates;
|
||||
GLES3GPUPipelineLayout *gpuLayout = nullptr;
|
||||
GLES3GPURenderPass *gpuRenderPass = nullptr;
|
||||
GLES3GPUPipelineLayout *gpuPipelineLayout = nullptr;
|
||||
};
|
||||
|
||||
struct GLES3GPUDescriptor {
|
||||
DescriptorType type = DescriptorType::UNKNOWN;
|
||||
GLES3GPUBuffer *gpuBuffer = nullptr;
|
||||
GLES3GPUTextureView *gpuTextureView = nullptr;
|
||||
GLES3GPUSampler *gpuSampler = nullptr;
|
||||
};
|
||||
using GLES3GPUDescriptorList = ccstd::vector<GLES3GPUDescriptor>;
|
||||
|
||||
struct GLES3GPUDescriptorSet {
|
||||
GLES3GPUDescriptorList gpuDescriptors;
|
||||
const ccstd::vector<uint32_t> *descriptorIndices = nullptr;
|
||||
};
|
||||
|
||||
struct GLES3GPUDispatchInfo {
|
||||
uint32_t groupCountX = 0;
|
||||
uint32_t groupCountY = 0;
|
||||
uint32_t groupCountZ = 0;
|
||||
|
||||
GLES3GPUBuffer *indirectBuffer = nullptr;
|
||||
uint32_t indirectOffset = 0;
|
||||
};
|
||||
|
||||
struct GLES3ObjectCache {
|
||||
uint32_t subpassIdx = 0U;
|
||||
GLES3GPURenderPass *gpuRenderPass = nullptr;
|
||||
GLES3GPUFramebuffer *gpuFramebuffer = nullptr;
|
||||
GLES3GPUPipelineState *gpuPipelineState = nullptr;
|
||||
GLES3GPUInputAssembler *gpuInputAssembler = nullptr;
|
||||
GLenum glPrimitive = 0;
|
||||
Rect renderArea;
|
||||
ColorList clearColors;
|
||||
float clearDepth = 1.F;
|
||||
uint32_t clearStencil = 0U;
|
||||
};
|
||||
|
||||
class GLES3GPUStateCache final {
|
||||
public:
|
||||
GLuint glArrayBuffer = 0;
|
||||
GLuint glElementArrayBuffer = 0;
|
||||
GLuint glUniformBuffer = 0;
|
||||
ccstd::vector<GLuint> glBindUBOs;
|
||||
ccstd::vector<GLuint> glBindUBOOffsets;
|
||||
GLuint glShaderStorageBuffer = 0;
|
||||
ccstd::vector<GLuint> glBindSSBOs;
|
||||
ccstd::vector<GLuint> glBindSSBOOffsets;
|
||||
GLuint glDispatchIndirectBuffer = 0;
|
||||
GLuint glVAO = 0;
|
||||
uint32_t texUint = 0;
|
||||
ccstd::vector<GLuint> glTextures;
|
||||
ccstd::vector<GLuint> glImages;
|
||||
ccstd::vector<GLuint> glSamplers;
|
||||
GLuint glProgram = 0;
|
||||
ccstd::vector<bool> glEnabledAttribLocs;
|
||||
ccstd::vector<bool> glCurrentAttribLocs;
|
||||
GLuint glReadFramebuffer = 0;
|
||||
GLuint glDrawFramebuffer = 0;
|
||||
GLuint glRenderbuffer = 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;
|
||||
GLES3ObjectCache gfxStateCache;
|
||||
|
||||
void initialize(size_t texUnits, size_t imageUnits, size_t uboBindings, size_t ssboBindings, size_t vertexAttributes) {
|
||||
glBindUBOs.resize(uboBindings, 0U);
|
||||
glBindUBOOffsets.resize(uboBindings, 0U);
|
||||
glBindSSBOs.resize(ssboBindings, 0U);
|
||||
glBindSSBOOffsets.resize(ssboBindings, 0U);
|
||||
glTextures.resize(texUnits, 0U);
|
||||
glSamplers.resize(texUnits, 0U);
|
||||
glImages.resize(imageUnits, 0U);
|
||||
glEnabledAttribLocs.resize(vertexAttributes, false);
|
||||
glCurrentAttribLocs.resize(vertexAttributes, false);
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (!_initialized) return;
|
||||
|
||||
glArrayBuffer = 0;
|
||||
glElementArrayBuffer = 0;
|
||||
glUniformBuffer = 0;
|
||||
glBindUBOs.assign(glBindUBOs.size(), 0U);
|
||||
glBindUBOOffsets.assign(glBindUBOOffsets.size(), 0U);
|
||||
glShaderStorageBuffer = 0;
|
||||
glBindSSBOs.assign(glBindSSBOs.size(), 0U);
|
||||
glBindSSBOOffsets.assign(glBindSSBOOffsets.size(), 0U);
|
||||
glDispatchIndirectBuffer = 0;
|
||||
glVAO = 0;
|
||||
texUint = 0;
|
||||
glTextures.assign(glTextures.size(), 0U);
|
||||
glImages.assign(glImages.size(), 0U);
|
||||
glSamplers.assign(glSamplers.size(), 0U);
|
||||
glProgram = 0;
|
||||
glEnabledAttribLocs.assign(glEnabledAttribLocs.size(), false);
|
||||
glCurrentAttribLocs.assign(glCurrentAttribLocs.size(), false);
|
||||
glReadFramebuffer = 0;
|
||||
glDrawFramebuffer = 0;
|
||||
glRenderbuffer = 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;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _initialized{false};
|
||||
};
|
||||
|
||||
class GLES3GPUFramebufferCacheMap final {
|
||||
public:
|
||||
explicit GLES3GPUFramebufferCacheMap(GLES3GPUStateCache *cache) : _cache(cache) {}
|
||||
|
||||
void registerExternal(GLuint glFramebuffer, const GLES3GPUTexture *gpuTexture, uint32_t mipLevel) {
|
||||
bool isTexture = gpuTexture->glTexture;
|
||||
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
|
||||
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
|
||||
|
||||
if (cacheMap[glResource].empty()) cacheMap[glResource].resize(gpuTexture->mipLevel);
|
||||
if (!cacheMap[glResource][mipLevel].glFramebuffer) {
|
||||
cacheMap[glResource][mipLevel] = {glFramebuffer, true};
|
||||
}
|
||||
}
|
||||
|
||||
void unregisterExternal(GLuint glFramebuffer) {
|
||||
for (auto &levels : _textureMap) {
|
||||
for (auto &fbo : levels.second) {
|
||||
if (fbo.glFramebuffer == glFramebuffer) {
|
||||
fbo.glFramebuffer = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &levels : _renderbufferMap) {
|
||||
for (auto &fbo : levels.second) {
|
||||
if (fbo.glFramebuffer == glFramebuffer) {
|
||||
fbo.glFramebuffer = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint getFramebufferFromTexture(const GLES3GPUTextureView *gpuTextureView, const TextureSubresLayers &subres) {
|
||||
const auto *gpuTexture = gpuTextureView->gpuTexture;
|
||||
bool isTexture = gpuTexture->glTexture;
|
||||
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
|
||||
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
|
||||
uint32_t mipLevel = isTexture ? subres.mipLevel : 0;
|
||||
|
||||
if (gpuTexture->swapchain) return gpuTexture->swapchain->glFramebuffer;
|
||||
CC_ASSERT(gpuTexture->glTexture || gpuTexture->glRenderbuffer);
|
||||
|
||||
if (cacheMap[glResource].empty()) cacheMap[glResource].resize(gpuTexture->mipLevel);
|
||||
|
||||
if (!cacheMap[glResource][mipLevel].glFramebuffer) {
|
||||
GLuint glFramebuffer = 0U;
|
||||
GL_CHECK(glGenFramebuffers(1, &glFramebuffer));
|
||||
if (_cache->glDrawFramebuffer != glFramebuffer) {
|
||||
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, glFramebuffer));
|
||||
_cache->glDrawFramebuffer = glFramebuffer;
|
||||
}
|
||||
|
||||
const FormatInfo &info = GFX_FORMAT_INFOS[static_cast<uint32_t>(gpuTexture->format)];
|
||||
GLenum attachment = GL_COLOR_ATTACHMENT0;
|
||||
if (info.hasStencil) {
|
||||
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||
} else if (info.hasDepth) {
|
||||
attachment = GL_DEPTH_ATTACHMENT;
|
||||
}
|
||||
if (isTexture) {
|
||||
GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, gpuTextureView->glTarget, glResource, mipLevel));
|
||||
} else {
|
||||
GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, glResource));
|
||||
}
|
||||
|
||||
GLenum status;
|
||||
GL_CHECK(status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
|
||||
CC_ASSERT_EQ(status, GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
cacheMap[glResource][mipLevel].glFramebuffer = glFramebuffer;
|
||||
}
|
||||
|
||||
return cacheMap[glResource][mipLevel].glFramebuffer;
|
||||
}
|
||||
|
||||
void onTextureDestroy(const GLES3GPUTexture *gpuTexture) {
|
||||
bool isTexture = gpuTexture->glTexture;
|
||||
GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer;
|
||||
auto &cacheMap = isTexture ? _textureMap : _renderbufferMap;
|
||||
|
||||
if (cacheMap.count(glResource)) {
|
||||
for (auto &record : cacheMap[glResource]) {
|
||||
if (!record.glFramebuffer || record.isExternal) continue;
|
||||
|
||||
if (_cache->glDrawFramebuffer == record.glFramebuffer || _cache->glReadFramebuffer == record.glFramebuffer) {
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
_cache->glDrawFramebuffer = _cache->glReadFramebuffer = 0;
|
||||
}
|
||||
GL_CHECK(glDeleteFramebuffers(1, &record.glFramebuffer));
|
||||
}
|
||||
cacheMap.erase(glResource);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GLES3GPUStateCache *_cache = nullptr;
|
||||
|
||||
struct FramebufferRecord {
|
||||
GLuint glFramebuffer{0};
|
||||
bool isExternal{false};
|
||||
};
|
||||
using CacheMap = ccstd::unordered_map<GLuint, ccstd::vector<FramebufferRecord>>;
|
||||
CacheMap _renderbufferMap; // renderbuffer -> mip level -> framebuffer
|
||||
CacheMap _textureMap; // texture -> mip level -> framebuffer
|
||||
};
|
||||
|
||||
class GLES3GPUFramebufferHub final {
|
||||
public:
|
||||
void connect(GLES3GPUTexture *texture, GLES3GPUFramebuffer *framebuffer) {
|
||||
_framebuffers[texture].push_back(framebuffer);
|
||||
}
|
||||
|
||||
void disengage(GLES3GPUTexture *texture) {
|
||||
_framebuffers.erase(texture);
|
||||
}
|
||||
|
||||
void disengage(GLES3GPUTexture *texture, GLES3GPUFramebuffer *framebuffer) {
|
||||
auto &pool = _framebuffers[texture];
|
||||
pool.erase(std::remove(pool.begin(), pool.end(), framebuffer), pool.end());
|
||||
}
|
||||
|
||||
void update(GLES3GPUTexture *texture);
|
||||
|
||||
private:
|
||||
ccstd::unordered_map<GLES3GPUTexture *, ccstd::vector<GLES3GPUFramebuffer *>> _framebuffers;
|
||||
};
|
||||
|
||||
struct GLES3GPUProgramBinary : public GFXDeviceObject<DefaultDeleter> {
|
||||
ccstd::string name;
|
||||
ccstd::hash_t hash = 0;
|
||||
GLenum format;
|
||||
std::vector<char> data;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
71
cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp
Normal file
71
cocos/renderer/gfx-gles3/GLES3InputAssembler.cpp
Normal 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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3InputAssembler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3InputAssembler::GLES3InputAssembler() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3InputAssembler::~GLES3InputAssembler() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3InputAssembler::doInit(const InputAssemblerInfo &info) {
|
||||
_gpuInputAssembler = ccnew GLES3GPUInputAssembler;
|
||||
_gpuInputAssembler->attributes = _attributes;
|
||||
_gpuInputAssembler->gpuVertexBuffers.resize(_vertexBuffers.size());
|
||||
for (size_t i = 0; i < _gpuInputAssembler->gpuVertexBuffers.size(); ++i) {
|
||||
auto *vb = static_cast<GLES3Buffer *>(_vertexBuffers[i]);
|
||||
_gpuInputAssembler->gpuVertexBuffers[i] = vb->gpuBuffer();
|
||||
}
|
||||
if (info.indexBuffer) {
|
||||
_gpuInputAssembler->gpuIndexBuffer = static_cast<GLES3Buffer *>(info.indexBuffer)->gpuBuffer();
|
||||
}
|
||||
|
||||
if (info.indirectBuffer) {
|
||||
_gpuInputAssembler->gpuIndirectBuffer = static_cast<GLES3Buffer *>(info.indirectBuffer)->gpuBuffer();
|
||||
}
|
||||
|
||||
cmdFuncGLES3CreateInputAssembler(GLES3Device::getInstance(), _gpuInputAssembler);
|
||||
}
|
||||
|
||||
void GLES3InputAssembler::doDestroy() {
|
||||
if (_gpuInputAssembler) {
|
||||
cmdFuncGLES3DestroyInputAssembler(GLES3Device::getInstance(), _gpuInputAssembler);
|
||||
delete _gpuInputAssembler;
|
||||
_gpuInputAssembler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
51
cocos/renderer/gfx-gles3/GLES3InputAssembler.h
Normal file
51
cocos/renderer/gfx-gles3/GLES3InputAssembler.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXInputAssembler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUInputAssembler;
|
||||
class GLES3CmdDraw;
|
||||
|
||||
class CC_GLES3_API GLES3InputAssembler final : public InputAssembler {
|
||||
public:
|
||||
GLES3InputAssembler();
|
||||
~GLES3InputAssembler() override;
|
||||
|
||||
inline GLES3GPUInputAssembler *gpuInputAssembler() const { return _gpuInputAssembler; }
|
||||
|
||||
protected:
|
||||
void doInit(const InputAssemblerInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUInputAssembler *_gpuInputAssembler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
215
cocos/renderer/gfx-gles3/GLES3PipelineCache.cpp
Normal file
215
cocos/renderer/gfx-gles3/GLES3PipelineCache.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 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 "GLES3PipelineCache.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "base/BinaryArchive.h"
|
||||
|
||||
#include "GLES3GPUObjects.h"
|
||||
#include "gfx-base/GFXUtil.h"
|
||||
|
||||
namespace cc::gfx {
|
||||
|
||||
//#define PIPELINE_CACHE_FORCE_INCREMENTAL
|
||||
|
||||
#if defined(_WIN32) && !defined(PIPELINE_CACHE_FORCE_INCREMENTAL)
|
||||
#define PIPELINE_CACHE_FULL
|
||||
#else
|
||||
#define PIPELINE_CACHE_INCREMENTAL
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
const char *fileName = "/pipeline_cache_gles3.bin";
|
||||
const uint32_t MAGIC = 0x4343474C; // "CCGL"
|
||||
const uint32_t VERSION = 1;
|
||||
|
||||
void saveHeader(BinaryOutputArchive &archive) {
|
||||
archive.save(MAGIC);
|
||||
archive.save(VERSION);
|
||||
}
|
||||
|
||||
void saveItem(BinaryOutputArchive &archive, GLES3GPUProgramBinary *binary) {
|
||||
archive.save(binary->format);
|
||||
archive.save(static_cast<uint32_t>(binary->name.size()));
|
||||
archive.save(static_cast<uint32_t>(binary->data.size()));
|
||||
archive.save(binary->hash);
|
||||
archive.save(binary->name.data(), static_cast<uint32_t>(binary->name.size()));
|
||||
archive.save(binary->data.data(), static_cast<uint32_t>(binary->data.size()));
|
||||
CC_LOG_INFO("Save program cache success, name %s.", binary->name.c_str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
GLES3PipelineCache::GLES3PipelineCache() {
|
||||
_savePath = getPipelineCacheFolder() + fileName;
|
||||
}
|
||||
|
||||
GLES3PipelineCache::~GLES3PipelineCache() { // NOLINT
|
||||
#ifdef PIPELINE_CACHE_FULL
|
||||
saveCacheFull();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GLES3PipelineCache::loadCache() {
|
||||
std::ifstream stream(_savePath, std::ios::binary);
|
||||
if (!stream.is_open()) {
|
||||
CC_LOG_INFO("Load program cache, no cached files.");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t magic = 0;
|
||||
uint32_t version = 0;
|
||||
|
||||
BinaryInputArchive archive(stream);
|
||||
auto loadResult = archive.load(magic);
|
||||
loadResult &= archive.load(version);
|
||||
|
||||
if (magic != MAGIC || version < VERSION) {
|
||||
// false means invalid cache, need to discard the file content.
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t cachedItemNum = 0;
|
||||
GLenum format = GL_NONE;
|
||||
while (loadResult && archive.load(format)) {
|
||||
++cachedItemNum;
|
||||
|
||||
// name length
|
||||
uint32_t nameLength = 0;
|
||||
loadResult &= archive.load(nameLength);
|
||||
|
||||
// data length
|
||||
uint32_t dataLength = 0;
|
||||
loadResult &= archive.load(dataLength);
|
||||
|
||||
// skip length if not valid.
|
||||
if (!checkProgramFormat(format)) {
|
||||
archive.move(dataLength + nameLength + sizeof(GLES3GPUProgramBinary::hash));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto *binary = ccnew GLES3GPUProgramBinary();
|
||||
binary->format = format;
|
||||
binary->name.resize(nameLength, 0);
|
||||
binary->data.resize(dataLength, 0);
|
||||
|
||||
// hash
|
||||
loadResult &= archive.load(binary->hash);
|
||||
|
||||
// name
|
||||
loadResult &= archive.load(binary->name.data(), nameLength);
|
||||
|
||||
// data
|
||||
loadResult &= archive.load(binary->data.data(), dataLength);
|
||||
|
||||
_programCaches.emplace(binary->name, binary);
|
||||
}
|
||||
|
||||
// If the number of cached items does not equal the number of loaded items, it may be necessary to update the cache.
|
||||
_dirty = cachedItemNum != _programCaches.size();
|
||||
CC_LOG_INFO("Load program cache success. records %u, loaded %u", cachedItemNum, _programCaches.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLES3PipelineCache::saveCacheIncremental(GLES3GPUProgramBinary *binary) {
|
||||
std::ofstream stream(_savePath, std::ios::binary | std::ios::app);
|
||||
if (!stream.is_open()) {
|
||||
CC_LOG_INFO("Save program cache failed.");
|
||||
return;
|
||||
}
|
||||
BinaryOutputArchive archive(stream);
|
||||
saveItem(archive, binary);
|
||||
}
|
||||
|
||||
void GLES3PipelineCache::saveCacheFull() {
|
||||
if (!_dirty) {
|
||||
return;
|
||||
}
|
||||
std::ofstream stream(_savePath, std::ios::binary);
|
||||
if (!stream.is_open()) {
|
||||
CC_LOG_INFO("Save program cache failed.");
|
||||
return;
|
||||
}
|
||||
BinaryOutputArchive archive(stream);
|
||||
saveHeader(archive);
|
||||
|
||||
for (auto &pair : _programCaches) {
|
||||
auto &binary = pair.second;
|
||||
saveItem(archive, binary);
|
||||
}
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
void GLES3PipelineCache::init() {
|
||||
GLint shaderBinaryFormats = 0;
|
||||
GL_CHECK(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &shaderBinaryFormats));
|
||||
|
||||
_programBinaryFormats.resize(shaderBinaryFormats);
|
||||
GL_CHECK(glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, _programBinaryFormats.data()));
|
||||
|
||||
bool success = loadCache();
|
||||
if (!success) {
|
||||
// discard cache content.
|
||||
std::ofstream stream(_savePath, std::ios::binary | std::ios::trunc);
|
||||
#ifdef PIPELINE_CACHE_INCREMENTAL
|
||||
if (stream.is_open()) {
|
||||
BinaryOutputArchive archive(stream);
|
||||
saveHeader(archive);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PipelineCache::addBinary(GLES3GPUProgramBinary *binary) {
|
||||
_programCaches[binary->name] = binary;
|
||||
#ifdef PIPELINE_CACHE_INCREMENTAL
|
||||
saveCacheIncremental(binary);
|
||||
#endif
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
GLES3GPUProgramBinary *GLES3PipelineCache::fetchBinary(const ccstd::string &key, ccstd::hash_t hash) {
|
||||
auto iter = _programCaches.find(key);
|
||||
if (iter == _programCaches.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if hash not match, re-generate program binary.
|
||||
if (iter->second->hash != hash) {
|
||||
_programCaches.erase(iter);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
bool GLES3PipelineCache::checkProgramFormat(GLuint format) const {
|
||||
return std::any_of(_programBinaryFormats.begin(), _programBinaryFormats.end(), [format](const auto &fmt) {
|
||||
return format == fmt;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace cc::gfx
|
||||
63
cocos/renderer/gfx-gles3/GLES3PipelineCache.h
Normal file
63
cocos/renderer/gfx-gles3/GLES3PipelineCache.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 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 "GLES3GPUObjects.h"
|
||||
#include "base/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
class BinaryOutputArchive;
|
||||
}
|
||||
|
||||
namespace cc::gfx {
|
||||
class GLES3GPUShader;
|
||||
|
||||
class GLES3PipelineCache : public RefCounted {
|
||||
public:
|
||||
GLES3PipelineCache();
|
||||
~GLES3PipelineCache() override;
|
||||
|
||||
void init();
|
||||
|
||||
void addBinary(GLES3GPUProgramBinary *binary);
|
||||
GLES3GPUProgramBinary *fetchBinary(const ccstd::string &key, ccstd::hash_t hash);
|
||||
bool checkProgramFormat(GLuint format) const;
|
||||
|
||||
private:
|
||||
bool loadCache();
|
||||
void saveCacheFull();
|
||||
void saveCacheIncremental(GLES3GPUProgramBinary *binary);
|
||||
|
||||
ccstd::vector<GLint> _programBinaryFormats;
|
||||
ccstd::unordered_map<ccstd::string, IntrusivePtr<GLES3GPUProgramBinary>> _programCaches;
|
||||
ccstd::string _savePath;
|
||||
bool _dirty = false;
|
||||
};
|
||||
|
||||
} // namespace cc::gfx
|
||||
76
cocos/renderer/gfx-gles3/GLES3PipelineLayout.cpp
Normal file
76
cocos/renderer/gfx-gles3/GLES3PipelineLayout.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSetLayout.h"
|
||||
#include "GLES3PipelineLayout.h"
|
||||
#include "base/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3PipelineLayout::GLES3PipelineLayout() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3PipelineLayout::~GLES3PipelineLayout() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3PipelineLayout::doInit(const PipelineLayoutInfo & /*info*/) {
|
||||
_gpuPipelineLayout = ccnew GLES3GPUPipelineLayout;
|
||||
|
||||
uint32_t offset = 0U;
|
||||
auto &hash = _gpuPipelineLayout->hash;
|
||||
_gpuPipelineLayout->dynamicOffsetIndices.resize(_setLayouts.size());
|
||||
for (uint32_t i = 0U; i < _setLayouts.size(); i++) {
|
||||
DescriptorSetLayout *setLayout = _setLayouts[i];
|
||||
GLES3GPUDescriptorSetLayout *gpuSetLayout = static_cast<GLES3DescriptorSetLayout *>(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] = static_cast<int32_t>(offset + j);
|
||||
}
|
||||
_gpuPipelineLayout->dynamicOffsetOffsets.push_back(static_cast<uint32_t>(offset));
|
||||
_gpuPipelineLayout->setLayouts.push_back(gpuSetLayout);
|
||||
offset += dynamicCount;
|
||||
|
||||
ccstd::hash_combine(hash, gpuSetLayout->hash);
|
||||
}
|
||||
_gpuPipelineLayout->dynamicOffsetOffsets.push_back(static_cast<uint32_t>(offset));
|
||||
_gpuPipelineLayout->dynamicOffsetCount = static_cast<uint32_t>(offset);
|
||||
_gpuPipelineLayout->dynamicOffsets.resize(offset);
|
||||
}
|
||||
|
||||
void GLES3PipelineLayout::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuPipelineLayout);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-gles3/GLES3PipelineLayout.h
Normal file
50
cocos/renderer/gfx-gles3/GLES3PipelineLayout.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXPipelineLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUPipelineLayout;
|
||||
|
||||
class CC_GLES3_API GLES3PipelineLayout final : public PipelineLayout {
|
||||
public:
|
||||
GLES3PipelineLayout();
|
||||
~GLES3PipelineLayout() override;
|
||||
|
||||
inline GLES3GPUPipelineLayout *gpuPipelineLayout() const { return _gpuPipelineLayout; }
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUPipelineLayout *_gpuPipelineLayout = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
148
cocos/renderer/gfx-gles3/GLES3PipelineState.cpp
Normal file
148
cocos/renderer/gfx-gles3/GLES3PipelineState.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3PipelineLayout.h"
|
||||
#include "GLES3PipelineState.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "GLES3Shader.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
const GLenum GLE_S3_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,
|
||||
};
|
||||
|
||||
namespace {
|
||||
void updateGPUShaderSourceByRenderPass(GLES3GPUShader *gpuShader, GLES3GPURenderPass *renderPass, uint32_t subpassIndex) {
|
||||
auto iter = std::find_if(gpuShader->gpuStages.begin(), gpuShader->gpuStages.end(), [](const GLES3GPUShaderStage &stage) {
|
||||
return stage.type == ShaderStageFlagBit::FRAGMENT;
|
||||
});
|
||||
if (iter == gpuShader->gpuStages.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CC_ASSERT(subpassIndex < renderPass->subpasses.size());
|
||||
if (renderPass->subpasses.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
bool dsInput{false};
|
||||
if (renderPass->depthStencil != INVALID_BINDING && !renderPass->subpasses[subpassIndex].inputs.empty()) {
|
||||
const auto &inputs = renderPass->subpasses[subpassIndex].inputs;
|
||||
// depth stencil input should always lies at the end of index list.
|
||||
dsInput = inputs.back() == renderPass->depthStencil;
|
||||
}
|
||||
|
||||
auto &drawBuffers = renderPass->drawBuffers.at(subpassIndex);
|
||||
ccstd::string::size_type offset = 0;
|
||||
for (uint32_t i = 0; i < drawBuffers.size(); ++i) {
|
||||
const char *layoutPrefix = "layout(location = ";
|
||||
|
||||
std::stringstream ss1;
|
||||
ss1 << layoutPrefix << i << ") out";
|
||||
|
||||
std::stringstream ss2;
|
||||
ss2 << layoutPrefix << i << ") inout";
|
||||
|
||||
auto &source = iter->source;
|
||||
auto sIter = source.find(ss1.str(), offset);
|
||||
if (sIter == std::string::npos) {
|
||||
sIter = source.find(ss2.str(), offset);
|
||||
}
|
||||
|
||||
if (sIter != std::string::npos) {
|
||||
auto loc = sIter + strlen(layoutPrefix);
|
||||
source[loc] = drawBuffers[i] + '0';
|
||||
offset = loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initGpuShader(GLES3GPUShader *gpuShader, GLES3GPUPipelineLayout *gpuPipelineLayout, GLES3GPURenderPass *renderPass, uint32_t subpassIndex) {
|
||||
updateGPUShaderSourceByRenderPass(gpuShader, renderPass, subpassIndex);
|
||||
cmdFuncGLES3CreateShader(GLES3Device::getInstance(), gpuShader, gpuPipelineLayout);
|
||||
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
|
||||
|
||||
GLES3PipelineState::GLES3PipelineState() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3PipelineState::~GLES3PipelineState() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3PipelineState::doInit(const PipelineStateInfo & /*info*/) {
|
||||
_gpuPipelineState = ccnew GLES3GPUPipelineState;
|
||||
_gpuPipelineState->glPrimitive = GLE_S3_PRIMITIVES[static_cast<int>(_primitive)];
|
||||
_gpuPipelineState->rs = _rasterizerState;
|
||||
_gpuPipelineState->dss = _depthStencilState;
|
||||
_gpuPipelineState->bs = _blendState;
|
||||
_gpuPipelineState->gpuPipelineLayout = static_cast<GLES3PipelineLayout *>(_pipelineLayout)->gpuPipelineLayout();
|
||||
_gpuPipelineState->gpuShader = static_cast<GLES3Shader *>(_shader)->gpuShader();
|
||||
if (_renderPass) _gpuPipelineState->gpuRenderPass = static_cast<GLES3RenderPass *>(_renderPass)->gpuRenderPass();
|
||||
if (_gpuPipelineState->gpuShader->glProgram == 0) {
|
||||
initGpuShader(_gpuPipelineState->gpuShader, _gpuPipelineState->gpuPipelineLayout, _gpuPipelineState->gpuRenderPass, _subpass);
|
||||
}
|
||||
|
||||
if (_renderPass) _gpuPipelineState->gpuRenderPass = static_cast<GLES3RenderPass *>(_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 GLES3PipelineState::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuPipelineState);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-gles3/GLES3PipelineState.h
Normal file
50
cocos/renderer/gfx-gles3/GLES3PipelineState.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXPipelineState.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUPipelineState;
|
||||
|
||||
class CC_GLES3_API GLES3PipelineState final : public PipelineState {
|
||||
public:
|
||||
GLES3PipelineState();
|
||||
~GLES3PipelineState() override;
|
||||
|
||||
inline GLES3GPUPipelineState *gpuPipelineState() const { return _gpuPipelineState; }
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineStateInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUPipelineState *_gpuPipelineState = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
301
cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp
Normal file
301
cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Buffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3DescriptorSet.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Framebuffer.h"
|
||||
#include "GLES3InputAssembler.h"
|
||||
#include "GLES3PipelineState.h"
|
||||
#include "GLES3PrimaryCommandBuffer.h"
|
||||
#include "GLES3QueryPool.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "GLES3Texture.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "states/GLES3GeneralBarrier.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3PrimaryCommandBuffer::~GLES3PrimaryCommandBuffer() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass*/, Framebuffer * /*frameBuffer*/) {
|
||||
_curGPUPipelineState = nullptr;
|
||||
_curGPUInputAssember = nullptr;
|
||||
_curGPUDescriptorSets.assign(_curGPUDescriptorSets.size(), nullptr);
|
||||
|
||||
_numDrawCalls = 0;
|
||||
_numInstances = 0;
|
||||
_numTriangles = 0;
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::end() {
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const * /*secondaryCBs*/, uint32_t /*secondaryCBCount*/) {
|
||||
_curSubpassIdx = 0U;
|
||||
|
||||
auto *gpuRenderPass = static_cast<GLES3RenderPass *>(renderPass)->gpuRenderPass();
|
||||
GLES3GPUFramebuffer *gpuFramebuffer = static_cast<GLES3Framebuffer *>(fbo)->gpuFBO();
|
||||
|
||||
cmdFuncGLES3BeginRenderPass(GLES3Device::getInstance(), gpuRenderPass, gpuFramebuffer, &renderArea, colors, depth, stencil);
|
||||
_curDynamicStates.viewport = {renderArea.x, renderArea.y, renderArea.width, renderArea.height};
|
||||
_curDynamicStates.scissor = renderArea;
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::endRenderPass() {
|
||||
cmdFuncGLES3EndRenderPass(GLES3Device::getInstance());
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::nextSubpass() {
|
||||
++_curSubpassIdx;
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::insertMarker(const MarkerInfo &marker) {
|
||||
cmdFuncGLES3InsertMarker(GLES3Device::getInstance(), marker.name.size(), marker.name.data());
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::beginMarker(const MarkerInfo &marker) {
|
||||
cmdFuncGLES3PushGroupMarker(GLES3Device::getInstance(), marker.name.size(), marker.name.data());
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::endMarker() {
|
||||
cmdFuncGLES3PopGroupMarker(GLES3Device::getInstance());
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::draw(const DrawInfo &info) {
|
||||
CC_PROFILE(GLES3PrimaryCommandBufferDraw);
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
|
||||
cmdFuncGLES3Draw(GLES3Device::getInstance(), info);
|
||||
|
||||
++_numDrawCalls;
|
||||
_numInstances += info.instanceCount;
|
||||
if (_curGPUPipelineState) {
|
||||
uint32_t indexCount = info.indexCount ? info.indexCount : info.vertexCount;
|
||||
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 GLES3PrimaryCommandBuffer::setViewport(const Viewport &vp) {
|
||||
auto *cache = GLES3Device::getInstance()->stateCache();
|
||||
if (cache->viewport != vp) {
|
||||
cache->viewport = vp;
|
||||
GL_CHECK(glViewport(vp.left, vp.top, vp.width, vp.height));
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::setScissor(const Rect &rect) {
|
||||
auto *cache = GLES3Device::getInstance()->stateCache();
|
||||
if (cache->scissor != rect) {
|
||||
cache->scissor = rect;
|
||||
GL_CHECK(glScissor(rect.x, rect.y, rect.width, rect.height));
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
|
||||
GLES3GPUBuffer *gpuBuffer = static_cast<GLES3Buffer *>(buff)->gpuBuffer();
|
||||
if (gpuBuffer) {
|
||||
cmdFuncGLES3UpdateBuffer(GLES3Device::getInstance(), gpuBuffer, data, 0U, size);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
|
||||
GLES3GPUTexture *gpuTexture = static_cast<GLES3Texture *>(texture)->gpuTexture();
|
||||
if (gpuTexture) {
|
||||
cmdFuncGLES3CopyBuffersToTexture(GLES3Device::getInstance(), buffers, gpuTexture, regions, count);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
copyTexture(srcTexture, dstTexture, regions, count);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
GLES3GPUTextureView *gpuTextureSrc = nullptr;
|
||||
GLES3GPUTextureView *gpuTextureDst = nullptr;
|
||||
if (srcTexture) gpuTextureSrc = static_cast<GLES3Texture *>(srcTexture)->gpuTextureView();
|
||||
if (dstTexture) gpuTextureDst = static_cast<GLES3Texture *>(dstTexture)->gpuTextureView();
|
||||
|
||||
ccstd::vector<TextureBlit> blitRegions(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
auto &blit = blitRegions[i];
|
||||
const auto © = 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;
|
||||
}
|
||||
cmdFuncGLES3BlitTexture(GLES3Device::getInstance(), gpuTextureSrc, gpuTextureDst, blitRegions.data(), count, Filter::POINT);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
|
||||
GLES3GPUTextureView *gpuTextureSrc = nullptr;
|
||||
GLES3GPUTextureView *gpuTextureDst = nullptr;
|
||||
if (srcTexture) gpuTextureSrc = static_cast<GLES3Texture *>(srcTexture)->gpuTextureView();
|
||||
if (dstTexture) gpuTextureDst = static_cast<GLES3Texture *>(dstTexture)->gpuTextureView();
|
||||
|
||||
cmdFuncGLES3BlitTexture(GLES3Device::getInstance(), gpuTextureSrc, gpuTextureDst, regions, count, filter);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::beginQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
|
||||
cmdFuncGLES3Query(GLES3Device::getInstance(), gles3QueryPool, GLES3QueryType::BEGIN, id);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::endQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
|
||||
cmdFuncGLES3Query(GLES3Device::getInstance(), gles3QueryPool, GLES3QueryType::END, id);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::resetQueryPool(QueryPool *queryPool) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
|
||||
cmdFuncGLES3Query(GLES3Device::getInstance(), gles3QueryPool, GLES3QueryType::RESET, 0);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::getQueryPoolResults(QueryPool *queryPool) {
|
||||
auto *gles3QueryPool = static_cast<GLES3QueryPool *>(queryPool);
|
||||
|
||||
cmdFuncGLES3Query(GLES3Device::getInstance(), gles3QueryPool, GLES3QueryType::GET_RESULTS, 0);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::execute(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
auto *cmdBuff = static_cast<GLES3PrimaryCommandBuffer *>(cmdBuffs[i]);
|
||||
|
||||
if (!cmdBuff->_pendingPackages.empty()) {
|
||||
GLES3CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
|
||||
|
||||
cmdFuncGLES3ExecuteCmds(GLES3Device::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 GLES3PrimaryCommandBuffer::bindStates() {
|
||||
if (_curGPUPipelineState) {
|
||||
ccstd::vector<uint32_t> &dynamicOffsetOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsetOffsets;
|
||||
ccstd::vector<uint32_t> &dynamicOffsets = _curGPUPipelineState->gpuPipelineLayout->dynamicOffsets;
|
||||
for (size_t i = 0U, len = dynamicOffsetOffsets.size() - 1; i < len; 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));
|
||||
}
|
||||
cmdFuncGLES3BindState(GLES3Device::getInstance(), _curGPUPipelineState, _curGPUInputAssember,
|
||||
_curGPUDescriptorSets.data(), dynamicOffsets.data(), &_curDynamicStates);
|
||||
}
|
||||
|
||||
_isStateInvalid = false;
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::dispatch(const DispatchInfo &info) {
|
||||
if (_isStateInvalid) {
|
||||
bindStates();
|
||||
}
|
||||
|
||||
GLES3GPUDispatchInfo gpuInfo;
|
||||
if (info.indirectBuffer) {
|
||||
gpuInfo.indirectBuffer = static_cast<GLES3Buffer *>(info.indirectBuffer)->gpuBuffer();
|
||||
gpuInfo.indirectOffset = info.indirectOffset;
|
||||
} else {
|
||||
gpuInfo.groupCountX = info.groupCountX;
|
||||
gpuInfo.groupCountY = info.groupCountY;
|
||||
gpuInfo.groupCountZ = info.groupCountZ;
|
||||
}
|
||||
cmdFuncGLES3Dispatch(GLES3Device::getInstance(), gpuInfo);
|
||||
}
|
||||
|
||||
void GLES3PrimaryCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const * /*buffers*/, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const * /*textures*/, uint32_t textureBarrierCount) {
|
||||
if (!barrier && !bufferBarrierCount && !textureBarrierCount) return;
|
||||
|
||||
GLuint glBarriers{0};
|
||||
GLuint glBarriersByRegion{0};
|
||||
|
||||
if (barrier) {
|
||||
GLES3GPUGeneralBarrier genBarrier = *(static_cast<const GLES3GeneralBarrier *>(barrier)->gpuBarrier());
|
||||
glBarriers |= genBarrier.glBarriers;
|
||||
glBarriersByRegion |= genBarrier.glBarriersByRegion;
|
||||
}
|
||||
|
||||
auto fullfill = [&glBarriers, &glBarriersByRegion](auto *barriers, uint32_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
GLES3GPUGeneralBarrier barrier{
|
||||
barriers[i]->getInfo().prevAccesses,
|
||||
barriers[i]->getInfo().nextAccesses,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
completeBarrier(&barrier);
|
||||
glBarriers |= barrier.glBarriers;
|
||||
glBarriersByRegion |= barrier.glBarriersByRegion;
|
||||
}
|
||||
};
|
||||
|
||||
fullfill(bufferBarriers, bufferBarrierCount);
|
||||
fullfill(textureBarriers, textureBarrierCount);
|
||||
|
||||
cmdFuncGLES3MemoryBarrier(GLES3Device::getInstance(), glBarriers, glBarriersByRegion);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h
Normal file
70
cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3CommandBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_GLES3_API GLES3PrimaryCommandBuffer final : public GLES3CommandBuffer {
|
||||
public:
|
||||
GLES3PrimaryCommandBuffer() = default;
|
||||
~GLES3PrimaryCommandBuffer() 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 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 bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const * /*textures*/, uint32_t textureBarrierCount) 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 beginQuery(QueryPool *queryPool, uint32_t id) override;
|
||||
void endQuery(QueryPool *queryPool, uint32_t id) override;
|
||||
void resetQueryPool(QueryPool *queryPool) override;
|
||||
|
||||
protected:
|
||||
friend class GLES3Queue;
|
||||
friend class GLES3QueryPool;
|
||||
|
||||
void getQueryPoolResults(QueryPool *query) override;
|
||||
|
||||
void bindStates() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
63
cocos/renderer/gfx-gles3/GLES3QueryPool.cpp
Normal file
63
cocos/renderer/gfx-gles3/GLES3QueryPool.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3QueryPool.h"
|
||||
#include "GLES3CommandBuffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3QueryPool::GLES3QueryPool() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3QueryPool::~GLES3QueryPool() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3QueryPool::doInit(const QueryPoolInfo & /*info*/) {
|
||||
GLES3Device *device = GLES3Device::getInstance();
|
||||
if (device->getCapabilities().supportQuery) {
|
||||
_gpuQueryPool = ccnew GLES3GPUQueryPool;
|
||||
_gpuQueryPool->type = _type;
|
||||
_gpuQueryPool->maxQueryObjects = _maxQueryObjects;
|
||||
_gpuQueryPool->forceWait = _forceWait;
|
||||
_gpuQueryPool->glQueryIds.resize(_maxQueryObjects, 0U);
|
||||
|
||||
cmdFuncGLES3CreateQueryPool(device, _gpuQueryPool);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3QueryPool::doDestroy() {
|
||||
if (_gpuQueryPool) {
|
||||
cmdFuncGLES3DestroyQueryPool(GLES3Device::getInstance(), _gpuQueryPool);
|
||||
delete _gpuQueryPool;
|
||||
_gpuQueryPool = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
59
cocos/renderer/gfx-gles3/GLES3QueryPool.h
Normal file
59
cocos/renderer/gfx-gles3/GLES3QueryPool.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXQueryPool.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GLES3GPUQueryPool;
|
||||
|
||||
class CC_GLES3_API GLES3QueryPool final : public QueryPool {
|
||||
public:
|
||||
GLES3QueryPool();
|
||||
~GLES3QueryPool() override;
|
||||
|
||||
inline GLES3GPUQueryPool *gpuQueryPool() const { return _gpuQueryPool; }
|
||||
inline uint32_t getIdCount() const { return static_cast<uint32_t>(_ids.size()); }
|
||||
inline void clearId() { _ids.clear(); }
|
||||
inline void addId(uint32_t id) { _ids.push_back(id); }
|
||||
inline uint32_t getId(uint32_t index) const { return _ids[index]; }
|
||||
inline std::mutex &getMutex() { return _mutex; }
|
||||
inline void setResults(ccstd::unordered_map<uint32_t, uint64_t> &&results) { _results = results; }
|
||||
|
||||
protected:
|
||||
friend class GLES3CommandBuffer;
|
||||
|
||||
void doInit(const QueryPoolInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUQueryPool *_gpuQueryPool = nullptr;
|
||||
ccstd::vector<uint32_t> _ids;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
71
cocos/renderer/gfx-gles3/GLES3Queue.cpp
Normal file
71
cocos/renderer/gfx-gles3/GLES3Queue.cpp
Normal 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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3CommandBuffer.h"
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Queue.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Queue::GLES3Queue() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Queue::~GLES3Queue() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3Queue::doInit(const QueueInfo &info) {
|
||||
}
|
||||
|
||||
void GLES3Queue::doDestroy() {
|
||||
}
|
||||
|
||||
void GLES3Queue::submit(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
auto *cmdBuff = static_cast<GLES3CommandBuffer *>(cmdBuffs[i]);
|
||||
|
||||
if (!cmdBuff->_pendingPackages.empty()) {
|
||||
GLES3CmdPackage *cmdPackage = cmdBuff->_pendingPackages.front();
|
||||
|
||||
cmdFuncGLES3ExecuteCmds(GLES3Device::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
|
||||
52
cocos/renderer/gfx-gles3/GLES3Queue.h
Normal file
52
cocos/renderer/gfx-gles3/GLES3Queue.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXQueue.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_GLES3_API GLES3Queue final : public Queue {
|
||||
public:
|
||||
GLES3Queue();
|
||||
~GLES3Queue() override;
|
||||
|
||||
void submit(CommandBuffer *const *cmdBuffs, uint32_t count) override;
|
||||
|
||||
protected:
|
||||
friend class GLES3Device;
|
||||
|
||||
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
|
||||
90
cocos/renderer/gfx-gles3/GLES3RenderPass.cpp
Normal file
90
cocos/renderer/gfx-gles3/GLES3RenderPass.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3RenderPass.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3RenderPass::GLES3RenderPass() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3RenderPass::~GLES3RenderPass() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3RenderPass::doInit(const RenderPassInfo & /*info*/) {
|
||||
_gpuRenderPass = ccnew GLES3GPURenderPass;
|
||||
_gpuRenderPass->colorAttachments = _colorAttachments;
|
||||
_gpuRenderPass->depthStencilAttachment = _depthStencilAttachment;
|
||||
_gpuRenderPass->depthStencilResolveAttachment = _depthStencilResolveAttachment;
|
||||
_gpuRenderPass->subpasses = _subpasses;
|
||||
_gpuRenderPass->dependencies = _dependencies;
|
||||
|
||||
// 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;
|
||||
}
|
||||
if (_depthStencilResolveAttachment.format != Format::UNKNOWN) {
|
||||
subpass.depthStencil = colorCount + 1;
|
||||
}
|
||||
} 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.depthStencil >= colorCount) {
|
||||
subpass.depthStencilResolve = colorCount + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmdFuncGLES3CreateRenderPass(GLES3Device::getInstance(), _gpuRenderPass);
|
||||
}
|
||||
|
||||
void GLES3RenderPass::doDestroy() {
|
||||
if (_gpuRenderPass) {
|
||||
cmdFuncGLES3DestroyRenderPass(GLES3Device::getInstance(), _gpuRenderPass);
|
||||
delete _gpuRenderPass;
|
||||
_gpuRenderPass = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-gles3/GLES3RenderPass.h
Normal file
50
cocos/renderer/gfx-gles3/GLES3RenderPass.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXRenderPass.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPURenderPass;
|
||||
|
||||
class CC_GLES3_API GLES3RenderPass final : public RenderPass {
|
||||
public:
|
||||
GLES3RenderPass();
|
||||
~GLES3RenderPass() override;
|
||||
|
||||
inline GLES3GPURenderPass *gpuRenderPass() const { return _gpuRenderPass; }
|
||||
|
||||
protected:
|
||||
void doInit(const RenderPassInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPURenderPass *_gpuRenderPass = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
78
cocos/renderer/gfx-gles3/GLES3Shader.cpp
Normal file
78
cocos/renderer/gfx-gles3/GLES3Shader.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Shader.h"
|
||||
#include "base/std/hash/hash_fwd.hpp"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Shader::GLES3Shader() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Shader::~GLES3Shader() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
GLES3GPUShader *GLES3Shader::gpuShader() const {
|
||||
return _gpuShader;
|
||||
}
|
||||
|
||||
void GLES3Shader::doInit(const ShaderInfo & /*info*/) {
|
||||
_gpuShader = ccnew GLES3GPUShader;
|
||||
CC_ASSERT(!_gpuShader->glProgram);
|
||||
_gpuShader->name = _name;
|
||||
_gpuShader->blocks = _blocks;
|
||||
_gpuShader->buffers = _buffers;
|
||||
_gpuShader->samplerTextures = _samplerTextures;
|
||||
_gpuShader->samplers = _samplers;
|
||||
_gpuShader->textures = _textures;
|
||||
_gpuShader->images = _images;
|
||||
_gpuShader->subpassInputs = _subpassInputs;
|
||||
_gpuShader->hash = _hash;
|
||||
for (const auto &stage : _stages) {
|
||||
GLES3GPUShaderStage gpuShaderStage = {stage.stage, stage.source};
|
||||
_gpuShader->gpuStages.emplace_back(std::move(gpuShaderStage));
|
||||
}
|
||||
for (auto &stage : _stages) {
|
||||
stage.source.clear();
|
||||
stage.source.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Shader::doDestroy() {
|
||||
if (_gpuShader) {
|
||||
cmdFuncGLES3DestroyShader(GLES3Device::getInstance(), _gpuShader);
|
||||
delete _gpuShader;
|
||||
_gpuShader = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-gles3/GLES3Shader.h
Normal file
50
cocos/renderer/gfx-gles3/GLES3Shader.h
Normal 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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXShader.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUShader;
|
||||
|
||||
class CC_GLES3_API GLES3Shader final : public Shader {
|
||||
public:
|
||||
GLES3Shader();
|
||||
~GLES3Shader() override;
|
||||
|
||||
GLES3GPUShader *gpuShader() const;
|
||||
|
||||
protected:
|
||||
void doInit(const ShaderInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
GLES3GPUShader *_gpuShader = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
65
cocos/renderer/gfx-gles3/GLES3Std.h
Normal file
65
cocos/renderer/gfx-gles3/GLES3Std.h
Normal 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_GLES3_API
|
||||
#else
|
||||
#ifdef CC_GLES3_EXPORTS
|
||||
#define CC_GLES3_API __declspec(dllexport)
|
||||
#else
|
||||
#define CC_GLES3_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define CC_GLES3_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
|
||||
243
cocos/renderer/gfx-gles3/GLES3Swapchain.cpp
Normal file
243
cocos/renderer/gfx-gles3/GLES3Swapchain.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/****************************************************************************
|
||||
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 "application/ApplicationManager.h"
|
||||
#include "platform/interfaces/modules/IXRInterface.h"
|
||||
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3GPUObjects.h"
|
||||
#include "GLES3Swapchain.h"
|
||||
#include "GLES3Texture.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 {
|
||||
|
||||
GLES3Swapchain::GLES3Swapchain() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Swapchain::~GLES3Swapchain() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3Swapchain::doInit(const SwapchainInfo &info) {
|
||||
_xr = CC_GET_XR_INTERFACE();
|
||||
if (_xr) {
|
||||
_xr->updateXRSwapchainTypedID(getTypedID());
|
||||
}
|
||||
auto width = static_cast<int32_t>(info.width);
|
||||
auto height = static_cast<int32_t>(info.height);
|
||||
const auto *context = GLES3Device::getInstance()->context();
|
||||
_gpuSwapchain = ccnew GLES3GPUSwapchain;
|
||||
#if CC_PLATFORM == CC_PLATFORM_LINUX
|
||||
auto window = reinterpret_cast<EGLNativeWindowType>(info.windowHandle);
|
||||
#else
|
||||
auto *window = reinterpret_cast<EGLNativeWindowType>(info.windowHandle);
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
if (_xr) {
|
||||
width = _xr->getXRConfig(xr::XRConfigKey::SWAPCHAIN_WIDTH).getInt();
|
||||
height = _xr->getXRConfig(xr::XRConfigKey::SWAPCHAIN_HEIGHT).getInt();
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
EGLSurfaceType surfaceType = _xr ? _xr->acquireEGLSurfaceType(getTypedID()) : EGLSurfaceType::WINDOW;
|
||||
if (surfaceType == EGLSurfaceType::PBUFFER) {
|
||||
EGLint pbufferAttribs[]{
|
||||
EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_NONE};
|
||||
EGL_CHECK(_gpuSwapchain->eglSurface = eglCreatePbufferSurface(context->eglDisplay, context->eglConfig, pbufferAttribs));
|
||||
} else if (surfaceType == EGLSurfaceType::WINDOW) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (_xr) {
|
||||
GLES3Device::getInstance()->context()->makeCurrent(_gpuSwapchain, _gpuSwapchain);
|
||||
_gpuSwapchain->isXR = true;
|
||||
}
|
||||
|
||||
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 GLES3Texture;
|
||||
_depthStencilTexture = ccnew GLES3Texture;
|
||||
|
||||
SwapchainTextureInfo textureInfo;
|
||||
textureInfo.swapchain = this;
|
||||
textureInfo.format = Format::RGBA8;
|
||||
textureInfo.width = width;
|
||||
textureInfo.height = height;
|
||||
initTexture(textureInfo, _colorTexture);
|
||||
|
||||
textureInfo.format = Format::DEPTH_STENCIL;
|
||||
initTexture(textureInfo, _depthStencilTexture);
|
||||
|
||||
_gpuSwapchain->gpuColorTexture = static_cast<GLES3Texture *>(_colorTexture.get())->gpuTexture();
|
||||
}
|
||||
|
||||
void GLES3Swapchain::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 GLES3Swapchain::doResize(uint32_t width, uint32_t height, SurfaceTransform /*transform*/) {
|
||||
_colorTexture->resize(width, height);
|
||||
_depthStencilTexture->resize(width, height);
|
||||
|
||||
if (_windowHandle) {
|
||||
doCreateSurface(_windowHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Swapchain::doDestroySurface() {
|
||||
if (_gpuSwapchain->eglSurface != EGL_NO_SURFACE) {
|
||||
auto *context = GLES3Device::getInstance()->context();
|
||||
eglDestroySurface(context->eglDisplay, _gpuSwapchain->eglSurface);
|
||||
_gpuSwapchain->eglSurface = EGL_NO_SURFACE;
|
||||
context->bindContext(true);
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Swapchain::doCreateSurface(void *windowHandle) {
|
||||
auto *context = GLES3Device::getInstance()->context();
|
||||
#if CC_PLATFORM == CC_PLATFORM_LINUX
|
||||
auto window = reinterpret_cast<EGLNativeWindowType>(windowHandle);
|
||||
#else
|
||||
auto *window = reinterpret_cast<EGLNativeWindowType>(windowHandle);
|
||||
#endif
|
||||
|
||||
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) {
|
||||
IXRInterface *xr = CC_GET_XR_INTERFACE();
|
||||
EGLSurfaceType surfaceType = xr ? xr->acquireEGLSurfaceType(getTypedID()) : EGLSurfaceType::WINDOW;
|
||||
if (surfaceType == EGLSurfaceType::PBUFFER) {
|
||||
EGLint pbufferAttribs[]{
|
||||
EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_NONE};
|
||||
EGL_CHECK(_gpuSwapchain->eglSurface = eglCreatePbufferSurface(context->eglDisplay, context->eglConfig, pbufferAttribs));
|
||||
} else if (surfaceType == EGLSurfaceType::WINDOW) {
|
||||
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
|
||||
55
cocos/renderer/gfx-gles3/GLES3Swapchain.h
Normal file
55
cocos/renderer/gfx-gles3/GLES3Swapchain.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXSwapchain.h"
|
||||
|
||||
namespace cc {
|
||||
class IXRInterface;
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUSwapchain;
|
||||
|
||||
class CC_GLES3_API GLES3Swapchain final : public Swapchain {
|
||||
public:
|
||||
GLES3Swapchain();
|
||||
~GLES3Swapchain() override;
|
||||
|
||||
inline GLES3GPUSwapchain *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;
|
||||
|
||||
GLES3GPUSwapchain *_gpuSwapchain{nullptr};
|
||||
IXRInterface *_xr{nullptr};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
183
cocos/renderer/gfx-gles3/GLES3Texture.cpp
Normal file
183
cocos/renderer/gfx-gles3/GLES3Texture.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
|
||||
#include "GLES3Commands.h"
|
||||
#include "GLES3Device.h"
|
||||
#include "GLES3Swapchain.h"
|
||||
#include "GLES3Texture.h"
|
||||
#include "base/Macros.h"
|
||||
#include "profiler/Profiler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Texture::GLES3Texture() {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
}
|
||||
|
||||
GLES3Texture::~GLES3Texture() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GLES3Texture::doInit(const TextureInfo & /*info*/) {
|
||||
_gpuTexture = ccnew GLES3GPUTexture;
|
||||
_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->glSamples = static_cast<GLint>(_info.samples);
|
||||
_gpuTexture->flags = _info.flags;
|
||||
_gpuTexture->size = _size;
|
||||
_gpuTexture->isPowerOf2 = math::isPowerOfTwo(_info.width) && math::isPowerOfTwo(_info.height);
|
||||
|
||||
bool hasExternalFlag = hasFlag(_gpuTexture->flags, TextureFlagBit::EXTERNAL_NORMAL) ||
|
||||
hasFlag(_gpuTexture->flags, TextureFlagBit::EXTERNAL_OES);
|
||||
if (_info.externalRes && !hasExternalFlag) {
|
||||
// compatibility
|
||||
_gpuTexture->flags = _gpuTexture->flags | TextureFlagBit::EXTERNAL_OES;
|
||||
hasExternalFlag = true;
|
||||
}
|
||||
|
||||
if (hasExternalFlag) {
|
||||
_gpuTexture->glTexture = static_cast<GLuint>(reinterpret_cast<size_t>(_info.externalRes));
|
||||
}
|
||||
|
||||
cmdFuncGLES3CreateTexture(GLES3Device::getInstance(), _gpuTexture);
|
||||
|
||||
if (_gpuTexture->memoryAllocated) {
|
||||
GLES3Device::getInstance()->getMemoryStatus().textureSize += _size;
|
||||
CC_PROFILE_MEMORY_INC(Texture, _size);
|
||||
}
|
||||
|
||||
_gpuTextureView = ccnew GLES3GPUTextureView;
|
||||
createTextureView();
|
||||
}
|
||||
|
||||
void GLES3Texture::doInit(const TextureViewInfo & /*info*/) {
|
||||
_gpuTexture = static_cast<GLES3Texture *>(_viewInfo.texture)->gpuTexture();
|
||||
|
||||
CC_ASSERT(_viewInfo.texture->getFormat() == _viewInfo.format);
|
||||
|
||||
_gpuTextureView = ccnew GLES3GPUTextureView;
|
||||
createTextureView();
|
||||
}
|
||||
|
||||
void GLES3Texture::createTextureView() {
|
||||
_gpuTextureView->gpuTexture = _gpuTexture;
|
||||
_gpuTextureView->type = _viewInfo.type;
|
||||
_gpuTextureView->format = _viewInfo.format;
|
||||
_gpuTextureView->baseLevel = _viewInfo.baseLevel;
|
||||
_gpuTextureView->levelCount = _viewInfo.levelCount;
|
||||
_gpuTextureView->baseLayer = _viewInfo.baseLayer;
|
||||
_gpuTextureView->layerCount = _viewInfo.layerCount;
|
||||
_gpuTextureView->basePlane = _viewInfo.basePlane;
|
||||
_gpuTextureView->planeCount = _viewInfo.planeCount;
|
||||
cmdFuncGLES3CreateTextureView(GLES3Device::getInstance(), _gpuTextureView);
|
||||
|
||||
}
|
||||
|
||||
void GLES3Texture::doDestroy() {
|
||||
CC_SAFE_DELETE(_gpuTextureView);
|
||||
if (_gpuTexture) {
|
||||
if (!_isTextureView) {
|
||||
if (_gpuTexture->memoryAllocated) {
|
||||
GLES3Device::getInstance()->getMemoryStatus().textureSize -= _size;
|
||||
CC_PROFILE_MEMORY_DEC(Texture, _size);
|
||||
}
|
||||
|
||||
cmdFuncGLES3DestroyTexture(GLES3Device::getInstance(), _gpuTexture);
|
||||
GLES3Device::getInstance()->framebufferHub()->disengage(_gpuTexture);
|
||||
delete _gpuTexture;
|
||||
}
|
||||
_gpuTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GLES3Texture::doResize(uint32_t width, uint32_t height, uint32_t size) {
|
||||
if (!_isTextureView && _gpuTexture->memoryAllocated) {
|
||||
GLES3Device::getInstance()->getMemoryStatus().textureSize -= _size;
|
||||
CC_PROFILE_MEMORY_DEC(Texture, _size);
|
||||
}
|
||||
|
||||
_gpuTexture->width = width;
|
||||
_gpuTexture->height = height;
|
||||
_gpuTexture->size = size;
|
||||
_gpuTexture->mipLevel = _info.levelCount;
|
||||
|
||||
cmdFuncGLES3ResizeTexture(GLES3Device::getInstance(), _gpuTexture);
|
||||
|
||||
GLES3Device::getInstance()->framebufferHub()->update(_gpuTexture);
|
||||
|
||||
if (!_isTextureView && _gpuTexture->memoryAllocated) {
|
||||
GLES3Device::getInstance()->getMemoryStatus().textureSize += size;
|
||||
CC_PROFILE_MEMORY_INC(Texture, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GLES3Texture::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 GLES3Texture::doInit(const SwapchainTextureInfo & /*info*/) {
|
||||
_gpuTexture = ccnew GLES3GPUTexture;
|
||||
_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->glSamples = static_cast<GLint>(_info.samples);
|
||||
_gpuTexture->flags = _info.flags;
|
||||
_gpuTexture->size = _size;
|
||||
_gpuTexture->memoryAllocated = false;
|
||||
_gpuTexture->swapchain = static_cast<GLES3Swapchain *>(_swapchain)->gpuSwapchain();
|
||||
_gpuTextureView = ccnew GLES3GPUTextureView;
|
||||
createTextureView();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
59
cocos/renderer/gfx-gles3/GLES3Texture.h
Normal file
59
cocos/renderer/gfx-gles3/GLES3Texture.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Std.h"
|
||||
#include "gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUTexture;
|
||||
struct GLES3GPUTextureView;
|
||||
class CC_GLES3_API GLES3Texture final : public Texture {
|
||||
public:
|
||||
GLES3Texture();
|
||||
~GLES3Texture() override;
|
||||
|
||||
inline GLES3GPUTexture *gpuTexture() const { return _gpuTexture; }
|
||||
inline GLES3GPUTextureView *gpuTextureView() const { return _gpuTextureView; }
|
||||
|
||||
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;
|
||||
|
||||
void createTextureView();
|
||||
|
||||
GLES3GPUTexture *_gpuTexture = nullptr;
|
||||
GLES3GPUTextureView *_gpuTextureView = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
155
cocos/renderer/gfx-gles3/GLES3Wrangler.cpp
Normal file
155
cocos/renderer/gfx-gles3/GLES3Wrangler.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3Wrangler.h"
|
||||
#include <string>
|
||||
#include "base/Log.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(ANDROID)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
|
||||
static HMODULE libegl = NULL;
|
||||
static HMODULE libgles = NULL;
|
||||
static PFNGLES3WLOADPROC pfnGles3wLoad = NULL;
|
||||
|
||||
bool gles3wOpen() {
|
||||
std::string eglPath = "libEGL.dll";
|
||||
std::string glesPath = "libGLESv2.dll";
|
||||
|
||||
#if CC_EDITOR
|
||||
// In editor,there are same library,so we need to use abs path to load them.
|
||||
HMODULE engine = NULL;
|
||||
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
(LPCWSTR)&gles3wOpen, &engine) != 0) {
|
||||
std::string dir;
|
||||
int times = 1;
|
||||
do {
|
||||
auto size = MAX_PATH * times++;
|
||||
char *path = static_cast<char *>(CC_MALLOC(size));
|
||||
if (path) {
|
||||
GetModuleFileNameA(engine, path, size);
|
||||
dir = path;
|
||||
}
|
||||
CC_FREE(path);
|
||||
} while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
dir = dir.substr(0, dir.rfind("\\") + 1);
|
||||
eglPath = dir + eglPath;
|
||||
glesPath = dir + glesPath;
|
||||
} else {
|
||||
DWORD err = GetLastError();
|
||||
CC_LOG_WARNING("Failed to get abs path for editor,error code:%lu", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
libegl = LoadLibraryA(eglPath.c_str());
|
||||
libgles = LoadLibraryA(glesPath.c_str());
|
||||
return (libegl && libgles);
|
||||
}
|
||||
|
||||
bool gles3wClose() {
|
||||
bool ret = true;
|
||||
if (libegl) {
|
||||
ret &= FreeLibrary(libegl) ? true : false;
|
||||
libegl = NULL;
|
||||
}
|
||||
|
||||
if (libgles) {
|
||||
ret &= FreeLibrary(libgles) ? true : false;
|
||||
libgles = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *gles3wLoad(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 gles3wOpen() { return true; }
|
||||
bool gles3wClose() { return true; }
|
||||
void *gles3wLoad(const char *proc) {
|
||||
return (void *)eglGetProcAddress(proc);
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *libegl = nullptr;
|
||||
static void *libgles = nullptr;
|
||||
static PFNGLES3WLOADPROC pfnGles3wLoad = nullptr;
|
||||
|
||||
bool gles3wOpen() {
|
||||
libegl = dlopen("libEGL.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
libgles = dlopen("libGLESv3.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
return (libegl && libgles);
|
||||
}
|
||||
|
||||
bool gles3wClose() {
|
||||
bool ret = true;
|
||||
if (libegl) {
|
||||
ret &= dlclose(libegl) == 0;
|
||||
libegl = nullptr;
|
||||
}
|
||||
|
||||
if (libgles) {
|
||||
ret &= dlclose(libgles) == 0;
|
||||
libgles = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *gles3wLoad(const char *proc) {
|
||||
void *res = nullptr;
|
||||
if (eglGetProcAddress) res = reinterpret_cast<void *>(eglGetProcAddress(proc));
|
||||
if (!res) res = dlsym(libegl, proc);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
PFNGLES3WLOADPROC pfnGLES3wLoadProc() {
|
||||
return pfnGles3wLoad;
|
||||
}
|
||||
|
||||
bool gles3wInit() {
|
||||
if (!gles3wOpen()) {
|
||||
return false;
|
||||
}
|
||||
eglwLoadProcs(gles3wLoad);
|
||||
gles2wLoadProcs(gles3wLoad);
|
||||
gles3wLoadProcs(gles3wLoad);
|
||||
|
||||
pfnGles3wLoad = gles3wLoad;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gles3wExit() {
|
||||
return gles3wClose();
|
||||
}
|
||||
33
cocos/renderer/gfx-gles3/GLES3Wrangler.h
Normal file
33
cocos/renderer/gfx-gles3/GLES3Wrangler.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
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"
|
||||
#include "../gfx-gles-common/gles3w.h"
|
||||
|
||||
PFNGLES3WLOADPROC pfnGLES3wLoadProc();
|
||||
bool gles3wInit();
|
||||
bool gles3wExit();
|
||||
47
cocos/renderer/gfx-gles3/states/GLES3GeneralBarrier.cpp
Normal file
47
cocos/renderer/gfx-gles3/states/GLES3GeneralBarrier.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
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 "GLES3GeneralBarrier.h"
|
||||
#include "../GLES3Commands.h"
|
||||
#include "gfx-gles3/GLES3Device.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3GeneralBarrier::GLES3GeneralBarrier(const GeneralBarrierInfo &info) : GeneralBarrier(info) {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
|
||||
_gpuBarrier = ccnew GLES3GPUGeneralBarrier;
|
||||
_gpuBarrier->prevAccesses = info.prevAccesses;
|
||||
_gpuBarrier->nextAccesses = info.nextAccesses;
|
||||
|
||||
cmdFuncGLES3CreateGeneralBarrier(GLES3Device::getInstance(), _gpuBarrier);
|
||||
}
|
||||
|
||||
GLES3GeneralBarrier::~GLES3GeneralBarrier() {
|
||||
CC_SAFE_DELETE(_gpuBarrier);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
47
cocos/renderer/gfx-gles3/states/GLES3GeneralBarrier.h
Normal file
47
cocos/renderer/gfx-gles3/states/GLES3GeneralBarrier.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
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 "../GLES3Std.h"
|
||||
#include "gfx-base/states/GFXGeneralBarrier.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct GLES3GPUGeneralBarrier;
|
||||
|
||||
class CC_GLES3_API GLES3GeneralBarrier : public GeneralBarrier {
|
||||
public:
|
||||
explicit GLES3GeneralBarrier(const GeneralBarrierInfo &info);
|
||||
~GLES3GeneralBarrier() override;
|
||||
|
||||
inline const GLES3GPUGeneralBarrier *gpuBarrier() const { return _gpuBarrier; }
|
||||
|
||||
protected:
|
||||
GLES3GPUGeneralBarrier *_gpuBarrier = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
52
cocos/renderer/gfx-gles3/states/GLES3Sampler.cpp
Normal file
52
cocos/renderer/gfx-gles3/states/GLES3Sampler.cpp
Normal 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.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GLES3Sampler.h"
|
||||
#include "../GLES3Commands.h"
|
||||
#include "../GLES3Device.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GLES3Sampler::GLES3Sampler(const SamplerInfo &info) : Sampler(info) {
|
||||
_typedID = generateObjectID<decltype(this)>();
|
||||
|
||||
_gpuSampler = ccnew GLES3GPUSampler;
|
||||
_gpuSampler->minFilter = _info.minFilter;
|
||||
_gpuSampler->magFilter = _info.magFilter;
|
||||
_gpuSampler->mipFilter = _info.mipFilter;
|
||||
_gpuSampler->addressU = _info.addressU;
|
||||
_gpuSampler->addressV = _info.addressV;
|
||||
_gpuSampler->addressW = _info.addressW;
|
||||
|
||||
// GL is not thread-safe, so any actual gl invocations need to be deferred to device thread
|
||||
cmdFuncGLES3PrepareSamplerInfo(GLES3Device::getInstance(), _gpuSampler);
|
||||
}
|
||||
|
||||
GLES3Sampler::~GLES3Sampler() {
|
||||
CC_SAFE_DELETE(_gpuSampler);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
47
cocos/renderer/gfx-gles3/states/GLES3Sampler.h
Normal file
47
cocos/renderer/gfx-gles3/states/GLES3Sampler.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
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 "../GLES3Std.h"
|
||||
#include "gfx-base/states/GFXSampler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GLES3GPUSampler;
|
||||
|
||||
class CC_GLES3_API GLES3Sampler final : public Sampler {
|
||||
public:
|
||||
explicit GLES3Sampler(const SamplerInfo &info);
|
||||
~GLES3Sampler() override;
|
||||
|
||||
inline GLES3GPUSampler *gpuSampler() const { return _gpuSampler; }
|
||||
|
||||
protected:
|
||||
GLES3GPUSampler *_gpuSampler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
Reference in New Issue
Block a user