Vulkan: added support for wrapping existing textures

main
Sam Lantinga 2024-02-28 21:18:17 -08:00
parent 2adbcce864
commit 0454e1fdb4
2 changed files with 41 additions and 48 deletions

View File

@ -616,6 +616,10 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
* associated with the V plane of a YUV texture, if you want to wrap an
* existing texture.
*
* With the vulkan renderer:
*
* - `SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER`: the VkImage with layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if you want to wrap an existing texture.
*
* \param renderer the rendering context
* \param props the properties to use
* \returns a pointer to the created texture or NULL if no rendering context
@ -655,6 +659,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv"
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u"
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v"
#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "vulkan.texture"
/**
* Get the properties associated with a texture.
@ -734,6 +739,10 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
* - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER`: the GLenum for the
* texture target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc)
*
* With the vulkan renderer:
*
* - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER`: the VkImage associated with the texture
*
* \param texture the texture to query
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
@ -766,10 +775,7 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t
#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u"
#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v"
#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER "SDL.texture.opengles2.target"
#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_POINTER "SDL.texture.vulkan.texture"
#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_U_POINTER "SDL.texture.vulkan.texture_u"
#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_V_POINTER "SDL.texture.vulkan.texture_v"
#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_UV_POINTER "SDL.texture.vulkan.texture_uv"
#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER "SDL.texture.vulkan.texture"
/**
* Get the renderer that created an SDL_Texture.

View File

@ -689,25 +689,27 @@ static void VULKAN_DestroyImage(VULKAN_RenderData *rendererData, VULKAN_Image *v
}
if (vulkanImage->deviceMemory != VK_NULL_HANDLE) {
if (vulkanImage->allocatedImage) {
vkFreeMemory(rendererData->device, vulkanImage->deviceMemory, NULL);
}
vulkanImage->deviceMemory = VK_NULL_HANDLE;
}
SDL_memset(vulkanImage, 0, sizeof(VULKAN_Image));
}
static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, uint32_t width, uint32_t height, VkFormat format,
VkImageUsageFlags imageUsage, VkComponentMapping swizzle, VkImage externalImage,
VkSamplerYcbcrConversionKHR samplerYcbcrConversion,
VULKAN_Image *imageOut)
static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_PropertiesID create_props, uint32_t width, uint32_t height, VkFormat format, VkImageUsageFlags imageUsage, VkComponentMapping swizzle, VkSamplerYcbcrConversionKHR samplerYcbcrConversion, VULKAN_Image *imageOut)
{
VkResult result;
VkImageCreateInfo imageCreateInfo = { 0 };
VkSamplerYcbcrConversionInfoKHR samplerYcbcrConversionInfo = { 0 };
SDL_memset(imageOut, 0, sizeof(VULKAN_Image));
imageOut->format = format;
imageOut->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageOut->image = (VkImage)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER, 0);
if (imageOut->image == VK_NULL_HANDLE) {
imageOut->allocatedImage = VK_TRUE;
VkImageCreateInfo imageCreateInfo = { 0 };
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.flags = 0;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
@ -724,9 +726,6 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, uint32_t w
imageCreateInfo.queueFamilyIndexCount = 0;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageOut->allocatedImage = VK_FALSE;
if (externalImage == VK_NULL_HANDLE) {
imageOut->allocatedImage = VK_TRUE;
result = vkCreateImage(rendererData->device, &imageCreateInfo, NULL, &imageOut->image);
if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut);
@ -765,13 +764,15 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, uint32_t w
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkBindImageMemory(): %s\n", SDL_Vulkan_GetResultString(result));
return result;
}
} else {
imageOut->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
VkImageViewCreateInfo imageViewCreateInfo = { 0 };
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.image = imageOut->image;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = imageCreateInfo.format;
imageViewCreateInfo.format = format;
imageViewCreateInfo.components = swizzle;
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
@ -779,7 +780,7 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, uint32_t w
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 1;
/* If it's a YcBcBr image, we need to pass the conversion info to the VkImageView (and the VkSampler) */
/* If it's a YCbCr image, we need to pass the conversion info to the VkImageView (and the VkSampler) */
if (samplerYcbcrConversion != VK_NULL_HANDLE) {
samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR;
samplerYcbcrConversionInfo.conversion = samplerYcbcrConversion;
@ -2395,22 +2396,11 @@ static SDL_bool VULKAN_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode b
return SDL_TRUE;
}
static int GetTextureProperty(SDL_PropertiesID props, const char *name, VkImage *image)
{
VkImage *propImage = (VkImage*)SDL_GetProperty(props, name, NULL);
if (propImage) {
*image = *propImage;
}
return 0;
}
static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->driverdata;
VULKAN_TextureData *textureData;
VkResult result;
VkImage externalImage = VK_NULL_HANDLE;
VkFormat textureFormat = SDLPixelFormatToVkTextureFormat(texture->format, renderer->output_colorspace);
uint32_t width = texture->w;
uint32_t height = texture->h;
@ -2562,17 +2552,14 @@ static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
if (GetTextureProperty(create_props, "vulkan.texture", &externalImage) < 0) {
return -1;
}
result = VULKAN_AllocateImage(rendererData, width, height, textureFormat, usage, imageViewSwizzle, externalImage, textureData->samplerYcbcrConversion, &textureData->mainImage);
result = VULKAN_AllocateImage(rendererData, create_props, width, height, textureFormat, usage, imageViewSwizzle, textureData->samplerYcbcrConversion, &textureData->mainImage);
if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_AllocateImage(): %s\n", SDL_Vulkan_GetResultString(result));
return result;
}
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_VULKAN_TEXTURE_POINTER, &textureData->mainImage.image);
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER, (Sint64)textureData->mainImage.image);
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
result = VULKAN_CreateFramebuffersAndRenderPasses(renderer,