#include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace extra2d { // ======================================== // CommandSorter 实现 // ======================================== CommandSorter::CommandSorter() { // 预分配初始容量 commands_.reserve(INITIAL_CAPACITY); sortedIndices_.reserve(INITIAL_CAPACITY); } CommandSorter::~CommandSorter() = default; CommandSorter::CommandSorter(CommandSorter&& other) noexcept : commands_(std::move(other.commands_)), sortedIndices_(std::move(other.sortedIndices_)), commandCount_(other.commandCount_) { other.commandCount_ = 0; } CommandSorter& CommandSorter::operator=(CommandSorter&& other) noexcept { if (this != &other) { commands_ = std::move(other.commands_); sortedIndices_ = std::move(other.sortedIndices_); commandCount_ = other.commandCount_; other.commandCount_ = 0; } return *this; } uint32_t CommandSorter::addCommand(const DrawCommand &cmd) { uint32_t index = commandCount_; // 如果缓冲区不够大,扩展它 if (index >= commands_.size()) { commands_.push_back(cmd); sortedIndices_.push_back(index); } else { commands_[index] = cmd; sortedIndices_[index] = index; } commandCount_++; return index; } void CommandSorter::sort() { if (commandCount_ == 0) return; // 只排序有效范围的索引 auto indicesBegin = sortedIndices_.begin(); auto indicesEnd = sortedIndices_.begin() + commandCount_; // 使用稳定排序保持相同键的命令顺序 std::stable_sort(indicesBegin, indicesEnd, [this](uint32_t a, uint32_t b) { return commands_[a].key < commands_[b].key; }); } void CommandSorter::clear() { // 重置计数器,保留内存 commandCount_ = 0; } void CommandSorter::reserve(uint32_t capacity) { commands_.reserve(capacity); sortedIndices_.reserve(capacity); } // ======================================== // CommandBatcher 实现 // ======================================== void CommandBatcher::process(const CommandSorter &sorter) { clear(); sorter_ = &sorter; if (sorter.getCount() == 0) { return; } CommandBatch currentBatch; currentBatch.startIndex = 0; currentBatch.count = 1; const auto &firstCmd = sorter.getCommand(0); currentBatch.pipeline = firstCmd.pipeline; currentBatch.textureCount = firstCmd.textureCount; for (uint32_t i = 0; i < firstCmd.textureCount; ++i) { currentBatch.textures[i] = firstCmd.textures[i]; } // 遍历所有命令,合并兼容的命令 for (uint32_t i = 1; i < sorter.getCount(); ++i) { const auto &cmd = sorter.getCommand(i); if (currentBatch.isCompatibleWith(cmd)) { // 兼容,加入当前批次 currentBatch.count++; } else { // 不兼容,保存当前批次并创建新批次 batches_.push_back(currentBatch); currentBatch.startIndex = i; currentBatch.count = 1; currentBatch.pipeline = cmd.pipeline; currentBatch.textureCount = cmd.textureCount; for (uint32_t j = 0; j < cmd.textureCount; ++j) { currentBatch.textures[j] = cmd.textures[j]; } } } // 保存最后一个批次 batches_.push_back(currentBatch); } const DrawCommand &CommandBatcher::getCommand(uint32_t batchIndex, uint32_t cmdIndex) const { const auto &batch = batches_[batchIndex]; return sorter_->getCommand(batch.startIndex + cmdIndex); } void CommandBatcher::clear() { batches_.clear(); sorter_ = nullptr; } // ======================================== // CommandQueue 实现 // ======================================== CommandQueue::CommandQueue() = default; CommandQueue::~CommandQueue() { shutdown(); } CommandQueue::CommandQueue(CommandQueue &&other) noexcept : sorter_(std::move(other.sorter_)), batcher_(std::move(other.batcher_)), context_(other.context_), commandList_(std::move(other.commandList_)), uboManager_(std::move(other.uboManager_)), globalUBOData_(other.globalUBOData_), materialUBOData_(std::move(other.materialUBOData_)), nextMaterialId_(other.nextMaterialId_), materialIds_(std::move(other.materialIds_)), currentMaterialUBO_(other.currentMaterialUBO_), materialUBOBufferOffset_(other.materialUBOBufferOffset_) { other.context_ = nullptr; other.globalUBOData_ = {}; other.nextMaterialId_ = 1; other.currentMaterialUBO_ = nullptr; other.materialUBOBufferOffset_ = 0; } CommandQueue &CommandQueue::operator=(CommandQueue &&other) noexcept { if (this != &other) { shutdown(); sorter_ = std::move(other.sorter_); batcher_ = std::move(other.batcher_); context_ = other.context_; commandList_ = std::move(other.commandList_); uboManager_ = std::move(other.uboManager_); globalUBOData_ = other.globalUBOData_; materialUBOData_ = std::move(other.materialUBOData_); nextMaterialId_ = other.nextMaterialId_; materialIds_ = std::move(other.materialIds_); currentMaterialUBO_ = other.currentMaterialUBO_; materialUBOBufferOffset_ = other.materialUBOBufferOffset_; other.context_ = nullptr; other.globalUBOData_ = {}; other.nextMaterialId_ = 1; other.currentMaterialUBO_ = nullptr; other.materialUBOBufferOffset_ = 0; } return *this; } bool CommandQueue::initialize() { // 获取 RHI 模块 auto *rhiModule = RHIModule::get(); if (!rhiModule) { E2D_LOG_ERROR("RHIModule not available"); return false; } auto *device = rhiModule->getDevice(); if (!device) { E2D_LOG_ERROR("RHIDevice not available"); return false; } context_ = rhiModule->getContext(); if (!context_) { E2D_LOG_ERROR("RHIContext not available"); return false; } // 创建命令列表 commandList_ = device->createCommandList(); if (!commandList_) { E2D_LOG_ERROR("Failed to create command list"); return false; } // 初始化 UBO 管理器 uboManager_ = std::make_unique(); if (!uboManager_->initialize()) { E2D_LOG_ERROR("Failed to initialize UniformBufferManager"); return false; } // 预分配材质 UBO 数据缓冲区 materialUBOData_.reserve(1024 * 1024); // 1MB E2D_LOG_INFO("CommandQueue initialized"); return true; } void CommandQueue::shutdown() { uboManager_.reset(); commandList_.reset(); context_ = nullptr; materialUBOData_.clear(); E2D_LOG_INFO("CommandQueue shutdown"); } void CommandQueue::beginFrame() { sorter_.clear(); batcher_.clear(); materialIds_.clear(); nextMaterialId_ = 1; // 重置材质 UBO 缓冲区(保留容量,避免重新分配) materialUBOBufferOffset_ = 0; currentMaterialUBO_ = nullptr; // 重置 UBO 管理器的材质 UBO 池 if (uboManager_) { uboManager_->resetMaterialUBOs(); } // 重置统计 stats_ = {}; // 开始录制命令 if (commandList_) { commandList_->begin(); } } void CommandQueue::endFrame() { // 结束录制 if (commandList_) { commandList_->end(); } } uint32_t CommandQueue::getMaterialId(Material *material) { auto it = materialIds_.find(material); if (it != materialIds_.end()) { return it->second; } uint32_t id = nextMaterialId_++; materialIds_[material] = id; return id; } std::pair CommandQueue::allocateMaterialUBO(uint32_t size) { if (!uboManager_ || size == 0) { return {nullptr, 0}; } // OpenGL 要求 UBO 偏移对齐到 GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT (通常是 256) static constexpr uint32_t UBO_ALIGNMENT = 256; // 使用批量更新机制:先分配到 CPU 缓冲区 uint32_t offset = materialUBOBufferOffset_; // 对齐到 UBO_ALIGNMENT 字节 offset = (offset + UBO_ALIGNMENT - 1) & ~(UBO_ALIGNMENT - 1); uint32_t alignedSize = (size + UBO_ALIGNMENT - 1) & ~(UBO_ALIGNMENT - 1); // 检查 CPU 缓冲区是否有足够空间 if (offset + alignedSize > materialUBOData_.capacity()) { // 如果缓冲区已满,先刷新到 GPU flushMaterialUBOToGPU(); offset = 0; // 重置偏移量 } // 确保缓冲区足够大 if (offset + alignedSize > materialUBOData_.size()) { materialUBOData_.resize(offset + alignedSize); } materialUBOBufferOffset_ = offset + alignedSize; return {nullptr, offset}; // 返回 nullptr 表示使用 CPU 缓冲区,offset 是 CPU 缓冲区偏移 } void CommandQueue::flushMaterialUBOToGPU() { if (materialUBOBufferOffset_ == 0) { return; } // 获取一个足够大的 UBO currentMaterialUBO_ = uboManager_->acquireMaterialUBO(materialUBOBufferOffset_); if (!currentMaterialUBO_) { E2D_LOG_ERROR("Failed to acquire material UBO for flush"); return; } // 批量更新到 GPU currentMaterialUBO_->update(materialUBOData_.data(), materialUBOBufferOffset_, 0); // 重置 CPU 缓冲区偏移 materialUBOBufferOffset_ = 0; } UniformBuffer* CommandQueue::getCurrentMaterialUBO() const { return currentMaterialUBO_; } void CommandQueue::submitDraw(Ptr material, Ptr mesh, const struct Transform &transform, const Color &color) { if (!material || !mesh || !material->getShader()) { return; } DrawCommand cmd; // 构建排序键 uint32_t materialId = getMaterialId(material.get()); cmd.key = DrawKey::make(materialId, 0, 0); // 设置管线 cmd.pipeline = material->getPipeline(); // 设置网格数据 cmd.vertexBuffer = mesh->getVertexBuffer(); cmd.indexBuffer = mesh->getIndexBuffer(); cmd.vertexCount = mesh->getVertexCount(); cmd.indexCount = mesh->getIndexCount(); // 设置变换和颜色 float matrixData[16]; transform.toMatrix(matrixData); cmd.modelMatrix = glm::make_mat4(matrixData); cmd.color = color; // 设置纹理 const auto &textures = material->getTextures(); cmd.textureCount = static_cast(std::min(textures.size(), size_t(8))); for (uint32_t i = 0; i < cmd.textureCount; ++i) { if (textures[i].texture) { cmd.textures[i] = textures[i].texture->getHandle(); } } // 分配材质 UBO 空间(使用 CPU 缓冲区) uint32_t materialDataSize = material->getDataSize(); if (materialDataSize > 0) { auto [ubo, offset] = allocateMaterialUBO(materialDataSize); (void)ubo; // ubo 为 nullptr,使用 CPU 缓冲区 // 复制材质数据到 CPU 缓冲区,并修改颜色 if (offset + materialDataSize <= materialUBOData_.size()) { std::memcpy(materialUBOData_.data() + offset, material->getData(), materialDataSize); // 将实例颜色应用到 UBO 数据中的 uColor 参数 auto layout = material->getLayout(); if (layout) { const auto* param = layout->getParam("uColor"); if (param && param->type == MaterialParamType::Color) { std::memcpy(materialUBOData_.data() + offset + param->offset, &color.r, sizeof(float) * 4); } } cmd.materialUBOOffset = offset; cmd.materialUBOSize = materialDataSize; } } sorter_.addCommand(cmd); } void CommandQueue::submitClear(const Color &color, uint32_t flags) { // 清除命令直接执行,不加入排序队列 if (!commandList_) { return; } commandList_->clear(static_cast(flags), color, 1.0f, 0); } void CommandQueue::setViewport(int32_t x, int32_t y, int32_t width, int32_t height) { if (!commandList_) { return; } Viewport viewport; viewport.x = static_cast(x); viewport.y = static_cast(y); viewport.width = static_cast(width); viewport.height = static_cast(height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; commandList_->setViewport(viewport); } void CommandQueue::updateGlobalUBO(const Mat4& viewProjection, float deltaTime, uint32_t screenWidth, uint32_t screenHeight, uint32_t frameIndex) { if (!uboManager_) { E2D_LOG_WARN("CommandQueue::updateGlobalUBO: uboManager is null"); return; } // 填充全局 UBO 数据 std::memcpy(globalUBOData_.viewProjection, glm::value_ptr(viewProjection), sizeof(float) * 16); globalUBOData_.cameraPosition[0] = 0.0f; globalUBOData_.cameraPosition[1] = 0.0f; globalUBOData_.cameraPosition[2] = 0.0f; globalUBOData_.cameraPosition[3] = 1.0f; globalUBOData_.time = 0.0f; // TODO: 传递实际时间 globalUBOData_.deltaTime = deltaTime; globalUBOData_.screenSize[0] = static_cast(screenWidth); globalUBOData_.screenSize[1] = static_cast(screenHeight); // 使用双缓冲更新 UBO uboManager_->updateGlobalUBO(&globalUBOData_, sizeof(globalUBOData_), frameIndex); } void CommandQueue::execute(uint32_t frameIndex) { if (!commandList_) { E2D_LOG_ERROR("CommandQueue::execute: commandList is null"); return; } // 在排序前刷新材质 UBO 数据到 GPU flushMaterialUBOToGPU(); // 排序命令 sorter_.sort(); // 批处理 batcher_.process(sorter_); // 执行批次 for (uint32_t i = 0; i < batcher_.getBatchCount(); ++i) { executeBatch(i, batcher_.getBatch(i), frameIndex); } // 提交命令到 GPU commandList_->submit(); } void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch, uint32_t frameIndex) { if (!commandList_) { return; } // 绑定管线 if (batch.pipeline.isValid()) { commandList_->setPipeline(batch.pipeline.get()); stats_.pipelineBinds++; } else { E2D_LOG_WARN("Batch has no valid pipeline!"); } // 绑定全局 UBO (binding = 0) - 使用双缓冲 if (uboManager_) { UniformBuffer* globalUBO = uboManager_->getGlobalUBO(frameIndex); if (globalUBO) { commandList_->setUniformBuffer(0, globalUBO->getRHIBuffer()); stats_.bufferBinds++; } } // 绑定纹理 if (batch.textureCount > 0) { for (uint32_t i = 0; i < batch.textureCount; ++i) { if (batch.textures[i].isValid()) { commandList_->setTexture(i, batch.textures[i].get()); stats_.textureBinds++; } } } // 执行批次中的所有命令 for (uint32_t i = 0; i < batch.count; ++i) { const auto &cmd = batcher_.getCommand(batchIndex, i); // 绑定顶点缓冲区 if (cmd.vertexBuffer.isValid()) { commandList_->setVertexBuffer(0, cmd.vertexBuffer.get(), 0); stats_.bufferBinds++; } else { E2D_LOG_WARN("Draw command has no valid vertex buffer!"); } // 绑定索引缓冲区(如果有) if (cmd.isIndexed() && cmd.indexBuffer.isValid()) { commandList_->setIndexBuffer(cmd.indexBuffer.get(), IndexType::UInt16, 0); stats_.bufferBinds++; } // 绑定材质 UBO (binding = 1) if (cmd.materialUBOSize > 0 && currentMaterialUBO_) { commandList_->setUniformBuffer(1, currentMaterialUBO_->getRHIBuffer(), cmd.materialUBOOffset, cmd.materialUBOSize); stats_.bufferBinds++; } // 设置模型矩阵 commandList_->setUniform("uModelMatrix", cmd.modelMatrix); // 绘制 if (cmd.isIndexed()) { commandList_->drawIndexed(cmd.indexCount, 0, 0, 1, 0); stats_.drawCalls++; stats_.triangles += cmd.indexCount / 3; } else { commandList_->draw(cmd.vertexCount, 0, 1, 0); stats_.drawCalls++; stats_.triangles += cmd.vertexCount / 3; } stats_.vertices += cmd.vertexCount; } } } // namespace extra2d