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: Allow MSAA on modern-ish mobile devices, but add a little warning sign. #18472

Merged
merged 1 commit into from
Dec 3, 2023
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
50 changes: 34 additions & 16 deletions Common/GPU/Vulkan/thin3d_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,22 +932,15 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)

// VkSampleCountFlagBits is arranged correctly for our purposes.
// Only support MSAA levels that have support for all three of color, depth, stencil.
if (!caps_.isTilingGPU) {
// Check for depth stencil resolve. Without it, depth textures won't work, and we don't want that mess
// of compatibility reports, so we'll just disable multisampling in this case for now.
// There are potential workarounds for devices that don't support it, but those are nearly non-existent now.
const auto &resolveProperties = vulkan->GetPhysicalDeviceProperties().depthStencilResolve;
if (vulkan->Extensions().KHR_depth_stencil_resolve &&
((resolveProperties.supportedDepthResolveModes & resolveProperties.supportedStencilResolveModes) & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) != 0) {
caps_.multiSampleLevelsMask = (limits.framebufferColorSampleCounts & limits.framebufferDepthSampleCounts & limits.framebufferStencilSampleCounts);
} else {
caps_.multiSampleLevelsMask = 1;
}
} else {
caps_.multiSampleLevelsMask = 1;
}

if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) {
bool multisampleAllowed = true;

caps_.deviceID = deviceProps.deviceID;

if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) {
if (caps_.deviceID < 0x6000000) // On sub 6xx series GPUs, disallow multisample.
multisampleAllowed = false;

// Adreno 5xx devices, all known driver versions, fail to discard stencil when depth write is off.
// See: https://github.com/hrydgard/ppsspp/pull/11684
if (deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000) {
Expand Down Expand Up @@ -1007,13 +1000,38 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
bugs_.Infest(Bugs::UNIFORM_INDEXING_BROKEN);
}
}

if (isOldVersion) {
// Very rough heuristic.
multisampleAllowed = false;
}
}

if (!vulkan->Extensions().KHR_depth_stencil_resolve) {
INFO_LOG(G3D, "KHR_depth_stencil_resolve not supported, disabling multisampling");
}

// We limit multisampling functionality to reasonably recent and known-good tiling GPUs.
if (multisampleAllowed) {
// Check for depth stencil resolve. Without it, depth textures won't work, and we don't want that mess
// of compatibility reports, so we'll just disable multisampling in this case for now.
// There are potential workarounds for devices that don't support it, but those are nearly non-existent now.
const auto &resolveProperties = vulkan->GetPhysicalDeviceProperties().depthStencilResolve;
if (((resolveProperties.supportedDepthResolveModes & resolveProperties.supportedStencilResolveModes) & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) != 0) {
caps_.multiSampleLevelsMask = (limits.framebufferColorSampleCounts & limits.framebufferDepthSampleCounts & limits.framebufferStencilSampleCounts);
INFO_LOG(G3D, "Multisample levels mask: %d", caps_.multiSampleLevelsMask);
} else {
INFO_LOG(G3D, "Not enough depth/stencil resolve modes supported, disabling multisampling.");
caps_.multiSampleLevelsMask = 1;
}
} else {
caps_.multiSampleLevelsMask = 1;
}

// Vulkan can support this through input attachments and various extensions, but not worth
// the trouble.
caps_.framebufferFetchSupported = false;

caps_.deviceID = deviceProps.deviceID;
device_ = vulkan->GetDevice();

VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
Expand Down
9 changes: 7 additions & 2 deletions Common/UI/PopupScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void MessagePopupScreen::OnCompleted(DialogResult result) {
void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;

listView_ = parent->Add(new ListView(&adaptor_, hidden_)); //, new LinearLayoutParams(1.0)));
listView_ = parent->Add(new ListView(&adaptor_, hidden_, icons_)); //, new LinearLayoutParams(1.0)));
listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140);
listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice);
}
Expand Down Expand Up @@ -105,6 +105,7 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_,
std::bind(&PopupMultiChoice::ChoiceCallback, this, std::placeholders::_1));
popupScreen->SetHiddenChoices(hidden_);
popupScreen->SetChoiceIcons(icons_);
if (e.v)
popupScreen->SetPopupOrigin(e.v);
screenManager_->push(popupScreen);
Expand Down Expand Up @@ -623,8 +624,12 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) {
textPadding_.right = w + paddingX;

Choice::Draw(dc);
int imagePadding = 0;
if (rightIconImage_.isValid()) {
imagePadding = bounds_.h;
}
dc.SetFontScale(scale, scale);
Bounds valueBounds(bounds_.x2() - textPadding_.right, bounds_.y, w, bounds_.h);
Bounds valueBounds(bounds_.x2() - textPadding_.right - imagePadding, bounds_.y, w, bounds_.h);
dc.DrawTextRect(valueText.c_str(), valueBounds, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER | FLAG_WRAP_TEXT);
dc.SetFontScale(1.0f, 1.0f);
} else {
Expand Down
8 changes: 8 additions & 0 deletions Common/UI/PopupScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class ListPopupScreen : public PopupScreen {
void SetHiddenChoices(std::set<int> hidden) {
hidden_ = hidden;
}
void SetChoiceIcons(std::map<int, ImageID> icons) {
icons_ = icons;
}
const char *tag() const override { return "listpopup"; }

UI::Event OnChoice;
Expand All @@ -49,6 +52,7 @@ class ListPopupScreen : public PopupScreen {
std::function<void(int)> callback_;
bool showButtons_ = false;
std::set<int> hidden_;
std::map<int, ImageID> icons_;
};

class MessagePopupScreen : public PopupScreen {
Expand Down Expand Up @@ -231,6 +235,9 @@ class PopupMultiChoice : public AbstractChoiceWithValueDisplay {
void HideChoice(int c) {
hidden_.insert(c);
}
void SetChoiceIcon(int c, ImageID id) {
icons_[c] = id;
}

UI::Event OnChoice;

Expand All @@ -254,6 +261,7 @@ class PopupMultiChoice : public AbstractChoiceWithValueDisplay {
std::string valueText_;
bool restoreFocus_ = false;
std::set<int> hidden_;
std::map<int, ImageID> icons_;
};

// Allows passing in a dynamic vector of strings. Saves the string.
Expand Down
28 changes: 20 additions & 8 deletions Common/UI/ScrollView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,8 @@ void ScrollView::Update() {
}
}

ListView::ListView(ListAdaptor *a, std::set<int> hidden, LayoutParams *layoutParams)
: ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a), maxHeight_(0), hidden_(hidden) {

ListView::ListView(ListAdaptor *a, std::set<int> hidden, std::map<int, ImageID> icons, LayoutParams *layoutParams)
: ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a), maxHeight_(0), hidden_(hidden), icons_(icons) {
linLayout_ = new LinearLayout(ORIENT_VERTICAL);
linLayout_->SetSpacing(0.0f);
Add(linLayout_);
Expand All @@ -510,7 +509,12 @@ void ListView::CreateAllItems() {
// Let's not be clever yet, we'll just create them all up front and add them all in.
for (int i = 0; i < adaptor_->GetNumItems(); i++) {
if (hidden_.find(i) == hidden_.end()) {
View *v = linLayout_->Add(adaptor_->CreateItemView(i));
ImageID *imageID = nullptr;
auto iter = icons_.find(i);
if (iter != icons_.end()) {
imageID = &iter->second;
}
View *v = linLayout_->Add(adaptor_->CreateItemView(i, imageID));
adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, std::placeholders::_1));
}
}
Expand Down Expand Up @@ -538,8 +542,12 @@ EventReturn ListView::OnItemCallback(int num, EventParams &e) {
return EVENT_DONE;
}

View *ChoiceListAdaptor::CreateItemView(int index) {
return new Choice(items_[index]);
View *ChoiceListAdaptor::CreateItemView(int index, ImageID *optionalImageID) {
Choice *choice = new Choice(items_[index]);
if (optionalImageID) {
choice->SetIcon(*optionalImageID);
}
return choice;
}

bool ChoiceListAdaptor::AddEventCallback(View *view, std::function<EventReturn(EventParams &)> callback) {
Expand All @@ -549,8 +557,12 @@ bool ChoiceListAdaptor::AddEventCallback(View *view, std::function<EventReturn(E
}


View *StringVectorListAdaptor::CreateItemView(int index) {
return new Choice(items_[index], "", index == selected_);
View *StringVectorListAdaptor::CreateItemView(int index, ImageID *optionalImageID) {
Choice *choice = new Choice(items_[index], "", index == selected_);
if (optionalImageID) {
choice->SetIcon(*optionalImageID);
}
return choice;
}

bool StringVectorListAdaptor::AddEventCallback(View *view, std::function<EventReturn(EventParams &)> callback) {
Expand Down
9 changes: 5 additions & 4 deletions Common/UI/ScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class ScrollView : public ViewGroup {
class ListAdaptor {
public:
virtual ~ListAdaptor() {}
virtual View *CreateItemView(int index) = 0;
virtual View *CreateItemView(int index, ImageID *optionalImageID) = 0;
virtual int GetNumItems() = 0;
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams &)> callback) { return false; }
virtual std::string GetTitle(int index) const { return ""; }
Expand All @@ -100,7 +100,7 @@ class ListAdaptor {
class ChoiceListAdaptor : public ListAdaptor {
public:
ChoiceListAdaptor(const char *items[], int numItems) : items_(items), numItems_(numItems) {}
View *CreateItemView(int index) override;
View *CreateItemView(int index, ImageID *optionalImageID) override;
int GetNumItems() override { return numItems_; }
bool AddEventCallback(View *view, std::function<EventReturn(EventParams &)> callback) override;

Expand All @@ -114,7 +114,7 @@ class StringVectorListAdaptor : public ListAdaptor {
public:
StringVectorListAdaptor() : selected_(-1) {}
StringVectorListAdaptor(const std::vector<std::string> &items, int selected = -1) : items_(items), selected_(selected) {}
View *CreateItemView(int index) override;
View *CreateItemView(int index, ImageID *optionalImageID) override;
int GetNumItems() override { return (int)items_.size(); }
bool AddEventCallback(View *view, std::function<EventReturn(EventParams &)> callback) override;
void SetSelected(int sel) override { selected_ = sel; }
Expand All @@ -130,7 +130,7 @@ class StringVectorListAdaptor : public ListAdaptor {
// In the future, it might be smart and load/unload items as they go, but currently not.
class ListView : public ScrollView {
public:
ListView(ListAdaptor *a, std::set<int> hidden = std::set<int>(), LayoutParams *layoutParams = 0);
ListView(ListAdaptor *a, std::set<int> hidden = std::set<int>(), std::map<int, ImageID> icons = std::map<int, ImageID>(), LayoutParams *layoutParams = 0);

int GetSelected() { return adaptor_->GetSelected(); }
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
Expand All @@ -146,6 +146,7 @@ class ListView : public ScrollView {
LinearLayout *linLayout_;
float maxHeight_;
std::set<int> hidden_;
std::map<int, ImageID> icons_;
};

} // namespace UI
9 changes: 8 additions & 1 deletion UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,19 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED);
return UI::EVENT_DONE;
});
msaaChoice->SetDisabledPtr(&g_Config.bSoftwareRendering);
if (g_Config.iMultiSampleLevel > 1 && draw->GetDeviceCaps().isTilingGPU) {
msaaChoice->SetIcon(ImageID("I_WARNING"), 0.7f);
}
msaaChoice->SetEnabledFunc([] {
return !g_Config.bSoftwareRendering && !g_Config.bSkipBufferEffects;
});

// Hide unsupported levels.
for (int i = 1; i < 5; i++) {
if ((draw->GetDeviceCaps().multiSampleLevelsMask & (1 << i)) == 0) {
msaaChoice->HideChoice(i);
} else if (i > 0 && draw->GetDeviceCaps().isTilingGPU) {
msaaChoice->SetChoiceIcon(i, ImageID("I_WARNING"));
}
}
}
Expand Down