forked from cogentcore/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
format.go
191 lines (160 loc) · 5.38 KB
/
format.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright (c) 2024, Cogent Core. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gpu
import (
"fmt"
"image"
"log"
"github.com/cogentcore/webgpu/wgpu"
)
// TextureFormat describes the size and WebGPU format of a Texture.
// If Layers > 1, all must be the same size.
type TextureFormat struct {
// Size of image
Size image.Point
// Texture format: RGBA8UnormSrgb is default
Format wgpu.TextureFormat
// number of samples. set higher for RenderTexture rendering
// but otherwise default of 1
Samples int
// number of layers for texture arrays
Layers int
}
// NewTextureFormat returns a new TextureFormat with default format and given size
// and number of layers
func NewTextureFormat(width, height, layers int) *TextureFormat {
im := &TextureFormat{}
im.Defaults()
im.Size = image.Point{width, height}
im.Layers = layers
return im
}
func (im *TextureFormat) Defaults() {
im.Format = wgpu.TextureFormatRGBA8UnormSrgb
im.Samples = 1
im.Layers = 1
}
// String returns human-readable version of format
func (im *TextureFormat) String() string {
return fmt.Sprintf("Size: %v Format: %s MultiSample: %d Layers: %d", im.Size, TextureFormatNames[im.Format], im.Samples, im.Layers)
}
// IsStdRGBA returns true if image format is the standard
// wgpu.TextureFormatRGBA8UnormSrgb
// which is compatible with go image.RGBA format.
func (im *TextureFormat) IsStdRGBA() bool {
return im.Format == wgpu.TextureFormatRGBA8UnormSrgb
}
// IsRGBAUnorm returns true if image format is the
// wgpu.TextureFormatRGBA8Unorm format
// which is compatible with go image.RGBA format with colorspace conversion.
func (im *TextureFormat) IsRGBAUnorm() bool {
return im.Format == wgpu.TextureFormatRGBA8Unorm
}
// SetSize sets the width, height
func (im *TextureFormat) SetSize(w, h int) {
im.Size = image.Point{X: w, Y: h}
}
// Set sets width, height and format
func (im *TextureFormat) Set(w, h int, ft wgpu.TextureFormat) {
im.SetSize(w, h)
im.Format = ft
}
// SetFormat sets the format using vgpu standard Types
func (im *TextureFormat) SetFormat(ft Types) {
im.Format = ft.TextureFormat()
}
// SetMultisample sets the number of multisampling to decrease aliasing
// 4 is typically sufficient. Values must be power of 2.
func (im *TextureFormat) SetMultisample(nsamp int) {
im.Samples = nsamp
}
// Size32 returns size as uint32 values
func (im *TextureFormat) Size32() (width, height uint32) {
width = uint32(im.Size.X)
height = uint32(im.Size.Y)
return
}
func (im *TextureFormat) Extent3D() wgpu.Extent3D {
ex := wgpu.Extent3D{
Width: uint32(im.Size.X),
Height: uint32(im.Size.Y),
DepthOrArrayLayers: uint32(im.Layers),
}
return ex
}
// Aspect returns the aspect ratio X / Y
func (im *TextureFormat) Aspect() float32 {
if im.Size.Y > 0 {
return float32(im.Size.X) / float32(im.Size.Y)
}
return 1.3
}
// Bounds returns the rectangle defining this image: 0,0,w,h
func (im *TextureFormat) Bounds() image.Rectangle {
return image.Rectangle{Max: im.Size}
}
// BytesPerPixel returns number of bytes required to represent
// one Pixel (in Host memory at least). TODO only works
// for known formats -- need to add more as needed.
func (im *TextureFormat) BytesPerPixel() int {
bpp := TextureFormatSizes[im.Format]
if bpp > 0 {
return bpp
}
log.Println("gpu.TextureFormat:BytesPerPixel() -- format not yet supported!")
return 0
}
// LayerByteSize returns number of bytes required to represent one layer of
// image in Host memory. TODO only works
// for known formats -- need to add more as needed.
func (im *TextureFormat) LayerByteSize() int {
return im.BytesPerPixel() * im.Size.X * im.Size.Y
}
// TotalByteSize returns total number of bytes required to represent all layers of
// images in Host memory. TODO only works
// for known formats -- need to add more as needed.
func (im *TextureFormat) TotalByteSize() int {
return im.LayerByteSize() * im.Layers
}
// Stride returns number of bytes per image row. TODO only works
// for known formats -- need to add more as needed.
func (im *TextureFormat) Stride() int {
return im.BytesPerPixel() * im.Size.X
}
//////////////////////////////////////////////////////////////////////
// TextureBufferDims represents the sizes required in Buffer to
// represent a texture of a given size.
type TextureBufferDims struct {
Width uint64
Height uint64
UnpaddedRowSize uint64
PaddedRowSize uint64
}
func NewTextureBufferDims(size image.Point) *TextureBufferDims {
td := &TextureBufferDims{}
td.Set(size)
return td
}
func (td *TextureBufferDims) Set(size image.Point) {
td.Width = uint64(size.X)
td.Height = uint64(size.Y)
const bytesPerPixel = 4 // unsafe.Sizeof(uint32(0))
td.UnpaddedRowSize = uint64(td.Width * bytesPerPixel)
align := uint64(wgpu.CopyBytesPerRowAlignment)
padding := (align - td.UnpaddedRowSize%align) % align
td.PaddedRowSize = td.UnpaddedRowSize + padding
}
// PaddedSize returns the total padded size of data
func (td *TextureBufferDims) PaddedSize() uint64 {
return td.PaddedRowSize * td.Height
}
// UnpaddedSize returns the total unpadded size of data
func (td *TextureBufferDims) UnpaddedSize() uint64 {
return td.UnpaddedRowSize * td.Height
}
// HasNoPadding returns true if the Unpadded and Padded row sizes
// are the same.
func (td *TextureBufferDims) HasNoPadding() bool {
return td.UnpaddedRowSize == td.PaddedRowSize
}