//----------------------------------------------------------------------------- void CPUTMeshDX11::Unmap( ID3D11Buffer *pBuffer, ID3D11Buffer *pStagingBuffer, eCPUTMapType *pMappedType, CPUTRenderParameters ¶ms ) { ASSERT( *pMappedType != CPUT_MAP_UNDEFINED, "Can't unmap a buffer that isn't mapped." ); ID3D11DeviceContext *pContext = CPUT_DX11::GetContext(); pContext->Unmap( pStagingBuffer, 0 ); // If we were mapped for write, then copy staging buffer to GPU switch( *pMappedType ) { case CPUT_MAP_READ: break; case CPUT_MAP_READ_WRITE: case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: pContext->CopyResource( pBuffer, pStagingBuffer ); break; }; } // CPUTMeshDX11::Unmap()
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); }
void DX11ScratchStructuredArray::Refresh(ID3D11DeviceContext& context) { // Read back the result into staging memory context.CopyResource(readback_buffer_.Get(), buffer_.Get()); // Copy the staging memory buffer into system memory buffer D3D11_MAPPED_SUBRESOURCE subresource; context.Map(readback_buffer_.Get(), 0, // Map everything D3D11_MAP_READ, 0, &subresource); auto size = element_size_ * element_count_; memcpy_s(raw_buffer_, size, subresource.pData, size); context.Unmap(readback_buffer_.Get(), 0); }
//----------------------------------------------------------------------------- void CPUTMeshDX11::Unmap( ID3D11Buffer *pBuffer, ID3D11Buffer *pStagingBuffer, eCPUTMapType *pMappedType, CPUTRenderParameters ¶ms ) { ASSERT( *pMappedType != CPUT_MAP_UNDEFINED, _L("Can't unmap a buffer that isn't mapped.") ); CPUTRenderParametersDX *pParamsDX11 = (CPUTRenderParametersDX*)¶ms; ID3D11DeviceContext *pContext = pParamsDX11->mpContext; pContext->Unmap( pStagingBuffer, 0 ); // If we were mapped for write, then copy staging buffer to GPU switch( *pMappedType ) { case CPUT_MAP_READ: break; case CPUT_MAP_READ_WRITE: case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: pContext->CopyResource( pBuffer, pStagingBuffer ); break; }; // *pMappedType = CPUT_MAP_UNDEFINED; // TODO: Just commented this out. Otherwise, assert in Map() fails. Verify. } // CPUTMeshDX11::Unmap()
void checkPixelsUsingD3D(bool usingPresentPathFast) { ASSERT_NE(nullptr, mOffscreenSurfaceD3D11Texture); D3D11_TEXTURE2D_DESC textureDesc = {0}; ID3D11Device *device; ID3D11DeviceContext *context; mOffscreenSurfaceD3D11Texture->GetDesc(&textureDesc); mOffscreenSurfaceD3D11Texture->GetDevice(&device); device->GetImmediateContext(&context); ASSERT_NE(nullptr, device); ASSERT_NE(nullptr, context); textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; textureDesc.Usage = D3D11_USAGE_STAGING; textureDesc.BindFlags = 0; textureDesc.MiscFlags = 0; ID3D11Texture2D *cpuTexture = nullptr; ASSERT_TRUE(SUCCEEDED(device->CreateTexture2D(&textureDesc, nullptr, &cpuTexture))); context->CopyResource(cpuTexture, mOffscreenSurfaceD3D11Texture); D3D11_MAPPED_SUBRESOURCE mappedSubresource; context->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mappedSubresource); ASSERT_EQ(static_cast<UINT>(mWindowWidth * 4), mappedSubresource.RowPitch); ASSERT_EQ(static_cast<UINT>(mWindowWidth * mWindowWidth * 4), mappedSubresource.DepthPitch); angle::GLColor *byteData = reinterpret_cast<angle::GLColor *>(mappedSubresource.pData); // Note that the texture is in BGRA format, although the GLColor struct is RGBA GLColor expectedTopLeftPixel = GLColor(0, 0, 255, 255); // Red GLColor expectedTopRightPixel = GLColor(0, 255, 0, 255); // Green GLColor expectedBottomLeftPixel = GLColor(255, 0, 0, 255); // Blue GLColor expectedBottomRightPixel = GLColor(0, 255, 255, 255); // Red + Green if (usingPresentPathFast) { // Invert the expected values GLColor tempTopLeft = expectedTopLeftPixel; GLColor tempTopRight = expectedTopRightPixel; expectedTopLeftPixel = expectedBottomLeftPixel; expectedTopRightPixel = expectedBottomRightPixel; expectedBottomLeftPixel = tempTopLeft; expectedBottomRightPixel = tempTopRight; } EXPECT_EQ(expectedTopLeftPixel, byteData[0]); EXPECT_EQ(expectedTopRightPixel, byteData[(mWindowWidth - 1)]); EXPECT_EQ(expectedBottomLeftPixel, byteData[(mWindowWidth - 1) * mWindowWidth]); EXPECT_EQ(expectedBottomRightPixel, byteData[(mWindowWidth - 1) * mWindowWidth + (mWindowWidth - 1)]); context->Unmap(cpuTexture, 0); SafeRelease(cpuTexture); SafeRelease(device); SafeRelease(context); }
// // Read the pixel content of a sprite. // uint8_t * SpriteUtils::ReadPixels( ID3D11DeviceContext2 * context, ID3D11Device2 * device, ID3D11Texture2D * texture, int * dimensions) { HBITMAP hBitmapTexture = NULL; ID3D11Texture2D* d3dtex = (ID3D11Texture2D*)texture; D3D11_TEXTURE2D_DESC desc; d3dtex->GetDesc(&desc); ID3D11Texture2D* pNewTexture = NULL; D3D11_TEXTURE2D_DESC description; d3dtex->GetDesc(&description); description.BindFlags = 0; description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; description.Usage = D3D11_USAGE_STAGING; HRESULT hr = device->CreateTexture2D(&description, NULL, &pNewTexture); ID3D11DeviceContext* ctx = NULL; device->GetImmediateContext(&ctx); ctx->CopyResource(pNewTexture, d3dtex); D3D11_MAPPED_SUBRESOURCE resource; UINT subresource = D3D11CalcSubresource(0, 0, 0); ctx->Map(pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource); // COPY from texture to bitmap buffer uint8_t* sptr = reinterpret_cast<uint8_t*>(resource.pData); uint8_t* dptr = new uint8_t[desc.Width * desc.Height * 4]; for (size_t h = 0; h < desc.Height; ++h) { size_t msize = std::min<size_t>(desc.Width * 4, resource.RowPitch); memcpy_s(dptr, desc.Width * 4, sptr, msize); sptr += resource.RowPitch; dptr += desc.Width * 4; } dptr -= desc.Width*desc.Height * 4; ctx->Unmap(pNewTexture, subresource); // SWAP BGR to RGB bitmap // Notice the capital "P". dptr vs dPtr. uint32_t * dPtr = reinterpret_cast<uint32_t*>(dptr); *(dimensions + WIDTH_INDEX) = desc.Width; *(dimensions + HEIGHT_INDEX) = desc.Height; return dptr; }
void* UAVBufferD3D::map() { if(!gpuBuffer) { LOGFUNCERROR("No SRV created"); return nullptr; } ID3D11DeviceContext* context = device->getImmediate(); context->CopyResource(stagingBuffer, gpuBuffer); D3D11_MAPPED_SUBRESOURCE mapped; HRESULT result = context->Map(stagingBuffer, 0, D3D11_MAP_READ_WRITE, 0, &mapped); if(FAILED(result)) return nullptr; return mapped.pData; }
void CD3DTexture::SaveTexture() { if (m_texture) { delete[] m_data; m_data = nullptr; ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext(); D3D11_TEXTURE2D_DESC textureDesc; m_texture->GetDesc(&textureDesc); ID3D11Texture2D* texture = nullptr; if (textureDesc.Usage != D3D11_USAGE_STAGING || 0 == (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)) { // create texture which can be readed by CPU - D3D11_USAGE_STAGING CD3D11_TEXTURE2D_DESC stagingDesc(textureDesc); stagingDesc.Usage = D3D11_USAGE_STAGING; stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; stagingDesc.BindFlags = 0; if (FAILED(g_Windowing.Get3D11Device()->CreateTexture2D(&stagingDesc, NULL, &texture))) return; // copy contents to new texture pContext->CopyResource(texture, m_texture); } else texture = m_texture; // read data from texture D3D11_MAPPED_SUBRESOURCE res; if (SUCCEEDED(pContext->Map(texture, 0, D3D11_MAP_READ, 0, &res))) { m_pitch = res.RowPitch; unsigned int memUsage = GetMemoryUsage(res.RowPitch); m_data = new unsigned char[memUsage]; memcpy(m_data, res.pData, memUsage); pContext->Unmap(texture, 0); } else CLog::Log(LOGERROR, "%s - Failed to store resource.", __FUNCTION__); if (texture != m_texture) SAFE_RELEASE(texture); } }
void CD3DBuffer::OnDestroyDevice(bool fatal) { if (fatal) { SAFE_RELEASE(m_buffer); return; } ID3D11Device* pDevice = g_Windowing.Get3D11Device(); ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext(); if (!pDevice || !pContext || !m_buffer) return; D3D11_BUFFER_DESC srcDesc; m_buffer->GetDesc(&srcDesc); ID3D11Buffer *buffer = nullptr; if (srcDesc.Usage != D3D11_USAGE_STAGING || 0 == (srcDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ)) { CD3D11_BUFFER_DESC trgDesc(srcDesc); trgDesc.Usage = D3D11_USAGE_STAGING; trgDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; trgDesc.BindFlags = 0; if (SUCCEEDED(pDevice->CreateBuffer(&trgDesc, NULL, &buffer))) pContext->CopyResource(buffer, m_buffer); } else buffer = m_buffer; if (buffer != nullptr) { D3D11_MAPPED_SUBRESOURCE res; if (SUCCEEDED(pContext->Map(buffer, 0, D3D11_MAP_READ, 0, &res))) { m_data = new unsigned char[srcDesc.ByteWidth]; memcpy(m_data, res.pData, srcDesc.ByteWidth); pContext->Unmap(buffer, 0); } } if (buffer != m_buffer) SAFE_RELEASE(buffer); SAFE_RELEASE(m_buffer); }
void ActorPicker::PostRender(void) { //todo: move to renderer D3D11_MAPPED_SUBRESOURCE res; ID3D11DeviceContext* ctx = (ID3D11DeviceContext*)CmGetApp()->VGetRenderer()->VGetContext(); ID3D11Resource* dst = (ID3D11Resource*)m_pTexture->VGetDevicePtr(); ID3D11Resource* src = (ID3D11Resource*)m_pRenderTarget->VGetTexture()->VGetDevicePtr(); ctx->CopyResource(dst, src); D3D_SAVE_CALL(ctx->Map(dst, 0, D3D11_MAP_READ, 0, &res)); m_currentActor = ((uint*)(res.pData))[0]; ctx->Unmap(dst, 0); IConstShaderBuffer* buffer = CmGetApp()->VGetHumanView()->VGetRenderer()->VGetConstShaderBuffer(chimera::eSelectedActorIdBuffer); uint* b = (uint*)buffer->VMap(); b[0] = m_currentActor; buffer->VUnmap(); }
void CRenderCaptureDX::EndRender() { // send commands to the GPU queue g_Windowing.FinishCommandList(); ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext(); pContext->CopyResource(m_copySurface, m_renderTexture); if (m_query) { pContext->End(m_query); } if (m_flags & CAPTUREFLAG_IMMEDIATELY) SurfaceToBuffer(); else SetState(CAPTURESTATE_NEEDSREADOUT); }
void CRenderCaptureDX::EndRender() { // send commands to the GPU queue auto deviceResources = DX::DeviceResources::Get(); deviceResources->FinishCommandList(); ID3D11DeviceContext* pContext = deviceResources->GetImmediateContext(); pContext->CopyResource(m_copyTex.Get(), m_renderTex.Get()); if (m_query) { pContext->End(m_query); } if (m_flags & CAPTUREFLAG_IMMEDIATELY) SurfaceToBuffer(); else SetState(CAPTURESTATE_NEEDSREADOUT); }
Void D3D11Texture1D::Copy( D3D11Texture1D * pDstTexture, D3D11DeferredContext * pContext ) const { DebugAssert( IsCreated() && pDstTexture->IsCreated() ); DebugAssert( !m_bLocked && !(pDstTexture->m_bLocked) ); DebugAssert( pDstTexture->CanGPUWrite() ); DebugAssert( pDstTexture != this ); DebugAssert( m_hTextureDesc.Format == pDstTexture->m_hTextureDesc.Format ); DebugAssert( m_hTextureDesc.Width == pDstTexture->m_hTextureDesc.Width ); DebugAssert( m_hTextureDesc.MipLevels == pDstTexture->m_hTextureDesc.MipLevels ); DebugAssert( m_hTextureDesc.ArraySize == pDstTexture->m_hTextureDesc.ArraySize ); ID3D11DeviceContext * pDeviceContext = m_pRenderer->m_pImmediateContext; if ( pContext != NULL && pContext->IsCreated() ) pDeviceContext = pContext->m_pDeferredContext; pDeviceContext->CopyResource( pDstTexture->m_pTexture, m_pTexture ); }
//----------------------------------------------------------------------------- void CPUTTextureDX11::UnmapTexture( CPUTRenderParameters ¶ms ) { ASSERT( mMappedType != CPUT_MAP_UNDEFINED, _L("Can't unmap a render target that isn't mapped.") ); CPUTRenderParametersDX *pParamsDX11 = (CPUTRenderParametersDX*)¶ms; ID3D11DeviceContext *pContext = pParamsDX11->mpContext; pContext->Unmap( mpTextureStaging, 0 ); // If we were mapped for write, then copy staging buffer to GPU switch( mMappedType ) { case CPUT_MAP_READ: break; case CPUT_MAP_READ_WRITE: case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: pContext->CopyResource( mpTexture, mpTextureStaging ); break; }; } // CPUTTextureDX11::Unmap()
//----------------------------------------------------------------------------- void CPUTRenderTargetDepth::UnmapRenderTarget( CPUTRenderParameters ¶ms ) { ASSERT( mMappedType != CPUT_MAP_UNDEFINED, "Can't unmap a render target that isn't mapped." ); ID3D11DeviceContext *pContext = CPUT_DX11::GetContext(); pContext->Unmap( mpDepthTextureDXStaging, 0 ); // If we were mapped for write, then copy staging buffer to GPU switch( mMappedType ) { case CPUT_MAP_READ: break; case CPUT_MAP_READ_WRITE: case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: pContext->CopyResource( mpDepthTextureDX, mpDepthTextureDXStaging ); break; }; // mMappedType = CPUT_MAP_UNDEFINED; } // CPUTRenderTargetDepth::Unmap()
//----------------------------------------------------------------------------- D3D11_MAPPED_SUBRESOURCE CPUTTextureDX11::MapTexture( CPUTRenderParameters ¶ms, eCPUTMapType type, bool wait ) { // Mapping for DISCARD requires dynamic buffer. Create dynamic copy? // Could easily provide input flag. But, where would we specify? Don't like specifying in the .set file // Because mapping is something the application wants to do - it isn't inherent in the data. // Could do Clone() and pass dynamic flag to that. // But, then we have two. Could always delete the other. // Could support programatic flag - apply to all loaded models in the .set // Could support programatic flag on model. Load model first, then load set. // For now, simply support CopyResource mechanism. HRESULT hr; ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTRenderParametersDX *pParamsDX11 = (CPUTRenderParametersDX*)¶ms; ID3D11DeviceContext *pContext = pParamsDX11->mpContext; if( !mpTextureStaging ) { // Annoying. We need to create the texture differently, based on dimension. D3D11_RESOURCE_DIMENSION dimension; mpTexture->GetType(&dimension); switch( dimension ) { case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { D3D11_TEXTURE1D_DESC desc; ((ID3D11Texture1D*)mpTexture)->GetDesc( &desc ); desc.Usage = D3D11_USAGE_STAGING; switch( type ) { case CPUT_MAP_READ: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; break; case CPUT_MAP_READ_WRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; }; hr = pD3dDevice->CreateTexture1D( &desc, NULL, (ID3D11Texture1D**)&mpTextureStaging ); ASSERT( SUCCEEDED(hr), _L("Failed to create staging texture") ); break; } case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { D3D11_TEXTURE2D_DESC desc; ((ID3D11Texture2D*)mpTexture)->GetDesc( &desc ); desc.Usage = D3D11_USAGE_STAGING; switch( type ) { case CPUT_MAP_READ: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; break; case CPUT_MAP_READ_WRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; }; hr = pD3dDevice->CreateTexture2D( &desc, NULL, (ID3D11Texture2D**)&mpTextureStaging ); ASSERT( SUCCEEDED(hr), _L("Failed to create staging texture") ); break; } case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { D3D11_TEXTURE3D_DESC desc; ((ID3D11Texture3D*)mpTexture)->GetDesc( &desc ); desc.Usage = D3D11_USAGE_STAGING; switch( type ) { case CPUT_MAP_READ: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; break; case CPUT_MAP_READ_WRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; }; hr = pD3dDevice->CreateTexture3D( &desc, NULL, (ID3D11Texture3D**)&mpTextureStaging ); ASSERT( SUCCEEDED(hr), _L("Failed to create staging texture") ); break; } default: ASSERT(0, _L("Unkown texture dimension") ); break; } } else { ASSERT( mMappedType == type, _L("Mapping with a different CPU access than creation parameter.") ); } D3D11_MAPPED_SUBRESOURCE info; switch( type ) { case CPUT_MAP_READ: case CPUT_MAP_READ_WRITE: // TODO: Copying and immediately mapping probably introduces a stall. // Expose the copy externally? // TODO: copy only if changed? // Copy only first time? // Copy the GPU version before we read from it. pContext->CopyResource( mpTextureStaging, mpTexture ); break; }; hr = pContext->Map( mpTextureStaging, wait ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, (D3D11_MAP)type, 0, &info ); mMappedType = type; return info; } // CPUTTextureDX11::Map()
void UAVBufferD3D::unmap() { ID3D11DeviceContext* context = device->getImmediate(); context->Unmap(stagingBuffer, 0); context->CopyResource(gpuBuffer, stagingBuffer); }
void D3D11Grab(ID3D11Texture2D *pBackBuffer) { D3D11_TEXTURE2D_DESC tex_desc; pBackBuffer->GetDesc(&tex_desc); ID3D11Device *pDev; pBackBuffer->GetDevice(&pDev); ID3D11DeviceContext * pDevContext; pDev->GetImmediateContext(&pDevContext); ID3D11Texture2D * pTexture; D3D11_MAPPED_SUBRESOURCE mappedTexture; tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; tex_desc.ArraySize = 1; tex_desc.MipLevels = 1; tex_desc.BindFlags = 0; tex_desc.SampleDesc.Count = 1; tex_desc.SampleDesc.Quality = 0; tex_desc.Usage = D3D11_USAGE_STAGING; tex_desc.MiscFlags = 0; HRESULT hr = pDev->CreateTexture2D(&tex_desc, NULL, &pTexture); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 pDev->CreateTexture2D 0x%x", hr); pDevContext->CopyResource(pTexture, pBackBuffer); D3D11_BOX box = {0, 0, tex_desc.Width, tex_desc.Height, 0, 1}; pDevContext->CopySubresourceRegion(pTexture, 0, 0, 0, 0, pBackBuffer, 0, &box); DxgiFrameGrabber *dxgiFrameGrabber = DxgiFrameGrabber::getInstance(); IPCContext *ipcContext = dxgiFrameGrabber->m_ipcContext; Logger *logger = dxgiFrameGrabber->m_logger; // __asm__("int $3"); if (S_OK != (hr = pDevContext->Map(pTexture, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_READ, 0, &mappedTexture))) { logger->reportLogError(L"d3d11 couldn't map texture, hresult = 0x%x", hr); goto end; } ipcContext->m_memDesc.width = tex_desc.Width; ipcContext->m_memDesc.height = tex_desc.Height; ipcContext->m_memDesc.rowPitch = mappedTexture.RowPitch; ipcContext->m_memDesc.frameId++; // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 texture description. width: %u, height: %u, pitch: %u", tex_desc.Width, tex_desc.Height, mappedTexture.RowPitch); DWORD errorcode; if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) { // __asm__("int $3"); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 writing description to mem mapped file"); memcpy(ipcContext->m_pMemMap, &ipcContext->m_memDesc, sizeof (ipcContext->m_memDesc)); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 writing data to mem mapped file"); PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc)); if (mappedTexture.RowPitch == tex_desc.Width * 4) { memcpy(pMemDataMap, mappedTexture.pData, tex_desc.Width * tex_desc.Height * 4); } else { UINT i = 0, cleanOffset = 0, pitchOffset = 0; while (i < tex_desc.Height) { memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(mappedTexture.pData, pitchOffset), tex_desc.Width * 4); cleanOffset += tex_desc.Width * 4; pitchOffset += mappedTexture.RowPitch; i++; } } ReleaseMutex(ipcContext->m_hMutex); SetEvent(ipcContext->m_hFrameGrabbedEvent); } else { logger->reportLogError(L"d3d11 couldn't wait mutex. errocode = 0x%x", errorcode); } pDevContext->Unmap(pTexture, D3D10CalcSubresource(0, 0, 1)); end: pTexture->Release(); pDevContext->Release(); pDev->Release(); }
int _tmain(int /*argc*/, _TCHAR* /*argv[]*/) { // GROUP_SIZE_X defined in kernel.hlsl must match the // groupSize declared here. size_t const groupSize = 512; size_t const numGroups = 16; size_t const dimension = numGroups*groupSize; // Create a D3D11 device and immediate context. // TODO: The code below uses the default video adapter, with the // default set of feature levels. Please see the MSDN docs if // you wish to control which adapter and feature level are used. D3D_FEATURE_LEVEL featureLevel; ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, 0, D3D11_SDK_VERSION, &device, &featureLevel, &context); if (FAILED(hr)) { printf("D3D11CreateDevice failed with return code %x\n", hr); return hr; } // Create system memory and fill it with our initial data. Note that // these data structures aren't really necessary , it's just a demonstration // of how you can take existing data structures you might have and copy // their data to/from GPU computations. std::vector<float> x(dimension); std::vector<float> y(dimension); std::vector<float> z(dimension); float const a = 2.0f; for (size_t i = 0; i < dimension; ++ i) { x[i] = static_cast<float>(i); y[i] = 100 - static_cast<float>(i); } // Create structured buffers for the "x" and "y" vectors. D3D11_BUFFER_DESC inputBufferDesc; inputBufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // The buffers are read-only by the GPU, writeable by the CPU. // TODO: If you will never again upate the data in a GPU buffer, // you might want to look at using a D3D11_SUBRESOURCE_DATA here to // provide the initialization data instead of doing the mapping // and copying that happens below. inputBufferDesc.Usage = D3D11_USAGE_DYNAMIC; inputBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; inputBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; inputBufferDesc.StructureByteStride = sizeof(float); inputBufferDesc.ByteWidth = sizeof(float) * dimension; ID3D11Buffer* xBuffer = nullptr; hr = device->CreateBuffer(&inputBufferDesc, NULL, &xBuffer); if (FAILED(hr)) { printf("CreateBuffer failed for x buffer with return code %x\n", hr); return hr; } // We can re-use inputBufferDesc here because the layout and usage of the x // and y buffers is exactly the same. ID3D11Buffer* yBuffer = nullptr; hr = device->CreateBuffer(&inputBufferDesc, NULL, &yBuffer); if (FAILED(hr)) { printf("CreateBuffer failed for x buffer with return code %x\n", hr); return hr; } // Create shader resource views for the "x" and "y" buffers. // TODO: You can optionally provide a D3D11_SHADER_RESOURCE_VIEW_DESC // as the second parameter if you need to use only part of the buffer // inside the compute shader. ID3D11ShaderResourceView* xSRV = nullptr; hr = device->CreateShaderResourceView(xBuffer, NULL, &xSRV); if (FAILED(hr)) { printf("CreateShaderResourceView failed for x buffer with return code %x\n", hr); return hr; } ID3D11ShaderResourceView* ySRV = nullptr; hr = device->CreateShaderResourceView(yBuffer, NULL, &ySRV); if (FAILED(hr)) { printf("CreateShaderResourceView failed for y buffer with return code %x\n", hr); return hr; } // Create a structured buffer for the "z" vector. This buffer needs to be // writeable by the GPU, so we can't create it with CPU read/write access. D3D11_BUFFER_DESC outputBufferDesc; outputBufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; outputBufferDesc.Usage = D3D11_USAGE_DEFAULT; outputBufferDesc.CPUAccessFlags = 0; outputBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; outputBufferDesc.StructureByteStride = sizeof(float); outputBufferDesc.ByteWidth = sizeof(float) * dimension; ID3D11Buffer* zBuffer = nullptr; hr = device->CreateBuffer(&outputBufferDesc, NULL, &zBuffer); if (FAILED(hr)) { printf("CreateBuffer failed for z buffer with return code %x\n", hr); return hr; } // Create an unordered access view for the "z" vector. D3D11_UNORDERED_ACCESS_VIEW_DESC outputUAVDesc; outputUAVDesc.Buffer.FirstElement = 0; outputUAVDesc.Buffer.Flags = 0; outputUAVDesc.Buffer.NumElements = dimension; outputUAVDesc.Format = DXGI_FORMAT_UNKNOWN; outputUAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; ID3D11UnorderedAccessView* zBufferUAV; hr = device->CreateUnorderedAccessView(zBuffer, &outputUAVDesc, &zBufferUAV); if (FAILED(hr)) { printf("CreateUnorderedAccessView failed for z buffer with return code %x\n", hr); return hr; } // Create a staging buffer, which will be used to copy back from zBuffer. D3D11_BUFFER_DESC stagingBufferDesc; stagingBufferDesc.BindFlags = 0; stagingBufferDesc.Usage = D3D11_USAGE_STAGING; stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; stagingBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; stagingBufferDesc.StructureByteStride = sizeof(float); stagingBufferDesc.ByteWidth = sizeof(float) * dimension; ID3D11Buffer* stagingBuffer; hr = device->CreateBuffer(&stagingBufferDesc, NULL, &stagingBuffer); if (FAILED(hr)) { printf("CreateBuffer failed for staging buffer with return code %x\n", hr); return hr; } // Create a constant buffer (this buffer is used to pass the constant // value 'a' to the kernel as cbuffer Constants). D3D11_BUFFER_DESC cbDesc; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.Usage = D3D11_USAGE_DYNAMIC; cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbDesc.MiscFlags = 0; // Even though the constant buffer only has one float, DX expects // ByteWidth to be a multiple of 4 floats (i.e., one 128-bit register). cbDesc.ByteWidth = sizeof(float)*4; ID3D11Buffer* constantBuffer = nullptr; hr = device->CreateBuffer( &cbDesc, NULL, &constantBuffer); if (FAILED(hr)) { printf("CreateBuffer failed for constant buffer with return code %x\n", hr); return hr; } // Map the constant buffer and set the constant value 'a'. D3D11_MAPPED_SUBRESOURCE mappedResource; context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); float* constants = reinterpret_cast<float*>(mappedResource.pData); constants[0] = a; constants = nullptr; context->Unmap(constantBuffer, 0); // Map the x buffer and copy our data into it. context->Map(xBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); float* xvalues = reinterpret_cast<float*>(mappedResource.pData); memcpy(xvalues, &x[0], sizeof(float)*x.size()); xvalues = nullptr; context->Unmap(xBuffer, 0); // Map the y buffer and copy our data into it. context->Map(yBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); float* yvalues = reinterpret_cast<float*>(mappedResource.pData); memcpy(yvalues, &y[0], sizeof(float)*y.size()); yvalues = nullptr; context->Unmap(yBuffer, 0); // Compile the compute shader into a blob. ID3DBlob* errorBlob = nullptr; ID3DBlob* shaderBlob = nullptr; hr = D3DX11CompileFromFile(L"kernel.hlsl", NULL, NULL, "saxpy", "cs_4_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &shaderBlob, &errorBlob, NULL); if (FAILED(hr)) { // Print out the error message if there is one. if (errorBlob) { char const* message = (char*)errorBlob->GetBufferPointer(); printf("kernel.hlsl failed to compile; error message:\n"); printf("%s\n", message); errorBlob->Release(); } return hr; } // Create a shader object from the compiled blob. ID3D11ComputeShader* computeShader; hr = device->CreateComputeShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL, &computeShader); if (FAILED(hr)) { printf("CreateComputeShader failed with return code %x\n", hr); return hr; } // Make the shader active. context->CSSetShader(computeShader, NULL, 0); // Attach the z buffer to the output via its unordered access view. UINT initCounts = 0xFFFFFFFF; context->CSSetUnorderedAccessViews(0, 1, &zBufferUAV, &initCounts); // Attach the input buffers via their shader resource views. context->CSSetShaderResources(0, 1, &xSRV); context->CSSetShaderResources(1, 1, &ySRV); // Attach the constant buffer context->CSSetConstantBuffers(0, 1, &constantBuffer); // Execute the shader, in 'numGroups' groups of 'groupSize' threads each. context->Dispatch(numGroups, 1, 1); // Copy the z buffer to the staging buffer so that we can // retrieve the data for accesss by the CPU. context->CopyResource(stagingBuffer, zBuffer); // Map the staging buffer for reading. context->Map(stagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); float* zData = reinterpret_cast<float*>(mappedResource.pData); memcpy(&z[0], zData, sizeof(float)*z.size()); zData = nullptr; context->Unmap(stagingBuffer, 0); // Now compare the GPU results against expected values. bool resultOK = true; for (size_t i = 0; i < x.size(); ++ i) { // NOTE: This comparison assumes the GPU produces *exactly* the // same result as the CPU. In general, this will not be the case // with floating-point calculations. float const expected = a*x[i] + y[i]; if (z[i] != expected) { printf("Unexpected result at position %lu: expected %.7e, got %.7e\n", i, expected, z[i]); resultOK = false; } } if (!resultOK) { printf("GPU results differed from the CPU results.\n"); OutputDebugStringA("GPU results differed from the CPU results.\n"); return 1; } printf("GPU output matched the CPU results.\n"); OutputDebugStringA("GPU output matched the CPU results.\n"); // Disconnect everything from the pipeline. ID3D11UnorderedAccessView* nullUAV = nullptr; context->CSSetUnorderedAccessViews( 0, 1, &nullUAV, &initCounts); ID3D11ShaderResourceView* nullSRV = nullptr; context->CSSetShaderResources(0, 1, &nullSRV); context->CSSetShaderResources(1, 1, &nullSRV); ID3D11Buffer* nullBuffer = nullptr; context->CSSetConstantBuffers(0, 1, &nullBuffer); // Release resources. Again, note that none of the error checks above // release resources that have been allocated up to this point, so the // sample doesn't clean up after itself correctly unless everything succeeds. computeShader->Release(); shaderBlob->Release(); constantBuffer->Release(); stagingBuffer->Release(); zBufferUAV->Release(); zBuffer->Release(); xSRV->Release(); xBuffer->Release(); ySRV->Release(); yBuffer->Release(); context->Release(); device->Release(); return 0; }
//----------------------------------------------------------------------------- D3D11_MAPPED_SUBRESOURCE CPUTMeshDX11::Map( UINT count, ID3D11Buffer *pBuffer, D3D11_BUFFER_DESC &bufferDesc, ID3D11Buffer **pStagingBuffer, eCPUTMapType *pMappedType, CPUTRenderParameters ¶ms, eCPUTMapType type, bool wait ) { // Mapping for DISCARD requires dynamic buffer. Create dynamic copy? // Could easily provide input flag. But, where would we specify? Don't like specifying in the .set file // Because mapping is something the application wants to do - it isn't inherent in the data. // Could do Clone() and pass dynamic flag to that. // But, then we have two. Could always delete the other. // Could support programatic flag - apply to all loaded models in the .set // Could support programatic flag on model. Load model first, then load set. // For now, simply support CopyResource mechanism. HRESULT hr; ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTRenderParametersDX *pParamsDX11 = (CPUTRenderParametersDX*)¶ms; ID3D11DeviceContext *pContext = pParamsDX11->mpContext; if( !*pStagingBuffer ) { D3D11_BUFFER_DESC desc = bufferDesc; // First time. Create the staging resource desc.Usage = D3D11_USAGE_STAGING; switch( type ) { case CPUT_MAP_READ: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; break; case CPUT_MAP_READ_WRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; }; hr = pD3dDevice->CreateBuffer( &desc, NULL, pStagingBuffer ); ASSERT( SUCCEEDED(hr), _L("Failed to create staging buffer") ); CPUTSetDebugName( *pStagingBuffer, _L("Mesh Staging buffer") ); } else { ASSERT( *pMappedType == type, _L("Mapping with a different CPU access than creation parameter.") ); } D3D11_MAPPED_SUBRESOURCE info; switch( type ) { case CPUT_MAP_READ: case CPUT_MAP_READ_WRITE: // TODO: Copying and immediately mapping probably introduces a stall. // Expose the copy externally? // TODO: copy only if vb has changed? // Copy only first time? // Copy the GPU version before we read from it. pContext->CopyResource( *pStagingBuffer, pBuffer ); break; }; hr = pContext->Map( *pStagingBuffer, wait ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, (D3D11_MAP)type, 0, &info ); *pMappedType = type; return info; } // CPUTMeshDX11::Map()
bool CScreenshotSurface::capture() { #if defined(TARGET_RASPBERRY_PI) g_RBP.GetDisplaySize(m_width, m_height); m_buffer = g_RBP.CaptureDisplay(m_width, m_height, &m_stride, true, false); if (!m_buffer) return false; #elif defined(HAS_DX) g_graphicsContext.Lock(); if (g_application.m_pPlayer->IsPlayingVideo()) { #ifdef HAS_VIDEO_PLAYBACK g_renderManager.SetupScreenshot(); #endif } g_application.RenderNoPresent(); g_Windowing.FinishCommandList(); ID3D11DeviceContext* pImdContext = g_Windowing.GetImmediateContext(); ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context(); ID3D11Device* pDevice = g_Windowing.Get3D11Device(); ID3D11RenderTargetView* pRTView = nullptr; pContext->OMGetRenderTargets(1, &pRTView, nullptr); if (pRTView == nullptr) return false; ID3D11Resource *pRTResource = nullptr; pRTView->GetResource(&pRTResource); SAFE_RELEASE(pRTView); ID3D11Texture2D* pCopyTexture = nullptr; ID3D11Texture2D* pRTTexture = nullptr; HRESULT hr = pRTResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pRTTexture)); SAFE_RELEASE(pRTResource); if (FAILED(hr)) return false; D3D11_TEXTURE2D_DESC desc; pRTTexture->GetDesc(&desc); desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; if (SUCCEEDED(pDevice->CreateTexture2D(&desc, nullptr, &pCopyTexture))) { // take copy pImdContext->CopyResource(pCopyTexture, pRTTexture); D3D11_MAPPED_SUBRESOURCE res; if (SUCCEEDED(pImdContext->Map(pCopyTexture, 0, D3D11_MAP_READ, 0, &res))) { m_width = desc.Width; m_height = desc.Height; m_stride = res.RowPitch; m_buffer = new unsigned char[m_height * m_stride]; memcpy(m_buffer, res.pData, m_height * m_stride); pImdContext->Unmap(pCopyTexture, 0); } else CLog::Log(LOGERROR, "%s: MAP_READ failed.", __FUNCTION__); SAFE_RELEASE(pCopyTexture); } SAFE_RELEASE(pRTTexture); g_graphicsContext.Unlock(); #elif defined(HAS_GL) || defined(HAS_GLES) g_graphicsContext.BeginPaint(); if (g_application.m_pPlayer->IsPlayingVideo()) { #ifdef HAS_VIDEO_PLAYBACK g_renderManager.SetupScreenshot(); #endif } g_application.RenderNoPresent(); #ifndef HAS_GLES glReadBuffer(GL_BACK); #endif //get current viewport GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); m_width = viewport[2] - viewport[0]; m_height = viewport[3] - viewport[1]; m_stride = m_width * 4; unsigned char* surface = new unsigned char[m_stride * m_height]; //read pixels from the backbuffer #if HAS_GLES == 2 glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)surface); #else glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)surface); #endif g_graphicsContext.EndPaint(); //make a new buffer and copy the read image to it with the Y axis inverted m_buffer = new unsigned char[m_stride * m_height]; for (int y = 0; y < m_height; y++) { #ifdef HAS_GLES // we need to save in BGRA order so XOR Swap RGBA -> BGRA unsigned char* swap_pixels = surface + (m_height - y - 1) * m_stride; for (int x = 0; x < m_width; x++, swap_pixels+=4) { std::swap(swap_pixels[0], swap_pixels[2]); } #endif memcpy(m_buffer + y * m_stride, surface + (m_height - y - 1) *m_stride, m_stride); } delete [] surface; #if defined(HAS_LIBAMCODEC) // Captures the current visible videobuffer and blend it into m_buffer (captured overlay) CScreenshotAML::CaptureVideoFrame(m_buffer, m_width, m_height); #endif #ifdef HAS_IMXVPU // Captures the current visible framebuffer page and blends it into the // captured GL overlay g_IMXContext.CaptureDisplay(m_buffer, m_width, m_height); #endif #else //nothing to take a screenshot from return false; #endif return true; }
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(); } }
//=============================================================================================================================== bool TextureManager::loadTexture(BetterString filename, ID3D11Texture2D** texture, int& textureDataSize, byte*& srcTextureData, TextureType tt) { ID3D11Device* device = mD3DSystem->GetDevice11(); ID3D11DeviceContext* immediateContext = mD3DSystem->GetDeviceContext(); ID3D11Texture2D* tempTexture; //string file = "Textures\\"; //file += filename.toString(); HRESULT hr = E_FAIL; unique_ptr<wchar_t> name = filename.ToWideStr(); switch (tt) { case DDS: { hr = CreateDDSTextureFromFile(device, name.get(), (ID3D11Resource **)texture, NULL); } break; //case TGA: case PNG: { hr = CreateWICTextureFromFile(device, name.get(), (ID3D11Resource **)texture, NULL); } break; } //if(SUCCEEDED(D3DX11CreateTextureFromFile(device, file.c_str(), NULL, NULL, (ID3D11Resource **)texture, NULL))) if(SUCCEEDED(hr)) { // Load the texture and store it GetTexture(filename, tt); D3D11_TEXTURE2D_DESC desc; (*texture)->GetDesc(&desc); // To keep it simple, we limit the textures we load to RGBA 8bits per channel if(desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM) { OutputDebugStringA( "We want to read a simple RGBA texture 8 bits per channel but the required texture has a different format." ); return false; } desc.Usage = D3D11_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; if (device->CreateTexture2D(&desc, NULL, &tempTexture) != S_OK) return false; immediateContext->CopyResource(tempTexture, *texture); D3D11_MAPPED_SUBRESOURCE mappedResource; if (immediateContext->Map(tempTexture, 0, D3D11_MAP_READ, 0, &mappedResource) != S_OK) return false; textureDataSize = mappedResource.RowPitch * desc.Height; if(srcTextureData) delete [] srcTextureData; srcTextureData = new byte[textureDataSize]; memcpy(srcTextureData, mappedResource.pData, textureDataSize); immediateContext->Unmap(tempTexture, 0); return true; } else return false; }
// Detour function that replaces the IDXGISwapChain::Present() API DllExport HRESULT __stdcall hook_DXGISwapChainPresent( IDXGISwapChain * This, UINT SyncInterval, UINT Flags ) { static int frame_interval; static LARGE_INTEGER initialTv, captureTv, freq; static int capture_initialized = 0; // int i; struct pooldata *data; struct vsource_frame *frame; // DXGI_SWAP_CHAIN_DESC pDESC; HRESULT hr = pDXGISwapChainPresent(This, SyncInterval, Flags); if(resolution_retrieved == 0) { if(DXGI_get_resolution(This) >= 0) { resolution_retrieved = 1; } return hr; } if(vsource_initialized == 0) { ga_error("video source not initialized.\n"); return hr; } This->GetDesc(&pDESC); pDXGI_FORMAT = pDESC.BufferDesc.Format; // extract screen format for sws_scale if(pDESC.BufferDesc.Width != game_width || pDESC.BufferDesc.Height != game_height) { ga_error("game width/height mismatched (%dx%d) != (%dx%d)\n", pDESC.BufferDesc.Width, pDESC.BufferDesc.Height, game_width, game_height); return hr; } // if (enable_server_rate_control && ga_hook_video_rate_control() < 0) return hr; if (dx_version == dx_none) { //bool check_result = FALSE; if (check_dx_device_version(This, IID_ID3D10Device)) { dx_version = dx_10; ga_error("[DXGISwapChain] DirectX 10\n"); } else if (check_dx_device_version(This, IID_ID3D10Device1)) { dx_version = dx_10_1; ga_error("[DXGISwapChain] DirectX 10.1\n"); } else if (check_dx_device_version(This, IID_ID3D11Device)) { dx_version = dx_11; ga_error("[DXGISwapChain] DirectX 11\n"); } } if (capture_initialized == 0) { frame_interval = 1000000/video_fps; // in the unif of us frame_interval++; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&initialTv); capture_initialized = 1; } else { QueryPerformanceCounter(&captureTv); } hr = 0; // d3d10 / d3d10.1 if (dx_version == dx_10 || dx_version == dx_10_1) { void *ppDevice; ID3D10Device *pDevice; //IUnknown *pDevice; if (dx_version == dx_10) { This->GetDevice(IID_ID3D10Device, &ppDevice); pDevice = (ID3D10Device *)ppDevice; } else if (dx_version == dx_10_1) { This->GetDevice(IID_ID3D10Device1, &ppDevice); pDevice = (ID3D10Device1 *)ppDevice; } else { OutputDebugString("Invalid DirectX version in IDXGISwapChain::Present"); return hr; } ID3D10RenderTargetView *pRTV = NULL; ID3D10Resource *pSrcResource = NULL; pDevice->OMGetRenderTargets(1, &pRTV, NULL); pRTV->GetResource(&pSrcResource); ID3D10Texture2D* pSrcBuffer = (ID3D10Texture2D *)pSrcResource; ID3D10Texture2D* pDstBuffer = NULL; D3D10_TEXTURE2D_DESC desc; pSrcBuffer->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; desc.Usage = D3D10_USAGE_STAGING; hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer); if (FAILED(hr)) { OutputDebugString("Failed to create texture2D"); //assert(exp_state == exp_none); } pDevice->CopyResource(pDstBuffer, pSrcBuffer); D3D10_MAPPED_TEXTURE2D mapped_screen; hr = pDstBuffer->Map(0, D3D10_MAP_READ, 0, &mapped_screen); if (FAILED(hr)) { OutputDebugString("Failed to map from DstBuffer"); //assert(exp_state == exp_none); } // copy image do { unsigned char *src, *dst; data = g_pipe[0]->allocate_data(); frame = (struct vsource_frame*) data->ptr; frame->pixelformat = PIX_FMT_BGRA; frame->realwidth = desc.Width; frame->realheight = desc.Height; frame->realstride = desc.Width<<2; frame->realsize = frame->realwidth * frame->realstride; frame->linesize[0] = frame->realstride;//frame->stride; // src = (unsigned char*) mapped_screen.pData; dst = (unsigned char*) frame->imgbuf; for (i = 0; i < encoder_height; i++) { CopyMemory(dst, src, frame->realstride/*frame->stride*/); src += mapped_screen.RowPitch; dst += frame->realstride;//frame->stride; } frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval; } while(0); // duplicate from channel 0 to other channels for(i = 1; i < SOURCES; i++) { int j; struct pooldata *dupdata; struct vsource_frame *dupframe; dupdata = g_pipe[i]->allocate_data(); dupframe = (struct vsource_frame*) dupdata->ptr; // vsource_dup_frame(frame, dupframe); // g_pipe[i]->store_data(dupdata); g_pipe[i]->notify_all(); } g_pipe[0]->store_data(data); g_pipe[0]->notify_all(); pDstBuffer->Unmap(0); pDevice->Release(); pSrcResource->Release(); pSrcBuffer->Release(); pRTV->Release(); pDstBuffer->Release(); // d11 } else if (dx_version == dx_11) { void *ppDevice; This->GetDevice(IID_ID3D11Device, &ppDevice); ID3D11Device *pDevice = (ID3D11Device*) ppDevice; This->GetDevice(IID_ID3D11DeviceContext, &ppDevice); ID3D11DeviceContext *pDeviceContext = (ID3D11DeviceContext *) ppDevice; ID3D11RenderTargetView *pRTV = NULL; ID3D11Resource *pSrcResource = NULL; pDeviceContext->OMGetRenderTargets(1, &pRTV, NULL); pRTV->GetResource(&pSrcResource); ID3D11Texture2D *pSrcBuffer = (ID3D11Texture2D *)pSrcResource; ID3D11Texture2D *pDstBuffer = NULL; D3D11_TEXTURE2D_DESC desc; pSrcBuffer->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.Usage = D3D11_USAGE_STAGING; hr = pDevice->CreateTexture2D(&desc, NULL, &pDstBuffer); if (FAILED(hr)) { OutputDebugString("Failed to create buffer"); //assert(exp_state == exp_none); } pDeviceContext->CopyResource(pDstBuffer, pSrcBuffer); D3D11_MAPPED_SUBRESOURCE mapped_screen; hr = pDeviceContext->Map(pDstBuffer, 0, D3D11_MAP_READ, 0, &mapped_screen); if (FAILED(hr)) { OutputDebugString("Failed to map from DeviceContext"); //assert(exp_state == exp_none); } // copy image do { unsigned char *src, *dst; data = g_pipe[0]->allocate_data(); frame = (struct vsource_frame*) data->ptr; frame->pixelformat = PIX_FMT_BGRA; frame->realwidth = desc.Width; frame->realheight = desc.Height; frame->realstride = desc.Width<<2; frame->realsize = frame->realwidth * frame->realstride; frame->linesize[0] = frame->realstride;//frame->stride; // src = (unsigned char*) mapped_screen.pData; dst = (unsigned char*) frame->imgbuf; for (i = 0; i < encoder_height; i++) { CopyMemory(dst, src, frame->realstride/*frame->stride*/); src += mapped_screen.RowPitch; dst += frame->realstride;//frame->stride; } frame->imgpts = pcdiff_us(captureTv, initialTv, freq)/frame_interval; } while(0); // duplicate from channel 0 to other channels for(i = 1; i < SOURCES; i++) { int j; struct pooldata *dupdata; struct vsource_frame *dupframe; dupdata = g_pipe[i]->allocate_data(); dupframe = (struct vsource_frame*) dupdata->ptr; // vsource_dup_frame(frame, dupframe); // g_pipe[i]->store_data(dupdata); g_pipe[i]->notify_all(); } g_pipe[0]->store_data(data); g_pipe[0]->notify_all(); pDeviceContext->Unmap(pDstBuffer, 0); pDevice->Release(); pDeviceContext->Release(); pSrcResource->Release(); pSrcBuffer->Release(); pRTV->Release(); pDstBuffer->Release(); } return hr; }
//----------------------------------------------------------------------------- D3D11_MAPPED_SUBRESOURCE CPUTRenderTargetDepth::MapRenderTarget( CPUTRenderParameters ¶ms, eCPUTMapType type, bool wait ) { // Mapping for DISCARD requires dynamic buffer. Create dynamic copy? // Could easily provide input flag. But, where would we specify? Don't like specifying in the .set file // Because mapping is something the application wants to do - it isn't inherent in the data. // Could do Clone() and pass dynamic flag to that. // But, then we have two. Could always delete the other. // Could support programatic flag - apply to all loaded models in the .set // Could support programatic flag on model. Load model first, then load set. // For now, simply support CopyResource mechanism. HRESULT hr; ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); ID3D11DeviceContext *pContext = CPUT_DX11::GetContext(); if( !mpDepthTextureDXStaging ) { CD3D11_TEXTURE2D_DESC desc = mDepthDesc; // First time. Create the staging resource desc.Usage = D3D11_USAGE_STAGING; switch( type ) { case CPUT_MAP_READ: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; break; case CPUT_MAP_READ_WRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; case CPUT_MAP_WRITE: case CPUT_MAP_WRITE_DISCARD: case CPUT_MAP_NO_OVERWRITE: desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.BindFlags = 0; break; }; HRESULT hr = pD3dDevice->CreateTexture2D( &desc, NULL, &mpDepthTextureDXStaging ); ASSERT( SUCCEEDED(hr), "Failed to create staging texture" ); CPUTSetDebugName( mpDepthTextureDXStaging, "Staging buffer" ); UNREFERENCED_PARAMETER(hr); } else { ASSERT( mMappedType == type, "Mapping with a different CPU access than creation parameter." ); } D3D11_MAPPED_SUBRESOURCE info; switch( type ) { case CPUT_MAP_READ: case CPUT_MAP_READ_WRITE: // TODO: Copying and immediately mapping probably introduces a stall. // Expose the copy externally? // TODO: copy only if vb has changed? // Copy only first time? // Copy the GPU version before we read from it. // pContext->CopyResource( mpDepthTextureDXStaging, (mMultiSampleCount>1) ? mpDepthTextureDXMSAA : mpDepthTextureDX); // TODO: Do we (can we) support MSAA depth pContext->CopyResource( mpDepthTextureDXStaging, mpDepthTextureDX ); break; }; hr = pContext->Map( mpDepthTextureDXStaging, wait ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, (D3D11_MAP)type, 0, &info ); mMappedType = type; return info; } // CPUTRenderTargetDepth::Map()
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; }
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; }