aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
Commit message (Collapse)AuthorAgeFilesLines
* Merge remote-tracking branch 'origin/nx2' into fe-fsr31Duck91226 hours14-76/+181
|\ | | | | | | | | | | # Conflicts: # src/video_core/renderer_vulkan/blit_image.cpp # src/video_core/renderer_vulkan/blit_image.h
| * Merge pull request #305 from Djihads80/fix/nx2-cache-version-fselJonas27 hours1-1/+1
| |\ | | | | | | video_core: bump the shader cache versions for the FSEL lowering fix
| | * video_core: bump the shader cache versions for the FSEL lowering fixTakoroka36 hours1-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The disk shader cache keeps the lowered native code. "shader: apply FSEL's floating operand modifiers" (ef3ae4ae23) changed that code without a version bump, so caches built before it keep programs that drop FSEL's negate until the user deletes them by hand. In Splatoon Raiders those stale programs leave the tutorial island and the dock with no shadows (the depth linearization ends with FSEL R0, -R0, 1.0, P and comes out negated), no aiming reticle and no steam (particle quads pick their corners with FSEL +0.5 / -0.5 and collapse to a point).
| * | Merge pull request #334 from snowstormxd/codex/upstream-mkw-testJonas28 hours3-10/+52
| |\ \ | | | | | | | | MKW performance improvements
| | * | vulkan: submit native work sooner and use the active draw countsnowstormxd31 hours2-3/+20
| | | | | | | | | | | | | | | | | | | | | | | | Adapted from sylvieistaken/selevet-eglantine performance builds, including 8b076b167ffc5ca1ba8ffedcd00e255accbe018c and d8c95fef. Preserve upstream command-list coherency and submission ordering. Assisted by Codex.
| | * | shader_cache: batch memory-write invalidations without skipping rangessnowstormxd31 hours1-5/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Adapt the batching from ymatrix1/Eglantine PR #237, retaining all CPU invalidations. Acquire the lock once and remove pending shaders once per write batch. Compare real cache contents with sequential invalidation across randomized overlapping writes and pending removals. Assisted-by: Codex (implementation, review, commit text and automated validation) (cherry picked from commit b65f818d7789ffadfb58fe4543b18060fd88ce53)
| | * | video_core/buffer_cache: reuse unchanged small uniform buffers within ↵gabrielskaminski31 hours1-2/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | command buffer (cherry picked from commit 4aa5cd89fd1862751b3297036f2d21a0dc924b23) (cherry picked from commit f1bdd5b13a1bdca81243b4aa1d8529f0485d3671)
| * | | Merge pull request #337 from Sssnowyyy/nx2-review-fixesJonas28 hours11-64/+121
| |\ \ \ | | | | | | | | | | nx2: fix pokopia regressions, textures that handle shader computes, and more
| | * | | vulkan: repack 69-byte vertices without dynamic vertex input on MoltenVKSssnowyyy30 hours6-10/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | e38b738b84 repacks the 69-byte vertex stride to 72 only with dynamic vertex input, unless EGLANTINE_EXPERIMENTAL_STATIC_VERTEX_REPACK=1. MoltenVK has no VK_EXT_vertex_input_dynamic_state and Metal needs strides that are a multiple of 4, so the stride was never fixed on Macs. Enable the static path automatically when the device's minimum vertex binding stride alignment does not divide 69. The device reports 4 for MoltenVK, matching its portability subset limit. The environment variable still overrides it: 1 forces the repack on, 0 forces it off. Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
| | * | | vk_pipeline_cache: keep the pipelines on MoltenVK and preload eight sessionsSssnowyyy30 hours1-4/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 5de94bdd1d cut the boot preload to the last two sessions and 2f94fb9680 evicts pipelines unused for 9000 frames, both because rebuilding one costs 2-3 ms through the driver's pipeline cache and each holds ~0.45 MB of driver memory. On MoltenVK a pipeline built while playing is translated from SPIR-V to MSL and compiled by Metal, which takes far longer even with a VkPipelineCache and shows as a stutter. On MoltenVK, keep the previous eight sessions' pipelines in vulkan_used.bin (be76402ab5's window) so they are built at boot, and do not evict. The memory is bounded by what a title builds; the stutter is not. Other drivers are unchanged and EDEN_NX2_PRELOAD_ALL_PIPELINES=1 still builds every cached pipeline. Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
| | * | | vulkan: back a sparse tiled image whole when its tiles can't be set upSssnowyyy30 hours1-13/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the aliased mode (AMD) a SparseTiles image is created unbound, and only InitSparseTiles binds every block to the shared zeroed one. When it fails (an unusual block shape, no memory for the zeroed block or the mip tail, a failed bind), the constructor went on to the next branch and flagged the image UnwrittenSparse with nothing bound. AMD's drivers can't sample such an image, and it is sampled before its first write replaces it, which is the hang a855e8373f avoided for large sparse images. Create the image again as an ordinary backed image in that case, as before sparse tiles, and drop the Unbacked flag. The other modes keep falling back to UnwrittenSparse, since their drivers sample unbound memory. Follow-up to 130c255ed9 (with a855e8373f and 1c794af564). Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
| | * | | vulkan: repack 69-byte vertices only when neededSssnowyyy30 hours5-12/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | SetVertexRepackLayout returned old_mask | new_mask, which stays non-zero on every draw that uses a 69-byte binding. PrepareDraw then re-dirtied the vertex buffers and vertex input each time, so the repack compute pass ran and the render pass ended once per draw, which is costly on tiled GPUs. Return old_mask ^ new_mask so only a layout change re-dirties the bindings. The repacked copy only stays valid while the source data is unchanged, so the buffer cache now flags the vertex buffers overlapping a CPU write, inline or DMA write, or GPU write, and re-dirties the repacked ones before binding. Command buffer submission already invalidates all vertex buffer state, which keeps the staging copy within its tick. Also pass the source buffer size to the repack pass and clamp the word-rounded storage descriptor range to it; it could run up to three bytes past the end of the buffer. A binding that does not fit is skipped like one over the device limits. Follow-up to e38b738b84. Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
| | * | | shader: evaluate handle programs for image and texture buffer descriptorsSssnowyyy30 hours2-25/+22
| | |/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 561f87abec only gave TextureDescriptor a handle_program. Image load/store/atomics and texture/image buffers whose handle comes from a storage buffer still got the placeholder constant buffer address (index 0, offset 0), so the pipelines read cbuf 0 word 0 as the handle (and asserted if cbuf 0 was unbound). Add handle_program to TextureBufferDescriptor, ImageBufferDescriptor and ImageDescriptor, compare it when merging, and let all four pipelines evaluate it for every descriptor kind instead of only TextureDescriptor. ImageQueryDimensions on such a handle was always declared Color2D, so array, cube and 3D views got a 2D declaration. The instruction carries no type, so take it from another instruction using the same handle program, falling back to Color2D when there is none. Follow-up to 561f87abec. The OpenGL pipeline edits are the same change as the Vulkan ones but were not compiled here. Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
| * | | Merge pull request #284 from Djihads80/fix/nx2-upscale-fallback-srgbJonas28 hours2-1/+7
| |\ \ \ | | |/ / | |/| | nx2: decode sRGB in the upscale fallback when the program does (washed-out Splatoon Raiders)
| | * | nx2: decode sRGB in the upscale fallback when the program doesTakoroka43 hours2-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Splatoon Raiders' upscaler program ends by decoding its result from sRGB to linear (HSETP2 against 0.04045, HMUL2 by 2.4 between MUFU.LG2 and MUFU.EX2) before its surface store. The bilinear copy that stands in for it while HMMA isn't emulated wrote the sRGB input as-is, so the later passes encoded it a second time: outdoor scenes were washed out, with a pale sky and a white haze. When the program carries those two immediates, the copy now decodes like it, through a new copy operation of the blit helper (a fragment shader with the piecewise sRGB decode). Programs without them, such as Kirby Air Riders' upscaler, keep the plain copy. The OpenGL backend ignores the operation.
* | | | video_core: replace Fortune's Weave's DLSS with AMD FSR 3.1Duck91229 hours9-14/+975
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fire Emblem: Fortune's Weave's DLSS network can't run here, and the temporal stand-in is only an approximation of it. FSR 3.1 takes the same inputs DLSS does: the jittered colour, motion vectors, the jitter and the depth, which the game's first DLSS pass reads through cbuf0+0x298 (Z32, reversed, the colour's size). Kepler compute keeps it next to the motion vectors. Fsr3Upscaler ports the host side of the SDK's ffx_fsr3upscaler.cpp: the eight passes (prepare inputs, luma and shading-change pyramids, shading change, reactivity, luma instability, accumulate, RCAS), the internal images and the constants, recorded through the scheduler with the shaders from externals/FidelityFX-SDK. It takes HDR colour, render-size motion vectors and reversed depth, computes its own exposure, and uses the no-wave SPD variants on devices without compute quad operations. The SDK's GLSL uses separate textures and samplers, so DescriptorBankInfo gains sampled image and sampler counts (default 0). FSR's RCAS follows the RCAS Sharpness slider. The result goes to FSR's own RGBA16F image and is drawn into the game's output, which keeps its format. TextureCacheRuntime::TemporalUpscale runs FSR 3.1 first. Without the depth, at mismatched scales, on a device lacking FSR's formats or features, or if its pipelines fail to build, the stand-in runs instead, and the bilinear blit stays last. EDEN_NX2_DLSS_REPLACEMENT=standin forces the stand-in. A gap of more than 250 ms between evaluations restarts the history. The BlitColor overload that takes a raw image view transitions its source to SHADER_READ_ONLY_OPTIMAL but described it as GENERAL in the descriptor (a validation error); it now describes the layout it uses. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com>
* | | | video_core: sharpen the temporal DLSS stand-inDuck91229 hours4-124/+302
|/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fire Emblem: Fortune's Weave's DLSS input matches Eden's (same 720p image, same detail), but the stand-in's 1440p output was blurrier than a plain bilinear 2x of it (Laplacian 0.0066 vs 0.0081; Eden's real DLSS 0.0111), and the image drifted darker over time: - the sample kernel was about twice too wide for the output resolution; - the history was kept in the output's B10G11R11 format, whose 5-6 bit mantissas round away a frame's 0.03-0.1 share; - the 1-sigma neighbourhood clip removed detail that only some jitter positions sample (railings, thin edges). The history is now an RGBA16F pair the shader writes as a storage image, with no per-frame copy. Still pixels use a third of the kernel width and a 1.5-sigma clip, so detail from many jitter positions accumulates. Moving pixels keep the old kernel and 1-sigma clip, and so do pixels that moved recently or whose history falls far outside the neighbourhood (content that changes without motion vectors), remembered in the history's alpha. Static output goes from 0.0066 to 0.0102 with no brightness drift and no new ghosting. With resolution scaling the stand-in used to fall back to a bilinear blit. The images are now scaled up as BlitImage does, the jitter is scaled to host pixels and the history follows the framebuffer's render area. RCAS (temporal_sharpen.frag) sharpens a copy of each result, never the history, in range-compressed space since the output is HDR. Its strength is the sharpness slider, relabelled "RCAS Sharpness" (0% turns it off). EDEN_NX2_TEMPORAL_KERNEL, _CLIP, _KERNEL_MOTION, _CLIP_MOTION and _WEIGHT tune the filter (all four filter values at 1 give the old one), and EDEN_NX2_TEMPORAL_SHARPEN=<stops>|off overrides the slider. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com>
* | | nx2: read GPU-written command lists from copies instead of drainingTakoroka34 hours4-1/+52
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The trees fix (#52) drains the split and flushes for every command list on a GPU-written page: in a Mario Kart World race ~13,500 lists and ~400 GPU round trips a second, during which the back has nothing to do. The replay ran at ~40 fps instead of ~45. The front now marks the pages those lists are on. The buffer cache notes writes to them; after a compute dispatch or DMA copy that writes one it copies the page into host memory and submits. The front waits for the back only up to the last compute or copy work it sent (not everything queued), then reads the copy once the GPU is done with it. Pages the GPU wrote once, long before, and the CPU now writes lists to have no copy: their first list drains and flushes the whole page, which is then read from guest memory until GPU work writes it again. CPU writes and inline uploads reach guest memory, so they keep such a page synced but make a copy stale. A page a draw writes always drains. Mario Kart World time-trial replay, Radeon 780M: ~40 -> ~45 fps, trees drawn, no list drains left.
* | | Merge nx2 into nx2-experimentalkraibse37 hours15-11/+608
|\ \ \ | | |/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Resolved by area: - audio feature_support.h: nx2's native revision handling. - fiber.cpp: ours, which also drops the unused rewind stack. - host_memory.cpp: ours granule bitmap and HintCold, plus nx2's fallocate hole punching per whole dirty granule on Linux. - texture_cache.h: nx2's old-age eviction pass, then our Collect(). - kepler_compute.cpp: shared upscale slots, then Fortune's Weave's, then the Kirby Air Riders scan. - nx2_gsv.h: ours, plus nx2's GetBufferMaxResolution and graphics device ids (1-based). - nvhost_ctrl_gpu.cpp: engine support flag bits 40-44. - lower_to_maxwell.h: ours as the base, with nx2's seven lowering commits applied one at a time. Second texture descriptor buffers are read bindless in TEX, TLD.SCR (level zero) and SUST; FSEL keeps its operand modifiers; TXD takes any channel mask. lower_to_maxwell.h lowers 837 Fortune's Weave and 1183 Mario Kart World shader dumps with the same rejects as nx2 and ours (12 and 0). Assisted-by: Claude Sonnet 5.5 (conflict analysis and drafting)
| * | Linux and AMD: BC3 flashing on RADV, ASTC decode stalls, lower RAM usage, a ↵Whovian6443 hours4-9/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | buffer cache crash (#260) * host_memory: punch holes in the backing on Linux instead of zero filling freed memory Freeing guest memory zero filled the memfd backing with memset, which commits every page it touches. fallocate(PUNCH_HOLE) hands the pages back to the kernel instead, and they read as zero afterwards. Only the partial pages at the ends are still cleared by hand. Mario Kart World on Linux (RX 9070 XT, 31 GB): peak RSS 23.1 -> 15.9 GB. EDEN_PUNCH_HOLE=0 restores the memset. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * fiber: don't zero fill the stacks, untouched pages stay unbacked The value initialised stack arrays were zero filled when each fiber was made, which commits the whole stack. Left uninitialised, the pages a fiber never touches stay unbacked. Together with the descriptor ring change, about 1.2 GB less RSS in Mario Kart World. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * vulkan: don't zero fill the descriptor update ring Same as the fiber stacks: make_unique value initialised the whole ring for every frame in flight. Entries are always written before they are read, so allocate it without initialising it. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * vulkan: wait for the GPU after an ASTC transcode decode like the other ASTC decodes TranscodeAstcToBcn (astc_recompression Bc1/Bc3 with GPU decode) was the only ASTC decode recorded with wait = false. On RADV (RX 9070 XT, Mesa) Mario Kart World with BC3 flashed heavily all over the screen, while the uncompressed GPU decode, which waits, did not. CPU decode with BC3 does not flash either. Waiting after the transcode removes the flashing; full pipeline barriers around its copy did not, so the wait hides a race somewhere else rather than fixing one in the transcode itself. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * vulkan: submit after an ASTC decode instead of waiting for the GPU by default Every ASTC decode ended with scheduler.Finish(). Over a 19 minute Mario Kart World Grand Prix that stalled the GPU thread 30.7 s in total, up to 1.2 s out of every 5 s while new textures stream in (track sections, race starts), which is where the hitches were. Flushing keeps the ordering that stops the BC3 flashing on RADV without the CPU waiting: no flashing in play, and frames over 100 ms went from dozens to 3 in about 7 minutes. EDEN_NX2_ASTC_FLUSH=0 restores the wait. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * texture_cache: over the expected use, evict costly images unused for 1800 frames first The collector never deletes CostlyLoad images outside aggressive mode, so once a cup moves on, the previous tracks' textures stay resident and the cache sits over its expected use deleting the cheap images still in use. When over the expected use, costly images unused for 1800 frames (half a minute) now go first. Mario Kart World Grand Prix on an RX 9070 XT: frames over 20 ms 8.8% -> 4.0%, 58.7 fps average. EDEN_NX2_TC_OLD_AGE=<frames> sets the age, 0 turns it off. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts) * buffer_cache: no buffer for device addresses past the page table FindBuffer indexed page_table, which covers 2^36 bytes, with any address. Mario Kart World crashed after about 4.5 minutes with a uniform buffer at 0x72253b2f2890 (FindBuffer <- UpdateUniformBuffers <- DrawEnd from a macro), reading far past the table. Treat such an address as no buffer. Where that address comes from is still unknown; this only stops the crash. Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)
| * | vulkan: repack 69-byte vertices to 72 bytes (#281)Mako43 hours7-2/+258
| |/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Splatoon Raiders draws with a 69-byte vertex stride and a packed 4-byte attribute at byte 65. Those fetches are unaligned, which Vulkan leaves undefined: NVIDIA reads them as meant, the AMD Windows driver does not, and the outdoor scenes turn into a white haze with horizontal streaks. When a binding uses that layout, a compute pass copies it to a 72-byte stride with the tail moved to byte 68, and the vertex input offsets and stride follow. EGLANTINE_TEST_VERTEX_REPACK=0 turns it off; EGLANTINE_EXPERIMENTAL_STATIC_VERTEX_REPACK=1 also covers pipelines without dynamic vertex input. Based on an outside patch (02-portable-vertex-repacking). Changes from it: a range over the device limits skips the repack instead of throwing, and the pipeline cache version stays, so caches are kept.
| * video_core: temporal upscale stand-in for Fortune's Weave's DLSSDuck91247 hours6-0/+338
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The one-frame blit left 3D edges aliased and shaking: the game jitters its camera every frame for DLSS to accumulate. Fire Emblem: Fortune's Weave's first DLSS pass (also rejected) has the motion vectors (cbuf0+0x290, R16G16) and the frame's jitter (+0x1b0/+0x1b4, in input pixels). Kepler compute keeps them, and the stand-in for the last network pass now draws temporal_upscale.frag: input samples placed where the jitter put them and weighted by distance, blended with the previous result reprojected along the motion vectors (Catmull-Rom) and clipped to the 3x3 neighbourhood in YCoCg. The history is copied from the result right after drawing it, so post-processing the game later applies to its output does not feed back. EDEN_NX2_TEMPORAL_UPSCALE=0 restores the blit. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com>
| * nx2:vi2: crop presents to their frame size and honour RGB10A2 imagesduck9122 days1-0/+2
| | | | | | | | | | | | | | | | | | | | | | Present word 7 holds the size of the frame drawn into the image's top-left corner, and image preference word 6 its format (1 RGBA8, 4 RGB10A2). Fire Emblem: Fortune's Weave draws 1280x720 RGB10A2 frames into 3840x2160 images; showing the whole image as RGBA8 gave a corner of wrongly decoded pixels. Assisted-by: Claude Opus 5.5 (debugging, porting and drafting) Signed-off-by: duck912 <350528965+Duck912@users.noreply.github.com>
* | texture_cache: keep the allocator's block slack out of the usable VRAMkraibse2 days2-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The collector's usage leaves out the unused part of VMA's blocks, but the driver counts it and a heap at its budget cannot give it to a new image. On an RX 7800 XT that slack was 1.06 GiB, the whole 1 GiB margin: the heap sat at its budget for a minute while the collector saw room, then images stopped fitting and the process died. Reserve the slack (capped at 1.5 GiB) on top of the margin: at once when it grows, slowly when it shrinks, so eviction leaving partly used blocks doesn't chase the threshold down. Assisted-by: Claude Sonnet 5.5 (diagnosis and code) (cherry picked from commit 73fd5a489ea28226fa16a55f5008e622d631b54c)
* | vulkan: don't make small images unbacked when device memory runs outkraibse2 days1-0/+5
| | | | | | | | | | | | | | | | | | | | When VRAM ran out, any image that failed to allocate became a sparse image with nothing bound, which AMD's drivers don't survive being sampled (an RX 6600 died mid-flood, an RX 7800 XT made 211 of them, 8x8 ones included). Try host memory first, and count the images that didn't fit: the texture cache then keeps more room under the budget (512 MiB a step, up to 3 GiB, decaying) so its collector runs earlier. The sparse fallback stays for images too large to back.
* | nx2: capture and lower native shader programs oncekraibse2 days1-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | Native programs were captured and lowered when their ShaderInfo was made and again for every environment built for their pipelines. The ShaderInfo now keeps the lowered code and the environments adopt it. Capture also reads a 4 KiB page at a time instead of flushing caches per instruction, and cached native programs fold bank 1 reads like live ones. Ported from Wael3rd/Eglantine-MKW (0ae093058e, 65a6aa877a, df076133c4). Assisted-by: Claude Sonnet 5.5 (porting the fixes) (cherry picked from commit 3af11ac401ad3061c183281d8c98c16c1d6da456)
* | vulkan: don't divide by a zero sparse block size (AMD)kraibse2 days1-1/+47
| | | | | | | | | | | | | | | | | | | | | | | | Image::InitSparseLayers divided by the imageGranularity the driver returns, which AMD's driver reports as 0 and crashed. Use Vulkan's standard 2D block shape when the device reports residencyStandard2DBlockShape, otherwise don't use sparse layers. Ported from Wael3rd/Eglantine-MKW (7a77946af3). Assisted-by: Claude Sonnet 5.5 (porting the fix) (cherry picked from commit eadb9fc0f06f32ff1684fe202519c0505669095d)
* | texture_cache: collect images in the emptiest device memory blocks firstTakoroka2 days1-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | Deleting by age alone left every block partly used: the collector deletes thousands of images a minute and new ones land in the holes, so blocks seldom empty (title 1: ~0.8 GB of holes in ~190 32 MiB blocks after ten minutes, counted by the driver as used). Among the oldest candidates, 8 per image a pass may delete, those in the emptiest blocks go first, so blocks drain and VMA returns them; placement already prefers the fullest blocks. (cherry picked from commit 2f8f0716fafd874cfbb3cc9086141aea61aff2df)
* | Merge remote-tracking branch 'origin/fix/vk-astc-array-trim-small-gpus' into ↵Takoroka2 days1-1/+16
|\ \ | | | | | | | | | test/linux-all-prs-plus
| * | vk_texture_cache: trim huge ASTC arrays harder on small GPUsTakoroka5 days1-1/+16
| | | | | | | | | | | | | | | | | | | | | | | | A trimmed ASTC array kept up to 512 MiB on the host. On GPUs with less than 7 GiB it now keeps up to 256 MiB (one mip level less): Mario Kart World's two terrain arrays took 724 MiB of a 6 GB card next to ~1.2 GB of other sparse terrain textures. EDEN_NX2_ASTC_ARRAY_MIB=<MiB> sets the limit.
* | | Merge remote-tracking branch 'origin/fix/vk-evict-unused-pipelines' into ↵Takoroka2 days4-0/+201
|\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | test/linux-all-prs # Conflicts: # src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
| * | | vk_pipeline_cache: cap boot builds when no used list exists yetTakoroka2 days1-2/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Without vulkan_used.bin (the first boot with this change, or a session that ended before saving it) every cached graphics pipeline was still built at boot. A Linux tester's cache had grown to 47,951 pipelines over many builds: ~21 GB of driver memory built before the game started, filling RAM and swap. The list is only saved at exit or after two minutes, so a boot that ran out of memory never saved one and the next boot did the same. Build at most 3,000 cached graphics pipelines at boot in that case and the rest when first needed; the next session uses the saved list. EDEN_NX2_PRELOAD_ALL_PIPELINES=1 still builds all of them.
| * | | vk_pipeline_cache: destroy graphics pipelines unused for 9000 framesTakoroka3 days4-1/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Each built pipeline holds ~0.45 MB of driver memory and none was ever destroyed, so it grew with every place a session went. One unused for 9000 frames is destroyed once the GPU is past it and built again from the driver's pipeline cache (2-3 ms) if it is needed later; the transitions between pipelines are cleared, and pipelines used this session still go to the used list. Mario Kart World's title screen, 10 minutes: 1,714 evicted, 1,700-1,850 kept instead of a count that only grows. (cherry picked from commit 24a37800034f83ec1d8fe9e8e5642d27eb2935b8)
| * | | vk_pipeline_cache: build only the last two sessions' pipelines at bootTakoroka3 days1-2/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Each pipeline built at boot holds ~0.45 MB of driver memory. Mario Kart World built 4,789 from the eight sessions the list kept, while one session of its title screen uses ~1,500. With the last two sessions it built 1,035 at boot and 972 when first needed: the emulator's own memory at five minutes 6.4 -> 5.6 GB, frames over 100 ms 9 -> 10 (none built at boot: 4.9 GB, but 38 frames over 100 ms). Lists saved with the longer window are trimmed when they are loaded.
| * | | vulkan: build at boot only the cached pipelines recent sessions usedTakoroka4 days2-0/+104
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Every graphics pipeline in the disk cache was built at boot, and each one holds driver memory: Mario Kart World builds 6.5k (the NVIDIA driver keeps ~1.6 GB for them) and a session uses about a quarter. Record the pipelines each session uses in <title>/vulkan_used.bin (key hash + sessions since the last use, dropped after 8), build only those at boot and the rest when a game first needs them, without storing them in the disk cache again. The first session without the file builds everything as before. EDEN_NX2_PRELOAD_ALL_PIPELINES=1 keeps building all of them.
* | | | Merge remote-tracking branch 'origin/fix/vk-transcode-reuse-decode-images' ↵Takoroka2 days2-26/+73
|\ \ \ \ | | | | | | | | | | | | | | | into test/linux-all-prs
| * | | | vulkan: reuse ASTC transcode decode imagesTakoroka3 days2-26/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The RGBA8 image an ASTC texture is decoded into before BC1/BC3 compression was made for each texture (263 us) and freed once the GPU was past it. Once the GPU is done with one it now decodes the next texture of the same shape: title 1's title screen decodes dozens of textures a frame, mostly of a few shapes. Free ones are kept up to 256 MiB and destroyed after 60 unused frames. Taking them from VMA's shared blocks instead was faster (90 us), but freeing dozens a frame there left ~1 GB of those blocks unused. Against that, Mario Kart World's title screen over 10 minutes: VRAM in use 6.34 -> 5.90 GB on average, peak 6.99 -> 6.45 GB.
* | | | | Merge remote-tracking branch 'origin/fix/vk-stream-buffer-128mib' into ↵Takoroka2 days1-1/+2
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | test/linux-all-prs
| * | | | | vk_staging_buffer_pool: 128 MiB stream buffer everywhereTakoroka3 days1-1/+2
| |/ / / / | | | | | | | | | | | | | | | | | | | | 256 MiB sat mostly unused in device memory on Switch 2 titles. FreeBSD already used 128 MiB.
* | | | | Merge remote-tracking branch 'origin/fix/vk-no-pipeline-cache-nv-amd' into ↵Takoroka2 days1-1/+18
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | test/linux-all-prs
| * | | | | vk_pipeline_cache: leave the pipeline cache to NVIDIA's and AMD's driversTakoroka3 days1-1/+18
| |/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Their drivers keep a disk cache of built pipelines of their own. Eden's VkPipelineCache on top loaded every pipeline the title ever built into host memory (title 1: a 245 MB file) and copied it whole at each save. Without it, title 1's title screen over ten minutes: private memory -373 MiB, frames over 100 ms 30 -> 21, worst frame 141 -> 94 ms, and pipelines built as fast (2.26 vs 2.46 ms each on the GPU thread). (cherry picked from commit ea3dcd444cad7de301ec949a350cc45abb48d3bf)
* | | | | Merge remote-tracking branch 'origin/fix/vk-free-shader-modules' into ↵Takoroka2 days2-1/+10
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | test/linux-all-prs
| * | | | | vulkan: drop shader modules once their pipeline is builtTakoroka3 days2-1/+10
| |/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Nothing reads a pipeline's shader modules after the pipeline exists, and the driver keeps a copy of each module's SPIR-V for as long as it lives: title 1 keeps ~1,500 graphics pipelines with 2-5 modules each. The graphics pipeline picks its configure function before queuing the build, which now frees what it looks at. (cherry picked from commit aaa414ec1dd96e466282b0c4501574cbe7c2494e)
* | | | | Merge remote-tracking branch 'origin/fix/tc-count-sentenced' into ↵Takoroka2 days2-0/+13
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | test/linux-all-prs
| * | | | | texture_cache: free deleted images once the GPU is past themTakoroka3 days2-0/+13
| |/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Deleted images kept their device memory for TICKS_TO_DESTROY (8) frames. While the collector deletes dozens a frame that held 1-1.5 GB of VRAM on top of its threshold, which the collector does not count (Mario Kart World on an 8 GB card: 6.6-7.0 GB in use against 5 GiB). On runtimes that report GPU progress (Vulkan) an image is destroyed as soon as the GPU is past it. Title screen, 10 minutes: VRAM in use 6.75 -> 6.34 GB on average, frames over 100 ms 22 -> 15. (cherry picked from commit 8c899541baf398deb892a857a932590f32d2aa4f)
* | | | | Merge remote-tracking branch 'origin/fix/pipeline-dump-exception' into ↵Takoroka2 days1-1/+6
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | test/linux-all-prs
| * | | | | vulkan: keep a failing shader's dump from ending the processTakoroka4 days1-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a graphics pipeline's translation throws, its handler walks each program again to dump it. A program whose flow cannot be analyzed (an indirect branch Nintendo Switch Sports Resort uses) throws again there, the exception leaves the handler and the process ends. Contain it, so the pipeline fails, the error is logged and the title goes on.
* | | | | | Merge remote-tracking branch 'origin/fix/nx2-storage-buffer-texture-handles' ↵Takoroka2 days2-0/+29
|\ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | into test/linux-all-prs
| * | | | | | shader: compute texture handles read from storage buffers for each drawTakoroka3 days2-0/+29
| | |/ / / / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Switch 2 shaders can read a texture handle from a storage buffer (Switch Sports' scenery: a per-object entry of a table whose pointer is in the driver constant buffer). The bindless handle search looked through the load into its address and returned the table pointer's constant buffer word as the handle, which named an arbitrary descriptor; the game repoints that one at transient render targets every few seconds, so the island and menu lighting flipped between correct, dark and red. The search no longer looks into memory loads. A handle it cannot trace is now built into a small program over constant buffer words, storage buffer words and integer operations (Shader::Info::handle_programs), which the pipelines evaluate when they bind the texture. Handles a single evaluation cannot give (one that changes in a loop) keep the previous search.
* | | | | | Merge remote-tracking branch 'origin/fix/nx2-igpu-stream-buffer' into ↵Takoroka2 days1-0/+13
|\ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | test/linux-all-prs