bool D3D11GeometryBuffer::AllocVertexBuffer(unsigned int bytes, bool dynamic) { D3D11_BUFFER_DESC desc; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.ByteWidth = bytes; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; desc.StructureByteStride = 0; desc.Usage = dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; ID3D11Device* pDevice = NULL; m_pContext->GetDevice(&pDevice); HRESULT ret = pDevice->CreateBuffer(&desc, NULL, &m_pVertexBuffer); if(FAILED(ret)) { pDevice->Release(); return false; } pDevice->Release(); return true; }
bool D3D11RenderData::AllocVertexBuffer(unsigned int bytes, void* pInitData, bool dynamic) { D3D11_BUFFER_DESC desc; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.ByteWidth = bytes; desc.CPUAccessFlags = dynamic ? D3D11_CPU_ACCESS_WRITE : 0; desc.MiscFlags = 0; desc.StructureByteStride = 0; desc.Usage = dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; ID3D11Device* pDevice = NULL; m_pContext->GetDevice(&pDevice); D3D11_SUBRESOURCE_DATA InitData = {pInitData, 0, 0,}; HRESULT ret = pDevice->CreateBuffer(&desc, pInitData == NULL ? NULL : &InitData, &m_pVertexBuffer); if(FAILED(ret)) { pDevice->Release(); return false; } pDevice->Release(); return true; }
bool D3D11RenderData::AllocIndexBuffer(unsigned int bytes, void* pInitData, bool dynamic) { // Fill in a buffer description. D3D11_BUFFER_DESC bufferDesc; bufferDesc.Usage = dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; bufferDesc.ByteWidth = bytes; bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; bufferDesc.CPUAccessFlags = dynamic ? D3D11_CPU_ACCESS_WRITE : 0; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; ID3D11Device* pDevice = NULL; m_pContext->GetDevice(&pDevice); D3D11_SUBRESOURCE_DATA InitData = {pInitData, 0, 0,}; if(FAILED(pDevice->CreateBuffer(&bufferDesc, pInitData == NULL ? NULL :&InitData, &m_pIndexBuffer))) { pDevice->Release(); return false; } pDevice->Release(); return true; }
bool D3D11GeometryBuffer::AllocIndexBuffer(unsigned int bytes, bool dynamic) { // Fill in a buffer description. D3D11_BUFFER_DESC bufferDesc; bufferDesc.Usage = dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; bufferDesc.ByteWidth = bytes; bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; ID3D11Device* pDevice = NULL; m_pContext->GetDevice(&pDevice); if(FAILED(pDevice->CreateBuffer(&bufferDesc, NULL, &m_pIndexBuffer))) { pDevice->Release(); return false; } pDevice->Release(); return true; }
bool D3D11DepthStencilBuffer::Create(int w, int h, G_FORMAT format) { D3D11_TEXTURE2D_DESC td; ZeroMemory(&td, sizeof(td)); td.ArraySize = 1; td.BindFlags = D3D11_BIND_DEPTH_STENCIL; td.CPUAccessFlags = 0; td.Format = D3D11Format::Convert(format); td.Width = w; td.Height = h; td.MipLevels = 1; td.ArraySize = 1; td.MiscFlags = 0; td.SampleDesc.Count = 1; td.SampleDesc.Quality = 0; td.Usage = D3D11_USAGE_DEFAULT; ID3D11Device* pDevice = NULL; m_pContext->GetDevice(&pDevice); if(FAILED(pDevice->CreateTexture2D(&td, NULL, &m_pBuffer))) { pDevice->Release(); return DepthStencilBufferPtr(); } D3D11_DEPTH_STENCIL_VIEW_DESC d; ZeroMemory(&d, sizeof(d)); d.Format = D3D11Format::Convert(format); d.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; d.Flags = 0; d.Texture2D.MipSlice = 0; if(FAILED(pDevice->CreateDepthStencilView( m_pBuffer, &d, &m_pDepthStencilView))) { pDevice->Release(); return false; } pDevice->Release(); return true; }
void DX11::Shader::UpdateConstantBuffer(ID3D11DeviceContext * context, std::vector<float> & constants, ID3D11Buffer ** buffer) { while((constants.size() % 4) != 0) { constants.push_back(0.0f); } if(*buffer) { context->UpdateSubresource(*buffer, 0, 0, constants.data(), 0, 0); } else { ID3D11Device * device = 0; context->GetDevice(&device); if(device) { D3D11_SUBRESOURCE_DATA data = { 0 }; data.pSysMem = constants.data(); device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(float) * constants.size(), D3D11_BIND_CONSTANT_BUFFER), &data, buffer); device->Release(); } } }
//---------------------------------------------------------------------------- void DX11GeometryShader::DisableUAView(ID3D11DeviceContext* context, unsigned int bindPoint) { if (mDXObject) { ID3D11Device* device = nullptr; context->GetDevice(&device); if (!device) { LogError("Cannot access device of context."); return; } if (device->GetFeatureLevel() == D3D_FEATURE_LEVEL_11_1) { ID3D11UnorderedAccessView* uaViews[1] = { nullptr }; unsigned int initialCounts[1] = { 0xFFFFFFFFu }; context->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, bindPoint, 1, uaViews, initialCounts); } else { LogError("D3D11.1 is required for UAVs in geometry shaders."); } device->Release(); } }
static bool grabFrameD3D11(IDXGISwapChain *swap) { ID3D11Device *device = 0; ID3D11DeviceContext *context = 0; ID3D11Texture2D *tex = 0, *captureTex = 0; if (FAILED(swap->GetBuffer(0, IID_ID3D11Texture2D, (void**)&tex))) return false; D3D11_TEXTURE2D_DESC desc; tex->GetDevice(&device); tex->GetDesc(&desc); // re-creating the capture staging texture each frame is definitely not the most efficient // way to handle things, but it frees me of all kind of resource management trouble, so // here goes... desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.MiscFlags = 0; if(FAILED(device->CreateTexture2D(&desc,0,&captureTex))) printLog("video/d3d11: couldn't create staging texture for gpu->cpu download!\n"); else setCaptureResolution(desc.Width,desc.Height); device->GetImmediateContext(&context); context->CopySubresourceRegion(captureTex,0,0,0,0,tex,0,0); D3D11_MAPPED_SUBRESOURCE mapped; bool grabOk = false; if(captureTex && SUCCEEDED(context->Map(captureTex,0,D3D11_MAP_READ,0,&mapped))) { switch(desc.Format) { case DXGI_FORMAT_R8G8B8A8_UNORM: blitAndFlipRGBAToCaptureData((unsigned char *) mapped.pData,mapped.RowPitch); grabOk = true; break; default: printLog("video/d3d11: unsupported backbuffer format, can't grab pixels!\n"); break; } context->Unmap(captureTex,0); } tex->Release(); if(captureTex) captureTex->Release(); context->Release(); device->Release(); return grabOk; }
// Save all states that are changed by the font-wrapper when drawing a string HRESULT CFW1StateSaver::saveCurrentState(ID3D11DeviceContext *pContext) { if(m_savedState) releaseSavedState(); if(pContext == NULL) return E_INVALIDARG; ID3D11Device *pDevice; pContext->GetDevice(&pDevice); if(pDevice != NULL) { m_featureLevel = pDevice->GetFeatureLevel(); pDevice->Release(); } pContext->AddRef(); m_pContext = pContext; m_pContext->IAGetPrimitiveTopology(&m_primitiveTopology); m_pContext->IAGetInputLayout(&m_pInputLayout); m_pContext->OMGetBlendState(&m_pBlendState, m_blendFactor, &m_sampleMask); m_pContext->OMGetDepthStencilState(&m_pDepthStencilState, &m_stencilRef); m_pContext->RSGetState(&m_pRasterizerState); m_numVSClassInstances = 256; m_pContext->VSGetShader(&m_pVS, m_pVSClassInstances, &m_numVSClassInstances); m_pContext->VSGetConstantBuffers(0, 1, &m_pVSConstantBuffer); m_numPSClassInstances = 256; m_pContext->PSGetShader(&m_pPS, m_pPSClassInstances, &m_numPSClassInstances); m_pContext->PSGetShaderResources(0, 1, &m_pPSSRV); pContext->PSGetSamplers(0, 1, &m_pSamplerState); if(m_featureLevel >= D3D_FEATURE_LEVEL_10_0) { m_numGSClassInstances = 256; m_pContext->GSGetShader(&m_pGS, m_pGSClassInstances, &m_numGSClassInstances); m_pContext->GSGetConstantBuffers(0, 1, &m_pGSConstantBuffer); m_pContext->GSGetShaderResources(0, 1, &m_pGSSRV); if(m_featureLevel >= D3D_FEATURE_LEVEL_11_0) { m_numHSClassInstances = 256; m_pContext->HSGetShader(&m_pHS, m_pHSClassInstances, &m_numHSClassInstances); m_numDSClassInstances = 256; m_pContext->DSGetShader(&m_pDS, m_pDSClassInstances, &m_numDSClassInstances); } } m_pContext->IAGetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); m_pContext->IAGetIndexBuffer(&m_pIndexBuffer, &m_indexFormat, &m_indexOffset); m_savedState = true; return S_OK; }
DeviceD3D::~DeviceD3D() { #if defined(ANGLE_ENABLE_D3D11) if (mIsInitialized && mDeviceType == EGL_D3D11_DEVICE_ANGLE) { // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it. ID3D11Device *device = static_cast<ID3D11Device *>(mDevice); device->Release(); } #endif }
// D3D11 specific logic for the Present function. extern void presentD3D11(IDXGISwapChain *pSwapChain) { ID3D11Device *pDevice = NULL; HRESULT hr = pSwapChain->GetDevice(__uuidof(ID3D11Device), (void **) &pDevice); if (SUCCEEDED(hr) && pDevice) { SwapchainMap::iterator it = chains.find(pSwapChain); D11State *ds = it != chains.end() ? it->second : NULL; if (ds && ds->pDevice != pDevice) { ods("D3D11: SwapChain device changed"); devices.erase(ds->pDevice); delete ds; ds = NULL; } if (ds == NULL) { ods("D3D11: New state"); ds = new D11State(pSwapChain, pDevice); if (!ds->init()) { pDevice->Release(); delete ds; return; } chains[pSwapChain] = ds; devices[pDevice] = ds; } ds->draw(); pDevice->Release(); } else { #ifdef EXTENDED_OVERLAY_DEBUGOUTPUT // DXGI is used for multiple D3D versions. Thus, this is expected if // another version is used (like D3D10). ods("D3D11: Could not draw because ID3D11Device could not be retrieved."); #endif } }
//! driver initialization void DirectX11Driver::Init() { super::Init(); UINT creationFlags = 0; #if defined(_DEBUG) creationFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevels[] = { //D3D_FEATURE_LEVEL_11_1, //D3D_FEATURE_LEVEL_11_0, //D3D_FEATURE_LEVEL_10_1, //D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3 // max compatibility with Windows Phone 8 }; ID3D11Device* pDevice = NULL; ID3D11DeviceContext* pContext = NULL; DX_ASSERT(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &pDevice, &m_FeatureLevel, &pContext)); ID3D11Device1* pDevice1 = NULL; ID3D11DeviceContext1* pContext1 = NULL; DX_ASSERT(pDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&pDevice1)); DX_ASSERT(pContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void**)&pContext1)); m_Device = pDevice1; m_ImmediateContext = pContext1; pDevice->Release(); pContext->Release(); #if SHOOT_PLATFORM != SHOOT_PLATFORM_WP8 if(!m_RenderTargetView.Get()) { ResizeScreen(Size(int(m_ViewPortArea.Size().X), int(m_ViewPortArea.Size().Y))); } #endif }
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter) { std::vector<DXGI_SAMPLE_DESC> aa_modes; // NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND shader resources. // Thus, we can't have MSAA with 10.0 level hardware. ID3D11Device* device; ID3D11DeviceContext* context; D3D_FEATURE_LEVEL feat_level; HRESULT hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &device, &feat_level, &context); if (FAILED(hr) || feat_level == D3D_FEATURE_LEVEL_10_0) { DXGI_SAMPLE_DESC desc; desc.Count = 1; desc.Quality = 0; aa_modes.push_back(desc); SAFE_RELEASE(context); SAFE_RELEASE(device); } else { for (int samples = 0; samples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples) { UINT quality_levels = 0; device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples, &quality_levels); if (quality_levels > 0) { DXGI_SAMPLE_DESC desc; desc.Count = samples; for (desc.Quality = 0; desc.Quality < quality_levels; ++desc.Quality) aa_modes.push_back(desc); } } context->Release(); device->Release(); } return aa_modes; }
void Edo::GetD3D11DeviceAndSwapchainVTable(HWND window, uintptr_t** ppDeviceVTable, uintptr_t** ppContextVTable, uintptr_t** ppSwapchainVTable) { ID3D11Device* pDevice; ID3D11DeviceContext* pContext; IDXGISwapChain* pSwapchain; //Create dummy devices. CreateD3D11DummyDeviceAndSwapchain(window, &pDevice, &pContext, &pSwapchain); //Set the vtable pointers if(ppDeviceVTable) *ppDeviceVTable = (uintptr_t*)*(uintptr_t*)pDevice; if(ppContextVTable) *ppContextVTable = (uintptr_t*)*(uintptr_t*)pContext; if(ppSwapchainVTable) *ppSwapchainVTable = (uintptr_t*)*(uintptr_t*)pSwapchain; //Cleanup. pDevice->Release(); pContext->Release(); pSwapchain->Release(); }
// 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; }
//-------------------------------------------------------------------------------------- // Enumerate for each adapter all of the supported display modes, // device types, adapter formats, back buffer formats, window/full screen support, // depth stencil formats, multisampling types/qualities, and presentations intervals. // // For each combination of device type (HAL/REF), adapter format, back buffer format, and // IsWindowed it will call the app's ConfirmDevice callback. This allows the app // to reject or allow that combination based on its caps/etc. It also allows the // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP // if supported otherwise it will default to SWVP, however the app can change this // through the ConfirmDevice callback. //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc, void* pIsD3D11DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" ); HRESULT hr; IDXGIFactory1* pFactory = DXUTGetDXGIFactory(); if( !pFactory ) return E_FAIL; m_bHasEnumerated = true; m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc; m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext; ClearAdapterInfoList(); for( int index = 0; ; ++index ) { IDXGIAdapter* pAdapter = nullptr; hr = pFactory->EnumAdapters( index, &pAdapter ); if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit break; IDXGIAdapter2* pAdapter2 = nullptr; if ( SUCCEEDED( pAdapter->QueryInterface( __uuidof(IDXGIAdapter2), ( LPVOID* )&pAdapter2 ) ) ) { // Succeeds on DirectX 11.1 Runtime systems DXGI_ADAPTER_DESC2 desc; hr = pAdapter2->GetDesc2( &desc ); pAdapter2->Release(); if ( SUCCEEDED(hr) && ( desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE ) ) { // Skip "always there" Microsoft Basics Display Driver pAdapter->Release(); continue; } } CD3D11EnumAdapterInfo* pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { SAFE_RELEASE( pAdapter ); return E_OUTOFMEMORY; } pAdapterInfo->AdapterOrdinal = index; pAdapter->GetDesc( &pAdapterInfo->AdapterDesc ); pAdapterInfo->m_pAdapter = pAdapter; // Enumerate the device driver types on the adapter. hr = EnumerateDevices( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; continue; } hr = EnumerateOutputs( pAdapterInfo ); if( FAILED( hr ) || pAdapterInfo->outputInfoList.empty() ) { delete pAdapterInfo; continue; } // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo ) ) ) { delete pAdapterInfo; continue; } m_AdapterInfoList.push_back( pAdapterInfo ); } // If we did not get an adapter then we should still enumerate WARP and Ref. if (m_AdapterInfoList.size() == 0) { CD3D11EnumAdapterInfo* pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { return E_OUTOFMEMORY; } pAdapterInfo->bAdapterUnavailable = true; hr = EnumerateDevices( pAdapterInfo ); // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) ) { delete pAdapterInfo; } if (SUCCEEDED(hr)) m_AdapterInfoList.push_back( pAdapterInfo ); } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; for( size_t i = 0; i < m_AdapterInfoList.size(); i++ ) { auto pAdapterInfo1 = m_AdapterInfoList[ i ]; for( size_t j = i + 1; j < m_AdapterInfoList.size(); j++ ) { auto pAdapterInfo2 = m_AdapterInfoList[ j ]; if( wcsncmp( pAdapterInfo1->AdapterDesc.Description, pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( auto it = m_AdapterInfoList.begin(); it != m_AdapterInfoList.end(); ++it ) { wcscpy_s( (*it)->szUniqueDescription, 100, (*it)->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; swprintf_s( sz, 100, L" (#%u)", (*it)->AdapterOrdinal ); wcscat_s( (*it)->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); } } D3D_FEATURE_LEVEL fLvl[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 }; // Check WARP max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, fLvl, _countof(fLvl), D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 runtime will not recognize FL 11.1, so try without it hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_warpFL = D3D_FEATURE_LEVEL_10_1; } // Check REF max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, fLvl, _countof(fLvl), D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 runtime will not recognize FL 11.1, so try without it hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_refFL = D3D_FEATURE_LEVEL_11_0; } return S_OK; }
int main(int argc, char* argv[]) { // Parse the command line int realParams = 0; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { Usage(argv[0]); } else switch (++realParams) { case 1: default: Usage(argv[0]); } } if (realParams != 0) { Usage(argv[0]); } // Get an OSVR client context to use to access the devices // that we need. osvr::clientkit::ClientContext context( "org.opengoggles.exampleclients.TrackerCallback"); // Construct button devices and connect them to a callback // that will set the "quit" variable to true when it is // pressed. Use button "1" on the left-hand or // right-hand controller. osvr::clientkit::Interface leftButton1 = context.getInterface("/controller/left/1"); leftButton1.registerCallback(&myButtonCallback, &quit); osvr::clientkit::Interface rightButton1 = context.getInterface("/controller/right/1"); rightButton1.registerCallback(&myButtonCallback, &quit); // Create a D3D11 device and context to be used, rather than // having RenderManager make one for us. This is an example // of using an external one, which would be needed for clients // that already have a rendering pipeline, like Unity. ID3D11Device* myDevice = nullptr; // Fill this in ID3D11DeviceContext* myContext = nullptr; // Fill this in. // Here, we open the device and context ourselves, but if you // are working with a render library that provides them for you, // just stick them into the values rather than constructing // them. (This is a bit of a toy example, because we could // just let RenderManager do this work for us and use the library // it sends back. However, it does let us set parameters on the // device and context construction the way that we want, so it // might be useful. Be sure to get D3D11 and have set // D3D11_CREATE_DEVICE_BGRA_SUPPORT in the device/context // creation, however it is done). D3D_FEATURE_LEVEL acceptibleAPI = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL foundAPI; auto hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, &acceptibleAPI, 1, D3D11_SDK_VERSION, &myDevice, &foundAPI, &myContext); if (FAILED(hr)) { std::cerr << "Could not create D3D11 device and context" << std::endl; return -1; } // Put the device and context into a structure to let RenderManager // know to use this one rather than creating its own. osvr::renderkit::GraphicsLibrary library; library.D3D11 = new osvr::renderkit::GraphicsLibraryD3D11; library.D3D11->device = myDevice; library.D3D11->context = myContext; // Open Direct3D and set up the context for rendering to // an HMD. Do this using the OSVR RenderManager interface, // which maps to the nVidia or other vendor direct mode // to reduce the latency. osvr::renderkit::RenderManager* render = osvr::renderkit::createRenderManager(context.get(), "Direct3D11", library); if ((render == nullptr) || (!render->doingOkay())) { std::cerr << "Could not create RenderManager" << std::endl; return 1; } // Set up a handler to cause us to exit cleanly. #ifdef _WIN32 SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); #endif // Open the display and make sure this worked. osvr::renderkit::RenderManager::OpenResults ret = render->OpenDisplay(); if (ret.status == osvr::renderkit::RenderManager::OpenStatus::FAILURE) { std::cerr << "Could not open display" << std::endl; return 2; } if (ret.library.D3D11 == nullptr) { std::cerr << "Attempted to run a Direct3D11 program with a config file " << "that specified a different rendering library." << std::endl; return 3; } // Do a call to get the information we need to construct our // color and depth render-to-texture buffers. std::vector<osvr::renderkit::RenderInfo> renderInfo; context.update(); renderInfo = render->GetRenderInfo(); // Set up the vector of textures to render to and any framebuffer // we need to group them. std::vector<osvr::renderkit::RenderBuffer> renderBuffers; std::vector<ID3D11Texture2D*> depthStencilTextures; std::vector<ID3D11DepthStencilView*> depthStencilViews; for (size_t i = 0; i < renderInfo.size(); i++) { // The color buffer for this eye. We need to put this into // a generic structure for the Present function, but we only need // to fill in the Direct3D portion. // Note that this texture format must be RGBA and unsigned byte, // so that we can present it to Direct3D for DirectMode. ID3D11Texture2D* D3DTexture = nullptr; unsigned width = static_cast<int>(renderInfo[i].viewport.width); unsigned height = static_cast<int>(renderInfo[i].viewport.height); // Initialize a new render target texture description. D3D11_TEXTURE2D_DESC textureDesc = {}; textureDesc.Width = width; textureDesc.Height = height; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; // textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; // We need it to be both a render target and a shader resource textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; // Create a new render target texture to use. hr = renderInfo[i].library.D3D11->device->CreateTexture2D( &textureDesc, NULL, &D3DTexture); if (FAILED(hr)) { std::cerr << "Can't create texture for eye " << i << std::endl; return -1; } // Fill in the resource view for your render texture buffer here D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc = {}; // This must match what was created in the texture to be rendered renderTargetViewDesc.Format = textureDesc.Format; renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; renderTargetViewDesc.Texture2D.MipSlice = 0; // Create the render target view. ID3D11RenderTargetView* renderTargetView; //< Pointer to our render target view hr = renderInfo[i].library.D3D11->device->CreateRenderTargetView( D3DTexture, &renderTargetViewDesc, &renderTargetView); if (FAILED(hr)) { std::cerr << "Could not create render target for eye " << i << std::endl; return -2; } // Push the filled-in RenderBuffer onto the stack. osvr::renderkit::RenderBufferD3D11* rbD3D = new osvr::renderkit::RenderBufferD3D11; rbD3D->colorBuffer = D3DTexture; rbD3D->colorBufferView = renderTargetView; osvr::renderkit::RenderBuffer rb; rb.D3D11 = rbD3D; renderBuffers.push_back(rb); //================================================================== // Create a depth buffer // Make the depth/stencil texture. D3D11_TEXTURE2D_DESC textureDescription = {}; textureDescription.SampleDesc.Count = 1; textureDescription.SampleDesc.Quality = 0; textureDescription.Usage = D3D11_USAGE_DEFAULT; textureDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL; textureDescription.Width = width; textureDescription.Height = height; textureDescription.MipLevels = 1; textureDescription.ArraySize = 1; textureDescription.CPUAccessFlags = 0; textureDescription.MiscFlags = 0; /// @todo Make this a parameter textureDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; ID3D11Texture2D* depthStencilBuffer; hr = renderInfo[i].library.D3D11->device->CreateTexture2D( &textureDescription, NULL, &depthStencilBuffer); if (FAILED(hr)) { std::cerr << "Could not create depth/stencil texture for eye " << i << std::endl; return -4; } depthStencilTextures.push_back(depthStencilBuffer); // Create the depth/stencil view description D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDescription = {}; depthStencilViewDescription.Format = textureDescription.Format; depthStencilViewDescription.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDescription.Texture2D.MipSlice = 0; ID3D11DepthStencilView* depthStencilView; hr = renderInfo[i].library.D3D11->device->CreateDepthStencilView( depthStencilBuffer, &depthStencilViewDescription, &depthStencilView); if (FAILED(hr)) { std::cerr << "Could not create depth/stencil view for eye " << i << std::endl; return -5; } depthStencilViews.push_back(depthStencilView); } // Create depth stencil state. // Describe how depth and stencil tests should be performed. D3D11_DEPTH_STENCIL_DESC depthStencilDescription = {}; depthStencilDescription.DepthEnable = true; depthStencilDescription.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDescription.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDescription.StencilEnable = true; depthStencilDescription.StencilReadMask = 0xFF; depthStencilDescription.StencilWriteMask = 0xFF; // Front-facing stencil operations depthStencilDescription.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDescription.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDescription.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDescription.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Back-facing stencil operations depthStencilDescription.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDescription.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDescription.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDescription.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; ID3D11DepthStencilState* depthStencilState; hr = renderInfo[0].library.D3D11->device->CreateDepthStencilState( &depthStencilDescription, &depthStencilState); if (FAILED(hr)) { std::cerr << "Could not create depth/stencil state" << std::endl; return -3; } // Register our constructed buffers so that we can use them for // presentation. if (!render->RegisterRenderBuffers(renderBuffers)) { std::cerr << "RegisterRenderBuffers() returned false, cannot continue" << std::endl; quit = true; } // Continue rendering until it is time to quit. while (!quit) { // Update the context so we get our callbacks called and // update tracker state. context.update(); renderInfo = render->GetRenderInfo(); // Render into each buffer using the specified information. for (size_t i = 0; i < renderInfo.size(); i++) { renderInfo[i].library.D3D11->context->OMSetDepthStencilState( depthStencilState, 1); RenderView(renderInfo[i], renderBuffers[i].D3D11->colorBufferView, depthStencilViews[i]); } // Send the rendered results to the screen if (!render->PresentRenderBuffers(renderBuffers, renderInfo)) { std::cerr << "PresentRenderBuffers() returned false, maybe because " "it was asked to quit" << std::endl; quit = true; } } // Close the Renderer interface cleanly. delete render; // Clean up after ourselves. myContext->Release(); myDevice->Release(); return 0; }
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; }
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(); }
void BBWin8Game::CreateD3dDevice(){ CoreWindow ^window=CoreWindow::GetForCurrentThread(); int width=DipsToPixels( window->Bounds.Width ); int height=DipsToPixels( window->Bounds.Height ); #if WINDOWS_8 switch( DisplayProperties::CurrentOrientation ){ case DisplayOrientations::Portrait: case DisplayOrientations::PortraitFlipped: std::swap( width,height ); break; } #endif UINT creationFlags=D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifdef _DEBUG creationFlags|=D3D11_CREATE_DEVICE_DEBUG; #endif #if WINDOWS_8 D3D_FEATURE_LEVEL featureLevels[]={ D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; #elif WINDOWS_PHONE_8 D3D_FEATURE_LEVEL featureLevels[]={ D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3 }; #endif ID3D11Device *device; ID3D11DeviceContext *context; DXASS( D3D11CreateDevice( 0, D3D_DRIVER_TYPE_HARDWARE, 0, creationFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &device, &_featureLevel, &context ) ); DXASS( device->QueryInterface( __uuidof( ID3D11Device1 ),(void**)&_d3dDevice ) ); DXASS( context->QueryInterface( __uuidof( ID3D11DeviceContext1 ),(void**)&_d3dContext ) ); device->Release(); context->Release(); //create swap chain if( _swapChain ){ DXASS( _swapChain->ResizeBuffers( 2,width,height,DXGI_FORMAT_B8G8R8A8_UNORM,0 ) ); }else{ #if WINDOWS_8 DXGI_SWAP_CHAIN_DESC1 swapChainDesc={0}; swapChainDesc.Width=width; swapChainDesc.Height=height; swapChainDesc.Format=DXGI_FORMAT_B8G8R8A8_UNORM; swapChainDesc.Stereo=false; swapChainDesc.SampleDesc.Count=1; swapChainDesc.SampleDesc.Quality=0; swapChainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount=2; swapChainDesc.Scaling=DXGI_SCALING_NONE; swapChainDesc.SwapEffect=DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.Flags=0; #elif WINDOWS_PHONE_8 DXGI_SWAP_CHAIN_DESC1 swapChainDesc={0}; swapChainDesc.Width=width; swapChainDesc.Height=height; swapChainDesc.Format=DXGI_FORMAT_B8G8R8A8_UNORM; swapChainDesc.Stereo=false; swapChainDesc.SampleDesc.Count=1; swapChainDesc.SampleDesc.Quality=0; swapChainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount=1; swapChainDesc.Scaling=DXGI_SCALING_STRETCH; swapChainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD; swapChainDesc.Flags=0; #endif IDXGIDevice1 *dxgiDevice; DXASS( _d3dDevice->QueryInterface( __uuidof( IDXGIDevice1 ),(void**)&dxgiDevice ) ); IDXGIAdapter *dxgiAdapter; DXASS( dxgiDevice->GetAdapter( &dxgiAdapter ) ); IDXGIFactory2 *dxgiFactory; DXASS( dxgiAdapter->GetParent( __uuidof( IDXGIFactory2 ),(void**)&dxgiFactory ) ); DXASS( dxgiFactory->CreateSwapChainForCoreWindow( _d3dDevice,(IUnknown*)window,&swapChainDesc,0,&_swapChain ) ); DXASS( dxgiDevice->SetMaximumFrameLatency( 1 ) ); dxgiFactory->Release(); dxgiAdapter->Release(); dxgiDevice->Release(); } // Create a render target view of the swap chain back buffer. // ID3D11Texture2D *backBuffer; DXASS( _swapChain->GetBuffer( 0,__uuidof( ID3D11Texture2D ),(void**)&backBuffer ) ); DXASS( _d3dDevice->CreateRenderTargetView( backBuffer,0,&_renderTargetView ) ); backBuffer->Release(); /* // Create a depth stencil view // D3D11_TEXTURE2D_DESC dsdesc; ZEROMEM( dsdesc ); dsdesc.Width=width; dsdesc.Height=height; dsdesc.MipLevels=1; dsdesc.ArraySize=1; dsdesc.Format=DXGI_FORMAT_D24_UNORM_S8_UINT; dsdesc.SampleDesc.Count=1; dsdesc.SampleDesc.Quality=0; dsdesc.Usage=D3D11_USAGE_DEFAULT; dsdesc.BindFlags=D3D11_BIND_DEPTH_STENCIL; dsdesc.CpuAccessFlags=0; dsdesc.MiscFlags=0; ID3D11Texture2D *depthStencil; DXASS( _d3dDevice->CreateTexture2D( &dsdesc,0,&depthStencil ) ); DXASS( _d3dDevice->CreateDepthStencilView( depthStencil,0,&_depthStencilView ) ); depthStencil->Release(); */ D3D11_VIEWPORT viewport={ 0,0,width,height,0,1 }; _d3dContext->RSSetViewports( 1,&viewport ); }
/// Prepares DXGI and D3D11 data by trying to determine the module filepath /// and function offsets in memory. /// (This data can later be used for hooking / code injection.) /// /// Adjusts the data behind the global variables dxgi and d3d11. void PrepareDXGI11(IDXGIAdapter1* pAdapter, bool initializeDXGIData) { if (!dxgi || !d3d11 || !pAdapter) return; ods("D3D11: Preparing static data for DXGI and D3D11 Injection"); d3d11->wcFileName[0] = 0; d3d11->iOffsetAddRef = 0; d3d11->iOffsetRelease = 0; HMODULE hD3D11 = LoadLibrary("D3D11.DLL"); if (hD3D11 != NULL) { HWND hwnd = CreateWindowW(L"STATIC", L"Mumble DXGI Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 0, NULL, NULL, 0); D3D11CreateDeviceAndSwapChainType pD3D11CreateDeviceAndSwapChain = reinterpret_cast<D3D11CreateDeviceAndSwapChainType>(GetProcAddress(hD3D11, "D3D11CreateDeviceAndSwapChain")); DXGI_SWAP_CHAIN_DESC desc; ZeroMemory(&desc, sizeof(desc)); RECT rcWnd; BOOL success = GetClientRect(hwnd, &rcWnd); if (success) { desc.BufferDesc.Width = rcWnd.right - rcWnd.left; desc.BufferDesc.Height = rcWnd.bottom - rcWnd.top; ods("D3D11: Got ClientRect W %d H %d", desc.BufferDesc.Width, desc.BufferDesc.Height); desc.BufferDesc.RefreshRate.Numerator = 60; desc.BufferDesc.RefreshRate.Denominator = 1; desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; desc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2; desc.OutputWindow = hwnd; desc.Windowed = true; desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; IDXGISwapChain *pSwapChain = NULL; ID3D11Device *pDevice = NULL; D3D_FEATURE_LEVEL featureLevel; ID3D11DeviceContext *pDeviceContext = NULL; HRESULT hr = pD3D11CreateDeviceAndSwapChain(pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &desc, &pSwapChain, &pDevice, &featureLevel, &pDeviceContext); if (FAILED(hr)) ods("D3D11: pD3D11CreateDeviceAndSwapChain failure!"); if (pDevice && pDeviceContext && pSwapChain) { // For VC++ the vtable is located at the base addr. of the object and each function entry is a single pointer. Since p.e. the base classes // of IDXGISwapChain have a total of 8 functions the 8+Xth entry points to the Xth added function in the derived interface. void ***vtbl = (void ***) pSwapChain; void *pPresent = (*vtbl)[8]; int offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pPresent), dxgi->wcFileName, ARRAY_NUM_ELEMENTS(dxgi->wcFileName), "D3D11", "Present"); if (offset >= 0) { if (initializeDXGIData) { dxgi->iOffsetPresent = offset; ods("D3D11: Successfully found Present offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetPresent); } else { if (dxgi->iOffsetPresent == offset) { ods("D3D11: Successfully verified Present offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetPresent); } else { ods("D3D11: Failed to verify Present offset for %ls. Found %d, but previously found %d.", dxgi->wcFileName, offset, dxgi->iOffsetPresent); } } } void *pResize = (*vtbl)[13]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pResize), dxgi->wcFileName, ARRAY_NUM_ELEMENTS(dxgi->wcFileName), "D3D11", "ResizeBuffers"); if (offset >= 0) { if (initializeDXGIData) { dxgi->iOffsetResize = offset; ods("D3D11: Successfully found ResizeBuffers offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetResize); } else { if (dxgi->iOffsetResize == offset) { ods("D3D11: Successfully verified ResizeBuffers offset: %ls: %d", dxgi->wcFileName, dxgi->iOffsetResize); } else { ods("D3D11: Failed to verify ResizeBuffers offset for %ls. Found %d, but previously found %d.", dxgi->wcFileName, offset, dxgi->iOffsetResize); } } } vtbl = (void ***) pDevice; void *pAddRef = (*vtbl)[1]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pAddRef), d3d11->wcFileName, ARRAY_NUM_ELEMENTS(d3d11->wcFileName), "D3D11", "AddRef"); if (offset >= 0) { d3d11->iOffsetAddRef = offset; ods("D3D11: Successfully found AddRef offset: %ls: %d", d3d11->wcFileName, d3d11->iOffsetAddRef); } void *pRelease = (*vtbl)[2]; offset = GetFnOffsetInModule(reinterpret_cast<voidFunc>(pRelease), d3d11->wcFileName, ARRAY_NUM_ELEMENTS(d3d11->wcFileName), "D3D11", "Release"); if (offset >= 0) { d3d11->iOffsetRelease = offset; ods("D3D11: Successfully found Release offset: %ls: %d", d3d11->wcFileName, d3d11->iOffsetRelease); } } if (pDevice) pDevice->Release(); if (pDeviceContext) pDeviceContext->Release(); if (pSwapChain) pSwapChain->Release(); } else { FreeLibrary(hD3D11); } DestroyWindow(hwnd); } else { FreeLibrary(hD3D11); } }
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; }
int main() { // Create Device const D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_11_1 }; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif /* ================================== */ printf("Creating device..."); ID3D11Device* device = nullptr; HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, lvl, _countof(lvl), D3D11_SDK_VERSION, &device, nullptr, nullptr); if (FAILED(hr)) { printf("Failed creating Direct3D 11 device %08X\n", hr); return returnDBG(-1); } /* ================================== */ printf("Compile Compute Shader..."); ID3DBlob *csBlob = nullptr; hr = CompileComputeShader(L"ComputeShader.hlsl", "main", device, &csBlob); if (FAILED(hr)) { device->Release(); printf("Failed compiling shader %08X\n", hr); return returnDBG(-1); } /* ================================== */ printf("Create Compute Shader..."); ID3D11ComputeShader* computeShader = nullptr; hr = device->CreateComputeShader(csBlob->GetBufferPointer(), csBlob->GetBufferSize(), nullptr, &computeShader); /* ================================== */ printf("Creating buffers and filling them with initial data..."); for (int i = 0; i < NUM_ELEMENTS; ++i) { g_vBuf0[i].i = i; g_vBuf0[i].f = (float)i; g_vBuf1[i].i = i; g_vBuf1[i].f = (float)i; } CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), &g_vBuf0[0], &g_pBuf0); CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), &g_vBuf1[0], &g_pBuf1); CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), nullptr, &g_pBufResult); /* ================================== */ printf("Running Compute Shader..."); ID3D11ShaderResourceView* aRViews[2] = { g_pBuf0SRV, g_pBuf1SRV }; RunComputeShader(g_pContext, g_pCS, 2, aRViews, nullptr, nullptr, 0, g_pBufResultUAV, NUM_ELEMENTS, 1, 1); printf("done\n"); csBlob->Release(); if (FAILED(hr)) { device->Release(); } printf("Success\n"); // Clean up computeShader->Release(); device->Release(); return returnDBG(0); }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow) { DXTInputHandlerDefault inputHandler; DXTWindowEventHandlerDefault eventHandler; DXTWindow window(hInstance, &inputHandler, &eventHandler); DXTRenderParams params; params.Extent = { 800, 600 }; params.UseVSync = true; params.Windowed = true; HRESULT result; result = window.Initialize(params, "DXT Example (DirectX 11)"); if (SUCCEEDED(result)) { ID3D11Device* device; ID3D11DeviceContext* context; IDXGISwapChain* swapChain; result = DXTInitDevice(params, &window, &swapChain, &device, &context); if (SUCCEEDED(result)) { eventHandler.SetSwapChain(swapChain); FLOAT clearColor[] = { 0.5f, 0.5f, 1.0f, 1.0f }; D3D11_INPUT_ELEMENT_DESC inputDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float) * 3, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(float) * 5, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT elementCount = 3; UINT stride = 8 * sizeof(FLOAT); UINT offset = 0; UINT indexCount = 0; FLOAT deltaTime = 0.016f; DXTSphericalCamera camera; DXTFirstPersonCameraController cameraController(&camera, &inputHandler); inputHandler.AddInputInterface(&cameraController); cameraController.Velocity = 40.0f; cameraController.RotationVelocity = 0.005f; camera.Position = DirectX::XMFLOAT3(20.0f, 20.0f, 20.0f); camera.LookAt(DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f)); ID3D11RenderTargetView* renderTargetView; ID3D11Texture2D* depthBuffer; ID3D11DepthStencilView* depthBufferView; ID3D11VertexShader* vertexShader; ID3D11PixelShader* pixelShader; DXTBytecodeBlob vertexBytecode; ID3D11DepthStencilState* depthState; ID3D11RasterizerState* rasterizerState; ID3D11Buffer* vertexBuffer; ID3D11Buffer* indexBuffer; ID3D11InputLayout* inputLayout; ID3D11Buffer* transformBuffer; DXTCreateRenderTargetFromBackBuffer(swapChain, device, &renderTargetView); DXTCreateDepthStencilBuffer(device, params.Extent.Width, params.Extent.Height, DXGI_FORMAT_D24_UNORM_S8_UINT, &depthBuffer, &depthBufferView); DXTVertexShaderFromFile(device, "VertexShader.cso", &vertexShader, &vertexBytecode); DXTPixelShaderFromFile(device, "PixelShader.cso", &pixelShader); DXTCreateDepthStencilStateDepthTestEnabled(device, &depthState); DXTCreateRasterizerStateSolid(device, &rasterizerState); DXTLoadStaticMeshFromFile(device, "mesh.ase", DXTVertexAttributePosition | DXTVertexAttributeUV | DXTVertexAttributeNormal, DXTIndexTypeShort, &vertexBuffer, &indexBuffer, &indexCount); DXTCreateBuffer(device, sizeof(DirectX::XMFLOAT4X4) * 2, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, D3D11_USAGE_DYNAMIC, &transformBuffer); device->CreateInputLayout(inputDesc, elementCount, vertexBytecode.Bytecode, vertexBytecode.BytecodeLength, &inputLayout); vertexBytecode.Destroy(); window.Present(false); while (!window.QuitMessageReceived()) { window.MessagePump(); if (inputHandler.IsKeyDown(VK_ESCAPE)) break; cameraController.Update(deltaTime); XMFLOAT4X4 ViewProj; XMFLOAT4X4 World; camera.GetViewProjectionMatrix(&ViewProj, params.Extent); XMStoreFloat4x4(&World, XMMatrixIdentity()); D3D11_MAPPED_SUBRESOURCE subres; context->Map(transformBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subres); XMFLOAT4X4* ptr = (XMFLOAT4X4*)subres.pData; ptr[0] = World; ptr[1] = ViewProj; context->Unmap(transformBuffer, 0); D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (FLOAT)params.Extent.Width, (FLOAT)params.Extent.Height, 0.0f, 1.0f }; context->ClearRenderTargetView(renderTargetView, clearColor); context->ClearDepthStencilView(depthBufferView, D3D11_CLEAR_DEPTH, 1.0f, 0); context->OMSetDepthStencilState(depthState, 0); context->OMSetRenderTargets(1, &renderTargetView, depthBufferView); context->RSSetState(rasterizerState); context->RSSetViewports(1, &viewport); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset); context->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, 0); context->IASetInputLayout(inputLayout); context->VSSetShader(vertexShader, nullptr, 0); context->PSSetShader(pixelShader, nullptr, 0); context->VSSetConstantBuffers(0, 1, &transformBuffer); context->DrawIndexed(indexCount, 0, 0); swapChain->Present(1, 0); } swapChain->SetFullscreenState(false, nullptr); transformBuffer->Release(); depthBufferView->Release(); depthBuffer->Release(); inputLayout->Release(); vertexBuffer->Release(); indexBuffer->Release(); depthState->Release(); rasterizerState->Release(); vertexShader->Release(); pixelShader->Release(); renderTargetView->Release(); swapChain->Release(); context->Release(); device->Release(); } window.Destroy(); } }
int main(int argc, char* argv[]) { options::option<bool> help("-h --help /?", "- Shows this help"); options::option<int> dimensions("--resolution", "<resolution> - Specifies texture resolution", { 128 }); options::option<float> scale("--scale", "<scale> - Specifies noise scale", { 8 } ); options::option<bool> gradients("--gradients", "- Store gradients in RGB channels (generates R8G8B8A8 textures instead of R8) - Note: gradients are fitted in [0-1]"); options::option<string> output("--output", 1, "<filename> - DDS destination texture"); options::option<bool> dumpAsFloat("--float", "- Use a floating-point texture format (default is R8/R8G8B8A8)"); auto cmdln = options::make_parser( help, dimensions, scale, gradients, output, dumpAsFloat ); cmdln.parse(argv, argv+argc); if (help || !output) { cout << "Generates tiling 3D textures filled with simplex noise. Options are :\n" << endl; cout << cmdln << endl; cout << "Example:" << endl; cout << " noise2dds --gradients --float --scale 16 --resolution 256 --output noise_256.dds" << endl; cout << "Will generate a texture with dimensions of 256x256x256, noise scale 16, with format DXGI_FORMAT_R32G32B32A32_FLOAT as noise_256.dds" << endl; return 0; } Volume<float> volume(dimensions(0), dimensions(0), dimensions(0), gradients ? 4 : 1); anl::CMWC4096 rnd; rnd.setSeedTime(); anl::CImplicitBasisFunction noise(anl::SIMPLEX, anl::QUINTIC); const float twopi = 2.f * 3.14159f; auto sampleNoise = [&](float x, float y, float z, int c) -> float { float dx = scale(0); float nx = cosf(x * twopi) * dx / twopi; float ny = cosf(y * twopi) * dx / twopi; float nz = cosf(z * twopi) * dx / twopi; float nw = sinf(x * twopi) * dx / twopi; float nu = sinf(y * twopi) * dx / twopi; float nv = sinf(z * twopi) * dx / twopi; float f = (float) noise.get(nx, ny, nz, nw, nu, nv) * 0.5f + 0.5f; return f; }; if (gradients) { float fmin = (std::numeric_limits<float>::max)(); float fmax = -(std::numeric_limits<float>::max)(); const float dx = 2.0f / 128.f; // 2.0f actually smoothes out the slight artifacts anl happens to have in its 6D simplex noise implementation volume.fill(0, [&](float x, float y, float z, int c) -> float { float m = (sampleNoise(x + dx, y, z, c) - sampleNoise(x - dx, y, z, c)) * 0.5f + 0.5f; fmin = (std::min)(m, fmin); fmax = (std::max)(m, fmax); return m; }); volume.fill(1, [&](float x, float y, float z, int c) -> float { float m = (sampleNoise(x, y + dx, z, c) - sampleNoise(x, y - dx, z, c)) * 0.5f + 0.5f; fmin = (std::min)(m, fmin); fmax = (std::max)(m, fmax); return m; }); volume.fill(2, [&](float x, float y, float z, int c) -> float { float m = (sampleNoise(x, y, z + dx, c) - sampleNoise(x, y, z - dx, c)) * 0.5f + 0.5f; fmin = (std::min)(m, fmin); fmax = (std::max)(m, fmax); return m; }); volume.fill(3, sampleNoise); // normalize gradients for (unsigned int n = 0; n < volume.Width*volume.Height*volume.Depth; n++) for (unsigned int c = 0; c < 3; c++) { float& f = volume.Data[n * 4 + c]; f = (f - fmin) / (fmax - fmin); } } else volume.fill(0, sampleNoise); // ID3D11Device* device; ID3D11DeviceContext* deviceContext; D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_SINGLETHREADED, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &deviceContext); if (dumpAsFloat) { volume.dump(output(0), gradients ? DXGI_FORMAT_R32G32B32A32_FLOAT : DXGI_FORMAT_R32_FLOAT, deviceContext); } else { Volume<byte> volumeByte(dimensions(0), dimensions(0), dimensions(0), gradients ? 4 : 1); volumeByte.fill([&](int x, int y, int z, int c) -> byte { return (byte) (volume.Data[(z * volume.Height * volume.Width + y * volume.Width + x) * volume.Channels + c] * 255.f); }); volumeByte.dump(output(0), gradients ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM, deviceContext); } deviceContext->Release(); device->Release(); return 0; }
/** * Handle OSVR direct mode. ***/ void* OSVR_DirectMode::Provoke(void* pThis, int eD3D, int eD3DInterface, int eD3DMethod, DWORD dwNumberConnected, int& nProvokerIndex) { if (eD3DInterface != INTERFACE_IDXGISWAPCHAIN) return nullptr; if (eD3DMethod != METHOD_IDXGISWAPCHAIN_PRESENT) return nullptr; if (!m_bHotkeySwitch) { if (GetAsyncKeyState(VK_F11)) { m_bHotkeySwitch = true; } return nullptr; } // Get an OSVR client context to use to access the devices // that we need. static osvr::clientkit::ClientContext m_pcClientContext = osvr::clientkit::ClientContext("com.mtbs3d.vireio.osvr.directmode"); if (m_pcRenderManager == nullptr) { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; switch (m_eMethod) { case OSVR_undefined: // TODO !! determine method by used DX version return nullptr; case OSVR_D3D11_use_Game_Device: if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); return nullptr; } break; case OSVR_D3D11_own_Device: case OSVR_D3D10_own_Device: case OSVR_D3D9_own_Device: { // get game device + context if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_own_Device) { if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &m_pcGameDevice, &m_pcGameDeviceContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); return nullptr; } m_pcGameDevice->Release(); m_pcGameDeviceContext->Release(); } // Be sure to get D3D11 and have set // D3D11_CREATE_DEVICE_BGRA_SUPPORT in the device/context D3D_FEATURE_LEVEL acceptibleAPI = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL foundAPI; auto hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, &acceptibleAPI, 1, D3D11_SDK_VERSION, &m_pcDevice, &foundAPI, &m_pcDeviceContext); if (FAILED(hr)) { OutputDebugString(L"Could not create D3D11 device and context"); return nullptr; } pcDevice = m_pcDevice; pcContext = m_pcDeviceContext; } break; default: break; } // Put the device and context into a structure to let RenderManager // know to use this one rather than creating its own. osvr::renderkit::GraphicsLibrary cLibrary; cLibrary.D3D11 = new osvr::renderkit::GraphicsLibraryD3D11; cLibrary.D3D11->device = pcDevice; cLibrary.D3D11->context = pcContext; if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } // Open Direct3D and set up the context for rendering to // an HMD. Do this using the OSVR RenderManager interface, // which maps to the nVidia or other vendor direct mode // to reduce the latency. m_pcRenderManager = osvr::renderkit::createRenderManager(m_pcClientContext.get(), "Direct3D11", cLibrary); if ((m_pcRenderManager == nullptr) || (!m_pcRenderManager->doingOkay())) { // Error OutputDebugString(L"OSVR-DirectMode: [Error] No Render Manager available !"); } else { // Set callback to handle setting up rendering in a display m_pcRenderManager->SetDisplayCallback((osvr::renderkit::DisplayCallback)&OSVR_DirectMode::SetupDisplay); // Register callback to render things in world space. m_pcRenderManager->AddRenderCallback("/", (osvr::renderkit::RenderCallback)&OSVR_DirectMode::DrawWorld); // Open the display and make sure this worked. osvr::renderkit::RenderManager::OpenResults ret = m_pcRenderManager->OpenDisplay(); if (ret.status == osvr::renderkit::RenderManager::OpenStatus::FAILURE) { OutputDebugString(L"Could not open display"); } if (ret.library.D3D11 == nullptr) { OutputDebugString(L"Attempted to run a Direct3D11 program with a config file that specified a different renderling library."); } // Do a call to get the information we need to construct our // color and depth render-to-texture buffers. std::vector<osvr::renderkit::RenderInfo> asRenderInfo; m_pcClientContext.update(); asRenderInfo = m_pcRenderManager->GetRenderInfo(); // Create the sampler state D3D11_SAMPLER_DESC sSampDesc; ZeroMemory(&sSampDesc, sizeof(sSampDesc)); sSampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sSampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sSampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sSampDesc.MinLOD = 0; sSampDesc.MaxLOD = D3D11_FLOAT32_MAX; if (FAILED(asRenderInfo[0].library.D3D11->device->CreateSamplerState(&sSampDesc, &m_pcSamplerState))) OutputDebugString(L"Failed to create Sampler State."); } } else { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; switch (m_eMethod) { case OSVR_undefined: return nullptr; case OSVR_D3D11_use_Game_Device: if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext))) { OutputDebugString(L"OSVR-DirectMode: Failed to get d3d11 device + context"); // release frame texture+view if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } return nullptr; } break; case OSVR_D3D11_own_Device: case OSVR_D3D10_own_Device: case OSVR_D3D9_own_Device: pcDevice = m_pcDevice; pcContext = m_pcDeviceContext; break; default: break; } // backup device states, if game device is used D3DX11_STATE_BLOCK sStateBlock; if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { // backup all states CreateStateblock(pcContext, &sStateBlock); // clear all states pcContext->ClearState(); } // Update the context so we get our callbacks called and // update tracker state. m_pcClientContext.update(); if (!m_pcRenderManager->Render()) { OutputDebugString(L"Render() returned false, maybe because it was asked to quit"); } // apply state block, if game device is used if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { // set back device ApplyStateblock(pcContext, &sStateBlock); if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } } return nullptr; }
/** * Handle Stereo Drawing. ***/ void* StereoPresenter::Provoke(void* pThis, int eD3D, int eD3DInterface, int eD3DMethod, DWORD dwNumberConnected, int& nProvokerIndex) { #ifdef _DEBUG_STP { wchar_t buf[128]; wsprintf(buf, L"[STP] ifc %u mtd %u", eD3DInterface, eD3DMethod); OutputDebugString(buf); } #endif // update our global time static float fGlobalTime = 0.0f; static DWORD dwTimeStart = 0; DWORD dwTimeCur = GetTickCount(); if (dwTimeStart == 0) dwTimeStart = dwTimeCur; fGlobalTime = (dwTimeCur - dwTimeStart) / 1000.0f; // only present accepted bool bValid = false; if (((eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT)) || ((eD3DInterface == INTERFACE_IDIRECT3DDEVICE9) && (eD3DMethod == METHOD_IDIRECT3DDEVICE9_PRESENT))) bValid = true; if (!bValid) return nullptr; // clear all previous menu events ZeroMemory(&m_abMenuEvents[0], sizeof(VireioMenuEvent)* (int)VireioMenuEvent::NumberOfEvents); // main menu update ? if ((m_sMainMenu.bOnChanged) && (!m_sMenuControl.eSelectionMovement)) { m_sMainMenu.bOnChanged = false; // loop through entries for (size_t nIx = 0; nIx < m_sMainMenu.asEntries.size(); nIx++) { // entry index changed ? if (m_sMainMenu.asEntries[nIx].bOnChanged) { m_sMainMenu.asEntries[nIx].bOnChanged = false; // set new menu index.. selection to zero m_sMenuControl.nMenuIx = (INT)nIx; m_sMenuControl.unSelectionFormer = m_sMenuControl.unSelection = 0; } } } // sub menu update ? if ((m_sSubMenu.bOnChanged) && (!m_sMenuControl.eSelectionMovement)) { m_sSubMenu.bOnChanged = false; // exit ? if (m_sSubMenu.bOnExit) m_sMenuControl.nMenuIx = -1; // loop through entries for (size_t nIx = 0; nIx < m_sSubMenu.asEntries.size(); nIx++) { // entry index changed ? if (m_sSubMenu.asEntries[nIx].bOnChanged) { m_sSubMenu.asEntries[nIx].bOnChanged = false; // font ? if (nIx == ENTRY_FONT) { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; HRESULT nHr = S_OK; if ((eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT)) nHr = GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext); else { if (m_ppcTexView11[0]) { if (*(m_ppcTexView11[0])) (*(m_ppcTexView11[0]))->GetDevice(&pcDevice); if (pcDevice) pcDevice->GetImmediateContext(&pcContext); else nHr = E_FAIL; if (!pcContext) nHr = E_FAIL; } else nHr = E_FAIL; } if (SUCCEEDED(nHr)) { HRESULT nHr; // get base directory std::string strVireioPath = GetBaseDir(); // add file path strVireioPath += "font//"; strVireioPath += m_sSubMenu.asEntries[nIx].astrValueEnumeration[m_sSubMenu.asEntries[nIx].unValue]; strVireioPath += ".spritefont"; OutputDebugStringA(strVireioPath.c_str()); // create font, make backup VireioFont* pcOldFont = m_pcFontSegeo128; m_pcFontSegeo128 = new VireioFont(pcDevice, pcContext, strVireioPath.c_str(), 128.0f, 1.0f, nHr, 1); if (FAILED(nHr)) { delete m_pcFontSegeo128; m_pcFontSegeo128 = pcOldFont; } else { // set new font name m_strFontName = m_sSubMenu.asEntries[nIx].astrValueEnumeration[m_sSubMenu.asEntries[nIx].unValue]; // write to ini file char szFilePathINI[1024]; GetCurrentDirectoryA(1024, szFilePathINI); strcat_s(szFilePathINI, "\\VireioPerception.ini"); WritePrivateProfileStringA("Stereo Presenter", "strFontName", m_strFontName.c_str(), szFilePathINI); } } SAFE_RELEASE(pcDevice); SAFE_RELEASE(pcContext); } } } } // get xbox controller input XINPUT_STATE sControllerState; bool bControllerAttached = false; ZeroMemory(&sControllerState, sizeof(XINPUT_STATE)); if (XInputGetState(0, &sControllerState) == ERROR_SUCCESS) { bControllerAttached = true; } if (true) { #pragma region menu hotkeys static bool bReleased = true; static bool s_bOnMenu = false; // keyboard menu on/off event + get hand poses UINT uIxHandPoses = 0, uIxPoseRequest = 0; s_bOnMenu = GetAsyncKeyState(VK_LCONTROL) && GetAsyncKeyState(0x51); for (UINT unIx = 0; unIx < 32; unIx++) { // set menu bool event if (m_apsSubMenues[unIx]) { if (m_apsSubMenues[unIx]->bOnBack) { // main menu ? exit if ((m_sMenuControl.nMenuIx == -1) && (!m_sMenuControl.eSelectionMovement)) s_bOnMenu = true; else m_abMenuEvents[VireioMenuEvent::OnExit] = TRUE; m_apsSubMenues[unIx]->bOnBack = false; } // hand poses ? if (m_apsSubMenues[unIx]->bHandPosesPresent) uIxHandPoses = unIx; if (m_apsSubMenues[unIx]->bHandPosesRequest) uIxPoseRequest = unIx; } } if ((m_apsSubMenues[uIxHandPoses]) && (m_apsSubMenues[uIxPoseRequest])) { // copy the hand pose data to the request node m_apsSubMenues[uIxPoseRequest]->sPoseMatrix[0] = m_apsSubMenues[uIxHandPoses]->sPoseMatrix[0]; m_apsSubMenues[uIxPoseRequest]->sPoseMatrix[1] = m_apsSubMenues[uIxHandPoses]->sPoseMatrix[1]; m_apsSubMenues[uIxPoseRequest]->sPosition[0] = m_apsSubMenues[uIxHandPoses]->sPosition[0]; m_apsSubMenues[uIxPoseRequest]->sPosition[1] = m_apsSubMenues[uIxHandPoses]->sPosition[1]; } // static hotkeys : LCTRL+Q - toggle vireio menu // F12 - toggle stereo output if (GetAsyncKeyState(VK_F12)) { m_bHotkeySwitch = true; } else if (s_bOnMenu) { m_bMenuHotkeySwitch = true; } else if (m_bMenuHotkeySwitch) { m_bMenuHotkeySwitch = false; m_bMenu = !m_bMenu; for (UINT unIx = 0; unIx < 32; unIx++) { // set sub menu active if menu is active if (m_apsSubMenues[unIx]) m_apsSubMenues[unIx]->bIsActive = m_bMenu; } } else if (m_bHotkeySwitch) { if (m_eStereoMode) m_eStereoMode = VireioMonitorStereoModes::Vireio_Mono; else m_eStereoMode = VireioMonitorStereoModes::Vireio_SideBySide; m_bHotkeySwitch = false; } else bReleased = true; #pragma endregion #pragma region menu events // menu is shown ? if (m_bMenu) { // handle controller if (bControllerAttached) { if (sControllerState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) { m_abMenuEvents[VireioMenuEvent::OnExit] = TRUE; } if (sControllerState.Gamepad.wButtons & XINPUT_GAMEPAD_A) { m_abMenuEvents[VireioMenuEvent::OnAccept] = TRUE; } if (sControllerState.Gamepad.sThumbLY > 28000) m_abMenuEvents[VireioMenuEvent::OnUp] = TRUE; if (sControllerState.Gamepad.sThumbLY < -28000) m_abMenuEvents[VireioMenuEvent::OnDown] = TRUE; if (sControllerState.Gamepad.sThumbLX > 28000) m_abMenuEvents[VireioMenuEvent::OnRight] = TRUE; if (sControllerState.Gamepad.sThumbLX < -28000) m_abMenuEvents[VireioMenuEvent::OnLeft] = TRUE; } // loop through sub menues for (UINT unIx = 0; unIx < 32; unIx++) { // set bool events if (m_apsSubMenues[unIx]) { if (m_apsSubMenues[unIx]->bOnUp) m_abMenuEvents[VireioMenuEvent::OnUp] = TRUE; if (m_apsSubMenues[unIx]->bOnDown) m_abMenuEvents[VireioMenuEvent::OnDown] = TRUE; if (m_apsSubMenues[unIx]->bOnLeft) m_abMenuEvents[VireioMenuEvent::OnLeft] = TRUE; if (m_apsSubMenues[unIx]->bOnRight) m_abMenuEvents[VireioMenuEvent::OnRight] = TRUE; if (m_apsSubMenues[unIx]->bOnAccept) m_abMenuEvents[VireioMenuEvent::OnAccept] = TRUE; // clear events m_apsSubMenues[unIx]->bOnUp = false; m_apsSubMenues[unIx]->bOnDown = false; m_apsSubMenues[unIx]->bOnLeft = false; m_apsSubMenues[unIx]->bOnRight = false; m_apsSubMenues[unIx]->bOnAccept = false; m_apsSubMenues[unIx]->bOnBack = false; } } #pragma endregion #pragma region menu update/render // update UpdateMenu(fGlobalTime); // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; HRESULT nHr = S_OK; if ((eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT)) nHr = GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext); else { if (m_ppcTexView11[0]) { if (*(m_ppcTexView11[0])) (*(m_ppcTexView11[0]))->GetDevice(&pcDevice); if (pcDevice) pcDevice->GetImmediateContext(&pcContext); else nHr = E_FAIL; if (!pcContext) nHr = E_FAIL; } else nHr = E_FAIL; } if (FAILED(nHr)) { // release frame texture+view if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } return nullptr; } // create the depth stencil... if D3D11 if ((eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT) && (!m_pcDSGeometry11)) { ID3D11Texture2D* pcBackBuffer = nullptr; ((IDXGISwapChain*)pThis)->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pcBackBuffer); if (pcBackBuffer) { D3D11_TEXTURE2D_DESC sDesc; pcBackBuffer->GetDesc(&sDesc); pcBackBuffer->Release(); // Create depth stencil texture D3D11_TEXTURE2D_DESC descDepth; ZeroMemory(&descDepth, sizeof(descDepth)); descDepth.Width = sDesc.Width; descDepth.Height = sDesc.Height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; if (FAILED(pcDevice->CreateTexture2D(&descDepth, NULL, &m_pcDSGeometry11))) OutputDebugString(L"[STP] Failed to create depth stencil."); // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory(&descDSV, sizeof(descDSV)); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; if (FAILED(pcDevice->CreateDepthStencilView(m_pcDSGeometry11, &descDSV, &m_pcDSVGeometry11))) OutputDebugString(L"[STP] Failed to create depth stencil view."); } } // get the viewport UINT dwNumViewports = 1; D3D11_VIEWPORT psViewport[16]; pcContext->RSGetViewports(&dwNumViewports, psViewport); // backup all states D3DX11_STATE_BLOCK sStateBlock; CreateStateblock(pcContext, &sStateBlock); // clear all states, set targets ClearContextState(pcContext); // set the menu texture (if present) if (m_ppcTexViewMenu) { if (*m_ppcTexViewMenu) { // set render target ID3D11RenderTargetView* pcRTView = *m_ppcTexViewMenu; pcContext->OMSetRenderTargets(1, &pcRTView, NULL); // set viewport D3D11_VIEWPORT sViewport = {}; sViewport.TopLeftX = 0; sViewport.TopLeftY = 0; sViewport.Width = 1024; sViewport.Height = 1024; sViewport.MinDepth = 0.0f; sViewport.MaxDepth = 1.0f; pcContext->RSSetViewports(1, &sViewport); // clear render target...zero alpha FLOAT afColorRgba[4] = { 0.5f, 0.4f, 0.2f, 0.4f }; pcContext->ClearRenderTargetView(*m_ppcTexViewMenu, afColorRgba); } } else if ((eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT)) { // set first active render target - the stored back buffer - get the stored private data view ID3D11Texture2D* pcBackBuffer = nullptr; ((IDXGISwapChain*)pThis)->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pcBackBuffer); ID3D11RenderTargetView* pcView = nullptr; UINT dwSize = sizeof(pcView); pcBackBuffer->GetPrivateData(PDIID_ID3D11TextureXD_RenderTargetView, &dwSize, (void*)&pcView); if (dwSize) { pcContext->OMSetRenderTargets(1, (ID3D11RenderTargetView**)&pcView, m_pcDSVGeometry11); pcView->Release(); } else { // create render target view for the back buffer ID3D11RenderTargetView* pcRTV = nullptr; pcDevice->CreateRenderTargetView(pcBackBuffer, NULL, &pcRTV); if (pcRTV) { pcBackBuffer->SetPrivateDataInterface(PDIID_ID3D11TextureXD_RenderTargetView, pcRTV); pcRTV->Release(); } } pcContext->RSSetViewports(dwNumViewports, psViewport); pcBackBuffer->Release(); // clear the depth stencil pcContext->ClearDepthStencilView(m_pcDSVGeometry11, D3D11_CLEAR_DEPTH, 1.0f, 0); } // create the font class if not present nHr = S_OK; if (!m_pcFontSegeo128) { // get base directory std::string strVireioPath = GetBaseDir(); // add file path strVireioPath += "font//"; strVireioPath += m_strFontName; strVireioPath += ".spritefont"; OutputDebugStringA(strVireioPath.c_str()); // create font m_pcFontSegeo128 = new VireioFont(pcDevice, pcContext, strVireioPath.c_str(), 128.0f, 1.0f, nHr, 1); } if (FAILED(nHr)) { delete m_pcFontSegeo128; m_pcFontSegeo128 = nullptr; } // render text (if font present) if (m_pcFontSegeo128) { m_pcFontSegeo128->SetTextAttributes(0.0f, 0.2f, 0.0001f); // set additional tremble for "accepted" event float fDepthTremble = 0.0f; if (m_sMenuControl.eSelectionMovement == MenuControl::SelectionMovement::Accepted) { float fActionTimeElapsed = (fGlobalTime - m_sMenuControl.fActionStartTime) / m_sMenuControl.fActionTime; fDepthTremble = sin(fActionTimeElapsed*PI_F) * -3.0f; } m_pcFontSegeo128->ToRender(pcContext, fGlobalTime, m_sMenuControl.fYOrigin, 30.0f, fDepthTremble); RenderMenu(pcDevice, pcContext); } else OutputDebugString(L"Failed to create font!"); // set back device ApplyStateblock(pcContext, &sStateBlock); if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } #pragma endregion #pragma region draw stereo (optionally) // draw stereo target to screen (optionally) if ((m_eStereoMode) && (eD3DInterface == INTERFACE_IDXGISWAPCHAIN) && (eD3DMethod == METHOD_IDXGISWAPCHAIN_PRESENT)) { // DX 11 if ((m_ppcTexView11[0]) && (m_ppcTexView11[1])) { // get device and context ID3D11Device* pcDevice = nullptr; ID3D11DeviceContext* pcContext = nullptr; if (FAILED(GetDeviceAndContext((IDXGISwapChain*)pThis, &pcDevice, &pcContext))) { // release frame texture+view if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } return nullptr; } // get the viewport UINT dwNumViewports = 1; D3D11_VIEWPORT psViewport[16]; pcContext->RSGetViewports(&dwNumViewports, psViewport); // backup all states D3DX11_STATE_BLOCK sStateBlock; CreateStateblock(pcContext, &sStateBlock); // clear all states, set targets ClearContextState(pcContext); // set first active render target - the stored back buffer - get the stored private data view ID3D11Texture2D* pcBackBuffer = nullptr; ((IDXGISwapChain*)pThis)->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pcBackBuffer); ID3D11RenderTargetView* pcView = nullptr; UINT dwSize = sizeof(pcView); pcBackBuffer->GetPrivateData(PDIID_ID3D11TextureXD_RenderTargetView, &dwSize, (void*)&pcView); if (dwSize) { pcContext->OMSetRenderTargets(1, (ID3D11RenderTargetView**)&pcView, m_pcDSVGeometry11); pcView->Release(); } else { // create render target view for the back buffer ID3D11RenderTargetView* pcRTV = nullptr; pcDevice->CreateRenderTargetView(pcBackBuffer, NULL, &pcRTV); if (pcRTV) { pcBackBuffer->SetPrivateDataInterface(PDIID_ID3D11TextureXD_RenderTargetView, pcRTV); pcRTV->Release(); } } pcContext->RSSetViewports(dwNumViewports, psViewport); pcBackBuffer->Release(); // clear the depth stencil pcContext->ClearDepthStencilView(m_pcDSVGeometry11, D3D11_CLEAR_DEPTH, 1.0f, 0); // create all bool bool bAllCreated = true; // create vertex shader if (!m_pcVertexShader11) { if (FAILED(CreateVertexShaderTechnique(pcDevice, &m_pcVertexShader11, &m_pcVertexLayout11, VertexShaderTechnique::PosUV2D))) bAllCreated = false; } // create pixel shader... TODO !! add option to switch output if (!m_pcPixelShader11) { if (FAILED(CreatePixelShaderEffect(pcDevice, &m_pcPixelShader11, PixelShaderTechnique::FullscreenSimple))) bAllCreated = false; } // Create vertex buffer if (!m_pcVertexBuffer11) { if (FAILED(CreateFullScreenVertexBuffer(pcDevice, &m_pcVertexBuffer11))) bAllCreated = false; } // create constant buffer if (!m_pcConstantBufferDirect11) { if (FAILED(CreateGeometryConstantBuffer(pcDevice, &m_pcConstantBufferDirect11, (UINT)sizeof(GeometryConstantBuffer)))) bAllCreated = false; } if (bAllCreated) { // left/right eye for (int nEye = 0; nEye < 2; nEye++) { // Set the input layout pcContext->IASetInputLayout(m_pcVertexLayout11); // Set vertex buffer UINT stride = sizeof(TexturedVertex); UINT offset = 0; pcContext->IASetVertexBuffers(0, 1, &m_pcVertexBuffer11, &stride, &offset); // Set constant buffer, first update it... scale and translate the left and right image D3DXMATRIX sScale; D3DXMatrixScaling(&sScale, 0.5f, 1.0f, 1.0f); D3DXMATRIX sTrans; if (nEye == 0) D3DXMatrixTranslation(&sTrans, -0.5f, 0.0f, 0.0f); else D3DXMatrixTranslation(&sTrans, 0.5f, 0.0f, 0.0f); D3DXMatrixTranspose(&sTrans, &sTrans); D3DXMATRIX sProj; D3DXMatrixMultiply(&sProj, &sTrans, &sScale); pcContext->UpdateSubresource((ID3D11Resource*)m_pcConstantBufferDirect11, 0, NULL, &sProj, 0, 0); pcContext->VSSetConstantBuffers(0, 1, &m_pcConstantBufferDirect11); // Set primitive topology pcContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // set texture pcContext->PSSetShaderResources(0, 1, m_ppcTexView11[nEye]); // set shaders pcContext->VSSetShader(m_pcVertexShader11, 0, 0); pcContext->PSSetShader(m_pcPixelShader11, 0, 0); // Render a triangle pcContext->Draw(6, 0); } } // set back device ApplyStateblock(pcContext, &sStateBlock); if (pcDevice) { pcDevice->Release(); pcDevice = nullptr; } if (pcContext) { pcContext->Release(); pcContext = nullptr; } } } #pragma endregion } return nullptr; }
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 PngViewer::init_d2d() { DXGI_SWAP_CHAIN_DESC1 swap_descriptor; RECT client_rect; ID3D11Device * device; IDXGISwapChain1 * swap_chain_1; HRESULT r; if(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, nullptr) != S_OK) { return false; } r = device->QueryInterface(__uuidof(IDXGIDevice3), (void **)&this->device_gi); device->Release(); if(r != S_OK) { return false; } if(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, __uuidof(IDXGIFactory3), (void **)&this->gi_factory) != S_OK) { return false; } ::GetClientRect(this->window, &client_rect); this->swap_chain_region.cx = client_rect.right - client_rect.left; this->swap_chain_region.cy = client_rect.bottom - client_rect.top; ::memset(&swap_descriptor, 0, sizeof(DXGI_SWAP_CHAIN_DESC1)); swap_descriptor.Width = this->swap_chain_region.cx; swap_descriptor.Height = this->swap_chain_region.cy; swap_descriptor.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swap_descriptor.SampleDesc.Count = 1; swap_descriptor.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_descriptor.BufferCount = 2; swap_descriptor.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swap_descriptor.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; if(this->gi_factory->CreateSwapChainForComposition(this->device_gi, &swap_descriptor, nullptr, &swap_chain_1) != S_OK) { return false; } r = swap_chain_1->QueryInterface(__uuidof(IDXGISwapChain2), (void **)&this->swap_chain); swap_chain_1->Release(); if(r != S_OK) { return false; } if(DCompositionCreateDevice(this->device_gi, __uuidof(IDCompositionDevice), (void **)&this->comp_device) != S_OK) { return false; } if(this->comp_device->CreateTargetForHwnd(this->window, true, &this->comp_target) != S_OK) { return false; } if(this->comp_device->CreateVisual(&this->comp_visual) != S_OK) { return false; } this->comp_visual->SetContent(this->swap_chain); this->comp_target->SetRoot(this->comp_visual); this->comp_device->Commit(); return true; }