bool GLTransferBuffers::createBuffers(unsigned int uiNumBuffers, unsigned int uiBufferSize, unsigned int uiTarget, bool bUseP2P, AlignedMem *pPinnedMem ) { // Check if buffers were already allocated. If so delete them for (unsigned int i = 0; i < m_uiNumBuffers && m_pBufferMemory; i++) { if (m_pBufferMemory[i].pBasePointer) delete [] m_pBufferMemory[i].pBasePointer; glDeleteBuffers(1, &m_pBuffer[i]); } if (uiTarget != GL_PIXEL_PACK_BUFFER && uiTarget != GL_PIXEL_UNPACK_BUFFER) return false; m_pBufferMemory = NULL; m_uiNumBuffers = uiNumBuffers; m_uiBufferSize = uiBufferSize; m_uiTarget = uiTarget; m_bUseP2P = bUseP2P; // Generate GL Buffers m_pBuffer = new unsigned int[m_uiNumBuffers]; glGenBuffers(m_uiNumBuffers, m_pBuffer); GLenum nUsage = m_uiTarget == GL_PIXEL_PACK_BUFFER ? GL_DYNAMIC_READ : GL_DYNAMIC_DRAW; if (m_bUseP2P) { ///////////////////////////////////////////// // Create bus addressable memory buffers m_pBufferBusAddress = new GLuint64[m_uiNumBuffers]; m_pMarkerBusAddress = new GLuint64[m_uiNumBuffers]; if (uiTarget == GL_PIXEL_UNPACK_BUFFER) { glGetError(); // In the case of an unpack buffer, the memory is allocated on the // GPU visible framebuffer. // In case of a pack buffer, memory is allocated on visible sdi // framebuffer, this needs to be done in the sdi thread and not here! // In this case only the buffer is generated and memory addressed will // be passed later. for (unsigned int i = 0; i < m_uiNumBuffers; i++) { glBindBuffer(GL_BUS_ADDRESSABLE_MEMORY_AMD, m_pBuffer[i]); glBufferData(GL_BUS_ADDRESSABLE_MEMORY_AMD, m_uiBufferSize, 0, nUsage); } // Call makeResident when all BufferData calls were submitted. glMakeBuffersResidentAMD(m_uiNumBuffers, m_pBuffer, m_pBufferBusAddress, m_pMarkerBusAddress); // Make sure that the buffer creation really succeed if (glGetError() != GL_NO_ERROR) return false; glBindBuffer(GL_BUS_ADDRESSABLE_MEMORY_AMD, 0); } } else { ///////////////////////////////////////////// // Create pinned memory buffers ///////////////////////////////////////////// if (!pPinnedMem) { m_pBufferMemory = new AlignedMem[m_uiNumBuffers]; memset(m_pBufferMemory, 0, m_uiNumBuffers * sizeof(AlignedMem)); // indicate that pinned mem was allocated and needs to be deleted. m_bAllocatedPinnedMem = true; } else { m_pBufferMemory = pPinnedMem; } for (unsigned int i = 0; i < m_uiNumBuffers; i++) { if (!m_pBufferMemory[i].pBasePointer) { m_pBufferMemory[i].pBasePointer = new char[m_uiBufferSize + 4096]; memset(m_pBufferMemory[i].pBasePointer, 0, (m_uiBufferSize + 4096)); // Align memory to 4K boundaries size_t addr = (size_t) m_pBufferMemory[i].pBasePointer; m_pBufferMemory[i].pAlignedPointer = (char*)((addr + 4095) & (~0xfff)); } glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_AMD, m_pBuffer[i]); glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_AMD, m_uiBufferSize, m_pBufferMemory[i].pAlignedPointer, nUsage); glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_AMD, 0); } } m_bBufferReady = true; return true; }
bool GLSink::createDownStream(unsigned int w, unsigned int h, int nIntFormat, int nExtFormat, int nType) { m_uiTextureWidth = w; m_uiTextureHeight = h; m_nIntFormat = nIntFormat; m_nExtFormat = nExtFormat; m_nType = nType; m_fAspectRatio = (float)w/(float)h; m_uiBufferSize = FormatInfo::getInternalFormatSize(m_nIntFormat) * m_uiTextureWidth * m_uiTextureHeight; if (m_uiBufferSize == 0) return false; // check if format is supported if (FormatInfo::getExternalFormatSize(m_nExtFormat, m_nType) == 0) return false; glBindBuffer(GL_BUS_ADDRESSABLE_MEMORY_AMD, 0); // Create texture that will be used to store frames from remote device glGenTextures(1, &m_uiTexture); glBindTexture(GL_TEXTURE_2D, m_uiTexture); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexImage2D(GL_TEXTURE_2D, 0, m_nIntFormat, m_uiTextureWidth, m_uiTextureHeight, 0, m_nExtFormat, m_nType, NULL); glBindTexture(GL_TEXTURE_2D, 0); m_uiTextureSize = m_uiTextureWidth*m_uiTextureHeight*FormatInfo::getExternalFormatSize(m_nExtFormat, m_nType); m_pUnPackBuffer = new unsigned int[NUM_BUFFERS]; m_pBufferBusAddress = new unsigned long long[NUM_BUFFERS]; m_pMarkerBusAddress = new unsigned long long[NUM_BUFFERS]; glGenBuffers(NUM_BUFFERS, m_pUnPackBuffer); // Create buffers for (unsigned int i = 0; i < NUM_BUFFERS; i++) { glBindBuffer(GL_BUS_ADDRESSABLE_MEMORY_AMD, m_pUnPackBuffer[i]); glBufferData(GL_BUS_ADDRESSABLE_MEMORY_AMD, m_uiBufferSize, 0, GL_DYNAMIC_DRAW); } // Call makeResident when all BufferData calls were submitted. This call will make the // buffers resident in local visible memory. glMakeBuffersResidentAMD(NUM_BUFFERS, m_pUnPackBuffer, m_pBufferBusAddress, m_pMarkerBusAddress); // Create synchronization buffers m_pInputBuffer = new SyncedBuffer; m_pInputBuffer->createSyncedBuffer(NUM_BUFFERS); for (unsigned int i = 0; i < NUM_BUFFERS; i++) { FrameData* pFrameData = new FrameData; pFrameData->uiTransferId = 0; pFrameData->ullBufferBusAddress = m_pBufferBusAddress[i]; pFrameData->ullMarkerBusAddress = m_pMarkerBusAddress[i]; m_pInputBuffer->setBufferMemory(i, (void*)pFrameData); } return true; }