Files
salmanoff/stimBuffApis/livoxGen1/openClCollatingAndMeshingEngine.h
T
hayodea 1dc74065fb OClCollMeshEngn: cleanup and get it working on RPi5+Rusticl+V3D GPU
It seems that whenever you have an HOST_PTR input buffer to be
"transferred" from the host to the GPU, whose contents must be
preserved, you must map it with WRITE_INVALIDATE_REGION on the
RPi5.

This makes little sense, but we'll have to let it be for now.
At least the code works now and we don't have to abandon using
OpenCL.
2025-11-12 12:36:41 -04:00

215 lines
5.6 KiB
C++

#ifndef _LIVOX_GEN1_OPENCL_COLLATING_AND_MESHING_ENGINE_H
#define _LIVOX_GEN1_OPENCL_COLLATING_AND_MESHING_ENGINE_H
#include <boostAsioLinkageFix.h>
#include <cstdint>
#include <cstddef>
#include <memory>
#include <functional>
#include <iostream>
#include <stdexcept>
#define CL_TARGET_OPENCL_VERSION 300
#include <CL/cl.h>
#include <asynchronousLoop.h>
#include <callback.h>
#include <user/stimulusFrame.h>
#include "stagingBuffer.h"
#include "frameAssemblyDesc.h"
namespace smo {
namespace stim_buff {
class PcloudStimulusBuffer;
class OpenClCollatingAndMeshingEngine
{
public:
explicit OpenClCollatingAndMeshingEngine(PcloudStimulusBuffer& parent);
~OpenClCollatingAndMeshingEngine();
// Non-copyable, movable
OpenClCollatingAndMeshingEngine(
const OpenClCollatingAndMeshingEngine&) = delete;
OpenClCollatingAndMeshingEngine& operator=(
const OpenClCollatingAndMeshingEngine&) = delete;
OpenClCollatingAndMeshingEngine(
OpenClCollatingAndMeshingEngine&&) = default;
OpenClCollatingAndMeshingEngine& operator=(
OpenClCollatingAndMeshingEngine&&) = default;
bool setup();
void finalize();
// Callback function types
typedef std::function<void(cl_int)> compactKernelCbFn;
typedef std::function<void(cl_int)> collateKernelCbFn;
typedef std::function<void(bool, StimulusFrame&)>
compactCollateAndMeshFrameReqCbFn;
bool startCompactKernel(
StagingBuffer& assemblyBuff, uint32_t nSucceeded,
compactKernelCbFn callback);
bool startCollateKernel(
StagingBuffer& assemblyBuff, StagingBuffer& collationBuff,
collateKernelCbFn callback);
void stopCompactKernel();
void stopCollateKernel();
void stop();
void compactCollateAndMeshFrameReq(
AsynchronousLoop& asyncLoop, StimulusFrame& stimulusFrame,
Callback<compactCollateAndMeshFrameReqCbFn> callback);
private:
PcloudStimulusBuffer& parent;
// OpenCL infrastructure
cl_platform_id platform;
cl_device_id device;
cl_context context;
cl_command_queue commandQueue;
cl_program slotCompactorProgram;
cl_program collateProgram;
cl_kernel slotCompactorKernel;
cl_kernel collateKernel;
bool isSetup;
// OpenCL buffers
cl_mem clAssemblyBuffer;
cl_mem clCollationBuffer;
// State tracking
bool compactIsSetup;
bool compactIsRunning;
bool collateIsSetup;
bool collateIsRunning;
cl_event currentCompactKernelEvent;
cl_event currentCollateKernelEvent;
// Memory tracking
void* assemblyBufferPtr;
size_t assemblyBufferSize;
void* collationBufferPtr;
size_t collationBufferSize;
// Mapped buffer pointers (for zero-copy synchronization)
void* mappedAssemblyBuffer;
void* mappedCollationBuffer;
// Frame descriptor (cached from setup)
std::shared_ptr<FrameAssemblyDesc> frameAssemblyDesc;
// Callback storage
compactKernelCbFn compactKernelCb;
collateKernelCbFn collateKernelCb;
// Static callbacks for OpenCL events
static void CL_CALLBACK compactKernelEventCallback(
cl_event event, cl_int event_command_exec_status, void* user_data);
static void CL_CALLBACK collateKernelEventCallback(
cl_event event, cl_int event_command_exec_status, void* user_data);
// Private helper methods
bool compileAndPrepareKernel(
const char* kernelSource, size_t kernelSourceLen,
const char* kernelName, cl_program& program, cl_kernel& kernel);
bool compileAndPrepareKernels();
bool setupSlotCompactorsArgs(
StagingBuffer& assemblyBuff, uint32_t nSucceeded);
bool setupCollateDgramsArgs(StagingBuffer& assemblyBuff);
// Generic buffer mapping/unmapping for zero-copy synchronization
bool mapBuffer(
cl_mem buffer, size_t size, cl_map_flags mapFlags, void*& mappedPtr);
bool unmapBuffer(cl_mem buffer, void*& mappedPtr);
// Wrapper functions for specific buffers
bool mapAssemblyBuffer(cl_map_flags mapFlags = CL_MAP_READ);
bool unmapAssemblyBuffer();
bool mapCollationBuffer(cl_map_flags mapFlags = CL_MAP_READ);
bool unmapCollationBuffer();
// Forward declaration for continuation class
class CompactCollateAndMeshFrameReq;
// Unified kernel start function
template<typename SetupArgsFn, typename ValidateBuffersFn>
bool startKernel(
cl_kernel kernel,
cl_event* eventPtr,
SetupArgsFn setupArgsFn,
ValidateBuffersFn validateBuffersFn,
size_t globalWorkSize,
void (CL_CALLBACK *eventCallback)(cl_event, cl_int, void*),
const char* kernelName,
bool& isSetup,
bool& isRunning)
{
if (!isSetup)
{
std::cerr << __func__ << ": engine not set up" << std::endl;
return false;
}
if (isRunning)
{
std::cerr << __func__ << ": already running, call stop() first"
<< std::endl;
return false;
}
// Validate buffers
validateBuffersFn();
// Set up kernel arguments
if (!setupArgsFn()) {
return false;
}
// Enqueue kernel execution
cl_int err = clEnqueueNDRangeKernel(
commandQueue, kernel, 1, nullptr, &globalWorkSize, nullptr,
0, nullptr, eventPtr);
if (err != CL_SUCCESS)
{
std::cerr << __func__ << ": failed to enqueue " << kernelName
<< " kernel: " << err << std::endl;
return false;
}
// Set up callback using static member function
err = clSetEventCallback(
*eventPtr, CL_COMPLETE, eventCallback, this);
if (err != CL_SUCCESS)
{
std::cerr << __func__ << ": failed to set event callback: " << err
<< std::endl;
clReleaseEvent(*eventPtr);
*eventPtr = nullptr;
return false;
}
// Force queue flush to ensure event processing and callback invocation
err = clFlush(commandQueue);
if (err != CL_SUCCESS)
{
std::cerr << __func__ << ": failed to flush queue: " << err
<< std::endl;
clReleaseEvent(*eventPtr);
*eventPtr = nullptr;
return false;
}
isRunning = true;
return true;
}
};
} // namespace stim_buff
} // namespace smo
#endif // _LIVOX_GEN1_OPENCL_COLLATING_AND_MESHING_ENGINE_H