Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan check for 16bit format support. Fixes running under MoltenVK. #12661

Merged
merged 2 commits into from
Mar 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation faux pas?

-[Unknown]

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about faux pas, but definitely a silly mistake. Being sloppy after burning a lot of energy on the atlas stuff yesterday...

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a TODO?

-[Unknown]

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, nope.

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