The chunked grass path draws each chunk as one mesh-shader dispatch when the setting asks and the card has VK_EXT_mesh_shader: work group y is a tile, x a batch of 16 of its blades, and a blade the placement, density, frustum, water or slope tests reject emits nothing - the instanced path still runs its eight vertices to a degenerate position. grass.mesh generates the same blades as grass.vert (grass_blade_mesh(4)'s rows, the same hashes, sway and lighting normal), capped at the instanced path's 65535 a tile. Vulkan: VK_EXT_mesh_shader with meshShader, and maintenance4 (glslang's mesh stages declare LocalSizeId); vkCmdDrawMeshTasksEXT looked up per device, as the Streamline interposer exports none; a *.mesh program's pipeline takes the mesh stage and no vertex input, its bindings the mesh stage bit. gpu_has_mesh, gpu_draw_mesh_tasks; r3d_mesh_grass and R3D_MESH_GRASS / R3D_NO_MESH. bin/ludic-dev rebuilt: the committed binary predated the shader tool's mesh support and compiled grass.mesh as a vertex stage. PC (RTX 3070 Ti): the camp matches the chunked path; validation only the no-window present-id message. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
48 lines
3.7 KiB
Text
48 lines
3.7 KiB
Text
# ============================================================================
|
|
# vk.ludic — Vk.*: Vulkan for Ludic.
|
|
#
|
|
# Every command of Vulkan 1.0-1.4 and of the extensions the render3d Vulkan renderer
|
|
# is built around is bound in vk_api.ludic (generated by `ludic-dev vkgen` from the
|
|
# Vulkan registry), with every constant and every struct's size and field offsets.
|
|
# Vk.<snake_name>(...) calls one: Vk.create_instance(info, null, out). Structs are
|
|
# plain memory filled by field name:
|
|
# let ci = bytes(VkInstanceCreateInfo_sizeof)
|
|
# Vk.zero(ci, VkInstanceCreateInfo_sizeof)
|
|
# Vk.put_i32(ci, VkInstanceCreateInfo_sType, VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
|
|
#
|
|
# Numbers: a C float is float bits in an int; uint64_t, VkDeviceSize and
|
|
# non-dispatchable handles are `long`. A negative long has to come from a `long`
|
|
# variable - an int literal passed straight to a long parameter is zero-extended.
|
|
#
|
|
# The loader is opened at run time by Vk.open() (vk_win.ll / vk_mac.ll), never
|
|
# linked: 0 means this machine has no Vulkan, and the program carries on without it.
|
|
# ============================================================================
|
|
|
|
import "vk_api.ludic"
|
|
|
|
# Streamline (NVIDIA DLSS, Ray Reconstruction, Frame Generation, Reflex), Windows only: Vk.sl_prefer(1)
|
|
# before Vk.open() loads sl.interposer.dll as the Vulkan loader when it is beside the program, and
|
|
# Vk.sl_active() says whether it was. Each Vk.sl_* is the sl* export of the same name and returns
|
|
# its sl::Result (0 is eOk); -1 means there is no Streamline (macOS, or the DLL missing). The
|
|
# structs are plain memory, laid out as the SDK headers (include/sl_*.h, SDK 2.14.1) declare them.
|
|
extern function vk_sl_prefer(on: int) = "lvk_sl_prefer"
|
|
extern function vk_sl_active() -> int = "lvk_sl_active"
|
|
extern function vk_sl_init(pref: pointer, sdk_version: long) -> int = "lsl_slInit"
|
|
extern function vk_sl_shutdown() -> int = "lsl_slShutdown"
|
|
extern function vk_sl_is_feature_supported(feature: int, adapter_info: pointer) -> int = "lsl_slIsFeatureSupported"
|
|
extern function vk_sl_is_feature_loaded(feature: int, loaded: pointer) -> int = "lsl_slIsFeatureLoaded"
|
|
extern function vk_sl_get_feature_requirements(feature: int, requirements: pointer) -> int = "lsl_slGetFeatureRequirements"
|
|
extern function vk_sl_get_feature_function(feature: int, name: pointer, function_out: pointer) -> int = "lsl_slGetFeatureFunction"
|
|
extern function vk_sl_get_new_frame_token(token_out: pointer, frame_index: pointer) -> int = "lsl_slGetNewFrameToken"
|
|
extern function vk_sl_set_tag_for_frame(frame: pointer, viewport: pointer, tags: pointer, num_tags: int, cmd_buffer: pointer) -> int = "lsl_slSetTagForFrame"
|
|
extern function vk_sl_set_constants(constants: pointer, frame: pointer, viewport: pointer) -> int = "lsl_slSetConstants"
|
|
extern function vk_sl_evaluate_feature(feature: int, frame: pointer, inputs: pointer, num_inputs: int, cmd_buffer: pointer) -> int = "lsl_slEvaluateFeature"
|
|
extern function vk_sl_free_resources(feature: int, viewport: pointer) -> int = "lsl_slFreeResources"
|
|
# a feature function obtained with Vk.sl_get_feature_function, called with its arguments
|
|
extern function vk_sl_call_p(fn: pointer, a: pointer) -> int = "lsl_call_p"
|
|
extern function vk_sl_call_pp(fn: pointer, a: pointer, b: pointer) -> int = "lsl_call_pp"
|
|
extern function vk_sl_call_ppp(fn: pointer, a: pointer, b: pointer, c: pointer) -> int = "lsl_call_ppp"
|
|
extern function vk_sl_call_ip(fn: pointer, a: int, b: pointer) -> int = "lsl_call_ip"
|
|
# a command-buffer command with three counts through a pointer (vkCmdDrawMeshTasksEXT, which the
|
|
# Streamline interposer does not export; looked up with vkGetDeviceProcAddr)
|
|
extern function vk_sl_call_piii(fn: pointer, a: pointer, b: int, c: int, d: int) = "lsl_call_piii"
|