Document/ignore GPU features without universal support

This commit is contained in:
Caleb Cornett 2025-02-23 13:34:28 -05:00 committed by Sam Lantinga
parent ad11c6988c
commit ea77472d75
4 changed files with 18 additions and 60 deletions

View file

@ -1495,6 +1495,9 @@ typedef struct SDL_GPUIndirectDispatchCommand
/** /**
* A structure specifying the parameters of a sampler. * A structure specifying the parameters of a sampler.
* *
* Note that mip_lod_bias is a no-op for the Metal driver.
* For Metal, LOD bias must be applied via shader instead.
*
* \since This function is available since SDL 3.2.0. * \since This function is available since SDL 3.2.0.
* *
* \sa SDL_CreateGPUSampler * \sa SDL_CreateGPUSampler
@ -1547,7 +1550,7 @@ typedef struct SDL_GPUVertexBufferDescription
Uint32 slot; /**< The binding slot of the vertex buffer. */ Uint32 slot; /**< The binding slot of the vertex buffer. */
Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */ Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */
SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */ SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */
Uint32 instance_step_rate; /**< The number of instances to draw using the same per-instance data before advancing in the instance buffer by one element. Ignored unless input_rate is SDL_GPU_VERTEXINPUTRATE_INSTANCE */ Uint32 instance_step_rate; /**< Ignored, reserved for future use. */
} SDL_GPUVertexBufferDescription; } SDL_GPUVertexBufferDescription;
/** /**
@ -1717,10 +1720,13 @@ typedef struct SDL_GPUTransferBufferCreateInfo
* A structure specifying the parameters of the graphics pipeline rasterizer * A structure specifying the parameters of the graphics pipeline rasterizer
* state. * state.
* *
* NOTE: Some backend APIs (D3D11/12) will enable depth clamping even if * Note that SDL_GPU_FILLMODE_LINE is not supported on many Android devices.
* enable_depth_clip is true. If you rely on this clamp+clip behavior, * For those devices, the fill mode will automatically fall back to FILL.
* consider enabling depth clip and then manually clamping depth in your *
* fragment shaders on Metal and Vulkan. * Also note that the D3D12 driver will enable depth clamping even if
* enable_depth_clip is true. If you need this clamp+clip behavior, consider
* enabling depth clip and then manually clamping depth in your fragment
* shaders on Metal and Vulkan.
* *
* \since This struct is available since SDL 3.2.0. * \since This struct is available since SDL 3.2.0.
* *
@ -1751,8 +1757,8 @@ typedef struct SDL_GPURasterizerState
typedef struct SDL_GPUMultisampleState typedef struct SDL_GPUMultisampleState
{ {
SDL_GPUSampleCount sample_count; /**< The number of samples to be used in rasterization. */ SDL_GPUSampleCount sample_count; /**< The number of samples to be used in rasterization. */
Uint32 sample_mask; /**< Determines which samples get updated in the render targets. Treated as 0xFFFFFFFF if enable_mask is false. */ Uint32 sample_mask; /**< Ignored, reserved for future use. */
bool enable_mask; /**< Enables sample masking. */ bool enable_mask; /**< Ignored, reserved for future use. */
Uint8 padding1; Uint8 padding1;
Uint8 padding2; Uint8 padding2;
Uint8 padding3; Uint8 padding3;

View file

@ -2928,7 +2928,7 @@ static bool D3D12_INTERNAL_ConvertVertexInputState(SDL_GPUVertexInputState verte
desc[i].AlignedByteOffset = attribute.offset; desc[i].AlignedByteOffset = attribute.offset;
desc[i].InputSlotClass = SDLToD3D12_InputRate[vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate]; desc[i].InputSlotClass = SDLToD3D12_InputRate[vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate];
desc[i].InstanceDataStepRate = (vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) desc[i].InstanceDataStepRate = (vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE)
? vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].instance_step_rate ? 1
: 0; : 0;
} }
@ -3010,11 +3010,7 @@ static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
return NULL; return NULL;
} }
Uint32 sampleMask = createinfo->multisample_state.enable_mask ? psoDesc.SampleMask = 0xFFFFFFFF;
createinfo->multisample_state.sample_mask :
0xFFFFFFFF;
psoDesc.SampleMask = sampleMask;
psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->multisample_state.sample_count]; psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->multisample_state.sample_count];
psoDesc.SampleDesc.Quality = (createinfo->multisample_state.sample_count > SDL_GPU_SAMPLECOUNT_1) ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0; psoDesc.SampleDesc.Quality = (createinfo->multisample_state.sample_count > SDL_GPU_SAMPLECOUNT_1) ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;

View file

@ -478,8 +478,6 @@ typedef struct MetalGraphicsPipeline
{ {
id<MTLRenderPipelineState> handle; id<MTLRenderPipelineState> handle;
Uint32 sample_mask;
SDL_GPURasterizerState rasterizerState; SDL_GPURasterizerState rasterizerState;
SDL_GPUPrimitiveType primitiveType; SDL_GPUPrimitiveType primitiveType;
@ -1181,9 +1179,7 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
for (Uint32 i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) { for (Uint32 i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
binding = METAL_FIRST_VERTEX_BUFFER_SLOT + createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot; binding = METAL_FIRST_VERTEX_BUFFER_SLOT + createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
vertexDescriptor.layouts[binding].stepFunction = SDLToMetal_StepFunction[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate]; vertexDescriptor.layouts[binding].stepFunction = SDLToMetal_StepFunction[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate];
vertexDescriptor.layouts[binding].stepRate = (createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) vertexDescriptor.layouts[binding].stepRate = 1;
? createinfo->vertex_input_state.vertex_buffer_descriptions[i].instance_step_rate
: 1;
vertexDescriptor.layouts[binding].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch; vertexDescriptor.layouts[binding].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
} }
@ -1202,13 +1198,8 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
SET_ERROR_AND_RETURN("Creating render pipeline failed: %s", [[error description] UTF8String], NULL); SET_ERROR_AND_RETURN("Creating render pipeline failed: %s", [[error description] UTF8String], NULL);
} }
Uint32 sampleMask = createinfo->multisample_state.enable_mask ?
createinfo->multisample_state.sample_mask :
0xFFFFFFFF;
result = SDL_calloc(1, sizeof(MetalGraphicsPipeline)); result = SDL_calloc(1, sizeof(MetalGraphicsPipeline));
result->handle = pipelineState; result->handle = pipelineState;
result->sample_mask = sampleMask;
result->depth_stencil_state = depthStencilState; result->depth_stencil_state = depthStencilState;
result->rasterizerState = createinfo->rasterizer_state; result->rasterizerState = createinfo->rasterizer_state;
result->primitiveType = createinfo->primitive_type; result->primitiveType = createinfo->primitive_type;

View file

@ -56,8 +56,6 @@ typedef struct VulkanExtensions
// Core since 1.2, but requires annoying paperwork to implement // Core since 1.2, but requires annoying paperwork to implement
Uint8 KHR_driver_properties; Uint8 KHR_driver_properties;
// EXT, probably not going to be Core
Uint8 EXT_vertex_attribute_divisor;
// Only required for special implementations (i.e. MoltenVK) // Only required for special implementations (i.e. MoltenVK)
Uint8 KHR_portability_subset; Uint8 KHR_portability_subset;
// Only required for decoding HDR ASTC textures // Only required for decoding HDR ASTC textures
@ -6202,11 +6200,8 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2]; VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2];
VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo; VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo;
VkPipelineVertexInputDivisorStateCreateInfoEXT divisorStateCreateInfo;
VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, createinfo->vertex_input_state.num_vertex_buffers); VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, createinfo->vertex_input_state.num_vertex_buffers);
VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, createinfo->vertex_input_state.num_vertex_attributes); VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, createinfo->vertex_input_state.num_vertex_attributes);
VkVertexInputBindingDivisorDescriptionEXT *divisorDescriptions = SDL_stack_alloc(VkVertexInputBindingDivisorDescriptionEXT, createinfo->vertex_input_state.num_vertex_buffers);
Uint32 divisorDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo; VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
@ -6289,10 +6284,6 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
vertexInputBindingDescriptions[i].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot; vertexInputBindingDescriptions[i].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
vertexInputBindingDescriptions[i].inputRate = SDLToVK_VertexInputRate[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate]; vertexInputBindingDescriptions[i].inputRate = SDLToVK_VertexInputRate[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate];
vertexInputBindingDescriptions[i].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch; vertexInputBindingDescriptions[i].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
if (createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
divisorDescriptionCount += 1;
}
} }
for (i = 0; i < createinfo->vertex_input_state.num_vertex_attributes; i += 1) { for (i = 0; i < createinfo->vertex_input_state.num_vertex_attributes; i += 1) {
@ -6310,26 +6301,6 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
vertexInputStateCreateInfo.vertexAttributeDescriptionCount = createinfo->vertex_input_state.num_vertex_attributes; vertexInputStateCreateInfo.vertexAttributeDescriptionCount = createinfo->vertex_input_state.num_vertex_attributes;
vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions; vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
if (divisorDescriptionCount > 0) {
divisorDescriptionCount = 0;
for (i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
if (createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
divisorDescriptions[divisorDescriptionCount].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
divisorDescriptions[divisorDescriptionCount].divisor = createinfo->vertex_input_state.vertex_buffer_descriptions[i].instance_step_rate;
divisorDescriptionCount += 1;
}
}
divisorStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
divisorStateCreateInfo.pNext = NULL;
divisorStateCreateInfo.vertexBindingDivisorCount = divisorDescriptionCount;
divisorStateCreateInfo.pVertexBindingDivisors = divisorDescriptions;
vertexInputStateCreateInfo.pNext = &divisorStateCreateInfo;
}
// Topology // Topology
inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@ -6376,9 +6347,7 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
// Multisample // Multisample
Uint32 sampleMask = createinfo->multisample_state.enable_mask ? Uint32 sampleMask = 0xFFFFFFFF;
createinfo->multisample_state.sample_mask :
0xFFFFFFFF;
multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampleStateCreateInfo.pNext = NULL; multisampleStateCreateInfo.pNext = NULL;
@ -6476,7 +6445,6 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
SDL_stack_free(vertexInputBindingDescriptions); SDL_stack_free(vertexInputBindingDescriptions);
SDL_stack_free(vertexInputAttributeDescriptions); SDL_stack_free(vertexInputAttributeDescriptions);
SDL_stack_free(colorBlendAttachmentStates); SDL_stack_free(colorBlendAttachmentStates);
SDL_stack_free(divisorDescriptions);
SDL_free(graphicsPipeline); SDL_free(graphicsPipeline);
SET_STRING_ERROR_AND_RETURN("Failed to initialize pipeline resource layout!", NULL); SET_STRING_ERROR_AND_RETURN("Failed to initialize pipeline resource layout!", NULL);
} }
@ -6515,7 +6483,6 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
SDL_stack_free(vertexInputBindingDescriptions); SDL_stack_free(vertexInputBindingDescriptions);
SDL_stack_free(vertexInputAttributeDescriptions); SDL_stack_free(vertexInputAttributeDescriptions);
SDL_stack_free(colorBlendAttachmentStates); SDL_stack_free(colorBlendAttachmentStates);
SDL_stack_free(divisorDescriptions);
renderer->vkDestroyRenderPass( renderer->vkDestroyRenderPass(
renderer->logicalDevice, renderer->logicalDevice,
@ -10898,7 +10865,7 @@ static inline Uint8 CheckDeviceExtensions(
supports->ext = 1; \ supports->ext = 1; \
} }
CHECK(KHR_swapchain) CHECK(KHR_swapchain)
else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(EXT_vertex_attribute_divisor) else CHECK(KHR_portability_subset) else CHECK(EXT_texture_compression_astc_hdr) else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) CHECK(KHR_portability_subset) else CHECK(EXT_texture_compression_astc_hdr)
#undef CHECK #undef CHECK
} }
@ -10912,7 +10879,6 @@ static inline Uint32 GetDeviceExtensionCount(VulkanExtensions *supports)
supports->KHR_swapchain + supports->KHR_swapchain +
supports->KHR_maintenance1 + supports->KHR_maintenance1 +
supports->KHR_driver_properties + supports->KHR_driver_properties +
supports->EXT_vertex_attribute_divisor +
supports->KHR_portability_subset + supports->KHR_portability_subset +
supports->EXT_texture_compression_astc_hdr); supports->EXT_texture_compression_astc_hdr);
} }
@ -10929,7 +10895,6 @@ static inline void CreateDeviceExtensionArray(
CHECK(KHR_swapchain) CHECK(KHR_swapchain)
CHECK(KHR_maintenance1) CHECK(KHR_maintenance1)
CHECK(KHR_driver_properties) CHECK(KHR_driver_properties)
CHECK(EXT_vertex_attribute_divisor)
CHECK(KHR_portability_subset) CHECK(KHR_portability_subset)
CHECK(EXT_texture_compression_astc_hdr) CHECK(EXT_texture_compression_astc_hdr)
#undef CHECK #undef CHECK