//-------------------------------------------------------------------------------------- // class ShadowMapRenderTarget: public RenderTarget; // 用途: シャドウマップのレンダリングターゲット //-------------------------------------------------------------------------------------- //構築と破棄 ShadowMapRenderTarget::ShadowMapRenderTarget(float ShadowMapDimension) : pImpl(new Impl(ShadowMapDimension)) { try{ //デバイスとコンテキストインターフェイスの取得 auto Dev = App::GetApp()->GetDeviceResources(); auto pD3D11Device = Dev->GetD3DDevice(); auto pSwapChain = Dev->GetSwapChain(); auto pD3D11DeviceContext = Dev->GetD3DDeviceContext(); //シャドウマップテクスチャの作成 D3D11_TEXTURE2D_DESC shadowMapDesc; ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC)); shadowMapDesc.Width = static_cast<UINT>(pImpl->m_ShadowMapDimension); shadowMapDesc.Height = static_cast<UINT>(pImpl->m_ShadowMapDimension); shadowMapDesc.MipLevels = 1; shadowMapDesc.ArraySize = 1; shadowMapDesc.SampleDesc.Count = 1; shadowMapDesc.Usage = D3D11_USAGE_DEFAULT; shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS; ThrowIfFailed( pD3D11Device->CreateTexture2D(&shadowMapDesc, nullptr, &pImpl->m_DepthStencil), L"シャドウマップテクスチャの作成に失敗しました。", L"pD3D11Device->CreateTexture2D(&shadowMapDesc, nullptr, &m_DepthStencil)", L"ShadowMapRenderTarget::ShadowMapRenderTarget()" ); //深度ステンシルビュー作成 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC)); depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; ThrowIfFailed( pD3D11Device->CreateDepthStencilView(pImpl->m_DepthStencil.Get(), &depthStencilViewDesc, &pImpl->m_DepthStencilView), L"深度ステンシルビューの作成に失敗しました。", L"pD3D11Device->CreateDepthStencilView(&m_DepthStencil, &depthStencilViewDesc, &m_DepthStencilView)", L"ShadowMapRenderTarget::ShadowMapRenderTarget()" ); //シェーダーリソースビュー作成 D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shaderResourceViewDesc.Texture2D.MipLevels = 1; ThrowIfFailed( pD3D11Device->CreateShaderResourceView(pImpl->m_DepthStencil.Get(), &shaderResourceViewDesc, &pImpl->m_ShaderResourceView), L"シェーダーリソースビューの作成に失敗しました。", L"pD3D11Device->CreateShaderResourceView(m_DepthStencil.Get(), &shaderResourceViewDesc, &m_ShaderResourceView)", L"ShadowMapRenderTarget::ShadowMapRenderTarget()" ); D3D11_RASTERIZER_DESC shadowRenderStateDesc; ZeroMemory(&shadowRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC)); shadowRenderStateDesc.CullMode = D3D11_CULL_FRONT; shadowRenderStateDesc.FillMode = D3D11_FILL_SOLID; shadowRenderStateDesc.DepthClipEnable = true; ThrowIfFailed(pD3D11Device->CreateRasterizerState(&shadowRenderStateDesc,&pImpl->m_ShadowRenderState), L"シャドウマップのラスタライザステートの作成に失敗しました。", L"pD3D11Device->CreateRasterizerState(&shadowRenderStateDesc,&pImpl->m_ShadowRenderState)", L"ShadowMapRenderTarget::ShadowMapRenderTarget()" ); //ビューポートの作成 //シャドウレンダリングビューポート ZeroMemory(&pImpl->m_ViewPort, sizeof(D3D11_VIEWPORT)); pImpl->m_ViewPort.Height = pImpl->m_ShadowMapDimension; pImpl->m_ViewPort.Width = pImpl->m_ShadowMapDimension; pImpl->m_ViewPort.MinDepth = 0.f; pImpl->m_ViewPort.MaxDepth = 1.f; } catch (...){ throw; } }
//------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage ) { if ( !srcImage.pixels || !destImage.pixels ) return E_INVALIDARG; if ( srcImage.width != destImage.width || srcImage.height != destImage.height || srcImage.width != m_width || srcImage.height != m_height || srcImage.format != m_srcformat || destImage.format != m_bcformat ) { return E_UNEXPECTED; } //--- Create input texture -------------------------------------------------------- auto pDevice = m_device.Get(); if ( !pDevice ) return E_POINTER; // We need to avoid the hardware doing additional colorspace conversion DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat; ScopedObject<ID3D11Texture2D> sourceTex; { D3D11_TEXTURE2D_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.Width = static_cast<UINT>( srcImage.width ); desc.Height = static_cast<UINT>( srcImage.height ); desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = inputFormat; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = srcImage.pixels; initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch ); initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch ); HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() ); if ( FAILED(hr) ) { return hr; } } ScopedObject<ID3D11ShaderResourceView> sourceSRV; { D3D11_SHADER_RESOURCE_VIEW_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.Texture2D.MipLevels = 1; desc.Format = inputFormat; desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } //--- Compress using DirectCompute ------------------------------------------------ bool isbc7 = false; switch( m_bcformat ) { case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: break; case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM: case DXGI_FORMAT_BC7_UNORM_SRGB: isbc7 = true; break; default: return E_UNEXPECTED; } const UINT MAX_BLOCK_BATCH = 64; auto pContext = m_context.Get(); if ( !pContext ) return E_UNEXPECTED; size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 ); size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 ); UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks ); UINT num_blocks = num_total_blocks; int start_block_id = 0; while (num_blocks > 0) { UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH ); UINT uThreadGroupCount = n; { D3D11_MAPPED_SUBRESOURCE mapped; HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped ); if ( FAILED(hr) ) return hr; ConstantsBC6HBC7 param; param.tex_width = static_cast<UINT>( srcImage.width ); param.num_block_x = static_cast<UINT>( xblocks ); param.format = m_bcformat; param.mode_id = 0; param.start_block_id = start_block_id; param.num_total_blocks = num_total_blocks; param.alpha_weight = m_alphaWeight; memcpy( mapped.pData, ¶m, sizeof( param ) ); pContext->Unmap( m_constBuffer.Get(), 0 ); } if ( isbc7 ) { //--- BC7 ----------------------------------------------------------------- ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr }; RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(), m_err1UAV.Get(), std::max<UINT>(uThreadGroupCount / 4, 1) ); for ( UINT i = 0; i < 3; ++i ) { static const UINT modes[] = { 1, 3, 7 }; { D3D11_MAPPED_SUBRESOURCE mapped; HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped ); if ( FAILED(hr) ) { ResetContext( pContext ); return hr; } ConstantsBC6HBC7 param; param.tex_width = static_cast<UINT>( srcImage.width ); param.num_block_x = static_cast<UINT>( xblocks ); param.format = m_bcformat; param.mode_id = modes[i]; param.start_block_id = start_block_id; param.num_total_blocks = num_total_blocks; param.alpha_weight = m_alphaWeight; memcpy( mapped.pData, ¶m, sizeof( param ) ); pContext->Unmap( m_constBuffer.Get(), 0 ); } pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get(); RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(), (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount ); } for ( UINT i = 0; i < 2; ++i ) { static const UINT modes[] = { 0, 2 }; { D3D11_MAPPED_SUBRESOURCE mapped; HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped ); if ( FAILED(hr) ) { ResetContext( pContext ); return hr; } ConstantsBC6HBC7 param; param.tex_width = static_cast<UINT>( srcImage.width ); param.num_block_x = static_cast<UINT>( xblocks ); param.format = m_bcformat; param.mode_id = modes[i]; param.start_block_id = start_block_id; param.num_total_blocks = num_total_blocks; param.alpha_weight = m_alphaWeight; memcpy( mapped.pData, ¶m, sizeof( param ) ); pContext->Unmap( m_constBuffer.Get(), 0 ); } pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get(); RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(), (i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount ); } pSRVs[1] = m_err2SRV.Get(); RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(), m_outputUAV.Get(), std::max<UINT>(uThreadGroupCount / 4, 1) ); } else { //--- BC6H ---------------------------------------------------------------- ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr }; RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(), m_err1UAV.Get(), std::max<UINT>(uThreadGroupCount / 4, 1) ); for ( UINT i = 0; i < 10; ++i ) { { D3D11_MAPPED_SUBRESOURCE mapped; HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped ); if ( FAILED(hr) ) { ResetContext( pContext ); return hr; } ConstantsBC6HBC7 param; param.tex_width = static_cast<UINT>( srcImage.width ); param.num_block_x = static_cast<UINT>( xblocks ); param.format = m_bcformat; param.mode_id = i; param.start_block_id = start_block_id; param.num_total_blocks = num_total_blocks; memcpy( mapped.pData, ¶m, sizeof( param ) ); pContext->Unmap( m_constBuffer.Get(), 0 ); } pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get(); RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(), (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>(uThreadGroupCount / 2, 1) ); } pSRVs[1] = m_err1SRV.Get(); RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(), m_outputUAV.Get(), std::max<UINT>(uThreadGroupCount / 2, 1) ); } start_block_id += n; num_blocks -= n; } ResetContext( pContext ); //--- Copy output texture back to CPU --------------------------------------------- pContext->CopyResource( m_outputCPU.Get(), m_output.Get() ); D3D11_MAPPED_SUBRESOURCE mapped; HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped ); if ( SUCCEEDED(hr) ) { const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData ); uint8_t *pDest = destImage.pixels; size_t pitch = xblocks * sizeof( BufferBC6HBC7 ); size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 ); for( size_t h = 0; h < rows; ++h ) { memcpy( pDest, pSrc, destImage.rowPitch ); pSrc += pitch; pDest += destImage.rowPitch; } pContext->Unmap( m_outputCPU.Get(), 0 ); } return hr; }
/** * Callback to draw things in world space. ***/ void OSVR_DirectMode::DrawWorld(void* userData, osvr::renderkit::GraphicsLibrary cLibrary, osvr::renderkit::RenderBuffer cBuffers, osvr::renderkit::OSVR_ViewportDescription sViewport, OSVR_PoseState pose, osvr::renderkit::OSVR_ProjectionMatrix sProjection, OSVR_TimeValue deadline) { static int nEye = 0; static float fAspect = 1.0f; // Make sure our pointers are filled in correctly. The config file selects // the graphics library to use, and may not match our needs. if (cLibrary.D3D11 == nullptr) { std::cerr << "SetupDisplay: No D3D11 GraphicsLibrary" << std::endl; return; } if (cBuffers.D3D11 == nullptr) { std::cerr << "SetupDisplay: No D3D11 RenderBuffer" << std::endl; return; } // auto pcContext = cLibrary.D3D11->context; auto pcDevice = cLibrary.D3D11->device; auto pcContext = cLibrary.D3D11->context; // create all bool bool bAllCreated = true; // create vertex shader if (!m_pcVertexShader11) { if (FAILED(Create2DVertexShader(pcDevice, &m_pcVertexShader11, &m_pcVertexLayout11))) { OutputDebugString(L"FAILED"); bAllCreated = false; } } // create pixel shader... if (!m_pcPixelShader11) { if (FAILED(CreatePixelShaderEffect(pcDevice, &m_pcPixelShader11, PixelShaderTechnique::FullscreenGammaCorrection))) bAllCreated = false; } // Create vertex buffer if (!m_pcVertexBuffer11) { if (FAILED(CreateFullScreenVertexBuffer(pcDevice, &m_pcVertexBuffer11))) bAllCreated = false; } // create constant buffer if (!m_pcConstantBufferDirect11) { if (FAILED(CreateMatrixConstantBuffer(pcDevice, &m_pcConstantBufferDirect11))) bAllCreated = false; } // sampler ? if (!m_pcSamplerState) { bAllCreated = false; } if ((bAllCreated) && (m_sStereoTextureViews.m_ppcTexView11[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); // get orthographic matrix from projection and normalize it by its width (since we use a fullscreen shader here) float afProjectionD3D[16]; osvr::renderkit::OSVR_Projection_to_D3D(afProjectionD3D, sProjection); D3DXMATRIX sProj(afProjectionD3D); // due to the aspect ratio (90° horizontal, 90° vertical) of the HDK we adjust the screen by // the height, not by the width... in this case we need to set a higher FOV by following formular: // V = 2 * arctan( tan(H / 2) * aspectratio ) - so we get V 90° and H 121° sProj.m[0][0] = sProj.m[0][0] * fAspect; // < incorporate game screen aspect ratio; sProj.m[0][1] = 0.0f; sProj.m[0][3] = sProj.m[0][2]; sProj.m[0][2] = 0.0f; sProj.m[1][0] = 0.0f; sProj.m[1][1] = sProj.m[1][1]; sProj.m[1][3] = sProj.m[1][2]; sProj.m[1][2] = 0.0f; sProj.m[2][0] = 0.0f; sProj.m[2][1] = 0.0f; sProj.m[2][2] = 1.0f; // 1.0f here... fullscreen shader ! sProj.m[2][3] = 0.0f; sProj.m[3][0] = 0.0f; sProj.m[3][1] = 0.0f; sProj.m[3][2] = 0.0f; sProj.m[3][3] = 1.0f; // zoom out ? if (m_pbZoomOut) { if (*m_pbZoomOut) { sProj.m[0][0] /= 2.0f; sProj.m[1][1] /= 2.0f; } } // Set constant buffer, first update it... scale and translate the left and right image 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); // texture connected ? if ((m_sStereoTextureViews.m_ppcTexView11[nEye]) && (*m_sStereoTextureViews.m_ppcTexView11[nEye])) { if (m_eMethod == OSVR_DirectModeMethods::OSVR_D3D11_use_Game_Device) { // set texture, sampler state pcContext->PSSetShaderResources(0, 1, m_sStereoTextureViews.m_ppcTexView11[nEye]); pcContext->PSSetSamplers(0, 1, &m_pcSamplerState); } else { ID3D11Resource* pcResource = nullptr; (*m_sStereoTextureViews.m_ppcTexView11[nEye])->GetResource(&pcResource); if (!m_sStereoTextureCopies.m_pcTex11Copy[nEye]) { // get the description and create the copy texture D3D11_TEXTURE2D_DESC sDesc; ((ID3D11Texture2D*)pcResource)->GetDesc(&sDesc); sDesc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; sDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; if (FAILED(((ID3D11Device*)m_pcGameDevice)->CreateTexture2D(&sDesc, NULL, (ID3D11Texture2D**)&m_sStereoTextureCopies.m_pcTex11Copy[nEye]))) { OutputDebugString(L"StereoSplitterDX10 : Failed to create twin texture !"); return; } // aspect ratio fAspect = (float)sDesc.Width / (float)sDesc.Height; // TODO !! DX9 // DX10 !! // get shared handle IDXGIResource* pcDXGIResource(NULL); m_sStereoTextureCopies.m_pcTex11Copy[nEye]->QueryInterface(__uuidof(IDXGIResource), (void**)&pcDXGIResource); HANDLE sharedHandle; if (pcDXGIResource) { pcDXGIResource->GetSharedHandle(&sharedHandle); pcDXGIResource->Release(); } else OutputDebugString(L"Failed to query IDXGIResource."); // open the shared handle with the temporary device ID3D11Resource* pcResourceShared; pcDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Resource), (void**)(&pcResourceShared)); if (pcResourceShared) { pcResourceShared->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&m_sStereoFrameTextures.m_pcFrameTexture[nEye])); pcResourceShared->Release(); } else OutputDebugString(L"Could not open shared resource."); // create shader resource view if (m_sStereoFrameTextures.m_pcFrameTexture[nEye]) { D3D11_SHADER_RESOURCE_VIEW_DESC sDescSRV; ZeroMemory(&sDescSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); sDescSRV.Format = sDesc.Format; sDescSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; sDescSRV.Texture2D.MostDetailedMip = 0; sDescSRV.Texture2D.MipLevels = 1; if (FAILED(pcDevice->CreateShaderResourceView(m_sStereoFrameTextures.m_pcFrameTexture[nEye], &sDescSRV, &m_sSteroFrameTextureSRViews.m_pcFrameTextureSRView[nEye]))) OutputDebugString(L"Failed to create shader resource view."); } else OutputDebugString(L"No Texture available."); } else { // copy the frame tex to shared texture m_pcGameDeviceContext->CopyResource(m_sStereoTextureCopies.m_pcTex11Copy[nEye], pcResource); if (pcResource) pcResource->Release(); // set texture, sampler state pcContext->PSSetShaderResources(0, 1, &m_sSteroFrameTextureSRViews.m_pcFrameTextureSRView[nEye]); pcContext->PSSetSamplers(0, 1, &m_pcSamplerState); } } } // set shaders pcContext->VSSetShader(m_pcVertexShader11, 0, 0); pcContext->PSSetShader(m_pcPixelShader11, 0, 0); // Render a triangle pcContext->Draw(6, 0); // switch eye for next call nEye = !nEye; } }
//------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight ) { if ( !width || !height || alphaWeight < 0.f ) return E_INVALIDARG; #ifdef _M_X64 if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif m_width = width; m_height = height; size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 ); size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 ); size_t num_blocks = xblocks * yblocks; switch( format ) { // BC6H GPU compressor takes RGBAF32 as input case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT; break; // BC7 GPU compressor takes RGBA32 as input case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM: m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM; break; case DXGI_FORMAT_BC7_UNORM_SRGB: m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; break; default: m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN; return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } m_bcformat = format; auto pDevice = m_device.Get(); if ( !pDevice ) return E_POINTER; // Create structured buffers size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 ); { D3D11_BUFFER_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; desc.Usage = D3D11_USAGE_DEFAULT; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; desc.StructureByteStride = sizeof( BufferBC6HBC7 ); desc.ByteWidth = static_cast<UINT>( bufferSize ); HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } // Create staging output buffer { D3D11_BUFFER_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.ByteWidth = static_cast<UINT>( bufferSize ); HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } // Create constant buffer { D3D11_BUFFER_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.ByteWidth = sizeof( ConstantsBC6HBC7 ); HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } // Create shader resource views { D3D11_SHADER_RESOURCE_VIEW_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.Buffer.NumElements = static_cast<UINT>( num_blocks ); desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } // Create unordered access views { D3D11_UNORDERED_ACCESS_VIEW_DESC desc; memset( &desc, 0, sizeof(desc) ); desc.Buffer.NumElements = static_cast<UINT>( num_blocks ); desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() ); if ( FAILED(hr) ) { return hr; } } return S_OK; }
Texture* Texture::createFromData(const sSize& size, const unsigned char* in_pData, bool in_generateMipmaps) { ID3D11Texture2D* pTexture = NULL; ID3D11ShaderResourceView* pTextureView = NULL; auto pRet = new Texture(); // Manually generate mip levels bool allowMipMaps = true; UINT w2 = 1; UINT h2 = 1; while (w2 < (UINT)size.x) w2 *= 2; if (size.x != w2) allowMipMaps = false; while (h2 < (UINT)size.y) h2 *= 2; if (size.y != h2) allowMipMaps = false; unsigned char* pMipMaps = NULL; int mipLevels = 1; D3D11_SUBRESOURCE_DATA* mipsData = NULL; allowMipMaps = allowMipMaps && in_generateMipmaps; if (allowMipMaps) { UINT biggest = std::max<>(w2, h2); UINT w2t = w2; UINT h2t = h2; UINT totalSize = w2t * h2t * 4; while (!(w2t == 1 && h2t == 1)) { ++mipLevels; w2t /= 2; if (w2t < 1) w2t = 1; h2t /= 2; if (h2t < 1) h2t = 1; totalSize += w2t * h2t * 4; } pMipMaps = new byte[totalSize]; memcpy(pMipMaps, in_pData, size.x * size.y * 4); mipsData = new D3D11_SUBRESOURCE_DATA[mipLevels]; w2t = w2; h2t = h2; totalSize = 0; int mipTarget = mipLevels; mipLevels = 0; byte* prev; byte* cur; while (mipLevels != mipTarget) { prev = pMipMaps + totalSize; mipsData[mipLevels].pSysMem = prev; mipsData[mipLevels].SysMemPitch = w2t * 4; mipsData[mipLevels].SysMemSlicePitch = 0; totalSize += w2t * h2t * 4; cur = pMipMaps + totalSize; w2t /= 2; if (w2t < 1) w2t = 1; h2t /= 2; if (h2t < 1) h2t = 1; ++mipLevels; if (mipLevels == mipTarget) break; int accum; // Generate the mips int multX = w2 / w2t; int multY = h2 / h2t; for (UINT y = 0; y < h2t; ++y) { for (UINT x = 0; x < w2t; ++x) { for (UINT k = 0; k < 4; ++k) { accum = 0; accum += prev[(y * multY * w2 + x * multX) * 4 + k]; accum += prev[(y * multY * w2 + (x + multX / 2) * multX) * 4 + k]; accum += prev[((y + multY / 2) * multY * w2 + x * multX) * 4 + k]; accum += prev[((y + multY / 2) * multY * w2 + (x + multX / 2) * multX) * 4 + k]; cur[(y * w2t + x) * 4 + k] = accum / 4; } } } w2 = w2t; h2 = h2t; } } D3D11_TEXTURE2D_DESC desc; desc.Width = size.x; desc.Height = size.y; desc.MipLevels = mipLevels; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA data; data.pSysMem = (pMipMaps) ? pMipMaps : in_pData; data.SysMemPitch = size.x * 4; data.SysMemSlicePitch = 0; auto pDevice = ORenderer->getDevice(); auto ret = pDevice->CreateTexture2D(&desc, (mipsData) ? mipsData : &data, &pTexture); assert(ret == S_OK); ret = pDevice->CreateShaderResourceView(pTexture, NULL, &pTextureView); assert(ret == S_OK); pTexture->Release(); if (pMipMaps) delete[] pMipMaps; if (mipsData) delete[] mipsData; pRet->m_size = size; pRet->m_pTextureView = pTextureView; return pRet; }