diff --git a/commonLibs/attachmentSupport/stagingBuffer.cpp b/commonLibs/attachmentSupport/stagingBuffer.cpp index 4a93836..b55aedc 100644 --- a/commonLibs/attachmentSupport/stagingBuffer.cpp +++ b/commonLibs/attachmentSupport/stagingBuffer.cpp @@ -68,10 +68,13 @@ static size_t calculateMaxAlignment( void StagingBuffer::computeSlotStrideAndBufferSize() { - // Slot stride is the maximum of alignment and padding - slotStrideNBytes = std::max( + // Slot stride is the maximum of alignment and padding, rounded up to a multiple of alignment + size_t minSlotStride = std::max( inputConstraints.slotStartAlignmentByteVal, inputConstraints.slotPadToNBytes); + slotStrideNBytes = ((minSlotStride + inputConstraints.slotStartAlignmentByteVal - 1) + / inputConstraints.slotStartAlignmentByteVal) + * inputConstraints.slotStartAlignmentByteVal; // Calculate maximum alignment needed for first slot (must satisfy both frame and slot alignment) size_t maxAlignment = calculateMaxAlignment( diff --git a/include/user/stimulusFrame.h b/include/user/stimulusFrame.h index b18cdb7..b8df377 100644 --- a/include/user/stimulusFrame.h +++ b/include/user/stimulusFrame.h @@ -96,7 +96,7 @@ public: + ": StimulusFrame: failed to create clBuffer"); } - std::cout << __func__ << ": StimulusFrame: created clBuffer with size " << slotDesc.nBytes << " bytes @ " << (const void*)slotDesc.vaddr << std::endl; +// std::cout << __func__ << ": StimulusFrame: created clBuffer with size " << slotDesc.nBytes << " bytes @ " << (const void*)slotDesc.vaddr << std::endl; } ~StimulusFrame() = default; diff --git a/tests/commonLibs/attachmentSupport/stagingBuffer_tests.cpp b/tests/commonLibs/attachmentSupport/stagingBuffer_tests.cpp index 81aea93..335241c 100644 --- a/tests/commonLibs/attachmentSupport/stagingBuffer_tests.cpp +++ b/tests/commonLibs/attachmentSupport/stagingBuffer_tests.cpp @@ -9,76 +9,6 @@ namespace smo { namespace stim_buff { -// Helper function to calculate expected buffer size using the same logic as computeSlotStrideAndBufferSize -static size_t calculateExpectedBufferSize( - size_t nSlots, - const StagingBuffer::IOEngineConstraints& constraints) -{ - // Slot stride is the maximum of alignment and padding - size_t slotStrideNBytes = std::max( - constraints.slotStartAlignmentByteVal, - constraints.slotPadToNBytes); - - // Calculate maximum alignment needed for first slot - size_t maxAlignment; - if (constraints.frameStartAlignmentByteVal >= constraints.slotStartAlignmentByteVal) - { - if (constraints.frameStartAlignmentByteVal % constraints.slotStartAlignmentByteVal == 0) - { - maxAlignment = constraints.frameStartAlignmentByteVal; - } - else - { - maxAlignment = std::max( - constraints.frameStartAlignmentByteVal, - constraints.slotStartAlignmentByteVal); - } - } - else - { - if (constraints.slotStartAlignmentByteVal % constraints.frameStartAlignmentByteVal == 0) - { - maxAlignment = constraints.slotStartAlignmentByteVal; - } - else - { - maxAlignment = std::max( - constraints.frameStartAlignmentByteVal, - constraints.slotStartAlignmentByteVal); - } - } - - // Calculate minimum buffer size - size_t minBufferSize = std::max( - constraints.framePadToNBytes, - constraints.slotPadToNBytes); - - // Calculate total size needed for nSlots slots - size_t slotAreaSize = nSlots * slotStrideNBytes; - - // Add padding space at buffer start for alignment offset (worst case: max alignment - 1) - size_t alignmentPadding = maxAlignment - 1; - - // Total size needed: alignment padding + slot area, then ensure minimum is met - size_t rawSize = alignmentPadding + slotAreaSize; - if (rawSize < minBufferSize) - { - rawSize = minBufferSize; - } - - // Align up to the maximum alignment to ensure we can always find a valid offset - return ((rawSize + maxAlignment - 1) / maxAlignment) * maxAlignment; -} - -// Helper function to calculate expected slot stride -static size_t calculateExpectedSlotStride( - const StagingBuffer::IOEngineConstraints& constraints) -{ - return std::max( - constraints.slotStartAlignmentByteVal, - constraints.slotPadToNBytes); -} - // Helper function to create test constraints static StagingBuffer::IOEngineConstraints createTestConstraints( size_t slotStartAlignment, @@ -117,357 +47,230 @@ protected: size_t pageSize; }; -// Test 1: Single slot, minimal padding, small alignments -TEST_F(StagingBufferTest, SingleSlotMinimalAlignment) { - size_t nSlots = 1; - auto constraints = createTestConstraints(4, 16, 4, 16); - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - - // Verify FrameAssemblyDesc +// Helper function to verify all slots are page-aligned and have correct stride +static void verifyAllSlotsPageAligned( + const StagingBuffer& buffer, + size_t expectedSlotStride, + size_t pageSize) +{ auto frameDesc = static_cast>(buffer); ASSERT_NE(frameDesc, nullptr); - EXPECT_EQ(frameDesc->numSlots, nSlots); - EXPECT_EQ(frameDesc->slots.size(), nSlots); + ASSERT_GT(frameDesc->slots.size(), 0u); - // Verify first slot alignment - if (!frameDesc->slots.empty()) { - verifyAlignment(frameDesc->slots[0].vaddr, constraints.slotStartAlignmentByteVal, - "First slot"); - verifyAlignment(frameDesc->slots[0].vaddr, constraints.frameStartAlignmentByteVal, - "First slot frame alignment"); + // Verify slot stride is a multiple of page size + EXPECT_EQ(expectedSlotStride % pageSize, 0u) + << "Slot stride " << expectedSlotStride + << " should be a multiple of page size " << pageSize; + + // Verify first slot is page-aligned + verifyAlignment(frameDesc->slots[0].vaddr, pageSize, "First slot"); + + // Verify all subsequent slots are page-aligned and have correct stride + for (size_t i = 1; i < frameDesc->slots.size(); ++i) { + verifyAlignment(frameDesc->slots[i].vaddr, pageSize, + "Slot " + std::to_string(i)); + + // Verify actual stride matches expected stride + size_t actualStride = reinterpret_cast(frameDesc->slots[i].vaddr) - + reinterpret_cast(frameDesc->slots[i-1].vaddr); + EXPECT_EQ(actualStride, expectedSlotStride) + << "Slot " << i << " stride mismatch: expected " << expectedSlotStride + << ", got " << actualStride; } } -// Test 2: Multiple slots, no alignment padding needed -TEST_F(StagingBufferTest, MultipleSlotsMinimalAlignment) { +// Test 1: Small slot stride (< page size) - should round up to page size +TEST_F(StagingBufferTest, SmallSlotStrideRoundsUpToPageSize) { size_t nSlots = 10; - auto constraints = createTestConstraints(4, 16, 4, 16); + size_t smallSlotPad = 256; // Much smaller than typical page size (4096) + auto constraints = createTestConstraints( + pageSize, // slotStartAlignment (page size) + smallSlotPad, // slotPadToNBytes (small) + pageSize, // frameStartAlignment + pageSize); // framePadToNBytes StagingBuffer buffer(constraints, constraints, nSlots); - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); + // Slot stride should be rounded up to page size + size_t expectedSlotStride = pageSize; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Small slot pad should round up to page size"; - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - - // Verify all slots are properly spaced - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - EXPECT_EQ(frameDesc->numSlots, nSlots); - - for (size_t i = 0; i < frameDesc->slots.size(); ++i) { - if (i > 0) { - size_t actualStride = reinterpret_cast(frameDesc->slots[i].vaddr) - - reinterpret_cast(frameDesc->slots[i-1].vaddr); - EXPECT_EQ(actualStride, expectedSlotStride) - << "Slot " << i << " stride mismatch"; - } - } + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); } -// Test 3: OpenCL Mesh constraints (real-world scenario) -TEST_F(StagingBufferTest, OpenClMeshConstraints) { - size_t nSlots = 909; // 30000ms / 33ms - size_t nDgramsPerFrame = 84; - size_t nPointsPerDgram = 96; // SingleFirst/Strongest/Dual return mode - size_t slotPadToNBytes = nDgramsPerFrame * nPointsPerDgram * sizeof(float) * 3; // 96768 - +// Test 2: Slot stride equal to page size - should remain page size +TEST_F(StagingBufferTest, SlotStrideEqualToPageSize) { + size_t nSlots = 20; auto constraints = createTestConstraints( - sizeof(float), // slotStartAlignment + pageSize, // slotStartAlignment + pageSize, // slotPadToNBytes (equal to page size) + pageSize, // frameStartAlignment + pageSize); // framePadToNBytes + + StagingBuffer buffer(constraints, constraints, nSlots); + + size_t expectedSlotStride = pageSize; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Slot stride equal to page size should remain unchanged"; + + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); +} + +// Test 3: Slot stride slightly larger than page size (e.g., 336) - should round up +TEST_F(StagingBufferTest, SlotStrideSlightlyLargerThanPageSize) { + size_t nSlots = 50; + size_t slotPadToNBytes = 336; // Slightly larger than page size (4096) + auto constraints = createTestConstraints( + pageSize, // slotStartAlignment slotPadToNBytes, // slotPadToNBytes pageSize, // frameStartAlignment pageSize); // framePadToNBytes StagingBuffer buffer(constraints, constraints, nSlots); - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); + // Should round up to next multiple of page size (4096) + size_t expectedSlotStride = pageSize; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Slot stride 336 should round up to page size " << pageSize; - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % pageSize, 0u) - << "Buffer size should be page-aligned"; + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); +} - // Verify FrameAssemblyDesc - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - EXPECT_EQ(frameDesc->numSlots, nSlots); - EXPECT_EQ(frameDesc->slotSizeBytes, slotPadToNBytes); +// Test 4: Slot stride much larger than page size (e.g., 32256) - should round up to 32768 +TEST_F(StagingBufferTest, SlotStrideMuchLargerThanPageSize) { + size_t nSlots = 100; + size_t slotPadToNBytes = 32256; // Much larger than page size + auto constraints = createTestConstraints( + pageSize, // slotStartAlignment + slotPadToNBytes, // slotPadToNBytes + pageSize, // frameStartAlignment + pageSize); // framePadToNBytes - // Verify first slot alignment - if (!frameDesc->slots.empty()) { - verifyAlignment(frameDesc->slots[0].vaddr, pageSize, "First slot frame alignment"); + StagingBuffer buffer(constraints, constraints, nSlots); + + // Should round up to next multiple of page size + // 32256 / 4096 = 7.875, so rounds up to 8 pages = 32768 + size_t expectedSlotStride = ((slotPadToNBytes + pageSize - 1) / pageSize) * pageSize; + EXPECT_EQ(expectedSlotStride, 32768u) + << "32256 should round up to 32768 (8 pages)"; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Slot stride should be rounded up to " << expectedSlotStride; + + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); +} + +// Test 5: Slot stride already a multiple of page size - should remain unchanged +TEST_F(StagingBufferTest, SlotStrideAlreadyMultipleOfPageSize) { + size_t nSlots = 30; + size_t slotPadToNBytes = pageSize * 3; // Already a multiple (e.g., 12288) + auto constraints = createTestConstraints( + pageSize, // slotStartAlignment + slotPadToNBytes, // slotPadToNBytes (already multiple) + pageSize, // frameStartAlignment + pageSize); // framePadToNBytes + + StagingBuffer buffer(constraints, constraints, nSlots); + + // Should remain unchanged + size_t expectedSlotStride = slotPadToNBytes; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Slot stride already a multiple of page size should remain unchanged"; + + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); +} + +// Test 6: Multiple different slot stride sizes in sequence +TEST_F(StagingBufferTest, MultipleDifferentSlotStrideSizes) { + // Test with various slot pad sizes + struct TestCase { + size_t slotPadToNBytes; + size_t expectedRoundedStride; + }; + + std::vector testCases = { + {256, pageSize}, // Small: rounds to 1 page + {pageSize, pageSize}, // Equal: stays 1 page + {pageSize + 1, pageSize * 2}, // Slightly larger: rounds to 2 pages + {32256, 32768}, // Much larger: rounds to 8 pages + {pageSize * 5, pageSize * 5}, // Already multiple: stays 5 pages + {pageSize * 10 + 100, pageSize * 11}, // Large with remainder: rounds to 11 pages + }; + + for (const auto& testCase : testCases) { + size_t nSlots = 10; + auto constraints = createTestConstraints( + pageSize, + testCase.slotPadToNBytes, + pageSize, + pageSize); + + StagingBuffer buffer(constraints, constraints, nSlots); + + EXPECT_EQ(buffer.slotStrideNBytes, testCase.expectedRoundedStride) + << "Slot pad " << testCase.slotPadToNBytes + << " should round to " << testCase.expectedRoundedStride; + + verifyAllSlotsPageAligned(buffer, testCase.expectedRoundedStride, pageSize); } } -// Test 4: OpenCL Intensity constraints -TEST_F(StagingBufferTest, OpenClIntensityConstraints) { - size_t nSlots = 909; // 30000ms / 33ms +// Test 7: Real-world scenario - PcloudIntensityStimulusBuffer (32256 bytes) +TEST_F(StagingBufferTest, RealWorldPcloudIntensityScenario) { + size_t nSlots = 909; // histbuffMs=30000 / CONFIG_STIMBUFF_FRAME_PERIOD_MS=33 size_t nDgramsPerFrame = 84; size_t nPointsPerDgram = 96; size_t slotPadToNBytes = nDgramsPerFrame * nPointsPerDgram * sizeof(float) * 1; // 32256 auto constraints = createTestConstraints( - sizeof(float), // slotStartAlignment + pageSize, // slotStartAlignment slotPadToNBytes, // slotPadToNBytes pageSize, // frameStartAlignment pageSize); // framePadToNBytes StagingBuffer buffer(constraints, constraints, nSlots); - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); + // Should round up to 32768 (8 pages) + size_t expectedSlotStride = 32768; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Real-world 32256-byte slots should round to 32768"; - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % pageSize, 0u) - << "Buffer size should be page-aligned"; + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); + // Verify FrameAssemblyDesc auto frameDesc = static_cast>(buffer); ASSERT_NE(frameDesc, nullptr); EXPECT_EQ(frameDesc->numSlots, nSlots); EXPECT_EQ(frameDesc->slotSizeBytes, slotPadToNBytes); } -// Test 5: OpenCL Ambience constraints -TEST_F(StagingBufferTest, OpenClAmbienceConstraints) { - size_t nSlots = 909; // 30000ms / 33ms +// Test 8: Real-world scenario - PcloudAmbienceStimulusBuffer (336 bytes) +TEST_F(StagingBufferTest, RealWorldPcloudAmbienceScenario) { + size_t nSlots = 909; size_t nDgramsPerFrame = 84; size_t slotPadToNBytes = nDgramsPerFrame * sizeof(float); // 336 - auto constraints = createTestConstraints( - sizeof(float), // slotStartAlignment - slotPadToNBytes, // slotPadToNBytes - pageSize, // frameStartAlignment - pageSize); // framePadToNBytes - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % pageSize, 0u) - << "Buffer size should be page-aligned"; - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - EXPECT_EQ(frameDesc->numSlots, nSlots); - EXPECT_EQ(frameDesc->slotSizeBytes, slotPadToNBytes); -} - -// Test 6: io_uring constraints -TEST_F(StagingBufferTest, IoUringConstraints) { - size_t nSlots = 84; auto constraints = createTestConstraints( pageSize, // slotStartAlignment - 1472, // slotPadToNBytes - pageSize, // frameStartAlignment - pageSize); // framePadToNBytes - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(expectedSlotStride, pageSize) << "Slot stride should be max(alignment, padding) = pageSize"; - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % pageSize, 0u) - << "Buffer size should be page-aligned"; -} - -// Test 7: Slot alignment larger than padding -TEST_F(StagingBufferTest, SlotAlignmentLargerThanPadding) { - size_t nSlots = 10; - auto constraints = createTestConstraints(64, 16, 64, 64); - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - EXPECT_EQ(expectedSlotStride, 64u) << "Slot stride should be max(64, 16) = 64"; - - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - if (!frameDesc->slots.empty()) { - verifyAlignment(frameDesc->slots[0].vaddr, 64, "First slot"); - } -} - -// Test 8: Frame alignment larger than slot alignment -TEST_F(StagingBufferTest, FrameAlignmentLargerThanSlotAlignment) { - size_t nSlots = 10; - auto constraints = createTestConstraints(4, 16, pageSize, pageSize); - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % pageSize, 0u) - << "Buffer size should be page-aligned"; - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - if (!frameDesc->slots.empty()) { - verifyAlignment(frameDesc->slots[0].vaddr, pageSize, "First slot frame alignment"); - verifyAlignment(frameDesc->slots[0].vaddr, 4, "First slot slot alignment"); - } -} - -// Test 9: Slot alignment larger than frame alignment -TEST_F(StagingBufferTest, SlotAlignmentLargerThanFrameAlignment) { - size_t nSlots = 10; - size_t largeAlignment = 8192; - auto constraints = createTestConstraints(largeAlignment, 16, pageSize, pageSize); - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len % largeAlignment, 0u) - << "Buffer size should be aligned to max alignment"; - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - if (!frameDesc->slots.empty()) { - verifyAlignment(frameDesc->slots[0].vaddr, largeAlignment, "First slot"); - } -} - -// Test 10: Minimum buffer size larger than calculated size -TEST_F(StagingBufferTest, MinimumBufferSizeEnforcement) { - size_t nSlots = 1; - auto constraints = createTestConstraints(4, 16, 4, 1024); - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - size_t actualBufferSize = buffer.getIoUringRegisterIoVec().iov_len; - - EXPECT_GE(actualBufferSize, 1024u) << "Buffer size should be at least framePadToNBytes"; - EXPECT_EQ(actualBufferSize, expectedBufferSize); -} - -// Test 11: Actual PcloudIntensityStimulusBuffer scenario -TEST_F(StagingBufferTest, RealWorldPcloudIntensityScenario) { - size_t nSlots = 909; // histbuffMs=30000 / CONFIG_STIMBUFF_FRAME_PERIOD_MS=33 - size_t nDgramsPerFrame = 84; - size_t nPointsPerDgram = 96; // SingleFirst/Strongest/Dual - size_t slotPadToNBytes = nDgramsPerFrame * nPointsPerDgram * sizeof(float) * 1; // 32256 - - auto constraints = createTestConstraints( - sizeof(float), // slotStartAlignment slotPadToNBytes, // slotPadToNBytes pageSize, // frameStartAlignment pageSize); // framePadToNBytes StagingBuffer buffer(constraints, constraints, nSlots); - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); + // Should round up to page size + size_t expectedSlotStride = pageSize; + EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride) + << "Real-world 336-byte slots should round to page size"; - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); + verifyAllSlotsPageAligned(buffer, expectedSlotStride, pageSize); - // Verify the buffer can hold all slots + // Verify FrameAssemblyDesc auto frameDesc = static_cast>(buffer); ASSERT_NE(frameDesc, nullptr); EXPECT_EQ(frameDesc->numSlots, nSlots); - - // Verify all slots fit within buffer - if (!frameDesc->slots.empty()) { - uint8_t* bufferStart = buffer.getIoUringRegisterIoVec().iov_base; - size_t bufferSize = buffer.getIoUringRegisterIoVec().iov_len; - uint8_t* lastSlotEnd = frameDesc->slots.back().vaddr + frameDesc->slots.back().nBytes; - EXPECT_LE(lastSlotEnd - bufferStart, static_cast(bufferSize)) - << "Last slot should fit within buffer"; - } -} - -// Test 12: Different return modes - Triple (90 points) -TEST_F(StagingBufferTest, TripleReturnModeMesh) { - size_t nSlots = 909; - size_t nDgramsPerFrame = 84; - size_t nPointsPerDgram = 90; // Triple return mode - size_t slotPadToNBytes = nDgramsPerFrame * nPointsPerDgram * sizeof(float) * 3; // 90720 - - auto constraints = createTestConstraints( - sizeof(float), // slotStartAlignment - slotPadToNBytes, // slotPadToNBytes - pageSize, // frameStartAlignment - pageSize); // framePadToNBytes - - StagingBuffer buffer(constraints, constraints, nSlots); - - size_t expectedSlotStride = calculateExpectedSlotStride(constraints); - size_t expectedBufferSize = calculateExpectedBufferSize(nSlots, constraints); - - EXPECT_EQ(buffer.slotStrideNBytes, expectedSlotStride); - EXPECT_EQ(buffer.getIoUringRegisterIoVec().iov_len, expectedBufferSize); - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); EXPECT_EQ(frameDesc->slotSizeBytes, slotPadToNBytes); } -// Test 13: Verify firstSlotOffsetNBytes is valid -TEST_F(StagingBufferTest, FirstSlotOffsetValidation) { - size_t nSlots = 100; - auto constraints = createTestConstraints(4, 16, pageSize, pageSize); - - StagingBuffer buffer(constraints, constraints, nSlots); - - EXPECT_LE(buffer.firstSlotOffsetNBytes, buffer.getIoUringRegisterIoVec().iov_len) - << "First slot offset should be within buffer"; - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - if (!frameDesc->slots.empty()) { - uint8_t* bufferStart = buffer.getIoUringRegisterIoVec().iov_base; - uint8_t* firstSlot = frameDesc->slots[0].vaddr; - size_t calculatedOffset = firstSlot - bufferStart; - EXPECT_EQ(calculatedOffset, buffer.firstSlotOffsetNBytes) - << "First slot offset should match calculated value"; - } -} - -// Test 14: Verify all slots are properly aligned -TEST_F(StagingBufferTest, AllSlotsProperlyAligned) { - size_t nSlots = 50; - auto constraints = createTestConstraints(64, 64, 64, 64); - - StagingBuffer buffer(constraints, constraints, nSlots); - - auto frameDesc = static_cast>(buffer); - ASSERT_NE(frameDesc, nullptr); - - for (size_t i = 0; i < frameDesc->slots.size(); ++i) { - verifyAlignment(frameDesc->slots[i].vaddr, constraints.slotStartAlignmentByteVal, - "Slot " + std::to_string(i)); - verifyAlignment(frameDesc->slots[i].vaddr, constraints.frameStartAlignmentByteVal, - "Slot " + std::to_string(i) + " frame alignment"); - } -} - } // namespace stim_buff } // namespace smo -