GPU: Rework MSAA (#10859)

This commit is contained in:
Caleb Cornett 2024-09-16 12:19:09 -05:00 committed by GitHub
parent e59344ad46
commit 9416917353
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 775 additions and 1110 deletions

View File

@ -282,8 +282,10 @@ typedef enum SDL_GPULoadOp
*/
typedef enum SDL_GPUStoreOp
{
SDL_GPU_STOREOP_STORE, /**< The contents generated during the render pass will be written to memory. */
SDL_GPU_STOREOP_DONT_CARE /**< The contents generated during the render pass are not needed and may be discarded. The contents will be undefined. */
SDL_GPU_STOREOP_STORE, /**< The contents generated during the render pass will be written to memory. */
SDL_GPU_STOREOP_DONT_CARE, /**< The contents generated during the render pass are not needed and may be discarded. The contents will be undefined. */
SDL_GPU_STOREOP_RESOLVE, /**< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture may then be discarded and will be undefined. */
SDL_GPU_STOREOP_RESOLVE_AND_STORE /**< The multisample contents generated during the render pass will be resolved to a non-multisample texture. The contents in the multisample texture will be written to memory. */
} SDL_GPUStoreOp;
/**
@ -1499,7 +1501,8 @@ typedef struct SDL_GPUComputePipelineCreateInfo
* The load_op field determines what is done with the texture at the beginning
* of the render pass.
*
* - LOAD: Loads the data currently in the texture.
* - LOAD: Loads the data currently in the texture. Not recommended for
* multisample textures as it requires significant memory bandwidth.
* - CLEAR: Clears the texture to a single color.
* - DONT_CARE: The driver will do whatever it wants with the texture memory.
* This is a good option if you know that every single pixel will be touched
@ -1508,9 +1511,16 @@ typedef struct SDL_GPUComputePipelineCreateInfo
* The store_op field determines what is done with the color results of the
* render pass.
*
* - STORE: Stores the results of the render pass in the texture.
* - STORE: Stores the results of the render pass in the texture. Not recommended
* for multisample textures as it requires significant memory bandwidth.
* - DONT_CARE: The driver will do whatever it wants with the texture memory.
* This is often a good option for depth/stencil textures.
* - RESOLVE: Resolves a multisample texture into resolve_texture, which must have
* a sample count of 1. Then the driver may discard the multisample texture memory.
* This is the most performant method of resolving a multisample target.
* - RESOLVE_AND_STORE: Resolves a multisample texture into the resolve_texture,
* which must have a sample count of 1. Then the driver stores the multisample
* texture's contents. Not recommended as it requires significant memory bandwidth.
*
* \since This struct is available since SDL 3.0.0
*
@ -1518,16 +1528,19 @@ typedef struct SDL_GPUComputePipelineCreateInfo
*/
typedef struct SDL_GPUColorTargetInfo
{
SDL_GPUTexture *texture; /**< The texture that will be used as a color target by a render pass. */
Uint32 mip_level; /**< The mip level to use as a color target. */
Uint32 layer_or_depth_plane; /**< The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. */
SDL_FColor clear_color; /**< The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. */
SDL_GPULoadOp load_op; /**< What is done with the contents of the color target at the beginning of the render pass. */
SDL_GPUStoreOp store_op; /**< What is done with the results of the render pass. */
SDL_bool cycle; /**< SDL_TRUE cycles the texture if the texture is bound and load_op is not LOAD */
SDL_GPUTexture *texture; /**< The texture that will be used as a color target by a render pass. */
Uint32 mip_level; /**< The mip level to use as a color target. */
Uint32 layer_or_depth_plane; /**< The layer index or depth plane to use as a color target. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. */
SDL_FColor clear_color; /**< The color to clear the color target to at the start of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. */
SDL_GPULoadOp load_op; /**< What is done with the contents of the color target at the beginning of the render pass. */
SDL_GPUStoreOp store_op; /**< What is done with the results of the render pass. */
SDL_GPUTexture *resolve_texture; /**< The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used. */
Uint32 resolve_mip_level; /**< The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. */
Uint32 resolve_layer; /**< The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. */
SDL_bool cycle; /**< SDL_TRUE cycles the texture if the texture is bound and load_op is not LOAD */
SDL_bool cycle_resolve_texture; /**< SDL_TRUE cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used. */
Uint8 padding1;
Uint8 padding2;
Uint8 padding3;
} SDL_GPUColorTargetInfo;
/**
@ -1568,6 +1581,8 @@ typedef struct SDL_GPUColorTargetInfo
* This is often a good option for depth/stencil textures that don't need to
* be reused again.
*
* Note that depth/stencil targets do not support multisample resolves.
*
* \since This struct is available since SDL 3.0.0
*
* \sa SDL_BeginGPURenderPass

View File

@ -867,6 +867,13 @@ SDL_GPUTexture *SDL_CreateGPUTexture(
SDL_assert_release(!"For any texture: usage cannot contain both GRAPHICS_STORAGE_READ and SAMPLER");
failed = true;
}
if (createinfo->sample_count > 1 && (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER |
SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ |
SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ |
SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE))) {
SDL_assert_release(!"For multisample textures: usage cannot contain SAMPLER or STORAGE flags");
failed = true;
}
if (IsDepthFormat(createinfo->format) && (createinfo->usage & ~(SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER))) {
SDL_assert_release(!"For depth textures: usage cannot contain any flags except for DEPTH_STENCIL_TARGET and SAMPLER");
failed = true;
@ -945,16 +952,10 @@ SDL_GPUTexture *SDL_CreateGPUTexture(
SDL_assert_release(!"For array textures: usage must not contain DEPTH_STENCIL_TARGET");
failed = true;
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"For array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1");
failed = true;
}
} else {
// 2D Texture Validation
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) {
SDL_assert_release(!"For 2D textures: if sample_count is >= SDL_GPU_SAMPLECOUNT_1, then num_levels must be 1");
failed = true;
}
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) {
SDL_assert_release(!"For 2D multisample textures: num_levels must be 1");
failed = true;
}
if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_2D, createinfo->usage)) {
SDL_assert_release(!"For 2D textures: the format is unsupported for the given usage");
@ -1347,13 +1348,50 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
CHECK_ANY_PASS_IN_PROGRESS("Cannot begin render pass during another pass!", NULL)
for (Uint32 i = 0; i < num_color_targets; i += 1) {
TextureCommonHeader *textureHeader = (TextureCommonHeader *)color_target_infos[i].texture;
if (color_target_infos[i].cycle && color_target_infos[i].load_op == SDL_GPU_LOADOP_LOAD) {
SDL_assert_release(!"Cannot cycle color target when load op is LOAD!");
}
if (color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE || color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
if (color_target_infos[i].resolve_texture == NULL) {
SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but resolve_texture is NULL!");
} else {
TextureCommonHeader *resolveTextureHeader = (TextureCommonHeader *)color_target_infos[i].resolve_texture;
if (textureHeader->info.sample_count == SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but texture is not multisample!");
}
if (resolveTextureHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"Resolve texture must have a sample count of 1!");
}
if (resolveTextureHeader->info.format != textureHeader->info.format) {
SDL_assert_release(!"Resolve texture must have the same format as its corresponding color target!");
}
if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) {
SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!");
}
}
}
}
if (depth_stencil_target_info != NULL && depth_stencil_target_info->cycle && (depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD || depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD)) {
SDL_assert_release(!"Cannot cycle depth target when load op or stencil load op is LOAD!");
if (depth_stencil_target_info != NULL) {
TextureCommonHeader *textureHeader = (TextureCommonHeader *)depth_stencil_target_info->texture;
if (!(textureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
SDL_assert_release(!"Depth target must have been created with the DEPTH_STENCIL_TARGET usage flag!");
}
if (depth_stencil_target_info->cycle && (depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD || depth_stencil_target_info->stencil_load_op == SDL_GPU_LOADOP_LOAD)) {
SDL_assert_release(!"Cannot cycle depth target when load op or stencil load op is LOAD!");
}
if (depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE ||
depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE ||
depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE ||
depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
SDL_assert_release(!"RESOLVE store ops are not supported for depth-stencil targets!");
}
}
}
@ -2397,6 +2435,10 @@ void SDL_BlitGPUTexture(
SDL_assert_release(!"Blit destination texture must be non-NULL");
return; // attempting to proceed will crash
}
if (srcHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"Blit source texture must have a sample count of 1");
failed = true;
}
if ((srcHeader->info.usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) == 0) {
SDL_assert_release(!"Blit source texture must be created with the SAMPLER usage flag");
failed = true;

View File

@ -438,9 +438,6 @@ typedef struct D3D11TextureSubresource
ID3D11UnorderedAccessView *uav; // NULL if not a storage texture
ID3D11DepthStencilView *depthStencilTargetView; // NULL if not a depth stencil target
ID3D11Resource *msaaHandle; // NULL if not using MSAA
ID3D11RenderTargetView *msaaTargetView; // NULL if not an MSAA color target
} D3D11TextureSubresource;
struct D3D11Texture
@ -637,12 +634,8 @@ typedef struct D3D11CommandBuffer
D3D11GraphicsPipeline *graphicsPipeline;
Uint8 stencilRef;
SDL_FColor blendConstants;
// Render Pass MSAA resolve
D3D11Texture *colorTargetResolveTexture[MAX_COLOR_TARGET_BINDINGS];
Uint32 colorTargetResolveSubresourceIndex[MAX_COLOR_TARGET_BINDINGS];
ID3D11Resource *colorTargetMsaaHandle[MAX_COLOR_TARGET_BINDINGS];
DXGI_FORMAT colorTargetMsaaFormat[MAX_COLOR_TARGET_BINDINGS];
D3D11TextureSubresource *colorTargetSubresources[MAX_COLOR_TARGET_BINDINGS];
D3D11TextureSubresource *colorResolveSubresources[MAX_COLOR_TARGET_BINDINGS];
// Compute Pass
D3D11ComputePipeline *computePipeline;
@ -1090,14 +1083,6 @@ static void D3D11_INTERNAL_DestroyTexture(D3D11Texture *d3d11Texture)
}
for (Uint32 subresourceIndex = 0; subresourceIndex < d3d11Texture->subresourceCount; subresourceIndex += 1) {
if (d3d11Texture->subresources[subresourceIndex].msaaHandle != NULL) {
ID3D11Resource_Release(d3d11Texture->subresources[subresourceIndex].msaaHandle);
}
if (d3d11Texture->subresources[subresourceIndex].msaaTargetView != NULL) {
ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].msaaTargetView);
}
if (d3d11Texture->subresources[subresourceIndex].colorTargetViews != NULL) {
for (Uint32 depthIndex = 0; depthIndex < d3d11Texture->subresources[subresourceIndex].depth; depthIndex += 1) {
ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
@ -1933,8 +1918,8 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
desc2D.Format = format;
desc2D.MipLevels = createInfo->num_levels;
desc2D.MiscFlags = 0;
desc2D.SampleDesc.Count = 1;
desc2D.SampleDesc.Quality = 0;
desc2D.SampleDesc.Count = SDLToD3D11_SampleCount[createInfo->sample_count];
desc2D.SampleDesc.Quality = isMultisample ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0;
desc2D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
@ -2067,54 +2052,10 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
d3d11Texture->subresources[subresourceIndex].colorTargetViews = NULL;
d3d11Texture->subresources[subresourceIndex].uav = NULL;
d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL;
d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL;
d3d11Texture->subresources[subresourceIndex].msaaTargetView = NULL;
if (isMultisample) {
D3D11_TEXTURE2D_DESC desc2D;
if (isColorTarget) {
desc2D.BindFlags = D3D11_BIND_RENDER_TARGET;
} else if (isDepthStencil) {
desc2D.BindFlags = D3D11_BIND_DEPTH_STENCIL;
}
desc2D.Width = createInfo->width;
desc2D.Height = createInfo->height;
desc2D.ArraySize = 1;
desc2D.CPUAccessFlags = 0;
desc2D.Format = format;
desc2D.MipLevels = 1;
desc2D.MiscFlags = 0;
desc2D.SampleDesc.Count = SDLToD3D11_SampleCount[createInfo->sample_count];
desc2D.SampleDesc.Quality = (UINT)D3D11_STANDARD_MULTISAMPLE_PATTERN;
desc2D.Usage = D3D11_USAGE_DEFAULT;
res = ID3D11Device_CreateTexture2D(
renderer->device,
&desc2D,
NULL,
(ID3D11Texture2D **)&d3d11Texture->subresources[subresourceIndex].msaaHandle);
ERROR_CHECK_RETURN("Could not create MSAA texture!", NULL);
if (!isDepthStencil) {
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = format;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
res = ID3D11Device_CreateRenderTargetView(
renderer->device,
d3d11Texture->subresources[subresourceIndex].msaaHandle,
&rtvDesc,
&d3d11Texture->subresources[subresourceIndex].msaaTargetView);
ERROR_CHECK_RETURN("Could not create MSAA RTV!", NULL);
}
}
if (isDepthStencil) {
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
dsvDesc.Flags = 0;
@ -2127,31 +2068,42 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
res = ID3D11Device_CreateDepthStencilView(
renderer->device,
isMultisample ? d3d11Texture->subresources[subresourceIndex].msaaHandle : d3d11Texture->handle,
d3d11Texture->handle,
&dsvDesc,
&d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
ERROR_CHECK_RETURN("Could not create DSV!", NULL);
} else if (isColorTarget) {
d3d11Texture->subresources[subresourceIndex].colorTargetViews = SDL_calloc(depth, sizeof(ID3D11RenderTargetView *));
for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
if (isMultisample) {
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
} else {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
}
}
res = ID3D11Device_CreateRenderTargetView(
@ -3238,10 +3190,8 @@ static SDL_GPUCommandBuffer *D3D11_AcquireCommandBuffer(
commandBuffer->blendConstants.a = 1.0f;
commandBuffer->computePipeline = NULL;
for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
commandBuffer->colorTargetResolveTexture[i] = NULL;
commandBuffer->colorTargetResolveSubresourceIndex[i] = 0;
commandBuffer->colorTargetMsaaHandle[i] = NULL;
commandBuffer->colorTargetMsaaFormat[i] = DXGI_FORMAT_UNKNOWN;
commandBuffer->colorTargetSubresources[i] = NULL;
commandBuffer->colorResolveSubresources[i] = NULL;
}
for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
@ -3507,10 +3457,8 @@ static void D3D11_BeginRenderPass(
// Clear the bound targets for the current command buffer
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
d3d11CommandBuffer->colorTargetResolveTexture[i] = NULL;
d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = 0;
d3d11CommandBuffer->colorTargetMsaaHandle[i] = NULL;
d3d11CommandBuffer->colorTargetMsaaFormat[i] = DXGI_FORMAT_UNKNOWN;
d3d11CommandBuffer->colorTargetSubresources[i] = NULL;
d3d11CommandBuffer->colorResolveSubresources[i] = NULL;
}
// Set up the new color target bindings
@ -3523,16 +3471,20 @@ static void D3D11_BeginRenderPass(
colorTargetInfos[i].mip_level,
colorTargetInfos[i].cycle);
if (subresource->msaaHandle != NULL) {
d3d11CommandBuffer->colorTargetResolveTexture[i] = subresource->parent;
d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresource->index;
d3d11CommandBuffer->colorTargetMsaaHandle[i] = subresource->msaaHandle;
d3d11CommandBuffer->colorTargetMsaaFormat[i] = SDLToD3D11_TextureFormat[container->header.info.format];
Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
rtvs[i] = subresource->colorTargetViews[rtvIndex];
d3d11CommandBuffer->colorTargetSubresources[i] = subresource;
rtvs[i] = subresource->msaaTargetView;
} else {
Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
rtvs[i] = subresource->colorTargetViews[rtvIndex];
if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
D3D11TextureContainer *resolveContainer = (D3D11TextureContainer *)colorTargetInfos[i].resolve_texture;
D3D11TextureSubresource *resolveSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
renderer,
resolveContainer,
colorTargetInfos[i].resolve_layer,
colorTargetInfos[i].resolve_mip_level,
colorTargetInfos[i].cycle_resolve_texture);
d3d11CommandBuffer->colorResolveSubresources[i] = resolveSubresource;
}
if (colorTargetInfos[i].load_op == SDL_GPU_LOADOP_CLEAR) {
@ -4220,14 +4172,14 @@ static void D3D11_EndRenderPass(
// Resolve MSAA color render targets
for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
if (d3d11CommandBuffer->colorTargetMsaaHandle[i] != NULL) {
if (d3d11CommandBuffer->colorResolveSubresources[i] != NULL) {
ID3D11DeviceContext_ResolveSubresource(
d3d11CommandBuffer->context,
d3d11CommandBuffer->colorTargetResolveTexture[i]->handle,
d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i],
d3d11CommandBuffer->colorTargetMsaaHandle[i],
0,
d3d11CommandBuffer->colorTargetMsaaFormat[i]);
d3d11CommandBuffer->colorResolveSubresources[i]->parent->handle,
d3d11CommandBuffer->colorResolveSubresources[i]->index,
d3d11CommandBuffer->colorTargetSubresources[i]->parent->handle,
d3d11CommandBuffer->colorTargetSubresources[i]->index,
SDLToD3D11_TextureFormat[d3d11CommandBuffer->colorTargetSubresources[i]->parent->container->header.info.format]);
}
}
@ -5083,8 +5035,6 @@ static bool D3D11_INTERNAL_InitializeSwapchainTexture(
return false;
}
// Create container
// Fill out the texture struct
pTexture->handle = NULL; // This will be set in AcquireSwapchainTexture.
pTexture->shaderView = NULL; // We don't allow swapchain texture to be sampled
@ -5095,8 +5045,6 @@ static bool D3D11_INTERNAL_InitializeSwapchainTexture(
pTexture->subresources[0].colorTargetViews[0] = rtv;
pTexture->subresources[0].uav = NULL;
pTexture->subresources[0].depthStencilTargetView = NULL;
pTexture->subresources[0].msaaHandle = NULL;
pTexture->subresources[0].msaaTargetView = NULL;
pTexture->subresources[0].layer = 0;
pTexture->subresources[0].level = 0;
pTexture->subresources[0].depth = 1;

View File

@ -673,8 +673,8 @@ struct D3D12CommandBuffer
Uint32 presentDataCount;
Uint32 presentDataCapacity;
Uint32 colorTargetTextureSubresourceCount;
D3D12TextureSubresource *colorTargetTextureSubresources[MAX_COLOR_TARGET_BINDINGS];
D3D12TextureSubresource *colorTargetSubresources[MAX_COLOR_TARGET_BINDINGS];
D3D12TextureSubresource *colorResolveSubresources[MAX_COLOR_TARGET_BINDINGS];
D3D12TextureSubresource *depthStencilTextureSubresource;
D3D12GraphicsPipeline *currentGraphicsPipeline;
D3D12ComputePipeline *currentComputePipeline;
@ -2619,7 +2619,7 @@ static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
psoDesc.SampleMask = sampleMask;
psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->multisample_state.sample_count];
psoDesc.SampleDesc.Quality = 0;
psoDesc.SampleDesc.Quality = (createinfo->multisample_state.sample_count > SDL_GPU_SAMPLECOUNT_1) ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
psoDesc.DSVFormat = SDLToD3D12_TextureFormat[createinfo->target_info.depth_stencil_format];
psoDesc.NumRenderTargets = createinfo->target_info.num_color_targets;
@ -2787,6 +2787,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
Uint32 layerCount = createinfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : createinfo->layer_count_or_depth;
Uint32 depth = createinfo->type == SDL_GPU_TEXTURETYPE_3D ? createinfo->layer_count_or_depth : 1;
bool isMultisample = createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1;
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
@ -2824,8 +2825,8 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
desc.MipLevels = (UINT16)createinfo->num_levels;
desc.Format = SDLToD3D12_TextureFormat[createinfo->format];
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->sample_count];
desc.SampleDesc.Quality = isMultisample ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // Apparently this is the most efficient choice
desc.Flags = resourceFlags;
} else {
@ -2956,21 +2957,31 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
rtvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
rtvDesc.Texture2DArray.PlaneSlice = 0;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
if (isMultisample) {
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
} else {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
rtvDesc.Texture2D.PlaneSlice = 0;
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
rtvDesc.Texture2DArray.PlaneSlice = 0;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
rtvDesc.Texture2D.PlaneSlice = 0;
}
}
ID3D12Device_CreateRenderTargetView(
@ -2992,8 +3003,13 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
dsvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
dsvDesc.Flags = (D3D12_DSV_FLAGS)0;
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = levelIndex;
if (isMultisample) {
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;
} else {
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = levelIndex;
}
ID3D12Device_CreateDepthStencilView(
renderer->device,
@ -3886,11 +3902,6 @@ static void D3D12_BeginRenderPass(
if (h < framebufferHeight) {
framebufferHeight = h;
}
if (!(container->header.info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) {
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Color target texture was not designated as a color target!");
return;
}
}
if (depthStencilTargetInfo != NULL) {
@ -3908,12 +3919,6 @@ static void D3D12_BeginRenderPass(
if (h < framebufferHeight) {
framebufferHeight = h;
}
// Fixme:
if (!(container->header.info.usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) {
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Depth stencil target texture was not designated as a depth target!");
return;
}
}
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[MAX_COLOR_TARGET_BINDINGS];
@ -3929,8 +3934,7 @@ static void D3D12_BeginRenderPass(
D3D12_RESOURCE_STATE_RENDER_TARGET);
Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
D3D12_CPU_DESCRIPTOR_HANDLE rtv =
subresource->rtvHandles[rtvIndex].cpuHandle;
D3D12_CPU_DESCRIPTOR_HANDLE rtv = subresource->rtvHandles[rtvIndex].cpuHandle;
if (colorTargetInfos[i].load_op == SDL_GPU_LOADOP_CLEAR) {
float clearColor[4];
@ -3948,12 +3952,24 @@ static void D3D12_BeginRenderPass(
}
rtvs[i] = rtv;
d3d12CommandBuffer->colorTargetTextureSubresources[i] = subresource;
d3d12CommandBuffer->colorTargetSubresources[i] = subresource;
D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, subresource->parent);
}
d3d12CommandBuffer->colorTargetTextureSubresourceCount = numColorTargets;
if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
D3D12TextureContainer *resolveContainer = (D3D12TextureContainer *)colorTargetInfos[i].resolve_texture;
D3D12TextureSubresource *resolveSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
d3d12CommandBuffer,
resolveContainer,
colorTargetInfos[i].resolve_layer,
colorTargetInfos[i].resolve_mip_level,
colorTargetInfos[i].cycle_resolve_texture,
D3D12_RESOURCE_STATE_RESOLVE_DEST);
d3d12CommandBuffer->colorResolveSubresources[i] = resolveSubresource;
D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, resolveSubresource->parent);
}
}
D3D12_CPU_DESCRIPTOR_HANDLE dsv;
if (depthStencilTargetInfo != NULL) {
@ -4780,15 +4796,42 @@ static void D3D12_EndRenderPass(
D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
Uint32 i;
for (i = 0; i < d3d12CommandBuffer->colorTargetTextureSubresourceCount; i += 1) {
D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
d3d12CommandBuffer,
D3D12_RESOURCE_STATE_RENDER_TARGET,
d3d12CommandBuffer->colorTargetTextureSubresources[i]);
for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
if (d3d12CommandBuffer->colorTargetSubresources[i] != NULL) {
if (d3d12CommandBuffer->colorResolveSubresources[i] != NULL) {
// Resolving requires some extra barriers
D3D12_INTERNAL_TextureSubresourceBarrier(
d3d12CommandBuffer,
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
d3d12CommandBuffer->colorTargetSubresources[i]
);
d3d12CommandBuffer->colorTargetTextureSubresources[i] = NULL;
ID3D12GraphicsCommandList_ResolveSubresource(
d3d12CommandBuffer->graphicsCommandList,
d3d12CommandBuffer->colorResolveSubresources[i]->parent->resource,
d3d12CommandBuffer->colorResolveSubresources[i]->index,
d3d12CommandBuffer->colorTargetSubresources[i]->parent->resource,
d3d12CommandBuffer->colorTargetSubresources[i]->index,
SDLToD3D12_TextureFormat[d3d12CommandBuffer->colorTargetSubresources[i]->parent->container->header.info.format]);
D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
d3d12CommandBuffer,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
d3d12CommandBuffer->colorTargetSubresources[i]);
D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
d3d12CommandBuffer,
D3D12_RESOURCE_STATE_RESOLVE_DEST,
d3d12CommandBuffer->colorResolveSubresources[i]);
} else {
D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
d3d12CommandBuffer,
D3D12_RESOURCE_STATE_RENDER_TARGET,
d3d12CommandBuffer->colorTargetSubresources[i]);
}
}
}
d3d12CommandBuffer->colorTargetTextureSubresourceCount = 0;
if (d3d12CommandBuffer->depthStencilTextureSubresource != NULL) {
D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
@ -4809,7 +4852,8 @@ static void D3D12_EndRenderPass(
NULL);
// Reset bind state
SDL_zeroa(d3d12CommandBuffer->colorTargetTextureSubresources);
SDL_zeroa(d3d12CommandBuffer->colorTargetSubresources);
SDL_zeroa(d3d12CommandBuffer->colorResolveSubresources);
d3d12CommandBuffer->depthStencilTextureSubresource = NULL;
SDL_zeroa(d3d12CommandBuffer->vertexBuffers);
@ -6820,8 +6864,8 @@ static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer(
// Set the bind state
commandBuffer->currentGraphicsPipeline = NULL;
SDL_zeroa(commandBuffer->colorTargetTextureSubresources);
commandBuffer->colorTargetTextureSubresourceCount = 0;
SDL_zeroa(commandBuffer->colorTargetSubresources);
SDL_zeroa(commandBuffer->colorResolveSubresources);
commandBuffer->depthStencilTextureSubresource = NULL;
SDL_zeroa(commandBuffer->vertexBuffers);

View File

@ -294,6 +294,13 @@ static MTLLoadAction SDLToMetal_LoadOp[] = {
MTLLoadActionDontCare, // DONT_CARE
};
static MTLStoreAction SDLToMetal_StoreOp[] = {
MTLStoreActionStore,
MTLStoreActionDontCare,
MTLStoreActionMultisampleResolve,
MTLStoreActionStoreAndMultisampleResolve
};
static MTLVertexStepFunction SDLToMetal_StepFunction[] = {
MTLVertexStepFunctionPerVertex,
MTLVertexStepFunctionPerInstance,
@ -323,25 +330,6 @@ static SDL_GPUTextureFormat SwapchainCompositionToFormat[] = {
static CFStringRef SwapchainCompositionToColorSpace[4]; // initialized on device creation
static MTLStoreAction SDLToMetal_StoreOp(
SDL_GPUStoreOp storeOp,
Uint8 isMultisample)
{
if (isMultisample) {
if (storeOp == SDL_GPU_STOREOP_STORE) {
return MTLStoreActionStoreAndMultisampleResolve;
} else {
return MTLStoreActionMultisampleResolve;
}
} else {
if (storeOp == SDL_GPU_STOREOP_STORE) {
return MTLStoreActionStore;
} else {
return MTLStoreActionDontCare;
}
}
};
static MTLColorWriteMask SDLToMetal_ColorWriteMask(
SDL_GPUColorComponentFlags mask)
{
@ -366,7 +354,6 @@ static MTLColorWriteMask SDLToMetal_ColorWriteMask(
typedef struct MetalTexture
{
id<MTLTexture> handle;
id<MTLTexture> msaaHandle;
SDL_AtomicInt referenceCount;
} MetalTexture;
@ -828,7 +815,6 @@ static void METAL_INTERNAL_DestroyTextureContainer(
{
for (Uint32 i = 0; i < container->textureCount; i += 1) {
container->textures[i]->handle = nil;
container->textures[i]->msaaHandle = nil;
SDL_free(container->textures[i]);
}
if (container->debugName != NULL) {
@ -1329,7 +1315,6 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
{
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor new];
id<MTLTexture> texture;
id<MTLTexture> msaaTexture = NULL;
MetalTexture *metalTexture;
textureDescriptor.textureType = SDLToMetal_TextureType[createinfo->type];
@ -1347,7 +1332,7 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
textureDescriptor.height = createinfo->height;
textureDescriptor.depth = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? createinfo->layer_count_or_depth : 1;
textureDescriptor.mipmapLevelCount = createinfo->num_levels;
textureDescriptor.sampleCount = 1;
textureDescriptor.sampleCount = SDLToMetal_SampleCount[createinfo->sample_count];
textureDescriptor.arrayLength =
(createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY)
? createinfo->layer_count_or_depth
@ -1374,22 +1359,8 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
return NULL;
}
// Create the MSAA texture, if needed
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->type == SDL_GPU_TEXTURETYPE_2D) {
textureDescriptor.textureType = MTLTextureType2DMultisample;
textureDescriptor.sampleCount = SDLToMetal_SampleCount[createinfo->sample_count];
textureDescriptor.usage = MTLTextureUsageRenderTarget;
msaaTexture = [renderer->device newTextureWithDescriptor:textureDescriptor];
if (msaaTexture == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create MSAA MTLTexture!");
return NULL;
}
}
metalTexture = (MetalTexture *)SDL_calloc(1, sizeof(MetalTexture));
metalTexture->handle = texture;
metalTexture->msaaHandle = msaaTexture;
SDL_AtomicSet(&metalTexture->referenceCount, 0);
return metalTexture;
}
@ -2189,12 +2160,7 @@ static void METAL_BeginRenderPass(
container,
colorTargetInfos[i].cycle);
if (texture->msaaHandle) {
passDescriptor.colorAttachments[i].texture = texture->msaaHandle;
passDescriptor.colorAttachments[i].resolveTexture = texture->handle;
} else {
passDescriptor.colorAttachments[i].texture = texture->handle;
}
passDescriptor.colorAttachments[i].texture = texture->handle;
passDescriptor.colorAttachments[i].level = colorTargetInfos[i].mip_level;
if (container->header.info.type == SDL_GPU_TEXTURETYPE_3D) {
passDescriptor.colorAttachments[i].depthPlane = colorTargetInfos[i].layer_or_depth_plane;
@ -2207,11 +2173,23 @@ static void METAL_BeginRenderPass(
colorTargetInfos[i].clear_color.b,
colorTargetInfos[i].clear_color.a);
passDescriptor.colorAttachments[i].loadAction = SDLToMetal_LoadOp[colorTargetInfos[i].load_op];
passDescriptor.colorAttachments[i].storeAction = SDLToMetal_StoreOp(
colorTargetInfos[i].store_op,
texture->msaaHandle ? 1 : 0);
passDescriptor.colorAttachments[i].storeAction = SDLToMetal_StoreOp[colorTargetInfos[i].store_op];
METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
MetalTextureContainer *resolveContainer = (MetalTextureContainer *)colorTargetInfos[i].resolve_texture;
MetalTexture *resolveTexture = METAL_INTERNAL_PrepareTextureForWrite(
renderer,
resolveContainer,
colorTargetInfos[i].cycle_resolve_texture);
passDescriptor.colorAttachments[i].resolveTexture = resolveTexture->handle;
passDescriptor.colorAttachments[i].resolveSlice = colorTargetInfos[i].resolve_layer;
passDescriptor.colorAttachments[i].resolveLevel = colorTargetInfos[i].resolve_mip_level;
METAL_INTERNAL_TrackTexture(metalCommandBuffer, resolveTexture);
}
}
if (depthStencilTargetInfo != NULL) {
@ -2221,29 +2199,15 @@ static void METAL_BeginRenderPass(
container,
depthStencilTargetInfo->cycle);
if (texture->msaaHandle) {
passDescriptor.depthAttachment.texture = texture->msaaHandle;
passDescriptor.depthAttachment.resolveTexture = texture->handle;
} else {
passDescriptor.depthAttachment.texture = texture->handle;
}
passDescriptor.depthAttachment.texture = texture->handle;
passDescriptor.depthAttachment.loadAction = SDLToMetal_LoadOp[depthStencilTargetInfo->load_op];
passDescriptor.depthAttachment.storeAction = SDLToMetal_StoreOp(
depthStencilTargetInfo->store_op,
texture->msaaHandle ? 1 : 0);
passDescriptor.depthAttachment.storeAction = SDLToMetal_StoreOp[depthStencilTargetInfo->store_op];
passDescriptor.depthAttachment.clearDepth = depthStencilTargetInfo->clear_depth;
if (IsStencilFormat(container->header.info.format)) {
if (texture->msaaHandle) {
passDescriptor.stencilAttachment.texture = texture->msaaHandle;
passDescriptor.stencilAttachment.resolveTexture = texture->handle;
} else {
passDescriptor.stencilAttachment.texture = texture->handle;
}
passDescriptor.stencilAttachment.loadAction = SDLToMetal_LoadOp[depthStencilTargetInfo->load_op];
passDescriptor.stencilAttachment.storeAction = SDLToMetal_StoreOp(
depthStencilTargetInfo->store_op,
texture->msaaHandle ? 1 : 0);
passDescriptor.stencilAttachment.texture = texture->handle;
passDescriptor.stencilAttachment.loadAction = SDLToMetal_LoadOp[depthStencilTargetInfo->stencil_load_op];
passDescriptor.stencilAttachment.storeAction = SDLToMetal_StoreOp[depthStencilTargetInfo->stencil_store_op];
passDescriptor.stencilAttachment.clearStencil = depthStencilTargetInfo->clear_stencil;
}

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@ typedef struct RenderState
typedef struct WindowState
{
int angle_x, angle_y, angle_z;
SDL_GPUTexture *tex_depth, *tex_msaa;
SDL_GPUTexture *tex_depth, *tex_msaa, *tex_resolve;
Uint32 prev_drawablew, prev_drawableh;
} WindowState;
@ -59,6 +59,7 @@ static void shutdownGPU(void)
WindowState *winstate = &window_states[i];
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_depth);
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_msaa);
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_resolve);
SDL_ReleaseWindowFromGPUDevice(gpu_device, state->windows[i]);
}
SDL_free(window_states);
@ -249,20 +250,20 @@ static const VertexData vertex_data[] = {
static SDL_GPUTexture*
CreateDepthTexture(Uint32 drawablew, Uint32 drawableh)
{
SDL_GPUTextureCreateInfo depthtex_createinfo;
SDL_GPUTextureCreateInfo createinfo;
SDL_GPUTexture *result;
depthtex_createinfo.type = SDL_GPU_TEXTURETYPE_2D;
depthtex_createinfo.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
depthtex_createinfo.width = drawablew;
depthtex_createinfo.height = drawableh;
depthtex_createinfo.layer_count_or_depth = 1;
depthtex_createinfo.num_levels = 1;
depthtex_createinfo.sample_count = render_state.sample_count;
depthtex_createinfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
depthtex_createinfo.props = 0;
createinfo.type = SDL_GPU_TEXTURETYPE_2D;
createinfo.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
createinfo.width = drawablew;
createinfo.height = drawableh;
createinfo.layer_count_or_depth = 1;
createinfo.num_levels = 1;
createinfo.sample_count = render_state.sample_count;
createinfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
createinfo.props = 0;
result = SDL_CreateGPUTexture(gpu_device, &depthtex_createinfo);
result = SDL_CreateGPUTexture(gpu_device, &createinfo);
CHECK_CREATE(result, "Depth Texture")
return result;
@ -271,29 +272,55 @@ CreateDepthTexture(Uint32 drawablew, Uint32 drawableh)
static SDL_GPUTexture*
CreateMSAATexture(Uint32 drawablew, Uint32 drawableh)
{
SDL_GPUTextureCreateInfo msaatex_createinfo;
SDL_GPUTextureCreateInfo createinfo;
SDL_GPUTexture *result;
if (render_state.sample_count == SDL_GPU_SAMPLECOUNT_1) {
return NULL;
}
msaatex_createinfo.type = SDL_GPU_TEXTURETYPE_2D;
msaatex_createinfo.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
msaatex_createinfo.width = drawablew;
msaatex_createinfo.height = drawableh;
msaatex_createinfo.layer_count_or_depth = 1;
msaatex_createinfo.num_levels = 1;
msaatex_createinfo.sample_count = render_state.sample_count;
msaatex_createinfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
msaatex_createinfo.props = 0;
createinfo.type = SDL_GPU_TEXTURETYPE_2D;
createinfo.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
createinfo.width = drawablew;
createinfo.height = drawableh;
createinfo.layer_count_or_depth = 1;
createinfo.num_levels = 1;
createinfo.sample_count = render_state.sample_count;
createinfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
createinfo.props = 0;
result = SDL_CreateGPUTexture(gpu_device, &msaatex_createinfo);
result = SDL_CreateGPUTexture(gpu_device, &createinfo);
CHECK_CREATE(result, "MSAA Texture")
return result;
}
static SDL_GPUTexture *
CreateResolveTexture(Uint32 drawablew, Uint32 drawableh)
{
SDL_GPUTextureCreateInfo createinfo;
SDL_GPUTexture *result;
if (render_state.sample_count == SDL_GPU_SAMPLECOUNT_1) {
return NULL;
}
createinfo.type = SDL_GPU_TEXTURETYPE_2D;
createinfo.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
createinfo.width = drawablew;
createinfo.height = drawableh;
createinfo.layer_count_or_depth = 1;
createinfo.num_levels = 1;
createinfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
createinfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
createinfo.props = 0;
result = SDL_CreateGPUTexture(gpu_device, &createinfo);
CHECK_CREATE(result, "Resolve Texture")
return result;
}
static void
Render(SDL_Window *window, const int windownum)
{
@ -354,8 +381,10 @@ Render(SDL_Window *window, const int windownum)
if (winstate->prev_drawablew != drawablew || winstate->prev_drawableh != drawableh) {
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_depth);
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_msaa);
SDL_ReleaseGPUTexture(gpu_device, winstate->tex_resolve);
winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
winstate->tex_resolve = CreateResolveTexture(drawablew, drawableh);
}
winstate->prev_drawablew = drawablew;
winstate->prev_drawableh = drawableh;
@ -364,14 +393,25 @@ Render(SDL_Window *window, const int windownum)
SDL_zero(color_target);
color_target.clear_color.a = 1.0f;
color_target.load_op = SDL_GPU_LOADOP_CLEAR;
color_target.store_op = SDL_GPU_STOREOP_STORE;
color_target.texture = winstate->tex_msaa ? winstate->tex_msaa : swapchain;
if (winstate->tex_msaa) {
color_target.load_op = SDL_GPU_LOADOP_CLEAR;
color_target.store_op = SDL_GPU_STOREOP_RESOLVE;
color_target.texture = winstate->tex_msaa;
color_target.resolve_texture = winstate->tex_resolve;
color_target.cycle = SDL_TRUE;
color_target.cycle_resolve_texture = SDL_TRUE;
} else {
color_target.load_op = SDL_GPU_LOADOP_CLEAR;
color_target.store_op = SDL_GPU_STOREOP_STORE;
color_target.texture = swapchain;
}
SDL_zero(depth_target);
depth_target.clear_depth = 1.0f;
depth_target.load_op = SDL_GPU_LOADOP_CLEAR;
depth_target.store_op = SDL_GPU_STOREOP_DONT_CARE;
depth_target.stencil_load_op = SDL_GPU_LOADOP_DONT_CARE;
depth_target.stencil_store_op = SDL_GPU_STOREOP_DONT_CARE;
depth_target.texture = winstate->tex_depth;
depth_target.cycle = SDL_TRUE;
@ -390,10 +430,10 @@ Render(SDL_Window *window, const int windownum)
SDL_DrawGPUPrimitives(pass, 36, 1, 0, 0);
SDL_EndGPURenderPass(pass);
/* Blit MSAA to swapchain, if needed */
/* Blit MSAA resolve target to swapchain, if needed */
if (render_state.sample_count > SDL_GPU_SAMPLECOUNT_1) {
SDL_zero(blit_info);
blit_info.source.texture = winstate->tex_msaa;
blit_info.source.texture = winstate->tex_resolve;
blit_info.source.w = drawablew;
blit_info.source.h = drawableh;
@ -609,6 +649,7 @@ init_render_state(int msaa)
SDL_GetWindowSizeInPixels(state->windows[i], (int*) &drawablew, (int*) &drawableh);
winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
winstate->tex_resolve = CreateResolveTexture(drawablew, drawableh);
/* make each window different */
winstate->angle_x = (i * 10) % 360;