#include #include #include #include #include #include #include "pcloudStimulusBuffer.h" namespace smo { namespace stim_buff { extern const SmoCallbacks* smoHooksPtr; // OpenCL kernels are used to collate and produce our StimFrames. static SpMcRingBuffer::InputEngineConstraints openClInputConstraints( static_cast(sysconf(_SC_PAGE_SIZE)), sizeof(void *)); PcloudStimulusBuffer::PcloudStimulusBuffer( const std::shared_ptr &deviceAttachmentSpec, std::shared_ptr &device, const PcloudFormatDesc& formatDesc, int histbuffMs, size_t nDgramsPerStagingBufferFrame) : StimulusBuffer( deviceAttachmentSpec, static_cast(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS), openClInputConstraints, device->componentThread->getIoService()), device(device), formatDesc(formatDesc), assemblyBuffer( StagingBuffer::InputEngineConstraints::ioUringConstraints, OpenClConstraints(), nDgramsPerStagingBufferFrame), ioUringAssemblyEngine(*this) { std::cout << __func__ << ": Device's component thread is " << device->componentThread->name << std::endl; #ifndef CONFIG_WORLD_USE_BODY_THREAD if (smoHooksPtr->ComponentThread_getSelf()->id != ComponentThread::WORLD) #else if (smoHooksPtr->ComponentThread_getSelf()->id != ComponentThread::BODY) #endif { std::string errMsg = std::string(__func__) + ": PcloudStimulusBuffer constructor called on non-world/body thread " + smoHooksPtr->ComponentThread_getSelf()->name; std::cout << errMsg << std::endl; // throw std::runtime_error(errMsg); } } void PcloudStimulusBuffer::start() { // Call ioUringAssemblyEngine setup() as the final step ioUringAssemblyEngine.setup(); // Call base class start() as the final step StimulusBuffer::start(); } void PcloudStimulusBuffer::stop() { // Call base class stop() as the first step StimulusBuffer::stop(); // Call ioUringAssemblyEngine stop() as the final step ioUringAssemblyEngine.finalize(); } void PcloudStimulusBuffer::stimFrameProductionTimesliceInd() { ioUringAssemblyEngine.assembleFrameReq( {nullptr, [this](bool success, AsynchronousLoop loop) { if (!success) { std::cerr << __func__ << ": Failed to assemble frame" << std::endl; } else { std::cout << __func__ << ": Successfully assembled frame " << loop.nSucceeded.load() << " slots succeeded " << "out of " << loop.nTotal << " total slots" << std::endl; } }}); // Release the spinlock for now frameAssemblyRateLimiter.release(); } class PcloudStimulusBuffer::AssembleAndProduceStimulusFrameReq : public smo::PostedAsynchronousContinuation< assembleAndProduceStimulusFrameReqCbFn> { private: PcloudStimulusBuffer& stimBuff; public: AssembleAndProduceStimulusFrameReq( PcloudStimulusBuffer& buffer, Callback callback) : PostedAsynchronousContinuation( buffer.device->componentThread, std::move(callback)), stimBuff(buffer) {} void callOriginalCallback() { stimBuff.frameAssemblyRateLimiter.release(); callOriginalCb(static_cast(0)); } void callOriginalCallbackWithFailure() { stimBuff.frameAssemblyRateLimiter.release(); callOriginalCb(static_cast(0)); } }; void PcloudStimulusBuffer::assembleAndProduceStimulusFrameReq( smo::Callback callback) { // Wireframe implementation - do nothing for now (void)callback; } } // namespace stim_buff } // namespace smo