Compare commits

...

9 Commits

5 changed files with 229 additions and 29 deletions

View File

@ -8,7 +8,7 @@ option(BUILD_SHARED_LIBS "Build shared library" ON)
# Version
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "4")
SET(LIB_MINOR_VERSION "5")
SET(LIB_REVISION "0")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")

View File

@ -55,7 +55,7 @@ extern "C" {
/* Version API */
#define REFRESH_MAJOR_VERSION 1
#define REFRESH_MINOR_VERSION 4
#define REFRESH_MINOR_VERSION 5
#define REFRESH_PATCH_VERSION 0
#define REFRESH_COMPILED_VERSION ( \
@ -124,6 +124,7 @@ typedef enum Refresh_TextureFormat
REFRESH_TEXTUREFORMAT_BC1,
REFRESH_TEXTUREFORMAT_BC2,
REFRESH_TEXTUREFORMAT_BC3,
REFRESH_TEXTUREFORMAT_BC7,
REFRESH_TEXTUREFORMAT_R8G8_SNORM,
REFRESH_TEXTUREFORMAT_R8G8B8A8_SNORM,
REFRESH_TEXTUREFORMAT_A2R10G10B10,

View File

@ -34,7 +34,12 @@
/* Drivers */
static const Refresh_Driver *drivers[] = {
#ifdef REFRESH_DRIVER_VULKAN
&VulkanDriver,
#endif
#ifdef REFRESH_DRIVER_PS5
&PS5Driver,
#endif
NULL
};

View File

@ -36,9 +36,15 @@
/* Logging */
extern void Refresh_LogInfo(const char *fmt, ...);
extern void Refresh_LogWarn(const char *fmt, ...);
extern void Refresh_LogError(const char *fmt, ...);
#ifdef __cplusplus
extern "C" {
#endif
void Refresh_LogInfo(const char *fmt, ...);
void Refresh_LogWarn(const char *fmt, ...);
void Refresh_LogError(const char *fmt, ...);
#ifdef __cplusplus
}
#endif
/* Internal Helper Utilities */
@ -51,6 +57,7 @@ static inline uint32_t Texture_GetFormatSize(
return 8;
case REFRESH_TEXTUREFORMAT_BC2:
case REFRESH_TEXTUREFORMAT_BC3:
case REFRESH_TEXTUREFORMAT_BC7:
return 16;
case REFRESH_TEXTUREFORMAT_R8:
return 1;
@ -117,7 +124,8 @@ static inline uint32_t BytesPerRow(
if ( format == REFRESH_TEXTUREFORMAT_BC1 ||
format == REFRESH_TEXTUREFORMAT_BC2 ||
format == REFRESH_TEXTUREFORMAT_BC3 )
format == REFRESH_TEXTUREFORMAT_BC3 ||
format == REFRESH_TEXTUREFORMAT_BC7 )
{
blocksPerRow = (width + 3) / 4;
}
@ -135,7 +143,8 @@ static inline int32_t BytesPerImage(
if ( format == REFRESH_TEXTUREFORMAT_BC1 ||
format == REFRESH_TEXTUREFORMAT_BC2 ||
format == REFRESH_TEXTUREFORMAT_BC3 )
format == REFRESH_TEXTUREFORMAT_BC3 ||
format == REFRESH_TEXTUREFORMAT_BC7 )
{
blocksPerRow = (width + 3) / 4;
blocksPerColumn = (height + 3) / 4;
@ -522,6 +531,7 @@ typedef struct Refresh_Driver
} Refresh_Driver;
extern Refresh_Driver VulkanDriver;
extern Refresh_Driver PS5Driver;
#endif /* REFRESH_DRIVER_H */

View File

@ -190,6 +190,7 @@ static VkFormat RefreshToVK_SurfaceFormat[] =
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, /* BC1 */
VK_FORMAT_BC2_UNORM_BLOCK, /* BC3 */
VK_FORMAT_BC3_UNORM_BLOCK, /* BC5 */
VK_FORMAT_BC7_UNORM_BLOCK, /* BC7 */
VK_FORMAT_R8G8_SNORM, /* R8G8_SNORM */
VK_FORMAT_R8G8B8A8_SNORM, /* R8G8B8A8_SNORM */
VK_FORMAT_A2R10G10B10_UNORM_PACK32, /* A2R10G10B10 */
@ -912,6 +913,7 @@ static inline void DescriptorSetLayoutHashTable_Insert(
typedef struct RenderPassColorTargetDescription
{
VkFormat format;
Refresh_Vec4 clearColor;
Refresh_LoadOp loadOp;
Refresh_StoreOp storeOp;
@ -919,6 +921,7 @@ typedef struct RenderPassColorTargetDescription
typedef struct RenderPassDepthStencilTargetDescription
{
VkFormat format;
Refresh_LoadOp loadOp;
Refresh_StoreOp storeOp;
Refresh_LoadOp stencilLoadOp;
@ -958,6 +961,11 @@ static inline uint8_t RenderPassHash_Compare(
for (i = 0; i < a->colorAttachmentCount; i += 1)
{
if (a->colorTargetDescriptions[i].format != b->colorTargetDescriptions[i].format)
{
return 0;
}
if ( a->colorTargetDescriptions[i].clearColor.x != b->colorTargetDescriptions[i].clearColor.x ||
a->colorTargetDescriptions[i].clearColor.y != b->colorTargetDescriptions[i].clearColor.y ||
a->colorTargetDescriptions[i].clearColor.z != b->colorTargetDescriptions[i].clearColor.z ||
@ -977,6 +985,11 @@ static inline uint8_t RenderPassHash_Compare(
}
}
if (a->depthStencilTargetDescription.format != b->depthStencilTargetDescription.format)
{
return 0;
}
if (a->depthStencilTargetDescription.loadOp != b->depthStencilTargetDescription.loadOp)
{
return 0;
@ -1674,6 +1687,10 @@ typedef struct VulkanRenderer
VkDeviceSize minUBOAlignment;
/* Some drivers don't support D16 for some reason. Fun! */
VkFormat D16Format;
VkFormat D16S8Format;
VulkanTexture **texturesToDestroy;
uint32_t texturesToDestroyCount;
uint32_t texturesToDestroyCapacity;
@ -1782,6 +1799,40 @@ static inline void LogVulkanResultAsWarn(
/* Utility */
static inline VkFormat RefreshToVK_DepthFormat(
VulkanRenderer* renderer,
Refresh_TextureFormat format
) {
switch (format)
{
case REFRESH_TEXTUREFORMAT_D16_UNORM:
return renderer->D16Format;
case REFRESH_TEXTUREFORMAT_D16_UNORM_S8_UINT:
return renderer->D16S8Format;
case REFRESH_TEXTUREFORMAT_D32_SFLOAT:
return VK_FORMAT_D32_SFLOAT;
case REFRESH_TEXTUREFORMAT_D32_SFLOAT_S8_UINT:
return VK_FORMAT_D32_SFLOAT_S8_UINT;
default:
return VK_FORMAT_UNDEFINED;
}
}
static inline uint8_t IsRefreshDepthFormat(Refresh_TextureFormat format)
{
switch (format)
{
case REFRESH_TEXTUREFORMAT_D16_UNORM:
case REFRESH_TEXTUREFORMAT_D32_SFLOAT:
case REFRESH_TEXTUREFORMAT_D16_UNORM_S8_UINT:
case REFRESH_TEXTUREFORMAT_D32_SFLOAT_S8_UINT:
return 1;
default:
return 0;
}
}
static inline uint8_t IsDepthFormat(VkFormat format)
{
switch(format)
@ -1817,6 +1868,7 @@ static inline uint32_t VULKAN_INTERNAL_BytesPerPixel(VkFormat format)
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_BC2_UNORM_BLOCK:
case VK_FORMAT_BC3_UNORM_BLOCK:
case VK_FORMAT_BC7_UNORM_BLOCK:
return 16;
case VK_FORMAT_R8G8B8A8_UNORM:
@ -1857,6 +1909,40 @@ static inline uint32_t VULKAN_INTERNAL_BytesPerPixel(VkFormat format)
}
}
static inline uint32_t VULKAN_INTERNAL_GetTextureBlockSize(
VkFormat format
) {
switch (format)
{
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
case VK_FORMAT_BC2_UNORM_BLOCK:
case VK_FORMAT_BC3_UNORM_BLOCK:
case VK_FORMAT_BC7_UNORM_BLOCK:
return 4;
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
case VK_FORMAT_R8G8_SNORM:
case VK_FORMAT_R8G8B8A8_SNORM:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
case VK_FORMAT_R16G16_UNORM:
case VK_FORMAT_R16G16B16A16_UNORM:
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_R32_SFLOAT:
case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16G16_SFLOAT:
case VK_FORMAT_R16G16B16A16_SFLOAT:
return 1;
default:
Refresh_LogError("Unrecognized texture format!");
return 0;
}
}
static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage(
uint32_t width,
uint32_t height,
@ -1864,12 +1950,12 @@ static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage(
) {
uint32_t blocksPerRow = width;
uint32_t blocksPerColumn = height;
uint32_t blockSize = VULKAN_INTERNAL_GetTextureBlockSize(format);
if (format == VK_FORMAT_BC1_RGBA_UNORM_BLOCK ||
format == VK_FORMAT_BC3_UNORM_BLOCK ||
format == VK_FORMAT_BC5_UNORM_BLOCK)
if (blockSize > 1)
{
blocksPerRow = (width + 3) / 4;
blocksPerRow = (width + blockSize - 1) / blockSize;
blocksPerColumn = (height + blockSize - 1) / blockSize;
}
return blocksPerRow * blocksPerColumn * VULKAN_INTERNAL_BytesPerPixel(format);
@ -5614,9 +5700,10 @@ static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass(
if (attachmentInfo.hasDepthStencilAttachment)
{
attachmentDescriptions[attachmentDescriptionCount].flags = 0;
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_DepthFormat(
renderer,
attachmentInfo.depthStencilFormat
];
);
attachmentDescriptions[attachmentDescriptionCount].samples =
VK_SAMPLE_COUNT_1_BIT; /* FIXME: do these take multisamples? */
attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@ -6313,7 +6400,16 @@ static Refresh_Texture* VULKAN_CreateTexture(
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
);
VkImageAspectFlags imageAspectFlags;
VkFormat format = RefreshToVK_SurfaceFormat[textureCreateInfo->format];
VkFormat format;
if (IsRefreshDepthFormat(textureCreateInfo->format))
{
format = RefreshToVK_DepthFormat(renderer, textureCreateInfo->format);
}
else
{
format = RefreshToVK_SurfaceFormat[textureCreateInfo->format];
}
if (textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT)
{
@ -6507,6 +6603,9 @@ static void VULKAN_SetTextureData(
VulkanTransferBuffer *transferBuffer;
VkBufferImageCopy imageCopy;
uint8_t *stagingBufferPointer;
uint32_t blockSize = VULKAN_INTERNAL_GetTextureBlockSize(vulkanTexture->format);
uint32_t bufferRowLength;
uint32_t bufferImageHeight;
if (vulkanCommandBuffer->renderPassInProgress)
{
@ -6555,6 +6654,9 @@ static void VULKAN_SetTextureData(
&vulkanTexture->resourceAccessType
);
bufferRowLength = SDL_max(blockSize, textureSlice->rectangle.w);
bufferImageHeight = SDL_max(blockSize, textureSlice->rectangle.h);
imageCopy.imageExtent.width = textureSlice->rectangle.w;
imageCopy.imageExtent.height = textureSlice->rectangle.h;
imageCopy.imageExtent.depth = 1;
@ -6566,8 +6668,8 @@ static void VULKAN_SetTextureData(
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = textureSlice->level;
imageCopy.bufferOffset = transferBuffer->offset;
imageCopy.bufferRowLength = 0;
imageCopy.bufferImageHeight = 0;
imageCopy.bufferRowLength = bufferRowLength;
imageCopy.bufferImageHeight = bufferImageHeight;
renderer->vkCmdCopyBufferToImage(
vulkanCommandBuffer->commandBuffer,
@ -6692,6 +6794,24 @@ static void VULKAN_SetTextureDataYUV(
&imageCopy
);
if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)
{
/* TODO: is it worth it to only transition the specific subresource? */
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE,
VK_IMAGE_ASPECT_COLOR_BIT,
0,
tex->layerCount,
0,
tex->levelCount,
0,
tex->image,
&tex->resourceAccessType
);
}
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex);
/* These apply to both U and V */
@ -6736,6 +6856,24 @@ static void VULKAN_SetTextureDataYUV(
&imageCopy
);
if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)
{
/* TODO: is it worth it to only transition the specific subresource? */
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE,
VK_IMAGE_ASPECT_COLOR_BIT,
0,
tex->layerCount,
0,
tex->levelCount,
0,
tex->image,
&tex->resourceAccessType
);
}
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex);
/* V */
@ -6775,11 +6913,9 @@ static void VULKAN_SetTextureDataYUV(
transferBuffer->offset += yDataLength + uvDataLength;
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex);
/* FIXME: don't we have to do this for every image? */
if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)
{
/* TODO: is it worth it to only transition the specific subresource? */
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
@ -6794,6 +6930,8 @@ static void VULKAN_SetTextureDataYUV(
&tex->resourceAccessType
);
}
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex);
}
static void VULKAN_INTERNAL_BlitImage(
@ -6858,8 +6996,8 @@ static void VULKAN_INTERNAL_BlitImage(
blit.dstOffsets[1].y = destinationTextureSlice->rectangle.y + destinationTextureSlice->rectangle.h;
blit.dstOffsets[1].z = 1;
blit.dstSubresource.mipLevel = sourceTextureSlice->level;
blit.dstSubresource.baseArrayLayer = sourceTextureSlice->layer;
blit.dstSubresource.mipLevel = destinationTextureSlice->level;
blit.dstSubresource.baseArrayLayer = destinationTextureSlice->layer;
blit.dstSubresource.layerCount = 1;
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@ -7656,6 +7794,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
for (i = 0; i < colorAttachmentCount; i += 1)
{
hash.colorTargetDescriptions[i].format = ((VulkanTexture*) colorAttachmentInfos[i].texture)->format;
hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor;
hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp;
hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp;
@ -7665,6 +7804,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
if (depthStencilAttachmentInfo == NULL)
{
hash.depthStencilTargetDescription.format = 0;
hash.depthStencilTargetDescription.loadOp = REFRESH_LOADOP_DONT_CARE;
hash.depthStencilTargetDescription.storeOp = REFRESH_STOREOP_DONT_CARE;
hash.depthStencilTargetDescription.stencilLoadOp = REFRESH_LOADOP_DONT_CARE;
@ -7672,6 +7812,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
}
else
{
hash.depthStencilTargetDescription.format = ((VulkanTexture*) depthStencilAttachmentInfo->texture)->format;
hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp;
hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp;
hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp;
@ -8000,6 +8141,8 @@ static void VULKAN_BeginRenderPass(
if (depthStencilAttachmentInfo != NULL)
{
texture = (VulkanTexture*) depthStencilAttachmentInfo->texture;
if (texture->dimensions.width < framebufferWidth)
{
framebufferWidth = texture->dimensions.width;
@ -9363,9 +9506,9 @@ static void VULKAN_Submit(
/* Mark command buffers as submitted */
if (renderer->submittedCommandBufferCount + commandBufferCount >= renderer->submittedCommandBufferCapacity)
if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity)
{
renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + commandBufferCount;
renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
renderer->submittedCommandBuffers = SDL_realloc(
renderer->submittedCommandBuffers,
@ -9373,12 +9516,9 @@ static void VULKAN_Submit(
);
}
for (i = 0; i < commandBufferCount; i += 1)
{
((VulkanCommandBuffer*)pCommandBuffers[i])->submitted = 1;
renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = (VulkanCommandBuffer*) pCommandBuffers[i];
renderer->submittedCommandBufferCount += 1;
}
((VulkanCommandBuffer*)pCommandBuffers[i])->submitted = 1;
renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = (VulkanCommandBuffer*) pCommandBuffers[i];
renderer->submittedCommandBufferCount += 1;
/* Present, if applicable */
@ -10132,6 +10272,9 @@ static Refresh_Device* VULKAN_CreateDevice(
VkDescriptorPoolSize poolSizes[4];
VkDescriptorSetAllocateInfo descriptorAllocateInfo;
/* Variables: Image Format Detection */
VkImageFormatProperties imageFormatProperties;
VULKAN_INTERNAL_LoadEntryPoints(renderer);
renderer->presentMode = presentationParameters->presentMode;
@ -10571,12 +10714,53 @@ static Refresh_Device* VULKAN_CreateDevice(
renderer->renderTargetHashArray.capacity = 0;
/* Initialize transfer buffer pool */
renderer->transferBufferPool.lock = SDL_CreateMutex();
renderer->transferBufferPool.availableBufferCapacity = 4;
renderer->transferBufferPool.availableBufferCount = 0;
renderer->transferBufferPool.availableBuffers = SDL_malloc(renderer->transferBufferPool.availableBufferCapacity * sizeof(VulkanTransferBuffer*));
/* Some drivers don't support D16, so we have to fall back to D32. */
vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
renderer->physicalDevice,
VK_FORMAT_D16_UNORM,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_ASPECT_DEPTH_BIT,
0,
&imageFormatProperties
);
if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
{
renderer->D16Format = VK_FORMAT_D32_SFLOAT;
}
else
{
renderer->D16Format = VK_FORMAT_D16_UNORM;
}
vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
renderer->physicalDevice,
VK_FORMAT_D16_UNORM_S8_UINT,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
0,
&imageFormatProperties
);
if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
{
renderer->D16S8Format = VK_FORMAT_D32_SFLOAT_S8_UINT;
}
else
{
renderer->D16S8Format = VK_FORMAT_D16_UNORM_S8_UINT;
}
/* Deferred destroy storage */
renderer->texturesToDestroyCapacity = 16;