RTV overhaul to fix binding an RT with a specific depth/mip level

d3d11
Caleb Cornett 2024-02-09 15:28:08 -06:00 committed by cosmonaut
parent 0f2aacbae9
commit 92f344d2f6
1 changed files with 145 additions and 97 deletions

View File

@ -355,13 +355,24 @@ static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *create
/* Structs */ /* Structs */
typedef struct D3D11TargetView
{
ID3D11View *view; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */
uint32_t level;
uint32_t depth;
uint32_t layer;
} D3D11TargetView;
typedef struct D3D11Texture typedef struct D3D11Texture
{ {
/* D3D Handles */ /* D3D Handles */
ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */
ID3D11ShaderResourceView *shaderView; ID3D11ShaderResourceView *shaderView;
ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ ID3D11UnorderedAccessView *unorderedAccessView; /* FIXME: This needs to be a dynamic array! */
ID3D11UnorderedAccessView *unorderedAccessView;
D3D11TargetView *targetViews;
uint32_t targetViewCount;
uint32_t targetViewCapacity;
/* Basic Info */ /* Basic Info */
Refresh_TextureFormat format; Refresh_TextureFormat format;
@ -370,6 +381,7 @@ typedef struct D3D11Texture
uint32_t depth; uint32_t depth;
uint32_t levelCount; uint32_t levelCount;
uint8_t isCube; uint8_t isCube;
uint8_t isRenderTarget;
} D3D11Texture; } D3D11Texture;
typedef struct D3D11SwapchainData typedef struct D3D11SwapchainData
@ -1120,6 +1132,8 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout(
return result; return result;
} }
/* Pipeline Creation */
static Refresh_ComputePipeline* D3D11_CreateComputePipeline( static Refresh_ComputePipeline* D3D11_CreateComputePipeline(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ComputeShaderInfo *computeShaderInfo Refresh_ComputeShaderInfo *computeShaderInfo
@ -1336,6 +1350,8 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline(
return (Refresh_GraphicsPipeline*) pipeline; return (Refresh_GraphicsPipeline*) pipeline;
} }
/* Resource Creation */
static Refresh_Sampler* D3D11_CreateSampler( static Refresh_Sampler* D3D11_CreateSampler(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_SamplerStateCreateInfo *samplerStateCreateInfo Refresh_SamplerStateCreateInfo *samplerStateCreateInfo
@ -1377,7 +1393,6 @@ static Refresh_Sampler* D3D11_CreateSampler(
); );
ERROR_CHECK_RETURN("Could not create sampler state", NULL); ERROR_CHECK_RETURN("Could not create sampler state", NULL);
/* FIXME: Is there even a point to having a D3D11Sampler struct if it's just a wrapper? */
d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler)); d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler));
d3d11Sampler->handle = samplerStateHandle; d3d11Sampler->handle = samplerStateHandle;
@ -1412,17 +1427,15 @@ static Refresh_Texture* D3D11_CreateTexture(
Refresh_TextureCreateInfo *textureCreateInfo Refresh_TextureCreateInfo *textureCreateInfo
) { ) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11Renderer *renderer = (D3D11Renderer*) driverData;
uint8_t isSampler, isCompute, isRenderTarget, isDepthStencil; uint8_t isSampler, isCompute, isColorTarget, isDepthStencil;
DXGI_FORMAT format; DXGI_FORMAT format;
ID3D11Resource *textureHandle; ID3D11Resource *textureHandle;
ID3D11ShaderResourceView *srv = NULL; ID3D11ShaderResourceView *srv = NULL;
ID3D11RenderTargetView *rtv = NULL;
ID3D11DepthStencilView *dsv = NULL;
ID3D11UnorderedAccessView *uav = NULL; ID3D11UnorderedAccessView *uav = NULL;
D3D11Texture *d3d11Texture; D3D11Texture *d3d11Texture;
HRESULT res; HRESULT res;
isRenderTarget = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT; isColorTarget = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT;
isDepthStencil = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT; isDepthStencil = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT;
isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT; isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT;
isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT;
@ -1445,7 +1458,7 @@ static Refresh_Texture* D3D11_CreateTexture(
{ {
desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
} }
if (isRenderTarget) if (isColorTarget)
{ {
desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET; desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET;
} }
@ -1458,7 +1471,7 @@ static Refresh_Texture* D3D11_CreateTexture(
desc2D.CPUAccessFlags = 0; desc2D.CPUAccessFlags = 0;
desc2D.Format = format; desc2D.Format = format;
desc2D.MipLevels = textureCreateInfo->levelCount; desc2D.MipLevels = textureCreateInfo->levelCount;
desc2D.MiscFlags = isRenderTarget ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; desc2D.MiscFlags = 0;
desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount];
desc2D.SampleDesc.Quality = 0; desc2D.SampleDesc.Quality = 0;
desc2D.Usage = D3D11_USAGE_DEFAULT; desc2D.Usage = D3D11_USAGE_DEFAULT;
@ -1529,40 +1542,6 @@ static Refresh_Texture* D3D11_CreateTexture(
return NULL; return NULL;
} }
} }
/* Create the RTV, if applicable */
if (isRenderTarget)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = format;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; /* FIXME: MSAA? */
rtvDesc.Texture2D.MipSlice = 0; /* FIXME */
res = ID3D11Device_CreateRenderTargetView(
renderer->device,
textureHandle,
&rtvDesc,
&rtv
);
if (FAILED(res))
{
ID3D11Resource_Release(textureHandle);
if (srv != NULL)
{
ID3D11ShaderResourceView_Release(srv);
}
if (uav != NULL)
{
ID3D11UnorderedAccessView_Release(uav);
}
D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 2D texture", res);
return NULL;
}
}
else if (isDepthStencil)
{
NOT_IMPLEMENTED
}
} }
else else
{ {
@ -1581,7 +1560,7 @@ static Refresh_Texture* D3D11_CreateTexture(
{ {
desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
} }
if (isRenderTarget) if (isColorTarget)
{ {
desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET; desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET;
} }
@ -1650,38 +1629,6 @@ static Refresh_Texture* D3D11_CreateTexture(
return NULL; return NULL;
} }
} }
/* Create the RTV, if applicable */
if (isRenderTarget)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = format;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = 0; /* FIXME */
rtvDesc.Texture3D.FirstWSlice = 0; /* FIXME */
rtvDesc.Texture3D.WSize = -1; /* FIXME */
res = ID3D11Device_CreateRenderTargetView(
renderer->device,
textureHandle,
&rtvDesc,
&rtv
);
if (FAILED(res))
{
ID3D11Resource_Release(textureHandle);
if (srv != NULL)
{
ID3D11ShaderResourceView_Release(srv);
}
if (uav != NULL)
{
ID3D11UnorderedAccessView_Release(uav);
}
D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 3D texture", res);
return NULL;
}
}
} }
d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture));
@ -1692,9 +1639,23 @@ static Refresh_Texture* D3D11_CreateTexture(
d3d11Texture->depth = textureCreateInfo->depth; d3d11Texture->depth = textureCreateInfo->depth;
d3d11Texture->levelCount = textureCreateInfo->levelCount; d3d11Texture->levelCount = textureCreateInfo->levelCount;
d3d11Texture->isCube = textureCreateInfo->isCube; d3d11Texture->isCube = textureCreateInfo->isCube;
d3d11Texture->targetView = isRenderTarget ? (ID3D11View*) rtv : (ID3D11View*) dsv; d3d11Texture->isRenderTarget = isColorTarget | isDepthStencil;
d3d11Texture->shaderView = srv; d3d11Texture->shaderView = srv;
d3d11Texture->unorderedAccessView = uav; d3d11Texture->unorderedAccessView = uav;
d3d11Texture->targetViewCount = 0;
if (d3d11Texture->isRenderTarget)
{
d3d11Texture->targetViewCapacity = d3d11Texture->isCube ? 6 : 1;
d3d11Texture->targetViews = SDL_malloc(
sizeof(ID3D11RenderTargetView) * d3d11Texture->targetViewCount
);
}
else
{
d3d11Texture->targetViewCapacity = 0;
d3d11Texture->targetViews = NULL;
}
return (Refresh_Texture*) d3d11Texture; return (Refresh_Texture*) d3d11Texture;
} }
@ -2286,9 +2247,13 @@ static void D3D11_QueueDestroyTexture(
{ {
ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView); ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView);
} }
if (d3d11Texture->targetView) if (d3d11Texture->targetViewCount > 0)
{ {
ID3D11View_Release(d3d11Texture->targetView); for (uint32_t i = 0; i < d3d11Texture->targetViewCount; i += 1)
{
ID3D11View_Release(d3d11Texture->targetViews[i].view);
}
SDL_free(d3d11Texture->targetViews);
} }
ID3D11Resource_Release(d3d11Texture->handle); ID3D11Resource_Release(d3d11Texture->handle);
@ -2529,6 +2494,80 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer(
return (Refresh_CommandBuffer*) commandBuffer; return (Refresh_CommandBuffer*) commandBuffer;
} }
static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV(
D3D11Renderer *renderer,
Refresh_ColorAttachmentInfo *info
) {
D3D11Texture *texture = (D3D11Texture*) info->texture;
D3D11TargetView *targetView;
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
ID3D11RenderTargetView *rtv;
HRESULT res;
/* Does this target already exist? */
for (uint32_t i = 0; i < texture->targetViewCount; i += 1)
{
targetView = &texture->targetViews[i];
if ( targetView->depth == info->depth &&
targetView->layer == info->layer &&
targetView->level == info->level )
{
return (ID3D11RenderTargetView*) targetView->view;
}
}
/* Let's create a new RTV! */
rtvDesc.Format = RefreshToD3D11_TextureFormat[texture->format];
if (texture->isCube)
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */
rtvDesc.Texture2DArray.ArraySize = 6;
rtvDesc.Texture2DArray.FirstArraySlice = 0;
rtvDesc.Texture2DArray.MipSlice = info->level;
}
else if (texture->depth > 1)
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = info->level;
rtvDesc.Texture3D.FirstWSlice = info->depth;
rtvDesc.Texture3D.WSize = 1;
}
else
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = info->level;
}
res = ID3D11Device_CreateRenderTargetView(
renderer->device,
texture->handle,
&rtvDesc,
&rtv
);
ERROR_CHECK_RETURN("Could not create RTV!", NULL);
/* Create the D3D11TargetView to wrap our new RTV */
if (texture->targetViewCount == texture->targetViewCapacity)
{
texture->targetViewCapacity *= 2;
texture->targetViews = SDL_realloc(
texture->targetViews,
sizeof(D3D11TargetView) * texture->targetViewCapacity
);
}
targetView = &texture->targetViews[texture->targetViewCount];
targetView->depth = info->depth;
targetView->layer = info->layer;
targetView->level = info->level;
targetView->view = (ID3D11View*) rtv;
texture->targetViewCount += 1;
return rtv;
}
static void D3D11_BeginRenderPass( static void D3D11_BeginRenderPass(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer, Refresh_CommandBuffer *commandBuffer,
@ -2543,11 +2582,6 @@ static void D3D11_BeginRenderPass(
D3D11_VIEWPORT viewport; D3D11_VIEWPORT viewport;
D3D11_RECT scissorRect; D3D11_RECT scissorRect;
/* FIXME:
* We need to unbind the RT textures on the Refresh side
* if they're bound for sampling on the command buffer!
*/
/* Clear the bound RTs for the current command buffer */ /* Clear the bound RTs for the current command buffer */
for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
{ {
@ -2558,15 +2592,19 @@ static void D3D11_BeginRenderPass(
/* Get RTVs for the color attachments */ /* Get RTVs for the color attachments */
for (uint32_t i = 0; i < colorAttachmentCount; i += 1) for (uint32_t i = 0; i < colorAttachmentCount; i += 1)
{ {
/* FIXME: Cube RTs */ d3d11CommandBuffer->rtViews[i] = D3D11_INTERNAL_FetchRTV(
renderer,
d3d11CommandBuffer->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView; &colorAttachmentInfos[i]
);
} }
/* Get the DSV for the depth stencil attachment, if applicable */ /* Get the DSV for the depth stencil attachment, if applicable */
if (depthStencilAttachmentInfo != NULL) if (depthStencilAttachmentInfo != NULL)
{ {
d3d11CommandBuffer->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView; NOT_IMPLEMENTED
//d3d11CommandBuffer->dsView = D3D11_INTERNAL_FetchDSV(
// &depthStencilAttachmentInfo
//);
} }
/* Actually set the RTs */ /* Actually set the RTs */
@ -2589,7 +2627,7 @@ static void D3D11_BeginRenderPass(
ID3D11DeviceContext_ClearRenderTargetView( ID3D11DeviceContext_ClearRenderTargetView(
d3d11CommandBuffer->context, d3d11CommandBuffer->context,
(ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView, d3d11CommandBuffer->rtViews[i],
clearColors clearColors
); );
} }
@ -2611,7 +2649,7 @@ static void D3D11_BeginRenderPass(
{ {
ID3D11DeviceContext_ClearDepthStencilView( ID3D11DeviceContext_ClearDepthStencilView(
d3d11CommandBuffer->context, d3d11CommandBuffer->context,
(ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView, d3d11CommandBuffer->dsView,
dsClearFlags, dsClearFlags,
depthStencilAttachmentInfo->depthStencilClearValue.depth, depthStencilAttachmentInfo->depthStencilClearValue.depth,
(uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil
@ -2932,6 +2970,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture(
ID3D11Texture2D *swapchainTexture; ID3D11Texture2D *swapchainTexture;
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
D3D11_TEXTURE2D_DESC textureDesc; D3D11_TEXTURE2D_DESC textureDesc;
ID3D11RenderTargetView *rtv;
HRESULT res; HRESULT res;
/* Clear all the texture data */ /* Clear all the texture data */
@ -2955,7 +2994,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture(
renderer->device, renderer->device,
(ID3D11Resource*) swapchainTexture, (ID3D11Resource*) swapchainTexture,
&rtvDesc, &rtvDesc,
(ID3D11RenderTargetView**) &pTexture->targetView &rtv
); );
if (FAILED(res)) if (FAILED(res))
{ {
@ -2964,16 +3003,22 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture(
return 0; return 0;
} }
/* Fill out the rest of the texture struct */ /* Fill out the texture struct */
pTexture->handle = NULL; pTexture->handle = NULL; /* The texture does not "own" the swapchain texture, and it can change dynamically. */
pTexture->shaderView = NULL; pTexture->shaderView = NULL;
pTexture->depth = 1; pTexture->unorderedAccessView = NULL;
pTexture->isCube = 0; pTexture->targetViewCapacity = 1;
pTexture->targetViewCount = 1;
pTexture->targetViews = SDL_calloc(1, sizeof(D3D11TargetView));
pTexture->targetViews[0].view = (ID3D11View*) rtv;
ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc);
pTexture->levelCount = textureDesc.MipLevels; pTexture->levelCount = textureDesc.MipLevels;
pTexture->width = textureDesc.Width; pTexture->width = textureDesc.Width;
pTexture->height = textureDesc.Height; pTexture->height = textureDesc.Height;
pTexture->depth = 1;
pTexture->isCube = 0;
pTexture->isRenderTarget = 1;
/* Cleanup */ /* Cleanup */
ID3D11Texture2D_Release(swapchainTexture); ID3D11Texture2D_Release(swapchainTexture);
@ -3096,7 +3141,8 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain(
HRESULT res; HRESULT res;
/* Release the old RTV */ /* Release the old RTV */
ID3D11RenderTargetView_Release(swapchainData->texture.targetView); ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view);
SDL_free(swapchainData->texture.targetViews);
/* Resize the swapchain */ /* Resize the swapchain */
res = IDXGISwapChain_ResizeBuffers( res = IDXGISwapChain_ResizeBuffers(
@ -3135,7 +3181,9 @@ static void D3D11_INTERNAL_DestroySwapchain(
return; return;
} }
ID3D11RenderTargetView_Release(swapchainData->texture.targetView); ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view);
SDL_free(swapchainData->texture.targetViews);
IDXGISwapChain_Release(swapchainData->swapchain); IDXGISwapChain_Release(swapchainData->swapchain);
windowData->swapchainData = NULL; windowData->swapchainData = NULL;