software

package
v0.25.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 14 Imported by: 1

Documentation

Overview

Package software provides a CPU-based software rendering backend.

Status: IMPLEMENTED (Phase 1 - Headless Rendering)

The software backend implements all HAL interfaces using pure Go CPU rendering. Unlike the noop backend, it actually performs rendering operations in memory.

Use cases:

  • Headless rendering (servers, CI/CD)
  • Screenshot/image generation without GPU
  • Testing rendering logic without GPU hardware
  • Embedded systems without GPU
  • Fallback when no GPU backend is available

Implemented features (Phase 1):

  • Real data storage for buffers and textures
  • Clear operations (fill framebuffer/texture with color)
  • Buffer/texture copy operations
  • Framebuffer readback via Surface.GetFramebuffer()
  • Thread-safe resource access

Limitations:

  • Much slower than GPU backends (CPU-bound)
  • No hardware acceleration
  • No compute shaders (returns error)
  • No rasterization yet (draw calls are no-op - Phase 2)
  • No shader execution (basic resources only)

Always compiled (no build tags required).

Example:

import _ "github.com/gogpu/wgpu/hal/software"

// Software backend is registered automatically
// Adapter name: "Software Renderer"
// Device type: types.DeviceTypeCPU

Backend identifier: types.BackendEmpty

Index

Constants

This section is empty.

Variables

View Source
var ErrComputeNotSupported = errors.New("software: compute shaders not supported")

ErrComputeNotSupported indicates that compute shaders are not available in the software backend. The software backend only supports rasterization; use a GPU-accelerated backend (Vulkan, Metal, DX12) for compute workloads.

Functions

This section is empty.

Types

type API

type API struct{}

API implements hal.Backend for the software backend.

func (API) CreateInstance

func (API) CreateInstance(_ *hal.InstanceDescriptor) (hal.Instance, error)

CreateInstance creates a new software rendering instance. Always succeeds and returns a CPU-based rendering instance.

func (API) Variant

func (API) Variant() gputypes.Backend

Variant returns the backend type identifier.

type Adapter

type Adapter struct{}

Adapter implements hal.Adapter for the software backend.

func (*Adapter) Destroy

func (a *Adapter) Destroy()

Destroy is a no-op for the software adapter.

func (*Adapter) Open

Open creates a software device with the requested features and limits. Always succeeds and returns a device/queue pair.

func (*Adapter) SurfaceCapabilities

func (a *Adapter) SurfaceCapabilities(_ hal.Surface) *hal.SurfaceCapabilities

SurfaceCapabilities returns default surface capabilities.

func (*Adapter) TextureFormatCapabilities

func (a *Adapter) TextureFormatCapabilities(_ gputypes.TextureFormat) hal.TextureFormatCapabilities

TextureFormatCapabilities returns default capabilities for all formats.

type BindGroup added in v0.21.3

type BindGroup struct {
	Resource
	// contains filtered or unexported fields
}

BindGroup stores bound resources for the software backend. It resolves handle-based entries to concrete software resource pointers.

type Buffer

type Buffer struct {
	Resource
	// contains filtered or unexported fields
}

Buffer implements hal.Buffer with real data storage. All software buffers store their data in memory.

func (*Buffer) GetData

func (b *Buffer) GetData() []byte

GetData returns a copy of the buffer data (thread-safe).

func (*Buffer) NativeHandle

func (b *Buffer) NativeHandle() uintptr

NativeHandle returns the buffer's unique ID for handle resolution.

func (*Buffer) WriteData

func (b *Buffer) WriteData(offset uint64, data []byte)

WriteData writes data to the buffer (thread-safe).

type CommandEncoder

type CommandEncoder struct{}

CommandEncoder implements hal.CommandEncoder for the software backend.

func (*CommandEncoder) BeginComputePass

func (c *CommandEncoder) BeginComputePass(desc *hal.ComputePassDescriptor) hal.ComputePassEncoder

BeginComputePass begins a compute pass and returns an encoder.

func (*CommandEncoder) BeginEncoding

func (c *CommandEncoder) BeginEncoding(_ string) error

BeginEncoding is a no-op.

func (*CommandEncoder) BeginRenderPass

func (c *CommandEncoder) BeginRenderPass(desc *hal.RenderPassDescriptor) hal.RenderPassEncoder

BeginRenderPass begins a render pass and returns an encoder.

func (*CommandEncoder) ClearBuffer

func (c *CommandEncoder) ClearBuffer(buffer hal.Buffer, offset, size uint64)

ClearBuffer clears a buffer region to zero.

func (*CommandEncoder) CopyBufferToBuffer

func (c *CommandEncoder) CopyBufferToBuffer(src, dst hal.Buffer, regions []hal.BufferCopy)

CopyBufferToBuffer copies data between buffers.

func (*CommandEncoder) CopyBufferToTexture

func (c *CommandEncoder) CopyBufferToTexture(src hal.Buffer, dst hal.Texture, regions []hal.BufferTextureCopy)

CopyBufferToTexture copies data from a buffer to a texture.

func (*CommandEncoder) CopyTextureToBuffer

func (c *CommandEncoder) CopyTextureToBuffer(src hal.Texture, dst hal.Buffer, regions []hal.BufferTextureCopy)

CopyTextureToBuffer copies data from a texture to a buffer.

func (*CommandEncoder) CopyTextureToTexture

func (c *CommandEncoder) CopyTextureToTexture(src, dst hal.Texture, regions []hal.TextureCopy)

CopyTextureToTexture copies data between textures.

func (*CommandEncoder) Destroy added in v0.23.4

func (c *CommandEncoder) Destroy()

Destroy is a no-op for the software backend.

func (*CommandEncoder) DiscardEncoding

func (c *CommandEncoder) DiscardEncoding()

DiscardEncoding is a no-op.

func (*CommandEncoder) EndEncoding

func (c *CommandEncoder) EndEncoding() (hal.CommandBuffer, error)

EndEncoding returns a placeholder command buffer.

func (*CommandEncoder) ResetAll

func (c *CommandEncoder) ResetAll(_ []hal.CommandBuffer)

ResetAll is a no-op.

func (*CommandEncoder) ResolveQuerySet

func (c *CommandEncoder) ResolveQuerySet(_ hal.QuerySet, _, _ uint32, _ hal.Buffer, _ uint64)

ResolveQuerySet is a no-op (query sets not supported in software backend).

func (*CommandEncoder) TransitionBuffers

func (c *CommandEncoder) TransitionBuffers(_ []hal.BufferBarrier)

TransitionBuffers is a no-op (software backend doesn't need explicit transitions).

func (*CommandEncoder) TransitionTextures

func (c *CommandEncoder) TransitionTextures(_ []hal.TextureBarrier)

TransitionTextures is a no-op (software backend doesn't need explicit transitions).

type ComputePassEncoder

type ComputePassEncoder struct {
	// contains filtered or unexported fields
}

ComputePassEncoder implements hal.ComputePassEncoder for the software backend.

func (*ComputePassEncoder) Dispatch

func (c *ComputePassEncoder) Dispatch(_, _, _ uint32)

Dispatch is a no-op (compute not supported).

func (*ComputePassEncoder) DispatchIndirect

func (c *ComputePassEncoder) DispatchIndirect(_ hal.Buffer, _ uint64)

DispatchIndirect is a no-op.

func (*ComputePassEncoder) End

func (c *ComputePassEncoder) End()

End is a no-op.

func (*ComputePassEncoder) SetBindGroup

func (c *ComputePassEncoder) SetBindGroup(_ uint32, _ hal.BindGroup, _ []uint32)

SetBindGroup is a no-op.

func (*ComputePassEncoder) SetPipeline

func (c *ComputePassEncoder) SetPipeline(_ hal.ComputePipeline)

SetPipeline is a no-op (compute not supported).

type Device

type Device struct {
	// contains filtered or unexported fields
}

Device implements hal.Device for the software backend. It maintains a resource registry for resolving handle-based bind group entries back to typed software resources.

func (*Device) CreateBindGroup

func (d *Device) CreateBindGroup(desc *hal.BindGroupDescriptor) (hal.BindGroup, error)

CreateBindGroup creates a software bind group. It resolves handle-based entries to typed software resources using the device registry.

func (*Device) CreateBindGroupLayout

func (d *Device) CreateBindGroupLayout(_ *hal.BindGroupLayoutDescriptor) (hal.BindGroupLayout, error)

CreateBindGroupLayout creates a software bind group layout.

func (*Device) CreateBuffer

func (d *Device) CreateBuffer(desc *hal.BufferDescriptor) (hal.Buffer, error)

CreateBuffer creates a software buffer with real data storage.

func (*Device) CreateCommandEncoder

func (d *Device) CreateCommandEncoder(_ *hal.CommandEncoderDescriptor) (hal.CommandEncoder, error)

CreateCommandEncoder creates a software command encoder.

func (*Device) CreateComputePipeline

func (d *Device) CreateComputePipeline(_ *hal.ComputePipelineDescriptor) (hal.ComputePipeline, error)

CreateComputePipeline returns ErrComputeNotSupported. The software backend does not support compute shaders.

func (*Device) CreateFence

func (d *Device) CreateFence() (hal.Fence, error)

CreateFence creates a software fence with atomic counter.

func (*Device) CreatePipelineLayout

func (d *Device) CreatePipelineLayout(_ *hal.PipelineLayoutDescriptor) (hal.PipelineLayout, error)

CreatePipelineLayout creates a software pipeline layout.

func (*Device) CreateQuerySet

func (d *Device) CreateQuerySet(_ *hal.QuerySetDescriptor) (hal.QuerySet, error)

CreateQuerySet is not supported in the software backend.

func (*Device) CreateRenderBundleEncoder

func (d *Device) CreateRenderBundleEncoder(_ *hal.RenderBundleEncoderDescriptor) (hal.RenderBundleEncoder, error)

CreateRenderBundleEncoder is not supported in the software backend.

func (*Device) CreateRenderPipeline

func (d *Device) CreateRenderPipeline(desc *hal.RenderPipelineDescriptor) (hal.RenderPipeline, error)

CreateRenderPipeline creates a software render pipeline.

func (*Device) CreateSampler

func (d *Device) CreateSampler(_ *hal.SamplerDescriptor) (hal.Sampler, error)

CreateSampler creates a software sampler.

func (*Device) CreateShaderModule

func (d *Device) CreateShaderModule(desc *hal.ShaderModuleDescriptor) (hal.ShaderModule, error)

CreateShaderModule creates a software shader module.

func (*Device) CreateTexture

func (d *Device) CreateTexture(desc *hal.TextureDescriptor) (hal.Texture, error)

CreateTexture creates a software texture with real pixel storage.

func (*Device) CreateTextureView

func (d *Device) CreateTextureView(texture hal.Texture, _ *hal.TextureViewDescriptor) (hal.TextureView, error)

CreateTextureView creates a software texture view.

func (*Device) Destroy

func (d *Device) Destroy()

Destroy is a no-op for the software device.

func (*Device) DestroyBindGroup

func (d *Device) DestroyBindGroup(_ hal.BindGroup)

DestroyBindGroup is a no-op.

func (*Device) DestroyBindGroupLayout

func (d *Device) DestroyBindGroupLayout(_ hal.BindGroupLayout)

DestroyBindGroupLayout is a no-op.

func (*Device) DestroyBuffer

func (d *Device) DestroyBuffer(_ hal.Buffer)

DestroyBuffer is a no-op (Go GC handles cleanup).

func (*Device) DestroyComputePipeline

func (d *Device) DestroyComputePipeline(_ hal.ComputePipeline)

DestroyComputePipeline is a no-op.

func (*Device) DestroyFence

func (d *Device) DestroyFence(_ hal.Fence)

DestroyFence is a no-op.

func (*Device) DestroyPipelineLayout

func (d *Device) DestroyPipelineLayout(_ hal.PipelineLayout)

DestroyPipelineLayout is a no-op.

func (*Device) DestroyQuerySet

func (d *Device) DestroyQuerySet(_ hal.QuerySet)

DestroyQuerySet is a no-op for the software device.

func (*Device) DestroyRenderBundle

func (d *Device) DestroyRenderBundle(_ hal.RenderBundle)

DestroyRenderBundle is a no-op for the software device.

func (*Device) DestroyRenderPipeline

func (d *Device) DestroyRenderPipeline(_ hal.RenderPipeline)

DestroyRenderPipeline is a no-op.

func (*Device) DestroySampler

func (d *Device) DestroySampler(_ hal.Sampler)

DestroySampler is a no-op.

func (*Device) DestroyShaderModule

func (d *Device) DestroyShaderModule(_ hal.ShaderModule)

DestroyShaderModule is a no-op.

func (*Device) DestroyTexture

func (d *Device) DestroyTexture(_ hal.Texture)

DestroyTexture is a no-op (Go GC handles cleanup).

func (*Device) DestroyTextureView

func (d *Device) DestroyTextureView(_ hal.TextureView)

DestroyTextureView is a no-op.

func (*Device) FreeCommandBuffer

func (d *Device) FreeCommandBuffer(_ hal.CommandBuffer)

FreeCommandBuffer is a no-op for the software device.

func (*Device) GetFenceStatus

func (d *Device) GetFenceStatus(fence hal.Fence) (bool, error)

GetFenceStatus returns true if the fence is signaled (non-blocking).

func (*Device) MapBuffer added in v0.25.0

func (d *Device) MapBuffer(buffer hal.Buffer, offset, size uint64) (hal.BufferMapping, error)

MapBuffer returns a pointer into the buffer's backing Go slice. Software buffers are always host-visible and coherent.

func (*Device) ResetFence

func (d *Device) ResetFence(fence hal.Fence) error

ResetFence resets a fence to the unsignaled state.

func (*Device) UnmapBuffer added in v0.25.0

func (d *Device) UnmapBuffer(_ hal.Buffer) error

UnmapBuffer is a no-op — software buffers are persistently host-visible.

func (*Device) Wait

func (d *Device) Wait(fence hal.Fence, value uint64, _ time.Duration) (bool, error)

Wait simulates waiting for a fence value. Always returns true immediately (fence reached).

func (*Device) WaitIdle

func (d *Device) WaitIdle() error

WaitIdle is a no-op for the software device.

type Fence

type Fence struct {
	Resource
	// contains filtered or unexported fields
}

Fence implements hal.Fence with an atomic counter for synchronization.

type Instance

type Instance struct{}

Instance implements hal.Instance for the software backend.

func (*Instance) CreateSurface

func (i *Instance) CreateSurface(displayHandle, window uintptr) (hal.Surface, error)

CreateSurface creates a software rendering surface. If a valid window handle is provided, Present() will automatically blit the framebuffer to the window via platform-native APIs (GDI on Windows, XPutImage on Linux X11). If window is 0 (headless mode), Present() is a no-op.

displayHandle is platform-specific: X11 Display* on Linux, 0 elsewhere. windowHandle is the native window: HWND on Windows, X11 Window on Linux.

func (*Instance) Destroy

func (i *Instance) Destroy()

Destroy is a no-op for the software instance.

func (*Instance) EnumerateAdapters

func (i *Instance) EnumerateAdapters(_ hal.Surface) []hal.ExposedAdapter

EnumerateAdapters returns a single default software adapter. The surfaceHint is ignored.

type Queue

type Queue struct {
	// contains filtered or unexported fields
}

Queue implements hal.Queue for the software backend.

func (*Queue) GetTimestampPeriod

func (q *Queue) GetTimestampPeriod() float32

GetTimestampPeriod returns 1.0 nanosecond timestamp period.

func (*Queue) PollCompleted added in v0.23.0

func (q *Queue) PollCompleted() uint64

PollCompleted returns the highest submission index known to be completed. Software backend is synchronous — all submissions are immediately complete.

func (*Queue) Present

func (q *Queue) Present(surface hal.Surface, texture hal.SurfaceTexture) error

Present blits the software-rendered framebuffer to the window. The framebuffer is in BGRA byte order (matching the surface format) after executeFullscreenBlit's RGBA→BGRA swizzle. GDI BI_RGB 32-bit expects BGRA, so no additional conversion is needed — the framebuffer is passed directly. In headless mode (hwnd == 0), this is a no-op.

IMPORTANT: Uses the SurfaceTexture's buffer (captured at AcquireTexture time), NOT s.framebuffer (which may have been replaced by Configure during resize). This prevents race: render draws into acquired buffer, Configure allocates new one, Present must blit the buffer that was actually rendered into.

func (*Queue) Submit

func (q *Queue) Submit(_ []hal.CommandBuffer) (uint64, error)

Submit simulates command buffer submission. Software backend is synchronous — work is complete immediately.

func (*Queue) SupportsCommandBufferCopies added in v0.23.4

func (q *Queue) SupportsCommandBufferCopies() bool

SupportsCommandBufferCopies returns false for the software backend. Writes are handled directly via memcpy without command buffer batching.

func (*Queue) WriteBuffer

func (q *Queue) WriteBuffer(buffer hal.Buffer, offset uint64, data []byte) error

WriteBuffer performs immediate buffer writes with real data storage.

func (*Queue) WriteTexture

func (q *Queue) WriteTexture(dst *hal.ImageCopyTexture, data []byte, layout *hal.ImageDataLayout, size *hal.Extent3D) error

WriteTexture performs immediate texture writes with real data storage. Respects dst.Origin (destination position), layout.BytesPerRow (source stride), layout.Offset (source data offset), and size (region dimensions).

type RenderPassEncoder

type RenderPassEncoder struct {
	// contains filtered or unexported fields
}

RenderPassEncoder implements hal.RenderPassEncoder for the software backend. It tracks pipeline state set during encoding and executes draw calls using the raster/ package for triangle rasterization.

func (*RenderPassEncoder) Draw

func (r *RenderPassEncoder) Draw(vertexCount, instanceCount, firstVertex, firstInstance uint32)

Draw executes a non-indexed draw call. It performs vertex fetch, viewport transform, and triangle rasterization using the raster/ package. If no vertex buffer is bound and a texture is available in a bind group, it performs a fullscreen texture blit.

func (*RenderPassEncoder) DrawIndexed

func (r *RenderPassEncoder) DrawIndexed(_, _, _ uint32, _ int32, _ uint32)

DrawIndexed is a no-op (indexed drawing not yet implemented).

func (*RenderPassEncoder) DrawIndexedIndirect

func (r *RenderPassEncoder) DrawIndexedIndirect(_ hal.Buffer, _ uint64)

DrawIndexedIndirect is a no-op.

func (*RenderPassEncoder) DrawIndirect

func (r *RenderPassEncoder) DrawIndirect(_ hal.Buffer, _ uint64)

DrawIndirect is a no-op.

func (*RenderPassEncoder) End

func (r *RenderPassEncoder) End()

End finishes the render pass. If no draw calls were issued and LoadOp is Clear, the clear is applied now. MSAA resolve: copies color attachment pixels to resolve target (WebGPU spec).

func (*RenderPassEncoder) ExecuteBundle

func (r *RenderPassEncoder) ExecuteBundle(_ hal.RenderBundle)

ExecuteBundle is a no-op.

func (*RenderPassEncoder) SetBindGroup

func (r *RenderPassEncoder) SetBindGroup(index uint32, bg hal.BindGroup, _ []uint32)

SetBindGroup stores a bind group at the given index.

func (*RenderPassEncoder) SetBlendConstant

func (r *RenderPassEncoder) SetBlendConstant(_ *gputypes.Color)

SetBlendConstant is a no-op (blend constants not yet wired to raster pipeline).

func (*RenderPassEncoder) SetIndexBuffer

func (r *RenderPassEncoder) SetIndexBuffer(buf hal.Buffer, format gputypes.IndexFormat, offset uint64)

SetIndexBuffer stores the index buffer for indexed draw calls.

func (*RenderPassEncoder) SetPipeline

func (r *RenderPassEncoder) SetPipeline(p hal.RenderPipeline)

SetPipeline stores the render pipeline for subsequent draw calls.

func (*RenderPassEncoder) SetScissorRect

func (r *RenderPassEncoder) SetScissorRect(x, y, w, h uint32)

SetScissorRect stores the scissor rectangle.

func (*RenderPassEncoder) SetStencilReference

func (r *RenderPassEncoder) SetStencilReference(_ uint32)

SetStencilReference is a no-op (stencil not yet wired).

func (*RenderPassEncoder) SetVertexBuffer

func (r *RenderPassEncoder) SetVertexBuffer(slot uint32, buf hal.Buffer, offset uint64)

SetVertexBuffer stores a vertex buffer binding at the given slot.

func (*RenderPassEncoder) SetViewport

func (r *RenderPassEncoder) SetViewport(x, y, w, h, minDepth, maxDepth float32)

SetViewport stores the viewport transformation.

type RenderPipeline added in v0.21.3

type RenderPipeline struct {
	Resource
	// contains filtered or unexported fields
}

RenderPipeline stores render pipeline configuration for the software backend.

type Resource

type Resource struct{}

Resource is a placeholder implementation for most HAL resource gputypes. It implements the hal.Resource interface with a no-op Destroy method.

func (*Resource) AddPendingRef added in v0.23.4

func (r *Resource) AddPendingRef()

func (*Resource) CurrentUsage added in v0.23.4

func (r *Resource) CurrentUsage() gputypes.TextureUsage

CurrentUsage returns 0 — Software backend has no resource state tracking.

func (*Resource) DecPendingRef added in v0.23.4

func (r *Resource) DecPendingRef()

func (*Resource) Destroy

func (r *Resource) Destroy()

Destroy is a no-op.

func (*Resource) NativeHandle

func (r *Resource) NativeHandle() uintptr

NativeHandle returns 0 for software resources (no real GPU handle).

type ShaderModule added in v0.21.3

type ShaderModule struct {
	Resource
	// contains filtered or unexported fields
}

ShaderModule stores shader source for the software backend.

type Surface

type Surface struct {
	Resource
	// contains filtered or unexported fields
}

Surface implements hal.Surface for the software backend.

func (*Surface) AcquireTexture

func (s *Surface) AcquireTexture(_ hal.Fence) (*hal.AcquiredSurfaceTexture, error)

AcquireTexture returns a surface texture backed by the framebuffer.

func (*Surface) Configure

func (s *Surface) Configure(_ hal.Device, config *hal.SurfaceConfiguration) error

Configure configures the surface with the given settings.

Returns hal.ErrZeroArea if width or height is zero. This commonly happens when the window is minimized or not yet fully visible. Wait until the window has valid dimensions before calling Configure again.

func (*Surface) DiscardTexture

func (s *Surface) DiscardTexture(_ hal.SurfaceTexture)

DiscardTexture is a no-op (framebuffer stays allocated).

func (*Surface) GetFramebuffer

func (s *Surface) GetFramebuffer() []byte

GetFramebuffer returns a copy of the current framebuffer data in RGBA byte order (thread-safe). If the surface format is BGRA, R and B channels are swapped so callers always receive consistent RGBA data. This allows platform blit code to do a single RGBA→BGRA conversion for GDI/X11.

func (*Surface) Unconfigure

func (s *Surface) Unconfigure(_ hal.Device)

Unconfigure removes the surface configuration.

type SurfaceTexture

type SurfaceTexture struct {
	Texture
	// contains filtered or unexported fields
}

SurfaceTexture implements hal.SurfaceTexture. It shares the framebuffer with the surface.

type Texture

type Texture struct {
	Resource
	// contains filtered or unexported fields
}

Texture implements hal.Texture with real pixel storage.

func (*Texture) Clear

func (t *Texture) Clear(color gputypes.Color)

Clear fills the texture with a color value in the texture's native format. BGRA textures store [B,G,R,A] per pixel; RGBA textures store [R,G,B,A].

func (*Texture) CurrentUsage added in v0.23.4

func (t *Texture) CurrentUsage() gputypes.TextureUsage

CurrentUsage returns 0 — Software backend has no resource state tracking.

func (*Texture) GetData

func (t *Texture) GetData() []byte

GetData returns a copy of the texture data (thread-safe).

func (*Texture) NativeHandle

func (t *Texture) NativeHandle() uintptr

NativeHandle returns the texture's unique ID for handle resolution.

func (*Texture) WriteData

func (t *Texture) WriteData(offset uint64, data []byte)

WriteData writes data to the texture (thread-safe).

type TextureView

type TextureView struct {
	Resource
	// contains filtered or unexported fields
}

TextureView implements hal.TextureView. In software backend, views just reference the original texture.

func (*TextureView) NativeHandle

func (v *TextureView) NativeHandle() uintptr

NativeHandle returns the view's unique ID for handle resolution.

Directories

Path Synopsis
Package raster provides CPU-based triangle rasterization for the software backend.
Package raster provides CPU-based triangle rasterization for the software backend.
Package shader provides callback-based shader execution for the software backend.
Package shader provides callback-based shader execution for the software backend.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL