Lg1: Implement both light|darkAmbience stimBuffs & their production

We now produce both light and dark ambience stimframes into
stimbuffs for the LivoxGen1 lidar devices.
This commit is contained in:
2026-04-18 14:54:14 -04:00
parent 632a227985
commit 27a5d48451
15 changed files with 668 additions and 336 deletions
+120 -44
View File
@@ -54,20 +54,29 @@ static StagingBuffer::IOEngineConstraints openClIntensityInputConstraints(
// framePadToNBytes (pointer size)
static_cast<size_t>(sysconf(_SC_PAGE_SIZE)));
/* IOEngineConstraints for PcloudAmbienceStimulusBuffer's StagingBuffer, which
* backs SpMcRingBuffer (one StimulusFrame per ring slot). Not the OpenCL
* collating engine's assembly/collation buffers — those use assemblyBuffer /
* collationBuffer above. slotPadToNBytes here is the byte size of each ringbuff
* slot: nDgramsPerStagingBufferFrame floats (set in ctor).
/* IOEngineConstraints for Pcloud[Light|Dark]AmbienceStimulusBuffer's
* StagingBuffer, which backs SpMcRingBuffer (one StimulusFrame per ring
* slot — a single uint32 passband count). slotPadToNBytes is sized in
* ctor to sizeof(uint32_t).
*/
static StagingBuffer::IOEngineConstraints openClAmbienceInputConstraints(
sizeof(float),
sizeof(float),
sizeof(uint32_t),
sizeof(uint32_t),
// frameStartAlignmentByteVal (page alignment)
static_cast<size_t>(sysconf(_SC_PAGE_SIZE)),
// framePadToNBytes (page alignment)
static_cast<size_t>(sysconf(_SC_PAGE_SIZE)));
/* IOEngineConstraints for OClCollMeshEngn's per-slot averageIntensityBuffer
* staging area. Holds nDgramsPerStagingBufferFrame floats; attached ambience
* stimbuffs read from it to compute passband counts after collate.
*/
static StagingBuffer::IOEngineConstraints openClAverageIntensityConstraints(
sizeof(float),
sizeof(float),
static_cast<size_t>(sysconf(_SC_PAGE_SIZE)),
static_cast<size_t>(sysconf(_SC_PAGE_SIZE)));
PcloudStimulusProducer::PcloudStimulusProducer(
const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec,
std::shared_ptr<livoxProto1::Device> &device,
@@ -90,6 +99,11 @@ collationBuffer(
StagingBuffer::IOEngineConstraints::openClInputConstraints,
nDgramsPerStagingBufferFrame),
collationBufferMlockPinner(collationBuffer.makeMlockPinner()),
averageIntensityBuffer(
openClAverageIntensityConstraints,
openClAverageIntensityConstraints,
nDgramsPerStagingBufferFrame),
averageIntensityBufferMlockPinner(averageIntensityBuffer.makeMlockPinner()),
pcloudFrameDumper(deviceAttachmentSpec),
tempStimulusFrameMem(0),
tempStimulusFrame(
@@ -99,10 +113,6 @@ tempStimulusFrame(
sizeof(tempStimulusFrameMem)},
*smoHooksPtr, 0, SIZE_MAX)
{
// See comment in openClAmbienceInputConstraints above.
openClAmbienceInputConstraints.slotPadToNBytes =
nDgramsPerStagingBufferFrame * sizeof(float);
if (smoHooksPtr->OptionParser_getOptions().verbose)
{
std::cout << __func__ << ": assembly buffer : "
@@ -133,7 +143,8 @@ bool PcloudStimulusProducer::supportsQualeIfaceApi(
const std::string& qualeIfaceApi)
{
return qualeIfaceApi == "mesh" || qualeIfaceApi == "pcloudIntensity" ||
qualeIfaceApi == "pcloudAmbience";
qualeIfaceApi == "pcloudLightAmbience" ||
qualeIfaceApi == "pcloudDarkAmbience";
}
bool PcloudStimulusProducer::exportsQualeIfaceApi(
@@ -224,9 +235,14 @@ PcloudStimulusProducer::getAttachedStimulusBuffer(
if (std::dynamic_pointer_cast<PcloudIntensityStimulusBuffer>(buffer))
{ return buffer; }
}
else if (qualeIfaceApi == "pcloudAmbience")
else if (qualeIfaceApi == "pcloudLightAmbience")
{
if (std::dynamic_pointer_cast<PcloudAmbienceStimulusBuffer>(buffer))
if (std::dynamic_pointer_cast<PcloudLightAmbienceStimulusBuffer>(buffer))
{ return buffer; }
}
else if (qualeIfaceApi == "pcloudDarkAmbience")
{
if (std::dynamic_pointer_cast<PcloudDarkAmbienceStimulusBuffer>(buffer))
{ return buffer; }
}
@@ -254,11 +270,19 @@ void PcloudStimulusProducer::destroyAttachedStimulusBuffer(
intensityBuff.reset();
intensityStimulusBuffer.store(nullptr, std::memory_order_release);
}
auto ambienceBuff = ambienceStimulusBuffer.load(std::memory_order_acquire);
if (ambienceBuff == buffer)
auto lightAmbienceBuff = lightAmbienceStimulusBuffer.load(
std::memory_order_acquire);
if (lightAmbienceBuff == buffer)
{
ambienceBuff.reset();
ambienceStimulusBuffer.store(nullptr, std::memory_order_release);
lightAmbienceBuff.reset();
lightAmbienceStimulusBuffer.store(nullptr, std::memory_order_release);
}
auto darkAmbienceBuff = darkAmbienceStimulusBuffer.load(
std::memory_order_acquire);
if (darkAmbienceBuff == buffer)
{
darkAmbienceBuff.reset();
darkAmbienceStimulusBuffer.store(nullptr, std::memory_order_release);
}
// Call base class implementation to remove from attachedStimulusBuffers
@@ -330,26 +354,45 @@ PcloudStimulusProducer::getOrCreateAttachedStimulusBuffer(
this->start();
return intensityBuffer;
}
else if (qualeIfaceApi == "pcloudAmbience")
else if (qualeIfaceApi == "pcloudLightAmbience")
{
auto ambienceStimBuff = std::make_shared<PcloudAmbienceStimulusBuffer>(
*this, deviceAttachmentSpec, histbuffMs,
openClAmbienceInputConstraints, openClAmbienceInputConstraints,
*smoHooksPtr, CL_MEM_READ_WRITE,
this->nDgramsPerStagingBufferFrame);
auto lightAmbienceStimBuff =
std::make_shared<PcloudLightAmbienceStimulusBuffer>(
*this, deviceAttachmentSpec, histbuffMs,
openClAmbienceInputConstraints, openClAmbienceInputConstraints,
*smoHooksPtr, CL_MEM_READ_WRITE,
this->nDgramsPerStagingBufferFrame);
this->stop();
addAttachedStimulusBufferIfNotExists(ambienceStimBuff);
ambienceStimulusBuffer.store(ambienceStimBuff, std::memory_order_release);
addAttachedStimulusBufferIfNotExists(lightAmbienceStimBuff);
lightAmbienceStimulusBuffer.store(
lightAmbienceStimBuff, std::memory_order_release);
this->start();
return ambienceStimBuff;
return lightAmbienceStimBuff;
}
else if (qualeIfaceApi == "pcloudDarkAmbience")
{
auto darkAmbienceStimBuff =
std::make_shared<PcloudDarkAmbienceStimulusBuffer>(
*this, deviceAttachmentSpec, histbuffMs,
openClAmbienceInputConstraints, openClAmbienceInputConstraints,
*smoHooksPtr, CL_MEM_READ_WRITE,
this->nDgramsPerStagingBufferFrame);
this->stop();
addAttachedStimulusBufferIfNotExists(darkAmbienceStimBuff);
darkAmbienceStimulusBuffer.store(
darkAmbienceStimBuff, std::memory_order_release);
this->start();
return darkAmbienceStimBuff;
}
else
{
throw std::runtime_error(
"Unsupported qualeIfaceApi: '" + qualeIfaceApi + "' for "
"PcloudStimulusProducer. "
"Supported values: mesh, pcloudIntensity, pcloudAmbience");
"Supported values: mesh, pcloudIntensity, "
"pcloudLightAmbience, pcloudDarkAmbience");
}
}
@@ -366,7 +409,8 @@ private:
sscl::AsynchronousLoop frameAssemblyResult;
StimulusFrame& stimulusFrame;
std::optional<std::reference_wrapper<StimulusFrame>> intensityStimFrame;
std::optional<std::reference_wrapper<StimulusFrame>> ambienceStimFrame;
std::optional<std::reference_wrapper<StimulusFrame>> lightAmbienceStimFrame;
std::optional<std::reference_wrapper<StimulusFrame>> darkAmbienceStimFrame;
public:
ProduceFrameReq(
@@ -446,28 +490,57 @@ public:
context->intensityStimFrame = std::nullopt;
}
// Check if ambience buffer is attached and acquire frame if so
if (auto ambienceBuff = pcloudProducer.ambienceStimulusBuffer.load(
std::memory_order_acquire))
// Check if light ambience buffer is attached and acquire frame if so
std::optional<AmbienceProductionDesc> lightAmbienceProductionDescDesc;
if (auto lightAmbienceBuff =
pcloudProducer.lightAmbienceStimulusBuffer.load(
std::memory_order_acquire))
{
size_t ambienceRingbuffIndex = ambienceBuff
size_t lightAmbienceRingbuffIndex = lightAmbienceBuff
->ringBuffer.getIndexToProduceInto();
StimulusFrame& ambienceStimFrame = ambienceBuff
->ringBuffer.getDataAtSlot(
ambienceRingbuffIndex);
StimulusFrame& lightAmbienceStimFrame = lightAmbienceBuff
->ringBuffer.getDataAtSlot(lightAmbienceRingbuffIndex);
ambienceStimFrame.lock.writeAcquire();
context->ambienceStimFrame = std::make_optional(
std::ref(ambienceStimFrame));
lightAmbienceStimFrame.lock.writeAcquire();
context->lightAmbienceStimFrame = std::make_optional(
std::ref(lightAmbienceStimFrame));
lightAmbienceProductionDescDesc = AmbienceProductionDesc{
std::ref(lightAmbienceStimFrame),
lightAmbienceBuff->passbandCountGtComparator};
}
else {
context->ambienceStimFrame = std::nullopt;
context->lightAmbienceStimFrame = std::nullopt;
}
// Check if dark ambience buffer is attached and acquire frame if so
std::optional<AmbienceProductionDesc> darkAmbienceProductionDescDesc;
if (auto darkAmbienceBuff =
pcloudProducer.darkAmbienceStimulusBuffer.load(
std::memory_order_acquire))
{
size_t darkAmbienceRingbuffIndex = darkAmbienceBuff
->ringBuffer.getIndexToProduceInto();
StimulusFrame& darkAmbienceStimFrame = darkAmbienceBuff
->ringBuffer.getDataAtSlot(darkAmbienceRingbuffIndex);
darkAmbienceStimFrame.lock.writeAcquire();
context->darkAmbienceStimFrame = std::make_optional(
std::ref(darkAmbienceStimFrame));
darkAmbienceProductionDescDesc = AmbienceProductionDesc{
std::ref(darkAmbienceStimFrame),
darkAmbienceBuff->passbandCountLtComparator};
}
else {
context->darkAmbienceStimFrame = std::nullopt;
}
pcloudProducer.openClCollatingAndMeshingEngine.compactCollateAndMeshFrameReq(
loop, stimulusFrame,
context->intensityStimFrame, context->ambienceStimFrame,
context->intensityStimFrame,
std::move(lightAmbienceProductionDescDesc),
std::move(darkAmbienceProductionDescDesc),
{context, std::bind(
&ProduceFrameReq::produceFrameReq3_compactCollateDone,
context.get(), context,
@@ -482,9 +555,12 @@ public:
if (context->intensityStimFrame.has_value()) {
context->intensityStimFrame->get().lock.writeRelease();
}
// Release ambience frame if it was used
if (context->ambienceStimFrame.has_value()) {
context->ambienceStimFrame->get().lock.writeRelease();
// Release ambience frames if they were used
if (context->lightAmbienceStimFrame.has_value()) {
context->lightAmbienceStimFrame->get().lock.writeRelease();
}
if (context->darkAmbienceStimFrame.has_value()) {
context->darkAmbienceStimFrame->get().lock.writeRelease();
}
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock);