diff --git a/.gdbinit b/.gdbinit index ae63996..09702a9 100644 --- a/.gdbinit +++ b/.gdbinit @@ -10,13 +10,6 @@ # Tell GDB that we are using 32-bit x86 architecture set arch i386 -# Tell GDB to load symbols from main.exe -# -# Notice here that we are using the .exe file, not the .xbe file, as -# GDB does not understand the .xbe format. -# -add-symbol-file main.exe - # Use a layout which shows source code # CLion: Not supported #layout src diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9835b10..66baa51 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,42 +15,6 @@ on: - 'README.md' jobs: - BuildISOWithCrashAvoidance: - name: Build ISO with experimental crash avoidance - runs-on: ubuntu-latest - steps: - - name: Clone tree - uses: actions/checkout@v2 - with: - submodules: recursive - path: nxdk_pgraph_tests - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - llvm \ - lld \ - libsdl2-dev \ - libsdl2-image-dev - pip3 install nv2a-vsh - - name: Compile - run: | - cd nxdk_pgraph_tests - make -j $(grep -c processor /proc/cpuinfo) \ - ENABLE_PROGRESS_LOG=y \ - ENABLE_INTERACTIVE_CRASH_AVOIDANCE=y \ - RUNTIME_CONFIG_PATH="e:/nxdk_pgraph_tests/pgraph_tests.cnf" \ - DUMP_CONFIG_FILE=y - - name: Create release - if: github.ref == 'refs/heads/main' - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "latest-experimental_crash_tracking" - prerelease: false - title: "xiso containing pgraph tests with experimental crash tracking" - files: | - nxdk_pgraph_tests/nxdk_pgraph_tests.iso BuildISO: name: Build ISO runs-on: ubuntu-latest @@ -64,18 +28,27 @@ jobs: run: | sudo apt-get update sudo apt-get install -y \ + cmake \ llvm \ lld \ libsdl2-dev \ - libsdl2-image-dev + libsdl2-image-dev \ + ninja-build pip3 install nv2a-vsh + - name: Prewarm nxdk + working-directory: nxdk_pgraph_tests + run: bash ${GITHUB_WORKSPACE}/nxdk_pgraph_tests/prewarm-nxdk.sh - name: Compile run: | cd nxdk_pgraph_tests - make -j $(grep -c processor /proc/cpuinfo) \ - ENABLE_PROGRESS_LOG=y \ - RUNTIME_CONFIG_PATH="e:/nxdk_pgraph_tests/pgraph_tests.cnf" \ - DUMP_CONFIG_FILE=y + export NXDK_DIR="${GITHUB_WORKSPACE}/nxdk_pgraph_tests/third_party/nxdk" + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE="${NXDK_DIR}/share/toolchain-nxdk.cmake" \ + -DENABLE_PROGRESS_LOG=ON \ + -DDUMP_CONFIG_FILE=ON \ + -DRUNTIME_CONFIG_PATH="e:/nxdk_pgraph_tests/pgraph_tests.cnf" + cmake --build build -- -j$(grep -c processor /proc/cpuinfo) - name: Create release if: github.ref == 'refs/heads/main' uses: "marvinpinto/action-automatic-releases@latest" @@ -85,4 +58,4 @@ jobs: prerelease: false title: "xiso containing pgraph tests" files: | - nxdk_pgraph_tests/nxdk_pgraph_tests.iso + build/xiso/nxdk_pgraph_tests_xiso/nxdk_pgraph_tests_xiso.iso diff --git a/.gitignore b/.gitignore index db90d73..6dc00cb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ .vscode/ .idea/ bin/ +cmake-build*/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..eca8800 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,352 @@ +cmake_minimum_required(VERSION 3.18) +project(nxdk_pgraph_tests) + +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/" + ) + +set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + +set(CMAKE_CXX_STANDARD 17) +include(CMakePushCheckState) +set(_CMAKE_PROCESSING_LANGUAGE "CXX") +include(CheckSymbolExists) +include(ExternalProject) +include(FindPkgConfig) + +include(NV2A_VSH REQUIRED) +include(NV20_CG REQUIRED) +include(XBEUtils REQUIRED) + +find_package(NXDK REQUIRED) +find_package(NXDK_SDL2 REQUIRED) +find_package(NXDK_SDL2_Image REQUIRED) +find_package(Threads REQUIRED) + +add_subdirectory(third_party) + +set(TARGET nxdk_pgraph_tests) + +option( + NO_OPT + "Suppress optimization on core files that are typically optimized regardless of release/debug configuration" + OFF +) + +option( + ENABLE_PROGRESS_LOG + "Write the name of each test to a log file on the target." + OFF +) + +option( + ENABLE_INTERACTIVE_CRASH_AVOIDANCE + "Attempt to detect crashes and prevent crashing tests from running after the next restart." + OFF +) + +option( + DUMP_CONFIG_FILE + "Write a test configuration file template that may be edited to filter the tests that are executed." + OFF +) + +option( + DISABLE_AUTORUN + "Prevents the tests from being executed without user input." + OFF +) + +option( + AUTORUN_IMMEDIATELY + "Remove the delay for input before starting automated testing." + OFF +) + +option( + ENABLE_SHUTDOWN + "Cause the program to shut down the xbox on completion instead of rebooting." + OFF +) + +option( + ENABLE_MULTIFRAME_CPU_BLIT_TEST + "Enables the MultiframeCPUBlit test within the Antialiasing tests. This test requires evaluation across multiple frames and thus cannot produce a usable golden artifact for automated validation. This should only be enabled for manual testing purposes." + OFF +) + +option( + ENABLE_PGRAPH_REGION_DIFF + "Causes a diff of the nv2a PGRAPH registers to be done between the start and end of each test in order to detect state leakage. Output is logged to XBDM and will be written into the progress log if it is enabled." + OFF +) + +set( + RUNTIME_CONFIG_PATH + "" + CACHE STRING + "XBOX-path to the location of a configuration file to filter the tests that are executed." +) + +set( + FALLBACK_OUTPUT_ROOT_PATH + "e:/" + CACHE STRING + "Path at which test artifacts will be written when executed from read-only media." +) + +configure_file(src/configure.h.in src/configure.h) + +macro(set_compile_options target) + if (CMAKE_BUILD_TYPE MATCHES Debug) + target_compile_options( + "${target}" + PRIVATE + -g + -gdwarf-4 + -O0 + -Wall + -fstandalone-debug + ) + target_link_options("${target}" PRIVATE "/debug:full") + else () + target_compile_options( + "${target}" + PRIVATE + -O3 + -fno-strict-aliasing + -Wall + ) + target_link_options("${target}" PRIVATE "/debug:none") + endif () +endmacro() + +# Vertex shaders. +generate_nv2a_vshinc_files( + generated_vertex_shaders + SOURCES + src/shaders/fog_infinite_fogc_test.vsh + src/shaders/fog_vec4_w.vsh + src/shaders/fog_vec4_w_x.vsh + src/shaders/fog_vec4_w_y.vsh + src/shaders/fog_vec4_w_z_y_x.vsh + src/shaders/fog_vec4_x.vsh + src/shaders/fog_vec4_xw.vsh + src/shaders/fog_vec4_xy.vsh + src/shaders/fog_vec4_xyz.vsh + src/shaders/fog_vec4_x_y_z_w.vsh + src/shaders/fog_vec4_xyzw.vsh + src/shaders/fog_vec4_xz.vsh + src/shaders/fog_vec4_xzw.vsh + src/shaders/fog_vec4_y.vsh + src/shaders/fog_vec4_yw.vsh + src/shaders/fog_vec4_yz.vsh + src/shaders/fog_vec4_yzw.vsh + src/shaders/fog_vec4_z.vsh + src/shaders/fog_vec4_zw.vsh + src/shaders/fog_vec4_unset.vsh +) + +generate_pixelshader_inl_files( + generated_fp20_pixel_shaders + SOURCES + src/shaders/textured_pixelshader.ps.cg + src/shaders/untextured_pixelshader.ps.cg +) + +generate_vertexshader_inl_files( + generated_vp20_vertex_shaders + SOURCES + src/shaders/attribute_carryover_test.vs.cg + src/shaders/attribute_explicit_setter_tests.vs.cg + src/shaders/mul_col0_by_const0_vertex_shader.vs.cg + src/shaders/precalculated_vertex_shader_2c_texcoords.vs.cg + src/shaders/precalculated_vertex_shader_4c_texcoords.vs.cg + src/shaders/projection_vertex_shader.vs.cg + src/shaders/projection_vertex_shader_no_lighting.vs.cg + src/shaders/projection_vertex_shader_no_lighting_4c_texcoords.vs.cg +) + +# Sources that should be optimized regardless of standard debug settings. +add_library( + optimized_sources + EXCLUDE_FROM_ALL + src/dds_image.cpp + src/dds_image.h + src/debug_output.cpp + src/debug_output.h + src/main.cpp + src/math3d.c + src/math3d.h + src/menu_item.cpp + src/menu_item.h + src/logger.cpp + src/logger.h + src/pbkit_ext.cpp + src/pbkit_ext.h + src/pgraph_diff_token.cpp + src/pgraph_diff_token.h + src/shaders/orthographic_vertex_shader.cpp + src/shaders/orthographic_vertex_shader.h + src/shaders/perspective_vertex_shader.cpp + src/shaders/perspective_vertex_shader.h + src/shaders/pixel_shader_program.cpp + src/shaders/pixel_shader_program.h + src/shaders/precalculated_vertex_shader.cpp + src/shaders/precalculated_vertex_shader.h + src/shaders/projection_vertex_shader.cpp + src/shaders/projection_vertex_shader.h + src/shaders/vertex_shader_program.cpp + src/shaders/vertex_shader_program.h + src/test_driver.cpp + src/test_driver.h + src/test_host.cpp + src/test_host.h + src/texture_format.cpp + src/texture_format.h + src/texture_generator.cpp + src/texture_generator.h + src/texture_stage.cpp + src/texture_stage.h + src/vertex_buffer.cpp + src/vertex_buffer.h +) + + +if (NOT NO_OPT) + target_compile_options( + optimized_sources + PRIVATE + -O3 + -fno-strict-aliasing + -Wall + ) + target_link_options(optimized_sources PRIVATE "/debug:none") +else () + set_compile_options(optimized_sources) +endif () + +target_include_directories( + optimized_sources + PRIVATE + src + third_party + "${CMAKE_CURRENT_BINARY_DIR}/src" +) + +target_link_libraries( + optimized_sources + PUBLIC + generated_fp20_pixel_shaders + generated_vp20_vertex_shaders + PRIVATE + fpng + printf + swizzle + NXDK::NXDK + NXDK::NXDK_CXX + NXDK::SDL2 + NXDK::SDL2_Image +) + +add_executable( + "${TARGET}" + src/tests/antialiasing_tests.cpp + src/tests/attribute_carryover_tests.cpp + src/tests/attribute_explicit_setter_tests.cpp + src/tests/attribute_float_tests.cpp + src/tests/blend_tests.cpp + src/tests/clear_tests.cpp + src/tests/color_mask_blend_tests.cpp + src/tests/color_zeta_disable_tests.cpp + src/tests/color_zeta_overlap_tests.cpp + src/tests/combiner_tests.cpp + src/tests/depth_format_fixed_function_tests.cpp + src/tests/depth_format_tests.cpp + src/tests/dma_corruption_around_surface_tests.cpp + src/tests/fog_tests.cpp + src/tests/front_face_tests.cpp + src/tests/image_blit_tests.cpp + src/tests/inline_array_size_mismatch.cpp + src/tests/lighting_normal_tests.cpp + src/tests/material_alpha_tests.cpp + src/tests/material_color_source_tests.cpp + src/tests/material_color_tests.cpp + src/tests/null_surface_tests.cpp + src/tests/overlapping_draw_modes_tests.cpp + src/tests/pvideo_tests.cpp + src/tests/set_vertex_data_tests.cpp + src/tests/shade_model_tests.cpp + src/tests/smoothing_tests.cpp + src/tests/stencil_tests.cpp + src/tests/surface_clip_tests.cpp + src/tests/surface_pitch_tests.cpp + src/tests/test_suite.cpp + src/tests/texgen_matrix_tests.cpp + src/tests/texgen_tests.cpp + src/tests/texture_border_tests.cpp + src/tests/texture_cpu_update_tests.cpp + src/tests/texture_cubemap_tests.cpp + src/tests/texture_format_dxt_tests.cpp + src/tests/texture_format_tests.cpp + src/tests/texture_framebuffer_blit_tests.cpp + src/tests/texture_matrix_tests.cpp + src/tests/texture_render_target_tests.cpp + src/tests/texture_render_update_in_place_tests.cpp + src/tests/texture_shadow_comparator_tests.cpp + src/tests/texture_signed_component_tests.cpp + src/tests/three_d_primitive_tests.cpp + src/tests/two_d_line_tests.cpp + src/tests/vertex_shader_independence_tests.cpp + src/tests/vertex_shader_rounding_tests.cpp + src/tests/vertex_shader_swizzle_tests.cpp + src/tests/viewport_tests.cpp + src/tests/volume_texture_tests.cpp + src/tests/w_param_tests.cpp + src/tests/window_clip_tests.cpp + src/tests/zero_stride_tests.cpp + ${generated_vertex_shaders} + ${generated_fp20_pixel_shaders_SOURCES} + ${generated_vp20_vertex_shaders_SOURCES} +) +set(EXECUTABLE_BINARY "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.exe") +target_include_directories( + "${TARGET}" + PRIVATE + src + third_party + "${CMAKE_CURRENT_BINARY_DIR}/src" +) + +set_compile_options("${TARGET}") + +target_link_libraries( + "${TARGET}" + fpng + optimized_sources + printf + swizzle + NXDK::NXDK + NXDK::NXDK_CXX + NXDK::SDL2 + NXDK::SDL2_Image +) + +add_xbe(xbe_file "${EXECUTABLE_BINARY}" TITLE "PGRAPH Tests" RESOURCE_DIRS resources) +add_xiso(nxdk_pgraph_tests_xiso xbe_file) + +#set(XBDM_GDB_BRIDGE $ENV{XBDM_GDB_BRIDGE}) +#set(XBOX $ENV{XBOX}) +#if (DEFINED ENV{REMOTE_PATH}) +# set(REMOTE_PATH $ENV{REMOTE_PATH}) +#else () +# set(REMOTE_PATH "e:\\\\cmake_pgraph") +#endif () +# +#add_custom_target( +# deploy_with_xbdm +# COMMAND "${XBDM_GDB_BRIDGE}" "${XBOX}" -- mkdir "${REMOTE_PATH}" +# COMMAND "${XBDM_GDB_BRIDGE}" "${XBOX}" -- putfile "${XBE_STAGING_DIR}" "${REMOTE_PATH}" -f +# DEPENDS "${XBE_OUTPUT_PATH}" +#) diff --git a/Makefile b/Makefile deleted file mode 100644 index 923201f..0000000 --- a/Makefile +++ /dev/null @@ -1,294 +0,0 @@ -XBE_TITLE = nxdk_pgraph_tests -GEN_XISO = $(XBE_TITLE).iso -NXDK_DIR ?= $(CURDIR)/third_party/nxdk -NXDK_SDL = y -NXDK_CXX = y - -# pip3 install nv2a-vsh -# https://pypi.org/project/nv2a-vsh/ -# https://github.com/abaire/nv2a_vsh_asm -NV2AVSH = nv2avsh - -RESOURCEDIR = $(CURDIR)/resources -SRCDIR = $(CURDIR)/src -THIRDPARTYDIR = $(CURDIR)/third_party - -OPTIMIZED_SRCS = \ - $(SRCDIR)/dds_image.cpp \ - $(SRCDIR)/debug_output.cpp \ - $(SRCDIR)/main.cpp \ - $(SRCDIR)/math3d.c \ - $(SRCDIR)/menu_item.cpp \ - $(SRCDIR)/logger.cpp \ - $(SRCDIR)/pbkit_ext.cpp \ - $(SRCDIR)/pgraph_diff_token.cpp \ - $(SRCDIR)/shaders/orthographic_vertex_shader.cpp \ - $(SRCDIR)/shaders/perspective_vertex_shader.cpp \ - $(SRCDIR)/shaders/pixel_shader_program.cpp \ - $(SRCDIR)/shaders/precalculated_vertex_shader.cpp \ - $(SRCDIR)/shaders/projection_vertex_shader.cpp \ - $(SRCDIR)/shaders/vertex_shader_program.cpp \ - $(SRCDIR)/test_driver.cpp \ - $(SRCDIR)/test_host.cpp \ - $(SRCDIR)/texture_format.cpp \ - $(SRCDIR)/texture_generator.cpp \ - $(SRCDIR)/texture_stage.cpp \ - $(SRCDIR)/vertex_buffer.cpp \ - $(THIRDPARTYDIR)/swizzle.c \ - $(THIRDPARTYDIR)/printf/printf.c \ - $(THIRDPARTYDIR)/fpng/src/fpng.cpp - -SRCS = \ - $(SRCDIR)/tests/antialiasing_tests.cpp \ - $(SRCDIR)/tests/attribute_carryover_tests.cpp \ - $(SRCDIR)/tests/attribute_explicit_setter_tests.cpp \ - $(SRCDIR)/tests/attribute_float_tests.cpp \ - $(SRCDIR)/tests/blend_tests.cpp \ - $(SRCDIR)/tests/clear_tests.cpp \ - $(SRCDIR)/tests/color_mask_blend_tests.cpp \ - $(SRCDIR)/tests/color_zeta_disable_tests.cpp \ - $(SRCDIR)/tests/color_zeta_overlap_tests.cpp \ - $(SRCDIR)/tests/combiner_tests.cpp \ - $(SRCDIR)/tests/depth_format_fixed_function_tests.cpp \ - $(SRCDIR)/tests/depth_format_tests.cpp \ - $(SRCDIR)/tests/dma_corruption_around_surface_tests.cpp \ - $(SRCDIR)/tests/fog_tests.cpp \ - $(SRCDIR)/tests/front_face_tests.cpp \ - $(SRCDIR)/tests/image_blit_tests.cpp \ - $(SRCDIR)/tests/inline_array_size_mismatch.cpp \ - $(SRCDIR)/tests/lighting_normal_tests.cpp \ - $(SRCDIR)/tests/material_alpha_tests.cpp \ - $(SRCDIR)/tests/material_color_tests.cpp \ - $(SRCDIR)/tests/material_color_source_tests.cpp \ - $(SRCDIR)/tests/null_surface_tests.cpp \ - $(SRCDIR)/tests/overlapping_draw_modes_tests.cpp \ - $(SRCDIR)/tests/pvideo_tests.cpp \ - $(SRCDIR)/tests/set_vertex_data_tests.cpp \ - $(SRCDIR)/tests/shade_model_tests.cpp \ - $(SRCDIR)/tests/smoothing_tests.cpp \ - $(SRCDIR)/tests/stencil_tests.cpp \ - $(SRCDIR)/tests/surface_clip_tests.cpp \ - $(SRCDIR)/tests/surface_pitch_tests.cpp \ - $(SRCDIR)/tests/test_suite.cpp \ - $(SRCDIR)/tests/texgen_matrix_tests.cpp \ - $(SRCDIR)/tests/texgen_tests.cpp \ - $(SRCDIR)/tests/texture_border_tests.cpp \ - $(SRCDIR)/tests/texture_cpu_update_tests.cpp \ - $(SRCDIR)/tests/texture_cubemap_tests.cpp \ - $(SRCDIR)/tests/texture_format_dxt_tests.cpp \ - $(SRCDIR)/tests/texture_format_tests.cpp \ - $(SRCDIR)/tests/texture_framebuffer_blit_tests.cpp \ - $(SRCDIR)/tests/texture_matrix_tests.cpp \ - $(SRCDIR)/tests/texture_render_target_tests.cpp \ - $(SRCDIR)/tests/texture_render_update_in_place_tests.cpp \ - $(SRCDIR)/tests/texture_shadow_comparator_tests.cpp \ - $(SRCDIR)/tests/texture_signed_component_tests.cpp \ - $(SRCDIR)/tests/three_d_primitive_tests.cpp \ - $(SRCDIR)/tests/two_d_line_tests.cpp \ - $(SRCDIR)/tests/vertex_shader_independence_tests.cpp \ - $(SRCDIR)/tests/vertex_shader_rounding_tests.cpp \ - $(SRCDIR)/tests/vertex_shader_swizzle_tests.cpp \ - $(SRCDIR)/tests/viewport_tests.cpp \ - $(SRCDIR)/tests/volume_texture_tests.cpp \ - $(SRCDIR)/tests/w_param_tests.cpp \ - $(SRCDIR)/tests/window_clip_tests.cpp \ - $(SRCDIR)/tests/zero_stride_tests.cpp - -SHADER_OBJS = \ - $(SRCDIR)/shaders/attribute_carryover_test.inl \ - $(SRCDIR)/shaders/attribute_explicit_setter_tests.inl \ - $(SRCDIR)/shaders/mul_col0_by_const0_vertex_shader.inl \ - $(SRCDIR)/shaders/precalculated_vertex_shader_2c_texcoords.inl \ - $(SRCDIR)/shaders/precalculated_vertex_shader_4c_texcoords.inl \ - $(SRCDIR)/shaders/projection_vertex_shader.inl \ - $(SRCDIR)/shaders/projection_vertex_shader_no_lighting.inl \ - $(SRCDIR)/shaders/projection_vertex_shader_no_lighting_4c_texcoords.inl \ - $(SRCDIR)/shaders/textured_pixelshader.inl \ - $(SRCDIR)/shaders/untextured_pixelshader.inl - -NV2A_VSH_OBJS = \ - $(SRCDIR)/shaders/fog_infinite_fogc_test.vshinc \ - $(SRCDIR)/shaders/fog_vec4_w.vshinc \ - $(SRCDIR)/shaders/fog_vec4_w_x.vshinc \ - $(SRCDIR)/shaders/fog_vec4_w_y.vshinc \ - $(SRCDIR)/shaders/fog_vec4_w_z_y_x.vshinc \ - $(SRCDIR)/shaders/fog_vec4_x.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xy.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xyz.vshinc \ - $(SRCDIR)/shaders/fog_vec4_x_y_z_w.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xyzw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xz.vshinc \ - $(SRCDIR)/shaders/fog_vec4_xzw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_y.vshinc \ - $(SRCDIR)/shaders/fog_vec4_yw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_yz.vshinc \ - $(SRCDIR)/shaders/fog_vec4_yzw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_z.vshinc \ - $(SRCDIR)/shaders/fog_vec4_zw.vshinc \ - $(SRCDIR)/shaders/fog_vec4_unset.vshinc - -CFLAGS += -I$(SRCDIR) -I$(THIRDPARTYDIR) -CXXFLAGS += -I$(SRCDIR) -I$(THIRDPARTYDIR) -DFPNG_NO_STDIO=1 -DFPNG_NO_SSE=1 - -OPTIMIZE_COMPILE_FLAGS = -O3 -fno-strict-aliasing -ifneq ($(DEBUG),y) -CFLAGS += $(OPTIMIZE_COMPILE_FLAGS) -CXXFLAGS += $(OPTIMIZE_COMPILE_FLAGS) -endif - -# Disable automatic test execution if no input is detected. -DISABLE_AUTORUN ?= n -# Remove the delay for input before starting automated testing. -AUTORUN_IMMEDIATELY ?= n -ifeq ($(DISABLE_AUTORUN),y) -CXXFLAGS += -DDISABLE_AUTORUN -else -ifeq ($(AUTORUN_IMMEDIATELY),y) -CXXFLAGS += -DAUTORUN_IMMEDIATELY -endif -endif - -# Cause the program to shut down the xbox on completion instead of rebooting. -ENABLE_SHUTDOWN ?= n -ifeq ($(ENABLE_SHUTDOWN),y) -CXXFLAGS += -DENABLE_SHUTDOWN -endif - -# Optionally set the root path at which test results will be written when running -# from read-only media. -# E.g., "c:" -ifdef FALLBACK_OUTPUT_ROOT_PATH -CXXFLAGS += -DFALLBACK_OUTPUT_ROOT_PATH="\"$(FALLBACK_OUTPUT_ROOT_PATH)\"" -endif - -# Set the path to a configuration file containing the names of tests that should -# be enabled, one per line. -# E.g., "c:/pgraph_tests.cnf" -ifdef RUNTIME_CONFIG_PATH -CXXFLAGS += -DRUNTIME_CONFIG_PATH="\"$(RUNTIME_CONFIG_PATH)\"" -endif - -# Cause a runtime config file enabling all tests to be generated in the standard results directory. -DUMP_CONFIG_FILE ?= n -ifeq ($(DUMP_CONFIG_FILE),y) -CXXFLAGS += -DDUMP_CONFIG_FILE -endif - -# Cause a log file to be created and updated with metrics at the start and end of each test. -ENABLE_PROGRESS_LOG ?= n -ifeq ($(ENABLE_PROGRESS_LOG),y) -CXXFLAGS += -DENABLE_PROGRESS_LOG -endif - -# Uses the result of the last progress log to ask the user whether tests that appeared to crash historically should be -# skipped. -ENABLE_INTERACTIVE_CRASH_AVOIDANCE ?= n -ifeq ($(ENABLE_INTERACTIVE_CRASH_AVOIDANCE),y) -ifneq ($(ENABLE_PROGRESS_LOG),y) -$(error ENABLE_INTERACTIVE_CRASH_AVOIDANCE may not be enabled without ENABLE_PROGRESS_LOG) -endif -CXXFLAGS += -DENABLE_INTERACTIVE_CRASH_AVOIDANCE -endif - -# Causes a diff of the nv2a PGRAPH registers to be done between the start and end of each test in order to detect state -# leakage. Output is logged to XBDM and will be written into the progress log if it is enabled. -ENABLE_PGRAPH_REGION_DIFF ?= n -ifeq ($(ENABLE_PGRAPH_REGION_DIFF),y) -CXXFLAGS += -DENABLE_PGRAPH_REGION_DIFF -endif - -# Enables the MultiframeCPUBlit test within the Antialiasing tests. -# This test requires evaluation across multiple frames and thus cannot produce -# a usable golden artifact for automated validation. This should only be enabled -# for manual testing purposes. -ENABLE_MULTIFRAME_CPU_BLIT_TEST ?= n -ifeq ($(ENABLE_MULTIFRAME_CPU_BLIT_TEST),y) -CXXFLAGS += -DMULTIFRAME_CPU_BLIT -endif - -CLEANRULES = clean-resources clean-optimized clean-nv2a-vsh-objs -include $(NXDK_DIR)/Makefile - -PBKIT_DEBUG ?= n -ifeq ($(PBKIT_DEBUG),y) -NXDK_CFLAGS += -DDBG -endif - -XBDM_GDB_BRIDGE := xbdm -REMOTE_PATH := e:\\pgraph -XBOX ?= -.phony: deploy -deploy: $(OUTPUT_DIR)/default.xbe - $(XBDM_GDB_BRIDGE) $(XBOX) -- mkdir $(REMOTE_PATH) - # TODO: Support moving the actual changed files. - # This hack will only work if the default.xbe changes when any resource changes. - $(XBDM_GDB_BRIDGE) $(XBOX) -- putfile $(OUTPUT_DIR)/ $(REMOTE_PATH) -f - -.phony: execute -execute: deploy - $(XBDM_GDB_BRIDGE) $(XBOX) -s -- /run $(REMOTE_PATH) - -.phony: debug_bridge_no_deploy -debug_bridge_no_deploy: - $(XBDM_GDB_BRIDGE) $(XBOX) -s -- gdb :1999 '&&' /launch $(REMOTE_PATH) - -.phony: debug_bridge -debug_bridge: deploy debug_bridge_no_deploy - -DEPS += $(filter %.c.d, $(OPTIMIZED_SRCS:.c=.c.d)) -DEPS += $(filter %.cpp.d, $(OPTIMIZED_SRCS:.cpp=.cpp.d)) -$(OPTIMIZED_SRCS): $(SHADER_OBJS) $(NV2A_VSH_OBJS) -OPTIMIZED_CC_SRCS := $(filter %.c,$(OPTIMIZED_SRCS)) -OPTIMIZED_CC_OBJS := $(addsuffix .obj, $(basename $(OPTIMIZED_CC_SRCS))) -OPTIMIZED_CXX_SRCS := $(filter %.cpp,$(OPTIMIZED_SRCS)) -OPTIMIZED_CXX_OBJS := $(addsuffix .obj, $(basename $(OPTIMIZED_CXX_SRCS))) -OPTIMIZED_AS_SRCS := $(filter %.s,$(OPTIMIZED_SRCS)) -OPTIMIZED_AS_OBJS := $(addsuffix .obj, $(basename $(OPTIMIZED_AS_SRCS))) -OPTIMIZED_OBJS := $(OPTIMIZED_CC_OBJS) $(OPTIMIZED_CXX_OBJS) $(OPTIMIZED_AS_OBJS) -OPTIMIZED_FILTER_COMPILE_FLAGS := -g -gdwarf-4 - -$(OPTIMIZED_CC_OBJS): %.obj: %.c - @echo "[ CC - OPT ] $@" - $(VE) $(CC) $(filter-out $(OPTIMIZED_FILTER_COMPILE_FLAGS),$(NXDK_CFLAGS)) $(OPTIMIZE_COMPILE_FLAGS) $(CFLAGS) -MD -MP -MT '$@' -MF '$(patsubst %.obj,%.c.d,$@)' -c -o '$@' '$<' - -$(OPTIMIZED_CXX_OBJS): %.obj: %.cpp - @echo "[ CXX - OPT] $@" - $(VE) $(CXX) $(filter-out $(OPTIMIZED_FILTER_COMPILE_FLAGS),$(NXDK_CXXFLAGS)) $(OPTIMIZE_COMPILE_FLAGS) $(CXXFLAGS) -MD -MP -MT '$@' -MF '$(patsubst %.obj,%.cpp.d,$@)' -c -o '$@' '$<' - -$(OPTIMIZED_AS_OBJS): %.obj: %.s - @echo "[ AS - OPT ] $@" - $(VE) $(AS) $(filter-out $(OPTIMIZED_FILTER_COMPILE_FLAGS),$(NXDK_ASFLAGS)) $(OPTIMIZE_COMPILE_FLAGS) $(ASFLAGS) -c -o '$@' '$<' - -optimized.lib: $(OPTIMIZED_OBJS) - -.PHONY: clean-optimized -clean-optimized: - $(VE)rm -f optimized.lib $(OPTIMIZED_OBJS) - -main.exe: optimized.lib - -RESOURCE_FILES = $(shell find $(RESOURCEDIR)/ -type f) -RESOURCES = \ - $(patsubst $(RESOURCEDIR)/%,$(OUTPUT_DIR)/%,$(RESOURCE_FILES)) - -TARGET += $(RESOURCES) -$(GEN_XISO): $(RESOURCES) - -$(OUTPUT_DIR)/%: $(RESOURCEDIR)/% - $(VE)mkdir -p '$(dir $@)' - $(VE)cp -r '$<' '$@' - -.PHONY: clean-resources -clean-resources: - $(VE)rm -rf $(patsubst $(RESOURCEDIR)/%,$(OUTPUT_DIR)/%,$(RESOURCES)) - -# nv2avsh assembler rules: -$(SRCS): $(NV2A_VSH_OBJS) -.PHONY: clean-nv2a-vsh-objs -clean-nv2a-vsh-objs: - $(VE)rm -f $(NV2A_VSH_OBJS) - -$(NV2A_VSH_OBJS): %.vshinc: %.vsh - @echo "[ nv2avsh ] $@" - $(VE) $(NV2AVSH) '$<' '$@' diff --git a/README.md b/README.md index b1d8e37..16c908b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Tests will be executed automatically if no gamepad input is given within an init Individual tests may be executed via the menu. ### Test configuration + Tests can optionally be determined via a configuration file loaded from the XBOX. The file follows a simple line-based format. @@ -27,6 +28,7 @@ The names used are the same as the names that appear in the `nxdk_praph_tests` m If the entire file is empty (or commented out), it will be ignored and all tests will be enabled. For example: + ``` ThisTestSuiteIsEnabled -ExceptThisTest @@ -72,21 +74,45 @@ It can be installed via `pip3 install nv2a-vsh --upgrade`. This test suite requires some modifications to the pbkit used by the nxdk in order to operate. To facilitate this, the nxdk is included as a submodule of this project, referencing the -`pbkit_extensions` branch from https://github.com/abaire/nxdk. +`cmake_pgraph_tester` branch from https://github.com/abaire/nxdk. This project should be cloned with the `--recursive` flag to pull the submodules and their submodules, after the fact this can be achieved via `git submodule update --init --recursive`. -For macOS, the patched nxdk currently assumes that the Homebrew llvm@11 package has been installed. +As of July 2023, the nxdk's CMake implementation requires bootstrapping before it may be used. To facilitate this, run +the `prewarm-nxdk.sh` script from this project's root directory. It will navigate into the `nxdk` subdir and build all +of the sample projects, triggering the creation of the `nxdk` libraries needed for the toolchain and for this project. + +### Building with CLion + +The CMake target can be configured to use the toolchain from the nxdk: + +* CMake options + + `-DCMAKE_TOOLCHAIN_FILE=/third_party/nxdk/share/toolchain-nxdk.cmake` + +* Environment + + `NXDK_DIR=/third_party/nxdk` + +On macOS you may also have to modify `PATH` in the `Environment` section such that a homebrew version of LLVM +is preferred over Xcode's (to supply `dlltool`). + +#### Example settings + +Assuming that this project has been checked out at `/development/pgraph_tester`: + +* CMake options: `-DCMAKE_TOOLCHAIN_FILE=/development/pgraph_tester/third_party/nxdk/share/toolchain-nxdk.cmake` +* Environment: `NXDK_DIR=/development/pgraph_tester/third_party/nxdk` ## Adding new tests -### Using nv2a log events from xemu +### Using nv2a log events from [xemu](https://xemu.app/) 1. Enable tracing of nv2a log events as normal (see xemu documentation) and exercise the event of interest within the game. 1. Duplicate an existing test as a skeleton. -1. Add the duplicated test to the `Makefile` and `main.cpp` (please preserve +1. Add the duplicated test to `CMakeLists.txt` and `main.cpp` (please preserve alphabetical ordering if possible). 1. Use [nv2a_to_pbkit](https://github.com/abaire/nv2a_to_pbkit) to get a rough set of pbkit invocations duplicating the behavior from the log. Take the @@ -94,23 +120,44 @@ For macOS, the patched nxdk currently assumes that the Homebrew llvm@11 package the test. You may wish to utilize some of the helper methods from `TestHost` and similar classes rather than using the raw output to improve readability. - ## Running with CLion +### On xemu + Create a build target 1. Create a new `Embedded GDB Server` target -1. Set the Target to `all` -1. Set the Executable to `main.exe` -1. Set `Download executable` to `None` +1. Set the Target to `nxdk_pgraph_tests_xiso` +1. Set the Executable to `nxdk_pgraph_tests` +1. Set `Download executable` to `Never` 1. Set `'target remote' args` to `127.0.0.1:1234` 1. Set `GDB Server` to the path to the xemu binary -1. Set `GDB Server args` to `-s -S` (the `-S` is optional and will cause xemu to wait for the debugger to connnect) +1. Set `GDB Server args` to `-s -S -dvd_path "$CMakeCurrentBuildDir$/xiso/nxdk_pgraph_tests.iso"` (the `-S` is + optional and will cause xemu to wait for the debugger to connnect) +1. Under `Advanced GDB Server Options` + 1. Set "Working directory" to `$ProjectFileDir$` + 1. On macOS, set "Environment variables" + to `DYLD_FALLBACK_LIBRARY_PATH=//Contents/Libraries/` + 3. Set "Reset command" to `Never` To capture DbgPrint, additionally append `-device lpc47m157 -serial tcp:127.0.0.1:9091` to `GDB Server args` and use something like [pykdclient](https://github.com/abaire/pykdclient). -## Deploying with xbdm_gdb_bridge +NOTE: If you see a failure due to "Remote target doesn't support qGetTIBAddr packet", check the GDB output to make sure +that the `.gdbinit` file was successfully loaded. -The `Makefile` contains a `deploy` target that will copy the finished binary to an XBOX running XBDM. This functionality -requires the [xbdm_gdb_bridge](https://github.com/abaire/xbdm_gdb_bridge) utility. +## Deploying with [xbdm_gdb_bridge](https://github.com/abaire/xbdm_gdb_bridge) + +To create a launch configuration that deploys the devhost to an XBDM-enabled XBOX (devkit) with debugging enabled: + +1. Create a new `Embedded GDB Server` run config. + 1. Set the "Target" to `nxdk_pgraph_tests` + 1. Set the "Executable binary" to `nxdk_pgraph_tests` + 1. Set "Download executable" to `Never` + 1. Set "'target remote' args" to `localhost:1999` + 1. Set "GDB Server" to the full path to the [xbdm_gdb_bridge binary](https://github.com/abaire/xbdm_gdb_bridge) + binary + 1. Set "GDB Server args" + to ` -s -- mkdir e:\$CMakeCurrentTargetName$ && putfile $CMakeCurrentBuildDir$/xbe/default.xbe e:\$CMakeCurrentTargetName$ -f && gdb :1999 e:\$CMakeCurrentTargetName$` + 1. Under "Advanced GDB Server Options" + 1. Set "Reset command" to `Never` diff --git a/cmake/modules/FindNXDK.cmake b/cmake/modules/FindNXDK.cmake new file mode 100644 index 0000000..66bfc00 --- /dev/null +++ b/cmake/modules/FindNXDK.cmake @@ -0,0 +1,108 @@ +if(NOT TARGET NXDK::NXDK) + add_library(nxdk STATIC IMPORTED) + set_target_properties( + nxdk + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libnxdk.lib" + ) + + add_library(nxdk_automount_d STATIC IMPORTED) + set_target_properties( + nxdk_automount_d + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libnxdk_automount_d.lib" + ) + + add_library(nxdk_hal STATIC IMPORTED) + set_target_properties( + nxdk_hal + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libnxdk_hal.lib" + ) + + add_library(nxdk_net STATIC IMPORTED) + set_target_properties( + nxdk_net + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libnxdk_net.lib" + ) + + add_library(nxdk_usb STATIC IMPORTED) + set_target_properties( + nxdk_usb + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/nxdk_usb.lib" + ) + + add_library(pbkit STATIC IMPORTED) + set_target_properties( + pbkit + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libpbkit.lib" + ) + + add_library(pdclib STATIC IMPORTED) + set_target_properties( + pdclib + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libpdclib.lib" + ) + + add_library(winapi STATIC IMPORTED) + set_target_properties( + winapi + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libwinapi.lib" + ) + + add_library(winmm STATIC IMPORTED) + set_target_properties( + winmm + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/winmm.lib" + ) + + add_library(xboxrt STATIC IMPORTED) + set_target_properties( + xboxrt + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libxboxrt.lib" + ) + + add_library(zlib STATIC IMPORTED) + set_target_properties( + zlib + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libzlib.lib" + ) + + add_library(NXDK::NXDK INTERFACE IMPORTED) + target_link_libraries( + NXDK::NXDK + INTERFACE + nxdk + nxdk_automount_d + nxdk_hal + nxdk_net + nxdk_usb + pbkit + pdclib + winapi + winmm + xboxrt + zlib + ) +endif() + +if(NOT TARGET NXDK::NXDK_CXX) + + add_library(nxdk_cxx STATIC IMPORTED) + set_target_properties( + nxdk_cxx + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libc++.lib" + ) + + add_library(NXDK::NXDK_CXX INTERFACE IMPORTED) + target_link_libraries(NXDK::NXDK_CXX INTERFACE nxdk_cxx) +endif() diff --git a/cmake/modules/FindNXDK_SDL2.cmake b/cmake/modules/FindNXDK_SDL2.cmake new file mode 100644 index 0000000..ed6d129 --- /dev/null +++ b/cmake/modules/FindNXDK_SDL2.cmake @@ -0,0 +1,6 @@ +if(NOT TARGET NXDK::SDL2) + find_package(PkgConfig REQUIRED) + pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2) + + add_library(NXDK::SDL2 ALIAS PkgConfig::SDL2) +endif() diff --git a/cmake/modules/FindNXDK_SDL2_Image.cmake b/cmake/modules/FindNXDK_SDL2_Image.cmake new file mode 100644 index 0000000..c3b5fb2 --- /dev/null +++ b/cmake/modules/FindNXDK_SDL2_Image.cmake @@ -0,0 +1,37 @@ +if (NOT TARGET NXDK::SDL2_Image) + + add_library(nxdk_sdl2_image STATIC IMPORTED) + set_target_properties( + nxdk_sdl2_image + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libSDL2_image.lib" + ) + + add_library(nxdk_jpeg STATIC IMPORTED) + set_target_properties( + nxdk_jpeg + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libjpeg.lib" + ) + + add_library(nxdk_png STATIC IMPORTED) + set_target_properties( + nxdk_png + PROPERTIES + IMPORTED_LOCATION "${NXDK_DIR}/lib/libpng.lib" + ) + + add_library(NXDK::SDL2_Image INTERFACE IMPORTED) + target_link_libraries( + NXDK::SDL2_Image + INTERFACE + nxdk_sdl2_image + nxdk_jpeg + nxdk_png + ) + target_include_directories( + NXDK::SDL2_Image + SYSTEM INTERFACE + "${NXDK_DIR}/lib/sdl/SDL2_image" + ) +endif () diff --git a/cmake/modules/FindThreads.cmake b/cmake/modules/FindThreads.cmake new file mode 100644 index 0000000..51c1f6b --- /dev/null +++ b/cmake/modules/FindThreads.cmake @@ -0,0 +1,5 @@ +if(NOT TARGET Threads::Threads) + set(CMAKE_HAVE_THREADS_LIBRARY 1) + set(Threads_FOUND TRUE) + add_library(Threads::Threads INTERFACE IMPORTED) +endif() diff --git a/cmake/modules/NV20_CG.cmake b/cmake/modules/NV20_CG.cmake new file mode 100644 index 0000000..d4e20c3 --- /dev/null +++ b/cmake/modules/NV20_CG.cmake @@ -0,0 +1,144 @@ +# Provides: +# +# `generate_pixelshader_inl_files`, a function to compile [cg](https://en.wikipedia.org/wiki/Cg_(programming_language)) +# pixel shaders to .inl files using the FP20COMPILER. +# +# `generate_vertexshader_inl_files`, a function to compile [cg](https://en.wikipedia.org/wiki/Cg_(programming_language)) +# vertex shaders to .inl files using the VP20COMPILER. +# +# Each function takes the name of a target followed by the "SOURCES" keyword, followed by any number of source files. +# The target should be added via `target_link_libraries` to any targets that require the generated sources. + +include(CMakeParseArguments) + +if (CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin) + set(CG "${NXDK_DIR}/tools/cg/mac/cgc") +elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) + set(CG "${NXDK_DIR}/tools/cg/win/cgc") +elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL Linux) + set(CG "${NXDK_DIR}/tools/cg/linux/cgc") +else () + message("Warning: Unknown host system '${CMAKE_HOST_SYSTEM_NAME}', defaulting to Linux") + set(CG "${NXDK_DIR}/tools/cg/linux/cgc") +endif () + +set(FP20COMPILER "${NXDK_DIR}/tools/fp20compiler/fp20compiler") +set(VP20COMPILER "${NXDK_DIR}/tools/vp20compiler/vp20compiler") + +function(generate_pixelshader_inl_files) + cmake_parse_arguments( + PARSE_ARGV + 1 + "FP20" + "" + "" + "SOURCES" + ) + + set(target "${ARGV0}") + + set(generated_sources) + set(generated_source_dirs) + foreach (src ${FP20_SOURCES}) + get_filename_component(abs_src "${src}" REALPATH) + + set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${src}.cgout") + get_filename_component(src_dirname "${src}" DIRECTORY) + get_filename_component(src_basename "${src}" NAME_WE) + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${src_dirname}") + set(output "${CMAKE_CURRENT_BINARY_DIR}/${src_dirname}/${src_basename}.inl") + + add_custom_command( + OUTPUT "${output}" + COMMAND "${CG}" -profile fp20 -o "${intermediate}" "${abs_src}" + COMMAND "${FP20COMPILER}" "${intermediate}" > "${output}" + DEPENDS "${abs_src}" + BYPRODUCTS "${intermediate}" + ) + + list(APPEND generated_sources "${output}") + list(APPEND generated_source_dirs "${CMAKE_CURRENT_BINARY_DIR}/${src_dirname}") + endforeach () + + add_custom_target( + "${target}_gen" + DEPENDS + ${generated_sources} + ) + + list(REMOVE_DUPLICATES generated_source_dirs) + add_library( + "${target}" + INTERFACE + EXCLUDE_FROM_ALL + ${generated_sources} + ) + target_include_directories( + "${target}" + INTERFACE + ${generated_source_dirs} + ) + add_dependencies( + "${target}" + "${target}_gen" + ) +endfunction() + + +function(generate_vertexshader_inl_files) + cmake_parse_arguments( + PARSE_ARGV + 1 + "VP20" + "" + "" + "SOURCES" + ) + + set(target "${ARGV0}") + + set(generated_sources) + set(generated_source_dirs) + foreach (src ${VP20_SOURCES}) + get_filename_component(abs_src "${src}" REALPATH) + + set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${src}.cgout") + get_filename_component(src_dirname "${src}" DIRECTORY) + get_filename_component(src_basename "${src}" NAME_WE) + set(output "${CMAKE_CURRENT_BINARY_DIR}/${src_dirname}/${src_basename}.inl") + + add_custom_command( + OUTPUT "${output}" + COMMAND "${CG}" -profile vp20 -o "${intermediate}" "${abs_src}" + COMMAND "${VP20COMPILER}" "${intermediate}" > "${output}" + DEPENDS "${abs_src}" + BYPRODUCTS "${intermediate}" + ) + + list(APPEND generated_sources "${output}") + list(APPEND generated_source_dirs "${CMAKE_CURRENT_BINARY_DIR}/${src_dirname}") + endforeach () + + add_custom_target( + "${target}_gen" + DEPENDS + ${generated_sources} + ) + + list(REMOVE_DUPLICATES generated_source_dirs) + add_library( + "${target}" + INTERFACE + EXCLUDE_FROM_ALL + ${generated_sources} + ) + target_include_directories( + "${target}" + INTERFACE + ${generated_source_dirs} + ) + add_dependencies( + "${target}" + "${target}_gen" + ) +endfunction() diff --git a/cmake/modules/NV2A_VSH.cmake b/cmake/modules/NV2A_VSH.cmake new file mode 100644 index 0000000..7f5b40f --- /dev/null +++ b/cmake/modules/NV2A_VSH.cmake @@ -0,0 +1,39 @@ +# Provides `generate_nv2a_vshinc_files`, a function to compile nv2a vertex +# shaders written in nv2a assembly into `.vshinc` source files that may be +# included and uploaded using pbkit. + +include(CMakeParseArguments) + +# pip3 install nv2a-vsh +# https://pypi.org/project/nv2a-vsh/ +# https://github.com/abaire/nv2a_vsh_asm +set(NV2AVSH nv2avsh) + +function(generate_nv2a_vshinc_files) + + cmake_parse_arguments( + PARSE_ARGV + 1 + "NV2A_VSH" + "" + "" + "SOURCES" + ) + + set(target "${ARGV0}") + + set("${target}") + foreach (src ${NV2A_VSH_SOURCES}) + set(output "${CMAKE_CURRENT_BINARY_DIR}/${src}inc") + + get_filename_component(abs_src "${src}" REALPATH) + + add_custom_command( + OUTPUT "${output}" + COMMAND "${NV2AVSH}" "${abs_src}" "${output}" + DEPENDS "${abs_src}" + ) + + set("${target}" "${${target}};${output}" CACHE INTERNAL "") + endforeach () +endfunction() diff --git a/cmake/modules/XBEUtils.cmake b/cmake/modules/XBEUtils.cmake new file mode 100644 index 0000000..de5d0a7 --- /dev/null +++ b/cmake/modules/XBEUtils.cmake @@ -0,0 +1,221 @@ +# Provides: +# +# add_xbe( +# target executable_file +# [XBENAME ="default.xbe"] +# [TITLE ={target}] +# RESOURCE_FILES +# RESOURCE_DIRS +# ) +# +# Generates an XBE file from the given executable_file. The given resources will be attached such that add_xiso will +# include them in the root of the generated iso. +# +# add_xiso(target xbe_target [XISO =.xiso]) +# Generates an xiso image for the given XBE. + +include(CMakeParseArguments) + +set(CXBE_TOOL_PATH "${NXDK_DIR}/tools/cxbe/cxbe") +set(EXTRACT_XISO_TOOL_PATH "${NXDK_DIR}/tools/extract-xiso/build/extract-xiso") + +# Makes each path in the given list into an absolute path. +function(_make_abs_paths list_name) + foreach (src "${${list_name}}") + get_filename_component(abs "${src}" ABSOLUTE) + list(APPEND ret "${abs}") + endforeach () + set(${list_name} ${ret} PARENT_SCOPE) +endfunction() + +# split_debug(executable_file debug_file_variable) +# +# Splits debugging information from the given `executable_file`, generating a companion file ending in ".debug.exe" +# Sets `debug_file_variable` in the parent scope to the generated file. +function(split_debug) + if (${ARGC} LESS 1) + message(FATAL_ERROR "Missing required 'executable_file' parameter.") + elseif (${ARGC} LESS 2) + message(FATAL_ERROR "Missing required 'debug_file_variable_name' parameter.") + endif () + + set(exe_file "${ARGV0}") + set(debug_file_variable "${ARGV1}") + get_filename_component(exe_dirname "${exe_file}" DIRECTORY) + get_filename_component(exe_basename "${exe_file}" NAME_WE) + set(output "${exe_dirname}/${exe_basename}.debug.exe") + + add_custom_command( + OUTPUT "${output}" + COMMAND "${CMAKE_COMMAND}" -E copy "${exe_file}" "${output}" + COMMAND "${CMAKE_OBJCOPY}" --strip-debug "${exe_file}" + COMMAND "${CMAKE_OBJCOPY}" --add-gnu-debuglink="${output}" "${exe_file}" + DEPENDS "${exe_file}" + ) + set("${debug_file_variable}" "${output}" PARENT_SCOPE) +endfunction() + +function(add_xbe) + cmake_parse_arguments( + PARSE_ARGV + 2 + "XBE" + "" + "XBENAME" + "RESOURCE_FILES;RESOURCE_DIRS" + ) + + if (${ARGC} LESS 1) + message(FATAL_ERROR "Missing required 'target' parameter.") + elseif (${ARGC} LESS 2) + message(FATAL_ERROR "Missing required 'executable_file' parameter.") + endif () + + set(target "${ARGV0}") + set(exe_file "${ARGV1}") + + # exe_file will be updated to contain the stripped binary and + # exe_file_DEBUG will be created to track the generated debug artifact. + split_debug("${exe_file}" exe_file_DEBUG) + message("DEBUG FILE: ${exe_file} -> ${exe_file_DEBUG}") + + if (NOT XBE_XBENAME) + set(XBE_XBENAME default.xbe) + endif () + + if (NOT XBE_TITLE) + set(XBE_TITLE "${target}") + endif () + + set( + "${target}_XBE_STAGING_DIR" + "${CMAKE_CURRENT_BINARY_DIR}/xbe/${target}" + CACHE INTERNAL + "Directory into which the raw sources for an xiso have been placed." + ) + set(XBE_STAGING_DIR "${${target}_XBE_STAGING_DIR}") + + set( + "${target}_XBE_OUTPUT_PATH" + "${${target}_XBE_STAGING_DIR}/${XBE_XBENAME}" + CACHE INTERNAL + "XBE file that should be added to an xiso." + ) + set(XBE_OUTPUT_PATH "${${target}_XBE_OUTPUT_PATH}") + + add_custom_command( + OUTPUT "${XBE_STAGING_DIR}" + COMMAND "${CMAKE_COMMAND}" -E make_directory "${XBE_STAGING_DIR}" + ) + + file(MAKE_DIRECTORY "${XBE_STAGING_DIR}") + + add_custom_command( + OUTPUT "${XBE_OUTPUT_PATH}" + COMMAND "${CXBE_TOOL_PATH}" + "-TITLE:${XBE_TITLE}" + "-OUT:${XBE_OUTPUT_PATH}" + "${exe_file}" + DEPENDS "${exe_file}" "${exe_file_DEBUG}" + ) + + # Copy resources to the staging directory. + set( + "${target}_RESOURCE_FILES_RECEIPT_OUTPUT_PATH" + CACHE + INTERNAL + "Timestamp file indicating that resource files have been copied." + ) + if (XBE_RESOURCE_FILES) + set( + "${target}_RESOURCE_FILES_RECEIPT_OUTPUT_PATH" + "${CMAKE_CURRENT_BINARY_DIR}/xbe/.${target}_resource_files_time" + CACHE + INTERNAL + "Timestamp file indicating that resource files have been copied." + ) + set(RESOURCE_FILES_RECEIPT "${${target}_RESOURCE_FILES_RECEIPT_OUTPUT_PATH}") + _make_abs_paths(XBE_RESOURCE_FILES) + add_custom_command( + OUTPUT "${RESOURCE_FILES_RECEIPT}" + COMMAND + "${CMAKE_COMMAND}" -E copy_if_different "${XBE_RESOURCE_FILES}" "${XBE_STAGING_DIR}" + COMMAND + "${CMAKE_COMMAND}" -E touch "${RESOURCE_FILES_RECEIPT}" + DEPENDS ${XBE_RESOURCE_FILES} + ) + endif () + + set( + "${target}_RESOURCE_DIRS_RECEIPT_OUTPUT_PATH" + CACHE + INTERNAL + "Timestamp file indicating that resource directories have been copied." + ) + if (XBE_RESOURCE_DIRS) + set( + "${target}_RESOURCE_DIRS_RECEIPT_OUTPUT_PATH" + "${CMAKE_CURRENT_BINARY_DIR}/xbe/.${target}_resource_dirs_time" + CACHE INTERNAL + "Timestamp file indicating that resource directories have been copied." + ) + set(RESOURCE_DIRS_RECEIPT "${${target}_RESOURCE_DIRS_RECEIPT_OUTPUT_PATH}") + _make_abs_paths(XBE_RESOURCE_DIRS) + add_custom_command( + OUTPUT "${RESOURCE_DIRS_RECEIPT}" + COMMAND + "${CMAKE_COMMAND}" -E env pwd + COMMAND + "${CMAKE_COMMAND}" -E copy_directory ${XBE_RESOURCE_DIRS} "${XBE_STAGING_DIR}" + COMMAND + "${CMAKE_COMMAND}" -E touch "${RESOURCE_DIRS_RECEIPT}" + DEPENDS ${XBE_RESOURCE_DIRS} + ) + endif () +endfunction() + +function(add_xiso) + cmake_parse_arguments( + PARSE_ARGV + 2 + "XISO" + "" + "XISO" + "" + ) + + if (${ARGC} LESS 1) + message(FATAL_ERROR "Missing required 'target' parameter.") + elseif (${ARGC} LESS 2) + message(FATAL_ERROR "Missing required 'xbe_target' parameter.") + endif () + set(target "${ARGV0}") + set(xbe_target "${ARGV1}") + + if (NOT XISO_XISO) + set(XISO_XISO "${target}.iso") + endif () + + set(XBE_STAGING_DIR "${${xbe_target}_XBE_STAGING_DIR}") + set(XBE_OUTPUT_PATH "${${xbe_target}_XBE_OUTPUT_PATH}") + set(XBE_RESOURCE_FILES_RECEIPT "${${xbe_target}_RESOURCE_FILES_RECEIPT_OUTPUT_PATH}") + set(XBE_RESOURCE_DIRS_RECEIPT "${${xbe_target}_RESOURCE_DIRS_RECEIPT_OUTPUT_PATH}") + set(XISO_STAGING_DIR "${CMAKE_CURRENT_BINARY_DIR}/xiso/${target}") + file(MAKE_DIRECTORY "${XISO_STAGING_DIR}") + set(XISO_OUTPUT_PATH "${XISO_STAGING_DIR}/${XISO_XISO}") + + add_custom_command( + OUTPUT "${XISO_OUTPUT_PATH}" + COMMAND "${EXTRACT_XISO_TOOL_PATH}" -c "${XBE_STAGING_DIR}" "${XISO_OUTPUT_PATH}" + DEPENDS + "${XBE_OUTPUT_PATH}" + "${XBE_RESOURCE_FILES_RECEIPT}" + "${XBE_RESOURCE_DIRS_RECEIPT}" + ) + + add_custom_target( + "${target}" + ALL + DEPENDS + "${XISO_OUTPUT_PATH}") +endfunction() diff --git a/prewarm-nxdk.sh b/prewarm-nxdk.sh new file mode 100755 index 0000000..bdad3f2 --- /dev/null +++ b/prewarm-nxdk.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -x +eval "$(./third_party/nxdk/bin/activate -s)" + +set -eu +set -o pipefail + +cd third_party/nxdk/samples +for x in *; do + pushd "${x}" + make -j24 + popd +done diff --git a/src/configure.h.in b/src/configure.h.in new file mode 100644 index 0000000..6a0b452 --- /dev/null +++ b/src/configure.h.in @@ -0,0 +1,24 @@ +#ifndef NXDK_PGRAPH_TESTS_SRC_CONFIGURE_H_IN_H_ +#define NXDK_PGRAPH_TESTS_SRC_CONFIGURE_H_IN_H_ + +#cmakedefine ENABLE_PROGRESS_LOG +#ifdef ENABLE_PROGRESS_LOG +#cmakedefine ENABLE_INTERACTIVE_CRASH_AVOIDANCE +#endif + +#cmakedefine DUMP_CONFIG_FILE +#cmakedefine DISABLE_AUTORUN +#ifndef DISABLE_AUTORUN +#cmakedefine AUTORUN_IMMEDIATELY +#endif + +#cmakedefine ENABLE_SHUTDOWN + +#cmakedefine ENABLE_MULTIFRAME_CPU_BLIT_TEST + +#cmakedefine ENABLE_PGRAPH_REGION_DIFF + +#cmakedefine RUNTIME_CONFIG_PATH "@RUNTIME_CONFIG_PATH@" +#cmakedefine FALLBACK_OUTPUT_ROOT_PATH "@FALLBACK_OUTPUT_ROOT_PATH@" + +#endif // NXDK_PGRAPH_TESTS_SRC_CONFIGURE_H_IN_H_ diff --git a/src/main.cpp b/src/main.cpp index 706ef04..79e4417 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include #include +#include "configure.h" #include "debug_output.h" #include "logger.h" #include "test_driver.h" @@ -100,6 +101,8 @@ static bool process_config(const char* config_file_path, std::vector #include +#include "configure.h" #include "debug_output.h" #include "tests/test_suite.h" @@ -463,4 +464,4 @@ void MenuItemOptions::CursorRight() { if (cursor_position > 0) { submenu[cursor_position]->CursorRight(); } -} \ No newline at end of file +} diff --git a/src/pgraph_diff_token.cpp b/src/pgraph_diff_token.cpp index eb8455d..a40a8f7 100644 --- a/src/pgraph_diff_token.cpp +++ b/src/pgraph_diff_token.cpp @@ -3,6 +3,7 @@ #include #include +#include "configure.h" #include "debug_output.h" #ifdef ENABLE_PROGRESS_LOG diff --git a/src/shaders/perspective_vertex_shader.cpp b/src/shaders/perspective_vertex_shader.cpp index c4b1c8c..86d3d19 100644 --- a/src/shaders/perspective_vertex_shader.cpp +++ b/src/shaders/perspective_vertex_shader.cpp @@ -8,14 +8,14 @@ PerspectiveVertexShader::PerspectiveVertexShader(uint32_t framebuffer_width, uin float z_max, float fov_y, float left, float right, float bottom, float top, float near, float far) : ProjectionVertexShader(framebuffer_width, framebuffer_height, z_min, z_max), + fov_y_(fov_y), + aspect_ratio_(framebuffer_width_ / framebuffer_height_), left_(left), right_(right), top_(top), bottom_(bottom), near_(near), - far_(far), - fov_y_(fov_y), - aspect_ratio_(framebuffer_width_ / framebuffer_height_) {} + far_(far) {} void PerspectiveVertexShader::CalculateProjectionMatrix() { memset(projection_matrix_, 0, sizeof(projection_matrix_)); diff --git a/src/tests/antialiasing_tests.cpp b/src/tests/antialiasing_tests.cpp index de64793..36b0be2 100644 --- a/src/tests/antialiasing_tests.cpp +++ b/src/tests/antialiasing_tests.cpp @@ -5,6 +5,7 @@ #include #include +#include "configure.h" #include "shaders/precalculated_vertex_shader.h" #include "test_host.h" #include "texture_generator.h" @@ -34,7 +35,7 @@ static constexpr const char kFramebufferIsIndependent[] = "FramebufferNotModifie static constexpr const char kCPUWriteIgnoresSurfaceConfig[] = "CPUWriteIgnoresSurfaceConfig"; static constexpr const char kGPUAAWriteAfterCPUWrite[] = "GPUAAWriteAfterCPUWrite"; static constexpr const char kNonAACPURoundTrip[] = "NonAACPURoundTrip"; -#ifdef MULTIFRAME_CPU_BLIT +#ifdef ENABLE_MULTIFRAME_CPU_BLIT_TEST static constexpr const char kMultiframeCPUBlit[] = "__MultiframeCPUBlit"; #endif @@ -58,7 +59,7 @@ AntialiasingTests::AntialiasingTests(TestHost &host, std::string output_dir) tests_[kGPUAAWriteAfterCPUWrite] = [this]() { TestGPUAAWriteAfterCPUWrite(); }; tests_[kNonAACPURoundTrip] = [this]() { TestNonAACPURoundTrip(); }; -#ifdef MULTIFRAME_CPU_BLIT +#ifdef ENABLE_MULTIFRAME_CPU_BLIT_TEST tests_[kMultiframeCPUBlit] = [this]() { TestMultiframeCPUBlit(); }; #endif }; @@ -550,7 +551,7 @@ void AntialiasingTests::TestNonAACPURoundTrip() { host_.FinishDraw(allow_saving_, output_dir_, kNonAACPURoundTrip); } -#ifdef MULTIFRAME_CPU_BLIT +#ifdef ENABLE_MULTIFRAME_CPU_BLIT_TEST void AntialiasingTests::TestMultiframeCPUBlit() { static constexpr uint32_t kNumFrames = 120; static constexpr uint32_t kColors[][2] = { @@ -599,7 +600,7 @@ void AntialiasingTests::TestMultiframeCPUBlit() { host_.SetSurfaceFormatImmediate(TestHost::SCF_A8R8G8B8, TestHost::SZF_Z16, host_.GetFramebufferWidth(), host_.GetFramebufferHeight()); } -#endif // MULTIFRAME_CPU_BLIT +#endif // ENABLE_MULTIFRAME_CPU_BLIT_TEST void AntialiasingTests::Draw() const { host_.SetFinalCombiner0Just(TestHost::SRC_TEX0); diff --git a/src/tests/antialiasing_tests.h b/src/tests/antialiasing_tests.h index e3e358b..a6934ff 100644 --- a/src/tests/antialiasing_tests.h +++ b/src/tests/antialiasing_tests.h @@ -5,6 +5,7 @@ #include #include +#include "configure.h" #include "test_host.h" #include "test_suite.h" @@ -35,7 +36,7 @@ class AntialiasingTests : public TestSuite { void TestGPUAAWriteAfterCPUWrite(); void TestNonAACPURoundTrip(); -#ifdef MULTIFRAME_CPU_BLIT +#ifdef ENABLE_MULTIFRAME_CPU_BLIT_TEST // This test is only useful when viewing live and should generally be disabled. void TestMultiframeCPUBlit(); #endif diff --git a/src/tests/attribute_carryover_tests.cpp b/src/tests/attribute_carryover_tests.cpp index 2aa072a..47e8906 100644 --- a/src/tests/attribute_carryover_tests.cpp +++ b/src/tests/attribute_carryover_tests.cpp @@ -10,7 +10,7 @@ // clang format off static constexpr uint32_t kShader[] = { -#include "shaders/attribute_carryover_test.inl" +#include "attribute_carryover_test.inl" }; // clang format on diff --git a/src/tests/attribute_explicit_setter_tests.cpp b/src/tests/attribute_explicit_setter_tests.cpp index 4af1230..f76dfb2 100644 --- a/src/tests/attribute_explicit_setter_tests.cpp +++ b/src/tests/attribute_explicit_setter_tests.cpp @@ -10,7 +10,7 @@ // clang format off static constexpr uint32_t kShader[] = { -#include "shaders/attribute_explicit_setter_tests.inl" +#include "attribute_explicit_setter_tests.inl" }; // clang format on diff --git a/src/tests/attribute_float_tests.cpp b/src/tests/attribute_float_tests.cpp index 2d3dc5e..98b7471 100644 --- a/src/tests/attribute_float_tests.cpp +++ b/src/tests/attribute_float_tests.cpp @@ -9,11 +9,11 @@ // clang format off static const std::vector passthrough{ -#include "shaders/precalculated_vertex_shader_4c_texcoords.inl" +#include "precalculated_vertex_shader_4c_texcoords.inl" }; static const std::vector mulColour{ -#include "shaders/mul_col0_by_const0_vertex_shader.inl" +#include "mul_col0_by_const0_vertex_shader.inl" }; // clang format on diff --git a/src/tests/fog_tests.cpp b/src/tests/fog_tests.cpp index b5f9e4d..2f78e1c 100644 --- a/src/tests/fog_tests.cpp +++ b/src/tests/fog_tests.cpp @@ -236,7 +236,7 @@ void FogCustomShaderTests::Initialize() { // clang format off static const uint32_t kInfiniteFogCShader[] = { -#include "shaders/fog_infinite_fogc_test.vshinc" +#include "fog_infinite_fogc_test.vshinc" }; // clang format on @@ -257,65 +257,65 @@ void FogInfiniteFogCoordinateTests::Initialize() { // clang format off static const uint32_t kFogVec4Unset[] = { -#include "shaders/fog_vec4_unset.vshinc" +#include "fog_vec4_unset.vshinc" }; // Individual setters. static const uint32_t kFogVec4X[] = { -#include "shaders/fog_vec4_x.vshinc" +#include "fog_vec4_x.vshinc" }; static const uint32_t kFogVec4Y[] = { -#include "shaders/fog_vec4_y.vshinc" +#include "fog_vec4_y.vshinc" }; static const uint32_t kFogVec4Z[] = { -#include "shaders/fog_vec4_z.vshinc" +#include "fog_vec4_z.vshinc" }; static const uint32_t kFogVec4W[] = { -#include "shaders/fog_vec4_w.vshinc" +#include "fog_vec4_w.vshinc" }; static const uint32_t kFogVec4W_X[] = { -#include "shaders/fog_vec4_w_x.vshinc" +#include "fog_vec4_w_x.vshinc" }; static const uint32_t kFogVec4W_Y[] = { -#include "shaders/fog_vec4_w_y.vshinc" +#include "fog_vec4_w_y.vshinc" }; static const uint32_t kFogVec4W_Z_Y_X[] = { -#include "shaders/fog_vec4_w_z_y_x.vshinc" +#include "fog_vec4_w_z_y_x.vshinc" }; static const uint32_t kFogVec4X_Y_Z_W[] = { -#include "shaders/fog_vec4_x_y_z_w.vshinc" +#include "fog_vec4_x_y_z_w.vshinc" }; // Bulk setters. static const uint32_t kFogVec4XW[] = { -#include "shaders/fog_vec4_xw.vshinc" +#include "fog_vec4_xw.vshinc" }; static const uint32_t kFogVec4XY[] = { -#include "shaders/fog_vec4_xy.vshinc" +#include "fog_vec4_xy.vshinc" }; static const uint32_t kFogVec4XYZ[] = { -#include "shaders/fog_vec4_xyz.vshinc" +#include "fog_vec4_xyz.vshinc" }; static const uint32_t kFogVec4XYZW[] = { -#include "shaders/fog_vec4_xyzw.vshinc" +#include "fog_vec4_xyzw.vshinc" }; static const uint32_t kFogVec4XZ[] = { -#include "shaders/fog_vec4_xz.vshinc" +#include "fog_vec4_xz.vshinc" }; static const uint32_t kFogVec4XZW[] = { -#include "shaders/fog_vec4_xzw.vshinc" +#include "fog_vec4_xzw.vshinc" }; static const uint32_t kFogVec4YW[] = { -#include "shaders/fog_vec4_yw.vshinc" +#include "fog_vec4_yw.vshinc" }; static const uint32_t kFogVec4YZ[] = { -#include "shaders/fog_vec4_yz.vshinc" +#include "fog_vec4_yz.vshinc" }; static const uint32_t kFogVec4YZW[] = { -#include "shaders/fog_vec4_yzw.vshinc" +#include "fog_vec4_yzw.vshinc" }; static const uint32_t kFogVec4ZW[] = { -#include "shaders/fog_vec4_zw.vshinc" +#include "fog_vec4_zw.vshinc" }; // clang format on diff --git a/src/tests/test_suite.cpp b/src/tests/test_suite.cpp index 26dd1c4..e5226bd 100644 --- a/src/tests/test_suite.cpp +++ b/src/tests/test_suite.cpp @@ -2,6 +2,7 @@ #include +#include "configure.h" #include "debug_output.h" #include "logger.h" #include "pbkit_ext.h" diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt new file mode 100644 index 0000000..ca9cd0f --- /dev/null +++ b/third_party/CMakeLists.txt @@ -0,0 +1,46 @@ +# Fast png compression. +add_library( + fpng + EXCLUDE_FROM_ALL + fpng/src/fpng.cpp + fpng/src/fpng.h +) +target_compile_options( + fpng + PRIVATE + -O3 + -Wno-everything + -DFPNG_NO_STDIO=1 + -DFPNG_NO_SSE=1 +) +target_link_options(fpng PRIVATE "/debug:none") + +# Full featured printf. +add_library( + printf + EXCLUDE_FROM_ALL + printf/printf.c + printf/printf.h +) +target_compile_options( + printf + PRIVATE + -O3 + -Wno-everything +) +target_link_options(printf PRIVATE "/debug:none") + +# Texture swizzling routines. +add_library( + swizzle + EXCLUDE_FROM_ALL + swizzle.c + swizzle.h +) +target_compile_options( + swizzle + PRIVATE + -O3 + -Wno-everything +) +target_link_options(swizzle PRIVATE "/debug:none") diff --git a/third_party/nxdk b/third_party/nxdk index ed4636d..8abae89 160000 --- a/third_party/nxdk +++ b/third_party/nxdk @@ -1 +1 @@ -Subproject commit ed4636d282041aa012be9b35a29965b8630340c8 +Subproject commit 8abae89f20d91252d7a5199fd18b2b1f78a958e7