Added SDL_SetRenderTextureAddressMode() and SDL_GetRenderTextureAddressMode()

Fixes https://github.com/libsdl-org/SDL/issues/4820
Fixes https://github.com/libsdl-org/SDL/issues/12610
This commit is contained in:
Sam Lantinga
2024-07-20 09:34:34 -07:00
parent eb918af3dc
commit 633b9f6fb1
20 changed files with 623 additions and 531 deletions

View File

@@ -169,16 +169,6 @@ typedef enum {
VULKAN_RENDERPASS_COUNT
} VULKAN_RenderPass;
// Sampler types
typedef enum
{
VULKAN_SAMPLER_NEAREST_CLAMP,
VULKAN_SAMPLER_NEAREST_WRAP,
VULKAN_SAMPLER_LINEAR_CLAMP,
VULKAN_SAMPLER_LINEAR_WRAP,
VULKAN_SAMPLER_COUNT
} VULKAN_Sampler;
// Vertex shader, common values
typedef struct
{
@@ -196,15 +186,6 @@ static const float INPUTTYPE_SRGB = 1;
static const float INPUTTYPE_SCRGB = 2;
static const float INPUTTYPE_HDR10 = 3;
typedef enum
{
SAMPLER_POINT_CLAMP,
SAMPLER_POINT_WRAP,
SAMPLER_LINEAR_CLAMP,
SAMPLER_LINEAR_WRAP,
NUM_SAMPLERS
} Sampler;
// Pixel shader constants, common values
typedef struct
{
@@ -347,7 +328,7 @@ typedef struct
uint32_t currentConstantBufferIndex;
int32_t currentConstantBufferOffset;
VkSampler samplers[VULKAN_SAMPLER_COUNT];
VkSampler samplers[RENDER_SAMPLER_COUNT];
VkDescriptorPool **descriptorPools;
uint32_t *numDescriptorPools;
uint32_t currentDescriptorPoolIndex;
@@ -1950,42 +1931,6 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
VULKAN_CreateVertexBuffer(rendererData, i, SDL_VULKAN_VERTEX_BUFFER_DEFAULT_SIZE);
}
// Create samplers
{
static struct
{
VkFilter filter;
VkSamplerAddressMode address;
} samplerParams[] = {
{ VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
{ VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT },
{ VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
{ VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT },
};
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == VULKAN_SAMPLER_COUNT);
VkSamplerCreateInfo samplerCreateInfo = { 0 };
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.anisotropyEnable = VK_FALSE;
samplerCreateInfo.maxAnisotropy = 1.0f;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 1000.0f;
for (int i = 0; i < SDL_arraysize(samplerParams); ++i) {
samplerCreateInfo.magFilter = samplerParams[i].filter;
samplerCreateInfo.minFilter = samplerParams[i].filter;
samplerCreateInfo.addressModeU = samplerParams[i].address;
samplerCreateInfo.addressModeV = samplerParams[i].address;
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[i]);
if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer);
SET_ERROR_CODE("vkCreateSampler()", result);
return result;
}
}
}
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER, rendererData->instance);
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER, (Sint64)rendererData->surface);
@@ -3762,6 +3707,42 @@ static bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand
return true;
}
static VkSampler VULKAN_GetSampler(VULKAN_RenderData *data, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
{
Uint32 key = RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v);
SDL_assert(key < SDL_arraysize(data->samplers));
if (!data->samplers[key]) {
VkSamplerCreateInfo samplerCreateInfo = { 0 };
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.anisotropyEnable = VK_FALSE;
samplerCreateInfo.maxAnisotropy = 1.0f;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 1000.0f;
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return VK_NULL_HANDLE;
}
VkResult result = vkCreateSampler(data->device, &samplerCreateInfo, NULL, &data->samplers[key]);
if (result != VK_SUCCESS) {
SET_ERROR_CODE("vkCreateSampler()", result);
return false;
}
}
return data->samplers[key];
}
static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix, VULKAN_DrawStateCache *stateCache)
{
@@ -3775,34 +3756,9 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_NEAREST_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_LINEAR_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
default:
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
textureSampler = VULKAN_GetSampler(rendererData, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
if (textureSampler == VK_NULL_HANDLE) {
return false;
}
if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {