void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset) { BufferStorage11* sourceStorage11 = makeBufferStorage11(sourceStorage); if (sourceStorage11) { TypedBufferStorage11 *dest = getLatestStorage(); if (!dest) { dest = getStagingBuffer(); } TypedBufferStorage11 *source = sourceStorage11->getLatestStorage(); if (source && dest) { // If copying to/from a pixel pack buffer, we must have a staging or // pack buffer partner, because other native buffers can't be mapped if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable()) { source = sourceStorage11->getStagingBuffer(); } else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable()) { dest = getStagingBuffer(); } dest->copyFromStorage(source, sourceOffset, size, destOffset); dest->setDataRevision(dest->getDataRevision() + 1); } mSize = std::max<size_t>(mSize, destOffset + size); } }
void *BufferStorage11::map(GLbitfield access) { ASSERT(!mMappedStorage); TypedBufferStorage11 *latestStorage = getLatestStorage(); ASSERT(latestStorage); if (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || latestStorage->getUsage() == BUFFER_USAGE_STAGING) { mMappedStorage = latestStorage; } else { mMappedStorage = getStagingBuffer(); } if (!mMappedStorage) { // Out-of-memory return NULL; } return mMappedStorage->map(access); }
BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage usage) { TypedBufferStorage11 *directBuffer = NULL; auto directBufferIt = mTypedBuffers.find(usage); if (directBufferIt != mTypedBuffers.end()) { directBuffer = directBufferIt->second; } if (!directBuffer) { if (usage == BUFFER_USAGE_PIXEL_PACK) { directBuffer = new PackStorage11(mRenderer); } else { // buffer is not allocated, create it directBuffer = new NativeBuffer11(mRenderer, usage); } mTypedBuffers.insert(std::make_pair(usage, directBuffer)); } // resize buffer if (directBuffer->getSize() < mSize) { if (!directBuffer->resize(mSize, true)) { // Out of memory error return NULL; } } TypedBufferStorage11 *latestBuffer = getLatestStorage(); if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) { // if copying from a pack buffer to a non-staging native buffer, we must first // copy through the staging buffer, because other native buffers can't be mapped if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) { NativeBuffer11 *stagingBuffer = getStagingBuffer(); stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); directBuffer->setDataRevision(latestBuffer->getDataRevision()); latestBuffer = stagingBuffer; } // if copyFromStorage returns true, the D3D buffer has been recreated // and we should update our serial if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) { updateSerial(); } directBuffer->setDataRevision(latestBuffer->getDataRevision()); } return directBuffer; }
void MyD3DAssets::readBuffer(ID3D11Buffer *inputBuffer, vector<BYTE> &result) { ID3D11Buffer *stagingBuffer = getStagingBuffer(inputBuffer); context->base->CopyResource(stagingBuffer, inputBuffer); D3D11_MAPPED_SUBRESOURCE mappedResource; context->base->Map(stagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); if (result.size() != mappedResource.RowPitch) result.resize(mappedResource.RowPitch); memcpy(result.data(), mappedResource.pData, mappedResource.RowPitch); context->base->Unmap(stagingBuffer, 0); }
void BufferStorage11::setData(const void* data, size_t size, size_t offset) { size_t requiredSize = size + offset; mSize = std::max(mSize, requiredSize); if (data) { NativeBuffer11 *stagingBuffer = getStagingBuffer(); if (!stagingBuffer) { // Out-of-memory return; } // Explicitly resize the staging buffer, preserving data if the new data will not // completely fill the buffer if (stagingBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); if (!stagingBuffer->resize(requiredSize, preserveData)) { // Out-of-memory return; } } ID3D11DeviceContext *context = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource); if (FAILED(result)) { return gl::error(GL_OUT_OF_MEMORY); } unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset; memcpy(offsetBufferPointer, data, size); context->Unmap(stagingBuffer->getNativeBuffer(), 0); stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); } }
void Driver::checkCurrentGprBuffer(ShaderStage shaderStage) { const void *registerVals = nullptr; if (shaderStage == ShaderStage::Vertex) { registerVals = &mRegisters[latte::Register::SQ_ALU_CONSTANT0_256 / 4]; } else if (shaderStage == ShaderStage::Geometry) { // No registers are reserved for GS return; } else if (shaderStage == ShaderStage::Pixel) { registerVals = &mRegisters[latte::Register::SQ_ALU_CONSTANT0_0 / 4]; } else { decaf_abort("Unknown shader stage"); } auto gprsBuffer = getStagingBuffer(256 * 4 * 4, vk::BufferUsageFlagBits::eUniformBuffer); auto mappedData = mapStagingBuffer(gprsBuffer, false); memcpy(mappedData, registerVals, 256 * 4 * 4); unmapStagingBuffer(gprsBuffer, true); mCurrentUniformBlocks[int(shaderStage)][0] = gprsBuffer; }
void *BufferStorage11::getData() { NativeBuffer11 *stagingBuffer = getStagingBuffer(); if (!stagingBuffer) { // Out-of-memory return NULL; } if (stagingBuffer->getDataRevision() > mResolvedDataRevision) { if (stagingBuffer->getSize() > mResolvedData.size()) { mResolvedData.resize(stagingBuffer->getSize()); } ID3D11DeviceContext *context = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); if (FAILED(result)) { return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); } memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); context->Unmap(stagingBuffer->getNativeBuffer(), 0); mResolvedDataRevision = stagingBuffer->getDataRevision(); } mReadUsageCount = 0; return mResolvedData.data(); }