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(); }
void MSAAFilter::RenderAA() { PIXEvent pixEvent(L"MSAA Resolve + Temporal AA"); ProfileBlock profileBlock(L"MSAA Resolve + Temporal AA"); ID3D11DeviceContext* context = deviceManager.ImmediateContext(); ID3D11RenderTargetView* rtvs[1] = { resolveTarget.RTView }; context->OMSetRenderTargets(1, rtvs, nullptr); if(AppSettings::UseStandardResolve) { if(AppSettings::MSAAMode == 0) context->CopyResource(resolveTarget.Texture, colorTarget.Texture); else context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format); return; } const uint32 SampleRadius = static_cast<uint32>((AppSettings::ResolveFilterDiameter / 2.0f) + 0.499f); ID3D11PixelShader* pixelShader = resolvePS[AppSettings::MSAAMode]; context->PSSetShader(pixelShader, nullptr, 0); context->VSSetShader(resolveVS, nullptr, 0); resolveConstants.Data.TextureSize = Float2(static_cast<float>(colorTarget.Width), static_cast<float>(colorTarget.Height)); resolveConstants.Data.SampleRadius = SampleRadius;; resolveConstants.ApplyChanges(context); resolveConstants.SetPS(context, 0); ID3D11ShaderResourceView* srvs[] = { colorTarget.SRView, velocityTarget.SRView, depthBuffer.SRView, prevFrameTarget.SRView}; context->PSSetShaderResources(0, ArraySize_(srvs), srvs); ID3D11SamplerState* samplers[] = { samplerStates.LinearClamp(), samplerStates.Point() }; context->PSSetSamplers(0, ArraySize_(samplers), samplers); ID3D11Buffer* vbs[1] = { nullptr }; UINT strides[1] = { 0 }; UINT offsets[1] = { 0 }; context->IASetVertexBuffers(0, 1, vbs, strides, offsets); context->IASetInputLayout(nullptr); context->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); context->Draw(3, 0); rtvs[0] = nullptr; context->OMSetRenderTargets(1, rtvs, nullptr); srvs[0] = srvs[1] = srvs[2] = nullptr; context->PSSetShaderResources(0, 3, srvs); context->CopyResource(prevFrameTarget.Texture, resolveTarget.Texture); }
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); }
//----------------------------------------- void CPUTRenderTargetColor::Resolve( CPUTRenderParameters &renderParams ) { ID3D11DeviceContext *pContext = CPUT_DX11::GetContext(); pContext->ResolveSubresource( mpColorTextureDX, 0, mpColorTextureDXMSAA, 0, mColorFormat); }
HRESULT STDMETHODCALLTYPE SwapPresentHook(UINT syncInterval, UINT flags) { IDXGISwapChain *swap = (IDXGISwapChain*)this; if(lpCurrentSwap == NULL && !bTargetAcquired) { lpCurrentSwap = swap; SetupD3D11(swap); bTargetAcquired = true; } if(lpCurrentSwap == swap) { ID3D11Device *device = NULL; HRESULT chi; if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device))) { if(!lpCurrentDevice) { lpCurrentDevice = device; oldD3D11Release = GetVTable(device, (8/4)); newD3D11Release = ConvertClassProcToFarproc((CLASSPROC)&D3D11Override::DeviceReleaseHook); SetVTable(device, (8/4), newD3D11Release); } ID3D11DeviceContext *context; device->GetImmediateContext(&context); if(!bHasTextures && bCapturing) { if(dxgiFormat) { if(!hwndReceiver) hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL); if(hwndReceiver) { D3D11_TEXTURE2D_DESC texDesc; ZeroMemory(&texDesc, sizeof(texDesc)); texDesc.Width = d3d11CaptureInfo.cx; texDesc.Height = d3d11CaptureInfo.cy; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = dxgiFormat; texDesc.SampleDesc.Count = 1; texDesc.Usage = D3D11_USAGE_STAGING; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; bool bSuccess = true; UINT pitch; for(UINT i=0; i<2; i++) { HRESULT ching; if(FAILED(ching = device->CreateTexture2D(&texDesc, NULL, &d3d11Textures[i]))) { bSuccess = false; break; } if(i == 0) { ID3D11Resource *resource; if(FAILED(d3d11Textures[i]->QueryInterface(__uuidof(ID3D11Resource), (void**)&resource))) { bSuccess = false; break; } D3D11_MAPPED_SUBRESOURCE map; if(FAILED(context->Map(resource, 0, D3D11_MAP_READ, 0, &map))) { bSuccess = false; break; } pitch = map.RowPitch; context->Unmap(resource, 0); resource->Release(); } } if(bSuccess) { d3d11CaptureInfo.mapID = InitializeSharedMemory(pitch*d3d11CaptureInfo.cy, &d3d11CaptureInfo.mapSize, ©Data, textureBuffers); if(!d3d11CaptureInfo.mapID) bSuccess = false; } if(bSuccess) { bHasTextures = true; d3d11CaptureInfo.captureType = CAPTURETYPE_MEMORY; d3d11CaptureInfo.hwndSender = hwndSender; d3d11CaptureInfo.pitch = pitch; d3d11CaptureInfo.bFlip = FALSE; PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d11CaptureInfo); } else { for(UINT i=0; i<2; i++) { SafeRelease(d3d11Textures[i]); if(textureBuffers[i]) { free(textureBuffers[i]); textureBuffers[i] = NULL; } } } } } } if(bHasTextures) { if(bCapturing) { DWORD nextCapture = curCapture == 0 ? 1 : 0; ID3D11Texture2D *texture = d3d11Textures[curCapture]; ID3D11Resource *backBuffer = NULL; if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer))) { if(bIsMultisampled) context->ResolveSubresource(texture, 0, backBuffer, 0, dxgiFormat); else context->CopyResource(texture, backBuffer); backBuffer->Release(); ID3D11Texture2D *lastTexture = d3d11Textures[nextCapture]; ID3D11Resource *resource; if(SUCCEEDED(lastTexture->QueryInterface(__uuidof(ID3D11Resource), (void**)&resource))) { D3D11_MAPPED_SUBRESOURCE map; if(SUCCEEDED(context->Map(resource, 0, D3D11_MAP_READ, 0, &map))) { LPBYTE *pTextureBuffer = NULL; int lastRendered = -1; //under no circumstances do we -ever- allow a stall if(WaitForSingleObject(textureMutexes[curCapture], 0) == WAIT_OBJECT_0) lastRendered = (int)curCapture; else if(WaitForSingleObject(textureMutexes[nextCapture], 0) == WAIT_OBJECT_0) lastRendered = (int)nextCapture; if(lastRendered != -1) { SSECopy(textureBuffers[lastRendered], map.pData, map.RowPitch*d3d11CaptureInfo.cy); ReleaseMutex(textureMutexes[lastRendered]); } context->Unmap(resource, 0); copyData->lastRendered = (UINT)lastRendered; } resource->Release(); } } curCapture = nextCapture; } else ClearD3D11Data(); } device->Release(); context->Release(); } } gi11swapPresent.Unhook(); HRESULT hRes = swap->Present(syncInterval, flags); gi11swapPresent.Rehook(); return hRes; }
HRESULT STDMETHODCALLTYPE D3D11SwapPresentHook(IDXGISwapChain *swap, UINT syncInterval, UINT flags) { if(lpCurrentSwap == NULL && !bTargetAcquired) { lpCurrentSwap = swap; SetupD3D11(swap); bTargetAcquired = true; } if(lpCurrentSwap == swap) { ID3D11Device *device = NULL; HRESULT chi; if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device))) { if(!lpCurrentDevice) { lpCurrentDevice = device; /*FARPROC curRelease = GetVTable(device, (8/4)); if(curRelease != newD3D11Release) { oldD3D11Release = curRelease; newD3D11Release = (FARPROC)DeviceReleaseHook; SetVTable(device, (8/4), newD3D11Release); }*/ } ID3D11DeviceContext *context; device->GetImmediateContext(&context); if(bCapturing && bStopRequested) { ClearD3D11Data(); bStopRequested = false; } if(!bHasTextures && bCapturing) { if(dxgiFormat) { if(!hwndReceiver) hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL); if(hwndReceiver) { BOOL bSuccess = DoD3D11Hook(device); if(bSuccess) { d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData); if(!d3d11CaptureInfo.mapID) { RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl; bSuccess = false; } } if(bSuccess) bSuccess = IsWindow(hwndReceiver); if(bSuccess) { bHasTextures = true; d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX; d3d11CaptureInfo.hwndSender = hwndSender; d3d11CaptureInfo.bFlip = FALSE; texData->texHandles[0] = sharedHandles[0]; texData->texHandles[1] = sharedHandles[1]; PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d11CaptureInfo); logOutput << "DoD3D11Hook: success"; } else { ClearD3D11Data(); } } } } if(bHasTextures) { LONGLONG frameTime; if(bCapturing) { if(texData) { if(frameTime = texData->frameTime) { LONGLONG timeVal = OSGetTimeMicroseconds(); LONGLONG timeElapsed = timeVal-lastTime; if(timeElapsed >= frameTime) { lastTime += frameTime; if(timeElapsed > frameTime*2) lastTime = timeVal; DWORD nextCapture = curCapture == 0 ? 1 : 0; ID3D11Resource *backBuffer = NULL; if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer))) { if(bIsMultisampled) context->ResolveSubresource(copyTextureGame, 0, backBuffer, 0, dxgiFormat); else context->CopyResource(copyTextureGame, backBuffer); ID3D10Texture2D *outputTexture = NULL; int lastRendered = -1; if(keyedMutexes[curCapture]->AcquireSync(0, 0) == WAIT_OBJECT_0) lastRendered = (int)curCapture; else if(keyedMutexes[nextCapture]->AcquireSync(0, 0) == WAIT_OBJECT_0) lastRendered = (int)nextCapture; if(lastRendered != -1) { shareDevice->CopyResource(sharedTextures[lastRendered], copyTextureIntermediary); keyedMutexes[lastRendered]->ReleaseSync(0); } texData->lastRendered = lastRendered; backBuffer->Release(); } curCapture = nextCapture; } } } } else ClearD3D11Data(); } device->Release(); context->Release(); } } gi11swapPresent.Unhook(); HRESULT hRes = swap->Present(syncInterval, flags); gi11swapPresent.Rehook(); return hRes; }
void DoD3D11Capture(IDXGISwapChain *swap) { ID3D11Device *device = NULL; HRESULT chi; if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device))) { if(!lpCurrentDevice) { lpCurrentDevice = device; /*FARPROC curRelease = GetVTable(device, (8/4)); if(curRelease != newD3D11Release) { oldD3D11Release = curRelease; newD3D11Release = (FARPROC)DeviceReleaseHook; SetVTable(device, (8/4), newD3D11Release); }*/ } ID3D11DeviceContext *context; device->GetImmediateContext(&context); if(bCapturing && bStopRequested) { ClearD3D11Data(); bCapturing = false; bStopRequested = false; } if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0) { hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL); if(hwndOBS) bCapturing = true; } if(!bHasTextures && bCapturing) { if(dxgiFormat && hwndOBS) { BOOL bSuccess = DoD3D11Hook(device); if(bSuccess) { d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData); if(!d3d11CaptureInfo.mapID) { RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl; bSuccess = false; } } if(bSuccess) { bHasTextures = true; d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX; d3d11CaptureInfo.bFlip = FALSE; texData->texHandle = (DWORD)sharedHandle; memcpy(infoMem, &d3d11CaptureInfo, sizeof(CaptureInfo)); SetEvent(hSignalReady); logOutput << "DoD3D11Hook: success" << endl; } else { ClearD3D11Data(); } } } if(bHasTextures) { LONGLONG timeVal = OSGetTimeMicroseconds(); //check keep alive state, dumb but effective if(bCapturing) { if((timeVal-keepAliveTime) > 3000000) { HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str()); if (hKeepAlive) { CloseHandle(hKeepAlive); } else { ClearD3D11Data(); bCapturing = false; } keepAliveTime = timeVal; } } LONGLONG frameTime; if(bCapturing) { if(texData) { if(frameTime = texData->frameTime) { LONGLONG timeElapsed = timeVal-lastTime; if(timeElapsed >= frameTime) { if(!IsWindow(hwndOBS)) { hwndOBS = NULL; bStopRequested = true; } if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0) bStopRequested = true; lastTime += frameTime; if(timeElapsed > frameTime*2) lastTime = timeVal; DWORD nextCapture = curCapture == 0 ? 1 : 0; ID3D11Resource *backBuffer = NULL; if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer))) { if(bIsMultisampled) context->ResolveSubresource(copyTextureGame, 0, backBuffer, 0, dxgiFormat); else context->CopyResource(copyTextureGame, backBuffer); backBuffer->Release(); } curCapture = nextCapture; } } } } else ClearD3D11Data(); } device->Release(); context->Release(); } }
void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat) { // No conversion needed-- use copyback fastpath ID3D11Texture2D *colorBufferTexture = NULL; unsigned int subresourceIndex = 0; if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) { D3D11_TEXTURE2D_DESC textureDesc; colorBufferTexture->GetDesc(&textureDesc); ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 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)) { ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); return; } deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); subresourceIndex = 0; } else { srcTex = colorBufferTexture; srcTex->AddRef(); } D3D11_BOX srcBox; srcBox.left = x; srcBox.right = x + width; srcBox.top = y; srcBox.bottom = y + height; srcBox.front = 0; srcBox.back = 1; deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox); SafeRelease(srcTex); SafeRelease(colorBufferTexture); } } else { // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels D3D11_MAPPED_SUBRESOURCE mappedImage; HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); if (FAILED(result)) { ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result); return; } // determine the offset coordinate into the destination buffer GLsizei rowOffset = gl::GetPixelBytes(mActualFormat) * xoffset; void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; GLenum format = gl::GetFormat(mInternalFormat); GLenum type = gl::GetType(mInternalFormat); mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); unmap(); } }
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); }
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); }