Ejemplo n.º 1
0
void MyD3DAssets::readTexture(ID3D11Texture2D *inputTexture, Bitmap &result)
{
    ID3D11Texture2D *stagingTexture = getStagingTexture(inputTexture);

    D3D11_TEXTURE2D_DESC desc;
    stagingTexture->GetDesc(&desc);
    if (result.getWidth() != desc.Width || result.getHeight() != desc.Height)
        result.allocate(desc.Width, desc.Height);

    for (auto &p : result)
        p.value = ml::vec4uc(50, 100, 150, 255);

    context->base->CopyResource(stagingTexture, inputTexture);

    D3D11_MAPPED_SUBRESOURCE resource;
    UINT subresource = D3D11CalcSubresource(0, 0, 0);
    HRESULT hr = context->base->Map(stagingTexture, subresource, D3D11_MAP_READ, 0, &resource);
    const BYTE *data = (BYTE *)resource.pData;

    for (UINT y = 0; y < desc.Height; y++)
    {
        memcpy(&result(0U, y), data + resource.RowPitch * y, desc.Width * sizeof(ml::vec4uc));
    }

    context->base->Unmap(stagingTexture, subresource);
}
Ejemplo n.º 2
0
gl::Error Image11::map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
    // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
    ANGLE_TRY(recoverFromAssociatedStorage(context));

    const TextureHelper11 *stagingTexture = nullptr;
    unsigned int subresourceIndex  = 0;
    ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex));

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    ASSERT(stagingTexture && stagingTexture->valid());
    HRESULT result = deviceContext->Map(stagingTexture->get(), subresourceIndex, mapType, 0, map);

    if (FAILED(result))
    {
        // this can fail if the device is removed (from TDR)
        if (d3d11::isDeviceLostError(result))
        {
            mRenderer->notifyDeviceLost();
        }
        return gl::OutOfMemory() << "Failed to map staging texture, " << gl::FmtHR(result);
    }

    mDirty = true;

    return gl::NoError();
}
Ejemplo n.º 3
0
gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
                                         const gl::Box &sourceArea,
                                         const TextureHelper11 &textureHelper,
                                         UINT sourceSubResource)
{
    // No conversion needed-- use copyback fastpath
    const TextureHelper11 *stagingTexture = nullptr;
    unsigned int stagingSubresourceIndex = 0;
    ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    const gl::Extents &extents = textureHelper.getExtents();

    D3D11_BOX srcBox;
    srcBox.left   = sourceArea.x;
    srcBox.right  = sourceArea.x + sourceArea.width;
    srcBox.top    = sourceArea.y;
    srcBox.bottom = sourceArea.y + sourceArea.height;
    srcBox.front  = sourceArea.z;
    srcBox.back   = sourceArea.z + sourceArea.depth;

    if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
    {
        D3D11_TEXTURE2D_DESC resolveDesc;
        resolveDesc.Width              = extents.width;
        resolveDesc.Height             = extents.height;
        resolveDesc.MipLevels          = 1;
        resolveDesc.ArraySize          = 1;
        resolveDesc.Format             = textureHelper.getFormat();
        resolveDesc.SampleDesc.Count   = 1;
        resolveDesc.SampleDesc.Quality = 0;
        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
        resolveDesc.BindFlags          = 0;
        resolveDesc.CPUAccessFlags     = 0;
        resolveDesc.MiscFlags          = 0;

        d3d11::Texture2D resolveTex;
        ANGLE_TRY(mRenderer->allocateResource(resolveDesc, &resolveTex));

        deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(),
                                          sourceSubResource, textureHelper.getFormat());

        deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
                                             destOffset.x, destOffset.y, destOffset.z,
                                             resolveTex.get(), 0, &srcBox);
    }
    else
    {
        deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
                                             destOffset.x, destOffset.y, destOffset.z,
                                             textureHelper.get(), sourceSubResource, &srcBox);
    }

    mDirty = true;
    return gl::NoError();
}
Ejemplo n.º 4
0
bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, bool mipped)
{
    TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
    bool ret = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height, mipped);
	/* blamb: attempt to reduce memory */
	if (mStagingTexture)
    {
        mStagingTexture->Release();
        mStagingTexture = NULL;
    }
	return ret;
}
Ejemplo n.º 5
0
gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
{
    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);

    // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times,
    // then we should just keep the staging texture around to prevent the copying from impacting perf.
    // We allow the Image11 to copy its data to/from TextureStorage once.
    // This accounts for an app making a late call to glGenerateMipmap.
    bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);

    if (attemptToReleaseStagingTexture)
    {
        // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it.
        gl::Error error = storage11->releaseAssociatedImage(index, this);
        if (error.isError())
        {
            return error;
        }
    }

    ID3D11Resource *stagingTexture = NULL;
    unsigned int stagingSubresourceIndex = 0;
    gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
    if (error.isError())
    {
        return error;
    }

    error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region);
    if (error.isError())
    {
        return error;
    }

    // Once the image data has been copied into the Storage, we can release it locally.
    if (attemptToReleaseStagingTexture)
    {
        storage11->associateImage(this, index);
        releaseStagingTexture();
        mRecoverFromStorage = true;
        mAssociatedStorage = storage11;
        mAssociatedImageIndex = index;
    }

    return gl::Error(GL_NO_ERROR);
}
Ejemplo n.º 6
0
gl::Error Image11::copyToStorage(const gl::Context *context,
                                 TextureStorage *storage,
                                 const gl::ImageIndex &index,
                                 const gl::Box &region)
{
    TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);

    // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage
    // multiple times, then we should just keep the staging texture around to prevent the copying
    // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This
    // accounts for an app making a late call to glGenerateMipmap.
    bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);

    if (attemptToReleaseStagingTexture)
    {
        // If another image is relying on this Storage for its data, then we must let it recover its
        // data before we overwrite it.
        ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this));
    }

    const TextureHelper11 *stagingTexture = nullptr;
    unsigned int stagingSubresourceIndex = 0;
    ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
    ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex,
                                                index, region));

    // Once the image data has been copied into the Storage, we can release it locally.
    if (attemptToReleaseStagingTexture)
    {
        storage11->associateImage(this, index);
        releaseStagingTexture();
        mRecoverFromStorage   = true;
        mAssociatedStorage    = storage11;
        mAssociatedImageIndex = index;
    }

    return gl::NoError();
}
Ejemplo n.º 7
0
gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
    // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
    gl::Error error = recoverFromAssociatedStorage();
    if (error.isError())
    {
        return error;
    }

    ID3D11Resource *stagingTexture = NULL;
    unsigned int subresourceIndex = 0;
    error = getStagingTexture(&stagingTexture, &subresourceIndex);
    if (error.isError())
    {
        return error;
    }

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    ASSERT(mStagingTexture);
    HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);

    // this can fail if the device is removed (from TDR)
    if (d3d11::isDeviceLostError(result))
    {
        mRenderer->notifyDeviceLost();
    }
    else if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
    }

    mDirty = true;

    return gl::Error(GL_NO_ERROR);
}
Ejemplo n.º 8
0
gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource)
{
    D3D11_TEXTURE2D_DESC textureDesc;
    source->GetDesc(&textureDesc);

    if (textureDesc.Format == mDXGIFormat)
    {
        // No conversion needed-- use copyback fastpath
        ID3D11Resource *stagingTexture = NULL;
        unsigned int stagingSubresourceIndex = 0;
        gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
        if (error.isError())
        {
            return error;
        }

        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

        UINT subresourceAfterResolve = sourceSubResource;

        ID3D11Texture2D* srcTex = NULL;
        if (textureDesc.SampleDesc.Count > 1)
        {
            D3D11_TEXTURE2D_DESC resolveDesc;
            resolveDesc.Width = textureDesc.Width;
            resolveDesc.Height = textureDesc.Height;
            resolveDesc.MipLevels = 1;
            resolveDesc.ArraySize = 1;
            resolveDesc.Format = textureDesc.Format;
            resolveDesc.SampleDesc.Count = 1;
            resolveDesc.SampleDesc.Quality = 0;
            resolveDesc.Usage = D3D11_USAGE_DEFAULT;
            resolveDesc.BindFlags = 0;
            resolveDesc.CPUAccessFlags = 0;
            resolveDesc.MiscFlags = 0;

            HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
            if (FAILED(result))
            {
                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
            }

            deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format);
            subresourceAfterResolve = 0;
        }
        else
        {
            srcTex = source;
        }

        D3D11_BOX srcBox;
        srcBox.left = sourceArea.x;
        srcBox.right = sourceArea.x + sourceArea.width;
        srcBox.top = sourceArea.y;
        srcBox.bottom = sourceArea.y + sourceArea.height;
        srcBox.front = 0;
        srcBox.back = 1;

        deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);

        if (textureDesc.SampleDesc.Count > 1)
        {
            SafeRelease(srcTex);
        }
    }
    else
    {
        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
        D3D11_MAPPED_SUBRESOURCE mappedImage;
        gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
        if (error.isError())
        {
            return error;
        }

        // determine the offset coordinate into the destination buffer
        GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
        uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;

        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);

        error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);

        unmap();

        if (error.isError())
        {
            return error;
        }
    }

    mDirty = true;

    return gl::Error(GL_NO_ERROR);
}
Ejemplo n.º 9
0
bool Image11::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
    TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
    return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, 0, width, height, 1);
}
Ejemplo n.º 10
0
bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height)
{
    TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance());
    return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, arrayLayer, xoffset, yoffset, 0, width, height, 1);
}
Ejemplo n.º 11
0
bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
{
    TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance());
    return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth);
}
Ejemplo n.º 12
0
gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
                                         const gl::Box &sourceArea,
                                         const TextureHelper11 &textureHelper,
                                         UINT sourceSubResource)
{
    // No conversion needed-- use copyback fastpath
    ID3D11Resource *stagingTexture       = nullptr;
    unsigned int stagingSubresourceIndex = 0;
    gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
    if (error.isError())
    {
        return error;
    }

    ID3D11Device *device               = mRenderer->getDevice();
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    UINT subresourceAfterResolve = sourceSubResource;

    ID3D11Resource *srcTex     = nullptr;
    const gl::Extents &extents = textureHelper.getExtents();

    bool needResolve =
        (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1);

    if (needResolve)
    {
        D3D11_TEXTURE2D_DESC resolveDesc;
        resolveDesc.Width              = extents.width;
        resolveDesc.Height             = extents.height;
        resolveDesc.MipLevels          = 1;
        resolveDesc.ArraySize          = 1;
        resolveDesc.Format             = textureHelper.getFormat();
        resolveDesc.SampleDesc.Count   = 1;
        resolveDesc.SampleDesc.Quality = 0;
        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
        resolveDesc.BindFlags          = 0;
        resolveDesc.CPUAccessFlags     = 0;
        resolveDesc.MiscFlags          = 0;

        ID3D11Texture2D *srcTex2D = NULL;
        HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.",
                             result);
        }
        srcTex = srcTex2D;

        deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(),
                                          sourceSubResource, textureHelper.getFormat());
        subresourceAfterResolve = 0;
    }
    else
    {
        srcTex = textureHelper.getResource();
    }

    D3D11_BOX srcBox;
    srcBox.left   = sourceArea.x;
    srcBox.right  = sourceArea.x + sourceArea.width;
    srcBox.top    = sourceArea.y;
    srcBox.bottom = sourceArea.y + sourceArea.height;
    srcBox.front  = sourceArea.z;
    srcBox.back   = sourceArea.z + sourceArea.depth;

    deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x,
                                         destOffset.y, destOffset.z, srcTex,
                                         subresourceAfterResolve, &srcBox);

    if (needResolve)
    {
        SafeRelease(srcTex);
    }

    mDirty = true;
    return gl::Error(GL_NO_ERROR);
}
Ejemplo n.º 13
0
gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource)
{
    D3D11_RESOURCE_DIMENSION dim;
    source->GetType(&dim);

    DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
    gl::Extents extents;
    UINT sampleCount = 0;

    ID3D11Texture2D *source2D = NULL;

    if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
    {
        D3D11_TEXTURE2D_DESC textureDesc2D;
        source2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(source);
        ASSERT(source2D);
        source2D->GetDesc(&textureDesc2D);

        format = textureDesc2D.Format;
        extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1);
        sampleCount = textureDesc2D.SampleDesc.Count;
    }
    else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
    {
        D3D11_TEXTURE3D_DESC textureDesc3D;
        ID3D11Texture3D *source3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(source);
        ASSERT(source3D);
        source3D->GetDesc(&textureDesc3D);

        format = textureDesc3D.Format;
        extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth);
        sampleCount = 1;
    }
    else
    {
        UNREACHABLE();
    }

    if (format == mDXGIFormat)
    {
        // No conversion needed-- use copyback fastpath
        ID3D11Resource *stagingTexture = NULL;
        unsigned int stagingSubresourceIndex = 0;
        gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
        if (error.isError())
        {
            return error;
        }

        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

        UINT subresourceAfterResolve = sourceSubResource;

        ID3D11Resource *srcTex = NULL;

        bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1);

        if (needResolve)
        {
            D3D11_TEXTURE2D_DESC resolveDesc;
            resolveDesc.Width = extents.width;
            resolveDesc.Height = extents.height;
            resolveDesc.MipLevels = 1;
            resolveDesc.ArraySize = 1;
            resolveDesc.Format = format;
            resolveDesc.SampleDesc.Count = 1;
            resolveDesc.SampleDesc.Quality = 0;
            resolveDesc.Usage = D3D11_USAGE_DEFAULT;
            resolveDesc.BindFlags = 0;
            resolveDesc.CPUAccessFlags = 0;
            resolveDesc.MiscFlags = 0;

            ID3D11Texture2D *srcTex2D = NULL;
            HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
            if (FAILED(result))
            {
                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
            }
            srcTex = srcTex2D;

            deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format);
            subresourceAfterResolve = 0;
        }
        else
        {
            srcTex = source;
        }

        D3D11_BOX srcBox;
        srcBox.left = sourceArea.x;
        srcBox.right = sourceArea.x + sourceArea.width;
        srcBox.top = sourceArea.y;
        srcBox.bottom = sourceArea.y + sourceArea.height;
        srcBox.front = sourceArea.z;
        srcBox.back = sourceArea.z + sourceArea.depth;

        deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y,
                                             destOffset.z, srcTex, subresourceAfterResolve, &srcBox);

        if (needResolve)
        {
            SafeRelease(srcTex);
        }
    }
    else
    {
        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
        D3D11_MAPPED_SUBRESOURCE mappedImage;
        gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
        if (error.isError())
        {
            return error;
        }

        // determine the offset coordinate into the destination buffer
        const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
        GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x;
        uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch;

        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);

        // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer
        // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats.
        ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D);
        ASSERT(sourceArea.z == 0 && sourceArea.depth == 1);
        gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height);
        error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);

        unmap();

        if (error.isError())
        {
            return error;
        }
    }

    mDirty = true;

    return gl::Error(GL_NO_ERROR);
}