FragmentShaderHlsl::FragmentShaderHlsl(Direct3D11Renderer &direct3D11Renderer, const char *sourceCode) : IFragmentShader(direct3D11Renderer), mD3D11PixelShader(nullptr) { // Create the Direct3D 11 binary large object for the pixel shader ID3DBlob *d3dBlob = static_cast<ShaderLanguageHlsl*>(direct3D11Renderer.getShaderLanguage())->loadShader("ps_5_0", sourceCode, nullptr); if (nullptr != d3dBlob) { // Create the Direct3D 11 pixel shader direct3D11Renderer.getD3D11Device()->CreatePixelShader(d3dBlob->GetBufferPointer(), d3dBlob->GetBufferSize(), nullptr, &mD3D11PixelShader); // Release the Direct3D 11 shader binary large object d3dBlob->Release(); } // Don't assign a default name to the resource for debugging purposes, Direct3D 11 automatically sets a decent default name }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] FragmentShaderHlsl::FragmentShaderHlsl(Direct3D11Renderer &direct3D11Renderer, const uint8_t *bytecode, uint32_t numberOfBytes) : IFragmentShader(direct3D11Renderer), mD3D11PixelShader(nullptr) { // Create the Direct3D 11 vertex shader direct3D11Renderer.getD3D11Device()->CreatePixelShader(bytecode, numberOfBytes, nullptr, &mD3D11PixelShader); // Don't assign a default name to the resource for debugging purposes, Direct3D 11 automatically sets a decent default name }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] DepthStencilState::DepthStencilState(Direct3D11Renderer &direct3D11Renderer, const Renderer::DepthStencilState &depthStencilState) : IDepthStencilState(direct3D11Renderer), mD3D11DepthStencilState(nullptr) { // Create the Direct3D 11 depth stencil state // -> "Renderer::DepthStencilState" maps directly to Direct3D 10 & 11, do not change it direct3D11Renderer.getD3D11Device()->CreateDepthStencilState(reinterpret_cast<const D3D11_DEPTH_STENCIL_DESC*>(&depthStencilState), &mD3D11DepthStencilState); // Assign a default name to the resource for debugging purposes #ifndef DIRECT3D11RENDERER_NO_DEBUG setDebugName("Depth stencil state"); #endif }
/** * @brief * Constructor */ RasterizerState::RasterizerState(Direct3D11Renderer &direct3D11Renderer, const Renderer::RasterizerState &rasterizerState) : IRasterizerState(direct3D11Renderer), mD3D11RasterizerState(nullptr) { // Create the Direct3D 11 rasterizer state // -> "Renderer::RasterizerState" maps directly to Direct3D 10 & 11, do not change it direct3D11Renderer.getD3D11Device()->CreateRasterizerState(reinterpret_cast<const D3D11_RASTERIZER_DESC*>(&rasterizerState), &mD3D11RasterizerState); // Assign a default name to the resource for debugging purposes #ifndef DIRECT3D11RENDERER_NO_DEBUG setDebugName("Rasterizer state"); #endif }
/** * @brief * Constructor */ TessellationControlShaderHlsl::TessellationControlShaderHlsl(Direct3D11Renderer &direct3D11Renderer, const char *sourceCode) : TessellationControlShader(direct3D11Renderer), mD3D11HullShader(nullptr) { // Create the Direct3D 11 binary large object for the hull shader ID3DBlob *d3dBlob = ShaderLanguageHlsl::loadShader("hs_5_0", sourceCode, nullptr); if (nullptr != d3dBlob) { // Create the Direct3D 11 hull shader direct3D11Renderer.getD3D11Device()->CreateHullShader(d3dBlob->GetBufferPointer(), d3dBlob->GetBufferSize(), nullptr, &mD3D11HullShader); // Release the Direct3D 11 shader binary large object d3dBlob->Release(); } // Don't assign a default name to the resource for debugging purposes, Direct3D 11 automatically sets a decent default name }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] VertexArray::VertexArray(Direct3D11Renderer &direct3D11Renderer, uint32_t numberOfVertexBuffers, const Renderer::VertexArrayVertexBuffer *vertexBuffers, IndexBuffer *indexBuffer) : IVertexArray(direct3D11Renderer), mD3D11DeviceContext(direct3D11Renderer.getD3D11DeviceContext()), mIndexBuffer(indexBuffer), mNumberOfSlots(numberOfVertexBuffers), mD3D11Buffers(nullptr), mStrides(nullptr), mOffsets(nullptr), mVertexBuffers(nullptr) { // Acquire our Direct3D 11 device context reference mD3D11DeviceContext->AddRef(); // Add a reference to the given index buffer if (nullptr != mIndexBuffer) { mIndexBuffer->addReference(); } // Add a reference to the used vertex buffers if (mNumberOfSlots > 0) { mD3D11Buffers = new ID3D11Buffer*[mNumberOfSlots]; mStrides = new UINT[mNumberOfSlots]; mOffsets = new UINT[mNumberOfSlots]; mVertexBuffers = new VertexBuffer*[mNumberOfSlots]; // Vertex buffer offset is not supported by OpenGL, so our renderer API doesn't support it either memset(mOffsets, 0, sizeof(uint32_t) * mNumberOfSlots); // Loop through all vertex buffers ID3D11Buffer** currentD3D11Buffer = mD3D11Buffers; UINT* currentStride = mStrides; VertexBuffer **currentVertexBuffer = mVertexBuffers; const Renderer::VertexArrayVertexBuffer *vertexBufferEnd = vertexBuffers + mNumberOfSlots; for (const Renderer::VertexArrayVertexBuffer *vertexBuffer = vertexBuffers; vertexBuffer < vertexBufferEnd; ++vertexBuffer, ++currentD3D11Buffer, ++currentStride, ++currentVertexBuffer) { // TODO(co) Add security check: Is the given resource one of the currently used renderer? *currentStride = vertexBuffer->strideInBytes; *currentVertexBuffer = static_cast<VertexBuffer*>(vertexBuffer->vertexBuffer); *currentD3D11Buffer = (*currentVertexBuffer)->getD3D11Buffer(); (*currentVertexBuffer)->addReference(); } } }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] SwapChain::SwapChain(Direct3D11Renderer &direct3D11Renderer, handle nativeWindowHandle) : ISwapChain(direct3D11Renderer), mDxgiSwapChain(nullptr), mD3D11RenderTargetView(nullptr), mD3D11DepthStencilView(nullptr) { // Get the Direct3D 11 device instance ID3D11Device *d3d11Device = direct3D11Renderer.getD3D11Device(); // Get the native window handle const HWND hWnd = reinterpret_cast<HWND>(nativeWindowHandle); // Get a DXGI factory instance IDXGIFactory1 *dxgiFactory1 = nullptr; { IDXGIDevice *dxgiDevice = nullptr; IDXGIAdapter *dxgiAdapter = nullptr; d3d11Device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); dxgiDevice->GetAdapter(&dxgiAdapter); dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory1)); dxgiAdapter->Release(); dxgiDevice->Release(); } // Get the width and height of the given native window and ensure they are never ever zero // -> See "getSafeWidthAndHeight()"-method comments for details long width = 1; long height = 1; { // Get the client rectangle of the given native window RECT rect; ::GetClientRect(hWnd, &rect); // Get the width and height... width = rect.right - rect.left; height = rect.bottom - rect.top; // ... and ensure that none of them is ever zero if (width < 1) { width = 1; } if (height < 1) { height = 1; } } // Create the swap chain DXGI_SWAP_CHAIN_DESC dxgiSwapChainDesc = {}; dxgiSwapChainDesc.BufferCount = 1; dxgiSwapChainDesc.BufferDesc.Width = static_cast<UINT>(width); dxgiSwapChainDesc.BufferDesc.Height = static_cast<UINT>(height); dxgiSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; dxgiSwapChainDesc.BufferDesc.RefreshRate.Numerator = 60; dxgiSwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; dxgiSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; dxgiSwapChainDesc.OutputWindow = hWnd; dxgiSwapChainDesc.SampleDesc.Count = 1; dxgiSwapChainDesc.SampleDesc.Quality = 0; dxgiSwapChainDesc.Windowed = TRUE; dxgiFactory1->CreateSwapChain(d3d11Device, &dxgiSwapChainDesc, &mDxgiSwapChain); // Disable alt-return for automatic fullscreen state change // -> We handle this manually to have more control over it dxgiFactory1->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); // Release our DXGI factory dxgiFactory1->Release(); // Create the Direct3D 11 views if (nullptr != mDxgiSwapChain) { createDirect3D11Views(); } // Assign a default name to the resource for debugging purposes #ifndef DIRECT3D11RENDERER_NO_DEBUG setDebugName("Swap chain"); #endif }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] Framebuffer::Framebuffer(Direct3D11Renderer &direct3D11Renderer, uint32_t numberOfColorTextures, Renderer::ITexture **colorTextures, Renderer::ITexture *depthStencilTexture) : IFramebuffer(direct3D11Renderer), mNumberOfColorTextures(numberOfColorTextures), mColorTextures(nullptr), // Set below mDepthStencilTexture(depthStencilTexture), mWidth(UINT_MAX), mHeight(UINT_MAX), mD3D11RenderTargetViews(nullptr), mD3D11DepthStencilView(nullptr) { // The Direct3D 11 "ID3D11DeviceContext::OMSetRenderTargets method"-documentation at MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ff476464%28v=vs.85%29.aspx // says the following about the framebuffer width and height when using multiple render targets // "All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types)" // So, in here I use the smallest width and height as the size of the framebuffer and let Direct3D 11 handle the rest regarding errors. // Add a reference to the used color textures if (mNumberOfColorTextures > 0) { mColorTextures = new Renderer::ITexture*[mNumberOfColorTextures]; mD3D11RenderTargetViews = new ID3D11RenderTargetView*[mNumberOfColorTextures]; // Loop through all color textures ID3D11RenderTargetView **d3d11RenderTargetView = mD3D11RenderTargetViews; Renderer::ITexture **colorTexturesEnd = mColorTextures + mNumberOfColorTextures; for (Renderer::ITexture **colorTexture = mColorTextures; colorTexture < colorTexturesEnd; ++colorTexture, ++colorTextures, ++d3d11RenderTargetView) { // Valid entry? if (nullptr != *colorTextures) { // TODO(co) Add security check: Is the given resource one of the currently used renderer? *colorTexture = *colorTextures; (*colorTexture)->addReference(); // Evaluate the color texture type switch ((*colorTexture)->getResourceType()) { case Renderer::ResourceType::TEXTURE_2D: { // Update the framebuffer width and height if required Texture2D *texture2D = static_cast<Texture2D*>(*colorTexture); if (mWidth > texture2D->getWidth()) { mWidth = texture2D->getWidth(); } if (mHeight > texture2D->getHeight()) { mHeight = texture2D->getHeight(); } // Create the Direct3D 11 render target view instance D3D11_RENDER_TARGET_VIEW_DESC d3d11RenderTargetViewDesc = {}; d3d11RenderTargetViewDesc.Format = static_cast<DXGI_FORMAT>(Mapping::getDirect3D11Format(texture2D->getTextureFormat())); d3d11RenderTargetViewDesc.ViewDimension = (texture2D->getNumberOfMultisamples() > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D; d3d11RenderTargetViewDesc.Texture2D.MipSlice = 0; direct3D11Renderer.getD3D11Device()->CreateRenderTargetView(texture2D->getD3D11Texture2D(), &d3d11RenderTargetViewDesc, d3d11RenderTargetView); break; } case Renderer::ResourceType::ROOT_SIGNATURE: case Renderer::ResourceType::PROGRAM: case Renderer::ResourceType::VERTEX_ARRAY: case Renderer::ResourceType::SWAP_CHAIN: case Renderer::ResourceType::FRAMEBUFFER: case Renderer::ResourceType::INDEX_BUFFER: case Renderer::ResourceType::VERTEX_BUFFER: case Renderer::ResourceType::UNIFORM_BUFFER: case Renderer::ResourceType::TEXTURE_BUFFER: case Renderer::ResourceType::INDIRECT_BUFFER: case Renderer::ResourceType::TEXTURE_2D_ARRAY: case Renderer::ResourceType::PIPELINE_STATE: case Renderer::ResourceType::SAMPLER_STATE: case Renderer::ResourceType::VERTEX_SHADER: case Renderer::ResourceType::TESSELLATION_CONTROL_SHADER: case Renderer::ResourceType::TESSELLATION_EVALUATION_SHADER: case Renderer::ResourceType::GEOMETRY_SHADER: case Renderer::ResourceType::FRAGMENT_SHADER: default: RENDERER_OUTPUT_DEBUG_PRINTF("Direct3D 11 error: The type of the given color texture at index %d is not supported", colorTexture - colorTextures) *d3d11RenderTargetView = nullptr; break; } } else { *colorTexture = nullptr; *d3d11RenderTargetView = nullptr; } } } // Add a reference to the used depth stencil texture if (nullptr != mDepthStencilTexture) { mDepthStencilTexture->addReference(); // Evaluate the depth stencil texture type switch (mDepthStencilTexture->getResourceType()) { case Renderer::ResourceType::TEXTURE_2D: { // Update the framebuffer width and height if required Texture2D *texture2D = static_cast<Texture2D*>(mDepthStencilTexture); if (mWidth > texture2D->getWidth()) { mWidth = texture2D->getWidth(); } if (mHeight > texture2D->getHeight()) { mHeight = texture2D->getHeight(); } // Create the Direct3D 11 render target view instance D3D11_DEPTH_STENCIL_VIEW_DESC d3d11DepthStencilViewDesc = {}; d3d11DepthStencilViewDesc.Format = static_cast<DXGI_FORMAT>(Mapping::getDirect3D11Format(texture2D->getTextureFormat())); d3d11DepthStencilViewDesc.ViewDimension = (texture2D->getNumberOfMultisamples() > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; d3d11DepthStencilViewDesc.Texture2D.MipSlice = 0; direct3D11Renderer.getD3D11Device()->CreateDepthStencilView(texture2D->getD3D11Texture2D(), &d3d11DepthStencilViewDesc, &mD3D11DepthStencilView); break; } case Renderer::ResourceType::ROOT_SIGNATURE: case Renderer::ResourceType::PROGRAM: case Renderer::ResourceType::VERTEX_ARRAY: case Renderer::ResourceType::SWAP_CHAIN: case Renderer::ResourceType::FRAMEBUFFER: case Renderer::ResourceType::INDEX_BUFFER: case Renderer::ResourceType::VERTEX_BUFFER: case Renderer::ResourceType::UNIFORM_BUFFER: case Renderer::ResourceType::TEXTURE_BUFFER: case Renderer::ResourceType::INDIRECT_BUFFER: case Renderer::ResourceType::TEXTURE_2D_ARRAY: case Renderer::ResourceType::PIPELINE_STATE: case Renderer::ResourceType::SAMPLER_STATE: case Renderer::ResourceType::VERTEX_SHADER: case Renderer::ResourceType::TESSELLATION_CONTROL_SHADER: case Renderer::ResourceType::TESSELLATION_EVALUATION_SHADER: case Renderer::ResourceType::GEOMETRY_SHADER: case Renderer::ResourceType::FRAGMENT_SHADER: default: RENDERER_OUTPUT_DEBUG_STRING("Direct3D 11 error: The type of the given depth stencil texture is not supported") break; } }