• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / luma.gl / 17192022436

24 Aug 2025 06:02PM UTC coverage: 62.079% (-13.2%) from 75.234%
17192022436

Pull #2437

github

web-flow
Merge 562c391b0 into 8314ecefa
Pull Request #2437: test(engine): add ShaderPassRenderer test

956 of 1559 branches covered (61.32%)

Branch coverage included in aggregate %.

491 of 666 new or added lines in 7 files covered. (73.72%)

5291 existing lines in 117 files now uncovered.

23238 of 37414 relevant lines covered (62.11%)

3.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.77
/modules/engine/src/compute/texture-transform.ts
1
// luma.gl
1✔
2
// SPDX-License-Identifier: MIT
1✔
3
// Copyright (c) vis.gl contributors
1✔
4

1✔
5
import {Buffer, Device, Framebuffer, RenderPassProps, Sampler, Texture} from '@luma.gl/core';
1✔
6
import {getPassthroughFS} from '@luma.gl/shadertools';
1✔
7
import {Model, ModelProps} from '../model/model';
1✔
8
import {uid} from '../utils/uid';
1✔
9

1✔
10
/**
1✔
11
 * Properties for creating a {@link TextureTransform}
1✔
12
 */
1✔
13
export type TextureTransformProps = Omit<ModelProps, 'fs'> & {
1✔
14
  fs?: ModelProps['fs']; // override as optional
1✔
15
  /** @deprecated TODO(donmccurdy): Needed? */
1✔
16
  inject?: Record<string, string>;
1✔
17
  /** @deprecated TODO(donmccurdy): Needed? */
1✔
18
  framebuffer?: Framebuffer;
1✔
19
  /** @deprecated TODO(donmccurdy): Model already handles this? */
1✔
20
  sourceBuffers?: Record<string, Buffer>;
1✔
21
  /** @deprecated TODO(donmccurdy): Model already handles this? */
1✔
22
  sourceTextures?: Record<string, Texture>;
1✔
23
  targetTexture: Texture;
1✔
24
  targetTextureChannels: 1 | 2 | 3 | 4;
1✔
25
  targetTextureVarying: string;
1✔
26
};
1✔
27

1✔
28
type TextureBinding = {
1✔
29
  sourceBuffers: Record<string, Buffer>;
1✔
30
  sourceTextures: Record<string, Texture>;
1✔
31
  targetTexture: Texture;
1✔
32
  framebuffer?: Framebuffer;
1✔
33
};
1✔
34

1✔
35
const FS_OUTPUT_VARIABLE = 'transform_output';
1✔
36

1✔
37
/**
1✔
38
 * Creates a pipeline for texture→texture transforms.
1✔
39
 * @deprecated
1✔
40
 */
1✔
41
export class TextureTransform {
1!
UNCOV
42
  readonly device: Device;
×
UNCOV
43
  readonly model: Model;
×
UNCOV
44
  readonly sampler: Sampler;
×
UNCOV
45

×
UNCOV
46
  currentIndex = 0;
×
UNCOV
47
  samplerTextureMap: Record<string, any> | null = null;
×
UNCOV
48
  bindings: TextureBinding[] = []; // each element is an object : {sourceTextures, targetTexture, framebuffer}
×
UNCOV
49
  resources: Record<string, any> = {}; // resources to be deleted
×
UNCOV
50

×
UNCOV
51
  constructor(device: Device, props: TextureTransformProps) {
×
UNCOV
52
    this.device = device;
×
UNCOV
53

×
UNCOV
54
    // For precise picking of element IDs.
×
UNCOV
55
    this.sampler = device.createSampler({
×
UNCOV
56
      addressModeU: 'clamp-to-edge',
×
UNCOV
57
      addressModeV: 'clamp-to-edge',
×
UNCOV
58
      minFilter: 'nearest',
×
UNCOV
59
      magFilter: 'nearest',
×
UNCOV
60
      mipmapFilter: 'nearest'
×
UNCOV
61
    });
×
UNCOV
62

×
UNCOV
63
    this.model = new Model(this.device, {
×
UNCOV
64
      id: props.id || uid('texture-transform-model'),
×
UNCOV
65
      fs:
×
UNCOV
66
        props.fs ||
×
UNCOV
67
        getPassthroughFS({
×
UNCOV
68
          input: props.targetTextureVarying,
×
UNCOV
69
          inputChannels: props.targetTextureChannels,
×
UNCOV
70
          output: FS_OUTPUT_VARIABLE
×
UNCOV
71
        }),
×
UNCOV
72
      vertexCount: props.vertexCount, // TODO(donmccurdy): Naming?
×
UNCOV
73
      ...props
×
UNCOV
74
    });
×
UNCOV
75

×
UNCOV
76
    this._initialize(props);
×
UNCOV
77
    Object.seal(this);
×
UNCOV
78
  }
×
UNCOV
79

×
UNCOV
80
  // Delete owned resources.
×
UNCOV
81
  destroy(): void {
×
UNCOV
82
    this.model.destroy();
×
UNCOV
83
    for (const binding of this.bindings) {
×
UNCOV
84
      binding.framebuffer?.destroy();
×
UNCOV
85
    }
×
UNCOV
86
  }
×
UNCOV
87

×
UNCOV
88
  /** @deprecated Use {@link destroy}. */
×
UNCOV
89
  delete(): void {
×
90
    this.destroy();
×
91
  }
×
UNCOV
92

×
UNCOV
93
  run(options?: RenderPassProps): void {
×
UNCOV
94
    const {framebuffer} = this.bindings[this.currentIndex];
×
UNCOV
95
    const renderPass = this.device.beginRenderPass({framebuffer, ...options});
×
UNCOV
96
    this.model.draw(renderPass);
×
UNCOV
97
    renderPass.end();
×
UNCOV
98
    this.device.submit();
×
UNCOV
99
  }
×
UNCOV
100

×
UNCOV
101
  getTargetTexture(): Texture {
×
UNCOV
102
    const {targetTexture} = this.bindings[this.currentIndex];
×
UNCOV
103
    return targetTexture;
×
UNCOV
104
  }
×
UNCOV
105

×
UNCOV
106
  getFramebuffer(): Framebuffer | undefined {
×
107
    const currentResources = this.bindings[this.currentIndex];
×
108
    return currentResources.framebuffer;
×
109
  }
×
UNCOV
110

×
UNCOV
111
  // Private
×
UNCOV
112

×
UNCOV
113
  _initialize(props: TextureTransformProps): void {
×
UNCOV
114
    this._updateBindings(props);
×
UNCOV
115
  }
×
UNCOV
116

×
UNCOV
117
  _updateBindings(props: TextureTransformProps) {
×
UNCOV
118
    this.bindings[this.currentIndex] = this._updateBinding(this.bindings[this.currentIndex], props);
×
UNCOV
119
  }
×
UNCOV
120

×
UNCOV
121
  _updateBinding(
×
UNCOV
122
    binding: TextureBinding,
×
UNCOV
123
    {sourceBuffers, sourceTextures, targetTexture}: TextureTransformProps
×
UNCOV
124
  ): TextureBinding {
×
UNCOV
125
    if (!binding) {
×
UNCOV
126
      binding = {
×
UNCOV
127
        sourceBuffers: {},
×
UNCOV
128
        sourceTextures: {},
×
UNCOV
129
        // @ts-expect-error
×
UNCOV
130
        targetTexture: null
×
UNCOV
131
      };
×
UNCOV
132
    }
×
UNCOV
133
    Object.assign(binding.sourceTextures, sourceTextures);
×
UNCOV
134
    Object.assign(binding.sourceBuffers, sourceBuffers);
×
UNCOV
135
    if (targetTexture) {
×
UNCOV
136
      binding.targetTexture = targetTexture;
×
UNCOV
137
      const {width, height} = targetTexture;
×
UNCOV
138
      // TODO(donmccurdy): When is this called, and is this expected?
×
UNCOV
139
      if (binding.framebuffer) {
×
140
        binding.framebuffer.destroy();
×
141
      }
×
UNCOV
142
      binding.framebuffer = this.device.createFramebuffer({
×
UNCOV
143
        id: 'transform-framebuffer',
×
UNCOV
144
        width,
×
UNCOV
145
        height,
×
UNCOV
146
        colorAttachments: [targetTexture]
×
UNCOV
147
      });
×
UNCOV
148
      binding.framebuffer.resize({width, height});
×
UNCOV
149
    }
×
UNCOV
150
    return binding;
×
UNCOV
151
  }
×
UNCOV
152

×
UNCOV
153
  // set texture filtering parameters on source textures.
×
UNCOV
154
  _setSourceTextureParameters(): void {
×
155
    const index = this.currentIndex;
×
156
    const {sourceTextures} = this.bindings[index];
×
157
    for (const name in sourceTextures) {
×
158
      sourceTextures[name].sampler = this.sampler;
×
159
    }
×
160
  }
×
UNCOV
161
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc