From a9b32f6ac74b2cf08ac48826fd67e3b5f9115c0d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 10 Mar 2022 00:30:28 -0500 Subject: [PATCH] Implemented Clear, fleshed out D3D11Texture, added depth-stencil clear support in BeginRenderPass --- src/Refresh_Driver_D3D11.c | 266 ++++++++++++++++++++++++++++--------- 1 file changed, 202 insertions(+), 64 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 5d8c0d0..c6d2c95 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -235,7 +235,39 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = typedef struct D3D11Texture { - ID3D11RenderTargetView *rtv; + /* D3D Handles */ + ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ + ID3D11ShaderResourceView *shaderView; + + /* Basic Info */ + int32_t levelCount; + uint8_t isRenderTarget; + + /* Dimensions */ + #define REFRESH_D3D11_RENDERTARGET_2D 0 + #define REFRESH_D3D11_RENDERTARGET_3D 1 + #define REFRESH_D3D11_RENDERTARGET_CUBE 2 + uint8_t rtType; + REFRESHNAMELESS union + { + struct + { + int32_t width; + int32_t height; + ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ + } twod; + struct + { + int32_t width; + int32_t height; + int32_t depth; + } threed; + struct + { + int32_t size; + ID3D11RenderTargetView **rtViews; + } cube; + }; } D3D11Texture; typedef struct D3D11SwapchainData @@ -247,9 +279,17 @@ typedef struct D3D11SwapchainData typedef struct D3D11CommandBuffer { + /* D3D11 Object References */ ID3D11DeviceContext *context; ID3D11CommandList *commandList; D3D11SwapchainData *swapchainData; + + /* Render Pass */ + uint8_t numBoundColorAttachments; + ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS]; + ID3D11DepthStencilView* dsView; + + /* State */ SDL_threadID threadID; uint8_t recording; uint8_t fixed; @@ -349,6 +389,57 @@ static void D3D11_INTERNAL_LogError( /* Swapchain Management */ +static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( + D3D11Renderer *renderer, + D3D11Texture *resultTexture, + IDXGISwapChain *swapchain +) { + ID3D11Texture2D *swapchainTexture; + D3D11_RENDER_TARGET_VIEW_DESC swapchainViewDesc; + D3D11_TEXTURE2D_DESC textureDesc; + HRESULT res; + + /* Clear all the texture data. */ + SDL_memset(resultTexture, 0, sizeof(D3D11Texture)); + + /* Grab the buffer from the swapchain */ + res = IDXGISwapChain_GetBuffer( + swapchain, + 0, + &D3D_IID_ID3D11Texture2D, + (void**) &swapchainTexture + ); + ERROR_CHECK_RETURN("Could not get buffer from swapchain", 0); + + /* Create the RTV for the swapchain */ + swapchainViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchainViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + swapchainViewDesc.Texture2D.MipSlice = 0; + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + (ID3D11Resource*) swapchainTexture, + &swapchainViewDesc, + (ID3D11RenderTargetView**) &resultTexture->twod.targetView + ); + ERROR_CHECK_RETURN("Swapchain RT view creation failed", 0); + + /* Fill out the rest of the texture struct */ + resultTexture->handle = NULL; /* FIXME: Is drawing the backbuffer to an offscreen RT allowed? If so we'll need to fill in this and shaderView. */ + resultTexture->shaderView = NULL; + resultTexture->isRenderTarget = 1; + + ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); + resultTexture->levelCount = textureDesc.MipLevels; + resultTexture->twod.width = textureDesc.Width; + resultTexture->twod.height = textureDesc.Height; + + /* Cleanup */ + ID3D11Texture2D_Release(swapchainTexture); + + return 1; +} + static uint8_t D3D11_INTERNAL_CreateSwapchain( D3D11Renderer *renderer, void *windowHandle @@ -360,8 +451,6 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( D3D11SwapchainData *swapchainData; SDL_SysWMinfo info; HWND dxgiHandle; - ID3D11Texture2D *swapchainTexture; - D3D11_RENDER_TARGET_VIEW_DESC swapchainViewDesc; HRESULT res; SDL_VERSION(&info.version); @@ -437,7 +526,8 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); swapchainData->swapchain = swapchain; swapchainData->windowHandle = windowHandle; - swapchainData->refreshTexture.rtv = NULL; + + /* Add the swapchain data to the window data */ SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_SWAPCHAIN_DATA, swapchainData); if (renderer->swapchainDataCount >= renderer->swapchainDataCapacity) { @@ -450,44 +540,23 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( renderer->swapchainDatas[renderer->swapchainDataCount] = swapchainData; renderer->swapchainDataCount += 1; - /* Create the RTV for the swapchain */ - swapchainViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - swapchainViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - swapchainViewDesc.Texture2D.MipSlice = 0; - - res = IDXGISwapChain_GetBuffer( - swapchainData->swapchain, - 0, - &D3D_IID_ID3D11Texture2D, - (void**) &swapchainTexture + /* Create the Refresh-side texture for the swapchain */ + return D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + &swapchainData->refreshTexture, + swapchainData->swapchain ); - ERROR_CHECK_RETURN("Could not get buffer from swapchain", 0); - - res = ID3D11Device_CreateRenderTargetView( - renderer->device, - (ID3D11Resource*) swapchainTexture, - &swapchainViewDesc, - &swapchainData->refreshTexture.rtv - ); - ERROR_CHECK_RETURN("Swapchain RT view creation failed", 0); - - /* Cleanup */ - ID3D11Texture2D_Release(swapchainTexture); - - return 1; } static uint8_t D3D11_INTERNAL_ResizeSwapchain( D3D11Renderer *renderer, D3D11SwapchainData *swapchainData ) { - ID3D11Texture2D *swapchainTexture; - D3D11_RENDER_TARGET_VIEW_DESC swapchainViewDesc; int w, h; HRESULT res; /* Release the old RTV */ - ID3D11RenderTargetView_Release(swapchainData->refreshTexture.rtv); + ID3D11RenderTargetView_Release(swapchainData->refreshTexture.twod.targetView); /* Resize the swapchain */ SDL_GetWindowSize((SDL_Window*) swapchainData->windowHandle, &w, &h); @@ -501,31 +570,12 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( ); ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0); - /* Recreate the RTV using the new swapchain buffer */ - swapchainViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - swapchainViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - swapchainViewDesc.Texture2D.MipSlice = 0; - - res = IDXGISwapChain_GetBuffer( - swapchainData->swapchain, - 0, - &D3D_IID_ID3D11Texture2D, - &swapchainTexture + /* Create the Refresh-side texture for the swapchain */ + return D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + &swapchainData->refreshTexture, + swapchainData->swapchain ); - ERROR_CHECK_RETURN("Could not get buffer from swapchain", 0); - - res = ID3D11Device_CreateRenderTargetView( - renderer->device, - (ID3D11Resource*) swapchainTexture, - &swapchainViewDesc, - &swapchainData->refreshTexture.rtv - ); - ERROR_CHECK_RETURN("Could not create render target view for swapchain", 0); - - /* Cleanup */ - ID3D11Texture2D_Release(swapchainTexture); - - return 1; } /* Quit */ @@ -554,7 +604,7 @@ static void D3D11_DestroyDevice( /* Release swapchain */ for (i = 0; i < renderer->swapchainDataCount; i += 1) { - ID3D11RenderTargetView_Release(renderer->swapchainDatas[i]->refreshTexture.rtv); + ID3D11RenderTargetView_Release(renderer->swapchainDatas[i]->refreshTexture.twod.targetView); IDXGISwapChain_Release(renderer->swapchainDatas[i]->swapchain); SDL_free(renderer->swapchainDatas[i]); } @@ -588,7 +638,54 @@ static void D3D11_Clear( uint32_t colorCount, Refresh_DepthStencilValue depthStencil ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11_CLEAR_FLAG dsClearFlags; + float clearColors[4]; + uint32_t i; + + /* FIXME: What should we do about clearRect? */ + /* FIXME: Do we need to use colorCount or is it always the number of bound RTs? */ + + if (options & REFRESH_CLEAROPTIONS_COLOR) + { + /* Clear color attachments */ + for (i = 0; i < cmdbuf->numBoundColorAttachments; i += 1) + { + clearColors[0] = colors[i].x; + clearColors[1] = colors[i].y; + clearColors[2] = colors[i].z; + clearColors[3] = colors[i].w; + + ID3D11DeviceContext_ClearRenderTargetView( + cmdbuf->context, + cmdbuf->rtViews[i], + clearColors + ); + } + } + + /* Check which of depth/stencil need to be cleared (if either) */ + dsClearFlags = 0; + if (options & REFRESH_CLEAROPTIONS_DEPTH) + { + dsClearFlags |= D3D11_CLEAR_DEPTH; + } + if (options & REFRESH_CLEAROPTIONS_STENCIL) + { + dsClearFlags |= D3D11_CLEAR_STENCIL; + } + + if (dsClearFlags != 0) + { + ID3D11DeviceContext_ClearDepthStencilView( + cmdbuf->context, + cmdbuf->dsView, + dsClearFlags, + depthStencil.depth, + (uint8_t) depthStencil.stencil + ); + } } static void D3D11_DrawInstancedPrimitives( @@ -855,26 +952,37 @@ static void D3D11_BeginRenderPass( D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; D3D11Texture *texture; float clearColors[4]; - ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS]; - ID3D11DepthStencilView *dsView = NULL; + D3D11_CLEAR_FLAG dsClearFlags; D3D11_VIEWPORT viewports[1]; D3D11_RECT scissorRects[1]; uint8_t i; + /* Clear the list of attachments for the command buffer */ + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + { + cmdbuf->rtViews[i] = NULL; + } + cmdbuf->dsView = NULL; + /* Get the RTVs for each color attachment. */ + cmdbuf->numBoundColorAttachments = colorAttachmentCount; for (i = 0; i < colorAttachmentCount; i += 1) { - rtViews[i] = ((D3D11Texture*) colorAttachmentInfos[i].texture)->rtv; + cmdbuf->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->twod.targetView; } - /* FIXME: Get the DSV for the depth stencil attachment, if one exists! */ + /* Get the DSV for the depth stencil attachment, if one exists */ + if (depthStencilAttachmentInfo != NULL) + { + cmdbuf->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView; + } /* Set the render targets. */ ID3D11DeviceContext_OMSetRenderTargets( cmdbuf->context, colorAttachmentCount, - rtViews, - NULL + cmdbuf->rtViews, + cmdbuf->dsView ); /* Perform load ops on those render targets. */ @@ -891,12 +999,36 @@ static void D3D11_BeginRenderPass( ID3D11DeviceContext_ClearRenderTargetView( cmdbuf->context, - texture->rtv, + (ID3D11RenderTargetView*) texture->twod.targetView, clearColors ); } } + if (cmdbuf->dsView != NULL) + { + dsClearFlags = 0; + if (depthStencilAttachmentInfo->loadOp == REFRESH_LOADOP_CLEAR) + { + dsClearFlags |= D3D11_CLEAR_DEPTH; + } + if (depthStencilAttachmentInfo->stencilLoadOp == REFRESH_LOADOP_CLEAR) + { + dsClearFlags |= D3D11_CLEAR_STENCIL; + } + + if (dsClearFlags != 0) + { + ID3D11DeviceContext_ClearDepthStencilView( + cmdbuf->context, + (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView, + dsClearFlags, + depthStencilAttachmentInfo->depthStencilClearValue.depth, + (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil + ); + } + } + /* FIXME: Set viewport and scissor state */ /* FIXME: What should we do with render area? */ @@ -1039,6 +1171,12 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->fixed = fixed; commandBuffer->swapchainData = NULL; commandBuffer->commandList = NULL; + commandBuffer->dsView = NULL; + commandBuffer->numBoundColorAttachments = 0; + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + { + commandBuffer->rtViews[i] = NULL; + } SDL_UnlockMutex(renderer->commandBufferAcquisitionMutex);