diff --git a/dm/games/0100535012974000/usage.tsv b/dm/games/0100535012974000/usage.tsv new file mode 100644 index 0000000..30c6463 --- /dev/null +++ b/dm/games/0100535012974000/usage.tsv @@ -0,0 +1,186 @@ +# kind: usage Hades (0100535012974000), revision 89744da75364, chain 6f4a4ad908e0, route smoke.tsv quick (60 s) +# generated by scripts/regress.py usage (names and counts only); impact: scripts/regress.py impact .. +kind name count +api vulkan 1 +key app_category 1 +key app_pool 1 +key build 1 +key ipa 1 +key mem_alias 1 +key mem_reserve 1 +key mem_stack 1 +key modules 1 +key name 1 +key package 1 +key pad_layout 1 +key program_id 1 +key romfs_marker 1 +key shader_note 1 +key shader_versions 1 +key title_id 1 +key zip_store 1 +present audio_out 1 +present display_link 1 +present nro_modules 1 +hle _ZN2nn2fs10CreateFileEPKcl 3 +hle _ZN2nn2fs10DeleteFileEPKc 3 +hle _ZN2nn2fs11GetFileSizeEPlNS0_10FileHandleE 1608 +hle _ZN2nn2fs12GetEntryTypeEPNS0_18DirectoryEntryTypeEPKc 8 +hle _ZN2nn2fs13MountSaveDataEPKcRKNS_7account3UidE 1 +hle _ZN2nn2fs13OpenDirectoryEPNS0_15DirectoryHandleEPKci 42 +hle _ZN2nn2fs13ReadDirectoryEPlPNS0_14DirectoryEntryENS0_15DirectoryHandleEl 42 +hle _ZN2nn2fs14CloseDirectoryENS0_15DirectoryHandleE 42 +hle _ZN2nn2fs14EnsureSaveDataERKNS_7account3UidE 1 +hle _ZN2nn2fs15CreateDirectoryEPKc 7 +hle _ZN2nn2fs22QueryMountRomCacheSizeEPm 1 +hle _ZN2nn2fs24InitializeForApplicationEv 1 +hle _ZN2nn2fs25EnableGlobalFileDataCacheEPvm 1 +hle _ZN2nn2fs6CommitEPKc 3 +hle _ZN2nn2fs8MountRomEPKcPvm 1 +hle _ZN2nn2fs8OpenFileEPNS0_10FileHandleEPKci 1625 +hle _ZN2nn2fs8ReadFileEPmNS0_10FileHandleElPvm 86909 +hle _ZN2nn2fs9CloseFileENS0_10FileHandleE 1612 +hle _ZN2nn2fs9FlushFileENS0_10FileHandleE 3 +hle _ZN2nn2fs9WriteFileENS0_10FileHandleElPKvmRKNS0_11WriteOptionE 3 +hle _ZN2nn2oe10InitializeEv 2 +hle _ZN2nn2oe15SetCpuBoostModeENS0_12CpuBoostModeE 2 +hle _ZN2nn2oe18GetDesiredLanguageEv 1 +hle _ZN2nn2oe27GetNotificationMessageEventEv 1 +hle _ZN2nn2oe27SetPerformanceConfigurationENS0_15PerformanceModeEi 1 +hle _ZN2nn2oe28SetResumeNotificationEnabledEb 1 +hle _ZN2nn2oe42SetOperationModeChangedNotificationEnabledEb 1 +hle _ZN2nn2ro10InitializeEv 1 +hle _ZN2nn2ro18RegisterModuleInfoEPNS0_16RegistrationInfoEPKv 1 +hle _ZN2nn2vi10InitializeEv 1 +hle _ZN2nn2vi11CreateLayerEPPNS0_5LayerEPNS0_7DisplayE 1 +hle _ZN2nn2vi15GetNativeWindowEPPvPNS0_5LayerE 2 +hle _ZN2nn2vi18OpenDefaultDisplayEPPNS0_7DisplayE 1 +hle _ZN2nn3aoc10InitializeEv 1 +hle _ZN2nn3hid12GetNpadStateEPNS0_16NpadFullKeyStateERKj 4938 +hle _ZN2nn3hid14InitializeNpadEv 1 +hle _ZN2nn3hid15GetNpadStyleSetERKj 9875 +hle _ZN2nn3hid18SetNpadJoyHoldTypeENS0_15NpadJoyHoldTypeE 1 +hle _ZN2nn3hid22GetVibrationDeviceInfoEPNS0_19VibrationDeviceInfoERKNS0_21VibrationDeviceHandleE 2 +hle _ZN2nn3hid22SetSupportedNpadIdTypeEPKjm 1 +hle _ZN2nn3hid24SetSupportedNpadStyleSetENS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid25GetVibrationDeviceHandlesEPNS0_21VibrationDeviceHandleEiRKjNS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid25InitializeVibrationDeviceERKNS0_21VibrationDeviceHandleE 2 +hle _ZN2nn3hid27BindNpadStyleSetUpdateEventERKjPNS_2os15SystemEventTypeENS3_14EventClearModeE 5 +hle _ZN2nn3hid6detail19SendVibrationValuesEPKNS0_21VibrationDeviceHandleEPKNS0_14VibrationValueEi 11936 +hle _ZN2nn3mem17StandardAllocator8AllocateEm 4406502 +hle _ZN2nn4diag34InitializeApplicationAbortObserverEv 1 +hle _ZN2nn4nifm10InitializeEv 1 +hle _ZN2nn4nifm18IsNetworkAvailableEv 707701 +hle _ZN2nn4nifm20CancelNetworkRequestEv 475591 +hle _ZN2nn4nifm20SubmitNetworkRequestEv 707702 +hle _ZN2nn4nifm22IsNetworkRequestOnHoldEv 951890659 +hle _ZN2nn4pctl10InitializeEv 1 +hle _ZN2nn4time10InitializeEv 1 +hle _ZN2nn4time23StandardUserSystemClock3nowEv 1 +hle _ZN2nn5audio13StartAudioOutEPNS0_8AudioOutE 1 +hle _ZN2nn5audio19OpenDefaultAudioOutEPNS0_8AudioOutEPNS_2os11SystemEventERKNS0_17AudioOutParameterE 1 +hle _ZN2nn5audio20AppendAudioOutBufferEPNS0_8AudioOutEPNS0_14AudioOutBufferE 2726 +hle _ZN2nn5audio21SetAudioOutBufferInfoEPNS0_14AudioOutBufferEPvmm 4 +hle _ZN2nn5audio25GetReleasedAudioOutBufferEPNS0_8AudioOutE 5444 +hle _ZN2nn5audio27InitializeAudioOutParameterEPNS0_17AudioOutParameterE 1 +hle _ZN2nn5audio28GetAudioOutBufferDataPointerEPKNS0_14AudioOutBufferE 2722 +hle _ZN2nn6socket10InitializeERKNS0_6ConfigE 1 +hle _ZN2nn7account10InitializeEv 1 +hle _ZN2nn7account17GetLastOpenedUserEPNS0_3UidE 1 +hle _ZN2nn7account22TryOpenPreselectedUserEPNS0_10UserHandleE 1 +hle _ZN2nv18InitializeGraphicsEPvm 1 +hle _ZN2nv20SetGraphicsAllocatorEPFPvmmS0_EPFvS0_S0_EPFS0_S0_mS0_ES0_ 1 +hle _ZN2nv28SetGraphicsDevtoolsAllocatorEPFPvmmS0_EPFvS0_S0_EPFS0_S0_mS0_ES0_ 1 +hle mktime 24 +hle nndiagStartup 1 +hle vkAcquireNextImageKHR 3526 +hle vkAllocateCommandBuffers 52 +hle vkAllocateDescriptorSets 173 +hle vkAllocateMemory 10 +hle vkBeginCommandBuffer 9012 +hle vkBindBufferMemory 11688 +hle vkBindImageMemory 486 +hle vkCmdBeginRenderPass 115833 +hle vkCmdBindDescriptorSets 981592 +hle vkCmdBindIndexBuffer 115833 +hle vkCmdBindPipeline 115833 +hle vkCmdBindVertexBuffers 115833 +hle vkCmdCopyBufferToImage 8614 +hle vkCmdDrawIndexed 772348 +hle vkCmdEndRenderPass 115833 +hle vkCmdPipelineBarrier 249285 +hle vkCmdSetScissor 115833 +hle vkCmdSetViewport 115833 +hle vkCreateBuffer 11688 +hle vkCreateBufferView 1 +hle vkCreateCommandPool 7 +hle vkCreateDescriptorPool 1 +hle vkCreateDescriptorSetLayout 173 +hle vkCreateDevice 1 +hle vkCreateFence 6 +hle vkCreateFramebuffer 11 +hle vkCreateGraphicsPipelines 1856 +hle vkCreateImage 486 +hle vkCreateImageView 588 +hle vkCreateInstance 1 +hle vkCreatePipelineLayout 58 +hle vkCreateRenderPass 1861 +hle vkCreateSampler 3 +hle vkCreateSemaphore 4 +hle vkCreateShaderModule 116 +hle vkCreateSwapchainKHR 2 +hle vkCreateViSurfaceNN 2 +hle vkDestroyBuffer 8614 +hle vkDestroyCommandPool 1 +hle vkDestroyImageView 9 +hle vkDestroyRenderPass 1856 +hle vkDestroySurfaceKHR 1 +hle vkDestroySwapchainKHR 1 +hle vkEndCommandBuffer 9012 +hle vkEnumerateDeviceExtensionProperties 4 +hle vkEnumerateDeviceLayerProperties 2 +hle vkEnumerateInstanceExtensionProperties 4 +hle vkEnumerateInstanceLayerProperties 2 +hle vkEnumeratePhysicalDevices 2 +hle vkFreeCommandBuffers 1 +hle vkGetDeviceQueue 3 +hle vkGetFenceStatus 9008 +hle vkGetInstanceProcAddr 26 +hle vkGetPhysicalDeviceFeatures2 3 +hle vkGetPhysicalDeviceFormatProperties 646 +hle vkGetPhysicalDeviceImageFormatProperties 1 +hle vkGetPhysicalDeviceMemoryProperties 2 +hle vkGetPhysicalDeviceProperties 1 +hle vkGetPhysicalDeviceProperties2 1 +hle vkGetPhysicalDeviceQueueFamilyProperties 18 +hle vkGetPhysicalDeviceSurfaceCapabilitiesKHR 2 +hle vkGetPhysicalDeviceSurfaceFormatsKHR 4 +hle vkGetPhysicalDeviceSurfacePresentModesKHR 4 +hle vkGetPhysicalDeviceSurfaceSupportKHR 4 +hle vkGetSwapchainImagesKHR 4 +hle vkMapMemory 3 +hle vkQueuePresentKHR 3525 +hle vkQueueSubmit 9012 +hle vkQueueWaitIdle 2 +hle vkResetCommandPool 9011 +hle vkResetFences 9008 +hle vkWaitForFences 2746 +svc 0x1 1 +svc 0x10 24366 +svc 0x17 12598 +svc 0x18 2723 +svc 0x1a 8845 +svc 0x1b 10932 +svc 0x1c 55418 +svc 0x1d 216425 +svc 0x25 17 +svc 0x29 19 +svc 0x2c 1 +svc 0x4 16 +svc 0x45 3 +svc 0x6 50 +svc 0x8 16 +svc 0x9 16 +svc 0xb 951904347 +svc 0xc 1 +svc 0xf 14 diff --git a/dm/games/01007EF00011E000/usage.tsv b/dm/games/01007EF00011E000/usage.tsv new file mode 100644 index 0000000..0d1820f --- /dev/null +++ b/dm/games/01007EF00011E000/usage.tsv @@ -0,0 +1,381 @@ +# kind: usage Zelda Breath of the Wild (01007EF00011E000), revision 89744da75364, chain 5cddc47253ab, route smoke.tsv quick (70 s) +# generated by scripts/regress.py usage (names and counts only); impact: scripts/regress.py impact .. +kind name count +api nvn 1 +key app_category 1 +key app_pool 1 +key build 1 +key fps_target 1 +key gpu_timestamps 1 +key ipa 1 +key mem_alias 1 +key mem_reserve 1 +key mem_stack 1 +key modules 1 +key name 1 +key package 1 +key pad_layout 1 +key present_snap 1 +key program_id 1 +key pso_mtl4 1 +key romfs_marker 1 +key shader_groups 1 +key shader_note 1 +key shader_versions 1 +key title_id 1 +key zip_store 1 +present audio_out 1 +present display_link 1 +present frame_step_vsync 1 +present pipeline_archive 1 +present pipeline_prepare 1 +present present_interval_changes 1 +present present_snapshots 1 +shader binding:c1 11612 +shader binding:cbuf 19023 +shader binding:drvcb 186 +shader binding:samp_tex 13205 +shader binding:sbuf 103 +shader binding:support 200 +shader binding:tex 13205 +shader binding:ubo_ptr 101 +shader binding_rw:sbuf 101 +shader depth_texture 1486 +shader device_buffer_write 9101 +shader discard 5923 +shader driver_read_c2 81 +shader gather 283 +shader integer_outputs 1901 +shader integer_vertex_inputs 1070 +shader layer_output 2 +shader lod_query 3174 +shader mixed_outputs 635 +shader note:texture handle # 23 +shader note:texture handle A 2 +shader position_invariant 8931 +shader pulling_vertex_inputs 8888 +shader readable_tile 6254 +shader sample_compare 1486 +shader stage:cs 101 +shader stage:ps 10560 +shader stage:vs 8931 +shader texture2d_array 2605 +shader texture3d 1307 +shader texture_cube 2558 +shader texture_ms 4 +shader threadgroup_memory 115 +shader vs_pad 5 +nvn nvnBlendStateSetBlendEquation 1506910 +nvn nvnBlendStateSetBlendFunc 1506910 +nvn nvnBlendStateSetBlendTarget 1506910 +nvn nvnBlendStateSetDefaults 1062848 +nvn nvnBufferBuilderSetDefaults 26976 +nvn nvnBufferBuilderSetDevice 26976 +nvn nvnBufferBuilderSetStorage 26976 +nvn nvnBufferFinalize 243 +nvn nvnBufferGetAddress 11847691 +nvn nvnBufferInitialize 26976 +nvn nvnBufferMap 868786 +nvn nvnBufferSetDebugLabel 18235 +nvn nvnChannelMaskStateSetChannelMask 8160288 +nvn nvnChannelMaskStateSetDefaults 2336 +nvn nvnColorStateSetBlendEnable 1506910 +nvn nvnColorStateSetDefaults 1062848 +nvn nvnColorStateSetLogicOp 1060512 +nvn nvnCommandBufferAddCommandMemory 232450 +nvn nvnCommandBufferAddControlMemory 232450 +nvn nvnCommandBufferBarrier 454579 +nvn nvnCommandBufferBeginRecording 232450 +nvn nvnCommandBufferBindBlendState 1867738 +nvn nvnCommandBufferBindChannelMaskState 1382908 +nvn nvnCommandBufferBindColorState 1423676 +nvn nvnCommandBufferBindDepthStencilState 1105261 +nvn nvnCommandBufferBindMultisampleState 87698 +nvn nvnCommandBufferBindPolygonState 1106089 +nvn nvnCommandBufferBindProgram 1605124 +nvn nvnCommandBufferBindStorageBuffer 662402 +nvn nvnCommandBufferBindTexture 3113548 +nvn nvnCommandBufferBindTexturesDeferred 379834 +nvn nvnCommandBufferBindUniformBuffer 8392436 +nvn nvnCommandBufferBindVertexAttribState 988708 +nvn nvnCommandBufferBindVertexBuffer 1372692 +nvn nvnCommandBufferBindVertexStreamState 988708 +nvn nvnCommandBufferCallCommands 7905218 +nvn nvnCommandBufferClearColor 40776 +nvn nvnCommandBufferClearDepthStencil 19643 +nvn nvnCommandBufferClearTexture 52225 +nvn nvnCommandBufferDispatchCompute 89336 +nvn nvnCommandBufferDrawArrays 1172 +nvn nvnCommandBufferDrawArraysInstanced 29330 +nvn nvnCommandBufferDrawElements 1066848 +nvn nvnCommandBufferDrawElementsBaseVertex 1865014 +nvn nvnCommandBufferDrawElementsInstanced 980795 +nvn nvnCommandBufferEndRecording 232450 +nvn nvnCommandBufferFinalize 228671 +nvn nvnCommandBufferGetCommandMemoryUsed 232436 +nvn nvnCommandBufferGetControlMemoryUsed 232436 +nvn nvnCommandBufferInitialize 228672 +nvn nvnCommandBufferReportCounter 19686 +nvn nvnCommandBufferResetCounter 830 +nvn nvnCommandBufferSetBlendColor 1380727 +nvn nvnCommandBufferSetDepthBounds 87698 +nvn nvnCommandBufferSetDepthClamp 1105261 +nvn nvnCommandBufferSetDepthRange 447830 +nvn nvnCommandBufferSetLineWidth 99222 +nvn nvnCommandBufferSetMemoryCallback 228672 +nvn nvnCommandBufferSetMemoryCallbackData 228672 +nvn nvnCommandBufferSetPointSize 97563 +nvn nvnCommandBufferSetPolygonOffsetClamp 1106089 +nvn nvnCommandBufferSetRasterizerDiscard 87698 +nvn nvnCommandBufferSetRenderTargets 466644 +nvn nvnCommandBufferSetSamplerPool 3779 +nvn nvnCommandBufferSetScissor 463326 +nvn nvnCommandBufferSetShaderScratchMemory 3779 +nvn nvnCommandBufferSetStencilMask 87698 +nvn nvnCommandBufferSetStencilRef 175396 +nvn nvnCommandBufferSetStencilValueMask 87698 +nvn nvnCommandBufferSetTexturePool 3779 +nvn nvnCommandBufferSetTiledCacheAction 20546 +nvn nvnCommandBufferSetTiledCacheTileSize 10273 +nvn nvnCommandBufferSetViewport 455954 +nvn nvnCommandBufferUpdateUniformBuffer 1009917 +nvn nvnDepthStencilStateSetDefaults 2169 +nvn nvnDepthStencilStateSetDepthFunc 1019732 +nvn nvnDepthStencilStateSetDepthTestEnable 1019732 +nvn nvnDepthStencilStateSetDepthWriteEnable 1019732 +nvn nvnDepthStencilStateSetStencilFunc 1021901 +nvn nvnDepthStencilStateSetStencilOp 1021901 +nvn nvnDepthStencilStateSetStencilTestEnable 1019732 +nvn nvnDeviceBuilderSetDefaults 1 +nvn nvnDeviceBuilderSetFlags 1 +nvn nvnDeviceGetInteger 123219 +nvn nvnDeviceGetProcAddress 1068 +nvn nvnDeviceGetTextureHandle 1780941 +nvn nvnDeviceGetTimestampInNanoseconds 15084 +nvn nvnDeviceInitialize 1 +nvn nvnDeviceRegisterFastClearColor 1 +nvn nvnDeviceSetWindowOriginMode 1 +nvn nvnMemoryPoolBuilderSetDefaults 3599 +nvn nvnMemoryPoolBuilderSetDevice 3599 +nvn nvnMemoryPoolBuilderSetFlags 3599 +nvn nvnMemoryPoolBuilderSetStorage 3599 +nvn nvnMemoryPoolFinalize 376 +nvn nvnMemoryPoolFlushMappedRange 34564 +nvn nvnMemoryPoolGetBufferAddress 227 +nvn nvnMemoryPoolGetFlags 652715 +nvn nvnMemoryPoolInitialize 3599 +nvn nvnMemoryPoolInvalidateMappedRange 25711 +nvn nvnMemoryPoolMap 1786764 +nvn nvnMemoryPoolMapVirtual 1 +nvn nvnMemoryPoolSetDebugLabel 393 +nvn nvnMultisampleStateSetAlphaToCoverageEnable 2169 +nvn nvnMultisampleStateSetDefaults 2169 +nvn nvnMultisampleStateSetMultisampleEnable 2169 +nvn nvnMultisampleStateSetSamples 2169 +nvn nvnPolygonStateSetCullFace 1020560 +nvn nvnPolygonStateSetDefaults 2169 +nvn nvnPolygonStateSetFrontFace 1020560 +nvn nvnPolygonStateSetPolygonMode 1020560 +nvn nvnPolygonStateSetPolygonOffsetEnables 1020560 +nvn nvnProgramFinalize 11 +nvn nvnProgramInitialize 7971 +nvn nvnProgramSetShaders 103 +nvn nvnProgramSetShadersExt 7868 +nvn nvnQueueBuilderGetQueueMemorySize 1 +nvn nvnQueueBuilderSetCommandMemorySize 1 +nvn nvnQueueBuilderSetComputeMemorySize 1 +nvn nvnQueueBuilderSetControlMemorySize 1 +nvn nvnQueueBuilderSetDefaults 1 +nvn nvnQueueBuilderSetDevice 1 +nvn nvnQueueBuilderSetFlags 1 +nvn nvnQueueBuilderSetQueueMemory 1 +nvn nvnQueueFenceSync 3765 +nvn nvnQueueFlush 3765 +nvn nvnQueueInitialize 1 +nvn nvnQueuePresentTexture 3765 +nvn nvnQueueSubmitCommands 3765 +nvn nvnSamplerBuilderSetBorderColor 118580 +nvn nvnSamplerBuilderSetCompare 118580 +nvn nvnSamplerBuilderSetDefaults 118581 +nvn nvnSamplerBuilderSetDevice 118581 +nvn nvnSamplerBuilderSetLodBias 118580 +nvn nvnSamplerBuilderSetLodClamp 118580 +nvn nvnSamplerBuilderSetMaxAnisotropy 112934 +nvn nvnSamplerBuilderSetMinMagFilter 118581 +nvn nvnSamplerBuilderSetReductionFilter 118580 +nvn nvnSamplerBuilderSetWrapMode 118580 +nvn nvnSamplerCompare 224587 +nvn nvnSamplerFinalize 112931 +nvn nvnSamplerInitialize 118581 +nvn nvnSamplerPoolInitialize 1 +nvn nvnSamplerPoolRegisterSampler 141 +nvn nvnSamplerSetDebugLabel 5580 +nvn nvnSyncInitialize 2 +nvn nvnSyncWait 7528 +nvn nvnTextureBuilderGetStorageAlignment 34792 +nvn nvnTextureBuilderGetStorageClass 34788 +nvn nvnTextureBuilderGetStorageSize 34791 +nvn nvnTextureBuilderSetDefaults 356496 +nvn nvnTextureBuilderSetDepth 356493 +nvn nvnTextureBuilderSetDepthStencilMode 353662 +nvn nvnTextureBuilderSetDevice 356496 +nvn nvnTextureBuilderSetFlags 356496 +nvn nvnTextureBuilderSetFormat 356496 +nvn nvnTextureBuilderSetHeight 356493 +nvn nvnTextureBuilderSetLevels 356493 +nvn nvnTextureBuilderSetPackagedTextureLayout 2829 +nvn nvnTextureBuilderSetSamples 353662 +nvn nvnTextureBuilderSetSize2D 3 +nvn nvnTextureBuilderSetStorage 321706 +nvn nvnTextureBuilderSetStride 1393 +nvn nvnTextureBuilderSetSwizzle 353662 +nvn nvnTextureBuilderSetTarget 356496 +nvn nvnTextureBuilderSetWidth 356493 +nvn nvnTextureCompare 318874 +nvn nvnTextureFinalize 397091 +nvn nvnTextureFlushTexels 148 +nvn nvnTextureGetFlags 74773 +nvn nvnTextureGetZCullStorageSize 27763 +nvn nvnTextureInitialize 321706 +nvn nvnTexturePoolInitialize 1 +nvn nvnTexturePoolRegisterTexture 156809 +nvn nvnTextureViewSetDefaults 95939 +nvn nvnTextureViewSetDepthStencilMode 2830 +nvn nvnTextureViewSetFormat 6659 +nvn nvnTextureViewSetLayers 511734 +nvn nvnTextureViewSetLevels 511735 +nvn nvnTextureViewSetSwizzle 81689 +nvn nvnTextureViewSetTarget 2893 +nvn nvnTextureWriteTexels 148 +nvn nvnVertexAttribStateSetDefaults 337464 +nvn nvnVertexAttribStateSetFormat 144226 +nvn nvnVertexAttribStateSetStreamIndex 144226 +nvn nvnVertexStreamStateSetDefaults 79534 +nvn nvnVertexStreamStateSetDivisor 78670 +nvn nvnVertexStreamStateSetStride 78724 +nvn nvnWindowAcquireTexture 3765 +nvn nvnWindowBuilderSetDefaults 1 +nvn nvnWindowBuilderSetDevice 1 +nvn nvnWindowBuilderSetNativeWindow 1 +nvn nvnWindowBuilderSetPresentInterval 1 +nvn nvnWindowBuilderSetTextures 1 +nvn nvnWindowInitialize 1 +nvn nvnWindowSetCrop 1 +nvn nvnWindowSetPresentInterval 3778 +hle _ZN2nn2fs11GetFileSizeEPlNS0_10FileHandleE 1297 +hle _ZN2nn2fs11SetFileSizeENS0_10FileHandleEl 2 +hle _ZN2nn2fs12GetEntryTypeEPNS0_18DirectoryEntryTypeEPKc 3 +hle _ZN2nn2fs13MountSaveDataEPKcRKNS_7account3UidE 1 +hle _ZN2nn2fs14CommitSaveDataEPKc 2 +hle _ZN2nn2fs17MountAddOnContentEPKciPvm 1 +hle _ZN2nn2fs22QueryMountRomCacheSizeEPm 1 +hle _ZN2nn2fs24InitializeForApplicationEv 1 +hle _ZN2nn2fs31QueryMountAddOnContentCacheSizeEPmi 1 +hle _ZN2nn2fs8MountRomEPKcPvm 1 +hle _ZN2nn2fs8OpenFileEPNS0_10FileHandleEPKci 1427 +hle _ZN2nn2fs8ReadFileEPmNS0_10FileHandleElPvm 14 +hle _ZN2nn2fs8ReadFileEPmNS0_10FileHandleElPvmRKNS0_10ReadOptionE 1760 +hle _ZN2nn2fs9CloseFileENS0_10FileHandleE 1423 +hle _ZN2nn2fs9FlushFileENS0_10FileHandleE 2 +hle _ZN2nn2fs9WriteFileENS0_10FileHandleElPKvmRKNS0_11WriteOptionE 2 +hle _ZN2nn2oe10InitializeEv 3 +hle _ZN2nn2oe15EnableRecordingEv 1 +hle _ZN2nn2oe15SetCpuBoostModeENS0_12CpuBoostModeE 7 +hle _ZN2nn2oe16GetOperationModeEv 2 +hle _ZN2nn2oe17FinishStartupLogoEv 1 +hle _ZN2nn2oe18GetDesiredLanguageEv 2 +hle _ZN2nn2oe18GetPerformanceModeEv 1 +hle _ZN2nn2oe20SetFocusHandlingModeENS0_17FocusHandlingModeE 1 +hle _ZN2nn2oe21TryPopLaunchParameterEPmPvm 1 +hle _ZN2nn2oe25TryPopNotificationMessageEPj 3779 +hle _ZN2nn2oe27SetPerformanceConfigurationENS0_15PerformanceModeEi 2 +hle _ZN2nn2oe28SetResumeNotificationEnabledEb 1 +hle _ZN2nn2oe42SetOperationModeChangedNotificationEnabledEb 1 +hle _ZN2nn2oe44SetPerformanceModeChangedNotificationEnabledEb 1 +hle _ZN2nn2pl16IsRunningOnOunceEv 3866 +hle _ZN2nn2pl8IsVrModeEv 3764 +hle _ZN2nn2pl9EndVrModeEv 1 +hle _ZN2nn2vi10InitializeEv 1 +hle _ZN2nn2vi11CreateLayerEPPNS0_5LayerEPNS0_7DisplayE 1 +hle _ZN2nn2vi15GetNativeWindowEPPvPNS0_5LayerE 1 +hle _ZN2nn2vi18OpenDefaultDisplayEPPNS0_7DisplayE 1 +hle _ZN2nn2vi20GetDisplayVsyncEventEPNS_2os15SystemEventTypeEPNS0_7DisplayE 1 +hle _ZN2nn3aoc10InitializeEv 1 +hle _ZN2nn3aoc16ListAddOnContentEPiii 1 +hle _ZN2nn3err26InitializeContextWriterApiEv 1 +hle _ZN2nn3hid13GetNpadStatesEPNS0_16NpadFullKeyStateEiRKj 3775 +hle _ZN2nn3hid14InitializeNpadEv 1 +hle _ZN2nn3hid15GetNpadStyleSetERKj 11379 +hle _ZN2nn3hid18SendVibrationValueERKNS0_21VibrationDeviceHandleERKNS0_14VibrationValueE 4 +hle _ZN2nn3hid18SetNpadJoyHoldTypeENS0_15NpadJoyHoldTypeE 1 +hle _ZN2nn3hid18StartSixAxisSensorERKNS0_19SixAxisSensorHandleE 1 +hle _ZN2nn3hid22GetSixAxisSensorStatesEPNS0_18SixAxisSensorStateEiRKNS0_19SixAxisSensorHandleE 3775 +hle _ZN2nn3hid22SetSupportedNpadIdTypeEPKjm 1 +hle _ZN2nn3hid22StopSevenSixAxisSensorEv 1 +hle _ZN2nn3hid23GetSixAxisSensorHandlesEPNS0_19SixAxisSensorHandleEiRKjNS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid24SetSupportedNpadStyleSetENS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 2 +hle _ZN2nn3hid25GetVibrationDeviceHandlesEPNS0_21VibrationDeviceHandleEiRKjNS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid25InitializeVibrationDeviceERKNS0_21VibrationDeviceHandleE 2 +hle _ZN2nn3hid25SetGyroscopeZeroDriftModeERKNS0_19SixAxisSensorHandleERKNS0_22GyroscopeZeroDriftModeE 1 +hle _ZN2nn3hid28InitializeSevenSixAxisSensorEPvm 1 +hle _ZN2nn3hid28SetNpadJoyAssignmentModeDualERKj 2 +hle _ZN2nn3mem17StandardAllocator8AllocateEm 1 +hle _ZN2nn3nfp8FinalizeEv 2 +hle _ZN2nn3nfp8GetStateEv 673 +hle _ZN2nn4diag34InitializeApplicationAbortObserverEv 1 +hle _ZN2nn4diag6detail7PutImplERKNS0_11LogMetaDataEPKcm 1 +hle _ZN2nn4pctl10InitializeEv 1 +hle _ZN2nn4time10InitializeEv 2 +hle _ZN2nn4time13IsInitializedEv 1 +hle _ZN2nn4time14ToCalendarTimeEPNS0_12CalendarTimeEPNS0_22CalendarAdditionalInfoERKNS0_9PosixTimeE 3 +hle _ZN2nn4time19StandardSteadyClock19GetCurrentTimePointEPNS0_20SteadyClockTimePointE 1 +hle _ZN2nn4time23StandardUserSystemClock14GetCurrentTimeEPNS0_9PosixTimeE 3 +hle _ZN2nn4time41GetStandardUserSystemClockCurrentTimespecEP8timespec 1 +hle _ZN2nn5audio17OpenAudioRendererEPNS0_19AudioRendererHandleEPNS_2os11SystemEventERKNS0_22AudioRendererParameterEPvm 1 +hle _ZN2nn5audio17OpenAudioRendererEPNS0_19AudioRendererHandleERKNS0_22AudioRendererParameterEPvm 1 +hle _ZN2nn5audio19ListAudioDeviceNameEPNS0_15AudioDeviceNameEi 1 +hle _ZN2nn5audio26SetAudioDeviceOutputVolumeEPKNS0_15AudioDeviceNameEf 3 +hle _ZN2nn5audio30GetAudioRendererWorkBufferSizeERKNS0_22AudioRendererParameterE 3 +hle _ZN2nn5audio39AcquireAudioDeviceNotificationForOutputEPNS_2os11SystemEventE 1 +hle _ZN2nn5audio41GetActiveAudioDeviceChannelCountForOutputEv 1 +hle _ZN2nn5audio6server17AudioRenderSystem29ExecuteAudioRendererRenderingEv 13618 +hle _ZN2nn5audio6server17AudioRenderSystem6UpdateEPvmS3_mPKvm 13614 +hle _ZN2nn5prepo10PlayReport4SaveERKNS_7account3UidE 19 +hle _ZN2nn6applet23GetAppletResourceUserIdEv 1 +hle _ZN2nn7account10InitializeEv 2 +hle _ZN2nn7account12ListAllUsersEPiPNS0_3UidEi 1 +hle _ZN2nn7account22TryOpenPreselectedUserEPNS0_10UserHandleE 1 +hle _ZN2nn7account9GetUserIdEPNS0_3UidERKNS0_10UserHandleE 20 +hle _ZN2nv18InitializeGraphicsEPvm 1 +hle _ZN2nv20SetGraphicsAllocatorEPFPvmmS0_EPFvS0_S0_EPFS0_S0_mS0_ES0_ 1 +hle nndiagStartup 1 +hle nvnBootstrapLoader 2 +svc 0x1 1 +svc 0x10 38 +svc 0x11 13618 +svc 0x16 4 +svc 0x17 13626 +svc 0x18 17402 +svc 0x1a 105606 +svc 0x1b 349924 +svc 0x1c 251571 +svc 0x1d 251534 +svc 0x2 3 +svc 0x25 44 +svc 0x29 63 +svc 0x2c 1 +svc 0x3 6 +svc 0x34 92929 +svc 0x35 86016 +svc 0x4 43 +svc 0x45 3 +svc 0x5 4 +svc 0x6 133 +svc 0x8 43 +svc 0x9 42 +svc 0xa 4 +svc 0xb 6871070 +svc 0xc 1 +svc 0xd 3 +svc 0xe 4 +svc 0xf 41 diff --git a/dm/games/0100F2C0115B6000/usage.tsv b/dm/games/0100F2C0115B6000/usage.tsv new file mode 100644 index 0000000..62e264d --- /dev/null +++ b/dm/games/0100F2C0115B6000/usage.tsv @@ -0,0 +1,421 @@ +# kind: usage Zelda Tears of the Kingdom (0100F2C0115B6000), revision 89744da75364, chain 5cddc47253ab, route smoke.tsv quick (60 s) +# generated by scripts/regress.py usage (names and counts only); impact: scripts/regress.py impact .. +kind name count +api nvn 1 +key app_category 1 +key app_pool 1 +key build 1 +key fps_target 1 +key ipa 1 +key mem_alias 1 +key mem_reserve 1 +key mem_stack 1 +key modules 1 +key name 1 +key package 1 +key pad_layout 1 +key program_id 1 +key render_cond 1 +key romfs_marker 1 +key shader_groups 1 +key shader_note 1 +key shader_versions 1 +key tex_dirty_upload 1 +key tex_flush_upload 1 +key title_id 1 +key zip_store 1 +present audio_out 1 +present display_link 1 +present frame_step_vsync 1 +present pipeline_archive 1 +present pipeline_prepare 1 +shader binding:c1 16824 +shader binding:cbuf 28079 +shader binding:drvcb 407 +shader binding:img 26 +shader binding:samp_tex 21248 +shader binding:sbuf 6093 +shader binding:sbuf_ubo 21 +shader binding:support 3620 +shader binding:tex 21248 +shader binding:ubo_ptr 181 +shader binding_rw:sbuf 2902 +shader buffer_atomic 406 +shader depth_texture 2510 +shader device_buffer_write 17865 +shader discard 8232 +shader driver_read_c0 30 +shader gather 607 +shader gradient 26 +shader image_atomic 2 +shader image_atomic_result 2 +shader integer_outputs 4951 +shader integer_vertex_inputs 1954 +shader layer_output 17 +shader lod_query 2827 +shader mixed_outputs 1189 +shader note:FP# lowered to FP# 30 +shader note:texture handle # 45 +shader note:texture handle #A 4 +shader note:texture handle #C 2 +shader note:texture handle #E 4 +shader note:texture handle A 316 +shader note:texture handle C 226 +shader note:translator: Failed to find storage buffer for global memory operation "…". 1 +shader note:visibility counter lowered to singleton groups 1 +shader position_invariant 14766 +shader pulling_vertex_inputs 14549 +shader readable_tile 8380 +shader sample_compare 2510 +shader simd 32 +shader stage:cs 257 +shader stage:ps 13646 +shader stage:vs 14766 +shader texture2d_array 4093 +shader texture3d 2938 +shader texture_cube 4009 +shader texture_ms 3 +shader texture_write 24 +shader threadgroup_memory 278 +shader vs_pad 387 +nvn nvnBlendStateSetBlendEquation 764189 +nvn nvnBlendStateSetBlendFunc 764189 +nvn nvnBlendStateSetBlendTarget 764189 +nvn nvnBlendStateSetDefaults 304086 +nvn nvnBufferBuilderSetDefaults 223164 +nvn nvnBufferBuilderSetDevice 223164 +nvn nvnBufferBuilderSetStorage 223164 +nvn nvnBufferFinalize 195521 +nvn nvnBufferGetAddress 2104519 +nvn nvnBufferInitialize 223164 +nvn nvnBufferMap 572484 +nvn nvnBufferSetDebugLabel 7141 +nvn nvnChannelMaskStateSetChannelMask 2459829 +nvn nvnChannelMaskStateSetDefaults 2429 +nvn nvnColorStateSetBlendEnable 764189 +nvn nvnColorStateSetDefaults 304086 +nvn nvnColorStateSetLogicOp 301657 +nvn nvnCommandBufferAddCommandMemory 135534 +nvn nvnCommandBufferAddControlMemory 135534 +nvn nvnCommandBufferBarrier 277173 +nvn nvnCommandBufferBeginRecording 135534 +nvn nvnCommandBufferBindBlendState 1043879 +nvn nvnCommandBufferBindChannelMaskState 589294 +nvn nvnCommandBufferBindColorState 583776 +nvn nvnCommandBufferBindDepthStencilState 366026 +nvn nvnCommandBufferBindMultisampleState 62518 +nvn nvnCommandBufferBindPolygonState 364175 +nvn nvnCommandBufferBindProgram 821223 +nvn nvnCommandBufferBindStorageBuffer 251699 +nvn nvnCommandBufferBindTexture 1667780 +nvn nvnCommandBufferBindTexturesDeferred 433722 +nvn nvnCommandBufferBindUniformBuffer 2252449 +nvn nvnCommandBufferBindVertexAttribState 393254 +nvn nvnCommandBufferBindVertexBuffer 723118 +nvn nvnCommandBufferBindVertexStreamState 393254 +nvn nvnCommandBufferCallCommands 1332361 +nvn nvnCommandBufferClearColor 108970 +nvn nvnCommandBufferClearDepthStencil 25645 +nvn nvnCommandBufferCopyBufferToBuffer 1851 +nvn nvnCommandBufferDispatchCompute 36575 +nvn nvnCommandBufferDrawArrays 248 +nvn nvnCommandBufferDrawArraysInstanced 14644 +nvn nvnCommandBufferDrawElements 533967 +nvn nvnCommandBufferDrawElementsBaseVertex 198101 +nvn nvnCommandBufferDrawElementsInstanced 873896 +nvn nvnCommandBufferEndRecording 135534 +nvn nvnCommandBufferFinalize 132829 +nvn nvnCommandBufferGetCommandMemoryUsed 135534 +nvn nvnCommandBufferGetControlMemoryUsed 135534 +nvn nvnCommandBufferInitialize 132830 +nvn nvnCommandBufferReportCounter 313873 +nvn nvnCommandBufferResetCounter 224054 +nvn nvnCommandBufferSetBlendColor 583776 +nvn nvnCommandBufferSetCommandMemoryCallbackEnabled 11111 +nvn nvnCommandBufferSetDepthBounds 62518 +nvn nvnCommandBufferSetDepthClamp 364175 +nvn nvnCommandBufferSetDepthRange 285777 +nvn nvnCommandBufferSetLineWidth 83833 +nvn nvnCommandBufferSetMemoryCallback 132830 +nvn nvnCommandBufferSetMemoryCallbackData 132830 +nvn nvnCommandBufferSetPointSize 85726 +nvn nvnCommandBufferSetPolygonOffsetClamp 364175 +nvn nvnCommandBufferSetRasterizerDiscard 62518 +nvn nvnCommandBufferSetRenderEnable 69969 +nvn nvnCommandBufferSetRenderEnableConditional 76294 +nvn nvnCommandBufferSetRenderTargets 312347 +nvn nvnCommandBufferSetSamplerPool 2705 +nvn nvnCommandBufferSetScissor 286507 +nvn nvnCommandBufferSetShaderScratchMemory 2705 +nvn nvnCommandBufferSetStencilMask 62518 +nvn nvnCommandBufferSetStencilRef 125036 +nvn nvnCommandBufferSetStencilValueMask 62518 +nvn nvnCommandBufferSetTexturePool 2705 +nvn nvnCommandBufferSetTiledCacheAction 3702 +nvn nvnCommandBufferSetTiledCacheTileSize 1851 +nvn nvnCommandBufferSetViewport 285777 +nvn nvnCommandBufferSignalEvent 13520 +nvn nvnCommandBufferUpdateUniformBuffer 502258 +nvn nvnDepthStencilStateSetDefaults 2326 +nvn nvnDepthStencilStateSetDepthFunc 305834 +nvn nvnDepthStencilStateSetDepthTestEnable 305834 +nvn nvnDepthStencilStateSetDepthWriteEnable 305834 +nvn nvnDepthStencilStateSetStencilFunc 308160 +nvn nvnDepthStencilStateSetStencilOp 308160 +nvn nvnDepthStencilStateSetStencilTestEnable 305834 +nvn nvnDeviceBuilderSetDefaults 1 +nvn nvnDeviceBuilderSetFlags 1 +nvn nvnDeviceGetInteger 80073 +nvn nvnDeviceGetProcAddress 1068 +nvn nvnDeviceGetTextureHandle 2196597 +nvn nvnDeviceGetTimestampInNanoseconds 10814 +nvn nvnDeviceInitialize 1 +nvn nvnDeviceRegisterFastClearColor 2 +nvn nvnDeviceRegisterFastClearDepth 1 +nvn nvnDeviceSetDepthMode 1 +nvn nvnDeviceSetWindowOriginMode 1 +nvn nvnEventBuilderSetDefaults 7 +nvn nvnEventBuilderSetStorage 7 +nvn nvnEventInitialize 7 +nvn nvnMemoryPoolBuilderSetDefaults 1593 +nvn nvnMemoryPoolBuilderSetDevice 1593 +nvn nvnMemoryPoolBuilderSetFlags 1593 +nvn nvnMemoryPoolBuilderSetStorage 1593 +nvn nvnMemoryPoolFinalize 26 +nvn nvnMemoryPoolFlushMappedRange 13781 +nvn nvnMemoryPoolGetBufferAddress 70 +nvn nvnMemoryPoolGetFlags 1109168 +nvn nvnMemoryPoolInitialize 1593 +nvn nvnMemoryPoolInvalidateMappedRange 24106 +nvn nvnMemoryPoolMap 1131 +nvn nvnMemoryPoolMapVirtual 1 +nvn nvnMemoryPoolSetDebugLabel 59 +nvn nvnMultisampleStateSetAlphaToCoverageEnable 2322 +nvn nvnMultisampleStateSetDefaults 2322 +nvn nvnMultisampleStateSetMultisampleEnable 2322 +nvn nvnMultisampleStateSetSamples 2322 +nvn nvnPolygonStateSetCullFace 303979 +nvn nvnPolygonStateSetDefaults 2322 +nvn nvnPolygonStateSetFrontFace 303979 +nvn nvnPolygonStateSetPolygonMode 303979 +nvn nvnPolygonStateSetPolygonOffsetEnables 303979 +nvn nvnProgramFinalize 11 +nvn nvnProgramInitialize 3559 +nvn nvnProgramSetShaders 113 +nvn nvnProgramSetShadersExt 3446 +nvn nvnQueueBuilderGetQueueMemorySize 1 +nvn nvnQueueBuilderSetCommandMemorySize 1 +nvn nvnQueueBuilderSetComputeMemorySize 1 +nvn nvnQueueBuilderSetControlMemorySize 1 +nvn nvnQueueBuilderSetDefaults 1 +nvn nvnQueueBuilderSetDevice 1 +nvn nvnQueueBuilderSetFlags 1 +nvn nvnQueueBuilderSetQueueMemory 1 +nvn nvnQueueFenceSync 2705 +nvn nvnQueueFlush 2705 +nvn nvnQueueInitialize 1 +nvn nvnQueuePresentTexture 2704 +nvn nvnQueueSubmitCommands 2705 +nvn nvnSamplerBuilderSetBorderColor 2117 +nvn nvnSamplerBuilderSetCompare 2117 +nvn nvnSamplerBuilderSetDefaults 2118 +nvn nvnSamplerBuilderSetDevice 2118 +nvn nvnSamplerBuilderSetLodBias 2117 +nvn nvnSamplerBuilderSetLodClamp 2117 +nvn nvnSamplerBuilderSetMaxAnisotropy 175 +nvn nvnSamplerBuilderSetMinMagFilter 2118 +nvn nvnSamplerBuilderSetReductionFilter 2117 +nvn nvnSamplerBuilderSetWrapMode 2117 +nvn nvnSamplerFinalize 32 +nvn nvnSamplerInitialize 2118 +nvn nvnSamplerPoolInitialize 1 +nvn nvnSamplerPoolRegisterSampler 163 +nvn nvnSamplerSetDebugLabel 1917 +nvn nvnSyncInitialize 7 +nvn nvnSyncWait 5407 +nvn nvnTextureBuilderGetStorageAlignment 9136 +nvn nvnTextureBuilderGetStorageClass 795 +nvn nvnTextureBuilderGetStorageSize 62753 +nvn nvnTextureBuilderGetZCullStorageSize 38557 +nvn nvnTextureBuilderSetDefaults 104444 +nvn nvnTextureBuilderSetDepth 104440 +nvn nvnTextureBuilderSetDepthStencilMode 102100 +nvn nvnTextureBuilderSetDevice 104444 +nvn nvnTextureBuilderSetFlags 104444 +nvn nvnTextureBuilderSetFormat 104444 +nvn nvnTextureBuilderSetHeight 104440 +nvn nvnTextureBuilderSetLevels 104440 +nvn nvnTextureBuilderSetPackagedTextureLayout 1513 +nvn nvnTextureBuilderSetSamples 102100 +nvn nvnTextureBuilderSetSize2D 4 +nvn nvnTextureBuilderSetStorage 55959 +nvn nvnTextureBuilderSetStride 101 +nvn nvnTextureBuilderSetSwizzle 102100 +nvn nvnTextureBuilderSetTarget 104444 +nvn nvnTextureBuilderSetWidth 104440 +nvn nvnTextureFinalize 52680 +nvn nvnTextureFlushTexels 69 +nvn nvnTextureGetFlags 89862 +nvn nvnTextureGetHeight 14 +nvn nvnTextureGetViewOffset 10708 +nvn nvnTextureGetWidth 14 +nvn nvnTextureInitialize 55959 +nvn nvnTexturePoolInitialize 1 +nvn nvnTexturePoolRegisterTexture 89848 +nvn nvnTextureReadTexels 25 +nvn nvnTextureSetDebugLabel 1 +nvn nvnTextureViewSetDefaults 322595 +nvn nvnTextureViewSetDepthStencilMode 2338 +nvn nvnTextureViewSetFormat 5393 +nvn nvnTextureViewSetLayers 287525 +nvn nvnTextureViewSetLevels 297112 +nvn nvnTextureViewSetSwizzle 35005 +nvn nvnTextureViewSetTarget 2689 +nvn nvnTextureWriteTexels 87 +nvn nvnVertexAttribStateSetDefaults 37424 +nvn nvnVertexAttribStateSetFormat 32755 +nvn nvnVertexAttribStateSetStreamIndex 32755 +nvn nvnVertexStreamStateSetDefaults 28052 +nvn nvnVertexStreamStateSetDivisor 26196 +nvn nvnVertexStreamStateSetStride 26310 +nvn nvnWindowAcquireTexture 2704 +nvn nvnWindowBuilderSetDefaults 1 +nvn nvnWindowBuilderSetDevice 1 +nvn nvnWindowBuilderSetNativeWindow 1 +nvn nvnWindowBuilderSetNumActiveTextures 1 +nvn nvnWindowBuilderSetPresentInterval 1 +nvn nvnWindowBuilderSetTextures 1 +nvn nvnWindowInitialize 1 +nvn nvnWindowSetCrop 1 +hle _ZN2nn2fs10CreateFileEPKcl 1 +hle _ZN2nn2fs11GetFileSizeEPlNS0_10FileHandleE 1701 +hle _ZN2nn2fs11SetFileSizeENS0_10FileHandleEl 2 +hle _ZN2nn2fs12GetEntryTypeEPNS0_18DirectoryEntryTypeEPKc 1445 +hle _ZN2nn2fs13MountSaveDataEPKcRKNS_7account3UidE 1 +hle _ZN2nn2fs15CreateDirectoryEPKc 1 +hle _ZN2nn2fs17MountCacheStorageEPKci 2 +hle _ZN2nn2fs18CreateCacheStorageEill 1 +hle _ZN2nn2fs18IsSaveDataExistingENS_13ApplicationIdERKNS_7account3UidE 1 +hle _ZN2nn2fs20OpenCacheStorageListEPNS0_22CacheStorageListHandleE 1 +hle _ZN2nn2fs20ReadCacheStorageListEPiPNS0_16CacheStorageInfoENS0_22CacheStorageListHandleEi 1 +hle _ZN2nn2fs21CloseCacheStorageListENS0_22CacheStorageListHandleE 1 +hle _ZN2nn2fs21MountTemporaryStorageEPKc 1 +hle _ZN2nn2fs22QueryMountRomCacheSizeEPm 1 +hle _ZN2nn2fs24InitializeForApplicationEv 1 +hle _ZN2nn2fs26SetPriorityOnCurrentThreadENS0_8PriorityE 1 +hle _ZN2nn2fs6CommitEPKc 3 +hle _ZN2nn2fs7UnmountEPKc 1 +hle _ZN2nn2fs8MountRomEPKcPvm 1 +hle _ZN2nn2fs8OpenFileEPNS0_10FileHandleEPKci 4793 +hle _ZN2nn2fs8ReadFileEPmNS0_10FileHandleElPvm 68 +hle _ZN2nn2fs8ReadFileEPmNS0_10FileHandleElPvmRKNS0_10ReadOptionE 2805 +hle _ZN2nn2fs9CloseFileENS0_10FileHandleE 2737 +hle _ZN2nn2fs9FlushFileENS0_10FileHandleE 3 +hle _ZN2nn2fs9WriteFileENS0_10FileHandleElPKvmRKNS0_11WriteOptionE 3 +hle _ZN2nn2oe10InitializeEv 2 +hle _ZN2nn2oe15SetCpuBoostModeENS0_12CpuBoostModeE 18 +hle _ZN2nn2oe16GetOperationModeEv 2 +hle _ZN2nn2oe17FinishStartupLogoEv 1 +hle _ZN2nn2oe18GetDesiredLanguageEv 2 +hle _ZN2nn2oe18GetPerformanceModeEv 1 +hle _ZN2nn2oe20GetCurrentFocusStateEv 1 +hle _ZN2nn2oe20SetFocusHandlingModeENS0_17FocusHandlingModeE 1 +hle _ZN2nn2oe21TryPopLaunchParameterEPmPvm 1 +hle _ZN2nn2oe23GetPreviousProgramIndexEv 1 +hle _ZN2nn2oe24GetExpectedVolumeBalanceEPfS1_ 1 +hle _ZN2nn2oe24SetExpectedVolumeBalanceEff 1 +hle _ZN2nn2oe25GetProgramTotalActiveTimeEv 1 +hle _ZN2nn2oe25TryPopNotificationMessageEPj 2705 +hle _ZN2nn2oe27SetPerformanceConfigurationENS0_15PerformanceModeEi 1 +hle _ZN2nn2oe28SetResumeNotificationEnabledEb 1 +hle _ZN2nn2oe38SetUserInactivityDetectionTimeExtendedEb 2 +hle _ZN2nn2oe42SetOperationModeChangedNotificationEnabledEb 2 +hle _ZN2nn2oe44SetPerformanceModeChangedNotificationEnabledEb 2 +hle _ZN2nn2pl16IsRunningOnOunceEv 1 +hle _ZN2nn2vi10InitializeEv 1 +hle _ZN2nn2vi11CreateLayerEPPNS0_5LayerEPNS0_7DisplayE 1 +hle _ZN2nn2vi15GetNativeWindowEPPvPNS0_5LayerE 1 +hle _ZN2nn2vi18OpenDefaultDisplayEPPNS0_7DisplayE 1 +hle _ZN2nn2vi20GetDisplayVsyncEventEPNS_2os15SystemEventTypeEPNS0_7DisplayE 1 +hle _ZN2nn3aoc10InitializeEv 1 +hle _ZN2nn3aoc16ListAddOnContentEPiii 1 +hle _ZN2nn3err26InitializeContextWriterApiEv 1 +hle _ZN2nn3hid13GetNpadStatesEPNS0_16NpadFullKeyStateEiRKj 4517 +hle _ZN2nn3hid14DisconnectNpadERKj 3 +hle _ZN2nn3hid14InitializeNpadEv 1 +hle _ZN2nn3hid15GetNpadStyleSetERKj 13551 +hle _ZN2nn3hid15InitializeMouseEv 1 +hle _ZN2nn3hid18InitializeKeyboardEv 1 +hle _ZN2nn3hid18SetNpadJoyHoldTypeENS0_15NpadJoyHoldTypeE 1 +hle _ZN2nn3hid18StartSixAxisSensorERKNS0_19SixAxisSensorHandleE 1 +hle _ZN2nn3hid22GetSixAxisSensorStatesEPNS0_18SixAxisSensorStateEiRKNS0_19SixAxisSensorHandleE 4517 +hle _ZN2nn3hid22SetSupportedNpadIdTypeEPKjm 1 +hle _ZN2nn3hid23GetSixAxisSensorHandlesEPNS0_19SixAxisSensorHandleEiRKjNS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid24SetSupportedNpadStyleSetENS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 2 +hle _ZN2nn3hid25GetVibrationDeviceHandlesEPNS0_21VibrationDeviceHandleEiRKjNS_4util10BitFlagSetILi32ENS0_12NpadStyleTagEEE 1 +hle _ZN2nn3hid25InitializeVibrationDeviceERKNS0_21VibrationDeviceHandleE 2 +hle _ZN2nn3hid6detail19SendVibrationValuesEPKNS0_21VibrationDeviceHandleEPKNS0_14VibrationValueEi 5805 +hle _ZN2nn3mem17StandardAllocator8AllocateEm 1 +hle _ZN2nn3nfp8GetStateEv 1 +hle _ZN2nn4diag34InitializeApplicationAbortObserverEv 1 +hle _ZN2nn4diag6detail7PutImplERKNS0_11LogMetaDataEPKcm 1 +hle _ZN2nn4pctl10InitializeEv 1 +hle _ZN2nn4time10InitializeEv 2 +hle _ZN2nn4time13ClockSnapshot29CreateWithStandardSystemClockEPS1_ 1 +hle _ZN2nn4time13IsInitializedEv 1 +hle _ZN2nn4time14ToCalendarTimeEPNS0_12CalendarTimeEPNS0_22CalendarAdditionalInfoERKNS0_9PosixTimeE 1 +hle _ZN2nn4time23StandardUserSystemClock14GetCurrentTimeEPNS0_9PosixTimeE 1 +hle _ZN2nn4time26StandardNetworkSystemClock14GetCurrentTimeEPNS0_9PosixTimeE 2 +hle _ZN2nn4time41GetStandardUserSystemClockCurrentTimespecEP8timespec 1 +hle _ZN2nn5audio17OpenAudioRendererEPNS0_19AudioRendererHandleEPNS_2os11SystemEventERKNS0_22AudioRendererParameterEPvm 1 +hle _ZN2nn5audio17OpenAudioRendererEPNS0_19AudioRendererHandleERKNS0_22AudioRendererParameterEPvm 1 +hle _ZN2nn5audio25ListAudioOutputDeviceNameEPNS0_15AudioDeviceNameEi 1 +hle _ZN2nn5audio26SetAudioDeviceOutputVolumeEPKNS0_15AudioDeviceNameEf 6 +hle _ZN2nn5audio30GetActiveAudioOutputDeviceNameEPNS0_15AudioDeviceNameE 1 +hle _ZN2nn5audio30GetAudioRendererWorkBufferSizeERKNS0_22AudioRendererParameterE 1 +hle _ZN2nn5audio39AcquireAudioDeviceNotificationForOutputEPNS_2os11SystemEventE 1 +hle _ZN2nn5audio41GetActiveAudioDeviceChannelCountForOutputEv 1 +hle _ZN2nn5audio6server17AudioRenderSystem29ExecuteAudioRendererRenderingEv 11452 +hle _ZN2nn5audio6server17AudioRenderSystem6UpdateEPvmS3_mPKvm 11415 +hle _ZN2nn5codec36GetHardwareOpusDecoderWorkBufferSizeEiii 12 +hle _ZN2nn5prepo10PlayReport4SaveERKNS_7account3UidE 11 +hle _ZN2nn5prepo27AddInternetConnectionStatusEPNS0_10PlayReportEPKcS4_S4_ 1 +hle _ZN2nn6applet23GetAppletResourceUserIdEv 1 +hle _ZN2nn6fontll18ScalableFontEngine8LoadFontEPcPKvjj 128 +hle _ZN2nn7account10InitializeEv 1 +hle _ZN2nn7account11GetNicknameEPNS0_8NicknameERKNS0_3UidE 1 +hle _ZN2nn7account22TryOpenPreselectedUserEPNS0_10UserHandleE 1 +hle _ZN2nn7account9GetUserIdEPNS0_3UidERKNS0_10UserHandleE 4 +hle _ZN2nv18InitializeGraphicsEPvm 1 +hle _ZN2nv20SetGraphicsAllocatorEPFPvmmS0_EPFvS0_S0_EPFS0_S0_mS0_ES0_ 1 +hle nndiagStartup 1 +hle nvnBootstrapLoader 2 +svc 0x1 1 +svc 0x10 92 +svc 0x11 11452 +svc 0x16 4 +svc 0x17 11416 +svc 0x18 14130 +svc 0x1a 231032 +svc 0x1b 224258 +svc 0x1c 6398 +svc 0x1d 6397 +svc 0x2 3 +svc 0x25 57 +svc 0x29 14632 +svc 0x2c 8351 +svc 0x2d 2032 +svc 0x3 6 +svc 0x34 367736 +svc 0x35 367648 +svc 0x4 56 +svc 0x45 3 +svc 0x5 4 +svc 0x6 177 +svc 0x8 56 +svc 0x9 56 +svc 0xa 4 +svc 0xb 3202466 +svc 0xc 1 +svc 0xd 11 +svc 0xf 646 diff --git a/dm/tools/impact_map.tsv b/dm/tools/impact_map.tsv new file mode 100644 index 0000000..72efbb1 --- /dev/null +++ b/dm/tools/impact_map.tsv @@ -0,0 +1,89 @@ +# kind: rules The coarse change → usage map of scripts/regress.py impact (dm/tools/usage.py): which rows of a game's usage manifest (dm/games//usage.tsv) a change can reach. +# Columns: file glob[:function regex] usage pattern why +# A rule with a function regex applies to the changed functions it matches (the function around each changed hunk); the file's rules without one apply to the other changed +# lines of that file. A rule whose why starts with "fallback" applies only when no other rule of the range matched (a translator binary that changed with its sources). +# Usage pattern: : (kind * = any; *:* = every game with a manifest), "-" = no game (tests, docs), "profile" = the game whose profile folder it is. +# Host code is also followed through its callers to the NVN entry points and HLE functions that reach it (usage.py host_graph); these rules add what a call graph cannot see +# A pattern that every game of an API matches (*:*, api:*, shader:stage:*, svc:*, hle:*, present:*) is broad: the report lists the games it reaches apart from those a +# narrower row reaches. +# (the replay runs on its own threads, the prepare step at the first submission, the chain offline). test_usage.py checks that every glob matches a file of the repository. +docs/* - documentation +*.md - documentation +dm/tools/tests/* - tool tests +dm/gfx/tests/* - graphics tests +dm/host/tests/* - host tests +dm/ios/tests/* - iOS tests +.github/* - CI +dm/games/*/README.md - a game's note +dm/games/*/smoke.tsv - a harness route +dm/games/*/bench.tsv - a benchmark route +dm/games/*/usage.tsv - a usage manifest +dm/games/* profile one game's profile +scripts/build_ipa_from_nsp.py *:* packing: every game's build +scripts/bench.py - the benchmark +scripts/regress.py - the regression harness +dm/tools/usage.py - the usage manifests +dm/tools/impact_map.tsv - this map +dm/gfx/nvn/* api:nvn NVN on Metal: every NVN game +dm/gfx/nvn/dmsh_chain.h shader:stage:* the chain version: every game's NVN shader libraries +dm/gfx/nvn/nvn_mtl.m:atomic|imga shader:image_atomic* image atomics on Metal +dm/gfx/nvn/nvn_mtl.m:warm_|prepare|prebuild|front_progress present:pipeline_prepare the prepare step and the prebuild before the first frame +dm/gfx/nvn/nvn_mtl.m:pso_arch|arch_|pso_bundle present:pipeline_archive the pipeline archive +dm/gfx/nvn/nvn_mtl.m:^tf_|xfb shader:transform_feedback transform feedback +dm/gfx/nvn/nvn_mtl.m:^geo_|^gs_ shader:stage:gs geometry shaders +dm/gfx/nvn/nvn_mtl.m:pull_|hybrid shader:pulling_vertex_inputs pulling vertex inputs and the hybrid pipelines +dm/gfx/nvn/nvn_mtl.m:fb_snap|fetch shader:readable_tile readable tiles and feedback snapshots +dm/gfx/nvn/nvn_mtl.m:tbuf shader:texture_buffer texture buffers +dm/gfx/nvn/nvn_mtl.m:mdi_|mdx_ nvn:nvnCommandBufferMultiDraw* indirect multi-draws +dm/gfx/nvn/nvn_mtl.m:present|snap|metalfx|upscale present:* the present path +dm/gfx/tex/* api:* texture layouts: every game +dm/gfx/vk/* api:vulkan Vulkan on Metal +dm/gfx/gl/* api:gl OpenGL on Metal +dm/gfx/tools/dmsh_atomic.py shader:image_atomic* image atomics in the MSL +dm/gfx/tools/dmsh_build.py:vs_tf|tf_layout shader:transform_feedback transform feedback capture +dm/gfx/tools/dmsh_build.py:gs_slice|geometry_finish|vs_layer|_ep_drop shader:stage:gs geometry shaders +dm/gfx/tools/dmsh_build.py:vs_layer|vs_layer_entry shader:layer_output layer output +dm/gfx/tools/dmsh_build.py:fs_uint shader:integer_outputs integer fragment outputs +dm/gfx/tools/dmsh_build.py:int_inputs|vin_finish shader:integer_vertex_inputs integer vertex inputs +dm/gfx/tools/dmsh_build.py:pull_finish shader:pulling_vertex_inputs pulling vertex inputs +dm/gfx/tools/dmsh_build.py:fetch_finish|bf_ shader:readable_tile readable tiles +dm/gfx/tools/dmsh_build.py:vs_pad shader:vs_pad padded vertex outputs +dm/gfx/tools/dmsh_build.py:drv_reads|unfillable|DRV_FILL shader:driver_read_* driver constant segments +dm/gfx/tools/dmsh_build.py:spv_single_lane|SG_ shader:simd subgroup operations +dm/gfx/tools/dmsh_build.py:vertex_ab shader:stage:vs VertexA / VertexB programs +dm/gfx/tools/dmsh_build.py:reflect|decode_ shader:stage:* the reflection every shader's bindings come from +dm/gfx/tools/dmsh_build.py shader:stage:* the shader build: every NVN game +dm/gfx/tools/dmsh_vin.py shader:integer_vertex_inputs integer vertex inputs +dm/gfx/tools/dmsh_pull.* shader:pulling_vertex_inputs pulling vertex inputs +dm/gfx/tools/dmsh_fetch.py shader:readable_tile readable tiles +dm/gfx/tools/dmsh_geometry.py shader:stage:gs geometry shaders +dm/gfx/tools/dmsh_facts.py shader:stage:* the translator's answer table +dm/gfx/tools/dmsh_chain.* shader:stage:* the chain version: every NVN game's libraries are rebuilt +dm/gfx/tools/dmsh_mtlcache.py shader:stage:* the Metal compile cache +dm/gfx/tools/dmsh_xlate/* shader:stage:* the translator's driver +dm/gfx/tools/dmsh_xlate_bin/* shader:stage:* fallback: the translator binary, when its sources are not in the range +dm/third_party/ryujinx/*/InstEmitSurface.cs shader:image_atomic* surface instructions: image loads, stores and atomics +dm/third_party/ryujinx/*/InstEmitSurface.cs shader:texture_write surface instructions: image loads, stores and atomics +dm/third_party/ryujinx/*/InstEmitSurface.cs shader:binding:img surface instructions: image loads, stores and atomics +dm/third_party/ryujinx/*/BindlessElimination.cs shader:note:texture handle* bindless texture handles +dm/third_party/ryujinx/*/InstEmitTexture*.cs shader:binding:tex texture instructions +dm/third_party/ryujinx/*/InstEmitMemory.cs shader:buffer_atomic global and shared memory, buffer atomics +dm/third_party/ryujinx/* shader:stage:* fallback: any other translator change +dm/gfx/tools/vk_shaders.py api:vulkan Vulkan shaders +dm/gfx/tools/gl_shaders.py api:gl OpenGL shaders +dm/gfx/tools/pso_offline.py present:pipeline_prebuild the offline pipeline archive of the Mac app and the iPhone +dm/gfx/tools/c1_guard.py shader:stage:* the c1 guard table +dm/gfx/tools/cb_extent.py shader:stage:* the uniform read extents +dm/gfx/tools/shader_split.py shader:stage:* the shader tables (after a split) +dm/tools/patch_nso.py *:* the rewriter: every game's code +dm/tools/nso_*.py *:* the rewriter: every game's code +dm/tools/sdk_patches.py *:* the SDK modules' patches (by build ID) +dm/host/hle_thread.c svc:* threads and synchronization +dm/host/hle_svc.c svc:* SVCs +dm/host/thread.c svc:* threads +dm/host/main.c *:* the host's start +dm/host/loader.c *:* module loading +dm/host/hle.c hle:* the HLE tables +dm/host/front_mac.m present:* the Mac front end +dm/host/front.h present:* the front end +dm/ios/* *:* the iOS app diff --git a/dm/tools/tests/test_usage.py b/dm/tools/tests/test_usage.py new file mode 100644 index 0000000..42f06f0 --- /dev/null +++ b/dm/tools/tests/test_usage.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# dm/tools/usage.py and dm/tools/impact_map.tsv (scripts/regress.py usage / impact): the map's globs name files of the repository, its patterns name usage kinds, the +# function scanner, the rule precedence and the manifests' format +import fnmatch, subprocess, sys, tempfile, unittest +from pathlib import Path + +REPO = Path(__file__).resolve().parents[3] +sys.path.insert(0, str(REPO / 'dm/tools')) +import usage + +KINDS = {'api', 'key', 'present', 'shader', 'nvn', 'hle', 'svc', '*'} + + +class Usage(unittest.TestCase): + def test_map_names_files_and_kinds(self): + files = [str(p.relative_to(REPO)) for p in REPO.rglob('*') if p.is_file() and '.git' not in p.parts] + for glob, frx, pat, why in usage.load_map(): + self.assertTrue(any(fnmatch.fnmatch(f, glob) for f in files), f'impact_map.tsv: {glob} matches no file') + self.assertTrue(why, f'impact_map.tsv: {glob} gives no reason') + if pat not in ('-', 'profile'): self.assertIn(pat.partition(':')[0], KINDS, f'impact_map.tsv: {glob}: unknown kind in {pat}') + if frx is not None and glob.endswith('dmsh_build.py'): # a function rule of the shader build names a function it has + names = {n for n, _, _ in usage.functions(REPO / glob)} + self.assertTrue(any(frx.search(n) for n in names), f'impact_map.tsv: {glob}:{frx.pattern} matches no function') + + def test_functions(self): + src = 'static int a(void) {\n return b(1);\n}\nNVN(nvnQueueFinish, void, NVNqueue *q) {\n a();\n}\nHLE("_ZN2nn2fs4OpenEv", Result, h_open, void) {\n return 0;\n}\n' + self.assertEqual([n for n, _, _ in usage.functions('x.c', src)], ['a', 'nvnQueueFinish', 'h_open']) + self.assertEqual([(n, a, b) for n, a, b in usage.functions('x.py', 'import os\ndef f():\n pass\nclass C:\n pass\n')], [('f', 2, 3), ('C', 4, 5)]) + + def test_changed_functions_and_headers(self): # a hunk maps to every function it spans; a header's static inline function reaches the entry points of its includers + with tempfile.TemporaryDirectory() as d: + run = lambda *c: subprocess.run(['git', '-c', 'user.name=t', '-c', 'user.email=t@t', *c], cwd=d, check=True, capture_output=True) + (Path(d) / 'dm/gfx/nvn').mkdir(parents=True); run('init', '-q') + (Path(d) / 'dm/gfx/nvn/f.h').write_text('static inline int step(int k) {\n return k;\n}\n') + (Path(d) / 'dm/gfx/nvn/hle_nvn.c').write_text('#include "f.h"\nNVN(nvnQueuePresentTexture, void, int k) {\n step(k);\n}\n') + run('add', '.'); run('commit', '-qm', '1') + (Path(d) / 'dm/gfx/nvn/f.h').write_text('static inline int step(int k) {\n return k + 1;\n}\nstatic inline int hold(int k) {\n return k;\n}\n') + (Path(d) / 'dm/gfx/nvn/hle_nvn.c').write_text('#include "f.h"\nNVN(nvnQueuePresentTexture, void, int k) {\n}\n') # a pure deletion inside the entry point + run('commit', '-qam', '2') + ch = usage.changed_functions('HEAD^..HEAD', root=d) + self.assertEqual(ch['dm/gfx/nvn/f.h'], {'step', 'hold'}); self.assertEqual(ch['dm/gfx/nvn/hle_nvn.c'], {'nvnQueuePresentTexture'}) + callers, roots, _ = usage.host_graph(d, rev='HEAD^') # read from git: the step call exists only in the first revision + self.assertEqual(usage.reach({('dm/gfx/nvn/f.h', 'step')}, callers, roots)[0], {('nvn', 'nvnQueuePresentTexture')}) + self.assertEqual(usage.reach({('dm/gfx/nvn/f.h', 'step')}, *usage.host_graph(d)[:2])[0], set()) + + def test_rule_precedence(self): + rules = usage.load_map() + rs, mapped = usage.rules_for('dm/gfx/tools/dmsh_build.py', {'fs_uint'}, rules) + self.assertTrue(mapped); self.assertEqual({r[2] for r in rs}, {'shader:integer_outputs'}) # the function's rule, not the file's catch-all + rs, _ = usage.rules_for('dm/gfx/tools/dmsh_build.py', {'some_new_function'}, rules) + self.assertEqual({r[2] for r in rs}, {'shader:stage:*'}) + rs, mapped = usage.rules_for('dm/games/01007EF00011E000/README.md', {''}, rules) + self.assertTrue(mapped); self.assertEqual(rs, []) # documentation reaches no game + + def test_manifest_roundtrip(self): + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'usage.tsv' + usage.write_manifest(p, {('nvn', 'nvnQueueFinish'): 12, ('api', 'nvn'): 1, ('shader', 'image_atomic'): 3}, 'test') + self.assertEqual(usage.read_manifest(p), {('nvn', 'nvnQueueFinish'): 12, ('api', 'nvn'): 1, ('shader', 'image_atomic'): 3}) + + def test_committed_manifests(self): # names and counts only + for p in (REPO / 'dm/games').glob('*/usage.tsv'): + for k, n in usage.read_manifest(p): + self.assertIn(k, KINDS - {'*'}, p); self.assertNotIn('/', n if k != 'shader' else n.replace('/', ''), p) + + +if __name__ == '__main__': + unittest.main() diff --git a/dm/tools/usage.py b/dm/tools/usage.py new file mode 100644 index 0000000..27523fa --- /dev/null +++ b/dm/tools/usage.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python3 +# Usage manifests and change impact (scripts/regress.py usage / impact). One chain and one host serve every profile, so a contributor who changes them needs to know which games, +# also ones they do not own, use what the change touches (GitHub issue #272). A game's usage manifest, dm/games//usage.tsv, holds only names and counts, no game content: +# shader shaders features of the game's translated shaders (stages, binding kinds, image / buffer atomics and whether a result is used, transform feedback, +# layer output, integer outputs, fp64 lowering, translator notes, texture types, ...), counted from the chain build's MSL and reflection +# nvn calls the NVN functions a smoke run called (DM_NVN_TSV call rows), summed over the run +# hle calls the SDK functions the host implements that the run called (DM_HLECOUNT: HLE table, forced takeovers, stubs) +# svc calls the SVCs the run made (DM_HLECOUNT) +# present 1 the frame step and present path the log names (frame step mode, present interval changes, display link, pipeline paths) +# key 1 the profile keys in game.tsv (their names: what the host's game_profile.h takes) +# api nvn|vulkan|gl 1 the graphics API +# Impact: the changed functions of a git range (hunks mapped to the C / Objective-C / Python function around them), widened to their callers in the host (a call graph made by +# a scanner, not a compiler), the NVN entry points (NVN(...) in hle_nvn.c) and HLE symbols ({"symbol", fn} tables) among those callers, and the coarse rules of +# dm/tools/impact_map.tsv (a file, or a function in it, → usage rows) → the games whose manifests hold any of them; games without a manifest are unknown. +import collections, fnmatch, json, re, subprocess +from pathlib import Path + +REPO = Path(__file__).resolve().parents[2] +NOTE_SKIP = ('not in the answer table',) + + +def norm(s): + return re.sub(r'\d+', '#', re.sub(r'\b[0-9a-f]{16}\b', '', re.sub(r'"[^"]*"', '"…"', s)))[:100] + + +# ---------------------------------------------------------------- shader features (static) + +MSL_TAGS = [ + ('image_atomic', re.compile(r'spvImage\w*AtomicCoord\((?!int|uint|tc)')), + ('image_atomic_result', re.compile(r'=\s*atomic_\w+_explicit\([^;]*spvImage\w*AtomicCoord')), + ('buffer_atomic', re.compile(r'atomic_\w+_explicit\((?![^;]*spvImage)')), + ('discard', re.compile(r'\bdiscard_fragment\(')), + ('gather', re.compile(r'\.gather(_compare)?\(')), + ('sample_compare', re.compile(r'\.sample_compare\(')), + ('gradient', re.compile(r'\bgradient(2d|3d|cube)\(')), + ('lod_query', re.compile(r'\.calculate_(un)?clamped_lod\(')), + ('simd', re.compile(r'\bsimd_\w+\(')), + ('threadgroup_memory', re.compile(r'\bthreadgroup\s+\w')), + ('texture_buffer', re.compile(r'\btexture_buffer<')), + ('texture3d', re.compile(r'\btexture3d<')), + ('texture_cube', re.compile(r'\btexturecube(_array)?<')), + ('texture2d_array', re.compile(r'\btexture2d_array<')), + ('texture_ms', re.compile(r'\btexture2d_ms(_array)?<')), + ('depth_texture', re.compile(r'\bdepth(2d|cube)(_array)?<')), + ('texture_write', re.compile(r'access::(write|read_write)\b')), + ('device_buffer_write', re.compile(r'\bdevice\s+(?!const)\w')), + ('fp64', re.compile(r'\bdouble\b')), + ('position_invariant', re.compile(r'\[\[position, invariant\]\]')), +] + + +def shader_features(lib): + """{feature: number of shaders} of one chain build's b- folder""" + c = collections.Counter() + for j in sorted(Path(lib).glob('*_b.json')): + try: r = json.loads(j.read_bytes()) + except ValueError: continue + f = {'stage:' + str(r.get('stage'))} + for b in r.get('bindings', []): + f.add('binding:' + str(b.get('kind'))) + if b.get('rw'): f.add('binding_rw:' + str(b.get('kind'))) + if b.get('fetch1d'): f.add('fetch1d') + for k, tag in (('entry_tf', 'transform_feedback'), ('entry_layer', 'layer_output'), ('entry_u', 'integer_outputs'), ('entry_m', 'mixed_outputs'), ('vin', 'integer_vertex_inputs'), + ('pull', 'pulling_vertex_inputs'), ('fetch', 'readable_tile'), ('vs_pad', 'vs_pad'), ('gs_slice', 'gs_layer_slice'), ('drv_unfillable', 'driver_read_unfillable')): + if r.get(k): f.add(tag) + for seg in r.get('drv_reads') or '': f.add('driver_read_c' + seg) + if r.get('stage') == 'gs' and not r.get('gs_slice'): f.add('geometry_as_compute') + for n in r.get('notes', []): + if not n.startswith(NOTE_SKIP): f.add('note:' + norm(n.split(' (')[0])) + m = j.with_name(j.name[:-5] + '.metal') + if m.is_file(): + src = m.read_text(errors='replace') + f.update(tag for tag, rx in MSL_TAGS if rx.search(src)) + c.update(f) + return c + + +# ---------------------------------------------------------------- runtime usage (one smoke run) + +PRESENT = [ + ('frame_step_vsync', re.compile(r'frame step in whole vsyncs')), + ('frame_step_variable', re.compile(r'frame step variable')), + ('present_interval_changes', re.compile(r'the game sets present interval')), + ('display_link', re.compile(r'display link up to tick')), + ('present_snapshots', re.compile(r'present snapshot', re.I)), + ('metalfx', re.compile(r'MetalFX', re.I)), + ('pipeline_prepare', re.compile(r'pipeline prepare: \d+ lines')), + ('pipeline_prebuild', re.compile(r'pipeline prebuild')), + ('hybrid_pipelines_off', re.compile(r'hybrid pipelines off')), + ('pipeline_archive', re.compile(r'pipeline archive')), + ('render_scale', re.compile(r'render scale', re.I)), + ('nro_modules', re.compile(r'\bNRO\b')), + ('audio_out', re.compile(r'OpenAudioOut|audren')), + ('movie', re.compile(r'\bmovie\b|\bmm::|nvdec|VideoToolbox', re.I)), +] + + +def runtime_usage(run_dir, api): + """[(kind, name, count)] of one run folder: frames.tsv call rows, hlecount.tsv, the log""" + rows = collections.Counter() + ft = Path(run_dir) / 'frames.tsv' + if ft.is_file(): + with open(ft, errors='replace') as fh: + for ln in fh: + c = ln.rstrip('\n').split('\t') + if len(c) == 3 and c[1].startswith('nvn') and c[2].isdigit(): rows['nvn', c[1]] += int(c[2]) + hc = Path(run_dir) / 'hlecount.tsv' + if hc.is_file(): + for ln in hc.read_text(errors='replace').splitlines()[1:]: + c = ln.split('\t') + if len(c) == 3 and c[2].isdigit() and int(c[2]): + rows[('svc' if c[0] == 'SVC' else 'hle'), c[1]] += int(c[2]) + log = Path(run_dir) / 'log.txt' + text = log.read_text(errors='replace') if log.is_file() else '' + for tag, rx in PRESENT: + if rx.search(text): rows['present', tag] = 1 + rows['api', api] = 1 + return rows + + +def write_manifest(path, rows, header): + order = {k: i for i, k in enumerate(('api', 'key', 'present', 'shader', 'nvn', 'hle', 'svc'))} + lines = [f'# kind: usage {header}', '# generated by scripts/regress.py usage (names and counts only); impact: scripts/regress.py impact ..', 'kind\tname\tcount'] + lines += [f'{k}\t{n}\t{v}' for (k, n), v in sorted(rows.items(), key=lambda x: (order.get(x[0][0], 99), x[0][1]))] + Path(path).write_text('\n'.join(lines) + '\n') + + +def read_manifest(path): + rows = {} + for ln in Path(path).read_text().splitlines(): + if not ln or ln.startswith(('#', 'kind\t')): continue + c = ln.split('\t') + if len(c) == 3: rows[c[0], c[1]] = int(c[2]) if c[2].isdigit() else 1 + return rows + + +# ---------------------------------------------------------------- the host's call graph (a scanner, not a compiler) + +DEF = re.compile(r'^(?:static\s+|inline\s+|__attribute__\(\([^)]*\)\)\s+)*[A-Za-z_][\w\s\*]*?\b([A-Za-z_]\w*)\s*\(([^;{}]|\n)*?\)\s*\{', re.M) +NVN_DEF = re.compile(r'^NVN(?:_NOPROTO)?\((nvn\w+)\s*,', re.M) +HLE_DEF = re.compile(r'^HLE\(\s*"([^"]+)"\s*,\s*[^,]+,\s*(\w+)', re.M) # HLE("symbol", ret, cname, ...) and HLE_FORCE("symbol", "why", ret, cname, ...) in dm/host/hle.h +HLE_FORCE_DEF = re.compile(r'^HLE_FORCE(?:_BIG)?\(\s*"([^"]+)"\s*,\s*"(?:[^"\\]|\\.)*"\s*,\s*[^,]+,\s*(\w+)', re.M) +CALL = re.compile(r'\b([A-Za-z_]\w*)\s*\(') +TABLE = re.compile(r'\{\s*"([^"]+)"\s*,\s*(?:\(void\s*\*\)\s*)?&?([A-Za-z_]\w*)\s*\}') +KEYWORDS = {'if', 'for', 'while', 'switch', 'return', 'sizeof', 'do', 'else', 'case', 'defined', 'typeof', '__typeof__', 'alignof'} +HOST_SRC = ('dm/host', 'dm/gfx', 'dm/gfx/nvn', 'dm/gfx/tex', 'dm/gfx/vk', 'dm/gfx/gl') +HOST_EXT = ('.c', '.m', '.inc', '.h') # headers too: the frame step, the texture layouts and other static inline code live in them + + +def functions(path, text=None): + """[(name, first line, last line)] of the functions defined at column 0 of a C / Objective-C / Python file (NVN(name, …) definitions named after the NVN function)""" + text = text if text is not None else Path(path).read_text(errors='replace') + if str(path).endswith('.py'): + starts = [(m.group(1) or m.group(2), text.count('\n', 0, m.start()) + 1) for m in re.finditer(r'^(?:async\s+)?def\s+(\w+)|^class\s+(\w+)', text, re.M)] + else: + starts = sorted([(m.group(1), text.count('\n', 0, m.start()) + 1) for m in DEF.finditer(text) if m.group(1) not in KEYWORDS] + + [(m.group(1), text.count('\n', 0, m.start()) + 1) for m in NVN_DEF.finditer(text)] + + [(m.group(2), text.count('\n', 0, m.start()) + 1) for rx in (HLE_DEF, HLE_FORCE_DEF) for m in rx.finditer(text)], key=lambda x: x[1]) + total = len(text.splitlines()) + return [(n, l, (starts[i + 1][1] - 1 if i + 1 < len(starts) else total)) for i, (n, l) in enumerate(starts)] + + +def host_sources(root=REPO, rev=None): + """[(path, text)] of the host's sources and headers: the files under root, or those of a git revision read from the object store (no checkout, no harness root)""" + if rev is None: + return [(str(p.relative_to(root)), p.read_text(errors='replace')) for d in HOST_SRC for p in sorted((Path(root) / d).glob('*')) if p.suffix in HOST_EXT and p.is_file()] + ls = subprocess.run(['git', 'ls-tree', rev, '--', *[d + '/' for d in HOST_SRC]], cwd=root, capture_output=True, text=True, check=True).stdout.splitlines() + paths = sorted(ln.split('\t', 1)[1] for ln in ls if ln.split()[1] == 'blob' and Path(ln.split('\t', 1)[1]).suffix in HOST_EXT) + out = subprocess.run(['git', 'cat-file', '--batch'], cwd=root, input=''.join(f'{rev}:{p}\n' for p in paths).encode(), capture_output=True, check=True).stdout + files, i = [], 0 + for p in paths: # blob \n\n per path + nl = out.index(b'\n', i); size = int(out[i:nl].split()[2]); i = nl + 1 + files.append((p, out[i:i + size].decode(errors='replace'))); i += size + 1 + return files + + +def host_graph(root=REPO, rev=None): + """(callers: {(file, function): {(file, function) calling it}}, roots: {(file, function): {('nvn' | 'hle', name)}}, defs: {function: [files]}). A call resolves to the function + of the same name in the calling file when there is one (static functions of the same name in several files), else to every file that defines it; a function defined in a + header (static inline ones included) is visible to every file, as to the files that include it""" + defs, bodies, roots, local = collections.defaultdict(list), {}, collections.defaultdict(set), set() + for rel, text in host_sources(root, rev): + lines = text.splitlines() + for name, a, b in functions(rel, text): + defs[name].append(rel); bodies[rel, name] = '\n'.join(lines[a - 1:b]) + if not rel.endswith('.h') and re.match(r'(static|NVN|HLE)\b', lines[a - 1]): local.add((rel, name)) # file-local: not called from other files + if rel.endswith('/hle_nvn.c') and name.startswith('nvn'): roots[rel, name].add(('nvn', name)) + for sym, fn in TABLE.findall(text) + [(m.group(1), m.group(2)) for rx in (HLE_DEF, HLE_FORCE_DEF) for m in rx.finditer(text)]: roots[rel, fn].add(('hle', sym)) + callers = collections.defaultdict(set) + for (rel, name), body in bodies.items(): + for c in set(CALL.findall(body)) - KEYWORDS - {name}: + if c not in defs: continue + for f in ([rel] if rel in defs[c] else [x for x in defs[c] if (x, c) not in local]): callers[f, c].add((rel, name)) + return callers, roots, defs + + +def reach(changed, callers, roots, limit=4000): + """The NVN entry points and HLE functions whose implementation calls a changed (file, function), at any depth""" + seen, todo, hit = set(changed), list(changed), set() + while todo and len(seen) < limit: + f = todo.pop() + hit |= roots.get(f, set()) + for c in callers.get(f, ()): + if c not in seen: seen.add(c); todo.append(c) + return hit, len(seen) + + +# ---------------------------------------------------------------- what a git range changes + +def changed_functions(rng, root=REPO): + """{file: set of function names whose lines the range changes ('' for lines outside any function)}""" + out = collections.defaultdict(set) + files = subprocess.run(['git', 'diff', '--name-only', rng], cwd=root, capture_output=True, text=True, check=True).stdout.split() + head = rng.split('..')[-1] or 'HEAD' + for f in files: + diff = subprocess.run(['git', 'diff', '-U0', rng, '--', f], cwd=root, capture_output=True, text=True, errors='replace').stdout + src = f.endswith(('.c', '.m', '.inc', '.h', '.py')) + new = subprocess.run(['git', 'show', f'{head}:{f}'], cwd=root, capture_output=True, text=True, errors='replace') if src else None + fns = functions(f, new.stdout) if new and new.returncode == 0 else [] + lines = set() # every line a hunk adds or changes; a pure deletion (+c,0) is after line c, inside the function around it + for m in re.finditer(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@', diff, re.M): + c, n = int(m.group(1)), int(m.group(2) if m.group(2) is not None else 1) + lines.update(range(c, c + n) if n else (max(c, 1),)) + if not fns: out[f].add(''); continue + for ln in sorted(lines): + out[f].add(next((n for n, a, b in fns if a <= ln <= b), '')) + return out + + +def load_map(path=REPO / 'dm/tools/impact_map.tsv'): + """[(file glob, function regex or None, usage pattern, why)] of the coarse map""" + rules = [] + for ln in Path(path).read_text().splitlines(): + if not ln.strip() or ln.startswith('#'): continue + c = ln.split('\t') + f, _, fn = c[0].partition(':') + rules.append((f, re.compile(fn) if fn else None, c[1], c[2] if len(c) > 2 else '')) + return rules + + +BROAD = re.compile(r'^(\*:\*|api:.*|shader:stage:\*|svc:\*|hle:\*|present:\*|\*:.*)$') # patterns every game of an API matches + + +def rules_for(f, fns, rules): + """The rules a changed file reaches: per changed function the rules whose regex matches it, else the file's rules without one; a file a "-" rule matches reaches nothing""" + mine = [r for r in rules if fnmatch.fnmatch(f, r[0])] + if any(r[2] == '-' for r in mine): return [], True + out = [] + for fn in fns or {''}: + spec = [r for r in mine if r[1] is not None and fn and r[1].search(fn)] + out += spec or [r for r in mine if r[1] is None] + return out, bool(mine) + + +def impact(rng, manifests, root=REPO, rules=None): + """→ {'changed': {file: [functions]}, 'names': [(kind, name, why)], 'patterns': [(pattern, why)], 'unmapped': [file], + 'games': {id: {'status': affected | not affected | unknown, 'matches': [(kind, name, count, why)]}}}""" + rules = rules if rules is not None else load_map(Path(root) / 'dm/tools/impact_map.tsv') + ch = changed_functions(rng, root) + callers, roots, _ = host_graph(root, rev=rng.split('..')[-1] or 'HEAD') # the call graph of the range's head, read from git + names, hits, unmapped = {}, [], [] + for f, fns in ch.items(): + if f.startswith(HOST_SRC) and f.endswith(('.c', '.m', '.inc', '.h')): + hit, _ = reach({(f, n) for n in fns if n}, callers, roots) + for k, n in hit: names.setdefault((k, n), f'{f}: calls reach it from {", ".join(sorted(x for x in fns if x))[:80]}') + rs, mapped = rules_for(f, fns, rules) + if not mapped and not any(names.get(k) for k in names if names[k].startswith(f + ':')): unmapped.append(f) + hits += [(f, r) for r in rs] + strong = [(f, r) for f, r in hits if not r[3].startswith('fallback')] + use = strong + ([(f, r) for f, r in hits if r[3].startswith('fallback')] if not strong else []) + patterns = sorted({(r[2], f'{f}{":" + r[1].pattern if r[1] else ""}: {r[3]}') for f, r in use}) + games = {} + for gid, rows in manifests.items(): + if rows is None: games[gid] = {'status': 'unknown', 'matches': []}; continue + m = {} + for (k, n), why in names.items(): + if (k, n) in rows: m[k, n] = why + for pat, why in sorted(patterns, key=lambda x: bool(BROAD.match(x[0]))): # a narrow pattern's reason first + if pat == 'profile': + if any(f'dm/games/{gid}/' in w for w in [why]): m['profile', gid] = why + continue + k, _, n = pat.partition(':') + for (rk, rn) in rows: + if (k == '*' or rk == k) and fnmatch.fnmatchcase(rn, n or '*'): m.setdefault((rk, rn), why) + narrow = {k: w for k, w in m.items() if not any(BROAD.match(pt) and w == pw for pt, pw in patterns)} + games[gid] = {'status': 'affected' if narrow else 'broad' if m else 'not affected', 'narrow': sorted(((k, n, rows.get((k, n), 1), w) for (k, n), w in narrow.items()), key=lambda x: ('calls reach' in x[3], -x[2], x[0], x[1])), # feature rows first, then the entry points the call graph reaches + 'matches': sorted(((k, n, rows.get((k, n), 1), why) for (k, n), why in m.items()), key=lambda x: (-x[2], x[0], x[1]))} + return {'changed': {f: sorted(x for x in v if x) for f, v in ch.items()}, 'names': sorted((k, n, w) for (k, n), w in names.items()), 'patterns': patterns, + 'unmapped': unmapped, 'games': games} diff --git a/docs/agents/06-dev-loop.md b/docs/agents/06-dev-loop.md index 8225c48..b7fe779 100644 --- a/docs/agents/06-dev-loop.md +++ b/docs/agents/06-dev-loop.md @@ -47,14 +47,20 @@ The routes are `dm/games//smoke.tsv`; a game without one takes part in the c Reading the report (`report.md` beside `report.json` in `/reports/`): one row per game, then the details. `PASS` and `CHANGED` (MSL or numbers moved, nothing worse) exit 0; `NEW-FAIL` (a shader, the interface check, a crash, a hang or the frame that worked in the baseline fails) and `REGRESSION` (new `[RED]` lines, a screenshot, frame time, memory or prepare time beyond the tolerances) exit 1; `ERROR` (the harness could not check a game) exits 2. Failures the baseline has too are listed as known and do not fail the check. Changed MSL is expected after a chain change: say in the pull request why it changed. A screenshot difference may be a fix: look at the run's screenshots in `/-work/regress/runs/` before calling it either. The report holds only numbers, hashes, shader keys and normalized `[RED]` texts, so it can be pasted as it is. -## 5. Continuous integration +## 5. Which games a change can reach: usage manifests and `regress.py impact` + +`regress.py` checks only the games on your Mac. For the others, each profile can carry a usage manifest, `dm/games//usage.tsv`, written by someone who owns the game with `python3 scripts/regress.py usage --games --write`: the features of its translated shaders (stages, binding kinds, image and buffer atomics, transform feedback, layer and integer outputs, translator notes, texture types), and from one run of its smoke route the NVN functions, HLE functions and SVCs it called, its present path and its profile keys. It holds names and counts only. + +`python3 scripts/regress.py impact ..` (or one commit) maps a change to those names: the functions around its changed lines, followed through the host's callers to the NVN entry points and HLE functions they serve, and the rules of `dm/tools/impact_map.tsv` (a file, or functions in it, to manifest rows: `dmsh_atomic.py` to the image atomic features, the prepare-step functions of `nvn_mtl.m` to the games that run it). It lists the games that use what the change touches, those reached only through a broad rule (every game of the API), and the profiles without a manifest as unknown. It reads only git and the committed manifests, so it needs neither game files nor a harness root: the report is printed, and written as `impact.md` and `impact.json` to `--out` or, when there is one, `/reports/`. Run it before a change to the chain or host, and run `regress.py check` on the games it names that you have; ask their owners for the others. A changed file no rule maps is listed: add a rule for it. + +## 6. Continuous integration `.github/workflows/tests.yml` runs on every pull request: the host's unit tests and ThreadSanitizer targets, the CPU-only graphics tests, the Python tool tests (`dm/tools/tests`, `dm/ios/tests`, `dm/gfx/tests`) including the translator's synthetic-shader tests, Mac host builds for an NVN, a Vulkan and an OpenGL profile, and the iOS source compile and smoke project ([Continuous integration](../development.md#continuous-integration)). GitHub's Macs have no Metal 4 and no game files, so these stay local: `make -C dm/gfx/tests GAME= run` (the Metal graphics tests), the translator tests with `DMSH_TEST_METAL=1` / `DMSH_TEST_GPU=1`, `profile_guess.py --check`, and everything `regress.py` does. -## 6. Before you open a pull request +## 7. Before you open a pull request By what the change touches (the largest that applies): - **Docs only:** `python3 -m unittest dm/tools/tests/test_docs.py`; after a change to `docs/reference`, `python3 dm/tools/docs_symptoms.py`. - **One game's profile or note** (`dm/games//`): the Python tool tests; a full shader build of that game after a change to its shader inputs; the game on the Mac (or the iPhone) along its route, with `scripts/bench.py` numbers when the change is about speed; the finding in the game's note ([AGENTS.md](../../AGENTS.md)). -- **The host, the chain or the tools** (`dm/host`, `dm/gfx`, `dm/tools`, `dm/gfx/tools`, `dm/ios`, `scripts`): everything above, `make -C dm/gfx/tests GAME= run`, `dmsh_chain.py --header` after a chain change, then `python3 scripts/regress.py check` over every local game (`--quick` while iterating, the full run before the pull request), and its `report.md` pasted into the pull request with a word on every `CHANGED`, `NEW-FAIL` or `REGRESSION`. Name the games the report covers: the others are unchecked. +- **The host, the chain or the tools** (`dm/host`, `dm/gfx`, `dm/tools`, `dm/gfx/tools`, `dm/ios`, `scripts`): everything above, `make -C dm/gfx/tests GAME= run`, `dmsh_chain.py --header` after a chain change, `python3 scripts/regress.py impact main..HEAD` to see which games it reaches, then `python3 scripts/regress.py check` over every local game (`--quick` while iterating, the full run before the pull request), and its `report.md` pasted into the pull request with a word on every `CHANGED`, `NEW-FAIL` or `REGRESSION`. Name the games the report covers: the others are unchecked. diff --git a/scripts/regress.py b/scripts/regress.py index 6ee7ab4..d5b8ba9 100644 --- a/scripts/regress.py +++ b/scripts/regress.py @@ -6,6 +6,8 @@ # Usage: python3 scripts/regress.py check [--baseline REV] [--candidate REV|worktree] [--quick] [--games ID,...] [--no-smoke] [--out DIR] # python3 scripts/regress.py baseline [--rev REV] [--quick] [--games ID,...] [--runs N] # python3 scripts/regress.py chain [--baseline REV] [--candidate REV|worktree] [--games ID,...] (the static checks only, no game runs) +# python3 scripts/regress.py usage [--rev REV] [--games ID,...] [--write] (a game's usage manifest, dm/games//usage.tsv: dm/tools/usage.py) +# python3 scripts/regress.py impact .. | (the games whose manifests hold what the change touches) # python3 scripts/regress.py list (the games found, their routes and stored baselines) # REV: any git revision of this repository; worktree = this checkout as it is, uncommitted and untracked files included. check: baseline = the merge base of HEAD and main, # candidate = worktree; baseline: --rev main. Each revision is checked out once into /trees/ (git worktree), and the chain, host and rewriter come from there. @@ -66,6 +68,7 @@ def load_module(name, path): # a module from a file (another script, or a tool bench = load_module('bench', REPO / 'scripts/bench.py') shader_regressions = load_module('shader_regressions', REPO / 'dm/gfx/tools/shader_regressions.py') +usage = load_module('usage', REPO / 'dm/tools/usage.py') # usage manifests and change impact (regress.py usage / impact) ROOT = Path(os.environ.get('REGRESS_ROOT', '/Volumes/NX/harness')) GAMES = Path(os.environ.get('REGRESS_GAMES', '/Volumes/NX/games')) HOST_DIRS = ('dm/host', 'dm/gfx', 'dm/gfx/nvn', 'dm/gfx/nvn/include', 'dm/gfx/tex', 'dm/gfx/vk', 'dm/gfx/gl') # as build_ipa_from_nsp.py: the host's sources and headers @@ -1016,6 +1019,74 @@ def cmd_check(a, smoke=True): return finish(rep, a) +def cmd_usage(a): + """The usage manifest of each game (dm/tools/usage.py): shader features of the revision's chain build, and what one run of the route's quick part calls""" + tree = Tree(a.rev); games = select(a, smoke=True) + for g in games: + art = artifacts(tree, g, a, rewrite=a.rewrite) + rows = collections.Counter() + if g.kind == 'nvn': + ff = art['lib'] / 'features.json' + if not ff.is_file(): say(f' {g.id}: shader features of chain {art["manifest"]["chain"]}'); ff.write_text(json.dumps(usage.shader_features(next(art['lib'].glob('b-*'))))) + for k, n in json.loads(ff.read_text()).items(): rows['shader', k] = n + for ln in (g.profile_dir(tree) / 'game.tsv').read_text().splitlines(): + if ln and not ln.startswith('#') and '\t' in ln: rows['key', ln.split('\t')[0]] = 1 + route = g.route() + if route and not a.no_smoke: + g.get_depth_zero = depth_zero(g, tree) + r2 = dict(route, shots=[]) + d = game_root(g) / 'runs' / f'{datetime.datetime.now():%Y%m%d-%H%M%S}-usage' # the run's logs stay in the NSP folder, as check's runs + a.env = list(a.env) + ['DM_HLECOUNT=hlecount.tsv', 'DM_NVN_TSV_CALLS=1'] + say(f' {g.id}: usage run ({route["quick"]:g} s) → {d}') + res = smoke_run(g, tree, art, r2, True, d, a) + a.env = a.env[:-2] + if run_failures(res, route): say(f' [RED] the run failed ({"; ".join(run_failures(res, route))}): its usage rows are incomplete') + rows.update(usage.runtime_usage(d, g.kind if g.kind != 'vk' else 'vulkan')) + else: rows['api', g.kind if g.kind != 'vk' else 'vulkan'] = 1 + out = ROOT / g.id / 'usage' / f'{tree.id}.tsv'; out.parent.mkdir(parents=True, exist_ok=True) + head = f'{g.name} ({g.id}), revision {tree.commit[:12]}, chain {art["manifest"]["chain"]}, ' + (f'route smoke.tsv quick ({route["quick"]:g} s)' if route and not a.no_smoke else 'no run') + usage.write_manifest(out, rows, head) + kinds = collections.Counter(k for k, _ in rows) + say(f' {g.id}: {", ".join(f"{k} {n}" for k, n in sorted(kinds.items()))} → {out}') + if a.write: + dst = REPO / 'dm/games' / g.id / 'usage.tsv'; shutil.copyfile(out, dst); say(f' written to {dst}') + return 0 + + +def cmd_impact(a): + """The games a git range can affect (dm/tools/usage.py impact), from the usage manifests of this checkout's profiles""" + rng = a.range if '..' in a.range else f'{a.range}^..{a.range}' + for rev in rng.split('..'): # read from git only: no checkout and no harness root, as a contributor without the games has neither + if sh(['git', 'rev-parse', '--verify', '--quiet', (rev or 'HEAD') + '^{commit}'], cwd=REPO).returncode: raise HarnessError(f'impact: {rev} is not a revision of this repository') + manifests = {} + for d in sorted((REPO / 'dm/games').iterdir()): + if (d / 'game.tsv').is_file(): manifests[d.name] = usage.read_manifest(d / 'usage.tsv') if (d / 'usage.tsv').is_file() else None + for extra in a.manifest: # a manifest from //usage/ that is not committed yet + manifests[Path(extra).parent.parent.name] = usage.read_manifest(extra) + r = usage.impact(rng, manifests) + names = {d.name: (d / 'README.md').read_text(errors='replace').split('\n', 1)[0].lstrip('# ').split(' (`')[0] if (d / 'README.md').is_file() else d.name for d in (REPO / 'dm/games').iterdir() if d.is_dir()} + st = collections.Counter(v['status'] for v in r['games'].values()) + L = [f"## regress.py impact `{rng}`", '', f"{st['affected']} games use what the change touches, {st['broad']} only through a broad rule (every game of its API), {st['not affected']} not affected, {st['unknown']} unknown (no usage manifest); " + f"{len(r['changed'])} files changed, {len(r['names'])} NVN / HLE entry points reached through the host's callers, {len(r['patterns'])} rules of dm/tools/impact_map.tsv", '', + '| game | status | what it uses of the change (kind: name ×count; for broad, the broad rows) |', '|---|---|---|'] + order = {'affected': 0, 'broad': 1, 'not affected': 2, 'unknown': 3} + for gid, v in sorted(r['games'].items(), key=lambda x: (order[x[1]['status']], x[0])): + if v['status'] == 'unknown' and not a.all: continue + ms = v.get('narrow') or v['matches'] + top = ', '.join(f'{k}: {n} ×{c}' for k, n, c, _ in ms[:6]) + (f' … ({len(ms)} in all)' if len(ms) > 6 else '') + L.append(f"| {names.get(gid, gid)} `{gid}` | {v['status']} | {top} |") + if st['unknown'] and not a.all: L += ['', f"Unknown (no usage.tsv): {st['unknown']} profiles (--all lists them)."] + L += ['', '### Why', ''] + [f'- `{p}` ← {w}' for p, w in r['patterns']] + [f'- `{k}:{n}` ← {w}' for k, n, w in r['names'][:30]] + (['- … more entry points'] if len(r['names']) > 30 else []) + if r['unmapped']: L += ['', 'Changed files no rule maps (add them to dm/tools/impact_map.tsv): ' + ', '.join(f'`{f}`' for f in r['unmapped'])] + md = '\n'.join(L) + '\n' + out = Path(a.out) if a.out else ROOT / 'reports' / f'{datetime.datetime.now():%Y%m%d-%H%M%S}-impact' if ROOT.is_dir() else None # without a harness root, the report is only printed + if out: + out.mkdir(parents=True, exist_ok=True) + (out / 'impact.json').write_text(json.dumps({'schema': 'nxnative-impact/1', 'range': rng, **r}, indent=1, default=list)); (out / 'impact.md').write_text(md) + say(md + (f'\nreport: {out / "impact.md"}' if out else '')) + return 0 + + def select(a, smoke): games = find_games(a.games.split(',') if a.games else None) if not games: raise HarnessError(f'no game with a Mac build under {GAMES}') @@ -1126,19 +1197,25 @@ def main(): p = sub.add_parser('baseline', help='record the runs of a revision'); p.add_argument('--rev', default='main'); common(p) p = sub.add_parser('check', help='compare a candidate with the stored baseline'); p.add_argument('--baseline'); p.add_argument('--candidate', default='worktree'); common(p) p = sub.add_parser('chain', help='the static checks only'); p.add_argument('--baseline'); p.add_argument('--candidate', default='worktree'); common(p, smoke=False) + p = sub.add_parser('usage', help='write each game\'s usage manifest (names and counts)'); p.add_argument('--rev', default='worktree'); common(p) + p.add_argument('--write', action='store_true', help='also write it to dm/games//usage.tsv of this checkout') + p = sub.add_parser('impact', help='the games a change can affect'); p.add_argument('range', help='.., or one commit') + p.add_argument('--manifest', action='append', default=[], help='a usage.tsv not in the profiles yet (//usage/.tsv)') + p.add_argument('--all', action='store_true', help='list the games without a manifest too'); p.add_argument('--out') sub.add_parser('list', help='the games, routes and baselines') a = ap.parse_args() ROOT, GAMES = Path(a.root), Path(a.games_dir) signal.signal(signal.SIGTERM, lambda *_: sys.exit(143)) # a stop runs the finally blocks: a game or a shader build in its own process group is stopped too try: if a.cmd == 'list': return cmd_list(a) + if a.cmd == 'impact': return cmd_impact(a) ROOT.mkdir(parents=True, exist_ok=True); (ROOT / 'tmp').mkdir(exist_ok=True) if a.cmd == 'chain': a.quick = False; a.no_smoke = True; a.rewrite = False a.lock = a.pause_lock = Path(a.lock) if a.lock else None a.jobs = a.jobs or os.cpu_count() or 8 a.tools_fp = toolchain_fp() free = check_disk(a.min_free_gb); say(f'internal disk: {free:.1f} GB free; root {ROOT}; {a.jobs} workers') - return {'baseline': cmd_baseline, 'check': cmd_check, 'chain': lambda a: cmd_check(a, smoke=False)}[a.cmd](a) + return {'baseline': cmd_baseline, 'check': cmd_check, 'usage': cmd_usage, 'chain': lambda a: cmd_check(a, smoke=False)}[a.cmd](a) except HarnessError as e: print(f'[RED] regress.py: {e}', file=sys.stderr); return 2