Skip to content

Commit

Permalink
Merge pull request #12661 from hrydgard/vulkan-check-for-16bit-format…
Browse files Browse the repository at this point in the history
…-support

Vulkan check for 16bit format support. Fixes running under MoltenVK.
  • Loading branch information
hrydgard authored Mar 1, 2020
2 parents eeafba1 + 25dcf8d commit 6b3cc36
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 43 deletions.
9 changes: 6 additions & 3 deletions Common/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,13 @@ class VulkanContext {
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata);
void DestroyDebugMsgCallback();

VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
VkPhysicalDevice GetPhysicalDevice(int n) const {
return physical_devices_[n];
}
int GetCurrentPhysicalDevice() const {
VkPhysicalDevice GetCurrentPhysicalDevice() const {
return physical_devices_[physical_device_];
}
int GetCurrentPhysicalDeviceIndex() const {
return physical_device_;
}
int GetNumPhysicalDevices() const {
Expand All @@ -202,7 +205,7 @@ class VulkanContext {

const PhysicalDeviceProps &GetPhysicalDeviceProperties(int i = -1) const {
if (i < 0)
i = GetCurrentPhysicalDevice();
i = GetCurrentPhysicalDeviceIndex();
return physicalDeviceProperties_[i];
}

Expand Down
37 changes: 36 additions & 1 deletion GPU/Vulkan/DepalettizeShaderVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.

#include "Common/ColorConv.h"
#include "Common/Vulkan/VulkanContext.h"
#include "GPU/GPUState.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
Expand Down Expand Up @@ -120,7 +121,7 @@ DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMod
return depal;
}

VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat, u32 clutHash, u32 *rawClut) {
VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat, u32 clutHash, u32 *rawClut, bool expandTo32bit) {
u32 clutId = GetClutID(clutFormat, clutHash);
auto oldtex = texCache_.find(clutId);
if (oldtex != texCache_.end()) {
Expand All @@ -131,7 +132,36 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat

VkComponentMapping componentMapping;
VkFormat destFormat = GetClutDestFormat(clutFormat, &componentMapping);

int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
int bpp = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
VkFormat dstFmt;
uint32_t *expanded = nullptr;
if (expandTo32bit && clutFormat != GE_CMODE_32BIT_ABGR8888) {
expanded = new uint32_t[texturePixels];
switch (clutFormat) {
case GE_CMODE_16BIT_ABGR4444:
ConvertRGBA4444ToRGBA8888(expanded, (const uint16_t *)rawClut, texturePixels);
break;
case GE_CMODE_16BIT_ABGR5551:
ConvertRGBA5551ToRGBA8888(expanded, (const uint16_t *)rawClut, texturePixels);
break;
case GE_CMODE_16BIT_BGR5650:
ConvertRGBA565ToRGBA8888(expanded, (const uint16_t *)rawClut, texturePixels);
break;
default:
break;
}
rawClut = expanded;
dstFmt = VK_FORMAT_R8G8B8A8_UNORM;
bpp = 4;
componentMapping.r = VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY;
componentMapping.g = VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY;
componentMapping.b = VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY;
componentMapping.a = VkComponentSwizzle::VK_COMPONENT_SWIZZLE_IDENTITY;
} else {
dstFmt = GetClutDestFormat(clutFormat, &componentMapping);
}

VulkanTexture *vktex = new VulkanTexture(vulkan_);
vktex->SetTag("DepalClut");
Expand All @@ -152,6 +182,11 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat
tex->texture = vktex;
tex->lastFrame = gpuStats.numFlips;
texCache_[clutId] = tex;

if (expandTo32bit) {
delete[] expanded;
}

return tex->texture;
}

Expand Down
2 changes: 1 addition & 1 deletion GPU/Vulkan/DepalettizeShaderVulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class DepalShaderCacheVulkan : public DepalShaderCacheCommon {

// This also uploads the palette and binds the correct texture.
DepalShaderVulkan *GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat);
VulkanTexture *GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut);
VulkanTexture *GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut, bool expandTo32bit);
void Clear();
void Decimate();

Expand Down
10 changes: 9 additions & 1 deletion GPU/Vulkan/GPU_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
features |= GPU_SUPPORTS_16BIT_FORMATS;
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH;
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
Expand All @@ -252,6 +251,15 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_ANISOTROPY;
}

uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16);
uint32_t fmt1555 = draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16);
uint32_t fmt565 = draw_->GetDataFormatSupport(Draw::DataFormat::R5G6B5_UNORM_PACK16);
if ((fmt4444 & Draw::FMT_TEXTURE) && (fmt565 & Draw::FMT_TEXTURE) && (fmt1555 & Draw::FMT_TEXTURE)) {
features |= GPU_SUPPORTS_16BIT_FORMATS;
} else {
INFO_LOG(G3D, "Deficient texture format support: 4444: %d 1555: %d 565: %d", fmt4444, fmt1555, fmt565);
}

if (PSP_CoreParameter().compat.flags().ClearToRAM) {
features |= GPU_USE_CLEAR_RAM_HACK;
}
Expand Down
11 changes: 8 additions & 3 deletions GPU/Vulkan/TextureCacheVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,12 +812,13 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr
uint32_t clutMode = gstate.clutformat & 0xFFFFFF;

bool useShaderDepal = framebufferManager_->GetCurrentRenderVFB() != framebuffer;
bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS);

if ((entry->status & TexCacheEntry::STATUS_DEPALETTIZE) && !g_Config.bDisableSlowFramebufEffects) {
if (useShaderDepal) {
depalShaderCache_->SetPushBuffer(drawEngine_->GetPushBufferForTextureData());
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_, expand32);
drawEngine_->SetDepalTexture(clutTexture ? clutTexture->GetImageView() : VK_NULL_HANDLE);
// Only point filtering enabled.
samplerKey.magFilt = false;
Expand All @@ -844,7 +845,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr
if (depalShader) {
depalShaderCache_->SetPushBuffer(drawEngine_->GetPushBufferForTextureData());
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_, expand32);

Draw::Framebuffer *depalFBO = framebufferManager_->GetTempFBO(TempFBO::DEPAL, framebuffer->renderWidth, framebuffer->renderHeight, Draw::FBO_8888);
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
Expand Down Expand Up @@ -1271,6 +1272,9 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
}

VkFormat TextureCacheVulkan::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const {
if (!gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS)) {
return VK_FORMAT_R8G8B8A8_UNORM;
}
switch (format) {
case GE_TFMT_CLUT4:
case GE_TFMT_CLUT8:
Expand Down Expand Up @@ -1336,7 +1340,8 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
decPitch = w * bpp;
}

DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false);
bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS);
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32);
gpuStats.numTexturesDecoded++;

// We check before scaling since scaling shouldn't invent alpha from a full alpha texture.
Expand Down
6 changes: 6 additions & 0 deletions ext/native/thin3d/VulkanQueueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,8 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
case VKRRenderCommand::DRAW_INDEXED:
steps[i]->commands.push_back(steps[j]->commands[k]);
break;
default:
break;
}
}
steps[j]->stepType = VKRStepType::RENDER_SKIP;
Expand All @@ -619,6 +621,8 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
case VKRRenderCommand::DRAW_INDEXED:
steps[i + 1]->commands.push_back(steps[j]->commands[k]);
break;
default:
break;
}
}
steps[j]->stepType = VKRStepType::RENDER_SKIP;
Expand Down Expand Up @@ -804,6 +808,8 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector<VKRStep *> &steps) {
goto done_fb;
}
break;
default:
break;
}
}
done_fb:
Expand Down
55 changes: 21 additions & 34 deletions ext/native/thin3d/thin3d_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,13 +565,16 @@ VkFormat DataFormatToVulkan(DataFormat format) {
case DataFormat::R8G8B8_UNORM: return VK_FORMAT_R8G8B8_UNORM;
case DataFormat::R8G8B8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM;
case DataFormat::R4G4_UNORM_PACK8: return VK_FORMAT_R4G4_UNORM_PACK8;

// Note: A4R4G4B4_UNORM_PACK16 is not supported.
case DataFormat::R4G4B4A4_UNORM_PACK16: return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
case DataFormat::B4G4R4A4_UNORM_PACK16: return VK_FORMAT_B4G4R4A4_UNORM_PACK16;
case DataFormat::R5G5B5A1_UNORM_PACK16: return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
case DataFormat::B5G5R5A1_UNORM_PACK16: return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
case DataFormat::R5G6B5_UNORM_PACK16: return VK_FORMAT_R5G6B5_UNORM_PACK16;
case DataFormat::B5G6R5_UNORM_PACK16: return VK_FORMAT_B5G6R5_UNORM_PACK16;
case DataFormat::A1R5G5B5_UNORM_PACK16: return VK_FORMAT_A1R5G5B5_UNORM_PACK16;

case DataFormat::R32_FLOAT: return VK_FORMAT_R32_SFLOAT;
case DataFormat::R32G32_FLOAT: return VK_FORMAT_R32G32_SFLOAT;
case DataFormat::R32G32B32_FLOAT: return VK_FORMAT_R32G32B32_SFLOAT;
Expand Down Expand Up @@ -740,7 +743,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case.
caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan.

auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).properties;
auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties;
switch (deviceProps.vendorID) {
case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
Expand Down Expand Up @@ -1346,41 +1349,25 @@ std::vector<std::string> VKContext::GetExtensionList() const {
}

uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const {
// TODO: Actually do proper checks
switch (fmt) {
case DataFormat::B8G8R8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::B4G4R4A4_UNORM_PACK16:
// This is the one that's guaranteed to be supported.
// A four-component, 16-bit packed unsigned normalized format that has a 4-bit B component in bits 12..15, a 4-bit
// G component in bits 8..11, a 4 - bit R component in bits 4..7, and a 4 - bit A component in bits 0..3
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::R4G4B4A4_UNORM_PACK16:
return 0;
case DataFormat::A4R4G4B4_UNORM_PACK16:
return 0;
case DataFormat::A1R5G5B5_UNORM_PACK16:
return FMT_RENDERTARGET | FMT_TEXTURE;

case DataFormat::R8G8B8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT;

case DataFormat::R32_FLOAT:
case DataFormat::R32G32_FLOAT:
case DataFormat::R32G32B32_FLOAT:
case DataFormat::R32G32B32A32_FLOAT:
return FMT_INPUTLAYOUT;
VkFormat vulkan_format = DataFormatToVulkan(fmt);
// TODO: Actually do proper check
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(vulkan_->GetCurrentPhysicalDevice(), vulkan_format, &properties);

case DataFormat::R8_UNORM:
return FMT_TEXTURE;

case DataFormat::BC1_RGBA_UNORM_BLOCK:
case DataFormat::BC2_UNORM_BLOCK:
case DataFormat::BC3_UNORM_BLOCK:
return FMT_TEXTURE;
default:
return 0;
uint32_t flags = 0;
if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
flags |= FMT_RENDERTARGET;
}
if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
flags |= FMT_DEPTHSTENCIL;
}
if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
flags |= FMT_TEXTURE;
}
if (properties.bufferFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) {
flags |= FMT_INPUTLAYOUT;
}
return flags;
}

// A VKFramebuffer is a VkFramebuffer (note caps difference) plus all the textures it owns.
Expand Down

0 comments on commit 6b3cc36

Please sign in to comment.