[UI] Image post-processing and full presentation/window rework

[GPU] Add FXAA post-processing
[UI] Add FidelityFX FSR and CAS post-processing
[UI] Add blue noise dithering from 10bpc to 8bpc
[GPU] Apply the DC PWL gamma ramp closer to the spec, supporting fully white color
[UI] Allow the GPU CP thread to present on the host directly, bypassing the UI thread OS paint event
[UI] Allow variable refresh rate (or tearing)
[UI] Present the newest frame (restart) on DXGI
[UI] Replace GraphicsContext with a far more advanced Presenter with more coherent surface connection and UI overlay state management
[UI] Connect presentation to windows via the Surface class, not native window handles
[Vulkan] Switch to simpler Vulkan setup with no instance/device separation due to interdependencies and to pass fewer objects around
[Vulkan] Lower the minimum required Vulkan version to 1.0
[UI/GPU] Various cleanup, mainly ComPtr usage
[UI] Support per-monitor DPI awareness v2 on Windows
[UI] DPI-scale Dear ImGui
[UI] Replace the remaining non-detachable window delegates with unified window event and input listeners
[UI] Allow listeners to safely destroy or close the window, and to register/unregister listeners without use-after-free and the ABA problem
[UI] Explicit Z ordering of input listeners and UI overlays, top-down for input, bottom-up for drawing
[UI] Add explicit window lifecycle phases
[UI] Replace Window virtual functions with explicit desired state, its application, actual state, its feedback
[UI] GTK: Apply the initial size to the drawing area
[UI] Limit internal UI frame rate to that of the monitor
[UI] Hide the cursor using a timer instead of polling due to no repeated UI thread paints with GPU CP thread presentation, and only within the window
This commit is contained in:
Triang3l 2022-01-29 13:22:03 +03:00
parent 372bdd3ec9
commit fe3f0f26e4
429 changed files with 75942 additions and 18360 deletions

6
.gitmodules vendored
View File

@ -76,3 +76,9 @@
[submodule "third_party/premake-androidndk"]
path = third_party/premake-androidndk
url = https://github.com/Triang3l/premake-androidndk.git
[submodule "third_party/FidelityFX-CAS"]
path = third_party/FidelityFX-CAS
url = https://github.com/GPUOpen-Effects/FidelityFX-CAS.git
[submodule "third_party/FidelityFX-FSR"]
path = third_party/FidelityFX-FSR
url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git

View File

@ -2,13 +2,20 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/app/emulator_window.h"
#include <filesystem>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include "third_party/fmt/include/fmt/format.h"
#include "third_party/imgui/imgui.h"
#include "xenia/base/assert.h"
@ -20,11 +27,17 @@
#include "xenia/base/profiling.h"
#include "xenia/base/system.h"
#include "xenia/base/threading.h"
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/ui/file_picker.h"
#include "xenia/ui/graphics_provider.h"
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/ui_event.h"
#include "xenia/ui/virtual_key.h"
// Autogenerated by `xb premake`.
@ -32,13 +45,91 @@
DECLARE_bool(debug);
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
"Display");
DEFINE_string(
postprocess_antialiasing, "",
"Post-processing anti-aliasing effect to apply to the image output of the "
"game.\n"
"Using post-process anti-aliasing is heavily recommended when AMD "
"FidelityFX Contrast Adaptive Sharpening or Super Resolution 1.0 is "
"active.\n"
"Use: [none, fxaa, fxaa_extreme]\n"
" none (or any value not listed here):\n"
" Don't alter the original image.\n"
" fxaa:\n"
" NVIDIA Fast Approximate Anti-Aliasing 3.11, normal quality preset (12)."
"\n"
" fxaa_extreme:\n"
" NVIDIA Fast Approximate Anti-Aliasing 3.11, extreme quality preset "
"(39).",
"Display");
DEFINE_string(
postprocess_scaling_and_sharpening, "",
"Post-processing effect to use for resampling and/or sharpening of the "
"final display output.\n"
"Use: [bilinear, cas, fsr]\n"
" bilinear (or any value not listed here):\n"
" Original image at 1:1, simple bilinear stretching for resampling.\n"
" cas:\n"
" Use AMD FidelityFX Contrast Adaptive Sharpening (CAS) for sharpening "
"at scaling factors of up to 2x2, with additional bilinear stretching for "
"larger factors.\n"
" fsr:\n"
" Use AMD FidelityFX Super Resolution 1.0 (FSR) for highest-quality "
"upscaling, or AMD FidelityFX Contrast Adaptive Sharpening for sharpening "
"while not scaling or downsampling.\n"
" For scaling by factors of more than 2x2, multiple FSR passes are done.",
"Display");
DEFINE_double(
postprocess_ffx_cas_additional_sharpness,
xe::ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessDefault,
"Additional sharpness for AMD FidelityFX Contrast Adaptive Sharpening "
"(CAS), from 0 to 1.\n"
"Higher is sharper.",
"Display");
DEFINE_uint32(
postprocess_ffx_fsr_max_upsampling_passes,
xe::ui::Presenter::GuestOutputPaintConfig::kFsrMaxUpscalingPassesMax,
"Maximum number of upsampling passes performed in AMD FidelityFX Super "
"Resolution 1.0 (FSR) before falling back to bilinear stretching after the "
"final pass.\n"
"Each pass upscales only to up to 2x2 the previous size. If the game "
"outputs a 1280x720 image, 1 pass will upscale it to up to 2560x1440 "
"(below 4K), after 2 passes it will be upscaled to a maximum of 5120x2880 "
"(including 3840x2160 for 4K), and so on.\n"
"This variable has no effect if the display resolution isn't very high, "
"but may be reduced on resolutions like 4K or 8K in case the performance "
"impact of multiple FSR upsampling passes is too high, or if softer edges "
"are desired.\n"
"The default value is the maximum internally supported by Xenia.",
"Display");
DEFINE_double(
postprocess_ffx_fsr_sharpness_reduction,
xe::ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionDefault,
"Sharpness reduction for AMD FidelityFX Super Resolution 1.0 (FSR), in "
"stops.\n"
"Lower is sharper.",
"Display");
// Dithering to 8bpc is enabled by default since the effect is minor, only
// effects what can't be shown normally by host displays, and nothing is changed
// by it for 8bpc source without resampling.
DEFINE_bool(
postprocess_dither, true,
"Dither the final image output from the internal precision to 8 bits per "
"channel so gradients are smoother.\n"
"On a 10bpc display, the lower 2 bits will still be kept, but noise will "
"be added to them - disabling may be recommended for 10bpc, but it "
"depends on the 10bpc displaying capabilities of the actual display used.",
"Display");
namespace xe {
namespace app {
using xe::ui::FileDropEvent;
using xe::ui::KeyEvent;
using xe::ui::MenuItem;
using xe::ui::MouseEvent;
using xe::ui::UIEvent;
const std::string kBaseTitle = "Xenia";
@ -47,7 +138,12 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator,
ui::WindowedAppContext& app_context)
: emulator_(emulator),
app_context_(app_context),
window_(ui::Window::Create(app_context, kBaseTitle)) {
window_listener_(*this),
window_(ui::Window::Create(app_context, kBaseTitle, 1280, 720)),
imgui_drawer_(
std::make_unique<ui::ImGuiDrawer>(window_.get(), kZOrderImGui)),
display_config_game_config_load_callback_(
new DisplayConfigGameConfigLoadCallback(*emulator, *this)) {
base_title_ = kBaseTitle +
#ifdef DEBUG
#if _NO_DEBUG_HEAP == 1
@ -76,109 +172,327 @@ std::unique_ptr<EmulatorWindow> EmulatorWindow::Create(
return emulator_window;
}
EmulatorWindow::~EmulatorWindow() {
// Notify the ImGui drawer that the immediate drawer is being destroyed.
ShutdownGraphicsSystemPresenterPainting();
}
ui::Presenter* EmulatorWindow::GetGraphicsSystemPresenter() const {
gpu::GraphicsSystem* graphics_system = emulator_->graphics_system();
return graphics_system ? graphics_system->presenter() : nullptr;
}
void EmulatorWindow::SetupGraphicsSystemPresenterPainting() {
ShutdownGraphicsSystemPresenterPainting();
if (!window_) {
return;
}
ui::Presenter* presenter = GetGraphicsSystemPresenter();
if (!presenter) {
return;
}
ApplyDisplayConfigForCvars();
window_->SetPresenter(presenter);
immediate_drawer_ =
emulator_->graphics_system()->provider()->CreateImmediateDrawer();
if (immediate_drawer_) {
immediate_drawer_->SetPresenter(presenter);
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter,
immediate_drawer_.get());
Profiler::SetUserIO(kZOrderProfiler, window_.get(), presenter,
immediate_drawer_.get());
}
}
void EmulatorWindow::ShutdownGraphicsSystemPresenterPainting() {
Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr);
imgui_drawer_->SetPresenterAndImmediateDrawer(nullptr, nullptr);
immediate_drawer_.reset();
if (window_) {
window_->SetPresenter(nullptr);
}
}
void EmulatorWindow::OnEmulatorInitialized() {
emulator_initialized_ = true;
window_->SetMainMenuEnabled(true);
// When the user can see that the emulator isn't initializing anymore (the
// menu isn't disabled), enter fullscreen if requested.
if (cvars::fullscreen) {
window_->SetFullscreen(true);
}
}
void EmulatorWindow::EmulatorWindowListener::OnClosing(ui::UIEvent& e) {
emulator_window_.app_context_.QuitFromUIThread();
}
void EmulatorWindow::EmulatorWindowListener::OnFileDrop(ui::FileDropEvent& e) {
emulator_window_.FileDrop(e.filename());
}
void EmulatorWindow::EmulatorWindowListener::OnKeyDown(ui::KeyEvent& e) {
emulator_window_.OnKeyDown(e);
}
void EmulatorWindow::DisplayConfigGameConfigLoadCallback::PostGameConfigLoad() {
emulator_window_.ApplyDisplayConfigForCvars();
}
void EmulatorWindow::DisplayConfigDialog::OnDraw(ImGuiIO& io) {
gpu::GraphicsSystem* graphics_system =
emulator_window_.emulator_->graphics_system();
if (!graphics_system) {
return;
}
// In the top-left corner so it's close to the menu bar from where it was
// opened.
// Origin Y coordinate 20 was taken from the Dear ImGui demo.
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(20, 20), ImGuiCond_FirstUseEver);
// Alpha from Dear ImGui tooltips (0.35 from the overlay provides too low
// visibility). Translucent so some effect of the changes can still be seen
// through it.
ImGui::SetNextWindowBgAlpha(0.6f);
bool dialog_open = true;
if (!ImGui::Begin("Post-processing", &dialog_open,
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_HorizontalScrollbar)) {
ImGui::End();
return;
}
// Even if the close button has been pressed, still paint everything not to
// have one frame with an empty window.
gpu::CommandProcessor* command_processor =
graphics_system->command_processor();
if (command_processor) {
if (ImGui::TreeNodeEx(
"Anti-aliasing",
ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) {
gpu::CommandProcessor::SwapPostEffect current_swap_post_effect =
command_processor->GetDesiredSwapPostEffect();
int new_swap_post_effect_index = int(current_swap_post_effect);
ImGui::RadioButton("None", &new_swap_post_effect_index,
int(gpu::CommandProcessor::SwapPostEffect::kNone));
ImGui::RadioButton(
"NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), normal quality",
&new_swap_post_effect_index,
int(gpu::CommandProcessor::SwapPostEffect::kFxaa));
ImGui::RadioButton(
"NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), extreme quality",
&new_swap_post_effect_index,
int(gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme));
gpu::CommandProcessor::SwapPostEffect new_swap_post_effect =
gpu::CommandProcessor::SwapPostEffect(new_swap_post_effect_index);
if (current_swap_post_effect != new_swap_post_effect) {
command_processor->SetDesiredSwapPostEffect(new_swap_post_effect);
}
// Override the values in the cvars to save them to the config at exit if
// the user has set them to anything new.
if (GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing) !=
new_swap_post_effect) {
OVERRIDE_string(postprocess_antialiasing,
GetCvarValueForSwapPostEffect(new_swap_post_effect));
}
ImGui::TreePop();
}
}
ui::Presenter* presenter = graphics_system->presenter();
if (presenter) {
const ui::Presenter::GuestOutputPaintConfig& current_presenter_config =
presenter->GetGuestOutputPaintConfigFromUIThread();
ui::Presenter::GuestOutputPaintConfig new_presenter_config =
current_presenter_config;
if (ImGui::TreeNodeEx(
"Resampling and sharpening",
ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) {
// Filtering effect.
int new_effect_index = int(new_presenter_config.GetEffect());
ImGui::RadioButton(
"None / bilinear", &new_effect_index,
int(ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear));
ImGui::RadioButton(
"AMD FidelityFX Contrast Adaptive Sharpening (CAS)",
&new_effect_index,
int(ui::Presenter::GuestOutputPaintConfig::Effect::kCas));
ImGui::RadioButton(
"AMD FidelityFX Super Resolution 1.0 (FSR)", &new_effect_index,
int(ui::Presenter::GuestOutputPaintConfig::Effect::kFsr));
new_presenter_config.SetEffect(
ui::Presenter::GuestOutputPaintConfig::Effect(new_effect_index));
// effect_description must be one complete, but short enough, sentence per
// line, as TextWrapped doesn't work correctly in auto-resizing windows
// (in the initial frames, the window becomes extremely tall, and widgets
// added after the wrapped text have no effect on the width of the text).
const char* effect_description = nullptr;
switch (new_presenter_config.GetEffect()) {
case ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear:
effect_description =
"Simple bilinear filtering is done if resampling is needed.\n"
"Otherwise, only anti-aliasing is done if enabled, or displaying "
"as is.";
break;
case ui::Presenter::GuestOutputPaintConfig::Effect::kCas:
effect_description =
"Sharpening and resampling to up to 2x2 to improve the fidelity "
"of details.\n"
"For scaling by more than 2x2, bilinear stretching is done "
"afterwards.";
break;
case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr:
effect_description =
"High-quality edge-preserving upscaling to arbitrary target "
"resolutions.\n"
"For scaling by more than 2x2, multiple upsampling passes are "
"done.\n"
"If not upscaling, Contrast Adaptive Sharpening (CAS) is used "
"instead.";
break;
}
if (effect_description) {
ImGui::TextUnformatted(effect_description);
}
if (new_presenter_config.GetEffect() ==
ui::Presenter::GuestOutputPaintConfig::Effect::kCas ||
new_presenter_config.GetEffect() ==
ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) {
if (effect_description) {
ImGui::Spacing();
}
ImGui::TextUnformatted(
"FXAA is highly recommended when using CAS or FSR.");
ImGui::Spacing();
// 2 decimal places is more or less enough precision for the sharpness
// given the minor visual effect of small changes, the width of the
// slider, and readability convenience (2 decimal places is like an
// integer percentage). However, because Dear ImGui parses the string
// representation of the number and snaps the value to it internally,
// 2 decimal places actually offer less precision than the slider itself
// does. This is especially prominent in the low range of the non-linear
// FSR sharpness reduction slider. 3 decimal places are optimal in this
// case.
if (new_presenter_config.GetEffect() ==
ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) {
float fsr_sharpness_reduction =
new_presenter_config.GetFsrSharpnessReduction();
ImGui::TextUnformatted(
"FSR sharpness reduction when upscaling (lower is sharper):");
// Power 2.0 as the reduction is in stops, used in exp2.
ImGui::SliderFloat(
"##FSRSharpnessReduction", &fsr_sharpness_reduction,
ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMin,
ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMax,
"%.3f stops", 2.0f);
ImGui::SameLine();
if (ImGui::Button("Reset##ResetFSRSharpnessReduction")) {
fsr_sharpness_reduction = ui::Presenter::GuestOutputPaintConfig ::
kFsrSharpnessReductionDefault;
}
new_presenter_config.SetFsrSharpnessReduction(
fsr_sharpness_reduction);
}
float cas_additional_sharpness =
new_presenter_config.GetCasAdditionalSharpness();
ImGui::TextUnformatted(
new_presenter_config.GetEffect() ==
ui::Presenter::GuestOutputPaintConfig::Effect::kFsr
? "CAS additional sharpness when not upscaling (higher is "
"sharper):"
: "CAS additional sharpness (higher is sharper):");
ImGui::SliderFloat(
"##CASAdditionalSharpness", &cas_additional_sharpness,
ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMin,
ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMax,
"%.3f");
ImGui::SameLine();
if (ImGui::Button("Reset##ResetCASAdditionalSharpness")) {
cas_additional_sharpness = ui::Presenter::GuestOutputPaintConfig ::
kCasAdditionalSharpnessDefault;
}
new_presenter_config.SetCasAdditionalSharpness(
cas_additional_sharpness);
// There's no need to expose the setting for the maximum number of FSR
// EASU passes as it's largely meaningless if the user doesn't have a
// very high-resolution monitor compared to the original image size as
// most of the values of the slider will have no effect, and that's just
// very fine-grained performance control for a fixed-overhead pass only
// for huge screen resolutions.
}
ImGui::TreePop();
}
if (ImGui::TreeNodeEx("Dithering", ImGuiTreeNodeFlags_Framed |
ImGuiTreeNodeFlags_DefaultOpen)) {
bool dither = current_presenter_config.GetDither();
ImGui::Checkbox(
"Dither the final output to 8bpc to make gradients smoother",
&dither);
new_presenter_config.SetDither(dither);
ImGui::TreePop();
}
presenter->SetGuestOutputPaintConfigFromUIThread(new_presenter_config);
// Override the values in the cvars to save them to the config at exit if
// the user has set them to anything new.
ui::Presenter::GuestOutputPaintConfig cvars_presenter_config =
GetGuestOutputPaintConfigForCvars();
if (cvars_presenter_config.GetEffect() !=
new_presenter_config.GetEffect()) {
OVERRIDE_string(postprocess_scaling_and_sharpening,
GetCvarValueForGuestOutputPaintEffect(
new_presenter_config.GetEffect()));
}
if (cvars_presenter_config.GetCasAdditionalSharpness() !=
new_presenter_config.GetCasAdditionalSharpness()) {
OVERRIDE_double(postprocess_ffx_cas_additional_sharpness,
new_presenter_config.GetCasAdditionalSharpness());
}
if (cvars_presenter_config.GetFsrSharpnessReduction() !=
new_presenter_config.GetFsrSharpnessReduction()) {
OVERRIDE_double(postprocess_ffx_fsr_sharpness_reduction,
new_presenter_config.GetFsrSharpnessReduction());
}
if (cvars_presenter_config.GetDither() !=
new_presenter_config.GetDither()) {
OVERRIDE_bool(postprocess_dither, new_presenter_config.GetDither());
}
}
ImGui::End();
if (!dialog_open) {
emulator_window_.ToggleDisplayConfigDialog();
// `this` might have been destroyed by ToggleDisplayConfigDialog.
return;
}
}
bool EmulatorWindow::Initialize() {
if (!window_->Initialize()) {
XELOGE("Failed to initialize platform window");
return false;
}
UpdateTitle();
window_->on_closed.AddListener(
[this](UIEvent* e) { app_context_.QuitFromUIThread(); });
window_->on_file_drop.AddListener(
[this](FileDropEvent* e) { FileDrop(e->filename()); });
window_->on_key_down.AddListener([this](KeyEvent* e) {
bool handled = true;
switch (e->virtual_key()) {
case ui::VirtualKey::kO: {
if (e->is_ctrl_pressed()) {
FileOpen();
}
} break;
case ui::VirtualKey::kMultiply: {
CpuTimeScalarReset();
} break;
case ui::VirtualKey::kSubtract: {
CpuTimeScalarSetHalf();
} break;
case ui::VirtualKey::kAdd: {
CpuTimeScalarSetDouble();
} break;
case ui::VirtualKey::kF3: {
Profiler::ToggleDisplay();
} break;
case ui::VirtualKey::kF4: {
GpuTraceFrame();
} break;
case ui::VirtualKey::kF5: {
GpuClearCaches();
} break;
#ifdef DEBUG
case ui::VirtualKey::kF7: {
// Save to file
// TODO: Choose path based on user input, or from options
// TODO: Spawn a new thread to do this.
emulator()->SaveToFile("test.sav");
} break;
case ui::VirtualKey::kF8: {
// Restore from file
// TODO: Choose path from user
// TODO: Spawn a new thread to do this.
emulator()->RestoreFromFile("test.sav");
} break;
#endif // #ifdef DEBUG
case ui::VirtualKey::kF11: {
ToggleFullscreen();
} break;
case ui::VirtualKey::kEscape: {
// Allow users to escape fullscreen (but not enter it).
if (window_->is_fullscreen()) {
window_->ToggleFullscreen(false);
} else {
handled = false;
}
} break;
case ui::VirtualKey::kPause: {
CpuBreakIntoDebugger();
} break;
case ui::VirtualKey::kCancel: {
CpuBreakIntoHostDebugger();
} break;
case ui::VirtualKey::kF1: {
ShowHelpWebsite();
} break;
case ui::VirtualKey::kF2: {
ShowCommitID();
} break;
default: {
handled = false;
} break;
}
e->set_handled(handled);
});
window_->on_mouse_move.AddListener([this](MouseEvent* e) {
if (window_->is_fullscreen() && (e->dx() > 2 || e->dy() > 2)) {
if (!window_->is_cursor_visible()) {
window_->set_cursor_visible(true);
}
cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000;
}
e->set_handled(false);
});
window_->on_paint.AddListener([this](UIEvent* e) { CheckHideCursor(); });
window_->AddListener(&window_listener_);
window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput);
// Main menu.
// FIXME: This code is really messy.
@ -198,9 +512,9 @@ bool EmulatorWindow::Initialize() {
MenuItem::Type::kString, "Show content directory...",
std::bind(&EmulatorWindow::ShowContentDirectory, this)));
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "E&xit",
"Alt+F4",
[this]() { window_->Close(); }));
file_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, "E&xit", "Alt+F4",
[this]() { window_->RequestClose(); }));
}
main_menu->AddChild(std::move(file_menu));
@ -253,14 +567,20 @@ bool EmulatorWindow::Initialize() {
}
main_menu->AddChild(std::move(gpu_menu));
// Window menu.
auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Window");
// Display menu.
auto display_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Display");
{
window_menu->AddChild(
display_menu->AddChild(MenuItem::Create(
MenuItem::Type::kString, "&Post-processing settings", "F6",
std::bind(&EmulatorWindow::ToggleDisplayConfigDialog, this)));
}
display_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
{
display_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11",
std::bind(&EmulatorWindow::ToggleFullscreen, this)));
}
main_menu->AddChild(std::move(window_menu));
main_menu->AddChild(std::move(display_menu));
// Help menu.
auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Help");
@ -284,16 +604,196 @@ bool EmulatorWindow::Initialize() {
}
main_menu->AddChild(std::move(help_menu));
window_->set_main_menu(std::move(main_menu));
window_->SetMainMenu(std::move(main_menu));
window_->Resize(1280, 720);
window_->SetMainMenuEnabled(false);
window_->DisableMainMenu();
UpdateTitle();
if (!window_->Open()) {
XELOGE("Failed to open the platform window");
return false;
}
Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr);
return true;
}
const char* EmulatorWindow::GetCvarValueForSwapPostEffect(
gpu::CommandProcessor::SwapPostEffect effect) {
switch (effect) {
case gpu::CommandProcessor::SwapPostEffect::kFxaa:
return "fxaa";
case gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme:
return "fxaa_extreme";
default:
return "";
}
}
gpu::CommandProcessor::SwapPostEffect
EmulatorWindow::GetSwapPostEffectForCvarValue(const std::string& cvar_value) {
if (cvar_value == GetCvarValueForSwapPostEffect(
gpu::CommandProcessor::SwapPostEffect::kFxaa)) {
return gpu::CommandProcessor::SwapPostEffect::kFxaa;
}
if (cvar_value == GetCvarValueForSwapPostEffect(
gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme)) {
return gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme;
}
return gpu::CommandProcessor::SwapPostEffect::kNone;
}
const char* EmulatorWindow::GetCvarValueForGuestOutputPaintEffect(
ui::Presenter::GuestOutputPaintConfig::Effect effect) {
switch (effect) {
case ui::Presenter::GuestOutputPaintConfig::Effect::kCas:
return "cas";
case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr:
return "fsr";
default:
return "";
}
}
ui::Presenter::GuestOutputPaintConfig::Effect
EmulatorWindow::GetGuestOutputPaintEffectForCvarValue(
const std::string& cvar_value) {
if (cvar_value == GetCvarValueForGuestOutputPaintEffect(
ui::Presenter::GuestOutputPaintConfig::Effect::kCas)) {
return ui::Presenter::GuestOutputPaintConfig::Effect::kCas;
}
if (cvar_value == GetCvarValueForGuestOutputPaintEffect(
ui::Presenter::GuestOutputPaintConfig::Effect::kFsr)) {
return ui::Presenter::GuestOutputPaintConfig::Effect::kFsr;
}
return ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear;
}
ui::Presenter::GuestOutputPaintConfig
EmulatorWindow::GetGuestOutputPaintConfigForCvars() {
ui::Presenter::GuestOutputPaintConfig paint_config;
paint_config.SetEffect(GetGuestOutputPaintEffectForCvarValue(
cvars::postprocess_scaling_and_sharpening));
paint_config.SetCasAdditionalSharpness(
float(cvars::postprocess_ffx_cas_additional_sharpness));
paint_config.SetFsrMaxUpsamplingPasses(
cvars::postprocess_ffx_fsr_max_upsampling_passes);
paint_config.SetFsrSharpnessReduction(
float(cvars::postprocess_ffx_fsr_sharpness_reduction));
paint_config.SetDither(cvars::postprocess_dither);
return paint_config;
}
void EmulatorWindow::ApplyDisplayConfigForCvars() {
gpu::GraphicsSystem* graphics_system = emulator_->graphics_system();
if (!graphics_system) {
return;
}
gpu::CommandProcessor* command_processor =
graphics_system->command_processor();
if (command_processor) {
command_processor->SetDesiredSwapPostEffect(
GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing));
}
ui::Presenter* presenter = graphics_system->presenter();
if (presenter) {
presenter->SetGuestOutputPaintConfigFromUIThread(
GetGuestOutputPaintConfigForCvars());
}
}
void EmulatorWindow::OnKeyDown(ui::KeyEvent& e) {
if (!emulator_initialized_) {
return;
}
switch (e.virtual_key()) {
case ui::VirtualKey::kO: {
if (!e.is_ctrl_pressed()) {
return;
}
FileOpen();
} break;
case ui::VirtualKey::kMultiply: {
CpuTimeScalarReset();
} break;
case ui::VirtualKey::kSubtract: {
CpuTimeScalarSetHalf();
} break;
case ui::VirtualKey::kAdd: {
CpuTimeScalarSetDouble();
} break;
case ui::VirtualKey::kF3: {
Profiler::ToggleDisplay();
} break;
case ui::VirtualKey::kF4: {
GpuTraceFrame();
} break;
case ui::VirtualKey::kF5: {
GpuClearCaches();
} break;
case ui::VirtualKey::kF6: {
ToggleDisplayConfigDialog();
} break;
case ui::VirtualKey::kF11: {
ToggleFullscreen();
} break;
case ui::VirtualKey::kEscape: {
// Allow users to escape fullscreen (but not enter it).
if (!window_->IsFullscreen()) {
return;
}
SetFullscreen(false);
} break;
#ifdef DEBUG
case ui::VirtualKey::kF7: {
// Save to file
// TODO: Choose path based on user input, or from options
// TODO: Spawn a new thread to do this.
emulator()->SaveToFile("test.sav");
} break;
case ui::VirtualKey::kF8: {
// Restore from file
// TODO: Choose path from user
// TODO: Spawn a new thread to do this.
emulator()->RestoreFromFile("test.sav");
} break;
#endif // #ifdef DEBUG
case ui::VirtualKey::kPause: {
CpuBreakIntoDebugger();
} break;
case ui::VirtualKey::kCancel: {
CpuBreakIntoHostDebugger();
} break;
case ui::VirtualKey::kF1: {
ShowHelpWebsite();
} break;
case ui::VirtualKey::kF2: {
ShowCommitID();
} break;
default:
return;
}
e.set_handled(true);
}
void EmulatorWindow::FileDrop(const std::filesystem::path& filename) {
if (!emulator_initialized_) {
return;
}
auto result = emulator_->LaunchPath(filename);
if (XFAILED(result)) {
// TODO: Display a message box.
@ -316,7 +816,7 @@ void EmulatorWindow::FileOpen() {
//{"Content Package (*.xcp)", "*.xcp" },
{"All Files (*.*)", "*.*"},
});
if (file_picker->Show(window_->native_handle())) {
if (file_picker->Show(window_.get())) {
auto selected_files = file_picker->selected_files();
if (!selected_files.empty()) {
path = selected_files[0];
@ -361,17 +861,6 @@ void EmulatorWindow::ShowContentDirectory() {
LaunchFileExplorer(target_path);
}
void EmulatorWindow::CheckHideCursor() {
if (!window_->is_fullscreen()) {
// Only hide when fullscreen.
return;
}
if (Clock::QueryHostSystemTime() > cursor_hide_time_) {
window_->set_cursor_visible(false);
}
}
void EmulatorWindow::CpuTimeScalarReset() {
Clock::set_guest_time_scalar(1.0);
UpdateTitle();
@ -389,7 +878,7 @@ void EmulatorWindow::CpuTimeScalarSetDouble() {
void EmulatorWindow::CpuBreakIntoDebugger() {
if (!cvars::debug) {
xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger",
xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Xenia Debugger",
"Xenia must be launched with the "
"--debug flag in order to enable "
"debugging.");
@ -415,13 +904,26 @@ void EmulatorWindow::GpuClearCaches() {
emulator()->graphics_system()->ClearCaches();
}
void EmulatorWindow::ToggleFullscreen() {
window_->ToggleFullscreen(!window_->is_fullscreen());
void EmulatorWindow::SetFullscreen(bool fullscreen) {
if (window_->IsFullscreen() == fullscreen) {
return;
}
window_->SetFullscreen(fullscreen);
window_->SetCursorVisibility(fullscreen
? ui::Window::CursorVisibility::kAutoHidden
: ui::Window::CursorVisibility::kVisible);
}
// Hide the cursor after a second if we're going fullscreen
cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000;
if (!window_->is_fullscreen()) {
window_->set_cursor_visible(true);
void EmulatorWindow::ToggleFullscreen() {
SetFullscreen(!window_->IsFullscreen());
}
void EmulatorWindow::ToggleDisplayConfigDialog() {
if (!display_config_dialog_) {
display_config_dialog_ = std::unique_ptr<DisplayConfigDialog>(
new DisplayConfigDialog(imgui_drawer_.get(), *this));
} else {
display_config_dialog_.reset();
}
}
@ -477,7 +979,7 @@ void EmulatorWindow::UpdateTitle() {
sb.Append(u8" (Preloading shaders\u2026)");
}
window_->set_title(sb.to_string_view());
window_->SetTitle(sb.to_string_view());
}
void EmulatorWindow::SetInitializingShaderStorage(bool initializing) {

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -13,42 +13,124 @@
#include <memory>
#include <string>
#include "xenia/emulator.h"
#include "xenia/gpu/command_processor.h"
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/menu_item.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/window.h"
#include "xenia/ui/window_listener.h"
#include "xenia/ui/windowed_app_context.h"
#include "xenia/xbox.h"
namespace xe {
class Emulator;
} // namespace xe
namespace xe {
namespace app {
class EmulatorWindow {
public:
enum : size_t {
// The UI is on top of the game and is open in special cases, so
// lowest-priority.
kZOrderHidInput,
kZOrderImGui,
kZOrderProfiler,
// Emulator window controls are expected to be always accessible by the
// user, so highest-priority.
kZOrderEmulatorWindowInput,
};
virtual ~EmulatorWindow();
static std::unique_ptr<EmulatorWindow> Create(
Emulator* emulator, ui::WindowedAppContext& app_context);
Emulator* emulator() const { return emulator_; }
ui::WindowedAppContext& app_context() const { return app_context_; }
ui::Window* window() const { return window_.get(); }
ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); }
ui::Presenter* GetGraphicsSystemPresenter() const;
void SetupGraphicsSystemPresenterPainting();
void ShutdownGraphicsSystemPresenterPainting();
void OnEmulatorInitialized();
void UpdateTitle();
void SetFullscreen(bool fullscreen);
void ToggleFullscreen();
void SetInitializingShaderStorage(bool initializing);
private:
class EmulatorWindowListener final : public ui::WindowListener,
public ui::WindowInputListener {
public:
explicit EmulatorWindowListener(EmulatorWindow& emulator_window)
: emulator_window_(emulator_window) {}
void OnClosing(ui::UIEvent& e) override;
void OnFileDrop(ui::FileDropEvent& e) override;
void OnKeyDown(ui::KeyEvent& e) override;
private:
EmulatorWindow& emulator_window_;
};
class DisplayConfigGameConfigLoadCallback
: public Emulator::GameConfigLoadCallback {
public:
DisplayConfigGameConfigLoadCallback(Emulator& emulator,
EmulatorWindow& emulator_window)
: Emulator::GameConfigLoadCallback(emulator),
emulator_window_(emulator_window) {}
void PostGameConfigLoad() override;
private:
EmulatorWindow& emulator_window_;
};
class DisplayConfigDialog final : public ui::ImGuiDialog {
public:
DisplayConfigDialog(ui::ImGuiDrawer* imgui_drawer,
EmulatorWindow& emulator_window)
: ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {}
protected:
void OnDraw(ImGuiIO& io) override;
private:
EmulatorWindow& emulator_window_;
};
explicit EmulatorWindow(Emulator* emulator,
ui::WindowedAppContext& app_context);
bool Initialize();
// For comparisons, use GetSwapPostEffectForCvarValue instead as the default
// fallback may be used for multiple values.
static const char* GetCvarValueForSwapPostEffect(
gpu::CommandProcessor::SwapPostEffect effect);
static gpu::CommandProcessor::SwapPostEffect GetSwapPostEffectForCvarValue(
const std::string& cvar_value);
// For comparisons, use GetGuestOutputPaintEffectForCvarValue instead as the
// default fallback may be used for multiple values.
static const char* GetCvarValueForGuestOutputPaintEffect(
ui::Presenter::GuestOutputPaintConfig::Effect effect);
static ui::Presenter::GuestOutputPaintConfig::Effect
GetGuestOutputPaintEffectForCvarValue(const std::string& cvar_value);
static ui::Presenter::GuestOutputPaintConfig
GetGuestOutputPaintConfigForCvars();
void ApplyDisplayConfigForCvars();
void OnKeyDown(ui::KeyEvent& e);
void FileDrop(const std::filesystem::path& filename);
void FileOpen();
void FileClose();
void ShowContentDirectory();
void CheckHideCursor();
void CpuTimeScalarReset();
void CpuTimeScalarSetHalf();
void CpuTimeScalarSetDouble();
@ -56,15 +138,26 @@ class EmulatorWindow {
void CpuBreakIntoHostDebugger();
void GpuTraceFrame();
void GpuClearCaches();
void ToggleDisplayConfigDialog();
void ShowHelpWebsite();
void ShowCommitID();
Emulator* emulator_;
ui::WindowedAppContext& app_context_;
EmulatorWindowListener window_listener_;
std::unique_ptr<ui::Window> window_;
std::unique_ptr<ui::ImGuiDrawer> imgui_drawer_;
std::unique_ptr<DisplayConfigGameConfigLoadCallback>
display_config_game_config_load_callback_;
// Creation may fail, in this case immediate drawer UI must not be drawn.
std::unique_ptr<ui::ImmediateDrawer> immediate_drawer_;
bool emulator_initialized_ = false;
std::string base_title_;
uint64_t cursor_hide_time_ = 0;
bool initializing_shader_storage_ = false;
std::unique_ptr<DisplayConfigDialog> display_config_dialog_;
};
} // namespace app

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -28,6 +28,7 @@
#include "xenia/emulator.h"
#include "xenia/ui/file_picker.h"
#include "xenia/ui/window.h"
#include "xenia/ui/window_listener.h"
#include "xenia/ui/windowed_app.h"
#include "xenia/ui/windowed_app_context.h"
#include "xenia/vfs/devices/host_path_device.h"
@ -62,8 +63,6 @@ DEFINE_string(gpu, "any", "Graphics system. Use: [any, d3d12, vulkan, null]",
DEFINE_string(hid, "any", "Input system. Use: [any, nop, sdl, winkey, xinput]",
"HID");
DEFINE_bool(fullscreen, false, "Toggles fullscreen", "GPU");
DEFINE_path(
storage_root, "",
"Root path for persistent internal data storage (config, etc.), or empty "
@ -192,6 +191,17 @@ class EmulatorApp final : public xe::ui::WindowedApp {
}
};
class DebugWindowClosedListener final : public xe::ui::WindowListener {
public:
explicit DebugWindowClosedListener(EmulatorApp& emulator_app)
: emulator_app_(emulator_app) {}
void OnClosing(xe::ui::UIEvent& e) override;
private:
EmulatorApp& emulator_app_;
};
explicit EmulatorApp(xe::ui::WindowedAppContext& app_context);
static std::unique_ptr<apu::AudioSystem> CreateAudioSystem(
@ -203,6 +213,8 @@ class EmulatorApp final : public xe::ui::WindowedApp {
void EmulatorThread();
void ShutdownEmulatorThreadFromUIThread();
DebugWindowClosedListener debug_window_closed_listener_;
std::unique_ptr<Emulator> emulator_;
std::unique_ptr<EmulatorWindow> emulator_window_;
@ -215,8 +227,15 @@ class EmulatorApp final : public xe::ui::WindowedApp {
std::thread emulator_thread_;
};
void EmulatorApp::DebugWindowClosedListener::OnClosing(xe::ui::UIEvent& e) {
EmulatorApp* emulator_app = &emulator_app_;
emulator_app->emulator_->processor()->set_debug_listener(nullptr);
emulator_app->debug_window_.reset();
}
EmulatorApp::EmulatorApp(xe::ui::WindowedAppContext& app_context)
: xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]") {
: xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]"),
debug_window_closed_listener_(*this) {
AddPositionalOption("target");
}
@ -252,9 +271,10 @@ std::vector<std::unique_ptr<hid::InputDriver>> EmulatorApp::CreateInputDrivers(
ui::Window* window) {
std::vector<std::unique_ptr<hid::InputDriver>> drivers;
if (cvars::hid.compare("nop") == 0) {
drivers.emplace_back(xe::hid::nop::Create(window));
drivers.emplace_back(
xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput));
} else {
Factory<hid::InputDriver, ui::Window*> factory;
Factory<hid::InputDriver, ui::Window*, size_t> factory;
#if XE_PLATFORM_WIN32
factory.Add("xinput", xe::hid::xinput::Create);
#endif // XE_PLATFORM_WIN32
@ -263,14 +283,16 @@ std::vector<std::unique_ptr<hid::InputDriver>> EmulatorApp::CreateInputDrivers(
// WinKey input driver should always be the last input driver added!
factory.Add("winkey", xe::hid::winkey::Create);
#endif // XE_PLATFORM_WIN32
for (auto& driver : factory.CreateAll(cvars::hid, window)) {
for (auto& driver : factory.CreateAll(cvars::hid, window,
EmulatorWindow::kZOrderHidInput)) {
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
}
if (drivers.empty()) {
// Fallback to nop if none created.
drivers.emplace_back(xe::hid::nop::Create(window));
drivers.emplace_back(
xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput));
}
}
return drivers;
@ -365,6 +387,9 @@ void EmulatorApp::OnDestroy() {
// The profiler needs to shut down before the graphics context.
Profiler::Shutdown();
// Write all cvar overrides to the config.
config::SaveConfig();
// TODO(DrChat): Remove this code and do a proper exit.
XELOGI("Cheap-skate exit!");
std::quick_exit(EXIT_SUCCESS);
@ -378,15 +403,18 @@ void EmulatorApp::EmulatorThread() {
// Setup and initialize all subsystems. If we can't do something
// (unsupported system, memory issues, etc) this will fail early.
X_STATUS result =
emulator_->Setup(emulator_window_->window(), CreateAudioSystem,
CreateGraphicsSystem, CreateInputDrivers);
X_STATUS result = emulator_->Setup(
emulator_window_->window(), emulator_window_->imgui_drawer(),
CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers);
if (XFAILED(result)) {
XELOGE("Failed to setup emulator: {:08X}", result);
app_context().RequestDeferredQuit();
return;
}
app_context().CallInUIThread(
[this]() { emulator_window_->SetupGraphicsSystemPresenterPainting(); });
if (cvars::mount_scratch) {
auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>(
"\\SCRATCH", "scratch", false);
@ -455,12 +483,8 @@ void EmulatorApp::EmulatorThread() {
app_context().CallInUIThreadSynchronous([this]() {
debug_window_ = xe::debug::ui::DebugWindow::Create(emulator_.get(),
app_context());
debug_window_->window()->on_closed.AddListener(
[this](xe::ui::UIEvent* e) {
emulator_->processor()->set_debug_listener(nullptr);
app_context().CallInUIThread(
[this]() { debug_window_.reset(); });
});
debug_window_->window()->AddListener(
&debug_window_closed_listener_);
});
// If failed to enqueue the UI thread call, this will just be null.
return debug_window_.get();
@ -489,9 +513,9 @@ void EmulatorApp::EmulatorThread() {
}
});
// Enable the main menu now that the emulator is properly loaded
// Enable emulator input now that the emulator is properly loaded.
app_context().CallInUIThread(
[this]() { emulator_window_->window()->EnableMainMenu(); });
[this]() { emulator_window_->OnEmulatorInitialized(); });
// Grab path from the flag or unnamed argument.
std::filesystem::path path;
@ -499,12 +523,6 @@ void EmulatorApp::EmulatorThread() {
path = cvars::target;
}
// Toggles fullscreen
if (cvars::fullscreen) {
app_context().CallInUIThread(
[this]() { emulator_window_->ToggleFullscreen(); });
}
if (!path.empty()) {
// Normalize the path and make absolute.
auto abs_path = std::filesystem::absolute(path);

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -86,6 +86,10 @@ class ConfigVar : public CommandVar<T>, virtual public IConfigVar {
void LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) override;
void SetConfigValue(T val);
void SetGameConfigValue(T val);
// Changes the actual value used to the one specified, and also makes it the
// one that will be stored when the global config is written next time. After
// overriding, however, the next game config loaded may still change it.
void OverrideConfigValue(T val);
private:
std::string category_;
@ -260,6 +264,16 @@ void ConfigVar<T>::SetGameConfigValue(T val) {
UpdateValue();
}
template <class T>
void ConfigVar<T>::OverrideConfigValue(T val) {
config_value_ = std::make_unique<T>(val);
// The user explicitly changes the value at runtime and wants it to take
// effect immediately. Drop everything with a higher priority. The next game
// config load, however, may still change it.
game_config_value_.reset();
this->commandline_value_.reset();
UpdateValue();
}
template <class T>
void ConfigVar<T>::ResetConfigValueToDefault() {
SetConfigValue(this->default_value_);
}
@ -373,6 +387,28 @@ ICommandVar* define_cmdvar(const char* name, T* default_value,
extern type name; \
}
#define ACCESS_CVar(name) (*cv::cv_##name)
// dynamic_cast is needed because of virtual inheritance.
#define OVERRIDE_CVar(name, type, value) \
dynamic_cast<cvar::ConfigVar<type>*>(&ACCESS_CVar(name)) \
->OverrideConfigValue(value);
#define OVERRIDE_bool(name, value) OVERRIDE_CVar(name, bool, value)
#define OVERRIDE_int32(name, value) OVERRIDE_CVar(name, int32_t, value)
#define OVERRIDE_uint32(name, value) OVERRIDE_CVar(name, uint32_t, value)
#define OVERRIDE_uint64(name, value) OVERRIDE_CVar(name, uint64_t, value)
#define OVERRIDE_double(name, value) OVERRIDE_CVar(name, double, value)
#define OVERRIDE_string(name, value) OVERRIDE_CVar(name, std::string, value)
#define OVERRIDE_path(name, value) \
OVERRIDE_CVar(name, std::filesystem::path, value)
// Interface for changing the default value of a variable with auto-upgrading of
// users' configs (to distinguish between a leftover old default and an explicit
// override), without having to rename the variable.

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -41,8 +41,8 @@ std::filesystem::path GetUserFolder();
// attempting to create it.
bool CreateParentFolder(const std::filesystem::path& path);
// Creates an empty file at the given path.
bool CreateFile(const std::filesystem::path& path);
// Creates an empty file at the given path, overwriting if it exists.
bool CreateEmptyFile(const std::filesystem::path& path);
// Opens the file at the given path with the specified mode.
// This behaves like fopen and the returned handle can be used with stdio.

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -122,7 +122,7 @@ static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) {
return filetime;
}
bool CreateFile(const std::filesystem::path& path) {
bool CreateEmptyFile(const std::filesystem::path& path) {
int file = creat(path.c_str(), 0774);
if (file >= 0) {
close(file);

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -60,7 +60,7 @@ std::filesystem::path GetUserFolder() {
return result;
}
bool CreateFile(const std::filesystem::path& path) {
bool CreateEmptyFile(const std::filesystem::path& path) {
auto handle = CreateFileW(path.c_str(), 0, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (handle == INVALID_HANDLE_VALUE) {

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2021 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -19,37 +19,64 @@
// Autogenerated by `xb premake`.
#include "build/version.h"
// For RequestHighPerformance.
// For RequestWin32MMCSS.
#include <dwmapi.h>
// For RequestWin32HighResolutionTimer.
#include <winternl.h>
DEFINE_bool(win32_high_freq, true,
"Requests high performance from the NT kernel", "Kernel");
DEFINE_bool(win32_high_resolution_timer, true,
"Requests high-resolution timer from the NT kernel", "Win32");
DEFINE_bool(
win32_mmcss, true,
"Opt in the Multimedia Class Scheduler Service (MMCSS) scheduling for "
"prioritized access to CPU resources",
"Win32");
namespace xe {
static void RequestHighPerformance() {
#if XE_PLATFORM_WIN32
NTSTATUS(*NtQueryTimerResolution)
(OUT PULONG MinimumResolution, OUT PULONG MaximumResolution,
OUT PULONG CurrentResolution);
static void RequestWin32HighResolutionTimer() {
HMODULE ntdll_module = GetModuleHandleW(L"ntdll.dll");
if (!ntdll_module) {
return;
}
NTSTATUS(*NtSetTimerResolution)
(IN ULONG DesiredResolution, IN BOOLEAN SetResolution,
// clang-format off
NTSTATUS (NTAPI* nt_query_timer_resolution)(OUT PULONG MinimumResolution,
OUT PULONG MaximumResolution,
OUT PULONG CurrentResolution);
NtQueryTimerResolution = (decltype(NtQueryTimerResolution))GetProcAddress(
GetModuleHandleW(L"ntdll.dll"), "NtQueryTimerResolution");
NtSetTimerResolution = (decltype(NtSetTimerResolution))GetProcAddress(
GetModuleHandleW(L"ntdll.dll"), "NtSetTimerResolution");
if (!NtQueryTimerResolution || !NtSetTimerResolution) {
NTSTATUS (NTAPI* nt_set_timer_resolution)(IN ULONG DesiredResolution,
IN BOOLEAN SetResolution,
OUT PULONG CurrentResolution);
// clang-format on
nt_query_timer_resolution =
reinterpret_cast<decltype(nt_query_timer_resolution)>(
GetProcAddress(ntdll_module, "NtQueryTimerResolution"));
nt_set_timer_resolution = reinterpret_cast<decltype(nt_set_timer_resolution)>(
GetProcAddress(ntdll_module, "NtSetTimerResolution"));
if (!nt_query_timer_resolution || !nt_set_timer_resolution) {
return;
}
ULONG minimum_resolution, maximum_resolution, current_resolution;
NtQueryTimerResolution(&minimum_resolution, &maximum_resolution,
nt_query_timer_resolution(&minimum_resolution, &maximum_resolution,
&current_resolution);
NtSetTimerResolution(maximum_resolution, TRUE, &current_resolution);
#endif
nt_set_timer_resolution(maximum_resolution, TRUE, &current_resolution);
}
static void RequestWin32MMCSS() {
HMODULE dwmapi_module = LoadLibraryW(L"dwmapi.dll");
if (!dwmapi_module) {
return;
}
// clang-format off
HRESULT (STDAPICALLTYPE* dwm_enable_mmcss)(BOOL fEnableMMCSS);
// clang-format on
dwm_enable_mmcss = reinterpret_cast<decltype(dwm_enable_mmcss)>(
GetProcAddress(dwmapi_module, "DwmEnableMMCSS"));
if (dwm_enable_mmcss) {
dwm_enable_mmcss(TRUE);
}
FreeLibrary(dwmapi_module);
}
bool ParseWin32LaunchArguments(
@ -103,9 +130,12 @@ int InitializeWin32App(const std::string_view app_name) {
#endif
XE_BUILD_BRANCH "@" XE_BUILD_COMMIT_SHORT " on " XE_BUILD_DATE);
// Request high performance timing.
if (cvars::win32_high_freq) {
RequestHighPerformance();
// Request high-performance timing and scheduling.
if (cvars::win32_high_resolution_timer) {
RequestWin32HighResolutionTimer();
}
if (cvars::win32_mmcss) {
RequestWin32MMCSS();
}
return 0;

View File

@ -53,8 +53,11 @@ constexpr T align(T value, T alignment) {
// Rounds the given number up to the next highest multiple.
template <typename T, typename V>
constexpr T round_up(T value, V multiple) {
return value ? (((value + multiple - 1) / multiple) * multiple) : multiple;
constexpr T round_up(T value, V multiple, bool force_non_zero = true) {
if (force_non_zero && !value) {
return multiple;
}
return (value + multiple - 1) / multiple * multiple;
}
// Using the same conventions as in shading languages, returning 0 for NaN.

View File

@ -2,11 +2,12 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <algorithm>
#include <string>
// NOTE: this must be included before microprofile as macro expansion needs
@ -36,6 +37,7 @@
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/profiling.h"
#include "xenia/ui/ui_event.h"
#include "xenia/ui/virtual_key.h"
#include "xenia/ui/window.h"
@ -44,21 +46,27 @@
#endif // XE_OPTION_PROFILING
#if XE_OPTION_PROFILING_UI
#undef DrawText
#include "xenia/ui/microprofile_drawer.h"
#endif // XE_OPTION_PROFILING_UI
DEFINE_bool(profiler_dpi_scaling, false,
"Apply window DPI scaling to the profiler.", "UI");
DEFINE_bool(show_profiler, false, "Show profiling UI by default.", "UI");
namespace xe {
#if XE_OPTION_PROFILING_UI
ui::Window* Profiler::window_ = nullptr;
std::unique_ptr<ui::MicroprofileDrawer> Profiler::drawer_ = nullptr;
#endif // XE_OPTION_PROFILING_UI
#if XE_OPTION_PROFILING
Profiler::ProfilerWindowInputListener Profiler::input_listener_;
size_t Profiler::z_order_ = 0;
ui::Window* Profiler::window_ = nullptr;
#if XE_OPTION_PROFILING_UI
Profiler::ProfilerUIDrawer Profiler::ui_drawer_;
ui::Presenter* Profiler::presenter_ = nullptr;
std::unique_ptr<ui::MicroprofileDrawer> Profiler::drawer_;
bool Profiler::dpi_scaling_ = false;
#endif // XE_OPTION_PROFILING_UI
bool Profiler::is_enabled() { return true; }
bool Profiler::is_visible() { return is_enabled() && MicroProfileIsDrawing(); }
@ -79,6 +87,7 @@ void Profiler::Initialize() {
g_MicroProfile.nActiveBars |= 0x1 | 0x2;
#if XE_OPTION_PROFILING_UI
dpi_scaling_ = cvars::profiler_dpi_scaling;
MicroProfileInitUI();
g_MicroProfileUI.bShowSpikes = true;
g_MicroProfileUI.nOpacityBackground = 0x40u << 24;
@ -102,7 +111,7 @@ void Profiler::Dump() {
}
void Profiler::Shutdown() {
drawer_.reset();
SetUserIO(0, nullptr, nullptr, nullptr);
window_ = nullptr;
MicroProfileShutdown();
}
@ -119,144 +128,208 @@ void Profiler::ThreadEnter(const char* name) {
void Profiler::ThreadExit() { MicroProfileOnThreadExit(); }
bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) {
void Profiler::ProfilerWindowInputListener::OnKeyDown(ui::KeyEvent& e) {
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
switch (virtual_key) {
bool handled = true;
switch (e.virtual_key()) {
case ui::VirtualKey::kOem3: // `
MicroProfileTogglePause();
return true;
break;
#if XE_OPTION_PROFILING_UI
case ui::VirtualKey::kTab:
MicroProfileToggleDisplayMode();
return true;
ToggleDisplay();
break;
case ui::VirtualKey::k1:
MicroProfileModKey(1);
return true;
break;
#endif // XE_OPTION_PROFILING_UI
default:
handled = false;
break;
}
return false;
if (handled) {
e.set_handled(true);
}
PostInputEvent();
}
bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) {
switch (virtual_key) {
void Profiler::ProfilerWindowInputListener::OnKeyUp(ui::KeyEvent& e) {
bool handled = true;
switch (e.virtual_key()) {
#if XE_OPTION_PROFILING_UI
case ui::VirtualKey::k1:
MicroProfileModKey(0);
return true;
break;
#endif // XE_OPTION_PROFILING_UI
default:
handled = false;
break;
}
return false;
if (handled) {
e.set_handled(true);
}
PostInputEvent();
}
#if XE_OPTION_PROFILING_UI
void Profiler::OnMouseDown(bool left_button, bool right_button) {
MicroProfileMouseButton(left_button, right_button);
void Profiler::ProfilerWindowInputListener::OnMouseDown(ui::MouseEvent& e) {
Profiler::SetMousePosition(e.x(), e.y(), 0);
MicroProfileMouseButton(e.button() == ui::MouseEvent::Button::kLeft,
e.button() == ui::MouseEvent::Button::kRight);
e.set_handled(true);
PostInputEvent();
}
void Profiler::OnMouseUp() { MicroProfileMouseButton(0, 0); }
void Profiler::OnMouseMove(int x, int y) { MicroProfileMousePosition(x, y, 0); }
void Profiler::OnMouseWheel(int x, int y, int dy) {
MicroProfileMousePosition(x, y, dy);
void Profiler::ProfilerWindowInputListener::OnMouseUp(ui::MouseEvent& e) {
Profiler::SetMousePosition(e.x(), e.y(), 0);
MicroProfileMouseButton(0, 0);
e.set_handled(true);
PostInputEvent();
}
void Profiler::ToggleDisplay() { MicroProfileToggleDisplayMode(); }
void Profiler::ProfilerWindowInputListener::OnMouseMove(ui::MouseEvent& e) {
Profiler::SetMousePosition(e.x(), e.y(), 0);
e.set_handled(true);
PostInputEvent();
}
void Profiler::ProfilerWindowInputListener::OnMouseWheel(ui::MouseEvent& e) {
Profiler::SetMousePosition(e.x(), e.y(), e.scroll_y());
e.set_handled(true);
PostInputEvent();
}
void Profiler::TogglePause() { MicroProfileTogglePause(); }
#else
void Profiler::OnMouseDown(bool left_button, bool right_button) {}
void Profiler::OnMouseUp() {}
void Profiler::OnMouseMove(int x, int y) {}
void Profiler::OnMouseWheel(int x, int y, int dy) {}
void Profiler::ToggleDisplay() {}
void Profiler::TogglePause() {}
#endif // XE_OPTION_PROFILING_UI
void Profiler::set_window(ui::Window* window) {
assert_null(window_);
void Profiler::ToggleDisplay() {
bool was_visible = is_visible();
MicroProfileToggleDisplayMode();
if (is_visible() != was_visible) {
if (window_) {
if (was_visible) {
window_->RemoveInputListener(&input_listener_);
} else {
window_->AddInputListener(&input_listener_, z_order_);
}
}
#if XE_OPTION_PROFILING_UI
if (presenter_) {
if (was_visible) {
presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_);
} else {
presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_);
}
}
#endif // XE_OPTION_PROFILING_UI
}
}
void Profiler::SetUserIO(size_t z_order, ui::Window* window,
ui::Presenter* presenter,
ui::ImmediateDrawer* immediate_drawer) {
#if XE_OPTION_PROFILING_UI
if (presenter_ && is_visible()) {
presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_);
}
drawer_.reset();
presenter_ = nullptr;
#endif // XE_OPTION_PROFILING_UI
if (window_) {
if (is_visible()) {
window_->RemoveInputListener(&input_listener_);
}
window_ = nullptr;
}
if (!window) {
return;
}
z_order_ = z_order;
window_ = window;
drawer_ = std::make_unique<ui::MicroprofileDrawer>(window);
window_->on_painted.AddListener([](ui::UIEvent* e) { Profiler::Present(); });
#if XE_OPTION_PROFILING_UI
if (presenter && immediate_drawer) {
presenter_ = presenter;
drawer_ = std::make_unique<ui::MicroprofileDrawer>(immediate_drawer);
}
#endif // XE_OPTION_PROFILING_UI
// Pass through mouse events.
window_->on_mouse_down.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseDown(e->button() == ui::MouseEvent::Button::kLeft,
e->button() == ui::MouseEvent::Button::kRight);
e->set_handled(true);
window_->Invalidate();
if (is_visible()) {
window_->AddInputListener(&input_listener_, z_order_);
#if XE_OPTION_PROFILING_UI
if (presenter_) {
presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_);
}
});
window_->on_mouse_up.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseUp();
e->set_handled(true);
window_->Invalidate();
#endif // XE_OPTION_PROFILING_UI
}
});
window_->on_mouse_move.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseMove(e->x(), e->y());
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_mouse_wheel.AddListener([](ui::MouseEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnMouseWheel(e->x(), e->y(), -e->dy());
e->set_handled(true);
window_->Invalidate();
}
});
// Watch for toggle/mode keys and such.
window_->on_key_down.AddListener([](ui::KeyEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnKeyDown(e->virtual_key());
e->set_handled(true);
window_->Invalidate();
}
});
window_->on_key_up.AddListener([](ui::KeyEvent* e) {
if (Profiler::is_visible()) {
Profiler::OnKeyUp(e->virtual_key());
e->set_handled(true);
window_->Invalidate();
}
});
}
void Profiler::Present() {
SCOPE_profile_cpu_f("internal");
void Profiler::Flip() {
MicroProfileFlip();
// This can be called from non-UI threads, so not trying to access the drawer
// to trigger redraw here as it's owned and managed exclusively by the UI
// thread. Relying on continuous painting currently.
}
#if XE_OPTION_PROFILING_UI
if (!window_ || !drawer_) {
void Profiler::ProfilerUIDrawer::Draw(ui::UIDrawContext& ui_draw_context) {
if (!window_ || !presenter_ || !drawer_) {
return;
}
drawer_->Begin();
MicroProfileDraw(window_->scaled_width(), window_->scaled_height());
SCOPE_profile_cpu_f("internal");
uint32_t coordinate_space_width = dpi_scaling_
? window_->GetActualLogicalWidth()
: window_->GetActualPhysicalWidth();
uint32_t coordinate_space_height = dpi_scaling_
? window_->GetActualLogicalHeight()
: window_->GetActualPhysicalHeight();
drawer_->Begin(ui_draw_context, coordinate_space_width,
coordinate_space_height);
MicroProfileDraw(coordinate_space_width, coordinate_space_height);
drawer_->End();
#endif // XE_OPTION_PROFILING_UI
// Continuous repaint.
if (is_visible()) {
presenter_->RequestUIPaintFromUIThread();
}
}
#endif // XE_OPTION_PROFILING_UI
void Profiler::Flip() { MicroProfileFlip(); }
#if XE_OPTION_PROFILING_UI
void Profiler::SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta) {
if (!window_) {
return;
}
if (dpi_scaling_) {
x = window_->PositionToLogical(x);
y = window_->PositionToLogical(y);
}
MicroProfileMousePosition(uint32_t(std::max(int32_t(0), x)),
uint32_t(std::max(int32_t(0), y)), wheel_delta);
}
#endif // XE_OPTION_PROFILING_UI
void Profiler::PostInputEvent() {
// The profiler can be hidden from within the profiler (Mode > Off).
if (!is_visible()) {
window_->RemoveInputListener(&input_listener_);
#if XE_OPTION_PROFILING_UI
if (presenter_) {
presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_);
}
#endif // XE_OPTION_PROFILING_UI
return;
}
// Relying on continuous painting currently, no need to request drawing.
}
#else
@ -268,16 +341,11 @@ void Profiler::Shutdown() {}
uint32_t Profiler::GetColor(const char* str) { return 0; }
void Profiler::ThreadEnter(const char* name) {}
void Profiler::ThreadExit() {}
bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { return false; }
bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { return false; }
void Profiler::OnMouseDown(bool left_button, bool right_button) {}
void Profiler::OnMouseUp() {}
void Profiler::OnMouseMove(int x, int y) {}
void Profiler::OnMouseWheel(int x, int y, int dy) {}
void Profiler::ToggleDisplay() {}
void Profiler::TogglePause() {}
void Profiler::set_window(ui::Window* window) {}
void Profiler::Present() {}
void Profiler::SetUserIO(size_t z_order, ui::Window* window,
ui::Presenter* presenter,
ui::ImmediateDrawer* immediate_drawer) {}
void Profiler::Flip() {}
#endif // XE_OPTION_PROFILING
@ -316,7 +384,7 @@ void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText,
if (!drawer) {
return;
}
drawer->DrawText(nX, nY, nColor, pText, nLen);
drawer->DrawTextString(nX, nY, nColor, pText, nLen);
}
#endif // XE_OPTION_PROFILING_UI

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -10,10 +10,15 @@
#ifndef XENIA_BASE_PROFILING_H_
#define XENIA_BASE_PROFILING_H_
#include <cstddef>
#include <cstdint>
#include <memory>
#include "xenia/base/platform.h"
#include "xenia/base/string.h"
#include "xenia/ui/ui_drawer.h"
#include "xenia/ui/virtual_key.h"
#include "xenia/ui/window_listener.h"
#if XE_PLATFORM_WIN32
#define XE_OPTION_PROFILING 1
@ -30,7 +35,9 @@
namespace xe {
namespace ui {
class ImmediateDrawer;
class MicroprofileDrawer;
class Presenter;
class Window;
} // namespace ui
} // namespace xe
@ -172,27 +179,65 @@ class Profiler {
// Deactivates the calling thread for profiling.
static void ThreadExit();
static bool OnKeyDown(ui::VirtualKey virtual_key);
static bool OnKeyUp(ui::VirtualKey virtual_key);
static void OnMouseDown(bool left_button, bool right_button);
static void OnMouseUp();
static void OnMouseMove(int x, int y);
static void OnMouseWheel(int x, int y, int dy);
static void ToggleDisplay();
static void TogglePause();
// Initializes input and drawing with the given display.
static void set_window(ui::Window* window);
// Gets the current display, if any.
static ui::MicroprofileDrawer* drawer() { return drawer_.get(); }
// Initializes input for the given window and drawing for the given presenter
// and immediate drawer.
static void SetUserIO(size_t z_order, ui::Window* window,
ui::Presenter* presenter,
ui::ImmediateDrawer* immediate_drawer);
// Gets the current drawer, if any.
static ui::MicroprofileDrawer* drawer() {
#if XE_OPTION_PROFILING_UI
return drawer_.get();
#else
return nullptr;
#endif
}
// Presents the profiler to the bound display, if any.
static void Present();
static void Present(ui::UIDrawContext& ui_draw_context);
// Starts a new frame on the profiler
static void Flip();
private:
#if XE_OPTION_PROFILING
class ProfilerWindowInputListener final : public ui::WindowInputListener {
public:
void OnKeyDown(ui::KeyEvent& e) override;
void OnKeyUp(ui::KeyEvent& e) override;
#if XE_OPTION_PROFILING_UI
void OnMouseDown(ui::MouseEvent& e) override;
void OnMouseMove(ui::MouseEvent& e) override;
void OnMouseUp(ui::MouseEvent& e) override;
void OnMouseWheel(ui::MouseEvent& e) override;
#endif // XE_OPTION_PROFILING_UI
};
// For now, no need for OnDpiChanged in a WindowListener because redrawing is
// done continuously.
#if XE_OPTION_PROFILING_UI
class ProfilerUIDrawer final : public ui::UIDrawer {
public:
void Draw(ui::UIDrawContext& context) override;
};
#endif // XE_OPTION_PROFILING_UI
#if XE_OPTION_PROFILING_UI
static void SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta);
#endif // XE_OPTION_PROFILING_UI
static void PostInputEvent();
static ProfilerWindowInputListener input_listener_;
static size_t z_order_;
static ui::Window* window_;
#if XE_OPTION_PROFILING_UI
static ProfilerUIDrawer ui_drawer_;
static ui::Presenter* presenter_;
static std::unique_ptr<ui::MicroprofileDrawer> drawer_;
static bool dpi_scaling_;
#endif // XE_OPTION_PROFILING_UI
#endif // XE_OPTION_PROFILING
};
} // namespace xe

View File

@ -105,6 +105,10 @@ void ReadGameConfig(const std::filesystem::path& file_path) {
}
void SaveConfig() {
if (config_path.empty()) {
return;
}
// All cvar defaults have been updated on loading - store the current date.
auto defaults_date_cvar =
dynamic_cast<cvar::ConfigVar<uint32_t>*>(cv::cv_defaults_date);

View File

@ -15,6 +15,7 @@
namespace config {
void SetupConfig(const std::filesystem::path& config_folder);
void LoadGameConfig(const std::string_view title_id);
void SaveConfig();
} // namespace config
#endif // XENIA_CONFIG_H_

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -32,6 +32,8 @@
#include "xenia/kernel/xthread.h"
#include "xenia/ui/graphics_provider.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/windowed_app_context.h"
DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.", "UI");
@ -49,14 +51,18 @@ using xe::ui::MenuItem;
using xe::ui::MouseEvent;
using xe::ui::UIEvent;
const std::string kBaseTitle = "Xenia Debugger";
void DebugWindow::DebugDialog::OnDraw(ImGuiIO& io) {
debug_window_.DrawFrame(io);
}
static const std::string kBaseTitle = "Xenia Debugger";
DebugWindow::DebugWindow(Emulator* emulator,
xe::ui::WindowedAppContext& app_context)
: emulator_(emulator),
processor_(emulator->processor()),
app_context_(app_context),
window_(xe::ui::Window::Create(app_context_, kBaseTitle)) {
window_(xe::ui::Window::Create(app_context_, kBaseTitle, 1500, 1000)) {
if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) {
assert_always("Failed to initialize capstone");
}
@ -86,44 +92,57 @@ std::unique_ptr<DebugWindow> DebugWindow::Create(
}
bool DebugWindow::Initialize() {
if (!window_->Initialize()) {
XELOGE("Failed to initialize platform window");
return false;
}
// Main menu.
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File");
{
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close",
"Alt+F4",
[this]() { window_->Close(); }));
file_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, "&Close", "Alt+F4",
[this]() { window_->RequestClose(); }));
}
main_menu->AddChild(std::move(file_menu));
window_->set_main_menu(std::move(main_menu));
window_->SetMainMenu(std::move(main_menu));
window_->Resize(1500, 1000);
// Open the window once it's configured.
if (!window_->Open()) {
XELOGE("Failed to open the platform window for the debugger");
return false;
}
// Create the graphics context used for drawing.
auto provider = emulator_->display_window()->context()->provider();
window_->set_context(provider->CreateContext(window_.get()));
// Setup drawing to the window.
// Enable imgui input.
window_->set_imgui_input_enabled(true);
xe::ui::GraphicsProvider& graphics_provider =
*emulator_->graphics_system()->provider();
window_->on_painting.AddListener([this](UIEvent* e) { DrawFrame(); });
presenter_ = graphics_provider.CreatePresenter();
if (!presenter_) {
XELOGE("Failed to initialize the presenter for the debugger");
return false;
}
immediate_drawer_ = graphics_provider.CreateImmediateDrawer();
if (!immediate_drawer_) {
XELOGE("Failed to initialize the immediate drawer for the debugger");
return false;
}
immediate_drawer_->SetPresenter(presenter_.get());
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window_.get(), 0);
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(),
immediate_drawer_.get());
debug_dialog_ =
std::unique_ptr<DebugDialog>(new DebugDialog(imgui_drawer_.get(), *this));
// Update the cache before the first frame.
UpdateCache();
window_->Invalidate();
// Begin drawing.
window_->SetPresenter(presenter_.get());
return true;
}
void DebugWindow::DrawFrame() {
xe::ui::GraphicsContextLock lock(window_->context());
auto& io = window_->imgui_drawer()->GetIO();
void DebugWindow::DrawFrame(ImGuiIO& io) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(-1, 0));
ImGui::Begin("main_window", nullptr,
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
@ -242,9 +261,6 @@ void DebugWindow::DrawFrame() {
ImGui::ShowDemoWindow();
ImGui::ShowMetricsWindow();
}
// Continuous paint.
window_->Invalidate();
}
void DebugWindow::DrawToolbar() {
@ -1443,7 +1459,7 @@ void DebugWindow::UpdateCache() {
title += " (stepping)";
break;
}
window_->set_title(title);
window_->SetTitle(title);
});
cache_.is_running =
@ -1573,7 +1589,7 @@ void DebugWindow::OnBreakpointHit(Breakpoint* breakpoint,
}
void DebugWindow::Focus() const {
app_context_.CallInUIThread([this]() { window_->set_focus(true); });
app_context_.CallInUIThread([this]() { window_->Focus(); });
}
} // namespace ui

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -18,7 +18,11 @@
#include "xenia/cpu/debug_listener.h"
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/menu_item.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/window.h"
#include "xenia/ui/windowed_app_context.h"
#include "xenia/xbox.h"
@ -48,11 +52,24 @@ class DebugWindow : public cpu::DebugListener {
cpu::ThreadDebugInfo* thread_info) override;
private:
class DebugDialog final : public xe::ui::ImGuiDialog {
public:
explicit DebugDialog(xe::ui::ImGuiDrawer* imgui_drawer,
DebugWindow& debug_window)
: xe::ui::ImGuiDialog(imgui_drawer), debug_window_(debug_window) {}
protected:
void OnDraw(ImGuiIO& io) override;
private:
DebugWindow& debug_window_;
};
explicit DebugWindow(Emulator* emulator,
xe::ui::WindowedAppContext& app_context);
bool Initialize();
void DrawFrame();
void DrawFrame(ImGuiIO& io);
void DrawToolbar();
void DrawFunctionsPane();
void DrawSourcePane();
@ -93,7 +110,10 @@ class DebugWindow : public cpu::DebugListener {
cpu::Processor* processor_ = nullptr;
xe::ui::WindowedAppContext& app_context_;
std::unique_ptr<xe::ui::Window> window_;
uint64_t last_draw_tick_count_ = 0;
std::unique_ptr<xe::ui::Presenter> presenter_;
std::unique_ptr<xe::ui::ImmediateDrawer> immediate_drawer_;
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
std::unique_ptr<DebugDialog> debug_dialog_;
uintptr_t capstone_handle_ = 0;

View File

@ -9,6 +9,7 @@
#include "xenia/emulator.h"
#include <algorithm>
#include <cinttypes>
#include "config.h"
@ -23,7 +24,6 @@
#include "xenia/base/literals.h"
#include "xenia/base/logging.h"
#include "xenia/base/mapped_memory.h"
#include "xenia/base/profiling.h"
#include "xenia/base/string.h"
#include "xenia/cpu/backend/code_cache.h"
#include "xenia/cpu/backend/x64/x64_backend.h"
@ -41,6 +41,7 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include "xenia/memory.h"
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/window.h"
#include "xenia/ui/windowed_app_context.h"
#include "xenia/vfs/devices/disc_image_device.h"
@ -63,6 +64,15 @@ namespace xe {
using namespace xe::literals;
Emulator::GameConfigLoadCallback::GameConfigLoadCallback(Emulator& emulator)
: emulator_(emulator) {
emulator_.AddGameConfigLoadCallback(this);
}
Emulator::GameConfigLoadCallback::~GameConfigLoadCallback() {
emulator_.RemoveGameConfigLoadCallback(this);
}
Emulator::Emulator(const std::filesystem::path& command_line,
const std::filesystem::path& storage_root,
const std::filesystem::path& content_root,
@ -116,7 +126,7 @@ Emulator::~Emulator() {
}
X_STATUS Emulator::Setup(
ui::Window* display_window,
ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer,
std::function<std::unique_ptr<apu::AudioSystem>(cpu::Processor*)>
audio_system_factory,
std::function<std::unique_ptr<gpu::GraphicsSystem>()>
@ -126,6 +136,7 @@ X_STATUS Emulator::Setup(
X_STATUS result = X_STATUS_UNSUCCESSFUL;
display_window_ = display_window;
imgui_drawer_ = imgui_drawer;
// Initialize clock.
// 360 uses a 50MHz clock.
@ -212,8 +223,10 @@ X_STATUS Emulator::Setup(
kernel_state_ = std::make_unique<xe::kernel::KernelState>(this);
// Setup the core components.
result = graphics_system_->Setup(processor_.get(), kernel_state_.get(),
display_window_);
result = graphics_system_->Setup(
processor_.get(), kernel_state_.get(),
display_window_ ? &display_window_->app_context() : nullptr,
display_window_ != nullptr);
if (result) {
return result;
}
@ -236,14 +249,6 @@ X_STATUS Emulator::Setup(
// Initialize emulator fallback exception handling last.
ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this);
if (display_window_) {
// Finish initializing the display.
display_window_->app_context().CallInUIThreadSynchronous([this]() {
xe::ui::GraphicsContextLock context_lock(display_window_->context());
Profiler::set_window(display_window_);
});
}
return result;
}
@ -417,7 +422,7 @@ void Emulator::Resume() {
bool Emulator::SaveToFile(const std::filesystem::path& path) {
Pause();
filesystem::CreateFile(path);
filesystem::CreateEmptyFile(path);
auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite, 0, 2_GiB);
if (!map) {
return false;
@ -587,14 +592,16 @@ bool Emulator::ExceptionCallback(Exception* ex) {
}
// Display a dialog telling the user the guest has crashed.
display_window()->app_context().CallInUIThreadSynchronous([this]() {
if (display_window_ && imgui_drawer_) {
display_window_->app_context().CallInUIThreadSynchronous([this]() {
xe::ui::ImGuiDialog::ShowMessageBox(
display_window(), "Uh-oh!",
imgui_drawer_, "Uh-oh!",
"The guest has crashed.\n\n"
""
"Xenia has now paused itself.\n"
"A crash dump has been written into the log.");
});
}
// Now suspend ourself (we should be a guest thread).
current_thread->Suspend(nullptr);
@ -621,6 +628,41 @@ void Emulator::WaitUntilExit() {
on_exit();
}
void Emulator::AddGameConfigLoadCallback(GameConfigLoadCallback* callback) {
assert_not_null(callback);
// Game config load callbacks handling is entirely in the UI thread.
assert_true(!display_window_ ||
display_window_->app_context().IsInUIThread());
// Check if already added.
if (std::find(game_config_load_callbacks_.cbegin(),
game_config_load_callbacks_.cend(),
callback) != game_config_load_callbacks_.cend()) {
return;
}
game_config_load_callbacks_.push_back(callback);
}
void Emulator::RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback) {
assert_not_null(callback);
// Game config load callbacks handling is entirely in the UI thread.
assert_true(!display_window_ ||
display_window_->app_context().IsInUIThread());
auto it = std::find(game_config_load_callbacks_.cbegin(),
game_config_load_callbacks_.cend(), callback);
if (it == game_config_load_callbacks_.cend()) {
return;
}
if (game_config_load_callback_loop_next_index_ != SIZE_MAX) {
// Actualize the next callback index after the erasure from the vector.
size_t existing_index =
size_t(std::distance(game_config_load_callbacks_.cbegin(), it));
if (game_config_load_callback_loop_next_index_ > existing_index) {
--game_config_load_callback_loop_next_index_;
}
}
game_config_load_callbacks_.erase(it);
}
std::string Emulator::FindLaunchModule() {
std::string path("game:\\");
@ -677,6 +719,10 @@ static std::string format_version(xex2_version version) {
X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
const std::string_view module_path) {
// Making changes to the UI (setting the icon) and executing game config load
// callbacks which expect to be called from the UI thread.
assert_true(display_window_->app_context().IsInUIThread());
// Setup NullDevices for raw HDD partition accesses
// Cache/STFC code baked into games tries reading/writing to these
// By using a NullDevice that just returns success to all IO requests it
@ -729,7 +775,19 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
// Try and load the resource database (xex only).
if (module->title_id()) {
auto title_id = fmt::format("{:08X}", module->title_id());
// Load the per-game configuration file and make sure updates are handled by
// the callbacks.
config::LoadGameConfig(title_id);
assert_true(game_config_load_callback_loop_next_index_ == SIZE_MAX);
game_config_load_callback_loop_next_index_ = 0;
while (game_config_load_callback_loop_next_index_ <
game_config_load_callbacks_.size()) {
game_config_load_callbacks_[game_config_load_callback_loop_next_index_++]
->PostGameConfigLoad();
}
game_config_load_callback_loop_next_index_ = SIZE_MAX;
uint32_t resource_data = 0;
uint32_t resource_size = 0;
if (XSUCCEEDED(module->GetSection(title_id.c_str(), &resource_data,

View File

@ -10,9 +10,12 @@
#ifndef XENIA_EMULATOR_H_
#define XENIA_EMULATOR_H_
#include <cstddef>
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include <vector>
#include "xenia/base/delegate.h"
#include "xenia/base/exception_handler.h"
@ -38,6 +41,7 @@ class InputDriver;
class InputSystem;
} // namespace hid
namespace ui {
class ImGuiDrawer;
class Window;
} // namespace ui
} // namespace xe
@ -50,6 +54,37 @@ constexpr fourcc_t kEmulatorSaveSignature = make_fourcc("XSAV");
// This is responsible for initializing and managing all the various subsystems.
class Emulator {
public:
// This is the class for the top-level callbacks. They may be called in an
// undefined order, so among them there must be no dependencies on each other,
// especially hierarchical ones. If hierarchical handling is needed, for
// instance, if a specific implementation of a subsystem needs to handle
// changes, but the entire implementation must be reloaded, the implementation
// in this example _must not_ register / unregister its own callback - rather,
// the proper ordering and hierarchy should be constructed in a single
// callback (in this example, for the whole subsystem).
//
// All callbacks must be created and destroyed in the UI thread only (or the
// thread that takes its place in the architecture of the specific app if
// there's no UI), as they are invoked in the UI thread.
class GameConfigLoadCallback {
public:
GameConfigLoadCallback(Emulator& emulator);
GameConfigLoadCallback(const GameConfigLoadCallback& callback) = delete;
GameConfigLoadCallback& operator=(const GameConfigLoadCallback& callback) =
delete;
virtual ~GameConfigLoadCallback();
// The callback is invoked in the UI thread (or the thread that takes its
// place in the architecture of the specific app if there's no UI).
virtual void PostGameConfigLoad() = 0;
protected:
Emulator& emulator() const { return emulator_; }
private:
Emulator& emulator_;
};
explicit Emulator(const std::filesystem::path& command_line,
const std::filesystem::path& storage_root,
const std::filesystem::path& content_root,
@ -82,9 +117,13 @@ class Emulator {
// Are we currently running a title?
bool is_title_open() const { return title_id_.has_value(); }
// Window used for displaying graphical output.
// Window used for displaying graphical output. Can be null.
ui::Window* display_window() const { return display_window_; }
// ImGui drawer for various kinds of dialogs requested by the guest. Can be
// null.
ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; }
// Guest memory system modelling the RAM (both virtual and physical) of the
// system.
Memory* memory() const { return memory_.get(); }
@ -121,7 +160,7 @@ class Emulator {
// Once this function returns a game can be launched using one of the Launch
// functions.
X_STATUS Setup(
ui::Window* display_window,
ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer,
std::function<std::unique_ptr<apu::AudioSystem>(cpu::Processor*)>
audio_system_factory,
std::function<std::unique_ptr<gpu::GraphicsSystem>()>
@ -170,6 +209,9 @@ class Emulator {
static bool ExceptionCallbackThunk(Exception* ex, void* data);
bool ExceptionCallback(Exception* ex);
void AddGameConfigLoadCallback(GameConfigLoadCallback* callback);
void RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback);
std::string FindLaunchModule();
X_STATUS CompleteLaunch(const std::filesystem::path& path,
@ -183,7 +225,8 @@ class Emulator {
std::string title_name_;
std::string title_version_;
ui::Window* display_window_;
ui::Window* display_window_ = nullptr;
ui::ImGuiDrawer* imgui_drawer_ = nullptr;
std::unique_ptr<Memory> memory_;
@ -196,6 +239,16 @@ class Emulator {
std::unique_ptr<vfs::VirtualFileSystem> file_system_;
std::unique_ptr<kernel::KernelState> kernel_state_;
// Accessible only from the thread that invokes those callbacks (the UI thread
// if the UI is available).
std::vector<GameConfigLoadCallback*> game_config_load_callbacks_;
// Using an index, not an iterator, because after the erasure, the adjustment
// must be done for the vector element indices that would be in the iterator
// range that would be invalidated.
// SIZE_MAX if not currently in the game config load callback loop.
size_t game_config_load_callback_loop_next_index_ = SIZE_MAX;
kernel::object_ref<kernel::XThread> main_thread_;
std::optional<uint32_t> title_id_; // Currently running title ID

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -45,15 +45,12 @@ CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,
CommandProcessor::~CommandProcessor() = default;
bool CommandProcessor::Initialize(
std::unique_ptr<xe::ui::GraphicsContext> context) {
context_ = std::move(context);
bool CommandProcessor::Initialize() {
// Initialize the gamma ramps to their default (linear) values - taken from
// what games set when starting.
for (uint32_t i = 0; i < 256; ++i) {
uint32_t value = i * 1023 / 255;
gamma_ramp_.normal[i].value = value | (value << 10) | (value << 20);
gamma_ramp_.table[i].value = value | (value << 10) | (value << 20);
}
for (uint32_t i = 0; i < 128; ++i) {
uint32_t value = (i * 65535 / 127) & ~63;
@ -64,7 +61,7 @@ bool CommandProcessor::Initialize(
gamma_ramp_.pwl[i].values[j].value = value;
}
}
dirty_gamma_ramp_normal_ = true;
dirty_gamma_ramp_table_ = true;
dirty_gamma_ramp_pwl_ = true;
worker_running_ = true;
@ -140,8 +137,18 @@ void CommandProcessor::CallInThread(std::function<void()> fn) {
void CommandProcessor::ClearCaches() {}
void CommandProcessor::SetDesiredSwapPostEffect(
SwapPostEffect swap_post_effect) {
if (swap_post_effect_desired_ == swap_post_effect) {
return;
}
swap_post_effect_desired_ = swap_post_effect;
CallInThread([this, swap_post_effect]() {
swap_post_effect_actual_ = swap_post_effect;
});
}
void CommandProcessor::WorkerThreadMain() {
context_->MakeCurrent();
if (!SetupContext()) {
xe::FatalError("Unable to setup command processor internal state");
return;
@ -212,9 +219,6 @@ void CommandProcessor::Pause() {
threading::Thread::GetCurrentThread()->Suspend();
});
// HACK - Prevents a hang in IssueSwap()
swap_state_.pending = false;
fence.Wait();
}
@ -255,7 +259,7 @@ bool CommandProcessor::Restore(ByteStream* stream) {
bool CommandProcessor::SetupContext() { return true; }
void CommandProcessor::ShutdownContext() { context_.reset(); }
void CommandProcessor::ShutdownContext() {}
void CommandProcessor::InitializeRingBuffer(uint32_t ptr, uint32_t size_log2) {
read_ptr_index_ = 0;
@ -326,14 +330,17 @@ void CommandProcessor::UpdateGammaRampValue(GammaRampType type,
if (mask_lo) {
switch (type) {
case GammaRampType::kNormal:
case GammaRampType::kTable:
assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 0);
gamma_ramp_.normal[index].value = value;
dirty_gamma_ramp_normal_ = true;
gamma_ramp_.table[index].value = value;
dirty_gamma_ramp_table_ = true;
break;
case GammaRampType::kPWL:
assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 1);
gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value = value;
// The lower 6 bits are hardwired to 0.
// https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf
gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value =
value & ~(uint32_t(63) | (uint32_t(63) << 16));
gamma_ramp_rw_subindex_ = (gamma_ramp_rw_subindex_ + 1) % 3;
dirty_gamma_ramp_pwl_ = true;
break;
@ -385,51 +392,6 @@ void CommandProcessor::PrepareForWait() { trace_writer_.Flush(); }
void CommandProcessor::ReturnFromWait() {}
void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
uint32_t frontbuffer_width,
uint32_t frontbuffer_height) {
SCOPE_profile_cpu_f("gpu");
if (!swap_request_handler_) {
return;
}
// If there was a swap pending we drop it on the floor.
// This prevents the display from pulling the backbuffer out from under us.
// If we skip a lot then we may need to buffer more, but as the display
// thread should be fairly idle that shouldn't happen.
if (!cvars::vsync) {
std::lock_guard<std::mutex> lock(swap_state_.mutex);
if (swap_state_.pending) {
swap_state_.pending = false;
// TODO(benvanik): frame skip counter.
XELOGW("Skipped frame!");
}
} else {
// Spin until no more pending swap.
while (worker_running_) {
{
std::lock_guard<std::mutex> lock(swap_state_.mutex);
if (!swap_state_.pending) {
break;
}
}
xe::threading::MaybeYield();
}
}
PerformSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height);
{
// Set pending so that the display will swap the next time it can.
std::lock_guard<std::mutex> lock(swap_state_.mutex);
swap_state_.pending = true;
}
// Notify the display a swap is pending so that our changes are picked up.
// It does the actual front/back buffer swap.
swap_request_handler_();
}
uint32_t CommandProcessor::ExecutePrimaryBuffer(uint32_t read_index,
uint32_t write_index) {
SCOPE_profile_cpu_f("gpu");
@ -837,7 +799,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader,
uint32_t frontbuffer_height = reader->ReadAndSwap<uint32_t>();
reader->AdvanceRead((count - 4) * sizeof(uint32_t));
if (swap_mode_ == SwapMode::kNormal) {
if (!ignore_swap_) {
IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height);
}

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -26,7 +26,7 @@
#include "xenia/gpu/xenos.h"
#include "xenia/kernel/xthread.h"
#include "xenia/memory.h"
#include "xenia/ui/graphics_context.h"
#include "xenia/ui/presenter.h"
namespace xe {
@ -60,12 +60,20 @@ enum class SwapMode {
enum class GammaRampType {
kUnknown = 0,
kNormal,
kTable,
kPWL,
};
struct GammaRamp {
struct NormalEntry {
// A lot of gamma ramp (DC_LUT) documentation:
// https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf
// The ramps entries are BGR, not RGB.
// For the 256-entry table (used by Direct3D 9 for a 8bpc front buffer),
// 535107D4 has in-game settings allowing separate configuration.
// The component order of the PWL table is untested, however, it's likely BGR
// too, since DC_LUTA/B registers have values for blue first, and for red
// last.
struct TableEntry {
union {
uint32_t value;
struct {
@ -81,6 +89,15 @@ struct GammaRamp {
union {
uint32_t value;
struct {
// The lower 6 bits are always zero (these are 10-bit in the upper bits
// thus, not fully 16-bit).
// See DC_LUTA/B_CONTROL for information about the way they should be
// interpreted (`output = base + (multiplier * delta) / 2^increment`,
// where the increment is the value specified in DC_LUTA/B_CONTROL for
// the specific color channel, the base is 7 bits of the front buffer
// value above `increment` bits, the multiplier is the lower `increment`
// bits of it; the increment is nonzero, otherwise the 256-entry table
// should be used instead).
uint16_t base;
uint16_t delta;
};
@ -91,19 +108,25 @@ struct GammaRamp {
union {
PWLValue values[3];
struct {
PWLValue r;
PWLValue g;
PWLValue b;
PWLValue g;
PWLValue r;
};
};
};
NormalEntry normal[256];
TableEntry table[256];
PWLEntry pwl[128];
};
class CommandProcessor {
public:
enum class SwapPostEffect {
kNone,
kFxaa,
kFxaaExtreme,
};
CommandProcessor(GraphicsSystem* graphics_system,
kernel::KernelState* kernel_state);
virtual ~CommandProcessor();
@ -114,21 +137,26 @@ class CommandProcessor {
Shader* active_vertex_shader() const { return active_vertex_shader_; }
Shader* active_pixel_shader() const { return active_pixel_shader_; }
virtual bool Initialize(std::unique_ptr<xe::ui::GraphicsContext> context);
virtual bool Initialize();
virtual void Shutdown();
void CallInThread(std::function<void()> fn);
virtual void ClearCaches();
SwapState& swap_state() { return swap_state_; }
void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; }
void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height);
void set_swap_request_handler(std::function<void()> fn) {
swap_request_handler_ = fn;
void SetIgnoreSwap(bool ignore_swap) { ignore_swap_ = ignore_swap; }
// "Desired" is for the external thread managing the post-processing effect.
SwapPostEffect GetDesiredSwapPostEffect() const {
return swap_post_effect_desired_;
}
void SetDesiredSwapPostEffect(SwapPostEffect swap_post_effect);
// Implementations must not make assumptions that the front buffer will
// necessarily be a resolve destination - it may be a texture generated by any
// means like written to by the CPU or loaded from a file (the disclaimer
// screen right in the beginning of 4D530AA4 is not a resolved render target,
// for instance).
virtual void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) = 0;
// May be called not only from the command processor thread when the command
// processor is paused, and the termination of this function may be explicitly
@ -179,9 +207,6 @@ class CommandProcessor {
virtual void PrepareForWait();
virtual void ReturnFromWait();
virtual void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) = 0;
uint32_t ExecutePrimaryBuffer(uint32_t start_index, uint32_t end_index);
virtual void OnPrimaryBufferEnd() {}
void ExecuteIndirectBuffer(uint32_t ptr, uint32_t length);
@ -254,6 +279,14 @@ class CommandProcessor {
bool major_mode_explicit) = 0;
virtual bool IssueCopy() = 0;
// "Actual" is for the command processor thread, to be read by the
// implementations.
SwapPostEffect GetActualSwapPostEffect() const {
return swap_post_effect_actual_;
}
// TODO(Triang3l): Write the gamma ramp (including the display controller
// write pointers) in the common code.
virtual void InitializeTrace() = 0;
Memory* memory_ = nullptr;
@ -274,10 +307,8 @@ class CommandProcessor {
std::atomic<bool> worker_running_;
kernel::object_ref<kernel::XHostThread> worker_thread_;
std::unique_ptr<xe::ui::GraphicsContext> context_;
SwapMode swap_mode_ = SwapMode::kNormal;
SwapState swap_state_;
std::function<void()> swap_request_handler_;
bool ignore_swap_ = false;
std::queue<std::function<void()>> pending_fns_;
// MicroEngine binary from PM4_ME_INIT
@ -305,8 +336,13 @@ class CommandProcessor {
GammaRamp gamma_ramp_ = {};
int gamma_ramp_rw_subindex_ = 0;
bool dirty_gamma_ramp_normal_ = true;
bool dirty_gamma_ramp_table_ = true;
bool dirty_gamma_ramp_pwl_ = true;
// By default (such as for tools), post-processing is disabled.
// "Desired" is for the external thread managing the post-processing effect.
SwapPostEffect swap_post_effect_desired_ = SwapPostEffect::kNone;
SwapPostEffect swap_post_effect_actual_ = SwapPostEffect::kNone;
};
} // namespace gpu

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -32,8 +32,8 @@
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/xenos.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/ui/d3d12/d3d12_context.h"
#include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h"
#include "xenia/ui/d3d12/d3d12_provider.h"
#include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h"
#include "xenia/ui/d3d12/d3d12_util.h"
@ -58,8 +58,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void RestoreEdramSnapshot(const void* snapshot) override;
ui::d3d12::D3D12Context& GetD3D12Context() const {
return static_cast<ui::d3d12::D3D12Context&>(*context_);
ui::d3d12::D3D12Provider& GetD3D12Provider() const {
return *static_cast<ui::d3d12::D3D12Provider*>(
graphics_system_->provider());
}
// Returns the deferred drawing command list for the currently open
@ -153,7 +154,7 @@ class D3D12CommandProcessor : public CommandProcessor {
kEdramR32G32UintUAV,
kEdramR32G32B32A32UintUAV,
kGammaRampNormalSRV,
kGammaRampTableSRV,
kGammaRampPWLSRV,
// Beyond this point, SRVs are accessible to shaders through an unbounded
@ -210,15 +211,13 @@ class D3D12CommandProcessor : public CommandProcessor {
// Returns the text to display in the GPU backend name in the window title.
std::string GetWindowTitleText() const;
std::unique_ptr<xe::ui::RawImage> Capture();
protected:
bool SetupContext() override;
void ShutdownContext() override;
void WriteRegister(uint32_t index, uint32_t value) override;
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override;
void OnPrimaryBufferEnd() override;
@ -321,8 +320,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void CheckSubmissionFence(uint64_t await_submission);
// If is_guest_command is true, a new full frame - with full cleanup of
// resources and, if needed, starting capturing - is opened if pending (as
// opposed to simply resuming after mid-frame synchronization).
void BeginSubmission(bool is_guest_command);
// opposed to simply resuming after mid-frame synchronization). Returns
// whether a submission is open currently and the device is not removed.
bool BeginSubmission(bool is_guest_command);
// If is_swap is true, a full frame is closed - with, if needed, cache
// clearing and stopping capturing. Returns whether the submission was done
// successfully, if it has failed, leaves it open.
@ -380,6 +380,8 @@ class D3D12CommandProcessor : public CommandProcessor {
void WriteGammaRampSRV(bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const;
bool device_removed_ = false;
bool cache_clear_requested_ = false;
HANDLE fence_completion_event_ = nullptr;
@ -497,42 +499,73 @@ class D3D12CommandProcessor : public CommandProcessor {
std::unique_ptr<TextureCache> texture_cache_;
// Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL
// ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D.
ID3D12Resource* gamma_ramp_texture_ = nullptr;
D3D12_RESOURCE_STATES gamma_ramp_texture_state_;
// Bytes 0x0...0x3FF - 256-entry R10G10B10X2 gamma ramp (red and blue must be
// read as swapped - 535107D4 has settings allowing separate configuration).
// Bytes 0x400...0x9FF - 128-entry PWL R16G16 gamma ramp (R - base, G - delta,
// low 6 bits of each are zero, 3 elements per entry).
// https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf
Microsoft::WRL::ComPtr<ID3D12Resource> gamma_ramp_buffer_;
D3D12_RESOURCE_STATES gamma_ramp_buffer_state_;
// Upload buffer for an image that is the same as gamma_ramp_, but with
// kQueueFrames array layers.
ID3D12Resource* gamma_ramp_upload_ = nullptr;
uint8_t* gamma_ramp_upload_mapping_ = nullptr;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT gamma_ramp_footprints_[kQueueFrames * 2];
Microsoft::WRL::ComPtr<ID3D12Resource> gamma_ramp_upload_buffer_;
uint8_t* gamma_ramp_upload_buffer_mapping_ = nullptr;
static constexpr uint32_t kSwapTextureWidth = 1280;
static constexpr uint32_t kSwapTextureHeight = 720;
std::pair<uint32_t, uint32_t> GetSwapTextureSize() const {
return std::make_pair(
kSwapTextureWidth * texture_cache_->GetDrawResolutionScaleX(),
kSwapTextureHeight * texture_cache_->GetDrawResolutionScaleY());
}
std::pair<uint32_t, uint32_t> GetSwapScreenSize() const {
uint32_t resolution_scale =
std::max(texture_cache_->GetDrawResolutionScaleX(),
texture_cache_->GetDrawResolutionScaleY());
return std::make_pair(kSwapTextureWidth * resolution_scale,
kSwapTextureHeight * resolution_scale);
}
ID3D12Resource* swap_texture_ = nullptr;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT swap_texture_copy_footprint_;
UINT64 swap_texture_copy_size_;
ID3D12DescriptorHeap* swap_texture_rtv_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE swap_texture_rtv_;
ID3D12DescriptorHeap* swap_texture_srv_descriptor_heap_ = nullptr;
struct ApplyGammaConstants {
uint32_t size[2];
};
enum class ApplyGammaRootParameter : UINT {
kConstants,
kDestination,
kSource,
kRamp,
kCount,
};
Microsoft::WRL::ComPtr<ID3D12RootSignature> apply_gamma_root_signature_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> apply_gamma_table_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState>
apply_gamma_table_fxaa_luma_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> apply_gamma_pwl_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState>
apply_gamma_pwl_fxaa_luma_pipeline_;
struct FxaaConstants {
uint32_t size[2];
float size_inv[2];
};
enum class FxaaRootParameter : UINT {
kConstants,
kDestination,
kSource,
kCount,
};
Microsoft::WRL::ComPtr<ID3D12RootSignature> fxaa_root_signature_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> fxaa_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> fxaa_extreme_pipeline_;
// PWL gamma ramp can result in values with more precision than 10bpc. Though
// those sub-10bpc bits don't have any noticeable visual effect, so normally
// R10G10B10A2_UNORM is enough. But what's the most important is that for the
// original FXAA shader, the luma needs to be written to the alpha channel.
// For simplicity (to avoid modifying the FXAA shader and adding more texture
// fetches into it), and for the highest quality (preserving all 13 bits that
// may be generated by applying the PWL gamma ramp with an increment of 2^3,
// and also leaving some space for the result of applying fractional weights
// to calculate the luma), using R16G16B16A16_UNORM instead of
// R10G10B10X2_UNORM with a separate alpha texture.
static constexpr DXGI_FORMAT kFxaaSourceTextureFormat =
DXGI_FORMAT_R16G16B16A16_UNORM;
// Kept in NON_PIXEL_SHADER_RESOURCE state.
Microsoft::WRL::ComPtr<ID3D12Resource> fxaa_source_texture_;
uint64_t fxaa_source_texture_submission_ = 0;
// Unsubmitted barrier batch.
std::vector<D3D12_RESOURCE_BARRIER> barriers_;
// <Resource, submission where requested>, sorted by the submission number.
std::deque<std::pair<ID3D12Resource*, uint64_t>> buffers_for_deletion_;
std::deque<std::pair<uint64_t, ID3D12Resource*>> resources_for_deletion_;
static constexpr uint32_t kScratchBufferSizeIncrement = 16 * 1024 * 1024;
ID3D12Resource* scratch_buffer_ = nullptr;

View File

@ -22,13 +22,6 @@ namespace xe {
namespace gpu {
namespace d3d12 {
// Generated with `xb buildshaders`.
namespace shaders {
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h"
} // namespace shaders
D3D12GraphicsSystem::D3D12GraphicsSystem() {}
D3D12GraphicsSystem::~D3D12GraphicsSystem() {}
@ -48,198 +41,11 @@ std::string D3D12GraphicsSystem::name() const {
X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
ui::Window* target_window) {
ui::WindowedAppContext* app_context,
bool is_surface_required) {
provider_ = xe::ui::d3d12::D3D12Provider::Create();
auto d3d12_provider = static_cast<xe::ui::d3d12::D3D12Provider*>(provider());
auto device = d3d12_provider->GetDevice();
auto result = GraphicsSystem::Setup(processor, kernel_state, target_window);
if (result != X_STATUS_SUCCESS) {
return result;
}
if (target_window) {
display_context_ = reinterpret_cast<xe::ui::d3d12::D3D12Context*>(
target_window->context());
}
// Create the stretch pipeline root signature, with 1 parameter (source
// texture) for raw stretch and 3 parameters (source texture, gamma ramp LUT,
// inverse of the size of the gamma ramp LUT) for gamma-correcting stretch.
// Raw.
D3D12_ROOT_PARAMETER stretch_root_parameters[3];
stretch_root_parameters[0].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
stretch_root_parameters[0].DescriptorTable.NumDescriptorRanges = 1;
D3D12_DESCRIPTOR_RANGE stretch_root_texture_range;
stretch_root_texture_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
stretch_root_texture_range.NumDescriptors = 1;
stretch_root_texture_range.BaseShaderRegister = 0;
stretch_root_texture_range.RegisterSpace = 0;
stretch_root_texture_range.OffsetInDescriptorsFromTableStart = 0;
stretch_root_parameters[0].DescriptorTable.pDescriptorRanges =
&stretch_root_texture_range;
stretch_root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_STATIC_SAMPLER_DESC stretch_sampler_desc;
stretch_sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
stretch_sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.MipLODBias = 0.0f;
stretch_sampler_desc.MaxAnisotropy = 1;
stretch_sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
stretch_sampler_desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
stretch_sampler_desc.MinLOD = 0.0f;
stretch_sampler_desc.MaxLOD = 0.0f;
stretch_sampler_desc.ShaderRegister = 0;
stretch_sampler_desc.RegisterSpace = 0;
stretch_sampler_desc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC stretch_root_desc;
stretch_root_desc.NumParameters = 1;
stretch_root_desc.pParameters = stretch_root_parameters;
stretch_root_desc.NumStaticSamplers = 1;
stretch_root_desc.pStaticSamplers = &stretch_sampler_desc;
stretch_root_desc.Flags =
D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS;
stretch_root_signature_ =
ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc);
if (stretch_root_signature_ == nullptr) {
XELOGE("Failed to create the front buffer stretch root signature");
return X_STATUS_UNSUCCESSFUL;
}
// Gamma.
stretch_root_parameters[1].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
stretch_root_parameters[1].DescriptorTable.NumDescriptorRanges = 1;
D3D12_DESCRIPTOR_RANGE stretch_root_gamma_ramp_range;
stretch_root_gamma_ramp_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
stretch_root_gamma_ramp_range.NumDescriptors = 1;
stretch_root_gamma_ramp_range.BaseShaderRegister = 1;
stretch_root_gamma_ramp_range.RegisterSpace = 0;
stretch_root_gamma_ramp_range.OffsetInDescriptorsFromTableStart = 0;
stretch_root_parameters[1].DescriptorTable.pDescriptorRanges =
&stretch_root_gamma_ramp_range;
stretch_root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
stretch_root_parameters[2].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
stretch_root_parameters[2].Constants.ShaderRegister = 0;
stretch_root_parameters[2].Constants.RegisterSpace = 0;
stretch_root_parameters[2].Constants.Num32BitValues = 1;
stretch_root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
stretch_root_desc.NumParameters = 3;
stretch_root_desc.pParameters = stretch_root_parameters;
stretch_gamma_root_signature_ =
ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc);
if (stretch_gamma_root_signature_ == nullptr) {
XELOGE(
"Failed to create the gamma-correcting front buffer stretch root "
"signature");
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
// Create the stretch pipelines.
D3D12_GRAPHICS_PIPELINE_STATE_DESC stretch_pipeline_desc = {};
stretch_pipeline_desc.pRootSignature = stretch_root_signature_;
stretch_pipeline_desc.VS.pShaderBytecode = shaders::fullscreen_tc_vs;
stretch_pipeline_desc.VS.BytecodeLength = sizeof(shaders::fullscreen_tc_vs);
stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_ps;
stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_ps);
// The shader will set alpha to 1, don't use output-merger to preserve it.
stretch_pipeline_desc.BlendState.RenderTarget[0].RenderTargetWriteMask =
D3D12_COLOR_WRITE_ENABLE_ALL;
stretch_pipeline_desc.SampleMask = UINT_MAX;
stretch_pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
stretch_pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
stretch_pipeline_desc.RasterizerState.DepthClipEnable = TRUE;
stretch_pipeline_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
stretch_pipeline_desc.NumRenderTargets = 1;
stretch_pipeline_desc.RTVFormats[0] =
ui::d3d12::D3D12Context::kSwapChainFormat;
stretch_pipeline_desc.SampleDesc.Count = 1;
if (FAILED(device->CreateGraphicsPipelineState(
&stretch_pipeline_desc, IID_PPV_ARGS(&stretch_pipeline_)))) {
XELOGE("Failed to create the front buffer stretch pipeline");
stretch_gamma_root_signature_->Release();
stretch_gamma_root_signature_ = nullptr;
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
stretch_pipeline_desc.pRootSignature = stretch_gamma_root_signature_;
stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_gamma_ps;
stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_gamma_ps);
if (FAILED(device->CreateGraphicsPipelineState(
&stretch_pipeline_desc, IID_PPV_ARGS(&stretch_gamma_pipeline_)))) {
XELOGE(
"Failed to create the gamma-correcting front buffer stretch pipeline");
stretch_pipeline_->Release();
stretch_pipeline_ = nullptr;
stretch_gamma_root_signature_->Release();
stretch_gamma_root_signature_ = nullptr;
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
return X_STATUS_SUCCESS;
}
void D3D12GraphicsSystem::Shutdown() {
ui::d3d12::util::ReleaseAndNull(stretch_gamma_pipeline_);
ui::d3d12::util::ReleaseAndNull(stretch_pipeline_);
ui::d3d12::util::ReleaseAndNull(stretch_gamma_root_signature_);
ui::d3d12::util::ReleaseAndNull(stretch_root_signature_);
GraphicsSystem::Shutdown();
}
std::unique_ptr<xe::ui::RawImage> D3D12GraphicsSystem::Capture() {
auto d3d12_command_processor =
static_cast<D3D12CommandProcessor*>(command_processor());
if (!d3d12_command_processor) {
return nullptr;
}
return d3d12_command_processor->Capture();
}
void D3D12GraphicsSystem::StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
ID3D12GraphicsCommandList* command_list) {
if (gamma_ramp_handle != nullptr) {
command_list->SetPipelineState(stretch_gamma_pipeline_);
command_list->SetGraphicsRootSignature(stretch_gamma_root_signature_);
command_list->SetGraphicsRootDescriptorTable(1, *gamma_ramp_handle);
command_list->SetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, 0);
} else {
command_list->SetPipelineState(stretch_pipeline_);
command_list->SetGraphicsRootSignature(stretch_root_signature_);
}
command_list->SetGraphicsRootDescriptorTable(0, handle);
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
command_list->DrawInstanced(3, 1, 0, 0);
}
void D3D12GraphicsSystem::StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
DeferredCommandList& command_list) {
if (gamma_ramp_handle != nullptr) {
command_list.D3DSetPipelineState(stretch_gamma_pipeline_);
command_list.D3DSetGraphicsRootSignature(stretch_gamma_root_signature_);
command_list.D3DSetGraphicsRootDescriptorTable(1, *gamma_ramp_handle);
command_list.D3DSetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size,
0);
} else {
command_list.D3DSetPipelineState(stretch_pipeline_);
command_list.D3DSetGraphicsRootSignature(stretch_root_signature_);
}
command_list.D3DSetGraphicsRootDescriptorTable(0, handle);
command_list.D3DIASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
command_list.D3DDrawInstanced(3, 1, 0, 0);
return GraphicsSystem::Setup(processor, kernel_state, app_context,
is_surface_required);
}
std::unique_ptr<CommandProcessor>
@ -248,69 +54,6 @@ D3D12GraphicsSystem::CreateCommandProcessor() {
new D3D12CommandProcessor(this, kernel_state_));
}
void D3D12GraphicsSystem::Swap(xe::ui::UIEvent* e) {
if (display_context_->WasLost()) {
// We're crashing. Cheese it.
return;
}
if (!command_processor_) {
return;
}
auto& swap_state = command_processor_->swap_state();
ID3D12DescriptorHeap* swap_srv_heap;
{
std::lock_guard<std::mutex> lock(swap_state.mutex);
swap_state.pending = false;
swap_srv_heap = reinterpret_cast<ID3D12DescriptorHeap*>(
swap_state.front_buffer_texture);
}
if (swap_srv_heap == nullptr) {
// Not ready yet.
return;
}
uint32_t window_width, window_height;
display_context_->GetSwapChainSize(window_width, window_height);
int32_t target_x, target_y;
uint32_t target_width, target_height;
draw_util::GetPresentArea(swap_state.width, swap_state.height, window_width,
window_height, target_x, target_y, target_width,
target_height);
// For safety.
target_x = clamp(target_x, int32_t(D3D12_VIEWPORT_BOUNDS_MIN),
int32_t(D3D12_VIEWPORT_BOUNDS_MAX));
target_y = clamp(target_y, int32_t(D3D12_VIEWPORT_BOUNDS_MIN),
int32_t(D3D12_VIEWPORT_BOUNDS_MAX));
target_width = std::min(
target_width, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_x));
target_height = std::min(
target_height, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_y));
auto command_list = display_context_->GetSwapCommandList();
// Assuming the window has already been cleared to the needed letterbox color.
D3D12_VIEWPORT viewport;
viewport.TopLeftX = float(target_x);
viewport.TopLeftY = float(target_y);
viewport.Width = float(target_width);
viewport.Height = float(target_height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 0.0f;
command_list->RSSetViewports(1, &viewport);
D3D12_RECT scissor;
scissor.left = 0;
scissor.top = 0;
scissor.right = window_width;
scissor.bottom = window_height;
command_list->RSSetScissorRects(1, &scissor);
command_list->SetDescriptorHeaps(1, &swap_srv_heap);
StretchTextureToFrontBuffer(
swap_srv_heap->GetGPUDescriptorHandleForHeapStart(), nullptr, 0.0f,
command_list);
}
} // namespace d3d12
} // namespace gpu
} // namespace xe

View File

@ -15,7 +15,6 @@
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/d3d12/deferred_command_list.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/ui/d3d12/d3d12_context.h"
namespace xe {
namespace gpu {
@ -31,37 +30,11 @@ class D3D12GraphicsSystem : public GraphicsSystem {
std::string name() const override;
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
ui::Window* target_window) override;
void Shutdown() override;
std::unique_ptr<xe::ui::RawImage> Capture() override;
// Draws a texture covering the entire viewport to the render target currently
// bound on the specified command list (in D3D12Context::kSwapChainFormat).
// This changes the current pipeline, graphics root signature and primitive
// topology. The gamma ramp texture must be 1D if present at all, for linear
// space, pass nullptr as the gamma ramp.
void StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
ID3D12GraphicsCommandList* command_list);
void StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
DeferredCommandList& command_list);
ui::WindowedAppContext* app_context,
bool is_surface_required) override;
protected:
std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
void Swap(xe::ui::UIEvent* e) override;
private:
ui::d3d12::D3D12Context* display_context_ = nullptr;
ID3D12RootSignature* stretch_root_signature_ = nullptr;
ID3D12RootSignature* stretch_gamma_root_signature_ = nullptr;
ID3D12PipelineState* stretch_pipeline_ = nullptr;
ID3D12PipelineState* stretch_gamma_pipeline_ = nullptr;
};
} // namespace d3d12

View File

@ -33,7 +33,7 @@ bool D3D12PrimitiveProcessor::Initialize() {
return false;
}
frame_index_buffer_pool_ = std::make_unique<ui::d3d12::D3D12UploadBufferPool>(
command_processor_.GetD3D12Context().GetD3D12Provider(),
command_processor_.GetD3D12Provider(),
std::max(size_t(kMinRequiredConvertedIndexBufferSize),
ui::GraphicsUploadBufferPool::kDefaultPageSize));
return true;
@ -90,7 +90,7 @@ bool D3D12PrimitiveProcessor::InitializeBuiltin16BitIndexBuffer(
assert_null(builtin_index_buffer_upload_);
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
D3D12_RESOURCE_DESC resource_desc;

View File

@ -215,7 +215,7 @@ D3D12RenderTargetCache::~D3D12RenderTargetCache() { Shutdown(true); }
bool D3D12RenderTargetCache::Initialize() {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (cvars::render_target_path_d3d12 == "rtv") {
@ -1298,7 +1298,7 @@ bool D3D12RenderTargetCache::Update(bool is_rasterization_done,
void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@ -1311,7 +1311,7 @@ void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor(
void D3D12RenderTargetCache::WriteEdramRawUAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@ -1339,7 +1339,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2SRVDescriptor(
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@ -1366,7 +1366,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2UAVDescriptor(
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@ -1668,8 +1668,9 @@ bool D3D12RenderTargetCache::InitializeTraceSubmitDownloads() {
ui::d3d12::util::FillBufferResourceDesc(edram_snapshot_download_buffer_desc,
xenos::kEdramSizeBytes,
D3D12_RESOURCE_FLAG_NONE);
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (FAILED(device->CreateCommittedResource(
&ui::d3d12::util::kHeapPropertiesReadback,
provider.GetHeapFlagCreateNotZeroed(),
@ -1721,7 +1722,8 @@ void D3D12RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) {
// Create the buffer - will be used for copying to either a 32-bit 1280x2048
// render target or the EDRAM buffer.
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (!edram_snapshot_restore_pool_) {
edram_snapshot_restore_pool_ =
std::make_unique<ui::d3d12::D3D12UploadBufferPool>(
@ -1966,8 +1968,7 @@ DXGI_FORMAT D3D12RenderTargetCache::GetDepthSRVStencilDXGIFormat(
RenderTargetCache::RenderTarget* D3D12RenderTargetCache::CreateRenderTarget(
RenderTargetKey key) {
ID3D12Device* device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
D3D12_RESOURCE_DESC resource_desc;
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
@ -4345,8 +4346,7 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// ***************************************************************************
ID3D12PipelineState* const* pipelines;
ID3D12Device* device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
D3D12_INPUT_ELEMENT_DESC pipeline_input_element_desc;
pipeline_input_element_desc.SemanticName = "POSITION";
pipeline_input_element_desc.SemanticIndex = 0;
@ -4516,7 +4516,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
assert_true(GetPath() == Path::kHostRenderTargets);
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
uint64_t current_submission = command_processor_.GetCurrentSubmission();
DeferredCommandList& command_list =
@ -6476,8 +6476,8 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline(
// Pipeline
// ***************************************************************************
ID3D12PipelineState* pipeline = ui::d3d12::util::CreateComputePipeline(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
built_shader_.data(), built_shader_size_bytes,
command_processor_.GetD3D12Provider().GetDevice(), built_shader_.data(),
built_shader_size_bytes,
key.is_depth ? dump_root_signature_depth_ : dump_root_signature_color_);
const char* format_name =
key.is_depth
@ -6561,7 +6561,7 @@ void D3D12RenderTargetCache::DumpRenderTargets(uint32_t dump_base,
// 32bpp and 64bpp.
size_t edram_uav_indices[2] = {SIZE_MAX, SIZE_MAX};
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
if (!bindless_resources_used_) {
if (any_sources_32bpp_64bpp[0]) {
edram_uav_indices[0] = current_temporary_descriptors_cpu_.size();

View File

@ -43,7 +43,7 @@ bool D3D12SharedMemory::Initialize() {
InitializeCommon();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
D3D12_RESOURCE_DESC buffer_desc;
@ -215,8 +215,9 @@ void D3D12SharedMemory::CommitUAVWritesAndTransitionBuffer(
void D3D12SharedMemory::WriteRawSRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@ -226,8 +227,9 @@ void D3D12SharedMemory::WriteRawSRVDescriptor(
void D3D12SharedMemory::WriteRawUAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@ -252,8 +254,9 @@ void D3D12SharedMemory::WriteUintPow2SRVDescriptor(
assert_unhandled_case(element_size_bytes_pow2);
return;
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@ -278,8 +281,9 @@ void D3D12SharedMemory::WriteUintPow2UAVDescriptor(
assert_unhandled_case(element_size_bytes_pow2);
return;
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@ -298,8 +302,9 @@ bool D3D12SharedMemory::InitializeTraceSubmitDownloads() {
ui::d3d12::util::FillBufferResourceDesc(
download_buffer_desc, download_page_count << page_size_log2(),
D3D12_RESOURCE_FLAG_NONE);
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (FAILED(device->CreateCommittedResource(
&ui::d3d12::util::kHeapPropertiesReadback,
provider.GetHeapFlagCreateNotZeroed(), &download_buffer_desc,
@ -365,7 +370,7 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange(
<< host_gpu_memory_sparse_granularity_log2();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
ID3D12CommandQueue* direct_queue = provider.GetDirectQueue();

View File

@ -87,7 +87,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor,
register_file_(register_file),
render_target_cache_(render_target_cache),
bindless_resources_used_(bindless_resources_used) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
bool edram_rov_used = render_target_cache.GetPath() ==
RenderTargetCache::Path::kPixelShaderInterlock;
@ -109,7 +110,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor,
PipelineCache::~PipelineCache() { Shutdown(); }
bool PipelineCache::Initialize() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
// Initialize the command processor thread DXIL objects.
dxbc_converter_ = nullptr;
@ -414,7 +416,8 @@ void PipelineCache::InitializeShaderStorage(
std::mutex shaders_failed_to_translate_mutex;
std::vector<D3D12Shader::D3D12Translation*> shaders_failed_to_translate;
auto shader_translation_thread_function = [&]() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
StringBuffer ucode_disasm_buffer;
DxbcShaderTranslator translator(
provider.GetAdapterVendorID(), bindless_resources_used_,
@ -1241,7 +1244,8 @@ bool PipelineCache::TranslateAnalyzedShader(
}
// Disassemble the shader for dumping.
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (cvars::d3d12_dxbc_disasm_dxilconv) {
translation.DisassembleDxbcAndDxil(provider, cvars::d3d12_dxbc_disasm,
dxbc_converter, dxc_utils, dxc_compiler);
@ -2052,8 +2056,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
}
// Create the D3D12 pipeline state object.
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
ID3D12PipelineState* state;
if (FAILED(device->CreateGraphicsPipelineState(&state_desc,
IID_PPV_ARGS(&state)))) {

View File

@ -869,8 +869,9 @@ TextureCache::TextureCache(D3D12CommandProcessor& command_processor,
TextureCache::~TextureCache() { Shutdown(); }
bool TextureCache::Initialize() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (IsDrawResolutionScaled()) {
// Buffers not used yet - no need aliasing barriers to change ownership of
@ -1444,7 +1445,8 @@ void TextureCache::WriteActiveTextureBindfulSRV(
}
}
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
D3D12_CPU_DESCRIPTOR_HANDLE source_handle;
if (descriptor_index != UINT32_MAX) {
assert_not_null(texture);
@ -1622,8 +1624,7 @@ void TextureCache::WriteSampler(SamplerParameters parameters,
desc.MinLOD = float(parameters.mip_min_level);
// Maximum mip level is in the texture resource itself.
desc.MaxLOD = FLT_MAX;
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
device->CreateSampler(&desc, handle);
}
@ -1712,8 +1713,9 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted(
uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) *
draw_resolution_scale_area;
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
// Ensure GPU virtual memory for buffers that may be used to access the range
// is allocated - buffers are created. Always creating both buffers for all
@ -1943,8 +1945,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV(
scaled_resolve_2gb_buffers_[buffer_index];
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedSRV(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
handle, buffer->resource(),
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
@ -1961,8 +1963,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV(
scaled_resolve_2gb_buffers_[buffer_index];
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedUAV(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
handle, buffer->resource(),
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
@ -2254,8 +2256,9 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
// Untiling through a buffer instead of using unordered access because copying
// is not done that often.
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
// Assuming untiling will be the next operation.
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST;
ID3D12Resource* resource;
@ -2317,9 +2320,9 @@ bool TextureCache::LoadTextureData(Texture* texture) {
return true;
}
auto& command_list = command_processor_.GetDeferredCommandList();
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
DeferredCommandList& command_list =
command_processor_.GetDeferredCommandList();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
// Get the pipeline.
LoadMode load_mode = GetLoadMode(texture->key);
@ -2875,8 +2878,7 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
host_swizzle |
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
uint32_t descriptor_index;
if (bindless_resources_used_) {
descriptor_index =
@ -2928,7 +2930,8 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
D3D12_CPU_DESCRIPTOR_HANDLE TextureCache::GetTextureDescriptorCPUHandle(
uint32_t descriptor_index) const {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (bindless_resources_used_) {
return provider.OffsetViewDescriptor(
command_processor_.GetViewBindlessHeapCPUStart(), descriptor_index);

View File

@ -23,6 +23,7 @@
#include "xenia/gpu/texture_info.h"
#include "xenia/gpu/texture_util.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/graphics_util.h"
// Very prominent in 545407F2.
DEFINE_bool(
@ -33,85 +34,10 @@ DEFINE_bool(
"for certain games to display the scene graphics).",
"GPU");
DEFINE_bool(
present_rescale, true,
"Whether to rescale the image, instead of maintaining the original pixel "
"size, when presenting to the window. When this is disabled, other "
"positioning options are ignored.",
"GPU");
DEFINE_bool(
present_letterbox, true,
"Maintain aspect ratio when stretching by displaying bars around the image "
"when there's no more overscan area to crop out.",
"GPU");
// https://github.com/MonoGame/MonoGame/issues/4697#issuecomment-217779403
// Using the value from DirectXTK (5% cropped out from each side, thus 90%),
// which is not exactly the Xbox One title-safe area, but close, and within the
// action-safe area:
// https://github.com/microsoft/DirectXTK/blob/1e80a465c6960b457ef9ab6716672c1443a45024/Src/SimpleMath.cpp#L144
// XNA TitleSafeArea is 80%, but it's very conservative, designed for CRT, and
// is the title-safe area rather than the action-safe area.
// 90% is also exactly the fraction of 16:9 height in 16:10.
DEFINE_int32(
present_safe_area_x, 90,
"Percentage of the image width that can be kept when presenting to "
"maintain aspect ratio without letterboxing or stretching.",
"GPU");
DEFINE_int32(
present_safe_area_y, 90,
"Percentage of the image height that can be kept when presenting to "
"maintain aspect ratio without letterboxing or stretching.",
"GPU");
namespace xe {
namespace gpu {
namespace draw_util {
int32_t FloatToD3D11Fixed16p8(float f32) {
// https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#3.2.4.1%20FLOAT%20-%3E%20Fixed%20Point%20Integer
// Early exit tests.
// n == NaN || n.unbiasedExponent < -f-1 -> 0 . 0
if (!(std::abs(f32) >= 1.0f / 512.0f)) {
return 0;
}
// n >= (2^(i-1)-2^-f) -> 2^(i-1)-1 . 2^f-1
if (f32 >= 32768.0f - 1.0f / 256.0f) {
return (1 << 23) - 1;
}
// n <= -2^(i-1) -> -2^(i-1) . 0
if (f32 <= -32768.0f) {
return -32768 * 256;
}
uint32_t f32_bits = *reinterpret_cast<const uint32_t*>(&f32);
// Copy float32 mantissa bits [22:0] into corresponding bits [22:0] of a
// result buffer that has at least 24 bits total storage (before reaching
// rounding step further below). This includes one bit for the hidden 1.
// Set bit [23] (float32 hidden bit).
// Clear bits [31:24].
union {
int32_t s;
uint32_t u;
} result;
result.u = (f32_bits & ((1 << 23) - 1)) | (1 << 23);
// If the sign bit is set in the float32 number (negative), then take the 2's
// component of the entire set of bits.
if ((f32_bits >> 31) != 0) {
result.s = -result.s;
}
// Final calculation: extraBits = (mantissa - f) - n.unbiasedExponent
// (guaranteed to be >= 0).
int32_t exponent = int32_t((f32_bits >> 23) & 255) - 127;
uint32_t extra_bits = uint32_t(15 - exponent);
if (extra_bits) {
// Round the 32-bit value to a decimal that is extraBits to the left of
// the LSB end, using nearest-even.
result.u += (1 << (extra_bits - 1)) - 1 + ((result.u >> extra_bits) & 1);
// Shift right by extraBits (sign extending).
result.s >>= extra_bits;
}
return result.s;
}
bool IsRasterizationPotentiallyDone(const RegisterFile& regs,
bool primitive_polygonal) {
// TODO(Triang3l): Investigate ModeControl::kIgnore better, with respect to
@ -746,7 +672,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
regs.Get<reg::PA_SU_VTX_CNTL>().pix_center ? 0.0f : 0.5f;
int32_t vertices_fixed[6];
for (size_t i = 0; i < xe::countof(vertices_fixed); ++i) {
vertices_fixed[i] = FloatToD3D11Fixed16p8(
vertices_fixed[i] = ui::FloatToD3D11Fixed16p8(
xenos::GpuSwap(vertices_guest[i], fetch.endian) + half_pixel_offset);
}
// Inclusive.
@ -1151,87 +1077,6 @@ ResolveCopyShaderIndex ResolveInfo::GetCopyShader(
return shader;
}
void GetPresentArea(uint32_t source_width, uint32_t source_height,
uint32_t window_width, uint32_t window_height,
int32_t& target_x_out, int32_t& target_y_out,
uint32_t& target_width_out, uint32_t& target_height_out) {
if (!cvars::present_rescale) {
target_x_out = (int32_t(window_width) - int32_t(source_width)) / 2;
target_y_out = (int32_t(window_height) - int32_t(source_height)) / 2;
target_width_out = source_width;
target_height_out = source_height;
return;
}
// Prevent division by zero.
if (!source_width || !source_height) {
target_x_out = 0;
target_y_out = 0;
target_width_out = 0;
target_height_out = 0;
return;
}
if (uint64_t(window_width) * source_height >
uint64_t(source_width) * window_height) {
// The window is wider that the source - crop along Y, then letterbox or
// stretch along X.
uint32_t present_safe_area;
if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) {
present_safe_area = uint32_t(cvars::present_safe_area_y);
} else {
present_safe_area = 100;
}
uint32_t target_height =
uint32_t(uint64_t(window_width) * source_height / source_width);
bool letterbox = false;
if (target_height * present_safe_area > window_height * 100) {
// Don't crop out more than the safe area margin - letterbox or stretch.
target_height = window_height * 100 / present_safe_area;
letterbox = true;
}
if (letterbox && cvars::present_letterbox) {
uint32_t target_width =
uint32_t(uint64_t(source_width) * window_height * 100 /
(source_height * present_safe_area));
target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2;
target_width_out = target_width;
} else {
target_x_out = 0;
target_width_out = window_width;
}
target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2;
target_height_out = target_height;
} else {
// The window is taller than the source - crop along X, then letterbox or
// stretch along Y.
uint32_t present_safe_area;
if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) {
present_safe_area = uint32_t(cvars::present_safe_area_x);
} else {
present_safe_area = 100;
}
uint32_t target_width =
uint32_t(uint64_t(window_height) * source_width / source_height);
bool letterbox = false;
if (target_width * present_safe_area > window_width * 100) {
// Don't crop out more than the safe area margin - letterbox or stretch.
target_width = window_width * 100 / present_safe_area;
letterbox = true;
}
if (letterbox && cvars::present_letterbox) {
uint32_t target_height =
uint32_t(uint64_t(source_height) * window_width * 100 /
(source_width * present_safe_area));
target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2;
target_height_out = target_height;
} else {
target_y_out = 0;
target_height_out = window_height;
}
target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2;
target_width_out = target_width;
}
}
} // namespace draw_util
} // namespace gpu
} // namespace xe

View File

@ -25,15 +25,6 @@ namespace xe {
namespace gpu {
namespace draw_util {
// For estimating coverage extents from vertices. This may give results that are
// different than what the host GPU will actually draw (this is the reference
// conversion with 1/2 ULP accuracy, but Direct3D 11 permits 0.6 ULP tolerance
// in floating point to fixed point conversion), but is enough to tie-break
// vertices at pixel centers (due to the half-pixel offset applied to integer
// coordinates incorrectly, for instance) with some error tolerance near 0.5,
// for use with the top-left rasterization rule later.
int32_t FloatToD3D11Fixed16p8(float f32);
// Polygonal primitive types (not including points and lines) are rasterized as
// triangles, have front and back faces, and also support face culling and fill
// modes (polymode_front_ptype, polymode_back_ptype). Other primitive types are

View File

@ -2,13 +2,19 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/gpu/graphics_system.h"
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <utility>
#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
@ -48,70 +54,40 @@ GraphicsSystem::~GraphicsSystem() = default;
X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
ui::Window* target_window) {
ui::WindowedAppContext* app_context,
[[maybe_unused]] bool is_surface_required) {
memory_ = processor->memory();
processor_ = processor;
kernel_state_ = kernel_state;
target_window_ = target_window;
app_context_ = app_context;
// Initialize display and rendering context.
// This must happen on the UI thread.
std::unique_ptr<xe::ui::GraphicsContext> processor_context = nullptr;
if (provider_) {
// Setup the context the command processor will do all its drawing in.
bool contexts_initialized = true;
processor_context = provider()->CreateOffscreenContext();
if (processor_context) {
if (target_window_) {
if (!target_window_->app_context().CallInUIThreadSynchronous([&]() {
// Create the context used for presentation.
assert_null(target_window->context());
target_window_->set_context(
provider_->CreateContext(target_window_));
})) {
contexts_initialized = false;
}
}
// Safe if either the UI thread call or the presenter creation fails.
if (app_context_) {
app_context_->CallInUIThreadSynchronous([this]() {
presenter_ = provider_->CreatePresenter(
[this](bool is_responsible, bool statically_from_ui_thread) {
OnHostGpuLossFromAnyThread(is_responsible);
});
});
} else {
contexts_initialized = false;
}
if (!contexts_initialized) {
xe::FatalError(
"Unable to initialize graphics context. Xenia requires Vulkan "
"support.\n"
"\n"
"Ensure you have the latest drivers for your GPU and "
"that it supports Vulkan.\n"
"\n"
"See https://xenia.jp/faq/ for more information and a list of "
"supported GPUs.");
return X_STATUS_UNSUCCESSFUL;
// May be needed for offscreen use, such as capturing the guest output
// image.
presenter_ = provider_->CreatePresenter(
[this](bool is_responsible, bool statically_from_ui_thread) {
OnHostGpuLossFromAnyThread(is_responsible);
});
}
}
// Create command processor. This will spin up a thread to process all
// incoming ringbuffer packets.
command_processor_ = CreateCommandProcessor();
if (!command_processor_->Initialize(std::move(processor_context))) {
if (!command_processor_->Initialize()) {
XELOGE("Unable to initialize command processor");
return X_STATUS_UNSUCCESSFUL;
}
if (target_window) {
command_processor_->set_swap_request_handler(
[this]() { target_window_->Invalidate(); });
// Watch for paint requests to do our swap.
target_window->on_painting.AddListener(
[this](xe::ui::UIEvent* e) { Swap(e); });
// Watch for context lost events.
target_window->on_context_lost.AddListener(
[this](xe::ui::UIEvent* e) { Reset(); });
} else {
command_processor_->set_swap_request_handler([]() {});
}
// Let the processor know we want register access callbacks.
memory_->AddVirtualMappedRange(
0x7FC80000, 0xFFFF0000, 0x0000FFFF, this,
@ -152,6 +128,7 @@ void GraphicsSystem::Shutdown() {
if (command_processor_) {
EndTracing();
command_processor_->Shutdown();
command_processor_.reset();
}
if (vsync_worker_thread_) {
@ -159,13 +136,35 @@ void GraphicsSystem::Shutdown() {
vsync_worker_thread_->Wait(0, 0, 0, nullptr);
vsync_worker_thread_.reset();
}
if (presenter_) {
if (app_context_) {
app_context_->CallInUIThreadSynchronous([this]() { presenter_.reset(); });
}
// If there's no app context (thus the presenter is owned by the thread that
// initialized the GraphicsSystem) or can't be queueing UI thread calls
// anymore, shutdown anyway.
presenter_.reset();
}
provider_.reset();
}
void GraphicsSystem::Reset() {
// TODO(DrChat): Reset the system.
XELOGI("Context lost; Reset invoked");
Shutdown();
void GraphicsSystem::OnHostGpuLossFromAnyThread(
[[maybe_unused]] bool is_responsible) {
// TODO(Triang3l): Somehow gain exclusive ownership of the Provider (may be
// used by the command processor, the presenter, and possibly anything else,
// it's considered free-threaded, except for lifetime management which will be
// involved in this case) and reset it so a new host GPU API device is
// created. Then ask the command processor to reset itself in its thread, and
// ask the UI thread to reset the Presenter (the UI thread manages its
// lifetime - but if there's no WindowedAppContext, either don't reset it as
// in this case there's no user who needs uninterrupted gameplay, or somehow
// protect it with a mutex so any thread can be considered a UI thread and
// reset).
if (host_gpu_loss_reported_.test_and_set(std::memory_order_relaxed)) {
return;
}
xe::FatalError("Graphics device lost (probably due to an internal error)");
}

View File

@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@ -11,7 +11,10 @@
#define XENIA_GPU_GRAPHICS_SYSTEM_H_
#include <atomic>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
@ -19,7 +22,9 @@
#include "xenia/gpu/register_file.h"
#include "xenia/kernel/xthread.h"
#include "xenia/memory.h"
#include "xenia/ui/window.h"
#include "xenia/ui/graphics_provider.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/windowed_app_context.h"
#include "xenia/xbox.h"
namespace xe {
@ -41,14 +46,17 @@ class GraphicsSystem {
cpu::Processor* processor() const { return processor_; }
kernel::KernelState* kernel_state() const { return kernel_state_; }
ui::GraphicsProvider* provider() const { return provider_.get(); }
ui::Presenter* presenter() const { return presenter_.get(); }
virtual X_STATUS Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
ui::Window* target_window);
ui::WindowedAppContext* app_context,
bool is_surface_required);
virtual void Shutdown();
virtual void Reset();
virtual std::unique_ptr<xe::ui::RawImage> Capture() { return nullptr; }
// May be called from any thread any number of times, even during recovery
// from a device loss.
void OnHostGpuLossFromAnyThread(bool is_responsible);
RegisterFile* register_file() { return &register_file_; }
CommandProcessor* command_processor() const {
@ -91,12 +99,11 @@ class GraphicsSystem {
void WriteRegister(uint32_t addr, uint32_t value);
void MarkVblank();
virtual void Swap(xe::ui::UIEvent* e) = 0;
Memory* memory_ = nullptr;
cpu::Processor* processor_ = nullptr;
kernel::KernelState* kernel_state_ = nullptr;
ui::Window* target_window_ = nullptr;
ui::WindowedAppContext* app_context_ = nullptr;
std::unique_ptr<ui::GraphicsProvider> provider_;
uint32_t interrupt_callback_ = 0;
@ -109,6 +116,11 @@ class GraphicsSystem {
std::unique_ptr<CommandProcessor> command_processor_;
bool paused_ = false;
private:
std::unique_ptr<ui::Presenter> presenter_;
std::atomic_flag host_gpu_loss_reported_;
};
} // namespace gpu

View File

@ -31,7 +31,7 @@ void NullCommandProcessor::ShutdownContext() {
return CommandProcessor::ShutdownContext();
}
void NullCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
void NullCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
uint32_t frontbuffer_width,
uint32_t frontbuffer_height) {}

View File

@ -33,7 +33,7 @@ class NullCommandProcessor : public CommandProcessor {
bool SetupContext() override;
void ShutdownContext() override;
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override;
Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address,

View File

@ -23,31 +23,20 @@ NullGraphicsSystem::~NullGraphicsSystem() {}
X_STATUS NullGraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
ui::Window* target_window) {
ui::WindowedAppContext* app_context,
bool is_surface_required) {
// This is a null graphics system, but we still setup vulkan because UI needs
// it through us :|
provider_ = xe::ui::vulkan::VulkanProvider::Create();
return GraphicsSystem::Setup(processor, kernel_state, target_window);
provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required);
return GraphicsSystem::Setup(processor, kernel_state, app_context,
is_surface_required);
}
void NullGraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); }
std::unique_ptr<CommandProcessor> NullGraphicsSystem::CreateCommandProcessor() {
return std::unique_ptr<CommandProcessor>(
new NullCommandProcessor(this, kernel_state_));
}
void NullGraphicsSystem::Swap(xe::ui::UIEvent* e) {
if (!command_processor_) {
return;
}
auto& swap_state = command_processor_->swap_state();
std::lock_guard<std::mutex> lock(swap_state.mutex);
swap_state.pending = false;
}
} // namespace null
} // namespace gpu
} // namespace xe

View File

@ -29,13 +29,11 @@ class NullGraphicsSystem : public GraphicsSystem {
std::string name() const override { return "null"; }
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
ui::Window* target_window) override;
void Shutdown() override;
ui::WindowedAppContext* app_context,
bool is_surface_required) override;
private:
std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
void Swap(xe::ui::UIEvent* e) override;
};
} // namespace null

View File

@ -39,6 +39,7 @@ project("xenia-gpu-shader-compiler")
"spirv-tools",
"xenia-base",
"xenia-gpu",
"xenia-ui",
"xenia-ui-spirv",
})
defines({

View File

@ -0,0 +1,2 @@
float XeApplyGammaGetAlpha(float3 color) { return 1.0f; }
#include "apply_gamma_pwl.hlsli"

View File

@ -0,0 +1,41 @@
// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally.
cbuffer XeApplyGammaRampConstants : register(b0) {
uint2 xe_apply_gamma_size;
};
RWTexture2D<unorm float4> xe_apply_gamma_dest : register(u0);
Texture2D<float3> xe_apply_gamma_source : register(t0);
Buffer<uint2> xe_apply_gamma_ramp : register(t1);
float XeApplyPWLGamma(uint input, uint component) {
// TODO(Triang3l): If this is ever used for gamma other than 128 entries for a
// 10bpc front buffer, handle the increment from DC_LUTA/B_CONTROL. Currently
// assuming it's 2^3 = 8, or 1024 / 128.
// output = base + (multiplier * delta) / increment
// https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf
// The lower 6 bits of the base and the delta are 0 (though enforcing that in
// the shader is not necessary).
// The `(multiplier * delta) / increment` part may result in a nonzero value
// in the lower 6 bits of the result, however, so doing `* (1.0f / 64.0f)`
// instead of `>> 6` to preserve them (if the render target is 16bpc rather
// than 10bpc, for instance).
uint2 ramp_value = xe_apply_gamma_ramp[(input >> 3u) * 3u + component];
return saturate((float(ramp_value.x) +
float((input & 7u) * ramp_value.y) * (1.0f / 8.0f)) *
(1.0f / (64.0f * 1023.0f)));
}
[numthreads(8, 8, 1)]
void main(uint3 xe_thread_id : SV_DispatchThreadID) {
[branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) {
return;
}
// UNORM conversion according to the Direct3D 10+ rules.
uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 1023.0f + 0.5f);
// The ramp is BGR, not RGB.
float3 output = float3(XeApplyPWLGamma(input.r, 2u),
XeApplyPWLGamma(input.g, 1u),
XeApplyPWLGamma(input.b, 0u));
xe_apply_gamma_dest[xe_thread_id.xy] =
float4(output, XeApplyGammaGetAlpha(output));
}

View File

@ -0,0 +1,5 @@
// Perceptual luminance for FXAA.
float XeApplyGammaGetAlpha(float3 color) {
return dot(color, float3(0.299, 0.587, 0.114));
}
#include "apply_gamma_pwl.hlsli"

View File

@ -0,0 +1,2 @@
float XeApplyGammaGetAlpha(float3 color) { return 1.0f; }
#include "apply_gamma_table.hlsli"

View File

@ -0,0 +1,23 @@
// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally.
cbuffer XeApplyGammaRampConstants : register(b0) {
uint2 xe_apply_gamma_size;
};
RWTexture2D<unorm float4> xe_apply_gamma_dest : register(u0);
Texture2D<float3> xe_apply_gamma_source : register(t0);
Buffer<float3> xe_apply_gamma_ramp : register(t1);
[numthreads(8, 8, 1)]
void main(uint3 xe_thread_id : SV_DispatchThreadID) {
[branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) {
return;
}
// UNORM conversion according to the Direct3D 10+ rules.
uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 255.0f + 0.5f);
// The ramp is BGR, not RGB.
float3 output = float3(xe_apply_gamma_ramp[input.r].b,
xe_apply_gamma_ramp[input.g].g,
xe_apply_gamma_ramp[input.b].r);
xe_apply_gamma_dest[xe_thread_id.xy] =
float4(output, XeApplyGammaGetAlpha(output));
}

View File

@ -0,0 +1,5 @@
// Perceptual luminance for FXAA.
float XeApplyGammaGetAlpha(float3 color) {
return dot(color, float3(0.299, 0.587, 0.114));
}
#include "apply_gamma_table.hlsli"

View File

@ -1 +1,2 @@
DisableFormat: true
SortIncludes: false

View File

@ -84,10 +84,10 @@ ret
const BYTE adaptive_quad_hs[] =
{
68, 88, 66, 67, 94, 229,
104, 122, 195, 92, 144, 36,
252, 149, 235, 210, 131, 205,
139, 42, 1, 0, 0, 0,
68, 88, 66, 67, 91, 114,
196, 93, 35, 195, 210, 49,
154, 70, 168, 244, 8, 132,
25, 246, 1, 0, 0, 0,
176, 4, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
164, 0, 0, 0, 220, 0,
@ -98,7 +98,7 @@ const BYTE adaptive_quad_hs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 60, 0,
0, 5, 0, 0, 60, 0,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -73,10 +73,10 @@ ret
const BYTE adaptive_triangle_hs[] =
{
68, 88, 66, 67, 86, 168,
189, 119, 111, 17, 238, 147,
225, 129, 174, 39, 170, 24,
24, 225, 1, 0, 0, 0,
68, 88, 66, 67, 10, 165,
117, 176, 19, 12, 130, 108,
171, 104, 195, 161, 52, 251,
99, 193, 1, 0, 0, 0,
224, 3, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
164, 0, 0, 0, 220, 0,
@ -87,7 +87,7 @@ const BYTE adaptive_triangle_hs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 60, 0,
0, 5, 0, 0, 60, 0,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -0,0 +1,409 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeApplyGammaRampConstants
// {
//
// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_apply_gamma_source texture float3 2d T0 t0 1
// xe_apply_gamma_ramp texture uint2 buf T1 t1 1
// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1
// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0
dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0
dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0
dcl_input vThreadID.xy
dcl_temps 3
dcl_thread_group 8, 8, 1
uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx
or r0.x, r0.y, r0.x
if_nz r0.x
ret
endif
mov r0.xy, vThreadID.xyxx
mov r0.zw, l(0,0,0,0)
ld r0.xyz, r0.xyzw, T0[0].xyzw
mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000)
ftou r0.xyz, r0.xyzx
ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0)
imul null, r0.w, r1.z, l(3)
imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0)
ld r1.xz, r1.xxxx, T1[1].xzyw
utof r1.x, r1.x
and r0.xyz, r0.xyzx, l(7, 7, 7, 0)
imul null, r0.x, r1.z, r0.x
utof r0.x, r0.x
mad r0.x, r0.x, l(0.125000), r1.x
mul r0.x, r0.x, l(0.000015)
min r2.x, r0.x, l(1.000000)
ld r1.xy, r1.yyyy, T1[1].xyzw
utof r0.x, r1.x
imul null, r0.y, r0.y, r1.y
utof r0.y, r0.y
mad r0.x, r0.y, l(0.125000), r0.x
mul r0.x, r0.x, l(0.000015)
min r2.y, r0.x, l(1.000000)
ld r0.xy, r0.wwww, T1[1].xyzw
imul null, r0.y, r0.y, r0.z
utof r0.xy, r0.xyxx
mad r0.x, r0.y, l(0.125000), r0.x
mul r0.x, r0.x, l(0.000015)
min r2.z, r0.x, l(1.000000)
mov r2.w, l(1.000000)
store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw
ret
// Approximately 37 instruction slots used
#endif
const BYTE apply_gamma_pwl_cs[] =
{
68, 88, 66, 67, 180, 180,
222, 28, 4, 138, 188, 113,
52, 97, 214, 88, 116, 106,
105, 240, 1, 0, 0, 0,
128, 7, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
24, 2, 0, 0, 40, 2,
0, 0, 56, 2, 0, 0,
228, 6, 0, 0, 82, 68,
69, 70, 220, 1, 0, 0,
1, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 0, 0,
180, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
220, 0, 0, 0, 2, 0,
0, 0, 5, 0, 0, 0,
4, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 242, 0,
0, 0, 2, 0, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 255, 255, 255, 255,
1, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 6, 1, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 1, 0, 0, 0,
12, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
26, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 115, 111, 117, 114, 99,
101, 0, 120, 101, 95, 97,
112, 112, 108, 121, 95, 103,
97, 109, 109, 97, 95, 114,
97, 109, 112, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 100, 101, 115, 116, 0,
88, 101, 65, 112, 112, 108,
121, 71, 97, 109, 109, 97,
82, 97, 109, 112, 67, 111,
110, 115, 116, 97, 110, 116,
115, 0, 26, 1, 0, 0,
1, 0, 0, 0, 76, 1,
0, 0, 16, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 116, 1, 0, 0,
0, 0, 0, 0, 8, 0,
0, 0, 2, 0, 0, 0,
144, 1, 0, 0, 0, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
120, 101, 95, 97, 112, 112,
108, 121, 95, 103, 97, 109,
109, 97, 95, 115, 105, 122,
101, 0, 117, 105, 110, 116,
50, 0, 171, 171, 1, 0,
19, 0, 1, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
136, 1, 0, 0, 77, 105,
99, 114, 111, 115, 111, 102,
116, 32, 40, 82, 41, 32,
72, 76, 83, 76, 32, 83,
104, 97, 100, 101, 114, 32,
67, 111, 109, 112, 105, 108,
101, 114, 32, 49, 48, 46,
49, 0, 73, 83, 71, 78,
8, 0, 0, 0, 0, 0,
0, 0, 8, 0, 0, 0,
79, 83, 71, 78, 8, 0,
0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 83, 72,
69, 88, 164, 4, 0, 0,
81, 0, 5, 0, 41, 1,
0, 0, 106, 8, 0, 1,
89, 0, 0, 7, 70, 142,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 88, 24,
0, 7, 70, 126, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
85, 85, 0, 0, 0, 0,
0, 0, 88, 8, 0, 7,
70, 126, 48, 0, 1, 0,
0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 68, 68,
0, 0, 0, 0, 0, 0,
156, 24, 0, 7, 70, 238,
49, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 17, 17, 0, 0,
0, 0, 0, 0, 95, 0,
0, 2, 50, 0, 2, 0,
104, 0, 0, 2, 3, 0,
0, 0, 155, 0, 0, 4,
8, 0, 0, 0, 8, 0,
0, 0, 1, 0, 0, 0,
80, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
70, 0, 2, 0, 70, 128,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 0, 7,
18, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
31, 0, 4, 3, 10, 0,
16, 0, 0, 0, 0, 0,
62, 0, 0, 1, 21, 0,
0, 1, 54, 0, 0, 4,
50, 0, 16, 0, 0, 0,
0, 0, 70, 0, 2, 0,
54, 0, 0, 8, 194, 0,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 45, 0, 0, 8,
114, 0, 16, 0, 0, 0,
0, 0, 70, 14, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 50, 0,
0, 15, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 192,
127, 68, 0, 192, 127, 68,
0, 192, 127, 68, 0, 0,
0, 0, 2, 64, 0, 0,
0, 0, 0, 63, 0, 0,
0, 63, 0, 0, 0, 63,
0, 0, 0, 0, 28, 0,
0, 5, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
85, 0, 0, 10, 114, 0,
16, 0, 1, 0, 0, 0,
70, 2, 16, 0, 0, 0,
0, 0, 2, 64, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 38, 0,
0, 8, 0, 208, 0, 0,
130, 0, 16, 0, 0, 0,
0, 0, 42, 0, 16, 0,
1, 0, 0, 0, 1, 64,
0, 0, 3, 0, 0, 0,
35, 0, 0, 15, 50, 0,
16, 0, 1, 0, 0, 0,
70, 0, 16, 0, 1, 0,
0, 0, 2, 64, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 64,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
45, 0, 0, 8, 82, 0,
16, 0, 1, 0, 0, 0,
6, 0, 16, 0, 1, 0,
0, 0, 134, 125, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 86, 0, 0, 5,
18, 0, 16, 0, 1, 0,
0, 0, 10, 0, 16, 0,
1, 0, 0, 0, 1, 0,
0, 10, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 7, 0,
0, 0, 7, 0, 0, 0,
7, 0, 0, 0, 0, 0,
0, 0, 38, 0, 0, 8,
0, 208, 0, 0, 18, 0,
16, 0, 0, 0, 0, 0,
42, 0, 16, 0, 1, 0,
0, 0, 10, 0, 16, 0,
0, 0, 0, 0, 86, 0,
0, 5, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
50, 0, 0, 9, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
0, 0, 0, 62, 10, 0,
16, 0, 1, 0, 0, 0,
56, 0, 0, 7, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
8, 32, 128, 55, 51, 0,
0, 7, 18, 0, 16, 0,
2, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
128, 63, 45, 0, 0, 8,
50, 0, 16, 0, 1, 0,
0, 0, 86, 5, 16, 0,
1, 0, 0, 0, 70, 126,
32, 0, 1, 0, 0, 0,
1, 0, 0, 0, 86, 0,
0, 5, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 1, 0, 0, 0,
38, 0, 0, 8, 0, 208,
0, 0, 34, 0, 16, 0,
0, 0, 0, 0, 26, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 1, 0,
0, 0, 86, 0, 0, 5,
34, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 50, 0,
0, 9, 18, 0, 16, 0,
0, 0, 0, 0, 26, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
0, 62, 10, 0, 16, 0,
0, 0, 0, 0, 56, 0,
0, 7, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 8, 32,
128, 55, 51, 0, 0, 7,
34, 0, 16, 0, 2, 0,
0, 0, 10, 0, 16, 0,
0, 0, 0, 0, 1, 64,
0, 0, 0, 0, 128, 63,
45, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
246, 15, 16, 0, 0, 0,
0, 0, 70, 126, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 38, 0, 0, 8,
0, 208, 0, 0, 34, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 0, 0,
0, 0, 42, 0, 16, 0,
0, 0, 0, 0, 86, 0,
0, 5, 50, 0, 16, 0,
0, 0, 0, 0, 70, 0,
16, 0, 0, 0, 0, 0,
50, 0, 0, 9, 18, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
0, 0, 0, 62, 10, 0,
16, 0, 0, 0, 0, 0,
56, 0, 0, 7, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
8, 32, 128, 55, 51, 0,
0, 7, 66, 0, 16, 0,
2, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
128, 63, 54, 0, 0, 5,
130, 0, 16, 0, 2, 0,
0, 0, 1, 64, 0, 0,
0, 0, 128, 63, 164, 0,
0, 7, 242, 224, 33, 0,
0, 0, 0, 0, 0, 0,
0, 0, 70, 5, 2, 0,
70, 14, 16, 0, 2, 0,
0, 0, 62, 0, 0, 1,
83, 84, 65, 84, 148, 0,
0, 0, 37, 0, 0, 0,
3, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
10, 0, 0, 0, 5, 0,
0, 0, 4, 0, 0, 0,
2, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0,
0, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0
};

View File

@ -0,0 +1,413 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeApplyGammaRampConstants
// {
//
// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_apply_gamma_source texture float3 2d T0 t0 1
// xe_apply_gamma_ramp texture uint2 buf T1 t1 1
// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1
// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0
dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0
dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0
dcl_input vThreadID.xy
dcl_temps 3
dcl_thread_group 8, 8, 1
uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx
or r0.x, r0.y, r0.x
if_nz r0.x
ret
endif
mov r0.xy, vThreadID.xyxx
mov r0.zw, l(0,0,0,0)
ld r0.xyz, r0.xyzw, T0[0].xyzw
mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000)
ftou r0.xyz, r0.xyzx
ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0)
imul null, r0.w, r1.z, l(3)
imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0)
ld r1.xz, r1.xxxx, T1[1].xzyw
utof r1.x, r1.x
and r0.xyz, r0.xyzx, l(7, 7, 7, 0)
imul null, r0.x, r1.z, r0.x
utof r0.x, r0.x
mad r0.x, r0.x, l(0.125000), r1.x
mul r0.x, r0.x, l(0.000015)
min r2.x, r0.x, l(1.000000)
ld r1.xy, r1.yyyy, T1[1].xyzw
utof r0.x, r1.x
imul null, r0.y, r0.y, r1.y
utof r0.y, r0.y
mad r0.x, r0.y, l(0.125000), r0.x
mul r0.x, r0.x, l(0.000015)
min r2.y, r0.x, l(1.000000)
ld r0.xy, r0.wwww, T1[1].xyzw
imul null, r0.y, r0.y, r0.z
utof r0.xy, r0.xyxx
mad r0.x, r0.y, l(0.125000), r0.x
mul r0.x, r0.x, l(0.000015)
min r2.z, r0.x, l(1.000000)
dp3 r2.w, r2.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000)
store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw
ret
// Approximately 37 instruction slots used
#endif
const BYTE apply_gamma_pwl_fxaa_luma_cs[] =
{
68, 88, 66, 67, 165, 122,
242, 36, 160, 218, 193, 67,
37, 43, 138, 45, 109, 219,
226, 109, 1, 0, 0, 0,
148, 7, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
24, 2, 0, 0, 40, 2,
0, 0, 56, 2, 0, 0,
248, 6, 0, 0, 82, 68,
69, 70, 220, 1, 0, 0,
1, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 0, 0,
180, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
220, 0, 0, 0, 2, 0,
0, 0, 5, 0, 0, 0,
4, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 242, 0,
0, 0, 2, 0, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 255, 255, 255, 255,
1, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 6, 1, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 1, 0, 0, 0,
12, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
26, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 115, 111, 117, 114, 99,
101, 0, 120, 101, 95, 97,
112, 112, 108, 121, 95, 103,
97, 109, 109, 97, 95, 114,
97, 109, 112, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 100, 101, 115, 116, 0,
88, 101, 65, 112, 112, 108,
121, 71, 97, 109, 109, 97,
82, 97, 109, 112, 67, 111,
110, 115, 116, 97, 110, 116,
115, 0, 26, 1, 0, 0,
1, 0, 0, 0, 76, 1,
0, 0, 16, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 116, 1, 0, 0,
0, 0, 0, 0, 8, 0,
0, 0, 2, 0, 0, 0,
144, 1, 0, 0, 0, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
120, 101, 95, 97, 112, 112,
108, 121, 95, 103, 97, 109,
109, 97, 95, 115, 105, 122,
101, 0, 117, 105, 110, 116,
50, 0, 171, 171, 1, 0,
19, 0, 1, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
136, 1, 0, 0, 77, 105,
99, 114, 111, 115, 111, 102,
116, 32, 40, 82, 41, 32,
72, 76, 83, 76, 32, 83,
104, 97, 100, 101, 114, 32,
67, 111, 109, 112, 105, 108,
101, 114, 32, 49, 48, 46,
49, 0, 73, 83, 71, 78,
8, 0, 0, 0, 0, 0,
0, 0, 8, 0, 0, 0,
79, 83, 71, 78, 8, 0,
0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 83, 72,
69, 88, 184, 4, 0, 0,
81, 0, 5, 0, 46, 1,
0, 0, 106, 8, 0, 1,
89, 0, 0, 7, 70, 142,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 88, 24,
0, 7, 70, 126, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
85, 85, 0, 0, 0, 0,
0, 0, 88, 8, 0, 7,
70, 126, 48, 0, 1, 0,
0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 68, 68,
0, 0, 0, 0, 0, 0,
156, 24, 0, 7, 70, 238,
49, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 17, 17, 0, 0,
0, 0, 0, 0, 95, 0,
0, 2, 50, 0, 2, 0,
104, 0, 0, 2, 3, 0,
0, 0, 155, 0, 0, 4,
8, 0, 0, 0, 8, 0,
0, 0, 1, 0, 0, 0,
80, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
70, 0, 2, 0, 70, 128,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 0, 7,
18, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
31, 0, 4, 3, 10, 0,
16, 0, 0, 0, 0, 0,
62, 0, 0, 1, 21, 0,
0, 1, 54, 0, 0, 4,
50, 0, 16, 0, 0, 0,
0, 0, 70, 0, 2, 0,
54, 0, 0, 8, 194, 0,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 45, 0, 0, 8,
114, 0, 16, 0, 0, 0,
0, 0, 70, 14, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 50, 0,
0, 15, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 192,
127, 68, 0, 192, 127, 68,
0, 192, 127, 68, 0, 0,
0, 0, 2, 64, 0, 0,
0, 0, 0, 63, 0, 0,
0, 63, 0, 0, 0, 63,
0, 0, 0, 0, 28, 0,
0, 5, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
85, 0, 0, 10, 114, 0,
16, 0, 1, 0, 0, 0,
70, 2, 16, 0, 0, 0,
0, 0, 2, 64, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 38, 0,
0, 8, 0, 208, 0, 0,
130, 0, 16, 0, 0, 0,
0, 0, 42, 0, 16, 0,
1, 0, 0, 0, 1, 64,
0, 0, 3, 0, 0, 0,
35, 0, 0, 15, 50, 0,
16, 0, 1, 0, 0, 0,
70, 0, 16, 0, 1, 0,
0, 0, 2, 64, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 64,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
45, 0, 0, 8, 82, 0,
16, 0, 1, 0, 0, 0,
6, 0, 16, 0, 1, 0,
0, 0, 134, 125, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 86, 0, 0, 5,
18, 0, 16, 0, 1, 0,
0, 0, 10, 0, 16, 0,
1, 0, 0, 0, 1, 0,
0, 10, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 7, 0,
0, 0, 7, 0, 0, 0,
7, 0, 0, 0, 0, 0,
0, 0, 38, 0, 0, 8,
0, 208, 0, 0, 18, 0,
16, 0, 0, 0, 0, 0,
42, 0, 16, 0, 1, 0,
0, 0, 10, 0, 16, 0,
0, 0, 0, 0, 86, 0,
0, 5, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
50, 0, 0, 9, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
0, 0, 0, 62, 10, 0,
16, 0, 1, 0, 0, 0,
56, 0, 0, 7, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
8, 32, 128, 55, 51, 0,
0, 7, 18, 0, 16, 0,
2, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
128, 63, 45, 0, 0, 8,
50, 0, 16, 0, 1, 0,
0, 0, 86, 5, 16, 0,
1, 0, 0, 0, 70, 126,
32, 0, 1, 0, 0, 0,
1, 0, 0, 0, 86, 0,
0, 5, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 1, 0, 0, 0,
38, 0, 0, 8, 0, 208,
0, 0, 34, 0, 16, 0,
0, 0, 0, 0, 26, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 1, 0,
0, 0, 86, 0, 0, 5,
34, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 50, 0,
0, 9, 18, 0, 16, 0,
0, 0, 0, 0, 26, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
0, 62, 10, 0, 16, 0,
0, 0, 0, 0, 56, 0,
0, 7, 18, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 8, 32,
128, 55, 51, 0, 0, 7,
34, 0, 16, 0, 2, 0,
0, 0, 10, 0, 16, 0,
0, 0, 0, 0, 1, 64,
0, 0, 0, 0, 128, 63,
45, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
246, 15, 16, 0, 0, 0,
0, 0, 70, 126, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 38, 0, 0, 8,
0, 208, 0, 0, 34, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 0, 0,
0, 0, 42, 0, 16, 0,
0, 0, 0, 0, 86, 0,
0, 5, 50, 0, 16, 0,
0, 0, 0, 0, 70, 0,
16, 0, 0, 0, 0, 0,
50, 0, 0, 9, 18, 0,
16, 0, 0, 0, 0, 0,
26, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
0, 0, 0, 62, 10, 0,
16, 0, 0, 0, 0, 0,
56, 0, 0, 7, 18, 0,
16, 0, 0, 0, 0, 0,
10, 0, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
8, 32, 128, 55, 51, 0,
0, 7, 66, 0, 16, 0,
2, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
128, 63, 16, 0, 0, 10,
130, 0, 16, 0, 2, 0,
0, 0, 70, 2, 16, 0,
2, 0, 0, 0, 2, 64,
0, 0, 135, 22, 153, 62,
162, 69, 22, 63, 213, 120,
233, 61, 0, 0, 0, 0,
164, 0, 0, 7, 242, 224,
33, 0, 0, 0, 0, 0,
0, 0, 0, 0, 70, 5,
2, 0, 70, 14, 16, 0,
2, 0, 0, 0, 62, 0,
0, 1, 83, 84, 65, 84,
148, 0, 0, 0, 37, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 11, 0, 0, 0,
5, 0, 0, 0, 4, 0,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0
};

View File

@ -0,0 +1,281 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeApplyGammaRampConstants
// {
//
// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_apply_gamma_source texture float3 2d T0 t0 1
// xe_apply_gamma_ramp texture float3 buf T1 t1 1
// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1
// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0
dcl_resource_buffer (float,float,float,float) T1[1:1], space=0
dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0
dcl_input vThreadID.xy
dcl_temps 2
dcl_thread_group 8, 8, 1
uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx
or r0.x, r0.y, r0.x
if_nz r0.x
ret
endif
mov r0.xy, vThreadID.xyxx
mov r0.zw, l(0,0,0,0)
ld r0.xyz, r0.xyzw, T0[0].xyzw
mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000)
ftou r0.xyz, r0.xyzx
ld r1.x, r0.xxxx, T1[1].zxyw
ld r1.y, r0.yyyy, T1[1].xyzw
ld r1.z, r0.zzzz, T1[1].yzxw
mov r1.w, l(1.000000)
store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw
ret
// Approximately 16 instruction slots used
#endif
const BYTE apply_gamma_table_cs[] =
{
68, 88, 66, 67, 20, 63,
31, 100, 63, 232, 227, 64,
21, 8, 34, 27, 205, 36,
202, 71, 1, 0, 0, 0,
252, 4, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
24, 2, 0, 0, 40, 2,
0, 0, 56, 2, 0, 0,
96, 4, 0, 0, 82, 68,
69, 70, 220, 1, 0, 0,
1, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 0, 0,
180, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
220, 0, 0, 0, 2, 0,
0, 0, 5, 0, 0, 0,
4, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 242, 0,
0, 0, 2, 0, 0, 0,
5, 0, 0, 0, 1, 0,
0, 0, 255, 255, 255, 255,
1, 0, 0, 0, 1, 0,
0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 6, 1, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 1, 0, 0, 0,
12, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
26, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 115, 111, 117, 114, 99,
101, 0, 120, 101, 95, 97,
112, 112, 108, 121, 95, 103,
97, 109, 109, 97, 95, 114,
97, 109, 112, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 100, 101, 115, 116, 0,
88, 101, 65, 112, 112, 108,
121, 71, 97, 109, 109, 97,
82, 97, 109, 112, 67, 111,
110, 115, 116, 97, 110, 116,
115, 0, 26, 1, 0, 0,
1, 0, 0, 0, 76, 1,
0, 0, 16, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 116, 1, 0, 0,
0, 0, 0, 0, 8, 0,
0, 0, 2, 0, 0, 0,
144, 1, 0, 0, 0, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
120, 101, 95, 97, 112, 112,
108, 121, 95, 103, 97, 109,
109, 97, 95, 115, 105, 122,
101, 0, 117, 105, 110, 116,
50, 0, 171, 171, 1, 0,
19, 0, 1, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
136, 1, 0, 0, 77, 105,
99, 114, 111, 115, 111, 102,
116, 32, 40, 82, 41, 32,
72, 76, 83, 76, 32, 83,
104, 97, 100, 101, 114, 32,
67, 111, 109, 112, 105, 108,
101, 114, 32, 49, 48, 46,
49, 0, 73, 83, 71, 78,
8, 0, 0, 0, 0, 0,
0, 0, 8, 0, 0, 0,
79, 83, 71, 78, 8, 0,
0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 83, 72,
69, 88, 32, 2, 0, 0,
81, 0, 5, 0, 136, 0,
0, 0, 106, 8, 0, 1,
89, 0, 0, 7, 70, 142,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 88, 24,
0, 7, 70, 126, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
85, 85, 0, 0, 0, 0,
0, 0, 88, 8, 0, 7,
70, 126, 48, 0, 1, 0,
0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 85, 85,
0, 0, 0, 0, 0, 0,
156, 24, 0, 7, 70, 238,
49, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 17, 17, 0, 0,
0, 0, 0, 0, 95, 0,
0, 2, 50, 0, 2, 0,
104, 0, 0, 2, 2, 0,
0, 0, 155, 0, 0, 4,
8, 0, 0, 0, 8, 0,
0, 0, 1, 0, 0, 0,
80, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
70, 0, 2, 0, 70, 128,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 0, 7,
18, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
31, 0, 4, 3, 10, 0,
16, 0, 0, 0, 0, 0,
62, 0, 0, 1, 21, 0,
0, 1, 54, 0, 0, 4,
50, 0, 16, 0, 0, 0,
0, 0, 70, 0, 2, 0,
54, 0, 0, 8, 194, 0,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 45, 0, 0, 8,
114, 0, 16, 0, 0, 0,
0, 0, 70, 14, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 50, 0,
0, 15, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
127, 67, 0, 0, 127, 67,
0, 0, 127, 67, 0, 0,
0, 0, 2, 64, 0, 0,
0, 0, 0, 63, 0, 0,
0, 63, 0, 0, 0, 63,
0, 0, 0, 0, 28, 0,
0, 5, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
45, 0, 0, 8, 18, 0,
16, 0, 1, 0, 0, 0,
6, 0, 16, 0, 0, 0,
0, 0, 38, 125, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 45, 0, 0, 8,
34, 0, 16, 0, 1, 0,
0, 0, 86, 5, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 1, 0, 0, 0,
1, 0, 0, 0, 45, 0,
0, 8, 66, 0, 16, 0,
1, 0, 0, 0, 166, 10,
16, 0, 0, 0, 0, 0,
150, 124, 32, 0, 1, 0,
0, 0, 1, 0, 0, 0,
54, 0, 0, 5, 130, 0,
16, 0, 1, 0, 0, 0,
1, 64, 0, 0, 0, 0,
128, 63, 164, 0, 0, 7,
242, 224, 33, 0, 0, 0,
0, 0, 0, 0, 0, 0,
70, 5, 2, 0, 70, 14,
16, 0, 1, 0, 0, 0,
62, 0, 0, 1, 83, 84,
65, 84, 148, 0, 0, 0,
16, 0, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 2, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0
};

View File

@ -0,0 +1,284 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeApplyGammaRampConstants
// {
//
// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_apply_gamma_source texture float3 2d T0 t0 1
// xe_apply_gamma_ramp texture float3 buf T1 t1 1
// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1
// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0
dcl_resource_buffer (float,float,float,float) T1[1:1], space=0
dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0
dcl_input vThreadID.xy
dcl_temps 2
dcl_thread_group 8, 8, 1
uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx
or r0.x, r0.y, r0.x
if_nz r0.x
ret
endif
mov r0.xy, vThreadID.xyxx
mov r0.zw, l(0,0,0,0)
ld r0.xyz, r0.xyzw, T0[0].xyzw
mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000)
ftou r0.xyz, r0.xyzx
ld r1.x, r0.xxxx, T1[1].zxyw
ld r1.y, r0.yyyy, T1[1].xyzw
ld r1.z, r0.zzzz, T1[1].yzxw
dp3 r1.w, r1.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000)
store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw
ret
// Approximately 16 instruction slots used
#endif
const BYTE apply_gamma_table_fxaa_luma_cs[] =
{
68, 88, 66, 67, 148, 92,
39, 196, 202, 33, 41, 82,
77, 137, 192, 188, 150, 218,
30, 64, 1, 0, 0, 0,
16, 5, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
24, 2, 0, 0, 40, 2,
0, 0, 56, 2, 0, 0,
116, 4, 0, 0, 82, 68,
69, 70, 220, 1, 0, 0,
1, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 0, 0,
180, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
220, 0, 0, 0, 2, 0,
0, 0, 5, 0, 0, 0,
4, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 242, 0,
0, 0, 2, 0, 0, 0,
5, 0, 0, 0, 1, 0,
0, 0, 255, 255, 255, 255,
1, 0, 0, 0, 1, 0,
0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 6, 1, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 4, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 1, 0, 0, 0,
12, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
26, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 115, 111, 117, 114, 99,
101, 0, 120, 101, 95, 97,
112, 112, 108, 121, 95, 103,
97, 109, 109, 97, 95, 114,
97, 109, 112, 0, 120, 101,
95, 97, 112, 112, 108, 121,
95, 103, 97, 109, 109, 97,
95, 100, 101, 115, 116, 0,
88, 101, 65, 112, 112, 108,
121, 71, 97, 109, 109, 97,
82, 97, 109, 112, 67, 111,
110, 115, 116, 97, 110, 116,
115, 0, 26, 1, 0, 0,
1, 0, 0, 0, 76, 1,
0, 0, 16, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 116, 1, 0, 0,
0, 0, 0, 0, 8, 0,
0, 0, 2, 0, 0, 0,
144, 1, 0, 0, 0, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
120, 101, 95, 97, 112, 112,
108, 121, 95, 103, 97, 109,
109, 97, 95, 115, 105, 122,
101, 0, 117, 105, 110, 116,
50, 0, 171, 171, 1, 0,
19, 0, 1, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
136, 1, 0, 0, 77, 105,
99, 114, 111, 115, 111, 102,
116, 32, 40, 82, 41, 32,
72, 76, 83, 76, 32, 83,
104, 97, 100, 101, 114, 32,
67, 111, 109, 112, 105, 108,
101, 114, 32, 49, 48, 46,
49, 0, 73, 83, 71, 78,
8, 0, 0, 0, 0, 0,
0, 0, 8, 0, 0, 0,
79, 83, 71, 78, 8, 0,
0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 83, 72,
69, 88, 52, 2, 0, 0,
81, 0, 5, 0, 141, 0,
0, 0, 106, 8, 0, 1,
89, 0, 0, 7, 70, 142,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 88, 24,
0, 7, 70, 126, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
85, 85, 0, 0, 0, 0,
0, 0, 88, 8, 0, 7,
70, 126, 48, 0, 1, 0,
0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 85, 85,
0, 0, 0, 0, 0, 0,
156, 24, 0, 7, 70, 238,
49, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 17, 17, 0, 0,
0, 0, 0, 0, 95, 0,
0, 2, 50, 0, 2, 0,
104, 0, 0, 2, 2, 0,
0, 0, 155, 0, 0, 4,
8, 0, 0, 0, 8, 0,
0, 0, 1, 0, 0, 0,
80, 0, 0, 8, 50, 0,
16, 0, 0, 0, 0, 0,
70, 0, 2, 0, 70, 128,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 60, 0, 0, 7,
18, 0, 16, 0, 0, 0,
0, 0, 26, 0, 16, 0,
0, 0, 0, 0, 10, 0,
16, 0, 0, 0, 0, 0,
31, 0, 4, 3, 10, 0,
16, 0, 0, 0, 0, 0,
62, 0, 0, 1, 21, 0,
0, 1, 54, 0, 0, 4,
50, 0, 16, 0, 0, 0,
0, 0, 70, 0, 2, 0,
54, 0, 0, 8, 194, 0,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 45, 0, 0, 8,
114, 0, 16, 0, 0, 0,
0, 0, 70, 14, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 50, 0,
0, 15, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
2, 64, 0, 0, 0, 0,
127, 67, 0, 0, 127, 67,
0, 0, 127, 67, 0, 0,
0, 0, 2, 64, 0, 0,
0, 0, 0, 63, 0, 0,
0, 63, 0, 0, 0, 63,
0, 0, 0, 0, 28, 0,
0, 5, 114, 0, 16, 0,
0, 0, 0, 0, 70, 2,
16, 0, 0, 0, 0, 0,
45, 0, 0, 8, 18, 0,
16, 0, 1, 0, 0, 0,
6, 0, 16, 0, 0, 0,
0, 0, 38, 125, 32, 0,
1, 0, 0, 0, 1, 0,
0, 0, 45, 0, 0, 8,
34, 0, 16, 0, 1, 0,
0, 0, 86, 5, 16, 0,
0, 0, 0, 0, 70, 126,
32, 0, 1, 0, 0, 0,
1, 0, 0, 0, 45, 0,
0, 8, 66, 0, 16, 0,
1, 0, 0, 0, 166, 10,
16, 0, 0, 0, 0, 0,
150, 124, 32, 0, 1, 0,
0, 0, 1, 0, 0, 0,
16, 0, 0, 10, 130, 0,
16, 0, 1, 0, 0, 0,
70, 2, 16, 0, 1, 0,
0, 0, 2, 64, 0, 0,
135, 22, 153, 62, 162, 69,
22, 63, 213, 120, 233, 61,
0, 0, 0, 0, 164, 0,
0, 7, 242, 224, 33, 0,
0, 0, 0, 0, 0, 0,
0, 0, 70, 5, 2, 0,
70, 14, 16, 0, 1, 0,
0, 0, 62, 0, 0, 1,
83, 84, 65, 84, 148, 0,
0, 0, 16, 0, 0, 0,
2, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
2, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0,
2, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0
};

View File

@ -44,10 +44,10 @@ ret
const BYTE clear_uint2_ps[] =
{
68, 88, 66, 67, 37, 23,
17, 1, 102, 148, 181, 42,
241, 102, 112, 167, 142, 147,
73, 7, 1, 0, 0, 0,
68, 88, 66, 67, 90, 79,
67, 15, 17, 175, 210, 170,
189, 222, 209, 228, 62, 31,
153, 246, 1, 0, 0, 0,
148, 2, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
88, 1, 0, 0, 104, 1,
@ -57,7 +57,7 @@ const BYTE clear_uint2_ps[] =
1, 0, 0, 0, 120, 0,
0, 0, 1, 0, 0, 0,
60, 0, 0, 0, 1, 5,
255, 255, 0, 5, 4, 0,
255, 255, 0, 5, 0, 0,
244, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -121,10 +121,10 @@ ret
const BYTE continuous_quad_hs[] =
{
68, 88, 66, 67, 109, 174,
137, 67, 82, 213, 246, 48,
97, 232, 232, 104, 109, 96,
97, 35, 1, 0, 0, 0,
68, 88, 66, 67, 38, 148,
187, 235, 226, 45, 172, 116,
78, 244, 151, 91, 91, 131,
203, 9, 1, 0, 0, 0,
240, 13, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
188, 10, 0, 0, 240, 10,
@ -135,7 +135,7 @@ const BYTE continuous_quad_hs[] =
0, 0, 120, 0, 0, 0,
1, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 82, 10,
0, 5, 0, 0, 82, 10,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -112,10 +112,10 @@ ret
const BYTE continuous_triangle_hs[] =
{
68, 88, 66, 67, 150, 55,
56, 98, 126, 111, 114, 179,
197, 7, 10, 15, 70, 32,
249, 93, 1, 0, 0, 0,
68, 88, 66, 67, 73, 225,
250, 199, 94, 238, 81, 135,
38, 37, 240, 107, 243, 39,
228, 138, 1, 0, 0, 0,
96, 13, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
188, 10, 0, 0, 240, 10,
@ -126,7 +126,7 @@ const BYTE continuous_triangle_hs[] =
0, 0, 120, 0, 0, 0,
1, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 82, 10,
0, 5, 0, 0, 82, 10,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -121,10 +121,10 @@ ret
const BYTE discrete_quad_hs[] =
{
68, 88, 66, 67, 174, 141,
75, 94, 70, 108, 133, 212,
18, 161, 84, 115, 238, 199,
1, 25, 1, 0, 0, 0,
68, 88, 66, 67, 30, 187,
71, 171, 142, 3, 72, 194,
131, 236, 131, 25, 126, 147,
165, 207, 1, 0, 0, 0,
240, 13, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
188, 10, 0, 0, 240, 10,
@ -135,7 +135,7 @@ const BYTE discrete_quad_hs[] =
0, 0, 120, 0, 0, 0,
1, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 82, 10,
0, 5, 0, 0, 82, 10,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -112,10 +112,10 @@ ret
const BYTE discrete_triangle_hs[] =
{
68, 88, 66, 67, 100, 231,
203, 227, 24, 0, 204, 209,
145, 54, 166, 75, 102, 255,
190, 98, 1, 0, 0, 0,
68, 88, 66, 67, 59, 166,
23, 194, 170, 244, 84, 16,
156, 139, 156, 141, 147, 143,
102, 19, 1, 0, 0, 0,
96, 13, 0, 0, 6, 0,
0, 0, 56, 0, 0, 0,
188, 10, 0, 0, 240, 10,
@ -126,7 +126,7 @@ const BYTE discrete_triangle_hs[] =
0, 0, 120, 0, 0, 0,
1, 0, 0, 0, 60, 0,
0, 0, 1, 5, 83, 72,
0, 5, 4, 0, 82, 10,
0, 5, 0, 0, 82, 10,
0, 0, 19, 19, 68, 37,
60, 0, 0, 0, 24, 0,
0, 0, 40, 0, 0, 0,

View File

@ -76,10 +76,10 @@ ret
const BYTE float24_round_ps[] =
{
68, 88, 66, 67, 23, 65,
158, 4, 125, 87, 131, 240,
183, 241, 233, 246, 170, 100,
46, 3, 1, 0, 0, 0,
68, 88, 66, 67, 229, 54,
46, 1, 194, 31, 164, 202,
193, 71, 175, 129, 44, 52,
218, 154, 1, 0, 0, 0,
8, 7, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 120, 2,
@ -89,7 +89,7 @@ const BYTE float24_round_ps[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
255, 255, 0, 5, 4, 0,
255, 255, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -58,10 +58,10 @@ ret
const BYTE float24_truncate_ps[] =
{
68, 88, 66, 67, 73, 81,
190, 30, 130, 230, 10, 4,
35, 6, 194, 2, 204, 207,
200, 64, 1, 0, 0, 0,
68, 88, 66, 67, 234, 72,
187, 196, 185, 155, 10, 179,
119, 204, 17, 88, 131, 142,
107, 205, 1, 0, 0, 0,
140, 4, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 120, 2,
@ -71,7 +71,7 @@ const BYTE float24_truncate_ps[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
255, 255, 0, 5, 4, 0,
255, 255, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1,166 +0,0 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_VertexID 0 x 0 VERTID uint x
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// TEXCOORD 0 xy 0 NONE float xy
// SV_Position 0 xyzw 1 POS float xyzw
//
vs_5_1
dcl_globalFlags refactoringAllowed
dcl_input_sgv v0.x, vertex_id
dcl_output o0.xy
dcl_output_siv o1.xyzw, position
dcl_temps 1
ishl r0.y, v0.x, l(1)
mov r0.x, v0.x
and r0.xy, r0.xyxx, l(2, 2, 0, 0)
utof r0.xy, r0.xyxx
mad o1.xy, r0.xyxx, l(2.000000, -2.000000, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000)
mov o1.zw, l(0,0,0,1.000000)
mov o0.xy, r0.xyxx
ret
// Approximately 8 instruction slots used
#endif
const BYTE fullscreen_tc_vs[] =
{
68, 88, 66, 67, 194, 19,
91, 0, 93, 21, 209, 27,
252, 153, 187, 171, 84, 80,
251, 138, 1, 0, 0, 0,
240, 2, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 212, 0,
0, 0, 44, 1, 0, 0,
84, 2, 0, 0, 82, 68,
69, 70, 100, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
254, 255, 0, 5, 4, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
77, 105, 99, 114, 111, 115,
111, 102, 116, 32, 40, 82,
41, 32, 72, 76, 83, 76,
32, 83, 104, 97, 100, 101,
114, 32, 67, 111, 109, 112,
105, 108, 101, 114, 32, 49,
48, 46, 49, 0, 73, 83,
71, 78, 44, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 32, 0, 0, 0,
0, 0, 0, 0, 6, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1,
0, 0, 83, 86, 95, 86,
101, 114, 116, 101, 120, 73,
68, 0, 79, 83, 71, 78,
80, 0, 0, 0, 2, 0,
0, 0, 8, 0, 0, 0,
56, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0,
0, 0, 3, 12, 0, 0,
65, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
3, 0, 0, 0, 1, 0,
0, 0, 15, 0, 0, 0,
84, 69, 88, 67, 79, 79,
82, 68, 0, 83, 86, 95,
80, 111, 115, 105, 116, 105,
111, 110, 0, 171, 171, 171,
83, 72, 69, 88, 32, 1,
0, 0, 81, 0, 1, 0,
72, 0, 0, 0, 106, 8,
0, 1, 96, 0, 0, 4,
18, 16, 16, 0, 0, 0,
0, 0, 6, 0, 0, 0,
101, 0, 0, 3, 50, 32,
16, 0, 0, 0, 0, 0,
103, 0, 0, 4, 242, 32,
16, 0, 1, 0, 0, 0,
1, 0, 0, 0, 104, 0,
0, 2, 1, 0, 0, 0,
41, 0, 0, 7, 34, 0,
16, 0, 0, 0, 0, 0,
10, 16, 16, 0, 0, 0,
0, 0, 1, 64, 0, 0,
1, 0, 0, 0, 54, 0,
0, 5, 18, 0, 16, 0,
0, 0, 0, 0, 10, 16,
16, 0, 0, 0, 0, 0,
1, 0, 0, 10, 50, 0,
16, 0, 0, 0, 0, 0,
70, 0, 16, 0, 0, 0,
0, 0, 2, 64, 0, 0,
2, 0, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 86, 0,
0, 5, 50, 0, 16, 0,
0, 0, 0, 0, 70, 0,
16, 0, 0, 0, 0, 0,
50, 0, 0, 15, 50, 32,
16, 0, 1, 0, 0, 0,
70, 0, 16, 0, 0, 0,
0, 0, 2, 64, 0, 0,
0, 0, 0, 64, 0, 0,
0, 192, 0, 0, 0, 0,
0, 0, 0, 0, 2, 64,
0, 0, 0, 0, 128, 191,
0, 0, 128, 63, 0, 0,
0, 0, 0, 0, 0, 0,
54, 0, 0, 8, 194, 32,
16, 0, 1, 0, 0, 0,
2, 64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
128, 63, 54, 0, 0, 5,
50, 32, 16, 0, 0, 0,
0, 0, 70, 0, 16, 0,
0, 0, 0, 0, 62, 0,
0, 1, 83, 84, 65, 84,
148, 0, 0, 0, 8, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0
};

View File

@ -34,10 +34,10 @@ ret
const BYTE fullscreen_vs[] =
{
68, 88, 66, 67, 11, 43,
171, 43, 233, 188, 20, 107,
115, 148, 0, 215, 116, 165,
194, 26, 1, 0, 0, 0,
68, 88, 66, 67, 111, 71,
234, 43, 238, 70, 168, 114,
17, 145, 139, 145, 152, 124,
190, 180, 1, 0, 0, 0,
172, 2, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 212, 0,
@ -47,7 +47,7 @@ const BYTE fullscreen_vs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
254, 255, 0, 5, 4, 0,
254, 255, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -100,10 +100,10 @@ ret
const BYTE host_depth_store_1xmsaa_cs[] =
{
68, 88, 66, 67, 40, 219,
237, 83, 207, 54, 217, 154,
183, 72, 124, 224, 242, 47,
153, 1, 1, 0, 0, 0,
68, 88, 66, 67, 240, 197,
52, 115, 102, 12, 206, 220,
26, 47, 204, 31, 163, 187,
103, 82, 1, 0, 0, 0,
196, 9, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
172, 2, 0, 0, 188, 2,
@ -113,7 +113,7 @@ const BYTE host_depth_store_1xmsaa_cs[] =
2, 0, 0, 0, 92, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
70, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -113,10 +113,10 @@ ret
const BYTE host_depth_store_2xmsaa_cs[] =
{
68, 88, 66, 67, 238, 111,
30, 240, 147, 73, 122, 32,
177, 28, 116, 35, 239, 195,
44, 205, 1, 0, 0, 0,
68, 88, 66, 67, 220, 153,
96, 168, 160, 176, 100, 61,
221, 246, 187, 57, 87, 53,
74, 27, 1, 0, 0, 0,
104, 11, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
172, 2, 0, 0, 188, 2,
@ -126,7 +126,7 @@ const BYTE host_depth_store_2xmsaa_cs[] =
2, 0, 0, 0, 92, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
70, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -102,10 +102,10 @@ ret
const BYTE host_depth_store_4xmsaa_cs[] =
{
68, 88, 66, 67, 2, 59,
173, 180, 27, 122, 26, 189,
176, 122, 66, 167, 148, 57,
133, 176, 1, 0, 0, 0,
68, 88, 66, 67, 255, 93,
213, 231, 110, 151, 46, 65,
140, 74, 54, 254, 196, 135,
241, 89, 1, 0, 0, 0,
72, 10, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
172, 2, 0, 0, 188, 2,
@ -115,7 +115,7 @@ const BYTE host_depth_store_4xmsaa_cs[] =
2, 0, 0, 0, 92, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
70, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -29,10 +29,10 @@ ret
const BYTE passthrough_position_xy_vs[] =
{
68, 88, 66, 67, 228, 252,
150, 103, 204, 200, 35, 231,
157, 180, 182, 79, 123, 204,
157, 78, 1, 0, 0, 0,
68, 88, 66, 67, 92, 220,
0, 199, 190, 67, 183, 153,
171, 192, 4, 39, 67, 55,
215, 255, 1, 0, 0, 0,
12, 2, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 212, 0,
@ -42,7 +42,7 @@ const BYTE passthrough_position_xy_vs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
254, 255, 0, 5, 4, 0,
254, 255, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -273,10 +273,10 @@ ret
const BYTE primitive_point_list_gs[] =
{
68, 88, 66, 67, 22, 253,
167, 182, 60, 53, 75, 37,
178, 38, 230, 182, 97, 141,
160, 120, 1, 0, 0, 0,
68, 88, 66, 67, 6, 119,
40, 99, 120, 121, 153, 224,
111, 77, 187, 15, 15, 245,
37, 128, 1, 0, 0, 0,
136, 29, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
184, 10, 0, 0, 248, 12,
@ -286,7 +286,7 @@ const BYTE primitive_point_list_gs[] =
1, 0, 0, 0, 120, 0,
0, 0, 1, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 71, 0, 5, 4, 0,
83, 71, 0, 5, 0, 0,
82, 10, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -194,10 +194,10 @@ ret
const BYTE primitive_quad_list_gs[] =
{
68, 88, 66, 67, 60, 29,
113, 120, 166, 105, 127, 75,
174, 160, 2, 184, 182, 91,
66, 12, 1, 0, 0, 0,
68, 88, 66, 67, 26, 143,
179, 72, 238, 147, 43, 130,
37, 11, 116, 191, 138, 68,
255, 76, 1, 0, 0, 0,
36, 16, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 224, 2,
@ -207,7 +207,7 @@ const BYTE primitive_quad_list_gs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 71, 0, 5, 4, 0,
83, 71, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -424,10 +424,10 @@ ret
const BYTE primitive_rectangle_list_gs[] =
{
68, 88, 66, 67, 8, 81,
101, 117, 123, 39, 249, 189,
184, 94, 218, 115, 216, 148,
125, 96, 1, 0, 0, 0,
68, 88, 66, 67, 84, 207,
1, 11, 213, 109, 28, 213,
94, 110, 135, 167, 112, 243,
154, 30, 1, 0, 0, 0,
68, 40, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
160, 0, 0, 0, 224, 2,
@ -437,7 +437,7 @@ const BYTE primitive_rectangle_list_gs[] =
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 71, 0, 5, 4, 0,
83, 71, 0, 5, 0, 0,
60, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -80,10 +80,10 @@ ret
const BYTE resolve_clear_32bpp_cs[] =
{
68, 88, 66, 67, 212, 33,
57, 169, 71, 99, 28, 75,
202, 138, 254, 170, 245, 39,
113, 44, 1, 0, 0, 0,
68, 88, 66, 67, 226, 247,
125, 160, 57, 195, 118, 226,
52, 138, 250, 148, 103, 90,
91, 213, 1, 0, 0, 0,
120, 7, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
64, 2, 0, 0, 80, 2,
@ -93,7 +93,7 @@ const BYTE resolve_clear_32bpp_cs[] =
1, 0, 0, 0, 176, 0,
0, 0, 2, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
220, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -100,10 +100,10 @@ ret
const BYTE resolve_clear_32bpp_scaled_cs[] =
{
68, 88, 66, 67, 151, 173,
156, 244, 183, 241, 226, 31,
214, 214, 54, 114, 10, 217,
153, 194, 1, 0, 0, 0,
68, 88, 66, 67, 205, 174,
123, 5, 98, 198, 38, 143,
98, 109, 190, 150, 214, 170,
216, 92, 1, 0, 0, 0,
104, 9, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
228, 2, 0, 0, 244, 2,
@ -113,7 +113,7 @@ const BYTE resolve_clear_32bpp_scaled_cs[] =
2, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
128, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -79,10 +79,10 @@ ret
const BYTE resolve_clear_64bpp_cs[] =
{
68, 88, 66, 67, 11, 134,
106, 112, 85, 206, 144, 113,
121, 69, 237, 199, 49, 129,
4, 62, 1, 0, 0, 0,
68, 88, 66, 67, 16, 5,
27, 66, 247, 175, 170, 221,
90, 253, 80, 46, 104, 119,
87, 139, 1, 0, 0, 0,
148, 7, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
64, 2, 0, 0, 80, 2,
@ -92,7 +92,7 @@ const BYTE resolve_clear_64bpp_cs[] =
1, 0, 0, 0, 176, 0,
0, 0, 2, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
220, 1, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -98,10 +98,10 @@ ret
const BYTE resolve_clear_64bpp_scaled_cs[] =
{
68, 88, 66, 67, 226, 249,
231, 177, 11, 141, 42, 153,
99, 45, 131, 104, 152, 194,
26, 176, 1, 0, 0, 0,
68, 88, 66, 67, 246, 14,
132, 223, 204, 44, 6, 28,
86, 181, 216, 251, 242, 62,
34, 31, 1, 0, 0, 0,
112, 9, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
228, 2, 0, 0, 244, 2,
@ -111,7 +111,7 @@ const BYTE resolve_clear_64bpp_scaled_cs[] =
2, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
128, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -214,10 +214,10 @@ ret
const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] =
{
68, 88, 66, 67, 155, 144,
108, 102, 32, 219, 74, 112,
191, 128, 193, 179, 111, 166,
110, 225, 1, 0, 0, 0,
68, 88, 66, 67, 239, 168,
103, 4, 189, 160, 141, 83,
16, 65, 33, 184, 201, 9,
185, 83, 1, 0, 0, 0,
156, 24, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -227,7 +227,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -278,10 +278,10 @@ ret
const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] =
{
68, 88, 66, 67, 145, 228,
65, 128, 86, 250, 142, 70,
190, 88, 12, 69, 154, 111,
98, 110, 1, 0, 0, 0,
68, 88, 66, 67, 33, 171,
235, 222, 88, 49, 17, 196,
69, 254, 64, 92, 43, 122,
25, 15, 1, 0, 0, 0,
40, 31, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -291,7 +291,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -225,10 +225,10 @@ ret
const BYTE resolve_fast_32bpp_4xmsaa_cs[] =
{
68, 88, 66, 67, 83, 123,
16, 172, 13, 23, 165, 181,
111, 176, 230, 199, 227, 113,
202, 160, 1, 0, 0, 0,
68, 88, 66, 67, 170, 85,
205, 145, 228, 207, 40, 6,
92, 178, 101, 253, 108, 144,
148, 218, 1, 0, 0, 0,
196, 25, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -238,7 +238,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -290,10 +290,10 @@ ret
const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] =
{
68, 88, 66, 67, 31, 111,
219, 218, 202, 212, 228, 164,
35, 4, 215, 208, 98, 172,
195, 246, 1, 0, 0, 0,
68, 88, 66, 67, 228, 200,
92, 46, 175, 37, 210, 169,
116, 188, 100, 167, 120, 186,
226, 184, 1, 0, 0, 0,
100, 32, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -303,7 +303,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -203,10 +203,10 @@ ret
const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] =
{
68, 88, 66, 67, 148, 119,
138, 27, 157, 3, 164, 49,
44, 31, 102, 96, 70, 236,
100, 146, 1, 0, 0, 0,
68, 88, 66, 67, 6, 88,
245, 144, 16, 3, 175, 59,
111, 160, 2, 183, 105, 216,
39, 35, 1, 0, 0, 0,
16, 23, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -216,7 +216,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -265,10 +265,10 @@ ret
const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] =
{
68, 88, 66, 67, 146, 74,
159, 181, 129, 209, 232, 153,
8, 178, 69, 215, 5, 127,
187, 119, 1, 0, 0, 0,
68, 88, 66, 67, 217, 58,
225, 5, 83, 76, 76, 76,
41, 4, 184, 58, 64, 138,
164, 215, 1, 0, 0, 0,
24, 29, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -278,7 +278,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -204,10 +204,10 @@ ret
const BYTE resolve_fast_64bpp_4xmsaa_cs[] =
{
68, 88, 66, 67, 103, 127,
24, 191, 130, 242, 189, 20,
38, 18, 213, 75, 35, 175,
132, 194, 1, 0, 0, 0,
68, 88, 66, 67, 219, 212,
228, 165, 45, 17, 135, 148,
112, 245, 209, 7, 35, 133,
189, 71, 1, 0, 0, 0,
40, 23, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -217,7 +217,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -263,10 +263,10 @@ ret
const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] =
{
68, 88, 66, 67, 175, 243,
135, 222, 141, 148, 29, 126,
11, 2, 155, 131, 194, 117,
96, 179, 1, 0, 0, 0,
68, 88, 66, 67, 128, 163,
164, 187, 116, 154, 133, 40,
143, 38, 115, 1, 152, 118,
125, 200, 1, 0, 0, 0,
36, 29, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -276,7 +276,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -797,10 +797,10 @@ ret
const BYTE resolve_full_128bpp_cs[] =
{
68, 88, 66, 67, 138, 187,
29, 190, 119, 248, 103, 130,
145, 38, 138, 150, 199, 99,
88, 186, 1, 0, 0, 0,
68, 88, 66, 67, 21, 9,
61, 18, 132, 97, 176, 57,
19, 100, 60, 248, 43, 42,
194, 237, 1, 0, 0, 0,
156, 86, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -810,7 +810,7 @@ const BYTE resolve_full_128bpp_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -858,10 +858,10 @@ ret
const BYTE resolve_full_128bpp_scaled_cs[] =
{
68, 88, 66, 67, 252, 54,
64, 236, 181, 3, 56, 102,
51, 248, 62, 205, 28, 164,
215, 11, 1, 0, 0, 0,
68, 88, 66, 67, 0, 197,
108, 112, 31, 221, 155, 150,
192, 148, 203, 210, 205, 214,
112, 66, 1, 0, 0, 0,
220, 91, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -871,7 +871,7 @@ const BYTE resolve_full_128bpp_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1350,10 +1350,10 @@ ret
const BYTE resolve_full_16bpp_cs[] =
{
68, 88, 66, 67, 85, 89,
112, 166, 132, 95, 159, 158,
148, 255, 182, 126, 49, 65,
238, 68, 1, 0, 0, 0,
68, 88, 66, 67, 122, 248,
161, 239, 38, 34, 59, 122,
64, 201, 159, 30, 45, 236,
145, 6, 1, 0, 0, 0,
112, 158, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -1363,7 +1363,7 @@ const BYTE resolve_full_16bpp_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1382,10 +1382,10 @@ ret
const BYTE resolve_full_16bpp_scaled_cs[] =
{
68, 88, 66, 67, 24, 35,
27, 103, 137, 85, 99, 31,
248, 119, 100, 82, 1, 5,
211, 65, 1, 0, 0, 0,
68, 88, 66, 67, 17, 196,
248, 162, 148, 187, 123, 170,
150, 149, 87, 23, 157, 34,
89, 51, 1, 0, 0, 0,
188, 160, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -1395,7 +1395,7 @@ const BYTE resolve_full_16bpp_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1354,10 +1354,10 @@ ret
const BYTE resolve_full_32bpp_cs[] =
{
68, 88, 66, 67, 191, 202,
187, 105, 122, 172, 254, 124,
230, 42, 42, 152, 112, 61,
118, 194, 1, 0, 0, 0,
68, 88, 66, 67, 6, 223,
221, 81, 201, 228, 242, 38,
30, 228, 108, 198, 29, 216,
108, 219, 1, 0, 0, 0,
220, 157, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -1367,7 +1367,7 @@ const BYTE resolve_full_32bpp_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1397,10 +1397,10 @@ ret
const BYTE resolve_full_32bpp_scaled_cs[] =
{
68, 88, 66, 67, 159, 80,
95, 78, 198, 213, 86, 238,
93, 9, 250, 90, 57, 206,
56, 203, 1, 0, 0, 0,
68, 88, 66, 67, 19, 170,
1, 90, 249, 15, 80, 164,
255, 208, 31, 117, 114, 147,
62, 94, 1, 0, 0, 0,
4, 162, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -1410,7 +1410,7 @@ const BYTE resolve_full_32bpp_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1275,10 +1275,10 @@ ret
const BYTE resolve_full_64bpp_cs[] =
{
68, 88, 66, 67, 123, 61,
63, 178, 155, 115, 88, 68,
202, 19, 87, 198, 58, 252,
174, 110, 1, 0, 0, 0,
68, 88, 66, 67, 87, 220,
183, 187, 206, 232, 244, 147,
255, 195, 21, 134, 69, 222,
224, 255, 1, 0, 0, 0,
232, 147, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -1288,7 +1288,7 @@ const BYTE resolve_full_64bpp_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1338,10 +1338,10 @@ ret
const BYTE resolve_full_64bpp_scaled_cs[] =
{
68, 88, 66, 67, 192, 10,
30, 169, 238, 27, 64, 245,
27, 79, 191, 206, 88, 74,
18, 223, 1, 0, 0, 0,
68, 88, 66, 67, 60, 118,
161, 100, 5, 152, 135, 130,
31, 41, 169, 237, 170, 21,
198, 182, 1, 0, 0, 0,
216, 153, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -1351,7 +1351,7 @@ const BYTE resolve_full_64bpp_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -678,10 +678,10 @@ ret
const BYTE resolve_full_8bpp_cs[] =
{
68, 88, 66, 67, 253, 28,
166, 242, 173, 99, 18, 102,
240, 221, 130, 124, 127, 224,
31, 30, 1, 0, 0, 0,
68, 88, 66, 67, 160, 163,
233, 191, 143, 128, 203, 231,
48, 167, 197, 167, 225, 27,
77, 108, 1, 0, 0, 0,
196, 76, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
208, 2, 0, 0, 224, 2,
@ -691,7 +691,7 @@ const BYTE resolve_full_8bpp_cs[] =
1, 0, 0, 0, 236, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
108, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -720,10 +720,10 @@ ret
const BYTE resolve_full_8bpp_scaled_cs[] =
{
68, 88, 66, 67, 162, 175,
232, 246, 251, 37, 158, 3,
20, 94, 73, 161, 62, 53,
31, 163, 1, 0, 0, 0,
68, 88, 66, 67, 143, 238,
173, 2, 246, 240, 28, 191,
52, 72, 53, 243, 190, 87,
239, 146, 1, 0, 0, 0,
200, 80, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
56, 3, 0, 0, 72, 3,
@ -733,7 +733,7 @@ const BYTE resolve_full_8bpp_scaled_cs[] =
2, 0, 0, 0, 52, 1,
0, 0, 4, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
212, 2, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -1,167 +0,0 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_sampler_linear_clamp sampler NA NA S0 s0 1
// xe_texture texture float3 2d T0 t0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// TEXCOORD 0 xy 0 NONE float xy
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Target 0 xyzw 0 TARGET float xyzw
//
ps_5_1
dcl_globalFlags refactoringAllowed
dcl_sampler S0[0:0], mode_default, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0
dcl_input_ps linear v0.xy
dcl_output o0.xyzw
dcl_temps 1
sample_l r0.xyz, v0.xyxx, T0[0].xyzw, S0[0], l(0.000000)
mov o0.xyz, r0.xyzx
mov o0.w, l(1.000000)
ret
// Approximately 4 instruction slots used
#endif
const BYTE stretch_ps[] =
{
68, 88, 66, 67, 42, 105,
40, 75, 32, 223, 178, 162,
221, 190, 237, 193, 82, 219,
83, 57, 1, 0, 0, 0,
224, 2, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
20, 1, 0, 0, 72, 1,
0, 0, 124, 1, 0, 0,
68, 2, 0, 0, 82, 68,
69, 70, 216, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0,
60, 0, 0, 0, 1, 5,
255, 255, 0, 5, 4, 0,
175, 0, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,
0, 0, 40, 0, 0, 0,
36, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0,
140, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 164, 0,
0, 0, 2, 0, 0, 0,
5, 0, 0, 0, 4, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 1, 0,
0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 120, 101, 95, 115,
97, 109, 112, 108, 101, 114,
95, 108, 105, 110, 101, 97,
114, 95, 99, 108, 97, 109,
112, 0, 120, 101, 95, 116,
101, 120, 116, 117, 114, 101,
0, 77, 105, 99, 114, 111,
115, 111, 102, 116, 32, 40,
82, 41, 32, 72, 76, 83,
76, 32, 83, 104, 97, 100,
101, 114, 32, 67, 111, 109,
112, 105, 108, 101, 114, 32,
49, 48, 46, 49, 0, 171,
73, 83, 71, 78, 44, 0,
0, 0, 1, 0, 0, 0,
8, 0, 0, 0, 32, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
3, 3, 0, 0, 84, 69,
88, 67, 79, 79, 82, 68,
0, 171, 171, 171, 79, 83,
71, 78, 44, 0, 0, 0,
1, 0, 0, 0, 8, 0,
0, 0, 32, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 15, 0,
0, 0, 83, 86, 95, 84,
97, 114, 103, 101, 116, 0,
171, 171, 83, 72, 69, 88,
192, 0, 0, 0, 81, 0,
0, 0, 48, 0, 0, 0,
106, 8, 0, 1, 90, 0,
0, 6, 70, 110, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 88, 24,
0, 7, 70, 126, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
85, 85, 0, 0, 0, 0,
0, 0, 98, 16, 0, 3,
50, 16, 16, 0, 0, 0,
0, 0, 101, 0, 0, 3,
242, 32, 16, 0, 0, 0,
0, 0, 104, 0, 0, 2,
1, 0, 0, 0, 72, 0,
0, 13, 114, 0, 16, 0,
0, 0, 0, 0, 70, 16,
16, 0, 0, 0, 0, 0,
70, 126, 32, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 96, 32, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 64, 0, 0, 0, 0,
0, 0, 54, 0, 0, 5,
114, 32, 16, 0, 0, 0,
0, 0, 70, 2, 16, 0,
0, 0, 0, 0, 54, 0,
0, 5, 130, 32, 16, 0,
0, 0, 0, 0, 1, 64,
0, 0, 0, 0, 128, 63,
62, 0, 0, 1, 83, 84,
65, 84, 148, 0, 0, 0,
4, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};

View File

@ -94,10 +94,10 @@ ret
const BYTE tessellation_adaptive_vs[] =
{
68, 88, 66, 67, 223, 69,
21, 252, 96, 81, 180, 155,
11, 146, 181, 238, 118, 211,
188, 154, 1, 0, 0, 0,
68, 88, 66, 67, 75, 49,
78, 76, 10, 94, 91, 100,
187, 17, 145, 80, 196, 255,
224, 35, 1, 0, 0, 0,
196, 13, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
184, 10, 0, 0, 236, 10,
@ -107,7 +107,7 @@ const BYTE tessellation_adaptive_vs[] =
1, 0, 0, 0, 120, 0,
0, 0, 1, 0, 0, 0,
60, 0, 0, 0, 1, 5,
254, 255, 0, 5, 4, 0,
254, 255, 0, 5, 0, 0,
82, 10, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -96,10 +96,10 @@ ret
const BYTE tessellation_indexed_vs[] =
{
68, 88, 66, 67, 6, 210,
5, 58, 145, 186, 106, 71,
191, 85, 65, 89, 187, 76,
25, 50, 1, 0, 0, 0,
68, 88, 66, 67, 126, 143,
61, 16, 42, 166, 147, 123,
54, 196, 251, 250, 225, 235,
160, 249, 1, 0, 0, 0,
248, 13, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
184, 10, 0, 0, 236, 10,
@ -109,7 +109,7 @@ const BYTE tessellation_indexed_vs[] =
1, 0, 0, 0, 120, 0,
0, 0, 1, 0, 0, 0,
60, 0, 0, 0, 1, 5,
254, 255, 0, 5, 4, 0,
254, 255, 0, 5, 0, 0,
82, 10, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -164,10 +164,10 @@ ret
const BYTE texture_load_128bpb_cs[] =
{
68, 88, 66, 67, 69, 109,
54, 62, 246, 252, 13, 179,
61, 140, 108, 218, 151, 23,
217, 10, 1, 0, 0, 0,
68, 88, 66, 67, 202, 63,
252, 201, 70, 118, 107, 252,
56, 217, 121, 32, 214, 118,
48, 42, 1, 0, 0, 0,
92, 19, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -177,7 +177,7 @@ const BYTE texture_load_128bpb_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -175,10 +175,10 @@ ret
const BYTE texture_load_128bpb_scaled_cs[] =
{
68, 88, 66, 67, 152, 21,
0, 244, 101, 90, 251, 167,
33, 145, 108, 252, 235, 186,
133, 5, 1, 0, 0, 0,
68, 88, 66, 67, 0, 151,
15, 173, 246, 165, 135, 120,
79, 233, 110, 0, 24, 192,
65, 142, 1, 0, 0, 0,
160, 20, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -188,7 +188,7 @@ const BYTE texture_load_128bpb_scaled_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -150,10 +150,10 @@ ret
const BYTE texture_load_16bpb_cs[] =
{
68, 88, 66, 67, 174, 93,
70, 99, 109, 104, 7, 76,
197, 223, 164, 98, 22, 191,
35, 145, 1, 0, 0, 0,
68, 88, 66, 67, 241, 108,
80, 210, 39, 187, 91, 178,
204, 21, 81, 58, 61, 11,
55, 221, 1, 0, 0, 0,
28, 17, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -163,7 +163,7 @@ const BYTE texture_load_16bpb_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -163,10 +163,10 @@ ret
const BYTE texture_load_16bpb_scaled_cs[] =
{
68, 88, 66, 67, 81, 210,
211, 210, 188, 152, 146, 59,
242, 122, 231, 17, 215, 172,
246, 100, 1, 0, 0, 0,
68, 88, 66, 67, 194, 117,
247, 194, 178, 87, 120, 28,
79, 25, 94, 189, 238, 128,
139, 128, 1, 0, 0, 0,
0, 19, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -176,7 +176,7 @@ const BYTE texture_load_16bpb_scaled_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -161,10 +161,10 @@ ret
const BYTE texture_load_32bpb_cs[] =
{
68, 88, 66, 67, 127, 41,
115, 152, 37, 92, 49, 26,
80, 31, 185, 102, 249, 41,
197, 36, 1, 0, 0, 0,
68, 88, 66, 67, 147, 100,
112, 89, 242, 160, 225, 236,
154, 215, 131, 75, 212, 235,
15, 182, 1, 0, 0, 0,
204, 18, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -174,7 +174,7 @@ const BYTE texture_load_32bpb_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

View File

@ -180,10 +180,10 @@ ret
const BYTE texture_load_32bpb_scaled_cs[] =
{
68, 88, 66, 67, 213, 122,
184, 211, 188, 144, 40, 184,
157, 227, 165, 48, 220, 115,
140, 200, 1, 0, 0, 0,
68, 88, 66, 67, 218, 190,
24, 130, 153, 203, 104, 119,
33, 181, 7, 206, 254, 211,
212, 77, 1, 0, 0, 0,
108, 21, 0, 0, 5, 0,
0, 0, 52, 0, 0, 0,
28, 4, 0, 0, 44, 4,
@ -193,7 +193,7 @@ const BYTE texture_load_32bpb_scaled_cs[] =
1, 0, 0, 0, 248, 0,
0, 0, 3, 0, 0, 0,
60, 0, 0, 0, 1, 5,
83, 67, 0, 5, 4, 0,
83, 67, 0, 5, 0, 0,
181, 3, 0, 0, 19, 19,
68, 37, 60, 0, 0, 0,
24, 0, 0, 0, 40, 0,

Some files were not shown because too many files have changed in this diff Show More