diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-12 01:06:33 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-12 01:06:33 +0000 |
commit | 0ab7e0a746b293df559e3639cf7e47056d4838d4 (patch) | |
tree | 53d402362d31d23f351ac8ca0fb5ad235b5b6637 | |
parent | 81b326bea53b93d084255cec645908d8f481a576 (diff) | |
parent | cc4cbd01bb9e444b4052acbe8aa3aaf7861d696d (diff) | |
download | skia-0ab7e0a746b293df559e3639cf7e47056d4838d4.tar.gz |
Snap for 7354453 from cc4cbd01bb9e444b4052acbe8aa3aaf7861d696d to sc-release
Change-Id: Ieb7a2850b7ad4d70665f9761ddaa8177a03f6a6b
98 files changed, 2931 insertions, 1045 deletions
@@ -11,15 +11,15 @@ vars = { deps = { "buildtools" : "https://chromium.googlesource.com/chromium/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8", - "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@69d593b5d6509d4698adb6e73422f20ed414a831", + "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@125f128e62399400f02254a09aad739056650d2a", "third_party/externals/brotli" : "https://skia.googlesource.com/external/github.com/google/brotli.git@e61745a6b7add50d380cfd7d3883dd6c62fc2c71", "third_party/externals/d3d12allocator" : "https://skia.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git@169895d529dfce00390a20e69c2f516066fe7a3b", # Dawn requires jinja2 and markupsafe for the code generator, and tint for SPIRV compilation. # When the Dawn revision is updated these should be updated from the Dawn DEPS as well. - "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@26468c4071756b016468fc6c2729f702955acdcf", + "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@e2f083e4b0f5926b6ca4abe9ab13a710fac2b917", "third_party/externals/jinja2" : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@a82a4944a7f2496639f34a89c9923be5908b80aa", "third_party/externals/markupsafe" : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@0944e71f4b2cb9a871bcbe353f95e889b64a611a", - "third_party/externals/tint" : "https://dawn.googlesource.com/tint@6a56744b557caf555713af4afff5061746a526f2", + "third_party/externals/tint" : "https://dawn.googlesource.com/tint@9fdfa1e32374f8d862c98ad241757853386f66e6", "third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123", "third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae", "third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@e976867fb57a0cd87e3b0fe05d59e0ed63c6febb", @@ -43,13 +43,13 @@ deps = { "third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@bdbef7b1f3982fe99a62d076043036abe6dd6d80", "third_party/externals/spirv-headers" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@bcf55210f13a4fa3c3d0963b509ff1070e434c79", "third_party/externals/spirv-tools" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@5d8c40399e1a483c168246215e4637e19551cd4f", - "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@e260190edbd2984a045ac5990b3d31429d45d27f", + "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@dcb33711bd4bd14a9bff84db379ad59295c337a3", #"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4", "third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs.git@f49c38202914c289621f547ff016e5f02c994dda", "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@c876c8f87101c5a75f6014b0f832499afeb65b73", "../src": { - "url": "https://chromium.googlesource.com/chromium/src.git@ed46c1e47728e5354ed01f9dcdb47f3e00d5980a", + "url": "https://chromium.googlesource.com/chromium/src.git@5d4a69b076e10cec343b89b90acc0af4a88850a7", "condition": "checkout_chromium", }, @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://skia.googlesource.com/skia" } - version: "bdadfc16dffbb144a607f8580f9b10b554c745e9" + version: "7c328b4b42c5c5a2761ea6811573b15280f910bc" license_type: RECIPROCAL last_upgrade_date { year: 2021 month: 5 - day: 10 + day: 11 } } diff --git a/build_overrides/angle.gni b/build_overrides/angle.gni index 2b38040ba7..22f0153897 100644 --- a/build_overrides/angle.gni +++ b/build_overrides/angle.gni @@ -1,5 +1,7 @@ angle_root = "//third_party/externals/angle2" angle_zlib_compression_utils_dir = "//third_party/zlib" +angle_spirv_headers_dir = "//third_party/externals/spirv-headers" +angle_spirv_tools_dir = "//third_party/externals/spirv-tools" # We don't have Chromium's build/ or testing/ directories. angle_has_build = false diff --git a/demos.skia.org/demos/textedit/index.html b/demos.skia.org/demos/textedit/index.html new file mode 100644 index 0000000000..8c1d2f0115 --- /dev/null +++ b/demos.skia.org/demos/textedit/index.html @@ -0,0 +1,141 @@ +<!DOCTYPE html> +<title>TextEdit demo in CanvasKit</title> +<meta charset="utf-8" /> +<meta http-equiv="X-UA-Compatible" content="IE=edge"> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<script type="text/javascript" src="https://particles.skia.org/dist/canvaskit.js"></script> +<script type="text/javascript" src="textapi_utils.js"></script> + +<style> +canvas { + border: 1px dashed grey; +} +</style> + +<body> + <h1>TextEdit in CanvasKit</h1> + + <canvas id=para2 width=600 height=600 tabindex='-1'></canvas> +</body> + +<script type="text/javascript" charset="utf-8"> + let CanvasKit; + onload = async () => { + CanvasKit = await CanvasKitInit({ locateFile: (file) => 'https://particles.skia.org/dist/'+file }); + ParagraphAPI2(); + }; + + function ParagraphAPI2() { + const surface = CanvasKit.MakeCanvasSurface('para2'); + if (!surface) { + console.error('Could not make surface'); + return; + } + + const mouse = MakeMouse(); + const cursor = MakeCursor(CanvasKit); + const canvas = surface.getCanvas(); + + const text0 = "In a hole in the ground there lived a hobbit. Not a nasty, dirty, " + + "wet hole full of worms and oozy smells. This was a hobbit-hole and " + + "that means good food, a warm hearth, and all the comforts of home."; + const LOC_X = 20, + LOC_Y = 20; + + const bgPaint = new CanvasKit.Paint(); + bgPaint.setColor([0.965, 0.965, 0.965, 1]); + + const editor = MakeEditor(text0, {typeface:null, size:24}, cursor, 400); + + editor.applyStyleToRange({size:100}, 0, 1); + editor.applyStyleToRange({italic:true}, 38, 38+6); + editor.applyStyleToRange({color:[1,0,0,1]}, 5, 5+4); + + editor.setXY(LOC_X, LOC_Y); + + function drawFrame(canvas) { + const lines = editor.getLines(); + + canvas.clear(CanvasKit.WHITE); + + if (mouse.isActive()) { + const pos = mouse.getPos(-LOC_X, -LOC_Y); + const a = lines_pos_to_index(lines, pos[0], pos[1]); + const b = lines_pos_to_index(lines, pos[2], pos[3]); + if (a === b) { + editor.setIndex(a); + } else { + editor.setIndices(a, b); + } + } + + canvas.drawRect(editor.bounds(), bgPaint); + editor.draw(canvas); + + surface.requestAnimationFrame(drawFrame); + } + surface.requestAnimationFrame(drawFrame); + + function interact(e) { + const type = e.type; + if (type === 'pointerup') { + mouse.setUp(e.offsetX, e.offsetY); + } else if (type === 'pointermove') { + mouse.setMove(e.offsetX, e.offsetY); + } else if (type === 'pointerdown') { + mouse.setDown(e.offsetX, e.offsetY); + } + }; + + function keyhandler(e) { + switch (e.key) { + case 'ArrowLeft': editor.moveDX(-1); return; + case 'ArrowRight': editor.moveDX(1); return; + case 'ArrowUp': + e.preventDefault(); + editor.moveDY(-1); + return; + case 'ArrowDown': + e.preventDefault(); + editor.moveDY(1); + return; + case 'Backspace': + editor.deleteSelection(-1); + return; + case 'Delete': + editor.deleteSelection(1); + return; + case 'Shift': + return; + case 'Tab': // todo: figure out how to handle... + e.preventDefault(); + return; + } + if (e.ctrlKey) { + switch (e.key) { + case 'r': editor.applyStyleToSelection({color:[1,0,0,1]}); return; + case 'g': editor.applyStyleToSelection({color:[0,0.6,0,1]}); return; + case 'u': editor.applyStyleToSelection({color:[0,0,1,1]}); return; + case 'k': editor.applyStyleToSelection({color:[0,0,0,1]}); return; + + case 'i': editor.applyStyleToSelection({italic:'toggle'}); return; + case 'b': editor.applyStyleToSelection({bold:'toggle'}); return; + + case ']': editor.applyStyleToSelection({size_add:1}); return; + case '[': editor.applyStyleToSelection({size_add:-1}); return; + } + } + if (!e.ctrlKey && !e.metaKey) { + e.preventDefault(); // at least needed for 'space' + editor.insert(e.key); + } + } + + document.getElementById('para2').addEventListener('pointermove', interact); + document.getElementById('para2').addEventListener('pointerdown', interact); + document.getElementById('para2').addEventListener('pointerup', interact); + document.getElementById('para2').addEventListener('keydown', keyhandler); + return surface; + } + +</script> diff --git a/demos.skia.org/demos/textedit/textapi_utils.js b/demos.skia.org/demos/textedit/textapi_utils.js new file mode 100644 index 0000000000..9cf4606f20 --- /dev/null +++ b/demos.skia.org/demos/textedit/textapi_utils.js @@ -0,0 +1,608 @@ + +function ASSERT(pred) { + console.assert(pred, 'assert failed'); +} + +function LOG(...args) { + // comment out for non-debugging +// console.log(args); +} + +function MakeCursor(CanvasKit) { + const linePaint = new CanvasKit.Paint(); + linePaint.setColor([0,0,1,1]); + linePaint.setStyle(CanvasKit.PaintStyle.Stroke); + linePaint.setStrokeWidth(2); + linePaint.setAntiAlias(true); + + const pathPaint = new CanvasKit.Paint(); + pathPaint.setColor([0,0,1,0.25]); + linePaint.setAntiAlias(true); + + return { + _line_paint: linePaint, // wrap in weak-ref so we can delete it? + _path_paint: pathPaint, + _x: 0, + _top: 0, + _bottom: 0, + _path: null, // only use x,top,bottom if path is null + _draws_per_sec: 2, + + // pass 0 for no-draw, pass inf. for always on + setBlinkRate: function(blinks_per_sec) { + this._draws_per_sec = blinks_per_sec; + }, + place: function(x, top, bottom) { + this._x = x; + this._top = top; + this._bottom = bottom; + + this.setPath(null); + }, + setPath: function(path) { + if (this._path) { + this._path.delete(); + } + this._path = path; + }, + draw_before: function(canvas) { + if (this._path) { + canvas.drawPath(this._path, this._path_paint); + } + }, + draw_after: function(canvas) { + if (this._path) { + return; + } + if (Math.floor(Date.now() * this._draws_per_sec / 1000) & 1) { + canvas.drawLine(this._x, this._top, this._x, this._bottom, this._line_paint); + } + }, + }; +} + +function MakeMouse() { + return { + _start_x: 0, _start_y: 0, + _curr_x: 0, _curr_y: 0, + _active: false, + + isActive: function() { + return this._active; + }, + setDown: function(x, y) { + this._start_x = this._curr_x = x; + this._start_y = this._curr_y = y; + this._active = true; + }, + setMove: function(x, y) { + this._curr_x = x; + this._curr_y = y; + }, + setUp: function(x, y) { + this._curr_x = x; + this._curr_y = y; + this._active = false; + }, + getPos: function(dx, dy) { + return [ this._start_x + dx, this._start_y + dy, this._curr_x + dx, this._curr_y + dy ]; + }, + }; +} + +function runs_x_to_index(runs, x) { + for (const r of runs) { + for (let i = 1; i < r.offsets.length; i += 1) { + if (x < r.positions[i*2]) { + const mid = (r.positions[i*2-2] + r.positions[i*2]) * 0.5; + if (x <= mid) { + return r.offsets[i-1]; + } else { + return r.offsets[i]; + } + } + } + } + const r = runs[runs.length-1]; + return r.offsets[r.offsets.length-1]; +} + +function lines_pos_to_index(lines, x, y) { + if (y < lines[0].top) { + return 0; + } + const l = lines.find((l) => y <= l.bottom); + return l ? runs_x_to_index(l.runs, x) + : lines[lines.length - 1].textRange.last; +} + +function runs_index_to_run(runs, index) { + const r = runs.find((r) => index <= r.offsets[r.offsets.length-1]); + // return last if no run is found + return r ? r : runs[runs.length-1]; +} + +function runs_index_to_x(runs, index) { + const r = runs_index_to_run(runs, index); + const i = r.offsets.findIndex((offset) => index === offset); + return i >= 0 ? r.positions[i*2] + : r.positions[r.positions.length-2]; // last x +} + +function lines_index_to_line_index(lines, index) { + const l = lines.findIndex((l) => index <= l.textRange.last); + return l >= 0 ? l : lines.length-1; +} + +function lines_index_to_line(lines, index) { + return lines[lines_index_to_line_index(lines, index)]; +} + +function lines_indices_to_path(lines, a, b, width) { + if (a == b) { + return null; + } + if (a > b) { [a, b] = [b, a]; } + + const path = new CanvasKit.Path(); + const la = lines_index_to_line(lines, a); + const lb = lines_index_to_line(lines, b); + const ax = runs_index_to_x(la.runs, a); + const bx = runs_index_to_x(lb.runs, b); + if (la == lb) { + path.addRect([ax, la.top, bx, la.bottom]); + } else { + path.addRect([ax, la.top, width, la.bottom]); + path.addRect([0, lb.top, bx, lb.bottom]); + if (la.bottom < lb.top) { + path.addRect([0, la.bottom, width, lb.top]); // extra lines inbetween + } + } + return path; +} + +function string_del(str, start, end) { + return str.slice(0, start) + str.slice(end, str.length); +} + +function make_default_paint() { + const p = new CanvasKit.Paint(); + p.setAntiAlias(true); + return p; +} + +function make_default_font(tf) { + const font = new CanvasKit.Font(tf); + font.setSubpixel(true); + return font; +} + +function MakeStyle(length) { + return { + _length: length, + typeface: null, + size: null, + color: null, + bold: null, + italic: null, + + _check_toggle: function(src, dst) { + if (src == 'toggle') { + return !dst; + } else { + return src; + } + }, + + // returns true if we changed something affecting layout + mergeFrom: function(src) { + let layoutChanged = false; + + if (src.typeface && this.typeface !== src.typeface) { + this.typeface = src.typeface; + layoutChanged = true; + } + if (src.size && this.size !== src.size) { + this.size = src.size; + layoutChanged = true; + } + if (src.color) { this.color = src.color; } + + if (src.bold) { + this.bold = this._check_toggle(src.bold, this.bold); + } + if (src.italic) { + this.italic = this._check_toggle(src.italic, this.italic); + } + + if (src.size_add) { + this.size += src.size_add; + layoutChanged = true; + } + + return layoutChanged; + } + }; +} + +function MakeEditor(text, style, cursor, width) { + const ed = { + _text: text, + _lines: null, + _cursor: cursor, + _width: width, + _index: { start: 0, end: 0 }, + _styles: null, + // drawing + _X: 0, + _Y: 0, + _paint: make_default_paint(), + _font: make_default_font(style.typeface), + + getLines: function() { return this._lines; }, + + width: function() { + return this._width; + }, + height: function() { + return this._lines[this._lines.length-1].bottom; + }, + bounds: function() { + return [this._X, this._Y, this._X + this.width(), this._Y + this.height()]; + }, + setXY: function(x, y) { + this._X = x; + this._Y = y; + }, + + _rebuild_selection: function() { + const a = this._index.start; + const b = this._index.end; + ASSERT(a >= 0 && a <= b && b <= this._text.length); + if (a === b) { + const l = lines_index_to_line(this._lines, a); + const x = runs_index_to_x(l.runs, a); + this._cursor.place(x, l.top, l.bottom); + } else { + this._cursor.setPath(lines_indices_to_path(this._lines, a, b, this._width)); + } + }, + setIndex: function(i) { + this._index.start = this._index.end = i; + this._rebuild_selection(); + }, + setIndices: function(a, b) { + if (a > b) { [a, b] = [b, a]; } + this._index.start = a; + this._index.end = b; + this._rebuild_selection(); + }, + moveDX: function(dx) { + let index; + if (this._index.start == this._index.end) { + // just adjust and pin + index = Math.max(Math.min(this._index.start + dx, this._text.length), 0); + } else { + // 'deselect' the region, and turn it into just a single index + index = dx < 0 ? this._index.start : this._index.end; + } + this.setIndex(index); + }, + moveDY: function(dy) { + let index = (dy < 0) ? this._index.start : this._index.end; + const i = lines_index_to_line_index(this._lines, index); + if (dy < 0 && i === 0) { + index = 0; + } else if (dy > 0 && i == this._lines.length - 1) { + index = this._text.length; + } else { + const x = runs_index_to_x(this._lines[i].runs, index); + // todo: statefully track "original" x when an up/down sequence started, + // so we can avoid drift. + index = runs_x_to_index(this._lines[i+dy].runs, x); + } + this.setIndex(index); + }, + + _validateStyles: function() { + const len = this._styles.reduce((sum, style) => sum + style._length, 0); + ASSERT(len === this._text.length); + }, + _validateBlocks: function(blocks) { + const len = blocks.reduce((sum, block) => sum + block.length, 0); + ASSERT(len === this._text.length); + }, + + _buildLines: function() { + this._validateStyles(); + + const blocks = []; + let block = null; + for (const s of this._styles) { + if (!block || (block.typeface === s.typeface && block.size === s.size)) { + if (!block) { + block = { length: 0, typeface: s.typeface, size: s.size }; + } + block.length += s._length; + } else { + blocks.push(block); + block = { length: s._length, typeface: s.typeface, size: s.size }; + } + } + blocks.push(block); + this._validateBlocks(blocks); + + this._lines = CanvasKit.ParagraphBuilder.ShapeText(this._text, blocks, this._width); + this._rebuild_selection(); + + // add textRange to each run, to aid in drawing + this._runs = []; + for (const l of this._lines) { + for (const r of l.runs) { + r.textRange = { start: r.offsets[0], end: r.offsets[r.offsets.length-1] }; + this._runs.push(r); + } + } + }, + + // note: this does not rebuild lines/runs, or update the cursor, + // but it does edit the text and styles + // returns true if it deleted anything + _deleteRange: function(start, end) { + ASSERT(start >= 0 && end <= this._text.length); + ASSERT(start <= end); + if (start === end) { + return false; + } + + this._delete_style_range(start, end); + // Do this after shrink styles (we use text.length in an assert) + this._text = string_del(this._text, start, end); + }, + deleteSelection: function(direction) { + let start = this._index.start; + if (start == this._index.end) { + if (direction < 0) { + if (start == 0) { + return; // nothing to do + } + this._deleteRange(start - 1, start); + start -= 1; + } else { + if (start >= this._text.length) { + return; // nothing to do + } + this._deleteRange(start, start + 1); + } + } else { + this._deleteRange(start, this._index.end); + } + this._index.start = this._index.end = start; + this._buildLines(); + }, + insert: function(charcode) { + if (this._index.start != this._index.end) { + this.deleteSelection(); + } + const index = this._index.start; + + // do this before edit the text (we use text.length in an assert) + const [i, prev_len] = this.find_style_index_and_prev_length(index); + this._styles[i]._length += 1; + + // now grow the text + this._text = this._text.slice(0, index) + charcode + this._text.slice(index); + + this._index.start = this._index.end = index + 1; + this._buildLines(); + }, + + draw: function(canvas) { + canvas.save(); + canvas.translate(this._X, this._Y); + + this._cursor.draw_before(canvas); + + const runs = this._runs; + const styles = this._styles; + const f = this._font; + const p = this._paint; + + let s = styles[0]; + let sindex = 0; + let s_start = 0; + let s_end = s._length; + + let r = runs[0]; + let rindex = 0; + + let start = 0; + let end = 0; + while (start < this._text.length) { + while (r.textRange.end <= start) { + r = runs[++rindex]; + if (!r) { + // ran out of runs, so the remaining text must just be WS + break; + } + } + if (!r) break; + while (s_end <= start) { + s = styles[++sindex]; + s_start = s_end; + s_end += s._length; + } + end = Math.min(r.textRange.end, s_end); + + LOG('New range: ', start, end, + 'from run', r.textRange.start, r.textRange.end, + 'style', s_start, s_end); + + // check that we have anything to draw + if (r.textRange.start >= end) { + start = end; + continue; // could be a span of WS with no glyphs + } + +// f.setTypeface(r.typeface); // r.typeface is always null (for now) + f.setSize(r.size); + f.setEmbolden(s.bold); + f.setSkewX(s.italic ? -0.2 : 0); + p.setColor(s.color ? s.color : [0,0,0,1]); + + let gly = r.glyphs; + let pos = r.positions; + if (start > r.textRange.start || end < r.textRange.end) { + // search for the subset of glyphs to draw + let glyph_start, glyph_end; + for (let i = 0; i < r.offsets.length; ++i) { + if (r.offsets[i] >= start) { + glyph_start = i; + break; + } + } + for (let i = glyph_start+1; i < r.offsets.length; ++i) { + if (r.offsets[i] >= end) { + glyph_end = i; + break; + } + } + LOG(' glyph subrange', glyph_start, glyph_end); + gly = gly.slice(glyph_start, glyph_end); + pos = pos.slice(glyph_start*2, glyph_end*2); + } else { + LOG(' use entire glyph run'); + } + canvas.drawGlyphs(gly, pos, 0, 0, f, p); + + start = end; + } + + this._cursor.draw_after(canvas); + canvas.restore(); + }, + + // Styling + + // returns [index, prev total length before this style] + find_style_index_and_prev_length: function(index) { + let len = 0; + for (let i = 0; i < this._styles.length; ++i) { + const l = this._styles[i]._length; + len += l; + // < favors the latter style if index is between two styles + if (index < len) { + return [i, len - l]; + } + } + ASSERT(len === this._text.length); + return [this._styles.length-1, len]; + }, + _delete_style_range: function(start, end) { + // shrink/remove styles + // + // [.....][....][....][.....] styles + // [..................] start...end + // + // - trim the first style + // - remove the middle styles + // - trim the last style + + let N = end - start; + let [i, prev_len] = this.find_style_index_and_prev_length(start); + let s = this._styles[i]; + if (start > prev_len) { + // we overlap the first style (but not entirely + const skip = start - prev_len; + ASSERT(skip < s._length); + const shrink = Math.min(N, s._length - skip); + ASSERT(shrink > 0); + s._length -= shrink; + N -= shrink; + if (N === 0) { + return; + } + i += 1; + ASSERT(i < this._styles.length); + } + while (N > 0) { + s = this._styles[i]; + if (N >= s._length) { + N -= s._length; + this._styles.splice(i, 1); + } else { + s._length -= N; + break; + } + } + }, + + applyStyleToRange: function(style, start, end) { + if (start > end) { [start, end] = [end, start]; } + ASSERT(start >= 0 && end <= this._text.length); + if (start === end) { + return; + } + + LOG('trying to apply', style, start, end); + let i; + for (i = 0; i < this._styles.length; ++i) { + if (start <= this._styles[i]._length) { + break; + } + start -= this._styles[i]._length; + end -= this._styles[i]._length; + } + + let s = this._styles[i]; + // do we need to fission off a clean subset for the head of s? + if (start > 0) { + const ns = Object.assign({}, s); + s._length = start; + ns._length -= start; + LOG('initial splice', i, start, s._length, ns._length); + i += 1; + this._styles.splice(i, 0, ns); + end -= start; + // we don't use start any more + } + // merge into any/all whole styles we overlap + let layoutChanged = false; + while (end >= this._styles[i]._length) { + LOG('whole run merging for style index', i) + layoutChanged |= this._styles[i].mergeFrom(style); + end -= this._styles[i]._length; + i += 1; + if (end == 0) { + break; + } + } + // do we partially cover the last run + if (end > 0) { + s = this._styles[i]; + const ns = Object.assign({}, s); // the new first half + ns._length = end; + s._length -= end; // trim the (unchanged) tail + LOG('merging tail', i, ns._length, s._length); + layoutChanged |= ns.mergeFrom(style); + this._styles.splice(i, 0, ns); + } + + this._validateStyles(); + LOG('after applying styles', this._styles); + + if (layoutChanged) { + this._buildLines(); + } + }, + applyStyleToSelection: function(style) { + this.applyStyleToRange(style, this._index.start, this._index.end); + }, + }; + + const s = MakeStyle(ed._text.length); + s.mergeFrom(style); + ed._styles = [ s ]; + ed._buildLines(); + return ed; +} diff --git a/fuzz/FuzzTriangulation.cpp b/fuzz/FuzzTriangulation.cpp index d9a54d6bb3..4a18a93833 100644 --- a/fuzz/FuzzTriangulation.cpp +++ b/fuzz/FuzzTriangulation.cpp @@ -29,4 +29,5 @@ DEF_FUZZ(Triangulation, fuzz) { bool isLinear; GrTriangulator::PathToTriangles(path, tol, clipBounds, &allocator, &isLinear); + allocator.detachVertexData(); // normally handled by the triangulating path renderer. } diff --git a/gm/tessellation.cpp b/gm/tessellation.cpp index 84bf7c1049..1fa252a481 100644 --- a/gm/tessellation.cpp +++ b/gm/tessellation.cpp @@ -72,44 +72,17 @@ private: args.fVertBuilder->declareGlobal( GrShaderVar("P_", kFloat3_GrSLType, GrShaderVar::TypeModifier::Out)); args.fVertBuilder->codeAppendf(R"( - P_.xy = (%s * float3(position.xy, 1)).xy; - P_.z = position.z;)", viewMatrix); + P_.xy = (%s * float3(position.xy, 1)).xy; + P_.z = position.z;)", viewMatrix); // GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling. this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage); } - void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage); - void setData(const GrGLSLProgramDataManager& pdman, - const GrShaderCaps&, - const GrGeometryProcessor& geomProc) override { - pdman.setSkMatrix(fViewMatrixUniform, - geomProc.cast<TessellationTestTriShader>().fViewMatrix); - } - GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; - }; - - GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override { - return new Impl; - } - - SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - - const SkMatrix fViewMatrix; -}; - -SkString TessellationTestTriShader::getTessControlShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(R"( + SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(R"( layout(vertices = 3) out; in vec3 P_[]; @@ -121,16 +94,14 @@ SkString TessellationTestTriShader::getTessControlShaderGLSL( gl_TessLevelInner[0] = 2.0; })"); - return code; -} - -SkString TessellationTestTriShader::getTessEvaluationShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(R"( + return code; + } + SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(R"( layout(triangles, equal_spacing, cw) in; uniform vec4 sk_RTAdjust; @@ -164,19 +135,33 @@ SkString TessellationTestTriShader::getTessEvaluationShaderGLSL( barycentric_coord = vec3(i, 0, 1.0 - i); })"); - return code; -} - -void TessellationTestTriShader::Impl::writeFragmentShader( - GrGLSLFPFragmentBuilder* f, const char* color, const char* coverage) { - f->declareGlobal( - GrShaderVar("barycentric_coord", kFloat3_GrSLType, GrShaderVar::TypeModifier::In)); - f->codeAppendf(R"( + return code; + } + void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color, + const char* coverage) { + f->declareGlobal(GrShaderVar("barycentric_coord", kFloat3_GrSLType, + GrShaderVar::TypeModifier::In)); + f->codeAppendf(R"( half3 d = half3(1 - barycentric_coord/fwidth(barycentric_coord)); half coverage = max(max(d.x, d.y), d.z); half4 %s = half4(0, coverage, coverage, 1); const half4 %s = half4(1);)", color, coverage); -} + } + void setData(const GrGLSLProgramDataManager& pdman, + const GrShaderCaps&, + const GrGeometryProcessor& geomProc) override { + pdman.setSkMatrix(fViewMatrixUniform, + geomProc.cast<TessellationTestTriShader>().fViewMatrix); + } + GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; + }; + + GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override { + return new Impl; + } + + const SkMatrix fViewMatrix; +}; class TessellationTestRectShader : public GrGeometryProcessor { public: @@ -200,39 +185,12 @@ private: // GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling. this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage); } - void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage); - void setData(const GrGLSLProgramDataManager& pdman, - const GrShaderCaps&, - const GrGeometryProcessor& geomProc) override { - pdman.setSkMatrix(fViewMatrixUniform, - geomProc.cast<TessellationTestRectShader>().fViewMatrix); - } - GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; - }; - - GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override { - return new Impl; - } - - SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - - const SkMatrix fViewMatrix; -}; - -SkString TessellationTestRectShader::getTessControlShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps& caps) const { - SkString code(versionAndExtensionDecls); - code.append(R"( + SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(R"( layout(vertices = 1) out; in mat3 M_[]; @@ -248,16 +206,14 @@ SkString TessellationTestRectShader::getTessControlShaderGLSL( gl_TessLevelOuter[3] = 8.0; })"); - return code; -} - -SkString TessellationTestRectShader::getTessEvaluationShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps& caps) const { - SkString code(versionAndExtensionDecls); - code.appendf(R"( + return code; + } + SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.appendf(R"( layout(quads, equal_spacing, cw) in; uniform vec4 sk_RTAdjust; @@ -281,14 +237,13 @@ SkString TessellationTestRectShader::getTessEvaluationShaderGLSL( } })", kRect.left(), kRect.top(), kRect.right(), kRect.bottom()); - return code; -} - -void TessellationTestRectShader::Impl::writeFragmentShader( - GrGLSLFPFragmentBuilder* f, const char* color, const char* coverage) { - f->declareGlobal(GrShaderVar("barycentric_coord", kFloat4_GrSLType, - GrShaderVar::TypeModifier::In)); - f->codeAppendf(R"( + return code; + } + void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color, + const char* coverage) { + f->declareGlobal(GrShaderVar("barycentric_coord", kFloat4_GrSLType, + GrShaderVar::TypeModifier::In)); + f->codeAppendf(R"( float4 fwidths = fwidth(barycentric_coord); half coverage = 0; for (int i = 0; i < 4; ++i) { @@ -298,8 +253,23 @@ void TessellationTestRectShader::Impl::writeFragmentShader( } half4 %s = half4(coverage, 0, coverage, 1); const half4 %s = half4(1);)", color, coverage); -} + } + void setData(const GrGLSLProgramDataManager& pdman, + const GrShaderCaps&, + const GrGeometryProcessor& geomProc) override { + pdman.setSkMatrix(fViewMatrixUniform, + geomProc.cast<TessellationTestRectShader>().fViewMatrix); + } + GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; + }; + + GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override { + return new Impl; + } + + const SkMatrix fViewMatrix; +}; class TessellationTestOp : public GrDrawOp { DEFINE_OP_CLASS_ID diff --git a/include/private/SkSLLayout.h b/include/private/SkSLLayout.h index 6de5e6a55e..8886b3c8b9 100644 --- a/include/private/SkSLLayout.h +++ b/include/private/SkSLLayout.h @@ -21,26 +21,25 @@ struct Layout { enum Flag { kOriginUpperLeft_Flag = 1 << 0, kOverrideCoverage_Flag = 1 << 1, - kEarlyFragmentTests_Flag = 1 << 2, - kPushConstant_Flag = 1 << 3, - kBlendSupportAllEquations_Flag = 1 << 4, - kTracked_Flag = 1 << 5, - kSRGBUnpremul_Flag = 1 << 6, - kKey_Flag = 1 << 7, + kPushConstant_Flag = 1 << 2, + kBlendSupportAllEquations_Flag = 1 << 3, + kTracked_Flag = 1 << 4, + kSRGBUnpremul_Flag = 1 << 5, + kKey_Flag = 1 << 6, // These flags indicate if the qualifier appeared, regardless of the accompanying value. - kLocation_Flag = 1 << 8, - kOffset_Flag = 1 << 9, - kBinding_Flag = 1 << 10, - kIndex_Flag = 1 << 11, - kSet_Flag = 1 << 12, - kBuiltin_Flag = 1 << 13, - kInputAttachmentIndex_Flag = 1 << 14, - kPrimitive_Flag = 1 << 15, - kMaxVertices_Flag = 1 << 16, - kInvocations_Flag = 1 << 17, - kWhen_Flag = 1 << 18, - kCType_Flag = 1 << 19, + kLocation_Flag = 1 << 7, + kOffset_Flag = 1 << 8, + kBinding_Flag = 1 << 9, + kIndex_Flag = 1 << 10, + kSet_Flag = 1 << 11, + kBuiltin_Flag = 1 << 12, + kInputAttachmentIndex_Flag = 1 << 13, + kPrimitive_Flag = 1 << 14, + kMaxVertices_Flag = 1 << 15, + kInvocations_Flag = 1 << 16, + kWhen_Flag = 1 << 17, + kCType_Flag = 1 << 18, }; enum Primitive { @@ -184,9 +183,6 @@ struct Layout { if (fFlags & kOverrideCoverage_Flag) { result += separator() + "override_coverage"; } - if (fFlags & kEarlyFragmentTests_Flag) { - result += separator() + "early_fragment_tests"; - } if (fFlags & kBlendSupportAllEquations_Flag) { result += separator() + "blend_support_all_equations"; } diff --git a/include/private/SkTHash.h b/include/private/SkTHash.h index 7997300fa8..79851b83fe 100644 --- a/include/private/SkTHash.h +++ b/include/private/SkTHash.h @@ -235,6 +235,7 @@ private: T* uncheckedSet(T&& val) { const K& key = Traits::GetKey(val); + SkASSERT(key == key); uint32_t hash = Hash(key); int index = hash & (fCapacity-1); for (int n = 0; n < fCapacity; n++) { diff --git a/include/private/SkTLogic.h b/include/private/SkTLogic.h index ecd40a13d3..a2c2f4cfdb 100644 --- a/include/private/SkTLogic.h +++ b/include/private/SkTLogic.h @@ -15,6 +15,7 @@ #include <cstddef> #include <type_traits> #include <utility> +#include "include/private/SkTo.h" namespace skstd { @@ -79,4 +80,7 @@ template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type } // namespace sknonstd +template <typename Container> +constexpr int SkCount(const Container& c) { return SkTo<int>(skstd::size(c)); } + #endif diff --git a/modules/androidkit/src/Matrix.cpp b/modules/androidkit/src/Matrix.cpp index 60972432d5..d0d033ca1a 100644 --- a/modules/androidkit/src/Matrix.cpp +++ b/modules/androidkit/src/Matrix.cpp @@ -21,6 +21,18 @@ static jlong Matrix_Create(JNIEnv* env, jobject, jfloat m0, jfloat m4, jfloat m8 m3, m7, m11, m15)); } +static jlong Matrix_CreateLookAt(JNIEnv* env, jobject, float eyeX, float eyeY, float eyeZ, + float coaX, float coaY, float coaZ, + float upX, float upY, float upZ) { + return reinterpret_cast<jlong>(new SkM44(SkM44::LookAt({eyeX, eyeY, eyeZ}, + {coaX, coaY, coaZ}, + {upX, upY, upZ}))); +} + +static jlong Matrix_CreatePerspective(JNIEnv* env, jobject, float near, float far, float angle) { + return reinterpret_cast<jlong>(new SkM44(SkM44::Perspective(near, far, angle))); +} + static void Matrix_Release(JNIEnv* env, jobject, jlong native_matrix) { delete reinterpret_cast<SkM44*>(native_matrix); } @@ -32,6 +44,19 @@ static void Matrix_PreConcat(JNIEnv* env, jobject, jlong native_matrixA, jlong n } } +static long Matrix_Inverse(JNIEnv* env, jobject, jlong native_matrix) { + if (auto* m = reinterpret_cast<SkM44*>(native_matrix)) { + SkM44 inverse(SkM44::kUninitialized_Constructor); + if (m->invert(&inverse)) { + return reinterpret_cast<jlong>(new SkM44(inverse)); + } else { + // matrix was not invertible, return 0 to Java and handle exception there + return 0; + } + } + return 0; +} + static long Matrix_Concat(JNIEnv* env, jobject, jlong native_matrixA, jlong native_matrixB) { if (auto* mA = reinterpret_cast<SkM44*>(native_matrixA), * mB = reinterpret_cast<SkM44*>(native_matrixB); mA && mB) { @@ -63,13 +88,16 @@ static void Matrix_Rotate(JNIEnv* env, jobject, jlong native_matrix, jfloat x, j int register_androidkit_Matrix(JNIEnv* env) { static const JNINativeMethod methods[] = { - {"nCreate" , "(FFFFFFFFFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_Create)}, - {"nRelease" , "(J)V" , reinterpret_cast<void*>(Matrix_Release)}, - {"nPreConcat" , "(JJ)V" , reinterpret_cast<void*>(Matrix_PreConcat)}, - {"nConcat" , "(JJ)J" , reinterpret_cast<void*>(Matrix_Concat)}, - {"nTranslate" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Translate)}, - {"nScale" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Scale)}, - {"nRotate" , "(JFFFF)V" , reinterpret_cast<void*>(Matrix_Rotate)}, + {"nCreate" , "(FFFFFFFFFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_Create)}, + {"nCreateLookAt" , "(FFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_CreateLookAt)}, + {"nCreatePerspective" , "(FFF)J" , reinterpret_cast<void*>(Matrix_CreatePerspective)}, + {"nRelease" , "(J)V" , reinterpret_cast<void*>(Matrix_Release)}, + {"nInverse" , "(J)J" , reinterpret_cast<void*>(Matrix_Inverse)}, + {"nPreConcat" , "(JJ)V" , reinterpret_cast<void*>(Matrix_PreConcat)}, + {"nConcat" , "(JJ)J" , reinterpret_cast<void*>(Matrix_Concat)}, + {"nTranslate" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Translate)}, + {"nScale" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Scale)}, + {"nRotate" , "(JFFFF)V" , reinterpret_cast<void*>(Matrix_Rotate)}, }; const auto clazz = env->FindClass("org/skia/androidkit/Matrix"); diff --git a/modules/androidkit/src/Paint.cpp b/modules/androidkit/src/Paint.cpp index a3db3d23b0..aa946d5c6c 100644 --- a/modules/androidkit/src/Paint.cpp +++ b/modules/androidkit/src/Paint.cpp @@ -27,6 +27,18 @@ static void Paint_SetColor(JNIEnv* env, jobject, jlong native_paint, } } +static void Paint_SetStroke(JNIEnv* env, jobject, jlong native_paint, jboolean stroke) { + if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) { + paint->setStroke(stroke); + } +} + +static void Paint_SetStrokeWidth(JNIEnv* env, jobject, jlong native_paint, jfloat width) { + if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) { + paint->setStrokeWidth(width); + } +} + static void Paint_SetShader(JNIEnv* env, jobject, jlong native_paint, jlong native_shader) { if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) { paint->setShader(sk_ref_sp(reinterpret_cast<SkShader*>(native_shader))); @@ -37,10 +49,12 @@ static void Paint_SetShader(JNIEnv* env, jobject, jlong native_paint, jlong nati int register_androidkit_Paint(JNIEnv* env) { static const JNINativeMethod methods[] = { - {"nCreate" , "()J" , reinterpret_cast<void*>(Paint_Create)}, - {"nRelease" , "(J)V" , reinterpret_cast<void*>(Paint_Release)}, - {"nSetColor" , "(JFFFF)V", reinterpret_cast<void*>(Paint_SetColor)}, - {"nSetShader", "(JJ)V" , reinterpret_cast<void*>(Paint_SetShader)}, + {"nCreate" , "()J" , reinterpret_cast<void*>(Paint_Create)}, + {"nRelease" , "(J)V" , reinterpret_cast<void*>(Paint_Release)}, + {"nSetColor" , "(JFFFF)V", reinterpret_cast<void*>(Paint_SetColor)}, + {"nSetStroke" , "(JZ)V" , reinterpret_cast<void*>(Paint_SetStroke)}, + {"nSetStrokeWidth" , "(JF)V" , reinterpret_cast<void*>(Paint_SetStrokeWidth)}, + {"nSetShader" , "(JJ)V" , reinterpret_cast<void*>(Paint_SetShader)}, }; const auto clazz = env->FindClass("org/skia/androidkit/Paint"); diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java index cc8bd07646..84bbb2fdc9 100644 --- a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java +++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java @@ -40,12 +40,33 @@ public class Matrix { mNativeInstance = nativeInstance; } + public static Matrix makeLookAt(float eyeX, float eyeY, float eyeZ, + float coaX, float coaY, float coaZ, + float upX, float upY, float upZ) { + return new Matrix(nCreateLookAt(eyeX, eyeY, eyeZ, + coaX, coaY, coaZ, + upX, upY, upZ)); + } + + public static Matrix makePerspective(float near, float far, float angle) { + return new Matrix(nCreatePerspective(near, far, angle)); + } + + public static Matrix makeInverse(Matrix m) throws RuntimeException { + long nativeMatrix = nInverse(m.getNativeInstance()); + if (nativeMatrix == 0){ + // extend generic exception? + throw new RuntimeException("Matrix m was not an invertible Matrix"); + } + return new Matrix(nativeMatrix); + } + /* * A: this Matrix * B: Matrix passed in * Concat A * B, return new Matrix C as result */ - public static Matrix Concat(Matrix a, Matrix b) { + public static Matrix makeConcat(Matrix a, Matrix b) { long nativeA = a.mNativeInstance; long nativeB = b.mNativeInstance; long nativeC = nConcat(nativeA, nativeB); @@ -57,10 +78,11 @@ public class Matrix { * B: Matrix passed in * Concat B * A, store result in Matrix A */ - public void preConcat(Matrix b) { + public Matrix preConcat(Matrix b) { long nativeA = this.mNativeInstance; long nativeB = b.mNativeInstance; nPreConcat(nativeA, nativeB); + return this; } /* @@ -133,8 +155,13 @@ public class Matrix { float m1, float m5, float m9, float m13, float m2, float m6, float m10, float m14, float m3, float m7, float m11, float m15); + private static native long nCreateLookAt(float eyeX, float eyeY, float eyeZ, + float coaX, float coaY, float coaZ, + float upX, float upY, float upZ); + private static native long nCreatePerspective(float near, float far, float angle); private static native void nRelease(long nativeInstance); + private static native long nInverse(long mNativeInstance); private static native void nPreConcat(long mNativeInstanceA, long mNativeInstanceB); private static native long nConcat(long mNativeInstanceA, long mNativeInstanceB); private static native void nTranslate(long mNativeInstance, float x, float y, float z); diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java index 186e64291c..478747e0e5 100644 --- a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java +++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java @@ -25,6 +25,13 @@ public class Paint { nSetShader(mNativeInstance, shader != null ? shader.getNativeInstance() : 0); } + public void setStroke(boolean stroke) { + nSetStroke(mNativeInstance, stroke); + } + + public void setStrokeWidth(float w) { + nSetStrokeWidth(mNativeInstance, w); + } /** * Releases any resources associated with this Paint. */ @@ -45,5 +52,7 @@ public class Paint { private static native void nRelease(long nativeInstance); private static native void nSetColor(long nativeInstance, float r, float g, float b, float a); + private static native void nSetStroke(long nativeInstance, boolean stroke); + private static native void nSetStrokeWidth(long nativeInstance, float w); private static native void nSetShader(long nativeInstance, long nativeShader); } diff --git a/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp b/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp index 3b1be4a122..ef2889b072 100644 --- a/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp +++ b/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp @@ -20,10 +20,10 @@ half4 main() { color.g = 0; } -// // A for-loop with two init-variables. TODO(skia:11868): currently unsupported in DSL -// for (half x = 0, y = 1; x <= y; ++x) { -// color.a = x; -// } + // A for-loop with two init-variables. + for (uint x = 0, y = 1; x <= y; ++x) { + color.a = half(x); + } // color contains green. return color; diff --git a/resources/sksl/errors/LayoutRepeatedQualifiers.sksl b/resources/sksl/errors/LayoutRepeatedQualifiers.sksl index d2454e46c2..cae4867d2d 100644 --- a/resources/sksl/errors/LayoutRepeatedQualifiers.sksl +++ b/resources/sksl/errors/LayoutRepeatedQualifiers.sksl @@ -1,7 +1,6 @@ layout ( origin_upper_left, override_coverage, - early_fragment_tests, push_constant, blend_support_all_equations, tracked, @@ -21,7 +20,6 @@ layout ( origin_upper_left, override_coverage, - early_fragment_tests, push_constant, blend_support_all_equations, tracked, diff --git a/resources/sksl/folding/BoolFolding.sksl b/resources/sksl/folding/BoolFolding.sksl index 2b253d1a81..d2a3073449 100644 --- a/resources/sksl/folding/BoolFolding.sksl +++ b/resources/sksl/folding/BoolFolding.sksl @@ -14,12 +14,14 @@ bool test() { const bool TRUE = true; const bool FALSE = false; - bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE)); // all are true - bool l = all(bool3(TRUE, 1 == 2, true)); // three out of four are true - bool m = any(bool4(true, 1 == 2, true, TRUE)); // three out of four are true - bool n = any(bool2(0 == 1, FALSE)); // none are true + bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE)); // all are true + bool l = all(bool3(TRUE, 1 == 2, true)); // three out of four are true + bool m = any(bool4(true, 1 == 2, true, TRUE)); // three out of four are true + bool n = any(bool2(0 == 1, FALSE)); // none are true + bool o = any(not(bool2(0 == 1, FALSE))); // all true + bool p = all(not(bool4(1 == 1, !false, 123 > 12, TRUE))); // none are true - return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n; + return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n && o && !p; } half4 main(float2 coords) { diff --git a/resources/sksl/intrinsics/AbsFloat.sksl b/resources/sksl/intrinsics/AbsFloat.sksl index 04df900548..48fc4fc02b 100644 --- a/resources/sksl/intrinsics/AbsFloat.sksl +++ b/resources/sksl/intrinsics/AbsFloat.sksl @@ -1,10 +1,15 @@ -uniform half4 testInputs; +uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25) uniform half4 colorGreen, colorRed; half4 main(float2 coords) { + const half4 constVal = half4(-1.25, 0, 0.75, 2.25); half4 expected = half4(1.25, 0, 0.75, 2.25); return (abs(testInputs.x) == expected.x && abs(testInputs.xy) == expected.xy && abs(testInputs.xyz) == expected.xyz && - abs(testInputs.xyzw) == expected.xyzw) ? colorGreen : colorRed; + abs(testInputs.xyzw) == expected.xyzw && + abs(constVal.x) == expected.x && + abs(constVal.xy) == expected.xy && + abs(constVal.xyz) == expected.xyz && + abs(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed; } diff --git a/resources/sksl/intrinsics/AbsInt.sksl b/resources/sksl/intrinsics/AbsInt.sksl index 8a87d7c23e..3f0bd6887b 100644 --- a/resources/sksl/intrinsics/AbsInt.sksl +++ b/resources/sksl/intrinsics/AbsInt.sksl @@ -2,9 +2,14 @@ uniform half4 testInputs; uniform half4 colorGreen, colorRed; half4 main(float2 coords) { + const half4 constVal = half4(-1.25, 0, 0.75, 2.25); int4 expected = int4(1, 0, 0, 2); return (abs(int4(testInputs).x) == expected.x && abs(int4(testInputs).xy) == expected.xy && abs(int4(testInputs).xyz) == expected.xyz && - abs(int4(testInputs).xyzw) == expected.xyzw) ? colorGreen : colorRed; + abs(int4(testInputs).xyzw) == expected.xyzw && + abs(int4(constVal).x) == expected.x && + abs(int4(constVal).xy) == expected.xy && + abs(int4(constVal).xyz) == expected.xyz && + abs(int4(constVal).xyzw) == expected.xyzw) ? colorGreen : colorRed; } diff --git a/resources/sksl/intrinsics/All.sksl b/resources/sksl/intrinsics/All.sksl index 8e42eb1bb8..c8bb4f85c8 100644 --- a/resources/sksl/intrinsics/All.sksl +++ b/resources/sksl/intrinsics/All.sksl @@ -1 +1,14 @@ -bool4 a; void main() { sk_FragColor.x = all(a) ? 1 : 0; } +uniform half4 inputH4, expectedH4; +uniform half4 colorGreen, colorRed; + +half4 main(float2 coords) { + bool4 input = bool4(inputH4); + bool4 expected = bool4(expectedH4); + const bool4 constVal = bool4(true, true, false, true); + return (all(input.xy) == expected.x && + all(input.xyz) == expected.y && + all(input.xyzw) == expected.z && + all(constVal.xy) == expected.x && + all(constVal.xyz) == expected.y && + all(constVal.xyzw) == expected.z) ? colorGreen : colorRed; +} diff --git a/resources/sksl/intrinsics/Any.sksl b/resources/sksl/intrinsics/Any.sksl index eef8e3e94e..41d6396e50 100644 --- a/resources/sksl/intrinsics/Any.sksl +++ b/resources/sksl/intrinsics/Any.sksl @@ -1 +1,14 @@ -bool4 a; void main() { sk_FragColor.x = any(a) ? 1 : 0; } +uniform half4 inputH4, expectedH4; +uniform half4 colorGreen, colorRed; + +half4 main(float2 coords) { + bool4 input = bool4(inputH4); + bool4 expected = bool4(expectedH4); + const bool4 constVal = bool4(false, false, true, false); + return (any(input.xy) == expected.x && + any(input.xyz) == expected.y && + any(input.xyzw) == expected.z && + any(constVal.xy) == expected.x && + any(constVal.xyz) == expected.y && + any(constVal.xyzw) == expected.z) ? colorGreen : colorRed; +} diff --git a/resources/sksl/intrinsics/Not.sksl b/resources/sksl/intrinsics/Not.sksl index 008f5659d0..a6ff27a81b 100644 --- a/resources/sksl/intrinsics/Not.sksl +++ b/resources/sksl/intrinsics/Not.sksl @@ -1 +1,14 @@ -bool4 a; void main() { sk_FragColor.x = not(a).x ? 1 : 0; } +uniform half4 inputH4, expectedH4; +uniform half4 colorGreen, colorRed; + +half4 main(float2 coords) { + bool4 input = bool4(inputH4); + bool4 expected = bool4(expectedH4); + const bool4 constVal = bool4(true, false, true, false); + return (not(input.xy) == expected.xy && + not(input.xyz) == expected.xyz && + not(input.xyzw) == expected.xyzw && + not(constVal.xy) == expected.xy && + not(constVal.xyz) == expected.xyz && + not(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed; +} diff --git a/resources/sksl/intrinsics/SignFloat.sksl b/resources/sksl/intrinsics/SignFloat.sksl index 2f0ef8880f..33c3d41d7a 100644 --- a/resources/sksl/intrinsics/SignFloat.sksl +++ b/resources/sksl/intrinsics/SignFloat.sksl @@ -1,10 +1,15 @@ -uniform half4 testInputs; +uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25) uniform half4 colorGreen, colorRed; half4 main(float2 coords) { + const half4 constVal = half4(-1.25, 0, 0.75, 2.25); half4 expected = half4(-1, 0, 1, 1); return (sign(testInputs.x) == expected.x && sign(testInputs.xy) == expected.xy && sign(testInputs.xyz) == expected.xyz && - sign(testInputs.xyzw) == expected.xyzw) ? colorGreen : colorRed; + sign(testInputs.xyzw) == expected.xyzw && + sign(constVal.x) == expected.x && + sign(constVal.xy) == expected.xy && + sign(constVal.xyz) == expected.xyz && + sign(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed; } diff --git a/resources/sksl/intrinsics/SignInt.sksl b/resources/sksl/intrinsics/SignInt.sksl index e24a488089..c1debeb595 100644 --- a/resources/sksl/intrinsics/SignInt.sksl +++ b/resources/sksl/intrinsics/SignInt.sksl @@ -1,10 +1,15 @@ -uniform half4 minus1234; +uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25) uniform half4 colorGreen, colorRed; half4 main(float2 coords) { + const half4 constVal = half4(-1.25, 0, 0.75, 2.25); int4 expected = int4(-1, 0, 0, 1); return (sign(int4(testInputs).x) == expected.x && sign(int4(testInputs).xy) == expected.xy && sign(int4(testInputs).xyz) == expected.xyz && - sign(int4(testInputs).xyzw) == expected.xyzw) ? colorGreen : colorRed; + sign(int4(testInputs).xyzw) == expected.xyzw && + sign(int4(constVal).x) == expected.x && + sign(int4(constVal).xy) == expected.xy && + sign(int4(constVal).xyz) == expected.xyz && + sign(int4(constVal).xyzw) == expected.xyzw) ? colorGreen : colorRed; } diff --git a/resources/sksl/runtime_errors/IllegalIndexing.rts b/resources/sksl/runtime_errors/IllegalIndexing.rts index 9b3789ac55..3c24417646 100644 --- a/resources/sksl/runtime_errors/IllegalIndexing.rts +++ b/resources/sksl/runtime_errors/IllegalIndexing.rts @@ -25,5 +25,5 @@ uniform int u; void uniform_index() { int a[2]; a[u] = 0; } void param_index(int p) { int a[2]; a[p] = 0; } -// Legal in GLSL, not yet in SkSL: -void func_index() { int a[2]; a[int(abs(-1))] = 0; } // skbug.com/10835 +// Legal in SkSL when optimization is enabled: +void func_index() { int a[2]; a[int(abs(-1))] = 0; } diff --git a/src/android/SkAnimatedImage.cpp b/src/android/SkAnimatedImage.cpp index d18cb5fa01..4c87596b7e 100644 --- a/src/android/SkAnimatedImage.cpp +++ b/src/android/SkAnimatedImage.cpp @@ -44,8 +44,12 @@ sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> cod return nullptr; } - const auto& decodeInfo = codec->getInfo(); - const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions()); + auto decodeInfo = codec->getInfo(); + const auto origin = codec->codec()->getOrigin(); + if (SkEncodedOriginSwapsWidthHeight(origin)) { + decodeInfo = decodeInfo.makeWH(decodeInfo.height(), decodeInfo.width()); + } + const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions()); return Make(std::move(codec), decodeInfo, cropRect, nullptr); } diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp index af8b8e483d..a8b638fb1b 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -86,7 +86,7 @@ SkRect SkGlyphRun::sourceBounds(const SkPaint& paint) const { // Use conservative bounds. All glyph have a box of fontBounds size. if (fScaledRotations.empty()) { SkRect bounds; - bounds.setBounds(this->positions().data(), this->positions().count()); + bounds.setBounds(this->positions().data(), SkCount(this->positions())); bounds.fLeft += fontBounds.left(); bounds.fTop += fontBounds.top(); bounds.fRight += fontBounds.right(); @@ -269,7 +269,7 @@ const SkGlyphRunList& SkGlyphRunBuilder::blobToGlyphRunList( std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>> SkGlyphRunBuilder::convertRSXForm(SkSpan<const SkRSXform> xforms) { - const int count = xforms.count(); + const int count = SkCount(xforms); this->prepareBuffers(count, count); auto positions = SkSpan(fPositions.get(), count); auto scaledRotations = SkSpan(fScaledRotations.get(), count); diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index 848e0f9449..0608ce4fd7 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -103,13 +103,13 @@ public: SkRect sourceBounds() const { return fSourceBounds; } const SkTextBlob* blob() const { return fOriginalTextBlob; } - auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } - auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } - auto begin() const -> decltype(fGlyphRuns.cbegin()) { return fGlyphRuns.cbegin(); } - auto end() const -> decltype(fGlyphRuns.cend()) { return fGlyphRuns.cend(); } - auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } - auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } - auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } + auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } + auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } + auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); } + auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); } + auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } + auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } + auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } private: // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It diff --git a/src/core/SkSpan.h b/src/core/SkSpan.h index 44f5c828a3..a61c04ed32 100644 --- a/src/core/SkSpan.h +++ b/src/core/SkSpan.h @@ -13,7 +13,6 @@ #include <type_traits> #include <utility> #include "include/private/SkTLogic.h" -#include "include/private/SkTo.h" template <typename T> class SkSpan { @@ -40,14 +39,9 @@ public: constexpr T& back() const { return fPtr[fSize - 1]; } constexpr T* begin() const { return fPtr; } constexpr T* end() const { return fPtr + fSize; } - constexpr const T* cbegin() const { return this->begin(); } - constexpr const T* cend() const { return this->end(); } constexpr auto rbegin() const { return std::make_reverse_iterator(this->end()); } constexpr auto rend() const { return std::make_reverse_iterator(this->begin()); } - constexpr auto crbegin() const { return std::make_reverse_iterator(this->cend()); } - constexpr auto crend() const { return std::make_reverse_iterator(this->cbegin()); } constexpr T* data() const { return this->begin(); } - constexpr int count() const { return SkTo<int>(fSize); } constexpr size_t size() const { return fSize; } constexpr bool empty() const { return fSize == 0; } constexpr size_t size_bytes() const { return fSize * sizeof(T); } diff --git a/src/gpu/GrAATriangulator.cpp b/src/gpu/GrAATriangulator.cpp index 2df204cf7d..9565bd9658 100644 --- a/src/gpu/GrAATriangulator.cpp +++ b/src/gpu/GrAATriangulator.cpp @@ -645,6 +645,8 @@ Poly* GrAATriangulator::tessellate(const VertexList& mesh, const Comparator& c) this->connectPartners(&fOuterMesh, c); this->connectPartners(&innerMesh, c); SortedMerge(&innerMesh, &fOuterMesh, &aaMesh, c); + TESS_LOG("\nmerged mesh:\n"); + DUMP_MESH(aaMesh); this->mergeCoincidentVertices(&aaMesh, c); result = this->simplify(&aaMesh, c); TESS_LOG("combined and simplified mesh:\n"); diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h index 3ab108a0c2..73c7627eb0 100644 --- a/src/gpu/GrGeometryProcessor.h +++ b/src/gpu/GrGeometryProcessor.h @@ -218,21 +218,6 @@ public: the object. */ virtual GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const = 0; - // We use these methods as a temporary back door to inject OpenGL tessellation code. Once - // tessellation is supported by SkSL we can remove these. - virtual SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SK_ABORT("Not implemented."); - } - virtual SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SK_ABORT("Not implemented."); - } - protected: // GPs that need to use either float or ubyte colors can just call this to get a correctly // configured Attribute struct diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 3d94791818..32d5f60c9c 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -624,7 +624,7 @@ void GrGpu::executeFlushInfo(SkSpan<GrSurfaceProxy*> proxies, // We currently don't support passing in new surface state for multiple proxies here. The only // time we have multiple proxies is if we are flushing a yuv SkImage which won't have state // updates anyways. - SkASSERT(!newState || proxies.count() == 1); + SkASSERT(!newState || proxies.size() == 1); SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess); this->prepareSurfacesForBackendAccessAndStateUpdates(proxies, access, newState); } diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index e93da0b0c6..f5415c2cbd 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -29,7 +29,7 @@ class GrOp; class GrSurfaceDrawContext; /** - * This immutable object contains information needed to set build a shader program and set API + * This immutable object contains information needed to build a shader program and set API * state for a draw. It is used along with a GrGeometryProcessor and a source of geometric * data to draw. */ diff --git a/src/gpu/GrRenderTaskCluster.cpp b/src/gpu/GrRenderTaskCluster.cpp index a3ce2a996e..0cf2ea13e1 100644 --- a/src/gpu/GrRenderTaskCluster.cpp +++ b/src/gpu/GrRenderTaskCluster.cpp @@ -160,7 +160,7 @@ bool GrClusterRenderTasks(SkSpan<const sk_sp<GrRenderTask>> input, SkTInternalLList<GrRenderTask>* llist) { SkASSERT(llist->isEmpty()); - if (input.count() < 3) { + if (input.size() < 3) { return false; } diff --git a/src/gpu/GrTriangulator.cpp b/src/gpu/GrTriangulator.cpp index b998b4f16f..35f2131682 100644 --- a/src/gpu/GrTriangulator.cpp +++ b/src/gpu/GrTriangulator.cpp @@ -126,7 +126,15 @@ static inline void round(SkPoint* p) { } static inline SkScalar double_to_clamped_scalar(double d) { - return SkDoubleToScalar(std::min((double) SK_ScalarMax, std::max(d, (double) -SK_ScalarMax))); + // Clamps large values to what's finitely representable when cast back to a float. + static const double kMaxLimit = (double) SK_ScalarMax; + // It's not perfect, but a using a value larger than float_min helps protect from denormalized + // values and ill-conditions in intermediate calculations on coordinates. + static const double kNearZeroLimit = 16 * (double) std::numeric_limits<float>::min(); + if (std::abs(d) < kNearZeroLimit) { + d = 0.f; + } + return SkDoubleToScalar(std::max(-kMaxLimit, std::min(d, kMaxLimit))); } bool GrTriangulator::Line::intersect(const Line& other, SkPoint* point) const { @@ -163,8 +171,8 @@ bool GrTriangulator::Edge::intersect(const Edge& other, SkPoint* p, uint8_t* alp } double s = sNumer / denom; SkASSERT(s >= 0.0 && s <= 1.0); - p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB); - p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA); + p->fX = double_to_clamped_scalar(fTop->fPoint.fX - s * fLine.fB); + p->fY = double_to_clamped_scalar(fTop->fPoint.fY + s * fLine.fA); if (alpha) { if (fType == EdgeType::kInner || other.fType == EdgeType::kInner) { // If the intersection is on any interior edge, it needs to stay fully opaque or later @@ -273,6 +281,22 @@ void* GrTriangulator::emitTriangle(Vertex* prev, Vertex* curr, Vertex* next, int return emit_triangle(prev, curr, next, fEmitCoverage, data); } +GrTriangulator::Poly::Poly(Vertex* v, int winding) + : fFirstVertex(v) + , fWinding(winding) + , fHead(nullptr) + , fTail(nullptr) + , fNext(nullptr) + , fPartner(nullptr) + , fCount(0) +{ +#if TRIANGULATOR_LOGGING + static int gID = 0; + fID = gID++; + TESS_LOG("*** created Poly %d\n", fID); +#endif +} + Poly* GrTriangulator::Poly::addEdge(Edge* e, Side side, SkArenaAlloc* alloc) { TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n", e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right"); @@ -318,7 +342,7 @@ void* GrTriangulator::emitPoly(const Poly* poly, void *data) const { if (poly->fCount < 3) { return data; } - TESS_LOG("emit() %d, size %d\n", fID, fCount); + TESS_LOG("emit() %d, size %d\n", poly->fID, poly->fCount); for (MonotonePoly* m = poly->fHead; m != nullptr; m = m->fNext) { data = this->emitMonotonePoly(m, data); } @@ -894,7 +918,7 @@ Vertex* GrTriangulator::makeSortedVertex(const SkPoint& p, uint8_t alpha, Vertex static bool nearly_flat(const Comparator& c, Edge* edge) { SkPoint diff = edge->fBottom->fPoint - edge->fTop->fPoint; float primaryDiff = c.fDirection == Comparator::Direction::kHorizontal ? diff.fX : diff.fY; - return fabs(primaryDiff) < std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f; + return fabs(primaryDiff) <= std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f; } static SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, const Comparator& c) { @@ -944,19 +968,24 @@ bool GrTriangulator::checkForIntersection(Edge* left, Edge* right, EdgeList* act while (top && c.sweep_lt(p, top->fPoint)) { top = top->fPrev; } - if (!nearly_flat(c, left)) { + bool leftFlat = nearly_flat(c, left); + bool rightFlat = nearly_flat(c, right); + if (leftFlat && rightFlat) { + return false; + } + if (!leftFlat) { p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c); } - if (!nearly_flat(c, right)) { + if (!rightFlat) { p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c); } - if (p == left->fTop->fPoint) { + if (coincident(p, left->fTop->fPoint)) { v = left->fTop; - } else if (p == left->fBottom->fPoint) { + } else if (coincident(p, left->fBottom->fPoint)) { v = left->fBottom; - } else if (p == right->fTop->fPoint) { + } else if (coincident(p, right->fTop->fPoint)) { v = right->fTop; - } else if (p == right->fBottom->fPoint) { + } else if (coincident(p, right->fBottom->fPoint)) { v = right->fBottom; } else { v = this->makeSortedVertex(p, alpha, mesh, top, c); @@ -979,10 +1008,14 @@ void GrTriangulator::sanitizeContours(VertexList* contours, int contourCnt) cons for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) { SkASSERT(contour->fHead); Vertex* prev = contour->fTail; + prev->fPoint.fX = double_to_clamped_scalar((double) prev->fPoint.fX); + prev->fPoint.fY = double_to_clamped_scalar((double) prev->fPoint.fY); if (fRoundVerticesToQuarterPixel) { round(&prev->fPoint); } for (Vertex* v = contour->fHead; v;) { + v->fPoint.fX = double_to_clamped_scalar((double) v->fPoint.fX); + v->fPoint.fY = double_to_clamped_scalar((double) v->fPoint.fY); if (fRoundVerticesToQuarterPixel) { round(&v->fPoint); } @@ -1376,8 +1409,14 @@ Poly* GrTriangulator::contoursToPolys(VertexList* contours, int contourCnt) cons : Comparator::Direction::kVertical); VertexList mesh; this->contoursToMesh(contours, contourCnt, &mesh, c); + TESS_LOG("\ninitial mesh:\n"); + DUMP_MESH(mesh); SortMesh(&mesh, c); + TESS_LOG("\nsorted mesh:\n"); + DUMP_MESH(mesh); this->mergeCoincidentVertices(&mesh, c); + TESS_LOG("\nsorted+merged mesh:\n"); + DUMP_MESH(mesh); this->simplify(&mesh, c); TESS_LOG("\nsimplified mesh:\n"); DUMP_MESH(mesh); diff --git a/src/gpu/GrTriangulator.h b/src/gpu/GrTriangulator.h index 2b45a18ac0..97f97e59cf 100644 --- a/src/gpu/GrTriangulator.h +++ b/src/gpu/GrTriangulator.h @@ -465,21 +465,8 @@ struct GrTriangulator::MonotonePoly { }; struct GrTriangulator::Poly { - Poly(Vertex* v, int winding) - : fFirstVertex(v) - , fWinding(winding) - , fHead(nullptr) - , fTail(nullptr) - , fNext(nullptr) - , fPartner(nullptr) - , fCount(0) - { -#if TRIANGULATOR_LOGGING - static int gID = 0; - fID = gID++; - TESS_LOG("*** created Poly %d\n", fID); -#endif - } + Poly(Vertex* v, int winding); + Poly* addEdge(Edge* e, Side side, SkArenaAlloc* alloc); Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; } Vertex* fFirstVertex; diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp index 951b994f67..47505111b6 100644 --- a/src/gpu/effects/GrCustomXfermode.cpp +++ b/src/gpu/effects/GrCustomXfermode.cpp @@ -29,27 +29,26 @@ bool GrCustomXfermode::IsSupportedMode(SkBlendMode mode) { /////////////////////////////////////////////////////////////////////////////// static constexpr GrBlendEquation hw_blend_equation(SkBlendMode mode) { -// In C++14 this could be a constexpr int variable. -#define EQ_OFFSET (kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay) - static_assert(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + EQ_OFFSET); - static_assert(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + EQ_OFFSET); - static_assert(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + EQ_OFFSET); - static_assert(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + EQ_OFFSET); - static_assert(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + EQ_OFFSET); - static_assert(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + EQ_OFFSET); - static_assert(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + EQ_OFFSET); - static_assert(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + EQ_OFFSET); - static_assert(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + EQ_OFFSET); - static_assert(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + EQ_OFFSET); - static_assert(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + EQ_OFFSET); - static_assert(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + EQ_OFFSET); - static_assert(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + EQ_OFFSET); - static_assert(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + EQ_OFFSET); + constexpr int kEqOffset = (kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay); + static_assert(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + kEqOffset); + static_assert(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + kEqOffset); + static_assert(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + kEqOffset); + static_assert(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + kEqOffset); + static_assert(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + kEqOffset); + static_assert(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + kEqOffset); + static_assert(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + kEqOffset); + static_assert(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + kEqOffset); + static_assert(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + kEqOffset); + static_assert(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + kEqOffset); + static_assert(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + kEqOffset); + static_assert(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + kEqOffset); + static_assert(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + kEqOffset); + static_assert(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + kEqOffset); // There's an illegal GrBlendEquation that corresponds to no SkBlendMode, hence the extra +1. - static_assert(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + 1 + EQ_OFFSET); + static_assert(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + 1 + kEqOffset); - return static_cast<GrBlendEquation>((int)mode + EQ_OFFSET); + return static_cast<GrBlendEquation>((int)mode + kEqOffset); #undef EQ_OFFSET } diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 9cbcacf759..4d01640c4e 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -73,7 +73,18 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fShaderCaps.reset(new GrShaderCaps(contextOptions)); - this->init(contextOptions, ctxInfo, glInterface); + // All of Skia's automated testing of ANGLE and all related tuning of performance and driver + // workarounds is oriented around the D3D backends of ANGLE. Chrome has started using Skia + // on top of ANGLE's GL backend. In this case ANGLE is still interfacing the same underlying + // GL driver that our performance and correctness tuning was performed on. To avoid losing + // that we strip the ANGLE info and for the rest of caps setup pretend we're directly on top of + // the GL driver. Note that this means that some driver workarounds are likely implemented at + // two levels of the stack (Skia and ANGLE) but we haven't determined which. + if (ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL) { + this->init(contextOptions, ctxInfo.makeNonAngle(), glInterface); + } else { + this->init(contextOptions, ctxInfo, glInterface); + } } void GrGLCaps::init(const GrContextOptions& contextOptions, @@ -286,8 +297,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, #ifdef SK_BUILD_FOR_WIN // We're assuming that on Windows Chromium we're using ANGLE. - bool isANGLE = ctxInfo.driver() == GrGLDriver::kANGLE || - ctxInfo.driver() == GrGLDriver::kChromium; + bool isANGLE = ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown || + ctxInfo.driver() == GrGLDriver::kChromium; // Angle has slow read/write pixel paths for 32bit RGBA (but fast for BGRA). fRGBA8888PixelsOpsAreSlow = isANGLE; // On DX9 ANGLE reading a partial FBO is slow. TODO: Check whether this is still true and @@ -882,11 +893,12 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; // This is the value for GLSL ES 3.0. } // not sure for WebGL - // Flat interpolation appears to be slow on Qualcomm GPUs (tested Adreno 405 and 530). ANGLE + // Flat interpolation appears to be slow on Qualcomm GPUs (tested Adreno 405 and 530). // Avoid on ANGLE too, it inserts a geometry shader into the pipeline to implement flat interp. + // Is this only true on ANGLE's D3D backends or also on the GL backend? shaderCaps->fPreferFlatInterpolation = shaderCaps->fFlatInterpolationSupport && ctxInfo.vendor() != GrGLVendor::kQualcomm && - ctxInfo.driver() != GrGLDriver::kANGLE; + ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown; if (GR_IS_GR_GL(standard)) { shaderCaps->fNoPerspectiveInterpolationSupport = ctxInfo.glslGeneration() >= k130_GrGLSLGeneration; @@ -3528,7 +3540,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, } // The TransferPixelsToTexture test fails on ANGLE. - if (ctxInfo.driver() == GrGLDriver::kANGLE) { + // TODO: Limit this to D3D and perhaps more specifically than that. + if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown) { fTransferFromBufferToTextureSupport = false; } @@ -3594,7 +3607,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, // bugs seems to involve clearing too much and not skipping the clear. // See crbug.com/768134. This is also needed for full clears and was seen on an nVidia K620 // but only for D3D11 ANGLE. - if (GrGLANGLEBackend::kD3D11 == ctxInfo.angleBackend()) { + if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) { fPerformColorClearsAsDraws = true; } @@ -3713,8 +3726,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, } // http://anglebug.com/4536 - if (ctxInfo.driver() == GrGLDriver::kANGLE && - ctxInfo.angleBackend() != GrGLANGLEBackend::kOpenGL) { + if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 || + ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) { fBaseVertexBaseInstanceSupport = false; fNativeDrawIndirectSupport = false; fMultiDrawType = MultiDrawType::kNone; @@ -3816,7 +3829,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, // we've explicitly guarded the division with a check against zero. This manifests in much // more complex ways in some of our shaders, so we use this caps bit to add an epsilon value // to the denominator of divisions, even when we've added checks that the denominator isn't 0. - if (ctxInfo.driver() == GrGLDriver::kANGLE || ctxInfo.driver() == GrGLDriver::kChromium) { + if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown || + ctxInfo.driver() == GrGLDriver::kChromium) { shaderCaps->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; } #endif @@ -3975,8 +3989,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, #ifdef SK_BUILD_FOR_WIN // glDrawElementsIndirect fails GrMeshTest on every Win10 Intel bot. if (ctxInfo.driver() == GrGLDriver::kIntel || - (ctxInfo.driver() == GrGLDriver::kANGLE && - ctxInfo.angleVendor() == GrGLANGLEVendor::kIntel && + (ctxInfo.angleVendor() == GrGLVendor::kIntel && ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL)) { fNativeDrawIndexedIndirectIsBroken = true; fUseClientSideIndirectBuffers = true; @@ -4088,14 +4101,14 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, fMSFBOType = kNone_MSFBOType; } - // ANGLE doesn't support do-while loops - if (ctxInfo.driver() == GrGLDriver::kANGLE) { + // ANGLE doesn't support do-while loops. + if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown) { shaderCaps->fCanUseDoLoops = false; } // ANGLE's D3D9 backend + AMD GPUs are flaky with program binary caching (skbug.com/10395) if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 && - ctxInfo.angleVendor() == GrGLANGLEVendor::kAMD) { + ctxInfo.angleVendor() == GrGLVendor::kATI) { fProgramBinarySupport = false; } diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp index 55b6ff2e1a..615d9b95aa 100644 --- a/src/gpu/gl/GrGLContext.cpp +++ b/src/gpu/gl/GrGLContext.cpp @@ -75,6 +75,26 @@ std::unique_ptr<GrGLContext> GrGLContext::Make(sk_sp<const GrGLInterface> interf GrGLContext::~GrGLContext() {} +GrGLContextInfo GrGLContextInfo::makeNonAngle() const { + GrGLContextInfo copy = *this; + if (fDriverInfo.fANGLEBackend == GrGLANGLEBackend::kUnknown) { + return copy; + } + + copy.fDriverInfo.fVendor = copy.fDriverInfo.fANGLEVendor; + copy.fDriverInfo.fDriver = copy.fDriverInfo.fANGLEDriver; + copy.fDriverInfo.fDriverVersion = copy.fDriverInfo.fANGLEDriverVersion; + copy.fDriverInfo.fRenderer = copy.fDriverInfo.fANGLERenderer; + + copy.fDriverInfo.fANGLEBackend = GrGLANGLEBackend::kUnknown; + copy.fDriverInfo.fANGLEVendor = GrGLVendor::kOther; + copy.fDriverInfo.fANGLEDriver = GrGLDriver::kUnknown; + copy.fDriverInfo.fANGLEDriverVersion = GR_GL_DRIVER_UNKNOWN_VER; + copy.fDriverInfo.fANGLERenderer = GrGLRenderer::kOther; + + return copy; +} + GrGLContextInfo::GrGLContextInfo(ConstructorArgs&& args) { fInterface = std::move(args.fInterface); fDriverInfo = args.fDriverInfo; diff --git a/src/gpu/gl/GrGLContext.h b/src/gpu/gl/GrGLContext.h index 051f7e4c98..798fe1aa10 100644 --- a/src/gpu/gl/GrGLContext.h +++ b/src/gpu/gl/GrGLContext.h @@ -23,8 +23,8 @@ struct GrContextOptions; */ class GrGLContextInfo { public: - GrGLContextInfo(const GrGLContextInfo&) = delete; - GrGLContextInfo& operator=(const GrGLContextInfo&) = delete; + GrGLContextInfo(GrGLContextInfo&&) = default; + GrGLContextInfo& operator=(GrGLContextInfo&&) = default; virtual ~GrGLContextInfo() {} @@ -34,8 +34,8 @@ public: GrGLVendor vendor() const { return fDriverInfo.fVendor; } GrGLRenderer renderer() const { return fDriverInfo.fRenderer; } GrGLANGLEBackend angleBackend() const { return fDriverInfo.fANGLEBackend; } - GrGLANGLEVendor angleVendor() const { return fDriverInfo.fANGLEVendor; } - GrGLANGLERenderer angleRenderer() const { return fDriverInfo.fANGLERenderer; } + GrGLVendor angleVendor() const { return fDriverInfo.fANGLEVendor; } + GrGLRenderer angleRenderer() const { return fDriverInfo.fANGLERenderer; } /** What driver is running our GL implementation? This is not necessarily related to the vendor. (e.g. Intel GPU being driven by Mesa) */ GrGLDriver driver() const { return fDriverInfo.fDriver; } @@ -48,7 +48,17 @@ public: const GrGLExtensions& extensions() const { return fInterface->fExtensions; } + /** + * Makes a version of this context info that strips the "angle-ness". It will report kUnknown + * for angleBackend() and report this info's angleRenderer() as renderer() and similiar for + * driver(), driverVersion(), and vendor(). + */ + GrGLContextInfo makeNonAngle() const; + protected: + GrGLContextInfo& operator=(const GrGLContextInfo&) = default; + GrGLContextInfo(const GrGLContextInfo&) = default; + struct ConstructorArgs { sk_sp<const GrGLInterface> fInterface; GrGLDriverInfo fDriverInfo; diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp index c48471f0e9..4bedee4c97 100644 --- a/src/gpu/gl/GrGLUtil.cpp +++ b/src/gpu/gl/GrGLUtil.cpp @@ -25,7 +25,7 @@ /////////////////////////////////////////////////////////////////////////////// GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { - if (nullptr == versionString) { + if (!versionString) { SkDebugf("nullptr GL version string."); return kNone_GrGLStandard; } @@ -62,7 +62,7 @@ GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { } GrGLVersion GrGLGetVersionFromString(const char* versionString) { - if (nullptr == versionString) { + if (!versionString) { SkDebugf("nullptr GL version string."); return GR_GL_INVALID_VER; } @@ -103,6 +103,7 @@ GrGLVersion GrGLGetVersionFromString(const char* versionString) { } GrGLVersion GrGLGetVersion(const GrGLInterface* gl) { + SkASSERT(gl); const GrGLubyte* v; GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION)); return GrGLGetVersionFromString((const char*)v); @@ -159,13 +160,6 @@ static GrGLVendor get_vendor(const char* vendorString) { return GrGLVendor::kOther; } -static bool is_renderer_angle(const char* rendererString) { - SkASSERT(rendererString); - static constexpr char kHeader[] = "ANGLE "; - static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1; - return rendererString && 0 == strncmp(rendererString, kHeader, kHeaderLength); -} - static GrGLRenderer get_renderer(const char* rendererString, const GrGLExtensions& extensions) { SkASSERT(rendererString); static const char kTegraStr[] = "NVIDIA Tegra"; @@ -355,111 +349,30 @@ static GrGLRenderer get_renderer(const char* rendererString, const GrGLExtension mali400Num < 500) { return GrGLRenderer::kMali4xx; } - if (is_renderer_angle(rendererString)) { - return GrGLRenderer::kANGLE; - } return GrGLRenderer::kOther; } -std::tuple<GrGLANGLEBackend, GrGLANGLEVendor, GrGLANGLERenderer> -get_angle_info(const char* rendererString) { - auto backend = GrGLANGLEBackend::kUnknown; - auto vendor = GrGLANGLEVendor::kUnknown; - auto renderer = GrGLANGLERenderer::kUnknown; - if (!is_renderer_angle(rendererString)) { - return {backend, vendor, renderer}; - } - if (strstr(rendererString, "Intel")) { - vendor = GrGLANGLEVendor::kIntel; - - const char* modelStr; - int modelNumber; - if ((modelStr = strstr(rendererString, "HD Graphics")) && - (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) || - 1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) { - switch (modelNumber) { - case 2000: - case 3000: - renderer = GrGLANGLERenderer::kSandyBridge; - break; - case 4000: - case 2500: - renderer = GrGLANGLERenderer::kIvyBridge; - break; - case 510: - case 515: - case 520: - case 530: - renderer = GrGLANGLERenderer::kSkylake; - break; - } - } else if ((modelStr = strstr(rendererString, "Iris")) && - (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) || - 1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) || - 1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) { - switch (modelNumber) { - case 540: - case 550: - case 555: - case 580: - renderer = GrGLANGLERenderer::kSkylake; - break; - } - } - } else if (strstr(rendererString, "NVIDIA")) { - vendor = GrGLANGLEVendor::kNVIDIA; - } else if (strstr(rendererString, "Radeon")) { - vendor = GrGLANGLEVendor::kAMD; - } - if (strstr(rendererString, "Direct3D11")) { - backend = GrGLANGLEBackend::kD3D11; - } else if (strstr(rendererString, "Direct3D9")) { - backend = GrGLANGLEBackend::kD3D9; - } else if (strstr(rendererString, "OpenGL")) { - backend = GrGLANGLEBackend::kOpenGL; - } - return {backend, vendor, renderer}; -} - -GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { - if (!interface) { - return {}; - } - SkASSERT(interface->fStandard != kNone_GrGLStandard); - GrGLDriverInfo info; - info.fStandard = interface->fStandard; - - auto getString = [&](GrGLenum s) { - const GrGLubyte* bytes = interface->fFunctions.fGetString(s); - if (!bytes) { - return ""; - } - return reinterpret_cast<const char*>(bytes); - }; - - const char* const version = getString(GR_GL_VERSION); - const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION); - const char* const renderer = getString(GR_GL_RENDERER); - const char* const vendor = getString(GR_GL_VENDOR); +std::tuple<GrGLDriver, GrGLDriverVersion> get_driver_and_version(GrGLStandard standard, + GrGLVendor vendor, + const char* rendererString, + const char* versionString) { + SkASSERT(rendererString); + SkASSERT(versionString); - info.fVersion = GrGLGetVersionFromString(version); - info.fGLSLVersion = get_glsl_version(slversion); - info.fVendor = get_vendor(vendor); - info.fRenderer = get_renderer(renderer, interface->fExtensions); + GrGLDriver driver = GrGLDriver::kUnknown; + GrGLDriverVersion driverVersion = GR_GL_DRIVER_UNKNOWN_VER; - std::tie(info.fANGLEBackend, info.fANGLEVendor, info.fANGLERenderer) = get_angle_info(renderer); int major, minor, rev, driverMajor, driverMinor, driverPoint; - static const char kChromium[] = "Chromium"; char suffix[SK_ARRAY_COUNT(kChromium)] = {0}; - if (0 == strcmp(renderer, kChromium) || - (3 == sscanf(version, "OpenGL ES %d.%d %8s", &major, &minor, suffix) && + if (0 == strcmp(rendererString, kChromium) || + (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) && 0 == strcmp(kChromium, suffix))) { - info.fDriver = GrGLDriver::kChromium; - } else if (GR_IS_GR_GL(interface->fStandard)) { - if (info.fVendor == GrGLVendor::kNVIDIA) { - info.fDriver = GrGLDriver::kNVIDIA; - int n = sscanf(version, + driver = GrGLDriver::kChromium; + } else if (GR_IS_GR_GL(standard)) { + if (vendor == GrGLVendor::kNVIDIA) { + driver = GrGLDriver::kNVIDIA; + int n = sscanf(versionString, "%d.%d.%d NVIDIA %d.%d", &major, &minor, @@ -468,12 +381,17 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { &driverMinor); // Some older NVIDIA drivers don't report the driver version. if (n == 5) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } } else { - int n = sscanf(version, "%d.%d Mesa %d.%d", &major, &minor, &driverMajor, &driverMinor); + int n = sscanf(versionString, + "%d.%d Mesa %d.%d", + &major, + &minor, + &driverMajor, + &driverMinor); if (n != 4) { - n = sscanf(version, + n = sscanf(versionString, "%d.%d (Core Profile) Mesa %d.%d", &major, &minor, @@ -481,14 +399,14 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { &driverMinor); } if (n == 4) { - info.fDriver = GrGLDriver::kMesa; - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); + driver = GrGLDriver::kMesa; + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } } - } else if (GR_IS_GR_GL_ES(interface->fStandard)) { - if (info.fVendor == GrGLVendor::kNVIDIA) { - info.fDriver = GrGLDriver::kNVIDIA; - int n = sscanf(version, + } else if (standard) { + if (vendor == GrGLVendor::kNVIDIA) { + driver = GrGLDriver::kNVIDIA; + int n = sscanf(versionString, "OpenGL ES %d.%d NVIDIA %d.%d", &major, &minor, @@ -496,42 +414,31 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { &driverMinor); // Some older NVIDIA drivers don't report the driver version. if (n == 4) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } } else { - int n = sscanf(version, + int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d", &major, &minor, &driverMajor, &driverMinor); if (n == 4) { - info.fDriver = GrGLDriver::kMesa; - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); - } else if (0 == strncmp("ANGLE", renderer, 5)) { - info.fDriver = GrGLDriver::kANGLE; - n = sscanf(version, - "OpenGL ES %d.%d (ANGLE %d.%d", - &major, - &minor, - &driverMajor, - &driverMinor); - if (n == 4) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); - } + driver = GrGLDriver::kMesa; + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } } } - if (info.fDriver == GrGLDriver::kUnknown) { - if (info.fVendor == GrGLVendor::kGoogle) { + if (driver == GrGLDriver::kUnknown) { + if (vendor == GrGLVendor::kGoogle) { // Swiftshader is the only Google vendor at the moment - info.fDriver = GrGLDriver::kSwiftShader; + driver = GrGLDriver::kSwiftShader; // Swiftshader has a strange version string: w.x.y.z Going to arbitrarily ignore // y and assume w,x and z are major, minor, point. // As of writing, version is 4.0.0.6 - int n = sscanf(version, + int n = sscanf(versionString, "OpenGL ES %d.%d SwiftShader %d.%d.0.%d", &major, &minor, @@ -539,16 +446,16 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { &driverMinor, &driverPoint); if (n == 5) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); } - } else if (info.fVendor == GrGLVendor::kIntel) { + } else if (vendor == GrGLVendor::kIntel) { // We presume we're on the Intel driver since it hasn't identified itself as Mesa. - info.fDriver = GrGLDriver::kIntel; + driver = GrGLDriver::kIntel; // This is how the macOS version strings are structured. This might be different on // different // OSes. - int n = sscanf(version, + int n = sscanf(versionString, "%d.%d INTEL-%d.%d.%d", &major, &minor, @@ -556,18 +463,22 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { &driverMinor, &driverPoint); if (n == 5) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); } - } else if (info.fVendor == GrGLVendor::kQualcomm) { - info.fDriver = GrGLDriver::kQualcomm; - int n = sscanf( - version, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor, &driverMinor); + } else if (vendor == GrGLVendor::kQualcomm) { + driver = GrGLDriver::kQualcomm; + int n = sscanf(versionString, + "OpenGL ES %d.%d V@%d.%d", + &major, + &minor, + &driverMajor, + &driverMinor); if (n == 4) { - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } - } else if (info.fVendor == GrGLVendor::kImagination) { + } else if (vendor == GrGLVendor::kImagination) { int revision; - int n = sscanf(version, + int n = sscanf(versionString, "OpenGL ES %d.%d build %d.%d@%d", &major, &minor, @@ -577,15 +488,171 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { if (n == 5) { // Revision is a large number (looks like a source control revision number) that // doesn't fit into the 'patch' bits, so omit it until we need it. - info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); + driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); } } else { static constexpr char kEmulatorPrefix[] = "Android Emulator OpenGL ES Translator"; - if (0 == strncmp(kEmulatorPrefix, renderer, strlen(kEmulatorPrefix))) { - info.fDriver = GrGLDriver::kAndroidEmulator; + if (0 == strncmp(kEmulatorPrefix, rendererString, strlen(kEmulatorPrefix))) { + driver = GrGLDriver::kAndroidEmulator; } } } + return {driver, driverVersion}; +} + +// If this is detected as ANGLE then the ANGLE backend is returned along with rendererString +// stripped of "ANGLE(" and ")" at the start and end, respectively. +static std::tuple<GrGLANGLEBackend, SkString> get_angle_backend(const char* rendererString) { + // crbug.com/1203705 ANGLE renderer will be "ANGLE (<gl-vendor>, <gl-renderer>, <gl-version>)" + // on ANGLE's GL backend with related substitutions for the inner strings on other backends. + static constexpr char kHeader[] = "ANGLE ("; + static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1; + int rendererLength = strlen(rendererString); + if (!strncmp(rendererString, kHeader, kHeaderLength) && + rendererString[rendererLength - 1] == ')') { + SkString innerString; + innerString.set(rendererString + kHeaderLength, rendererLength - kHeaderLength - 1); + if (strstr(rendererString, "Direct3D11")) { + return {GrGLANGLEBackend::kD3D11, std::move(innerString)}; + } else if (strstr(rendererString, "Direct3D9")) { + return {GrGLANGLEBackend::kD3D9, std::move(innerString)}; + } else if (strstr(rendererString, "OpenGL")) { + return {GrGLANGLEBackend::kOpenGL, std::move(innerString)}; + } + } + return {GrGLANGLEBackend::kUnknown, {}}; +} + +std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion> +get_angle_gl_vendor_and_renderer( + const char* innerString, + const GrGLExtensions& extensions) { + SkTArray<SkString> parts; + SkStrSplit(innerString, ",", &parts); + // This would need some fixing if we have substrings that contain commas. + if (parts.size() != 3) { + return {GrGLVendor::kOther, + GrGLRenderer::kOther, + GrGLDriver::kUnknown, + GR_GL_DRIVER_UNKNOWN_VER}; + } + + const char* angleVendorString = parts[0].c_str(); + const char* angleRendererString = parts[1].c_str() + 1; // skip initial space + const char* angleVersionString = parts[2].c_str() + 1; // skip initial space + + GrGLVendor angleVendor = get_vendor(angleVendorString); + + auto [angleDriver, angleDriverVersion] = get_driver_and_version(kGLES_GrGLStandard, + angleVendor, + angleRendererString, + angleVersionString); + + auto angleRenderer = get_renderer(angleRendererString, extensions); + + return {angleVendor, angleRenderer, angleDriver, angleDriverVersion}; +} + +std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion> +get_angle_d3d_vendor_and_renderer(const char* innerString) { + auto vendor = GrGLVendor::kOther; + auto renderer = GrGLRenderer::kOther; + + if (strstr(innerString, "Intel")) { + vendor = GrGLVendor::kIntel; + + const char* modelStr; + int modelNumber; + if ((modelStr = strstr(innerString, "HD Graphics")) && + (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) || + 1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) { + switch (modelNumber) { + case 2000: + case 3000: + renderer = GrGLRenderer::kIntelSandyBridge; + break; + case 4000: + case 2500: + renderer = GrGLRenderer::kIntelSandyBridge; + break; + case 510: + case 515: + case 520: + case 530: + renderer = GrGLRenderer::kIntelSkyLake; + break; + } + } else if ((modelStr = strstr(innerString, "Iris")) && + (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) || + 1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) || + 1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) { + switch (modelNumber) { + case 540: + case 550: + case 555: + case 580: + renderer = GrGLRenderer::kIntelSkyLake; + break; + } + } + } else if (strstr(innerString, "NVIDIA")) { + vendor = GrGLVendor::kNVIDIA; + } else if (strstr(innerString, "Radeon")) { + vendor = GrGLVendor::kATI; + } + // We haven't had a need yet to parse the D3D driver string. + return {vendor, renderer, GrGLDriver::kUnknown, GR_GL_DRIVER_UNKNOWN_VER}; +} + +GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) { + if (!interface) { + return {}; + } + SkASSERT(interface->fStandard != kNone_GrGLStandard); + GrGLDriverInfo info; + info.fStandard = interface->fStandard; + + auto getString = [&](GrGLenum s) { + const GrGLubyte* bytes = interface->fFunctions.fGetString(s); + if (!bytes) { + return ""; + } + return reinterpret_cast<const char*>(bytes); + }; + + const char* const version = getString(GR_GL_VERSION); + const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION); + const char* const renderer = getString(GR_GL_RENDERER); + const char* const vendor = getString(GR_GL_VENDOR); + + info.fVersion = GrGLGetVersionFromString(version); + info.fGLSLVersion = get_glsl_version(slversion); + info.fVendor = get_vendor(vendor); + info.fRenderer = get_renderer(renderer, interface->fExtensions); + + std::tie(info.fDriver, info.fDriverVersion) = get_driver_and_version(interface->fStandard, + info.fVendor, + renderer, + version); + + SkString innerAngleRendererString; + std::tie(info.fANGLEBackend, innerAngleRendererString) = get_angle_backend(renderer); + + if (info.fANGLEBackend == GrGLANGLEBackend::kD3D9 || + info.fANGLEBackend == GrGLANGLEBackend::kD3D11) { + std::tie(info.fANGLEVendor, + info.fANGLERenderer, + info.fANGLEDriver, + info.fANGLEDriverVersion) = + get_angle_d3d_vendor_and_renderer(innerAngleRendererString.c_str()); + } else if (info.fANGLEBackend == GrGLANGLEBackend::kOpenGL) { + std::tie(info.fANGLEVendor, + info.fANGLERenderer, + info.fANGLEDriver, + info.fANGLEDriverVersion) = + get_angle_gl_vendor_and_renderer(innerAngleRendererString.c_str(), + interface->fExtensions); + } return info; } diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h index 71d2a69acc..877779426b 100644 --- a/src/gpu/gl/GrGLUtil.h +++ b/src/gpu/gl/GrGLUtil.h @@ -135,7 +135,6 @@ enum class GrGLRenderer { kMaliG, /** T-6xx, T-7xx, or T-8xx */ kMaliT, - kANGLE, kAMDRadeonHD7xxx, // AMD Radeon HD 7000 Series kAMDRadeonR9M3xx, // AMD Radeon R9 M300 Series @@ -151,7 +150,6 @@ enum class GrGLDriver { kChromium, kNVIDIA, kIntel, - kANGLE, kSwiftShader, kQualcomm, kAndroidEmulator, @@ -165,20 +163,6 @@ enum class GrGLANGLEBackend { kOpenGL }; -enum class GrGLANGLEVendor { - kUnknown, - kIntel, - kNVIDIA, - kAMD -}; - -enum class GrGLANGLERenderer { - kUnknown, - kSandyBridge, - kIvyBridge, - kSkylake -}; - //////////////////////////////////////////////////////////////////////////////// /** @@ -236,16 +220,19 @@ GrGLSLVersion GrGLGetVersion(const GrGLInterface*); GrGLSLVersion GrGLGetVersionFromString(const char*); struct GrGLDriverInfo { - GrGLStandard fStandard = kNone_GrGLStandard; - GrGLVersion fVersion = GR_GL_INVALID_VER; - GrGLSLVersion fGLSLVersion = GR_GLSL_INVALID_VER; - GrGLVendor fVendor = GrGLVendor::kOther; - GrGLRenderer fRenderer = GrGLRenderer::kOther; - GrGLDriver fDriver = GrGLDriver::kUnknown; - GrGLDriverVersion fDriverVersion = GR_GL_DRIVER_UNKNOWN_VER; - GrGLANGLEBackend fANGLEBackend = GrGLANGLEBackend::kUnknown; - GrGLANGLEVendor fANGLEVendor = GrGLANGLEVendor::kUnknown; - GrGLANGLERenderer fANGLERenderer = GrGLANGLERenderer::kUnknown; + GrGLStandard fStandard = kNone_GrGLStandard; + GrGLVersion fVersion = GR_GL_INVALID_VER; + GrGLSLVersion fGLSLVersion = GR_GLSL_INVALID_VER; + GrGLVendor fVendor = GrGLVendor::kOther; + GrGLRenderer fRenderer = GrGLRenderer::kOther; + GrGLDriver fDriver = GrGLDriver::kUnknown; + GrGLDriverVersion fDriverVersion = GR_GL_DRIVER_UNKNOWN_VER; + + GrGLANGLEBackend fANGLEBackend = GrGLANGLEBackend::kUnknown; + GrGLVendor fANGLEVendor = GrGLVendor::kOther; + GrGLRenderer fANGLERenderer = GrGLRenderer::kOther; + GrGLDriver fANGLEDriver = GrGLDriver::kUnknown; + GrGLDriverVersion fANGLEDriverVersion = GR_GL_DRIVER_UNKNOWN_VER; }; GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface*); diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 856d2b9836..210faaa234 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -389,8 +389,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString); } - SkString tessControlShader = geomProc.getTessControlShaderGLSL( - fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler, + SkString tessControlShader = fGeometryProcessor->getTessControlShaderGLSL( + geomProc, versionAndExtensionDecls.c_str(), fUniformHandler, *this->shaderCaps()); if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID, GR_GL_TESS_CONTROL_SHADER, &shadersToDelete, @@ -399,8 +399,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr return nullptr; } - SkString tessEvaluationShader = geomProc.getTessEvaluationShaderGLSL( - fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler, + SkString tessEvaluationShader = fGeometryProcessor->getTessEvaluationShaderGLSL( + geomProc, versionAndExtensionDecls.c_str(), fUniformHandler, *this->shaderCaps()); if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID, GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete, @@ -459,7 +459,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr if (!cached && !geomProc.willUseTessellationShaders() && !precompiledProgram) { // FIXME: Remove the check for tessellation shaders in the above 'if' once the back door // GLSL mechanism is removed. - (void)&GrGeometryProcessor::getTessControlShaderGLSL; + (void)&GrGLSLGeometryProcessor::getTessControlShaderGLSL; bool isSkSL = false; if (fGpu->getContext()->priv().options().fShaderCacheStrategy == GrContextOptions::ShaderCacheStrategy::kSkSL) { diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h index a52406a8f1..bf1d62aed7 100644 --- a/src/gpu/glsl/GrGLSLGeometryProcessor.h +++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h @@ -130,6 +130,21 @@ public: const GrShaderCaps&, const GrGeometryProcessor&) = 0; + // We use these methods as a temporary back door to inject OpenGL tessellation code. Once + // tessellation is supported by SkSL we can remove these. + virtual SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const { + SK_ABORT("Not implemented."); + } + virtual SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const { + SK_ABORT("Not implemented."); + } + protected: void setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder, GrGLSLUniformHandler* uniformHandler, diff --git a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp index 6fe394dce3..0c28e5228b 100644 --- a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp +++ b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp @@ -16,20 +16,18 @@ void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char* if (this->getProgramBuilder()->snapVerticesToPixelCenters()) { if (kFloat3_GrSLType == devPosType) { const char* p = devPos; - out->appendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p); + out->appendf("{float2 _posTmp = %s.xy / %s.z;", p, p); } else { SkASSERT(kFloat2_GrSLType == devPosType); out->appendf("{float2 _posTmp = %s;", devPos); } - out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);" - "sk_Position = float4(_posTmp, 0, 1);}"); + out->appendf("_posTmp = floor(_posTmp) + float2(0.5);" + "sk_Position = _posTmp.xy01;}"); } else if (kFloat3_GrSLType == devPosType) { - out->appendf("sk_Position = float4(%s.x , %s.y, 0, %s.z);", - devPos, devPos, devPos); + out->appendf("sk_Position = %s.xy0z;", devPos); } else { SkASSERT(kFloat2_GrSLType == devPosType); - out->appendf("sk_Position = float4(%s.x , %s.y, 0, 1);", - devPos, devPos); + out->appendf("sk_Position = %s.xy01;", devPos); } } diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp index cf4e8bb004..85b1f42d73 100644 --- a/src/gpu/tessellate/GrStencilPathShader.cpp +++ b/src/gpu/tessellate/GrStencilPathShader.cpp @@ -109,185 +109,197 @@ GrGLSLGeometryProcessor* GrStencilPathShader::createGLSLInstance(const GrShaderC return new Impl; } -SkString GrCubicTessellateShader::getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(kWangsFormulaCubicFn); - code.append(kSkSLTypeDefs); - code.append(kUnpackRationalCubicFn); - code.append(R"( - layout(vertices = 1) out; - - in vec2 vsPt[]; - out vec4 X[]; - out vec4 Y[]; - out float w[]; - - void main() { - mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]); - - // Chop the curve at T=1/2. Here we take advantage of the fact that a uniform scalar has no - // effect on homogeneous coordinates in order to eval quickly at .5: - // - // mix(p0, p1, .5) / mix(w0, w1, .5) - // == ((p0 + p1) * .5) / ((w0 + w1) * .5) - // == (p0 + p1) / (w0 + w1) - // - vec3 ab = P[0] + P[1]; - vec3 bc = P[1] + P[2]; - vec3 cd = P[2] + P[3]; - vec3 abc = ab + bc; - vec3 bcd = bc + cd; - vec3 abcd = abc + bcd; - - // Calculate how many triangles we need to linearize each half of the curve. We simply call - // Wang's formula for integral cubics with the down-projected points. This appears to be an - // upper bound on what the actual number of subdivisions would have been. - float w0 = wangs_formula_cubic(P[0].xy, ab.xy/ab.z, abc.xy/abc.z, abcd.xy/abcd.z); - float w1 = wangs_formula_cubic(abcd.xy/abcd.z, bcd.xy/bcd.z, cd.xy/cd.z, P[3].xy); - - gl_TessLevelOuter[0] = w1; - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = w0; - - // Changing the inner level to 1 when w0 == w1 == 1 collapses the entire patch to a single - // triangle. Otherwise, we need an inner level of 2 so our curve triangles have an interior - // point to originate from. - gl_TessLevelInner[0] = min(max(w0, w1), 2.0); - - X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x); - Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y); - w[gl_InvocationID /*== 0*/] = P[1].z; - })"); - - return code; -} - -SkString GrCubicTessellateShader::getTessEvaluationShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(kSkSLTypeDefs); - code.append(kEvalRationalCubicFn); - code.append(R"( - layout(triangles, equal_spacing, ccw) in; - - uniform vec4 sk_RTAdjust; - - in vec4 X[]; - in vec4 Y[]; - in float w[]; - - void main() { - // Locate our parametric point of interest. T ramps from [0..1/2] on the left edge of the - // triangle, and [1/2..1] on the right. If we are the patch's interior vertex, then we want - // T=1/2. Since the barycentric coords are (1/3, 1/3, 1/3) at the interior vertex, the below - // fma() works in all 3 scenarios. - float T = fma(.5, gl_TessCoord.y, gl_TessCoord.z); - - mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1)); - vec2 vertexpos = eval_rational_cubic(P, T); - if (all(notEqual(gl_TessCoord.xz, vec2(0)))) { - // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)]. - vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0; +GrGLSLGeometryProcessor* GrCubicTessellateShader::createGLSLInstance(const GrShaderCaps&) const { + class CubicImpl : public GrStencilPathShader::Impl { + SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(kWangsFormulaCubicFn); + code.append(kSkSLTypeDefs); + code.append(kUnpackRationalCubicFn); + code.append(R"( + layout(vertices = 1) out; + + in vec2 vsPt[]; + out vec4 X[]; + out vec4 Y[]; + out float w[]; + + void main() { + mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]); + + // Chop the curve at T=1/2. Here we take advantage of the fact that a uniform scalar + // has no effect on homogeneous coordinates in order to eval quickly at .5: + // + // mix(p0, p1, .5) / mix(w0, w1, .5) + // == ((p0 + p1) * .5) / ((w0 + w1) * .5) + // == (p0 + p1) / (w0 + w1) + // + vec3 ab = P[0] + P[1]; + vec3 bc = P[1] + P[2]; + vec3 cd = P[2] + P[3]; + vec3 abc = ab + bc; + vec3 bcd = bc + cd; + vec3 abcd = abc + bcd; + + // Calculate how many triangles we need to linearize each half of the curve. We + // simply call Wang's formula for integral cubics with the down-projected points. + // This appears to be an upper bound on what the actual number of subdivisions would + // have been. + float w0 = wangs_formula_cubic(P[0].xy, ab.xy/ab.z, abc.xy/abc.z, abcd.xy/abcd.z); + float w1 = wangs_formula_cubic(abcd.xy/abcd.z, bcd.xy/bcd.z, cd.xy/cd.z, P[3].xy); + + gl_TessLevelOuter[0] = w1; + gl_TessLevelOuter[1] = 1.0; + gl_TessLevelOuter[2] = w0; + + // Changing the inner level to 1 when w0 == w1 == 1 collapses the entire patch to a + // single triangle. Otherwise, we need an inner level of 2 so our curve triangles + // have an interior point to originate from. + gl_TessLevelInner[0] = min(max(w0, w1), 2.0); + + X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x); + Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y); + w[gl_InvocationID /*== 0*/] = P[1].z; + })"); + + return code; } - gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0); - })"); - - return code; -} + SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(kSkSLTypeDefs); + code.append(kEvalRationalCubicFn); + code.append(R"( + layout(triangles, equal_spacing, ccw) in; + + uniform vec4 sk_RTAdjust; + + in vec4 X[]; + in vec4 Y[]; + in float w[]; + + void main() { + // Locate our parametric point of interest. T ramps from [0..1/2] on the left edge + // of the triangle, and [1/2..1] on the right. If we are the patch's interior + // vertex, then we want T=1/2. Since the barycentric coords are (1/3, 1/3, 1/3) at + // the interior vertex, the below fma() works in all 3 scenarios. + float T = fma(.5, gl_TessCoord.y, gl_TessCoord.z); + + mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1)); + vec2 vertexpos = eval_rational_cubic(P, T); + if (all(notEqual(gl_TessCoord.xz, vec2(0)))) { + // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)]. + vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0; + } + + gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0); + })"); + + return code; + } + }; -SkString GrWedgeTessellateShader::getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(kWangsFormulaCubicFn); - code.append(kSkSLTypeDefs); - code.append(kUnpackRationalCubicFn); - code.append(R"( - layout(vertices = 1) out; - - in vec2 vsPt[]; - out vec4 X[]; - out vec4 Y[]; - out float w[]; - out vec2 fanpoint[]; - - void main() { - mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]); - - // Figure out how many segments to divide the curve into. To do this we simply call Wang's - // formula for integral cubics with the down-projected points. This appears to be an upper - // bound on what the actual number of subdivisions would have been. - float num_segments = wangs_formula_cubic(P[0].xy, P[1].xy/P[1].z, P[2].xy/P[2].z, P[3].xy); - - // Tessellate the first side of the patch into num_segments triangles. - gl_TessLevelOuter[0] = num_segments; - - // Leave the other two sides of the patch as single segments. - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = 1.0; - - // Changing the inner level to 1 when num_segments == 1 collapses the entire - // patch to a single triangle. Otherwise, we need an inner level of 2 so our curve - // triangles have an interior point to originate from. - gl_TessLevelInner[0] = min(num_segments, 2.0); - - X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x); - Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y); - w[gl_InvocationID /*== 0*/] = P[1].z; - fanpoint[gl_InvocationID /*== 0*/] = vsPt[4]; - })"); - - return code; + return new CubicImpl; } -SkString GrWedgeTessellateShader::getTessEvaluationShaderGLSL( - const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const { - SkString code(versionAndExtensionDecls); - code.append(kSkSLTypeDefs); - code.append(kEvalRationalCubicFn); - code.append(R"( - layout(triangles, equal_spacing, ccw) in; - - uniform vec4 sk_RTAdjust; - - in vec4 X[]; - in vec4 Y[]; - in float w[]; - in vec2 fanpoint[]; - - void main() { - // Locate our parametric point of interest. It is equal to the barycentric y-coordinate if - // we are a vertex on the tessellated edge of the triangle patch, 0.5 if we are the patch's - // interior vertex, or N/A if we are the fan point. - // NOTE: We are on the tessellated edge when the barycentric x-coordinate == 0. - float T = (gl_TessCoord.x == 0.0) ? gl_TessCoord.y : 0.5; - - mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1)); - vec2 vertexpos = eval_rational_cubic(P, T); - - if (gl_TessCoord.x == 1.0) { - // We are the anchor point that fans from the center of the curve's contour. - vertexpos = fanpoint[0]; - } else if (gl_TessCoord.x != 0.0) { - // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)]. - vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0; +GrGLSLGeometryProcessor* GrWedgeTessellateShader::createGLSLInstance(const GrShaderCaps&) const { + class WedgeImpl : public GrStencilPathShader::Impl { + SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(kWangsFormulaCubicFn); + code.append(kSkSLTypeDefs); + code.append(kUnpackRationalCubicFn); + code.append(R"( + layout(vertices = 1) out; + + in vec2 vsPt[]; + out vec4 X[]; + out vec4 Y[]; + out float w[]; + out vec2 fanpoint[]; + + void main() { + mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]); + + // Figure out how many segments to divide the curve into. To do this we simply call + // Wang's formula for integral cubics with the down-projected points. This appears + // to be an upper bound on what the actual number of subdivisions would have been. + float num_segments = wangs_formula_cubic(P[0].xy, P[1].xy/P[1].z, P[2].xy/P[2].z, + P[3].xy); + + // Tessellate the first side of the patch into num_segments triangles. + gl_TessLevelOuter[0] = num_segments; + + // Leave the other two sides of the patch as single segments. + gl_TessLevelOuter[1] = 1.0; + gl_TessLevelOuter[2] = 1.0; + + // Changing the inner level to 1 when num_segments == 1 collapses the entire + // patch to a single triangle. Otherwise, we need an inner level of 2 so our curve + // triangles have an interior point to originate from. + gl_TessLevelInner[0] = min(num_segments, 2.0); + + X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x); + Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y); + w[gl_InvocationID /*== 0*/] = P[1].z; + fanpoint[gl_InvocationID /*== 0*/] = vsPt[4]; + })"); + + return code; } - gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0); - })"); + SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override { + SkString code(versionAndExtensionDecls); + code.append(kSkSLTypeDefs); + code.append(kEvalRationalCubicFn); + code.append(R"( + layout(triangles, equal_spacing, ccw) in; + + uniform vec4 sk_RTAdjust; + + in vec4 X[]; + in vec4 Y[]; + in float w[]; + in vec2 fanpoint[]; + + void main() { + // Locate our parametric point of interest. It is equal to the barycentric + // y-coordinate if we are a vertex on the tessellated edge of the triangle patch, + // 0.5 if we are the patch's interior vertex, or N/A if we are the fan point. + // NOTE: We are on the tessellated edge when the barycentric x-coordinate == 0. + float T = (gl_TessCoord.x == 0.0) ? gl_TessCoord.y : 0.5; + + mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1)); + vec2 vertexpos = eval_rational_cubic(P, T); + + if (gl_TessCoord.x == 1.0) { + // We are the anchor point that fans from the center of the curve's contour. + vertexpos = fanpoint[0]; + } else if (gl_TessCoord.x != 0.0) { + // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)]. + vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0; + } + + gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0); + })"); + + return code; + } + }; - return code; + return new WedgeImpl; } constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel; diff --git a/src/gpu/tessellate/GrStencilPathShader.h b/src/gpu/tessellate/GrStencilPathShader.h index d5e7f7c04e..7236dea47b 100644 --- a/src/gpu/tessellate/GrStencilPathShader.h +++ b/src/gpu/tessellate/GrStencilPathShader.h @@ -114,14 +114,7 @@ public: const char* name() const override { return "tessellate_GrCubicTessellateShader"; } private: - SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; + GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override; }; // Uses GPU tessellation shaders to linearize, triangulate, and render cubic "wedge" patches. A @@ -137,14 +130,7 @@ public: const char* name() const override { return "tessellate_GrWedgeTessellateShader"; } private: - SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; + GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override; }; // Uses indirect (instanced) draws to triangulate standalone closed cubics with a "middle-out" diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.cpp b/src/gpu/tessellate/GrStrokeTessellateShader.cpp index 2ee59643a5..16b64ecf93 100644 --- a/src/gpu/tessellate/GrStrokeTessellateShader.cpp +++ b/src/gpu/tessellate/GrStrokeTessellateShader.cpp @@ -86,18 +86,6 @@ static void append_wangs_formula_fn(SkString* code, bool hasConics) { } class GrStrokeTessellateShader::TessellationImpl : public GrGLSLGeometryProcessor { -public: - const char* getTessArgsUniformName(const GrGLSLUniformHandler& uniformHandler) const { - return uniformHandler.getUniformCStr(fTessArgsUniform); - } - const char* getTranslateUniformName(const GrGLSLUniformHandler& uniformHandler) const { - return uniformHandler.getUniformCStr(fTranslateUniform); - } - const char* getAffineMatrixUniformName(const GrGLSLUniformHandler& uniformHandler) const { - return uniformHandler.getUniformCStr(fAffineMatrixUniform); - } - -private: void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const auto& shader = args.fGeomProc.cast<GrStrokeTessellateShader>(); auto* uniHandler = args.fUniformHandler; @@ -414,6 +402,16 @@ private: args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage); } + SkString getTessControlShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override; + SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const override; + + void setData(const GrGLSLProgramDataManager& pdman, const GrShaderCaps&, const GrGeometryProcessor& geomProc) override { @@ -461,13 +459,13 @@ private: GrGLSLUniformHandler::UniformHandle fColorUniform; }; -SkString GrStrokeTessellateShader::getTessControlShaderGLSL( - const GrGLSLGeometryProcessor* glslGeomProc, +SkString GrStrokeTessellateShader::TessellationImpl::getTessControlShaderGLSL( + const GrGeometryProcessor& geomProc, const char* versionAndExtensionDecls, const GrGLSLUniformHandler& uniformHandler, const GrShaderCaps& shaderCaps) const { - SkASSERT(fMode == Mode::kHardwareTessellation); - auto impl = static_cast<const GrStrokeTessellateShader::TessellationImpl*>(glslGeomProc); + const auto& shader = geomProc.cast<GrStrokeTessellateShader>(); + SkASSERT(shader.fMode == Mode::kHardwareTessellation); SkString code(versionAndExtensionDecls); // Run 3 invocations: 1 for each section that the vertex shader chopped the curve into. @@ -483,8 +481,8 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL( code.appendf("#define MAX_TESSELLATION_SEGMENTS %i.0\n", shaderCaps.maxTessellationSegments()); code.appendf("#define cross cross2d\n"); // GLSL already has a function named "cross". - const char* tessArgsName = impl->getTessArgsUniformName(uniformHandler); - if (!this->hasDynamicStroke()) { + const char* tessArgsName = uniformHandler.getUniformCStr(fTessArgsUniform); + if (!shader.hasDynamicStroke()) { code.appendf("uniform vec4 %s;\n", tessArgsName); code.appendf("#define PARAMETRIC_PRECISION %s.x\n", tessArgsName); code.appendf("#define NUM_RADIAL_SEGMENTS_PER_RADIAN %s.y\n", tessArgsName); @@ -495,7 +493,7 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL( } code.append(kLengthPow2Fn); - append_wangs_formula_fn(&code, this->hasConics()); + append_wangs_formula_fn(&code, shader.hasConics()); code.append(kAtan2Fn); code.append(kCosineBetweenVectorsFn); code.append(kMiterExtentFn); @@ -514,11 +512,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL( in vec4 vsPts89[]; in vec4 vsTans01[]; in vec4 vsTans23[];)"); - if (this->hasDynamicStroke()) { + if (shader.hasDynamicStroke()) { code.append(R"( in vec2 vsStrokeArgs[];)"); } - if (this->hasDynamicColor()) { + if (shader.hasDynamicColor()) { code.append(R"( in mediump vec4 vsColor[];)"); } @@ -531,11 +529,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL( // prevJoinTangent.xy] patch out vec4 tcsJoinArgs1; // [joinAngle0, radsPerJoinSegment, joinOutsetClamp.xy] patch out vec4 tcsEndPtEndTan;)"); - if (this->hasDynamicStroke()) { + if (shader.hasDynamicStroke()) { code.append(R"( patch out float tcsStrokeRadius;)"); } - if (this->hasDynamicColor()) { + if (shader.hasDynamicColor()) { code.append(R"( patch out mediump vec4 tcsColor;)"); } @@ -545,11 +543,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL( // Forward join args to the evaluation stage. tcsJoinArgs0 = vsJoinArgs0[0]; tcsJoinArgs1 = vsJoinArgs1[0];)"); - if (this->hasDynamicStroke()) { + if (shader.hasDynamicStroke()) { code.append(R"( tcsStrokeRadius = vsStrokeArgs[0].y;)"); } - if (this->hasDynamicColor()) { + if (shader.hasDynamicColor()) { code.append(R"( tcsColor = vsColor[0];)"); } @@ -821,13 +819,13 @@ static void append_eval_stroke_edge_fn(SkString* code, bool hasConics) { })"); } -SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( - const GrGLSLGeometryProcessor* glslGeomProc, +SkString GrStrokeTessellateShader::TessellationImpl::getTessEvaluationShaderGLSL( + const GrGeometryProcessor& geomProc, const char* versionAndExtensionDecls, const GrGLSLUniformHandler& uniformHandler, const GrShaderCaps& shaderCaps) const { - SkASSERT(fMode == Mode::kHardwareTessellation); - auto impl = static_cast<const GrStrokeTessellateShader::TessellationImpl*>(glslGeomProc); + const auto& shader = geomProc.cast<GrStrokeTessellateShader>(); + SkASSERT(shader.fMode == Mode::kHardwareTessellation); SkString code(versionAndExtensionDecls); code.append("layout(quads, equal_spacing, ccw) in;\n"); @@ -843,22 +841,22 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( code.appendf("#define MAX_PARAMETRIC_SEGMENTS_LOG2 %i\n", SkNextLog2(shaderCaps.maxTessellationSegments())); - if (!this->hasDynamicStroke()) { - const char* tessArgsName = impl->getTessArgsUniformName(uniformHandler); + if (!shader.hasDynamicStroke()) { + const char* tessArgsName = uniformHandler.getUniformCStr(fTessArgsUniform); code.appendf("uniform vec4 %s;\n", tessArgsName); code.appendf("#define STROKE_RADIUS %s.w\n", tessArgsName); } else { code.appendf("#define STROKE_RADIUS tcsStrokeRadius\n"); } - if (!this->viewMatrix().isIdentity()) { - const char* translateName = impl->getTranslateUniformName(uniformHandler); + if (!shader.viewMatrix().isIdentity()) { + const char* translateName = uniformHandler.getUniformCStr(fTranslateUniform); code.appendf("uniform vec2 %s;\n", translateName); code.appendf("#define TRANSLATE %s\n", translateName); - if (!fStroke.isHairlineStyle()) { + if (!shader.fStroke.isHairlineStyle()) { // In the normal case we need the affine matrix too. (In the hairline case we already // applied the affine matrix in the vertex shader.) - const char* affineMatrixName = impl->getAffineMatrixUniformName(uniformHandler); + const char* affineMatrixName = uniformHandler.getUniformCStr(fAffineMatrixUniform); code.appendf("uniform vec4 %s;\n", affineMatrixName); code.appendf("#define AFFINE_MATRIX mat2(%s)\n", affineMatrixName); } @@ -872,11 +870,11 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( // prevJoinTangent.xy] patch in vec4 tcsJoinArgs1; // [joinAngle0, radsPerJoinSegment, joinOutsetClamp.xy] patch in vec4 tcsEndPtEndTan;)"); - if (this->hasDynamicStroke()) { + if (shader.hasDynamicStroke()) { code.append(R"( patch in float tcsStrokeRadius;)"); } - if (this->hasDynamicColor()) { + if (shader.hasDynamicColor()) { code.appendf(R"( patch in mediump vec4 tcsColor; %s out mediump vec4 tesColor;)", shaderCaps.preferFlatInterpolation() ? "flat" : ""); @@ -886,7 +884,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( uniform vec4 sk_RTAdjust;)"); code.append(kUncheckedMixFn); - append_eval_stroke_edge_fn(&code, this->hasConics()); + append_eval_stroke_edge_fn(&code, shader.hasConics()); code.append(R"( void main() { @@ -937,7 +935,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( float w = -1.0; // w<0 means the curve is an integral cubic.)"); - if (this->hasConics()) { + if (shader.hasConics()) { code.append(R"( if (isinf(P[3].y)) { w = P[3].x; // The curve is actually a conic. @@ -971,8 +969,8 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( vec2 vertexPos = position + normalize(vec2(-tangent.y, tangent.x)) * outset;)"); - if (!this->viewMatrix().isIdentity()) { - if (!fStroke.isHairlineStyle()) { + if (!shader.viewMatrix().isIdentity()) { + if (!shader.fStroke.isHairlineStyle()) { // Normal case. Do the transform after tessellation. code.append("vertexPos = AFFINE_MATRIX * vertexPos + TRANSLATE;"); } else { @@ -984,7 +982,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL( code.append(R"( gl_Position = vec4(vertexPos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);)"); - if (this->hasDynamicColor()) { + if (shader.hasDynamicColor()) { code.append(R"( tesColor = tcsColor;)"); } diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.h b/src/gpu/tessellate/GrStrokeTessellateShader.h index 5b7118d3a4..9372a21e40 100644 --- a/src/gpu/tessellate/GrStrokeTessellateShader.h +++ b/src/gpu/tessellate/GrStrokeTessellateShader.h @@ -183,15 +183,6 @@ private: void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override; GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const final; - SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*, - const char* versionAndExtensionDecls, - const GrGLSLUniformHandler&, - const GrShaderCaps&) const override; - const Mode fMode; const ShaderFlags fShaderFlags; const SkStrokeRec fStroke; diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp index 96d55cd065..4e25999745 100644 --- a/src/gpu/text/GrTextBlob.cpp +++ b/src/gpu/text/GrTextBlob.cpp @@ -409,7 +409,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end, } // Update atlas generation if there are no more glyphs to put in the atlas. - if (success && begin + glyphsPlacedInAtlas == fGlyphs.count()) { + if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) { // Need to get the freshest value of the atlas' generation because // updateTextureCoordinates may have changed it. fAtlasGeneration = atlasManager->atlasGeneration(maskFormat); @@ -418,7 +418,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end, return {success, glyphsPlacedInAtlas}; } else { // The atlas hasn't changed, so our texture coordinates are still valid. - if (end == fGlyphs.count()) { + if (end == SkCount(fGlyphs)) { // The atlas hasn't changed and the texture coordinates are all still valid. Update // all the plots used to the new use token. atlasManager->setUseTokenBulk(fBulkUseToken, @@ -584,7 +584,7 @@ size_t DirectMaskSubRun::vertexStride(const SkMatrix&) const { } int DirectMaskSubRun::glyphCount() const { - return fGlyphs.glyphs().count(); + return SkCount(fGlyphs.glyphs()); } namespace { @@ -1059,7 +1059,7 @@ size_t TransformedMaskSubRun::vertexStride(const SkMatrix& drawMatrix) const { } int TransformedMaskSubRun::glyphCount() const { - return fVertexData.count(); + return SkCount(fVertexData); } SkRect TransformedMaskSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const { @@ -1327,7 +1327,7 @@ void SDFTSubRun::fillVertexData( } int SDFTSubRun::glyphCount() const { - return fVertexData.count(); + return SkCount(fVertexData); } SkRect SDFTSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const { @@ -1743,7 +1743,7 @@ size_t DirectMaskSubRunNoCache::vertexStride(const SkMatrix&) const { } int DirectMaskSubRunNoCache::glyphCount() const { - return fGlyphs.glyphs().count(); + return SkCount(fGlyphs.glyphs()); } std::tuple<const GrClip*, GrOp::Owner> @@ -2076,7 +2076,7 @@ size_t TransformedMaskSubRunNoCache::vertexStride(const SkMatrix& drawMatrix) co } int TransformedMaskSubRunNoCache::glyphCount() const { - return fVertexData.count(); + return SkCount(fVertexData); } SkRect TransformedMaskSubRunNoCache::deviceRect( @@ -2269,7 +2269,7 @@ void SDFTSubRunNoCache::fillVertexData( } int SDFTSubRunNoCache::glyphCount() const { - return fVertexData.count(); + return SkCount(fVertexData); } SkRect SDFTSubRunNoCache::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const { diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index b0db7efba6..cea30b033b 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -2037,7 +2037,7 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates( // only time we have multiple proxies is if we are flushing a yuv SkImage which won't have // state updates anyways. Additionally if we have a newState than we must not have any // BackendSurfaceAccess. - SkASSERT(!newState || proxies.count() == 1); + SkASSERT(!newState || proxies.size() == 1); SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess); GrVkImage* image; for (GrSurfaceProxy* proxy : proxies) { diff --git a/src/ports/SkFontHost_FreeType_common.cpp b/src/ports/SkFontHost_FreeType_common.cpp index 805eafaec7..120a29eb0e 100644 --- a/src/ports/SkFontHost_FreeType_common.cpp +++ b/src/ports/SkFontHost_FreeType_common.cpp @@ -491,6 +491,28 @@ inline SkPoint SkVectorProjection(SkPoint a, SkPoint b) { void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette, FT_COLR_Paint colrv1_paint, SkPaint* paint) { + auto fetch_color_stops = [&face, &palette](FT_ColorStopIterator& color_stop_iterator, + std::vector<SkScalar>& stops, + std::vector<SkColor>& colors) { + const FT_UInt num_color_stops = color_stop_iterator.num_color_stops; + stops.resize(num_color_stops); + colors.resize(num_color_stops); + + FT_ColorStop color_stop; + while (FT_Get_Colorline_Stops(face, &color_stop, &color_stop_iterator)) { + FT_UInt index = color_stop_iterator.current_color_stop - 1; + stops[index] = color_stop.stop_offset / float(1 << 14); + FT_UInt16& palette_index = color_stop.color.palette_index; + // TODO(drott): Ensure palette_index is sanitized on the FreeType + // side and 0xFFFF foreground color will be handled correctly here. + colors[index] = SkColorSetARGB( + palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha), + palette[palette_index].red, + palette[palette_index].green, + palette[palette_index].blue); + } + }; + switch (colrv1_paint.format) { case FT_COLR_PAINTFORMAT_SOLID: { SkColor color = @@ -529,31 +551,12 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette, perpendicular_to_p2_p0 = SkPoint::Make(perpendicular_to_p2_p0.y(), -perpendicular_to_p2_p0.x()); line_positions[1] = p0 + SkVectorProjection((p1 - p0), perpendicular_to_p2_p0); - /* populate points */ - const FT_UInt num_color_stops = - colrv1_paint.u.linear_gradient.colorline.color_stop_iterator.num_color_stops; std::vector<SkScalar> stops; std::vector<SkColor> colors; - stops.resize(num_color_stops); - colors.resize(num_color_stops); - - FT_ColorStop color_stop; - while (FT_Get_Colorline_Stops( - face, &color_stop, - &colrv1_paint.u.linear_gradient.colorline.color_stop_iterator)) { - FT_UInt index = colrv1_paint.u.linear_gradient.colorline.color_stop_iterator - .current_color_stop - - 1; - stops[index] = color_stop.stop_offset / float(1 << 14); - FT_UInt16& palette_index = color_stop.color.palette_index; - colors[index] = SkColorSetARGB( - palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha), - palette[palette_index].red, palette[palette_index].green, - palette[palette_index].blue); - } + fetch_color_stops(colrv1_paint.u.linear_gradient.colorline.color_stop_iterator, stops, colors); sk_sp<SkShader> shader(SkGradientShader::MakeLinear( - line_positions, colors.data(), stops.data(), num_color_stops, + line_positions, colors.data(), stops.data(), stops.size(), ToSkTileMode(colrv1_paint.u.linear_gradient.colorline.extend))); SkASSERT(shader); // An opaque color is needed to ensure the gradient's not modulated by alpha. @@ -572,33 +575,16 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette, -colrv1_paint.u.radial_gradient.c1.y); SkScalar end_radius = colrv1_paint.u.radial_gradient.r1; - const FT_UInt num_color_stops = - colrv1_paint.u.radial_gradient.colorline.color_stop_iterator.num_color_stops; + std::vector<SkScalar> stops; std::vector<SkColor> colors; - stops.resize(num_color_stops); - colors.resize(num_color_stops); - - FT_ColorStop color_stop; - while (FT_Get_Colorline_Stops( - face, &color_stop, - &colrv1_paint.u.radial_gradient.colorline.color_stop_iterator)) { - FT_UInt index = colrv1_paint.u.radial_gradient.colorline.color_stop_iterator - .current_color_stop - - 1; - stops[index] = color_stop.stop_offset / float(1 << 14); - FT_UInt16& palette_index = color_stop.color.palette_index; - colors[index] = SkColorSetARGB( - palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha), - palette[palette_index].red, palette[palette_index].green, - palette[palette_index].blue); - } + fetch_color_stops(colrv1_paint.u.radial_gradient.colorline.color_stop_iterator, stops, colors); // An opaque color is needed to ensure the gradient's not modulated by alpha. paint->setColor(SK_ColorBLACK); paint->setShader(SkGradientShader::MakeTwoPointConical( - start, radius, end, end_radius, colors.data(), stops.data(), num_color_stops, + start, radius, end, end_radius, colors.data(), stops.data(), stops.size(), ToSkTileMode(colrv1_paint.u.radial_gradient.colorline.extend))); break; } @@ -608,27 +594,9 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette, SkScalar startAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.start_angle); SkScalar endAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.end_angle); - const FT_UInt num_color_stops = - colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator.num_color_stops; std::vector<SkScalar> stops; std::vector<SkColor> colors; - stops.resize(num_color_stops); - colors.resize(num_color_stops); - - FT_ColorStop color_stop; - while (FT_Get_Colorline_Stops( - face, &color_stop, - &colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator)) { - FT_UInt index = colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator - .current_color_stop - - 1; - stops[index] = color_stop.stop_offset / float(1 << 14); - FT_UInt16& palette_index = color_stop.color.palette_index; - colors[index] = SkColorSetARGB( - palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha), - palette[palette_index].red, palette[palette_index].green, - palette[palette_index].blue); - } + fetch_color_stops(colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator, stops, colors); // An opaque color is needed to ensure the gradient's not modulated by alpha. paint->setColor(SK_ColorBLACK); @@ -655,7 +623,7 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette, angle_adjust.postScale(-1, 1, center.x(), center.y()); paint->setShader(SkGradientShader::MakeSweep( - center.x(), center.y(), colors.data(), stops.data(), num_color_stops, + center.x(), center.y(), colors.data(), stops.data(), stops.size(), SkTileMode::kDecal, startAngle, endAngle, 0, &angle_adjust)); break; } diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 6f2d6fb352..78758238a7 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -41,7 +41,6 @@ namespace dsl { } class ExternalFunction; -class ExternalValue; class FunctionCall; class StructDefinition; struct ParsedModule; diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index ca4a0d7ef9..0df361928d 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -95,7 +95,6 @@ void Parser::InitLayoutMap() { TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index"); TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left"); TOKEN(OVERRIDE_COVERAGE, "override_coverage"); - TOKEN(EARLY_FRAGMENT_TESTS, "early_fragment_tests"); TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations"); TOKEN(PUSH_CONSTANT, "push_constant"); TOKEN(POINTS, "points"); @@ -920,9 +919,6 @@ Layout Parser::layout() { case LayoutToken::OVERRIDE_COVERAGE: setFlag(Layout::kOverrideCoverage_Flag); break; - case LayoutToken::EARLY_FRAGMENT_TESTS: - setFlag(Layout::kEarlyFragmentTests_Flag); - break; case LayoutToken::PUSH_CONSTANT: setFlag(Layout::kPushConstant_Flag); break; diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index 6131940dbb..701e4a7220 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -38,7 +38,6 @@ public: INPUT_ATTACHMENT_INDEX, ORIGIN_UPPER_LEFT, OVERRIDE_COVERAGE, - EARLY_FRAGMENT_TESTS, BLEND_SUPPORT_ALL_EQUATIONS, PUSH_CONSTANT, POINTS, diff --git a/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp b/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp index e545e622c0..f1646d09be 100644 --- a/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp @@ -32,6 +32,8 @@ static const char* get_scalar_type_name(const Context& context, const Type& type return "Float"; } else if (type.isSigned()) { return "Int"; + } else if (type.isUnsigned()) { + return "UInt"; } else if (type.isBoolean()) { return "Bool"; } diff --git a/src/sksl/dsl/DSLCore.cpp b/src/sksl/dsl/DSLCore.cpp index d5e162d914..cfaaecf013 100644 --- a/src/sksl/dsl/DSLCore.cpp +++ b/src/sksl/dsl/DSLCore.cpp @@ -204,6 +204,18 @@ DSLStatement Continue() { return DSLCore::Continue(); } +// Logically, we'd want the variable's initial value to appear on here in Declare, since that +// matches how we actually write code (and in fact that was what our first attempt looked like). +// Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear +// as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out +// of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the +// variable's initial value is unknown at the point of reference. There are probably some other +// issues with this as well, but it is particularly dangerous when x is const, since SkSL will +// expect its value to be known when it is referenced and will end up asserting, dereferencing a +// null pointer, or possibly doing something else awful. +// +// So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is +// always executed in the correct order. DSLStatement Declare(DSLVar& var, PositionInfo pos) { return DSLCore::Declare(var, pos); } diff --git a/src/sksl/generated/sksl_fp.dehydrated.sksl b/src/sksl/generated/sksl_fp.dehydrated.sksl index 1467aeac6b..e032778633 100644 --- a/src/sksl/generated/sksl_fp.dehydrated.sksl +++ b/src/sksl/generated/sksl_fp.dehydrated.sksl @@ -27,25 +27,25 @@ static uint8_t SKSL_INCLUDE_sksl_fp[] = {255,0, 22,2,0,17,0, 53,3,0, 37, -36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,30,0,0,2,31,0, +36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,30,0,0,2,31,0, 50,4,0,44,0,0, 0,5,0, 47,4,0,1, 53,6,0, 37, -36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,51,0, +36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,51,0, 47,5,0,0, 53,7,0, 37, -36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,67,0, +36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,67,0, 50,8,0,84,0,0, 53,9,0, 37, -36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,90,0, +36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,90,0, 47,8,0,0, 53,10,0, 37, -36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,110,0, +36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,110,0, 47,8,0,0, 53,11,0, 16,135,0, diff --git a/src/sksl/generated/sksl_frag.dehydrated.sksl b/src/sksl/generated/sksl_frag.dehydrated.sksl index 12bd60b1f9..5477418509 100644 --- a/src/sksl/generated/sksl_frag.dehydrated.sksl +++ b/src/sksl/generated/sksl_frag.dehydrated.sksl @@ -11,23 +11,23 @@ static uint8_t SKSL_INCLUDE_sksl_frag[] = {100,0, 49,5,0, 53,1,0, 37, -36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,2,3,0, +36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,2,3,0, 50,2,0,16,0,0, 53,3,0, 37, -36,0,32,0,0,255,255,255,255,255,17,0,255,255,255,255,2,0,0,2,23,0, +36,0,16,0,0,255,255,255,255,255,17,0,255,255,255,255,2,0,0,2,23,0, 50,4,0,36,0,0, 53,5,0, 37, -36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,2,0,0,4,41,0, +36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,2,0,0,4,41,0, 50,6,0,66,0,0, 53,7,0, 37, -36,0,41,0,0,0,255,255,0,255,17,39,255,255,255,255,2,0,0,4,72,0, +36,128,20,0,0,0,255,255,0,255,17,39,255,255,255,255,2,0,0,4,72,0, 47,6,0,0, 53,8,0, 37, -36,0,32,0,0,255,255,255,255,255,24,39,255,255,255,255,2,0,0,0,85,0, +36,0,16,0,0,255,255,255,255,255,24,39,255,255,255,255,2,0,0,0,85,0, 47,6,0,0,5,0, 2,0, 1,0, diff --git a/src/sksl/generated/sksl_geom.dehydrated.sksl b/src/sksl/generated/sksl_geom.dehydrated.sksl index 100fbc2da6..91b9f04613 100644 --- a/src/sksl/generated/sksl_geom.dehydrated.sksl +++ b/src/sksl/generated/sksl_geom.dehydrated.sksl @@ -16,26 +16,26 @@ static uint8_t SKSL_INCLUDE_sksl_geom[] = {134,0, 49,12,0, 44,1,0,2,0,2, 37, -36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, +36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, 50,2,0,28,0, 37, -36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, +36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, 50,3,0,48,0, 53,4,0, 37, -36,0,32,0,0,255,255,255,255,255,18,39,255,255,255,255,15,0,0,2,54,0, +36,0,16,0,0,255,255,255,255,255,18,39,255,255,255,255,15,0,0,2,54,0, 0,5,0, 47,1,0,255,0, 44,6,0,2,0,2, 37, -36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, +36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, 47,2,0, 37, -36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, +36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, 47,3,0, 53,7,0, 37, -36,0,32,0,0,255,255,255,255,255,23,39,255,255,255,255,15,0,0,4,2,0, +36,0,16,0,0,255,255,255,255,255,23,39,255,255,255,255,15,0,0,4,2,0, 47,6,0,0, 24,7,0,0, 24,7,0,1, diff --git a/src/sksl/generated/sksl_rt_shader.dehydrated.sksl b/src/sksl/generated/sksl_rt_shader.dehydrated.sksl index f0e0516dd5..d9392d90ff 100644 --- a/src/sksl/generated/sksl_rt_shader.dehydrated.sksl +++ b/src/sksl/generated/sksl_rt_shader.dehydrated.sksl @@ -14,7 +14,7 @@ static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {77,0, 49,8,0, 53,1,0, 37, -36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,0,3,0, +36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,0,3,0, 50,2,0,16,0,0, 53,3,0, 16,23,0, diff --git a/src/sksl/generated/sksl_vert.dehydrated.sksl b/src/sksl/generated/sksl_vert.dehydrated.sksl index 4d1d64caaf..4f950edc8b 100644 --- a/src/sksl/generated/sksl_vert.dehydrated.sksl +++ b/src/sksl/generated/sksl_vert.dehydrated.sksl @@ -11,10 +11,10 @@ static uint8_t SKSL_INCLUDE_sksl_vert[] = {82,0, 49,6,0, 44,1,0,2,0,2, 37, -36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, +36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0, 50,2,0,28,0, 37, -36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, +36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0, 50,3,0,48,0, 53,4,0, 37, @@ -24,11 +24,11 @@ static uint8_t SKSL_INCLUDE_sksl_vert[] = {82,0, 24,4,0,1, 53,5,0, 37, -36,0,32,0,0,255,255,255,255,255,42,0,255,255,255,255,15,0,0,2,54,0, +36,0,16,0,0,255,255,255,255,255,42,0,255,255,255,255,15,0,0,2,54,0, 50,6,0,66,0,0, 53,7,0, 37, -36,0,32,0,0,255,255,255,255,255,43,0,255,255,255,255,15,0,0,2,70,0, +36,0,16,0,0,255,255,255,255,255,43,0,255,255,255,255,15,0,0,2,70,0, 47,6,0,0,4,0, 5,0, 3,0, diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp index 1f6e774fae..63384ad735 100644 --- a/src/sksl/ir/SkSLFunctionCall.cpp +++ b/src/sksl/ir/SkSLFunctionCall.cpp @@ -81,44 +81,89 @@ static std::unique_ptr<Expression> optimize_comparison(const Context& context, SkASSERT(arguments.size() == 2); const Expression* left = ConstantFolder::GetConstantValueForVariable(*arguments[0]); const Expression* right = ConstantFolder::GetConstantValueForVariable(*arguments[1]); + const Type& type = left->type().componentType(); - if (left->type().componentType().isFloat()) { + if (type.isFloat()) { return optimize_comparison_of_type<FloatLiteral>(context, *left, *right, compare); } - if (left->type().componentType().isInteger()) { + if (type.isInteger()) { return optimize_comparison_of_type<IntLiteral>(context, *left, *right, compare); } - SkDEBUGFAILF("unsupported type %s", left->type().description().c_str()); + SkDEBUGFAILF("unsupported type %s", type.description().c_str()); return nullptr; } -using Float1Fn = float (*)(float); -static std::unique_ptr<Expression> evaluate_intrinsic_float1(const Context& context, - const ExpressionArray& arguments, - const Float1Fn& evaluate) { - SkASSERT(arguments.size() == 1); - const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front()); +template <typename LITERAL, typename FN> +static std::unique_ptr<Expression> evaluate_intrinsic_1_of_type(const Context& context, + const Expression* arg, + const FN& evaluate) { const Type& vecType = arg->type(); const Type& type = vecType.componentType(); + SkASSERT(type.isScalar()); - if (type.isFloat()) { - ExpressionArray result; - result.reserve_back(vecType.columns()); - - for (int index = 0; index < vecType.columns(); ++index) { - const Expression* subexpr = arg->getConstantSubexpression(index); - SkASSERT(subexpr); - float value = evaluate(subexpr->as<FloatLiteral>().value()); - result.push_back(FloatLiteral::Make(subexpr->fOffset, value, &type)); - } + ExpressionArray result; + result.reserve_back(vecType.columns()); - return ConstructorCompound::Make(context, arg->fOffset, vecType, std::move(result)); + for (int index = 0; index < vecType.columns(); ++index) { + const Expression* subexpr = arg->getConstantSubexpression(index); + SkASSERT(subexpr); + auto value = evaluate(subexpr->as<LITERAL>().value()); + result.push_back(LITERAL::Make(subexpr->fOffset, value, &type)); } + return ConstructorCompound::Make(context, arg->fOffset, vecType, std::move(result)); +} + +template <typename FN, + bool kSupportsFloat = true, + bool kSupportsInt = true, + bool kSupportsBool = false> +static std::unique_ptr<Expression> evaluate_intrinsic_generic1(const Context& context, + const ExpressionArray& arguments, + const FN& evaluate) { + SkASSERT(arguments.size() == 1); + const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front()); + const Type& type = arg->type().componentType(); + + if constexpr (kSupportsFloat) { + if (type.isFloat()) { + return evaluate_intrinsic_1_of_type<FloatLiteral>(context, arg, evaluate); + } + } + if constexpr (kSupportsInt) { + if (type.isInteger()) { + return evaluate_intrinsic_1_of_type<IntLiteral>(context, arg, evaluate); + } + } + if constexpr (kSupportsBool) { + if (type.isBoolean()) { + return evaluate_intrinsic_1_of_type<BoolLiteral>(context, arg, evaluate); + } + } SkDEBUGFAILF("unsupported type %s", type.description().c_str()); return nullptr; } +template <typename FN> +static std::unique_ptr<Expression> evaluate_intrinsic_float1(const Context& context, + const ExpressionArray& arguments, + const FN& evaluate) { + return evaluate_intrinsic_generic1<FN, + /*kSupportsFloat=*/true, + /*kSupportsInt=*/false, + /*kSupportsBool=*/false>(context, arguments, evaluate); +} + +template <typename FN> +static std::unique_ptr<Expression> evaluate_intrinsic_bool1(const Context& context, + const ExpressionArray& arguments, + const FN& evaluate) { + return evaluate_intrinsic_generic1<FN, + /*kSupportsFloat=*/false, + /*kSupportsInt=*/false, + /*kSupportsBool=*/true>(context, arguments, evaluate); +} + static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& context, IntrinsicKind intrinsic, const ExpressionArray& arguments) { @@ -129,6 +174,9 @@ static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& contex case k_any_IntrinsicKind: return coalesce_bool_vector(arguments, /*startingState=*/false, [](bool a, bool b) { return a || b; }); + case k_not_IntrinsicKind: + return evaluate_intrinsic_bool1(context, arguments, [](bool a) { return !a; }); + case k_greaterThan_IntrinsicKind: return optimize_comparison(context, arguments, [](auto a, auto b) { return a > b; }); @@ -147,6 +195,12 @@ static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& contex case k_notEqual_IntrinsicKind: return optimize_comparison(context, arguments, [](auto a, auto b) { return a != b; }); + case k_abs_IntrinsicKind: + return evaluate_intrinsic_generic1(context, arguments, [](auto a) { return abs(a); }); + + case k_sign_IntrinsicKind: + return evaluate_intrinsic_generic1(context, arguments, + [](auto a) { return (a > 0) - (a < 0); }); case k_sin_IntrinsicKind: return evaluate_intrinsic_float1(context, arguments, [](float a) { return sin(a); }); diff --git a/tests/AnimatedImageTest.cpp b/tests/AnimatedImageTest.cpp index 180573adde..91c6606f18 100644 --- a/tests/AnimatedImageTest.cpp +++ b/tests/AnimatedImageTest.cpp @@ -48,6 +48,41 @@ DEF_TEST(AnimatedImage_simple, r) { REPORTER_ASSERT(r, animatedImage); } +DEF_TEST(AnimatedImage_rotation, r) { + if (GetResourcePath().isEmpty()) { + return; + } + + // These images use different exif orientations to achieve the same final + // dimensions + const auto expectedBounds = SkRect::MakeIWH(100, 80); + for (int i = 1; i <=8; i++) { + for (const SkString& name : { SkStringPrintf("images/orientation/%d.webp", i), + SkStringPrintf("images/orientation/%d_444.jpg", i) }) { + + const char* file = name.c_str(); + auto data = GetResourceAsData(file); + if (!data) { + ERRORF(r, "Could not get %s", file); + return; + } + + auto androidCodec = SkAndroidCodec::MakeFromData(std::move(data)); + auto animatedImage = SkAnimatedImage::Make(std::move(androidCodec)); + if (!animatedImage) { + ERRORF(r, "Failed to create animated image from %s", file); + return; + } + + auto bounds = animatedImage->getBounds(); + if (bounds != expectedBounds) { + ERRORF(r, "Mismatched bounds for %", file); + bounds.dump(); + } + } + } +} + DEF_TEST(AnimatedImage_invalidCrop, r) { if (GetResourcePath().isEmpty()) { return; diff --git a/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp b/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp index 0b7c5f3dd1..ad94d7e846 100644 --- a/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp +++ b/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp @@ -31,10 +31,13 @@ Var _color(kNo_Modifier, DSLType(kHalf4_Type), "color", _colorWhite); Var _a(kNo_Modifier, DSLType(kHalf_Type), "a", 0.0f); Var _r(kNo_Modifier, DSLType(kHalf_Type), "r", -5.0f); Var _b(kNo_Modifier, DSLType(kHalf_Type), "b", 5.0f); +Var _x(kNo_Modifier, DSLType(kUInt_Type), "x", 0u); +Var _y(kNo_Modifier, DSLType(kUInt_Type), "y", 1u); Declare(_color); For(Declare(_a), _a <= 1.0f, ++_a, /*Body:*/ _color.w() = _a); For(Declare(_r), _r < 5.0f, _r += 1.0f, /*Body:*/ Block(_color.x() = _r, If(_color.x() == 0.0f, /*Then:*/ Break()))); For(Declare(_b), _b >= 0.0f, _b -= 1.0f, /*Body:*/ Block(_color.z() = _b, If(_color.w() == 1.0f, /*Then:*/ Continue()), _color.y() = 0.0f)); +Block(Declare(_x), Declare(_y), For(Statement(), _x <= _y, ++_x, /*Body:*/ Block(_color.w() = Half(_x)))); Return(_color); EndFragmentProcessor(); } diff --git a/tests/sksl/errors/LayoutRepeatedQualifiers.glsl b/tests/sksl/errors/LayoutRepeatedQualifiers.glsl index 917d9219e5..5ceeaed0d9 100644 --- a/tests/sksl/errors/LayoutRepeatedQualifiers.glsl +++ b/tests/sksl/errors/LayoutRepeatedQualifiers.glsl @@ -1,22 +1,21 @@ ### Compilation failed: -error: 22: layout qualifier 'origin_upper_left' appears more than once -error: 23: layout qualifier 'override_coverage' appears more than once -error: 24: layout qualifier 'early_fragment_tests' appears more than once -error: 25: layout qualifier 'push_constant' appears more than once -error: 26: layout qualifier 'blend_support_all_equations' appears more than once -error: 27: layout qualifier 'tracked' appears more than once -error: 28: layout qualifier 'srgb_unpremul' appears more than once -error: 29: layout qualifier 'key' appears more than once -error: 30: layout qualifier 'location' appears more than once -error: 31: layout qualifier 'offset' appears more than once -error: 32: layout qualifier 'binding' appears more than once -error: 33: layout qualifier 'index' appears more than once -error: 34: layout qualifier 'set' appears more than once -error: 35: layout qualifier 'builtin' appears more than once -error: 36: layout qualifier 'input_attachment_index' appears more than once -error: 37: layout qualifier 'max_vertices' appears more than once -error: 38: layout qualifier 'invocations' appears more than once -error: 39: layout qualifier 'when' appears more than once -error: 40: layout qualifier 'ctype' appears more than once -19 errors +error: 21: layout qualifier 'origin_upper_left' appears more than once +error: 22: layout qualifier 'override_coverage' appears more than once +error: 23: layout qualifier 'push_constant' appears more than once +error: 24: layout qualifier 'blend_support_all_equations' appears more than once +error: 25: layout qualifier 'tracked' appears more than once +error: 26: layout qualifier 'srgb_unpremul' appears more than once +error: 27: layout qualifier 'key' appears more than once +error: 28: layout qualifier 'location' appears more than once +error: 29: layout qualifier 'offset' appears more than once +error: 30: layout qualifier 'binding' appears more than once +error: 31: layout qualifier 'index' appears more than once +error: 32: layout qualifier 'set' appears more than once +error: 33: layout qualifier 'builtin' appears more than once +error: 34: layout qualifier 'input_attachment_index' appears more than once +error: 35: layout qualifier 'max_vertices' appears more than once +error: 36: layout qualifier 'invocations' appears more than once +error: 37: layout qualifier 'when' appears more than once +error: 38: layout qualifier 'ctype' appears more than once +18 errors diff --git a/tests/sksl/folding/BoolFolding.glsl b/tests/sksl/folding/BoolFolding.glsl index a598aecea2..6aea1a5053 100644 --- a/tests/sksl/folding/BoolFolding.glsl +++ b/tests/sksl/folding/BoolFolding.glsl @@ -17,5 +17,7 @@ vec4 main() { bool _13_l = false; bool _14_m = true; bool _15_n = false; - return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n ? colorGreen : colorRed; + bool _16_o = true; + bool _17_p = false; + return ((((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n) && _16_o) && !_17_p ? colorGreen : colorRed; } diff --git a/tests/sksl/inliner/StaticSwitch.glsl b/tests/sksl/inliner/StaticSwitch.glsl index 89ac653966..8f8b42e91a 100644 --- a/tests/sksl/inliner/StaticSwitch.glsl +++ b/tests/sksl/inliner/StaticSwitch.glsl @@ -4,9 +4,9 @@ uniform vec4 colorGreen; uniform vec4 colorRed; float get_f() { { - return abs(2.0); + return 2.0; } - return abs(5.0); + return 5.0; } vec4 main() { float result = get_f(); diff --git a/tests/sksl/intrinsics/AbsFloat.asm.frag b/tests/sksl/intrinsics/AbsFloat.asm.frag index baf68482e5..98df218500 100644 --- a/tests/sksl/intrinsics/AbsFloat.asm.frag +++ b/tests/sksl/intrinsics/AbsFloat.asm.frag @@ -45,9 +45,18 @@ OpDecorate %63 RelaxedPrecision OpDecorate %70 RelaxedPrecision OpDecorate %72 RelaxedPrecision OpDecorate %73 RelaxedPrecision -OpDecorate %84 RelaxedPrecision +OpDecorate %80 RelaxedPrecision +OpDecorate %81 RelaxedPrecision +OpDecorate %86 RelaxedPrecision OpDecorate %87 RelaxedPrecision OpDecorate %88 RelaxedPrecision +OpDecorate %94 RelaxedPrecision +OpDecorate %95 RelaxedPrecision +OpDecorate %96 RelaxedPrecision +OpDecorate %102 RelaxedPrecision +OpDecorate %112 RelaxedPrecision +OpDecorate %115 RelaxedPrecision +OpDecorate %116 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -78,6 +87,8 @@ OpDecorate %88 RelaxedPrecision %v3float = OpTypeVector %float 3 %v3bool = OpTypeVector %bool 3 %v4bool = OpTypeVector %bool 4 +%86 = OpConstantComposite %v2float %float_1_25 %float_0 +%94 = OpConstantComposite %v3float %float_1_25 %float_0 %float_0_75 %int_1 = OpConstant %int 1 %int_2 = OpConstant %int 2 %_entrypoint_v = OpFunction %void None %15 @@ -92,7 +103,7 @@ OpFunctionEnd %24 = OpFunctionParameter %_ptr_Function_v2float %25 = OpLabel %expected = OpVariable %_ptr_Function_v4float Function -%78 = OpVariable %_ptr_Function_v4float Function +%106 = OpVariable %_ptr_Function_v4float Function OpStore %expected %31 %34 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 %38 = OpLoad %v4float %34 @@ -141,19 +152,57 @@ OpBranchConditional %67 %68 %69 OpBranch %69 %69 = OpLabel %77 = OpPhi %bool %false %56 %76 %68 -OpSelectionMerge %81 None -OpBranchConditional %77 %79 %80 +OpSelectionMerge %79 None +OpBranchConditional %77 %78 %79 +%78 = OpLabel +%80 = OpLoad %v4float %expected +%81 = OpCompositeExtract %float %80 0 +%82 = OpFOrdEqual %bool %float_1_25 %81 +OpBranch %79 %79 = OpLabel -%82 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 -%84 = OpLoad %v4float %82 -OpStore %78 %84 -OpBranch %81 -%80 = OpLabel -%85 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 -%87 = OpLoad %v4float %85 -OpStore %78 %87 -OpBranch %81 -%81 = OpLabel -%88 = OpLoad %v4float %78 -OpReturnValue %88 +%83 = OpPhi %bool %false %69 %82 %78 +OpSelectionMerge %85 None +OpBranchConditional %83 %84 %85 +%84 = OpLabel +%87 = OpLoad %v4float %expected +%88 = OpVectorShuffle %v2float %87 %87 0 1 +%89 = OpFOrdEqual %v2bool %86 %88 +%90 = OpAll %bool %89 +OpBranch %85 +%85 = OpLabel +%91 = OpPhi %bool %false %79 %90 %84 +OpSelectionMerge %93 None +OpBranchConditional %91 %92 %93 +%92 = OpLabel +%95 = OpLoad %v4float %expected +%96 = OpVectorShuffle %v3float %95 %95 0 1 2 +%97 = OpFOrdEqual %v3bool %94 %96 +%98 = OpAll %bool %97 +OpBranch %93 +%93 = OpLabel +%99 = OpPhi %bool %false %85 %98 %92 +OpSelectionMerge %101 None +OpBranchConditional %99 %100 %101 +%100 = OpLabel +%102 = OpLoad %v4float %expected +%103 = OpFOrdEqual %v4bool %31 %102 +%104 = OpAll %bool %103 +OpBranch %101 +%101 = OpLabel +%105 = OpPhi %bool %false %93 %104 %100 +OpSelectionMerge %109 None +OpBranchConditional %105 %107 %108 +%107 = OpLabel +%110 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%112 = OpLoad %v4float %110 +OpStore %106 %112 +OpBranch %109 +%108 = OpLabel +%113 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%115 = OpLoad %v4float %113 +OpStore %106 %115 +OpBranch %109 +%109 = OpLabel +%116 = OpLoad %v4float %106 +OpReturnValue %116 OpFunctionEnd diff --git a/tests/sksl/intrinsics/AbsFloat.glsl b/tests/sksl/intrinsics/AbsFloat.glsl index d8ebb3fa2d..46a3d6b11c 100644 --- a/tests/sksl/intrinsics/AbsFloat.glsl +++ b/tests/sksl/intrinsics/AbsFloat.glsl @@ -5,5 +5,5 @@ uniform vec4 colorGreen; uniform vec4 colorRed; vec4 main() { vec4 expected = vec4(1.25, 0.0, 0.75, 2.25); - return ((abs(testInputs.x) == expected.x && abs(testInputs.xy) == expected.xy) && abs(testInputs.xyz) == expected.xyz) && abs(testInputs) == expected ? colorGreen : colorRed; + return ((((((abs(testInputs.x) == expected.x && abs(testInputs.xy) == expected.xy) && abs(testInputs.xyz) == expected.xyz) && abs(testInputs) == expected) && 1.25 == expected.x) && vec2(1.25, 0.0) == expected.xy) && vec3(1.25, 0.0, 0.75) == expected.xyz) && vec4(1.25, 0.0, 0.75, 2.25) == expected ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/AbsFloat.metal b/tests/sksl/intrinsics/AbsFloat.metal index 4b829a97ac..93020cac8c 100644 --- a/tests/sksl/intrinsics/AbsFloat.metal +++ b/tests/sksl/intrinsics/AbsFloat.metal @@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo Outputs _out; (void)_out; float4 expected = float4(1.25, 0.0, 0.75, 2.25); - _out.sk_FragColor = ((abs(_uniforms.testInputs.x) == expected.x && all(abs(_uniforms.testInputs.xy) == expected.xy)) && all(abs(_uniforms.testInputs.xyz) == expected.xyz)) && all(abs(_uniforms.testInputs) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; + _out.sk_FragColor = ((((((abs(_uniforms.testInputs.x) == expected.x && all(abs(_uniforms.testInputs.xy) == expected.xy)) && all(abs(_uniforms.testInputs.xyz) == expected.xyz)) && all(abs(_uniforms.testInputs) == expected)) && 1.25 == expected.x) && all(float2(1.25, 0.0) == expected.xy)) && all(float3(1.25, 0.0, 0.75) == expected.xyz)) && all(float4(1.25, 0.0, 0.75, 2.25) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/AbsInt.asm.frag b/tests/sksl/intrinsics/AbsInt.asm.frag index d31bc058b8..7db6b5d3ce 100644 --- a/tests/sksl/intrinsics/AbsInt.asm.frag +++ b/tests/sksl/intrinsics/AbsInt.asm.frag @@ -41,9 +41,9 @@ OpDecorate %88 RelaxedPrecision OpDecorate %90 RelaxedPrecision OpDecorate %92 RelaxedPrecision OpDecorate %94 RelaxedPrecision -OpDecorate %108 RelaxedPrecision -OpDecorate %110 RelaxedPrecision -OpDecorate %111 RelaxedPrecision +OpDecorate %136 RelaxedPrecision +OpDecorate %138 RelaxedPrecision +OpDecorate %139 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -76,6 +76,8 @@ OpDecorate %111 RelaxedPrecision %v3int = OpTypeVector %int 3 %v3bool = OpTypeVector %bool 3 %v4bool = OpTypeVector %bool 4 +%110 = OpConstantComposite %v2int %int_1 %int_0 +%118 = OpConstantComposite %v3int %int_1 %int_0 %int_0 %_ptr_Function_v4float = OpTypePointer Function %v4float %_entrypoint_v = OpFunction %void None %15 %16 = OpLabel @@ -89,7 +91,7 @@ OpFunctionEnd %24 = OpFunctionParameter %_ptr_Function_v2float %25 = OpLabel %expected = OpVariable %_ptr_Function_v4int Function -%102 = OpVariable %_ptr_Function_v4float Function +%130 = OpVariable %_ptr_Function_v4float Function OpStore %expected %33 %36 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 %38 = OpLoad %v4float %36 @@ -160,19 +162,57 @@ OpBranchConditional %82 %83 %84 OpBranch %84 %84 = OpLabel %101 = OpPhi %bool %false %63 %100 %83 -OpSelectionMerge %106 None -OpBranchConditional %101 %104 %105 -%104 = OpLabel -%107 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 -%108 = OpLoad %v4float %107 -OpStore %102 %108 -OpBranch %106 -%105 = OpLabel -%109 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 -%110 = OpLoad %v4float %109 -OpStore %102 %110 -OpBranch %106 -%106 = OpLabel -%111 = OpLoad %v4float %102 -OpReturnValue %111 +OpSelectionMerge %103 None +OpBranchConditional %101 %102 %103 +%102 = OpLabel +%104 = OpLoad %v4int %expected +%105 = OpCompositeExtract %int %104 0 +%106 = OpIEqual %bool %int_1 %105 +OpBranch %103 +%103 = OpLabel +%107 = OpPhi %bool %false %84 %106 %102 +OpSelectionMerge %109 None +OpBranchConditional %107 %108 %109 +%108 = OpLabel +%111 = OpLoad %v4int %expected +%112 = OpVectorShuffle %v2int %111 %111 0 1 +%113 = OpIEqual %v2bool %110 %112 +%114 = OpAll %bool %113 +OpBranch %109 +%109 = OpLabel +%115 = OpPhi %bool %false %103 %114 %108 +OpSelectionMerge %117 None +OpBranchConditional %115 %116 %117 +%116 = OpLabel +%119 = OpLoad %v4int %expected +%120 = OpVectorShuffle %v3int %119 %119 0 1 2 +%121 = OpIEqual %v3bool %118 %120 +%122 = OpAll %bool %121 +OpBranch %117 +%117 = OpLabel +%123 = OpPhi %bool %false %109 %122 %116 +OpSelectionMerge %125 None +OpBranchConditional %123 %124 %125 +%124 = OpLabel +%126 = OpLoad %v4int %expected +%127 = OpIEqual %v4bool %33 %126 +%128 = OpAll %bool %127 +OpBranch %125 +%125 = OpLabel +%129 = OpPhi %bool %false %117 %128 %124 +OpSelectionMerge %134 None +OpBranchConditional %129 %132 %133 +%132 = OpLabel +%135 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%136 = OpLoad %v4float %135 +OpStore %130 %136 +OpBranch %134 +%133 = OpLabel +%137 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%138 = OpLoad %v4float %137 +OpStore %130 %138 +OpBranch %134 +%134 = OpLabel +%139 = OpLoad %v4float %130 +OpReturnValue %139 OpFunctionEnd diff --git a/tests/sksl/intrinsics/AbsInt.glsl b/tests/sksl/intrinsics/AbsInt.glsl index b032933b41..f5da94f649 100644 --- a/tests/sksl/intrinsics/AbsInt.glsl +++ b/tests/sksl/intrinsics/AbsInt.glsl @@ -5,5 +5,5 @@ uniform vec4 colorGreen; uniform vec4 colorRed; vec4 main() { ivec4 expected = ivec4(1, 0, 0, 2); - return ((abs(int(testInputs.x)) == expected.x && abs(ivec2(testInputs.xy)) == expected.xy) && abs(ivec3(testInputs.xyz)) == expected.xyz) && abs(ivec4(testInputs)) == expected ? colorGreen : colorRed; + return ((((((abs(int(testInputs.x)) == expected.x && abs(ivec2(testInputs.xy)) == expected.xy) && abs(ivec3(testInputs.xyz)) == expected.xyz) && abs(ivec4(testInputs)) == expected) && 1 == expected.x) && ivec2(1, 0) == expected.xy) && ivec3(1, 0, 0) == expected.xyz) && ivec4(1, 0, 0, 2) == expected ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/AbsInt.metal b/tests/sksl/intrinsics/AbsInt.metal index 21747e9221..4a97949234 100644 --- a/tests/sksl/intrinsics/AbsInt.metal +++ b/tests/sksl/intrinsics/AbsInt.metal @@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo Outputs _out; (void)_out; int4 expected = int4(1, 0, 0, 2); - _out.sk_FragColor = ((abs(int(_uniforms.testInputs.x)) == expected.x && all(abs(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(abs(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(abs(int4(_uniforms.testInputs)) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; + _out.sk_FragColor = ((((((abs(int(_uniforms.testInputs.x)) == expected.x && all(abs(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(abs(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(abs(int4(_uniforms.testInputs)) == expected)) && 1 == expected.x) && all(int2(1, 0) == expected.xy)) && all(int3(1, 0, 0) == expected.xyz)) && all(int4(1, 0, 0, 2) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/All.asm.frag b/tests/sksl/intrinsics/All.asm.frag index be5aaf7857..5b3112f7ab 100644 --- a/tests/sksl/intrinsics/All.asm.frag +++ b/tests/sksl/intrinsics/All.asm.frag @@ -1,18 +1,56 @@ OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise -OpExecutionMode %main OriginUpperLeft +OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise +OpExecutionMode %_entrypoint_v OriginUpperLeft OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" -OpName %a "a" +OpName %_UniformBuffer "_UniformBuffer" +OpMemberName %_UniformBuffer 0 "inputH4" +OpMemberName %_UniformBuffer 1 "expectedH4" +OpMemberName %_UniformBuffer 2 "colorGreen" +OpMemberName %_UniformBuffer 3 "colorRed" +OpName %_entrypoint_v "_entrypoint_v" OpName %main "main" +OpName %input "input" +OpName %expected "expected" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %17 RelaxedPrecision -OpDecorate %22 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 0 Offset 0 +OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 1 Offset 16 +OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 2 Offset 32 +OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 3 Offset 48 +OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision +OpDecorate %_UniformBuffer Block +OpDecorate %10 Binding 0 +OpDecorate %10 DescriptorSet 0 +OpDecorate %33 RelaxedPrecision +OpDecorate %34 RelaxedPrecision +OpDecorate %36 RelaxedPrecision +OpDecorate %38 RelaxedPrecision +OpDecorate %40 RelaxedPrecision +OpDecorate %46 RelaxedPrecision +OpDecorate %47 RelaxedPrecision +OpDecorate %49 RelaxedPrecision +OpDecorate %51 RelaxedPrecision +OpDecorate %53 RelaxedPrecision +OpDecorate %58 RelaxedPrecision +OpDecorate %61 RelaxedPrecision +OpDecorate %67 RelaxedPrecision +OpDecorate %70 RelaxedPrecision +OpDecorate %77 RelaxedPrecision +OpDecorate %78 RelaxedPrecision +OpDecorate %84 RelaxedPrecision +OpDecorate %89 RelaxedPrecision +OpDecorate %95 RelaxedPrecision +OpDecorate %106 RelaxedPrecision +OpDecorate %109 RelaxedPrecision +OpDecorate %110 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -20,22 +58,134 @@ OpDecorate %22 RelaxedPrecision %bool = OpTypeBool %_ptr_Input_bool = OpTypePointer Input %bool %sk_Clockwise = OpVariable %_ptr_Input_bool Input -%v4bool = OpTypeVector %bool 4 -%_ptr_Private_v4bool = OpTypePointer Private %v4bool -%a = OpVariable %_ptr_Private_v4bool Private +%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float +%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer +%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform %void = OpTypeVoid -%14 = OpTypeFunction %void +%15 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%float_0 = OpConstant %float 0 +%19 = OpConstantComposite %v2float %float_0 %float_0 +%_ptr_Function_v2float = OpTypePointer Function %v2float +%23 = OpTypeFunction %v4float %_ptr_Function_v2float +%v4bool = OpTypeVector %bool 4 +%_ptr_Function_v4bool = OpTypePointer Function %v4bool +%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float %int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 %int_0 = OpConstant %int 0 -%_ptr_Output_float = OpTypePointer Output %float -%main = OpFunction %void None %14 -%15 = OpLabel -%17 = OpLoad %v4bool %a -%16 = OpAll %bool %17 -%18 = OpSelect %int %16 %int_1 %int_0 -%22 = OpConvertSToF %float %18 -%23 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 -OpStore %23 %22 +%int_1 = OpConstant %int 1 +%false = OpConstantFalse %bool +%v2bool = OpTypeVector %bool 2 +%v3bool = OpTypeVector %bool 3 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%int_2 = OpConstant %int 2 +%int_3 = OpConstant %int 3 +%_entrypoint_v = OpFunction %void None %15 +%16 = OpLabel +%20 = OpVariable %_ptr_Function_v2float Function +OpStore %20 %19 +%22 = OpFunctionCall %v4float %main %20 +OpStore %sk_FragColor %22 OpReturn OpFunctionEnd +%main = OpFunction %v4float None %23 +%24 = OpFunctionParameter %_ptr_Function_v2float +%25 = OpLabel +%input = OpVariable %_ptr_Function_v4bool Function +%expected = OpVariable %_ptr_Function_v4bool Function +%99 = OpVariable %_ptr_Function_v4float Function +%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%33 = OpLoad %v4float %29 +%34 = OpCompositeExtract %float %33 0 +%35 = OpFUnordNotEqual %bool %34 %float_0 +%36 = OpCompositeExtract %float %33 1 +%37 = OpFUnordNotEqual %bool %36 %float_0 +%38 = OpCompositeExtract %float %33 2 +%39 = OpFUnordNotEqual %bool %38 %float_0 +%40 = OpCompositeExtract %float %33 3 +%41 = OpFUnordNotEqual %bool %40 %float_0 +%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41 +OpStore %input %42 +%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%46 = OpLoad %v4float %44 +%47 = OpCompositeExtract %float %46 0 +%48 = OpFUnordNotEqual %bool %47 %float_0 +%49 = OpCompositeExtract %float %46 1 +%50 = OpFUnordNotEqual %bool %49 %float_0 +%51 = OpCompositeExtract %float %46 2 +%52 = OpFUnordNotEqual %bool %51 %float_0 +%53 = OpCompositeExtract %float %46 3 +%54 = OpFUnordNotEqual %bool %53 %float_0 +%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54 +OpStore %expected %55 +%58 = OpLoad %v4bool %input +%59 = OpVectorShuffle %v2bool %58 %58 0 1 +%57 = OpAll %bool %59 +%61 = OpLoad %v4bool %expected +%62 = OpCompositeExtract %bool %61 0 +%63 = OpLogicalEqual %bool %57 %62 +OpSelectionMerge %65 None +OpBranchConditional %63 %64 %65 +%64 = OpLabel +%67 = OpLoad %v4bool %input +%68 = OpVectorShuffle %v3bool %67 %67 0 1 2 +%66 = OpAll %bool %68 +%70 = OpLoad %v4bool %expected +%71 = OpCompositeExtract %bool %70 1 +%72 = OpLogicalEqual %bool %66 %71 +OpBranch %65 +%65 = OpLabel +%73 = OpPhi %bool %false %25 %72 %64 +OpSelectionMerge %75 None +OpBranchConditional %73 %74 %75 +%74 = OpLabel +%77 = OpLoad %v4bool %input +%76 = OpAll %bool %77 +%78 = OpLoad %v4bool %expected +%79 = OpCompositeExtract %bool %78 2 +%80 = OpLogicalEqual %bool %76 %79 +OpBranch %75 +%75 = OpLabel +%81 = OpPhi %bool %false %65 %80 %74 +OpSelectionMerge %83 None +OpBranchConditional %81 %82 %83 +%82 = OpLabel +%84 = OpLoad %v4bool %expected +%85 = OpCompositeExtract %bool %84 0 +OpBranch %83 +%83 = OpLabel +%86 = OpPhi %bool %false %75 %85 %82 +OpSelectionMerge %88 None +OpBranchConditional %86 %87 %88 +%87 = OpLabel +%89 = OpLoad %v4bool %expected +%90 = OpCompositeExtract %bool %89 1 +%91 = OpLogicalEqual %bool %false %90 +OpBranch %88 +%88 = OpLabel +%92 = OpPhi %bool %false %83 %91 %87 +OpSelectionMerge %94 None +OpBranchConditional %92 %93 %94 +%93 = OpLabel +%95 = OpLoad %v4bool %expected +%96 = OpCompositeExtract %bool %95 2 +%97 = OpLogicalEqual %bool %false %96 +OpBranch %94 +%94 = OpLabel +%98 = OpPhi %bool %false %88 %97 %93 +OpSelectionMerge %103 None +OpBranchConditional %98 %101 %102 +%101 = OpLabel +%104 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%106 = OpLoad %v4float %104 +OpStore %99 %106 +OpBranch %103 +%102 = OpLabel +%107 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3 +%109 = OpLoad %v4float %107 +OpStore %99 %109 +OpBranch %103 +%103 = OpLabel +%110 = OpLoad %v4float %99 +OpReturnValue %110 +OpFunctionEnd diff --git a/tests/sksl/intrinsics/All.glsl b/tests/sksl/intrinsics/All.glsl index e7db8f69f7..c524ee64e5 100644 --- a/tests/sksl/intrinsics/All.glsl +++ b/tests/sksl/intrinsics/All.glsl @@ -1,6 +1,11 @@ out vec4 sk_FragColor; -bvec4 a; -void main() { - sk_FragColor.x = float(all(a) ? 1 : 0); +uniform vec4 inputH4; +uniform vec4 expectedH4; +uniform vec4 colorGreen; +uniform vec4 colorRed; +vec4 main() { + bvec4 input = bvec4(inputH4); + bvec4 expected = bvec4(expectedH4); + return ((((all(input.xy) == expected.x && all(input.xyz) == expected.y) && all(input) == expected.z) && expected.x) && false == expected.y) && false == expected.z ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/All.metal b/tests/sksl/intrinsics/All.metal index d521a14996..8412515a54 100644 --- a/tests/sksl/intrinsics/All.metal +++ b/tests/sksl/intrinsics/All.metal @@ -1,19 +1,23 @@ #include <metal_stdlib> #include <simd/simd.h> using namespace metal; +struct Uniforms { + float4 inputH4; + float4 expectedH4; + float4 colorGreen; + float4 colorRed; +}; struct Inputs { }; struct Outputs { float4 sk_FragColor [[color(0)]]; }; -struct Globals { - bool4 a; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Globals _globals{{}}; - (void)_globals; + +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { Outputs _out; (void)_out; - _out.sk_FragColor.x = float(all(_globals.a) ? 1 : 0); + bool4 input = bool4(_uniforms.inputH4); + bool4 expected = bool4(_uniforms.expectedH4); + _out.sk_FragColor = ((((all(input.xy) == expected.x && all(input.xyz) == expected.y) && all(input) == expected.z) && expected.x) && false == expected.y) && false == expected.z ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/Any.asm.frag b/tests/sksl/intrinsics/Any.asm.frag index d924998f5a..7424a93ee1 100644 --- a/tests/sksl/intrinsics/Any.asm.frag +++ b/tests/sksl/intrinsics/Any.asm.frag @@ -1,18 +1,56 @@ OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise -OpExecutionMode %main OriginUpperLeft +OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise +OpExecutionMode %_entrypoint_v OriginUpperLeft OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" -OpName %a "a" +OpName %_UniformBuffer "_UniformBuffer" +OpMemberName %_UniformBuffer 0 "inputH4" +OpMemberName %_UniformBuffer 1 "expectedH4" +OpMemberName %_UniformBuffer 2 "colorGreen" +OpMemberName %_UniformBuffer 3 "colorRed" +OpName %_entrypoint_v "_entrypoint_v" OpName %main "main" +OpName %input "input" +OpName %expected "expected" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %17 RelaxedPrecision -OpDecorate %22 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 0 Offset 0 +OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 1 Offset 16 +OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 2 Offset 32 +OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 3 Offset 48 +OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision +OpDecorate %_UniformBuffer Block +OpDecorate %10 Binding 0 +OpDecorate %10 DescriptorSet 0 +OpDecorate %33 RelaxedPrecision +OpDecorate %34 RelaxedPrecision +OpDecorate %36 RelaxedPrecision +OpDecorate %38 RelaxedPrecision +OpDecorate %40 RelaxedPrecision +OpDecorate %46 RelaxedPrecision +OpDecorate %47 RelaxedPrecision +OpDecorate %49 RelaxedPrecision +OpDecorate %51 RelaxedPrecision +OpDecorate %53 RelaxedPrecision +OpDecorate %58 RelaxedPrecision +OpDecorate %61 RelaxedPrecision +OpDecorate %67 RelaxedPrecision +OpDecorate %70 RelaxedPrecision +OpDecorate %77 RelaxedPrecision +OpDecorate %78 RelaxedPrecision +OpDecorate %84 RelaxedPrecision +OpDecorate %90 RelaxedPrecision +OpDecorate %95 RelaxedPrecision +OpDecorate %105 RelaxedPrecision +OpDecorate %108 RelaxedPrecision +OpDecorate %109 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -20,22 +58,133 @@ OpDecorate %22 RelaxedPrecision %bool = OpTypeBool %_ptr_Input_bool = OpTypePointer Input %bool %sk_Clockwise = OpVariable %_ptr_Input_bool Input -%v4bool = OpTypeVector %bool 4 -%_ptr_Private_v4bool = OpTypePointer Private %v4bool -%a = OpVariable %_ptr_Private_v4bool Private +%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float +%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer +%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform %void = OpTypeVoid -%14 = OpTypeFunction %void +%15 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%float_0 = OpConstant %float 0 +%19 = OpConstantComposite %v2float %float_0 %float_0 +%_ptr_Function_v2float = OpTypePointer Function %v2float +%23 = OpTypeFunction %v4float %_ptr_Function_v2float +%v4bool = OpTypeVector %bool 4 +%_ptr_Function_v4bool = OpTypePointer Function %v4bool +%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float %int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 %int_0 = OpConstant %int 0 -%_ptr_Output_float = OpTypePointer Output %float -%main = OpFunction %void None %14 -%15 = OpLabel -%17 = OpLoad %v4bool %a -%16 = OpAny %bool %17 -%18 = OpSelect %int %16 %int_1 %int_0 -%22 = OpConvertSToF %float %18 -%23 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 -OpStore %23 %22 +%int_1 = OpConstant %int 1 +%false = OpConstantFalse %bool +%v2bool = OpTypeVector %bool 2 +%v3bool = OpTypeVector %bool 3 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%int_2 = OpConstant %int 2 +%int_3 = OpConstant %int 3 +%_entrypoint_v = OpFunction %void None %15 +%16 = OpLabel +%20 = OpVariable %_ptr_Function_v2float Function +OpStore %20 %19 +%22 = OpFunctionCall %v4float %main %20 +OpStore %sk_FragColor %22 OpReturn OpFunctionEnd +%main = OpFunction %v4float None %23 +%24 = OpFunctionParameter %_ptr_Function_v2float +%25 = OpLabel +%input = OpVariable %_ptr_Function_v4bool Function +%expected = OpVariable %_ptr_Function_v4bool Function +%98 = OpVariable %_ptr_Function_v4float Function +%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%33 = OpLoad %v4float %29 +%34 = OpCompositeExtract %float %33 0 +%35 = OpFUnordNotEqual %bool %34 %float_0 +%36 = OpCompositeExtract %float %33 1 +%37 = OpFUnordNotEqual %bool %36 %float_0 +%38 = OpCompositeExtract %float %33 2 +%39 = OpFUnordNotEqual %bool %38 %float_0 +%40 = OpCompositeExtract %float %33 3 +%41 = OpFUnordNotEqual %bool %40 %float_0 +%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41 +OpStore %input %42 +%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%46 = OpLoad %v4float %44 +%47 = OpCompositeExtract %float %46 0 +%48 = OpFUnordNotEqual %bool %47 %float_0 +%49 = OpCompositeExtract %float %46 1 +%50 = OpFUnordNotEqual %bool %49 %float_0 +%51 = OpCompositeExtract %float %46 2 +%52 = OpFUnordNotEqual %bool %51 %float_0 +%53 = OpCompositeExtract %float %46 3 +%54 = OpFUnordNotEqual %bool %53 %float_0 +%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54 +OpStore %expected %55 +%58 = OpLoad %v4bool %input +%59 = OpVectorShuffle %v2bool %58 %58 0 1 +%57 = OpAny %bool %59 +%61 = OpLoad %v4bool %expected +%62 = OpCompositeExtract %bool %61 0 +%63 = OpLogicalEqual %bool %57 %62 +OpSelectionMerge %65 None +OpBranchConditional %63 %64 %65 +%64 = OpLabel +%67 = OpLoad %v4bool %input +%68 = OpVectorShuffle %v3bool %67 %67 0 1 2 +%66 = OpAny %bool %68 +%70 = OpLoad %v4bool %expected +%71 = OpCompositeExtract %bool %70 1 +%72 = OpLogicalEqual %bool %66 %71 +OpBranch %65 +%65 = OpLabel +%73 = OpPhi %bool %false %25 %72 %64 +OpSelectionMerge %75 None +OpBranchConditional %73 %74 %75 +%74 = OpLabel +%77 = OpLoad %v4bool %input +%76 = OpAny %bool %77 +%78 = OpLoad %v4bool %expected +%79 = OpCompositeExtract %bool %78 2 +%80 = OpLogicalEqual %bool %76 %79 +OpBranch %75 +%75 = OpLabel +%81 = OpPhi %bool %false %65 %80 %74 +OpSelectionMerge %83 None +OpBranchConditional %81 %82 %83 +%82 = OpLabel +%84 = OpLoad %v4bool %expected +%85 = OpCompositeExtract %bool %84 0 +%86 = OpLogicalEqual %bool %false %85 +OpBranch %83 +%83 = OpLabel +%87 = OpPhi %bool %false %75 %86 %82 +OpSelectionMerge %89 None +OpBranchConditional %87 %88 %89 +%88 = OpLabel +%90 = OpLoad %v4bool %expected +%91 = OpCompositeExtract %bool %90 1 +OpBranch %89 +%89 = OpLabel +%92 = OpPhi %bool %false %83 %91 %88 +OpSelectionMerge %94 None +OpBranchConditional %92 %93 %94 +%93 = OpLabel +%95 = OpLoad %v4bool %expected +%96 = OpCompositeExtract %bool %95 2 +OpBranch %94 +%94 = OpLabel +%97 = OpPhi %bool %false %89 %96 %93 +OpSelectionMerge %102 None +OpBranchConditional %97 %100 %101 +%100 = OpLabel +%103 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%105 = OpLoad %v4float %103 +OpStore %98 %105 +OpBranch %102 +%101 = OpLabel +%106 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3 +%108 = OpLoad %v4float %106 +OpStore %98 %108 +OpBranch %102 +%102 = OpLabel +%109 = OpLoad %v4float %98 +OpReturnValue %109 +OpFunctionEnd diff --git a/tests/sksl/intrinsics/Any.glsl b/tests/sksl/intrinsics/Any.glsl index 41d3671e74..e78bcb128e 100644 --- a/tests/sksl/intrinsics/Any.glsl +++ b/tests/sksl/intrinsics/Any.glsl @@ -1,6 +1,11 @@ out vec4 sk_FragColor; -bvec4 a; -void main() { - sk_FragColor.x = float(any(a) ? 1 : 0); +uniform vec4 inputH4; +uniform vec4 expectedH4; +uniform vec4 colorGreen; +uniform vec4 colorRed; +vec4 main() { + bvec4 input = bvec4(inputH4); + bvec4 expected = bvec4(expectedH4); + return ((((any(input.xy) == expected.x && any(input.xyz) == expected.y) && any(input) == expected.z) && false == expected.x) && expected.y) && expected.z ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/Any.metal b/tests/sksl/intrinsics/Any.metal index 402e25b8bb..b21eb7f5da 100644 --- a/tests/sksl/intrinsics/Any.metal +++ b/tests/sksl/intrinsics/Any.metal @@ -1,19 +1,23 @@ #include <metal_stdlib> #include <simd/simd.h> using namespace metal; +struct Uniforms { + float4 inputH4; + float4 expectedH4; + float4 colorGreen; + float4 colorRed; +}; struct Inputs { }; struct Outputs { float4 sk_FragColor [[color(0)]]; }; -struct Globals { - bool4 a; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Globals _globals{{}}; - (void)_globals; + +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { Outputs _out; (void)_out; - _out.sk_FragColor.x = float(any(_globals.a) ? 1 : 0); + bool4 input = bool4(_uniforms.inputH4); + bool4 expected = bool4(_uniforms.expectedH4); + _out.sk_FragColor = ((((any(input.xy) == expected.x && any(input.xyz) == expected.y) && any(input) == expected.z) && false == expected.x) && expected.y) && expected.z ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/Not.asm.frag b/tests/sksl/intrinsics/Not.asm.frag index 5cb4270384..d217a18722 100644 --- a/tests/sksl/intrinsics/Not.asm.frag +++ b/tests/sksl/intrinsics/Not.asm.frag @@ -1,18 +1,56 @@ OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise -OpExecutionMode %main OriginUpperLeft +OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise +OpExecutionMode %_entrypoint_v OriginUpperLeft OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" -OpName %a "a" +OpName %_UniformBuffer "_UniformBuffer" +OpMemberName %_UniformBuffer 0 "inputH4" +OpMemberName %_UniformBuffer 1 "expectedH4" +OpMemberName %_UniformBuffer 2 "colorGreen" +OpMemberName %_UniformBuffer 3 "colorRed" +OpName %_entrypoint_v "_entrypoint_v" OpName %main "main" +OpName %input "input" +OpName %expected "expected" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %17 RelaxedPrecision -OpDecorate %23 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 0 Offset 0 +OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 1 Offset 16 +OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 2 Offset 32 +OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 3 Offset 48 +OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision +OpDecorate %_UniformBuffer Block +OpDecorate %10 Binding 0 +OpDecorate %10 DescriptorSet 0 +OpDecorate %33 RelaxedPrecision +OpDecorate %34 RelaxedPrecision +OpDecorate %36 RelaxedPrecision +OpDecorate %38 RelaxedPrecision +OpDecorate %40 RelaxedPrecision +OpDecorate %46 RelaxedPrecision +OpDecorate %47 RelaxedPrecision +OpDecorate %49 RelaxedPrecision +OpDecorate %51 RelaxedPrecision +OpDecorate %53 RelaxedPrecision +OpDecorate %58 RelaxedPrecision +OpDecorate %61 RelaxedPrecision +OpDecorate %68 RelaxedPrecision +OpDecorate %71 RelaxedPrecision +OpDecorate %79 RelaxedPrecision +OpDecorate %80 RelaxedPrecision +OpDecorate %88 RelaxedPrecision +OpDecorate %96 RelaxedPrecision +OpDecorate %104 RelaxedPrecision +OpDecorate %115 RelaxedPrecision +OpDecorate %118 RelaxedPrecision +OpDecorate %119 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -20,23 +58,143 @@ OpDecorate %23 RelaxedPrecision %bool = OpTypeBool %_ptr_Input_bool = OpTypePointer Input %bool %sk_Clockwise = OpVariable %_ptr_Input_bool Input -%v4bool = OpTypeVector %bool 4 -%_ptr_Private_v4bool = OpTypePointer Private %v4bool -%a = OpVariable %_ptr_Private_v4bool Private +%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float +%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer +%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform %void = OpTypeVoid -%14 = OpTypeFunction %void +%15 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%float_0 = OpConstant %float 0 +%19 = OpConstantComposite %v2float %float_0 %float_0 +%_ptr_Function_v2float = OpTypePointer Function %v2float +%23 = OpTypeFunction %v4float %_ptr_Function_v2float +%v4bool = OpTypeVector %bool 4 +%_ptr_Function_v4bool = OpTypePointer Function %v4bool +%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float %int = OpTypeInt 32 1 -%int_1 = OpConstant %int 1 %int_0 = OpConstant %int 0 -%_ptr_Output_float = OpTypePointer Output %float -%main = OpFunction %void None %14 -%15 = OpLabel -%17 = OpLoad %v4bool %a -%16 = OpLogicalNot %v4bool %17 -%18 = OpCompositeExtract %bool %16 0 -%19 = OpSelect %int %18 %int_1 %int_0 -%23 = OpConvertSToF %float %19 -%24 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 -OpStore %24 %23 +%int_1 = OpConstant %int 1 +%false = OpConstantFalse %bool +%v2bool = OpTypeVector %bool 2 +%v3bool = OpTypeVector %bool 3 +%true = OpConstantTrue %bool +%87 = OpConstantComposite %v2bool %false %true +%95 = OpConstantComposite %v3bool %false %true %false +%103 = OpConstantComposite %v4bool %false %true %false %true +%_ptr_Function_v4float = OpTypePointer Function %v4float +%int_2 = OpConstant %int 2 +%int_3 = OpConstant %int 3 +%_entrypoint_v = OpFunction %void None %15 +%16 = OpLabel +%20 = OpVariable %_ptr_Function_v2float Function +OpStore %20 %19 +%22 = OpFunctionCall %v4float %main %20 +OpStore %sk_FragColor %22 OpReturn OpFunctionEnd +%main = OpFunction %v4float None %23 +%24 = OpFunctionParameter %_ptr_Function_v2float +%25 = OpLabel +%input = OpVariable %_ptr_Function_v4bool Function +%expected = OpVariable %_ptr_Function_v4bool Function +%108 = OpVariable %_ptr_Function_v4float Function +%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%33 = OpLoad %v4float %29 +%34 = OpCompositeExtract %float %33 0 +%35 = OpFUnordNotEqual %bool %34 %float_0 +%36 = OpCompositeExtract %float %33 1 +%37 = OpFUnordNotEqual %bool %36 %float_0 +%38 = OpCompositeExtract %float %33 2 +%39 = OpFUnordNotEqual %bool %38 %float_0 +%40 = OpCompositeExtract %float %33 3 +%41 = OpFUnordNotEqual %bool %40 %float_0 +%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41 +OpStore %input %42 +%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%46 = OpLoad %v4float %44 +%47 = OpCompositeExtract %float %46 0 +%48 = OpFUnordNotEqual %bool %47 %float_0 +%49 = OpCompositeExtract %float %46 1 +%50 = OpFUnordNotEqual %bool %49 %float_0 +%51 = OpCompositeExtract %float %46 2 +%52 = OpFUnordNotEqual %bool %51 %float_0 +%53 = OpCompositeExtract %float %46 3 +%54 = OpFUnordNotEqual %bool %53 %float_0 +%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54 +OpStore %expected %55 +%58 = OpLoad %v4bool %input +%59 = OpVectorShuffle %v2bool %58 %58 0 1 +%57 = OpLogicalNot %v2bool %59 +%61 = OpLoad %v4bool %expected +%62 = OpVectorShuffle %v2bool %61 %61 0 1 +%63 = OpLogicalEqual %v2bool %57 %62 +%64 = OpAll %bool %63 +OpSelectionMerge %66 None +OpBranchConditional %64 %65 %66 +%65 = OpLabel +%68 = OpLoad %v4bool %input +%69 = OpVectorShuffle %v3bool %68 %68 0 1 2 +%67 = OpLogicalNot %v3bool %69 +%71 = OpLoad %v4bool %expected +%72 = OpVectorShuffle %v3bool %71 %71 0 1 2 +%73 = OpLogicalEqual %v3bool %67 %72 +%74 = OpAll %bool %73 +OpBranch %66 +%66 = OpLabel +%75 = OpPhi %bool %false %25 %74 %65 +OpSelectionMerge %77 None +OpBranchConditional %75 %76 %77 +%76 = OpLabel +%79 = OpLoad %v4bool %input +%78 = OpLogicalNot %v4bool %79 +%80 = OpLoad %v4bool %expected +%81 = OpLogicalEqual %v4bool %78 %80 +%82 = OpAll %bool %81 +OpBranch %77 +%77 = OpLabel +%83 = OpPhi %bool %false %66 %82 %76 +OpSelectionMerge %85 None +OpBranchConditional %83 %84 %85 +%84 = OpLabel +%88 = OpLoad %v4bool %expected +%89 = OpVectorShuffle %v2bool %88 %88 0 1 +%90 = OpLogicalEqual %v2bool %87 %89 +%91 = OpAll %bool %90 +OpBranch %85 +%85 = OpLabel +%92 = OpPhi %bool %false %77 %91 %84 +OpSelectionMerge %94 None +OpBranchConditional %92 %93 %94 +%93 = OpLabel +%96 = OpLoad %v4bool %expected +%97 = OpVectorShuffle %v3bool %96 %96 0 1 2 +%98 = OpLogicalEqual %v3bool %95 %97 +%99 = OpAll %bool %98 +OpBranch %94 +%94 = OpLabel +%100 = OpPhi %bool %false %85 %99 %93 +OpSelectionMerge %102 None +OpBranchConditional %100 %101 %102 +%101 = OpLabel +%104 = OpLoad %v4bool %expected +%105 = OpLogicalEqual %v4bool %103 %104 +%106 = OpAll %bool %105 +OpBranch %102 +%102 = OpLabel +%107 = OpPhi %bool %false %94 %106 %101 +OpSelectionMerge %112 None +OpBranchConditional %107 %110 %111 +%110 = OpLabel +%113 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%115 = OpLoad %v4float %113 +OpStore %108 %115 +OpBranch %112 +%111 = OpLabel +%116 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3 +%118 = OpLoad %v4float %116 +OpStore %108 %118 +OpBranch %112 +%112 = OpLabel +%119 = OpLoad %v4float %108 +OpReturnValue %119 +OpFunctionEnd diff --git a/tests/sksl/intrinsics/Not.glsl b/tests/sksl/intrinsics/Not.glsl index da4df6183c..b6b8d3dfd3 100644 --- a/tests/sksl/intrinsics/Not.glsl +++ b/tests/sksl/intrinsics/Not.glsl @@ -1,6 +1,11 @@ out vec4 sk_FragColor; -bvec4 a; -void main() { - sk_FragColor.x = float(not(a).x ? 1 : 0); +uniform vec4 inputH4; +uniform vec4 expectedH4; +uniform vec4 colorGreen; +uniform vec4 colorRed; +vec4 main() { + bvec4 input = bvec4(inputH4); + bvec4 expected = bvec4(expectedH4); + return ((((not(input.xy) == expected.xy && not(input.xyz) == expected.xyz) && not(input) == expected) && bvec2(false, true) == expected.xy) && bvec3(false, true, false) == expected.xyz) && bvec4(false, true, false, true) == expected ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/Not.metal b/tests/sksl/intrinsics/Not.metal index 5535bfd0d6..bb17fc6d8f 100644 --- a/tests/sksl/intrinsics/Not.metal +++ b/tests/sksl/intrinsics/Not.metal @@ -1,19 +1,23 @@ #include <metal_stdlib> #include <simd/simd.h> using namespace metal; +struct Uniforms { + float4 inputH4; + float4 expectedH4; + float4 colorGreen; + float4 colorRed; +}; struct Inputs { }; struct Outputs { float4 sk_FragColor [[color(0)]]; }; -struct Globals { - bool4 a; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Globals _globals{{}}; - (void)_globals; + +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { Outputs _out; (void)_out; - _out.sk_FragColor.x = float(not(_globals.a).x ? 1 : 0); + bool4 input = bool4(_uniforms.inputH4); + bool4 expected = bool4(_uniforms.expectedH4); + _out.sk_FragColor = ((((all(not(input.xy) == expected.xy) && all(not(input.xyz) == expected.xyz)) && all(not(input) == expected)) && all(bool2(false, true) == expected.xy)) && all(bool3(false, true, false) == expected.xyz)) && all(bool4(false, true, false, true) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/SignFloat.asm.frag b/tests/sksl/intrinsics/SignFloat.asm.frag index daebc2b205..b2a0a46c63 100644 --- a/tests/sksl/intrinsics/SignFloat.asm.frag +++ b/tests/sksl/intrinsics/SignFloat.asm.frag @@ -45,9 +45,18 @@ OpDecorate %62 RelaxedPrecision OpDecorate %69 RelaxedPrecision OpDecorate %71 RelaxedPrecision OpDecorate %72 RelaxedPrecision -OpDecorate %83 RelaxedPrecision +OpDecorate %79 RelaxedPrecision +OpDecorate %80 RelaxedPrecision +OpDecorate %85 RelaxedPrecision OpDecorate %86 RelaxedPrecision OpDecorate %87 RelaxedPrecision +OpDecorate %93 RelaxedPrecision +OpDecorate %94 RelaxedPrecision +OpDecorate %95 RelaxedPrecision +OpDecorate %101 RelaxedPrecision +OpDecorate %111 RelaxedPrecision +OpDecorate %114 RelaxedPrecision +OpDecorate %115 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -77,6 +86,8 @@ OpDecorate %87 RelaxedPrecision %v3float = OpTypeVector %float 3 %v3bool = OpTypeVector %bool 3 %v4bool = OpTypeVector %bool 4 +%85 = OpConstantComposite %v2float %float_n1 %float_0 +%93 = OpConstantComposite %v3float %float_n1 %float_0 %float_1 %int_1 = OpConstant %int 1 %int_2 = OpConstant %int 2 %_entrypoint_v = OpFunction %void None %15 @@ -91,7 +102,7 @@ OpFunctionEnd %24 = OpFunctionParameter %_ptr_Function_v2float %25 = OpLabel %expected = OpVariable %_ptr_Function_v4float Function -%77 = OpVariable %_ptr_Function_v4float Function +%105 = OpVariable %_ptr_Function_v4float Function OpStore %expected %30 %33 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 %37 = OpLoad %v4float %33 @@ -140,19 +151,57 @@ OpBranchConditional %66 %67 %68 OpBranch %68 %68 = OpLabel %76 = OpPhi %bool %false %55 %75 %67 -OpSelectionMerge %80 None -OpBranchConditional %76 %78 %79 +OpSelectionMerge %78 None +OpBranchConditional %76 %77 %78 +%77 = OpLabel +%79 = OpLoad %v4float %expected +%80 = OpCompositeExtract %float %79 0 +%81 = OpFOrdEqual %bool %float_n1 %80 +OpBranch %78 %78 = OpLabel -%81 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 -%83 = OpLoad %v4float %81 -OpStore %77 %83 -OpBranch %80 -%79 = OpLabel -%84 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 -%86 = OpLoad %v4float %84 -OpStore %77 %86 -OpBranch %80 -%80 = OpLabel -%87 = OpLoad %v4float %77 -OpReturnValue %87 +%82 = OpPhi %bool %false %68 %81 %77 +OpSelectionMerge %84 None +OpBranchConditional %82 %83 %84 +%83 = OpLabel +%86 = OpLoad %v4float %expected +%87 = OpVectorShuffle %v2float %86 %86 0 1 +%88 = OpFOrdEqual %v2bool %85 %87 +%89 = OpAll %bool %88 +OpBranch %84 +%84 = OpLabel +%90 = OpPhi %bool %false %78 %89 %83 +OpSelectionMerge %92 None +OpBranchConditional %90 %91 %92 +%91 = OpLabel +%94 = OpLoad %v4float %expected +%95 = OpVectorShuffle %v3float %94 %94 0 1 2 +%96 = OpFOrdEqual %v3bool %93 %95 +%97 = OpAll %bool %96 +OpBranch %92 +%92 = OpLabel +%98 = OpPhi %bool %false %84 %97 %91 +OpSelectionMerge %100 None +OpBranchConditional %98 %99 %100 +%99 = OpLabel +%101 = OpLoad %v4float %expected +%102 = OpFOrdEqual %v4bool %30 %101 +%103 = OpAll %bool %102 +OpBranch %100 +%100 = OpLabel +%104 = OpPhi %bool %false %92 %103 %99 +OpSelectionMerge %108 None +OpBranchConditional %104 %106 %107 +%106 = OpLabel +%109 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%111 = OpLoad %v4float %109 +OpStore %105 %111 +OpBranch %108 +%107 = OpLabel +%112 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%114 = OpLoad %v4float %112 +OpStore %105 %114 +OpBranch %108 +%108 = OpLabel +%115 = OpLoad %v4float %105 +OpReturnValue %115 OpFunctionEnd diff --git a/tests/sksl/intrinsics/SignFloat.glsl b/tests/sksl/intrinsics/SignFloat.glsl index c7b71cf442..f0e5510850 100644 --- a/tests/sksl/intrinsics/SignFloat.glsl +++ b/tests/sksl/intrinsics/SignFloat.glsl @@ -5,5 +5,5 @@ uniform vec4 colorGreen; uniform vec4 colorRed; vec4 main() { vec4 expected = vec4(-1.0, 0.0, 1.0, 1.0); - return ((sign(testInputs.x) == expected.x && sign(testInputs.xy) == expected.xy) && sign(testInputs.xyz) == expected.xyz) && sign(testInputs) == expected ? colorGreen : colorRed; + return ((((((sign(testInputs.x) == expected.x && sign(testInputs.xy) == expected.xy) && sign(testInputs.xyz) == expected.xyz) && sign(testInputs) == expected) && -1.0 == expected.x) && vec2(-1.0, 0.0) == expected.xy) && vec3(-1.0, 0.0, 1.0) == expected.xyz) && vec4(-1.0, 0.0, 1.0, 1.0) == expected ? colorGreen : colorRed; } diff --git a/tests/sksl/intrinsics/SignFloat.metal b/tests/sksl/intrinsics/SignFloat.metal index 15e5c7ec8c..db1ed725ef 100644 --- a/tests/sksl/intrinsics/SignFloat.metal +++ b/tests/sksl/intrinsics/SignFloat.metal @@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo Outputs _out; (void)_out; float4 expected = float4(-1.0, 0.0, 1.0, 1.0); - _out.sk_FragColor = ((sign(_uniforms.testInputs.x) == expected.x && all(sign(_uniforms.testInputs.xy) == expected.xy)) && all(sign(_uniforms.testInputs.xyz) == expected.xyz)) && all(sign(_uniforms.testInputs) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; + _out.sk_FragColor = ((((((sign(_uniforms.testInputs.x) == expected.x && all(sign(_uniforms.testInputs.xy) == expected.xy)) && all(sign(_uniforms.testInputs.xyz) == expected.xyz)) && all(sign(_uniforms.testInputs) == expected)) && -1.0 == expected.x) && all(float2(-1.0, 0.0) == expected.xy)) && all(float3(-1.0, 0.0, 1.0) == expected.xyz)) && all(float4(-1.0, 0.0, 1.0, 1.0) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; return _out; } diff --git a/tests/sksl/intrinsics/SignInt.asm.frag b/tests/sksl/intrinsics/SignInt.asm.frag index 82285401d4..97a563d95f 100644 --- a/tests/sksl/intrinsics/SignInt.asm.frag +++ b/tests/sksl/intrinsics/SignInt.asm.frag @@ -1,4 +1,219 @@ -### Compilation failed: - -error: 6: unknown identifier 'testInputs' -1 error +OpCapability Shader +%1 = OpExtInstImport "GLSL.std.450" +OpMemoryModel Logical GLSL450 +OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise +OpExecutionMode %_entrypoint_v OriginUpperLeft +OpName %sk_FragColor "sk_FragColor" +OpName %sk_Clockwise "sk_Clockwise" +OpName %_UniformBuffer "_UniformBuffer" +OpMemberName %_UniformBuffer 0 "testInputs" +OpMemberName %_UniformBuffer 1 "colorGreen" +OpMemberName %_UniformBuffer 2 "colorRed" +OpName %_entrypoint_v "_entrypoint_v" +OpName %main "main" +OpName %expected "expected" +OpDecorate %sk_FragColor RelaxedPrecision +OpDecorate %sk_FragColor Location 0 +OpDecorate %sk_FragColor Index 0 +OpDecorate %sk_Clockwise BuiltIn FrontFacing +OpMemberDecorate %_UniformBuffer 0 Offset 0 +OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 1 Offset 16 +OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 2 Offset 32 +OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision +OpDecorate %_UniformBuffer Block +OpDecorate %10 Binding 0 +OpDecorate %10 DescriptorSet 0 +OpDecorate %38 RelaxedPrecision +OpDecorate %39 RelaxedPrecision +OpDecorate %48 RelaxedPrecision +OpDecorate %49 RelaxedPrecision +OpDecorate %50 RelaxedPrecision +OpDecorate %52 RelaxedPrecision +OpDecorate %66 RelaxedPrecision +OpDecorate %67 RelaxedPrecision +OpDecorate %69 RelaxedPrecision +OpDecorate %71 RelaxedPrecision +OpDecorate %73 RelaxedPrecision +OpDecorate %87 RelaxedPrecision +OpDecorate %88 RelaxedPrecision +OpDecorate %90 RelaxedPrecision +OpDecorate %92 RelaxedPrecision +OpDecorate %94 RelaxedPrecision +OpDecorate %136 RelaxedPrecision +OpDecorate %139 RelaxedPrecision +OpDecorate %140 RelaxedPrecision +%float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%sk_FragColor = OpVariable %_ptr_Output_v4float Output +%bool = OpTypeBool +%_ptr_Input_bool = OpTypePointer Input %bool +%sk_Clockwise = OpVariable %_ptr_Input_bool Input +%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float +%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer +%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform +%void = OpTypeVoid +%15 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%float_0 = OpConstant %float 0 +%19 = OpConstantComposite %v2float %float_0 %float_0 +%_ptr_Function_v2float = OpTypePointer Function %v2float +%23 = OpTypeFunction %v4float %_ptr_Function_v2float +%int = OpTypeInt 32 1 +%v4int = OpTypeVector %int 4 +%_ptr_Function_v4int = OpTypePointer Function %v4int +%int_n1 = OpConstant %int -1 +%int_0 = OpConstant %int 0 +%int_1 = OpConstant %int 1 +%33 = OpConstantComposite %v4int %int_n1 %int_0 %int_0 %int_1 +%false = OpConstantFalse %bool +%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float +%v2int = OpTypeVector %int 2 +%v2bool = OpTypeVector %bool 2 +%v3float = OpTypeVector %float 3 +%v3int = OpTypeVector %int 3 +%v3bool = OpTypeVector %bool 3 +%v4bool = OpTypeVector %bool 4 +%110 = OpConstantComposite %v2int %int_n1 %int_0 +%118 = OpConstantComposite %v3int %int_n1 %int_0 %int_0 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%int_2 = OpConstant %int 2 +%_entrypoint_v = OpFunction %void None %15 +%16 = OpLabel +%20 = OpVariable %_ptr_Function_v2float Function +OpStore %20 %19 +%22 = OpFunctionCall %v4float %main %20 +OpStore %sk_FragColor %22 +OpReturn +OpFunctionEnd +%main = OpFunction %v4float None %23 +%24 = OpFunctionParameter %_ptr_Function_v2float +%25 = OpLabel +%expected = OpVariable %_ptr_Function_v4int Function +%130 = OpVariable %_ptr_Function_v4float Function +OpStore %expected %33 +%36 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%38 = OpLoad %v4float %36 +%39 = OpCompositeExtract %float %38 0 +%40 = OpConvertFToS %int %39 +%35 = OpExtInst %int %1 SSign %40 +%41 = OpLoad %v4int %expected +%42 = OpCompositeExtract %int %41 0 +%43 = OpIEqual %bool %35 %42 +OpSelectionMerge %45 None +OpBranchConditional %43 %44 %45 +%44 = OpLabel +%47 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%48 = OpLoad %v4float %47 +%49 = OpVectorShuffle %v2float %48 %48 0 1 +%50 = OpCompositeExtract %float %49 0 +%51 = OpConvertFToS %int %50 +%52 = OpCompositeExtract %float %49 1 +%53 = OpConvertFToS %int %52 +%54 = OpCompositeConstruct %v2int %51 %53 +%46 = OpExtInst %v2int %1 SSign %54 +%56 = OpLoad %v4int %expected +%57 = OpVectorShuffle %v2int %56 %56 0 1 +%58 = OpIEqual %v2bool %46 %57 +%60 = OpAll %bool %58 +OpBranch %45 +%45 = OpLabel +%61 = OpPhi %bool %false %25 %60 %44 +OpSelectionMerge %63 None +OpBranchConditional %61 %62 %63 +%62 = OpLabel +%65 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%66 = OpLoad %v4float %65 +%67 = OpVectorShuffle %v3float %66 %66 0 1 2 +%69 = OpCompositeExtract %float %67 0 +%70 = OpConvertFToS %int %69 +%71 = OpCompositeExtract %float %67 1 +%72 = OpConvertFToS %int %71 +%73 = OpCompositeExtract %float %67 2 +%74 = OpConvertFToS %int %73 +%75 = OpCompositeConstruct %v3int %70 %72 %74 +%64 = OpExtInst %v3int %1 SSign %75 +%77 = OpLoad %v4int %expected +%78 = OpVectorShuffle %v3int %77 %77 0 1 2 +%79 = OpIEqual %v3bool %64 %78 +%81 = OpAll %bool %79 +OpBranch %63 +%63 = OpLabel +%82 = OpPhi %bool %false %45 %81 %62 +OpSelectionMerge %84 None +OpBranchConditional %82 %83 %84 +%83 = OpLabel +%86 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%87 = OpLoad %v4float %86 +%88 = OpCompositeExtract %float %87 0 +%89 = OpConvertFToS %int %88 +%90 = OpCompositeExtract %float %87 1 +%91 = OpConvertFToS %int %90 +%92 = OpCompositeExtract %float %87 2 +%93 = OpConvertFToS %int %92 +%94 = OpCompositeExtract %float %87 3 +%95 = OpConvertFToS %int %94 +%96 = OpCompositeConstruct %v4int %89 %91 %93 %95 +%85 = OpExtInst %v4int %1 SSign %96 +%97 = OpLoad %v4int %expected +%98 = OpIEqual %v4bool %85 %97 +%100 = OpAll %bool %98 +OpBranch %84 +%84 = OpLabel +%101 = OpPhi %bool %false %63 %100 %83 +OpSelectionMerge %103 None +OpBranchConditional %101 %102 %103 +%102 = OpLabel +%104 = OpLoad %v4int %expected +%105 = OpCompositeExtract %int %104 0 +%106 = OpIEqual %bool %int_n1 %105 +OpBranch %103 +%103 = OpLabel +%107 = OpPhi %bool %false %84 %106 %102 +OpSelectionMerge %109 None +OpBranchConditional %107 %108 %109 +%108 = OpLabel +%111 = OpLoad %v4int %expected +%112 = OpVectorShuffle %v2int %111 %111 0 1 +%113 = OpIEqual %v2bool %110 %112 +%114 = OpAll %bool %113 +OpBranch %109 +%109 = OpLabel +%115 = OpPhi %bool %false %103 %114 %108 +OpSelectionMerge %117 None +OpBranchConditional %115 %116 %117 +%116 = OpLabel +%119 = OpLoad %v4int %expected +%120 = OpVectorShuffle %v3int %119 %119 0 1 2 +%121 = OpIEqual %v3bool %118 %120 +%122 = OpAll %bool %121 +OpBranch %117 +%117 = OpLabel +%123 = OpPhi %bool %false %109 %122 %116 +OpSelectionMerge %125 None +OpBranchConditional %123 %124 %125 +%124 = OpLabel +%126 = OpLoad %v4int %expected +%127 = OpIEqual %v4bool %33 %126 +%128 = OpAll %bool %127 +OpBranch %125 +%125 = OpLabel +%129 = OpPhi %bool %false %117 %128 %124 +OpSelectionMerge %134 None +OpBranchConditional %129 %132 %133 +%132 = OpLabel +%135 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%136 = OpLoad %v4float %135 +OpStore %130 %136 +OpBranch %134 +%133 = OpLabel +%137 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2 +%139 = OpLoad %v4float %137 +OpStore %130 %139 +OpBranch %134 +%134 = OpLabel +%140 = OpLoad %v4float %130 +OpReturnValue %140 +OpFunctionEnd diff --git a/tests/sksl/intrinsics/SignInt.glsl b/tests/sksl/intrinsics/SignInt.glsl index 82285401d4..a1dab10cc0 100644 --- a/tests/sksl/intrinsics/SignInt.glsl +++ b/tests/sksl/intrinsics/SignInt.glsl @@ -1,4 +1,9 @@ -### Compilation failed: -error: 6: unknown identifier 'testInputs' -1 error +out vec4 sk_FragColor; +uniform vec4 testInputs; +uniform vec4 colorGreen; +uniform vec4 colorRed; +vec4 main() { + ivec4 expected = ivec4(-1, 0, 0, 1); + return ((((((sign(int(testInputs.x)) == expected.x && sign(ivec2(testInputs.xy)) == expected.xy) && sign(ivec3(testInputs.xyz)) == expected.xyz) && sign(ivec4(testInputs)) == expected) && -1 == expected.x) && ivec2(-1, 0) == expected.xy) && ivec3(-1, 0, 0) == expected.xyz) && ivec4(-1, 0, 0, 1) == expected ? colorGreen : colorRed; +} diff --git a/tests/sksl/intrinsics/SignInt.metal b/tests/sksl/intrinsics/SignInt.metal index 82285401d4..ac5260f8c8 100644 --- a/tests/sksl/intrinsics/SignInt.metal +++ b/tests/sksl/intrinsics/SignInt.metal @@ -1,4 +1,21 @@ -### Compilation failed: +#include <metal_stdlib> +#include <simd/simd.h> +using namespace metal; +struct Uniforms { + float4 testInputs; + float4 colorGreen; + float4 colorRed; +}; +struct Inputs { +}; +struct Outputs { + float4 sk_FragColor [[color(0)]]; +}; -error: 6: unknown identifier 'testInputs' -1 error +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { + Outputs _out; + (void)_out; + int4 expected = int4(-1, 0, 0, 1); + _out.sk_FragColor = ((((((sign(int(_uniforms.testInputs.x)) == expected.x && all(sign(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(sign(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(sign(int4(_uniforms.testInputs)) == expected)) && -1 == expected.x) && all(int2(-1, 0) == expected.xy)) && all(int3(-1, 0, 0) == expected.xyz)) && all(int4(-1, 0, 0, 1) == expected) ? _uniforms.colorGreen : _uniforms.colorRed; + return _out; +} diff --git a/tests/sksl/runtime_errors/IllegalIndexing.skvm b/tests/sksl/runtime_errors/IllegalIndexing.skvm index cf4620b014..aaf54774d1 100644 --- a/tests/sksl/runtime_errors/IllegalIndexing.skvm +++ b/tests/sksl/runtime_errors/IllegalIndexing.skvm @@ -2,5 +2,4 @@ error: 25: index expression must be constant error: 26: index expression must be constant -error: 29: index expression must be constant -3 errors +2 errors diff --git a/tests/sksl/shared/ConstVariableComparison.asm.frag b/tests/sksl/shared/ConstVariableComparison.asm.frag index 6daa0e4514..0cd10e55a5 100644 --- a/tests/sksl/shared/ConstVariableComparison.asm.frag +++ b/tests/sksl/shared/ConstVariableComparison.asm.frag @@ -23,8 +23,8 @@ OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision OpDecorate %_UniformBuffer Block OpDecorate %10 Binding 0 OpDecorate %10 DescriptorSet 0 -OpDecorate %45 RelaxedPrecision -OpDecorate %48 RelaxedPrecision +OpDecorate %43 RelaxedPrecision +OpDecorate %46 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -64,23 +64,21 @@ OpFunctionEnd %b = OpVariable %_ptr_Function_v4float Function %c = OpVariable %_ptr_Function_v4float Function OpStore %b %29 -%32 = OpLoad %v4float %b -%31 = OpExtInst %v4float %1 FAbs %32 -OpStore %c %31 -%33 = OpLoad %v4float %b -%34 = OpLoad %v4float %c -%35 = OpFOrdNotEqual %v4bool %33 %34 -%37 = OpAny %bool %35 -OpSelectionMerge %40 None -OpBranchConditional %37 %38 %39 +OpStore %c %29 +%31 = OpLoad %v4float %b +%32 = OpLoad %v4float %c +%33 = OpFOrdNotEqual %v4bool %31 %32 +%35 = OpAny %bool %33 +OpSelectionMerge %38 None +OpBranchConditional %35 %36 %37 +%36 = OpLabel +%39 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%43 = OpLoad %v4float %39 +OpReturnValue %43 +%37 = OpLabel +%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%46 = OpLoad %v4float %44 +OpReturnValue %46 %38 = OpLabel -%41 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 -%45 = OpLoad %v4float %41 -OpReturnValue %45 -%39 = OpLabel -%46 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 -%48 = OpLoad %v4float %46 -OpReturnValue %48 -%40 = OpLabel OpUnreachable OpFunctionEnd diff --git a/tests/sksl/shared/ConstVariableComparison.glsl b/tests/sksl/shared/ConstVariableComparison.glsl index 6ee8a9605e..98599b0ece 100644 --- a/tests/sksl/shared/ConstVariableComparison.glsl +++ b/tests/sksl/shared/ConstVariableComparison.glsl @@ -4,7 +4,7 @@ uniform vec4 colorGreen; uniform vec4 colorRed; vec4 main() { const vec4 b = vec4(1.0); - vec4 c = abs(b); + vec4 c = vec4(1.0, 1.0, 1.0, 1.0); if (b != c) { return colorRed; } else { diff --git a/tests/sksl/shared/ConstVariableComparison.metal b/tests/sksl/shared/ConstVariableComparison.metal index d679750de0..e50d400521 100644 --- a/tests/sksl/shared/ConstVariableComparison.metal +++ b/tests/sksl/shared/ConstVariableComparison.metal @@ -15,7 +15,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo Outputs _out; (void)_out; const float4 b = float4(1.0); - float4 c = abs(b); + float4 c = float4(1.0, 1.0, 1.0, 1.0); if (any(b != c)) { _out.sk_FragColor = _uniforms.colorRed; return _out; diff --git a/tests/sksl/shared/StaticSwitchWithContinue.asm.frag b/tests/sksl/shared/StaticSwitchWithContinue.asm.frag index 3ccb6ebffa..bac74a4160 100644 --- a/tests/sksl/shared/StaticSwitchWithContinue.asm.frag +++ b/tests/sksl/shared/StaticSwitchWithContinue.asm.frag @@ -23,9 +23,9 @@ OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision OpDecorate %_UniformBuffer Block OpDecorate %10 Binding 0 OpDecorate %10 DescriptorSet 0 -OpDecorate %53 RelaxedPrecision +OpDecorate %52 RelaxedPrecision +OpDecorate %54 RelaxedPrecision OpDecorate %55 RelaxedPrecision -OpDecorate %56 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -64,7 +64,7 @@ OpFunctionEnd %25 = OpLabel %result = OpVariable %_ptr_Function_float Function %x = OpVariable %_ptr_Function_int Function -%46 = OpVariable %_ptr_Function_v4float Function +%45 = OpVariable %_ptr_Function_v4float Function OpStore %result %float_0 OpStore %x %int_0 OpBranch %32 @@ -76,30 +76,29 @@ OpBranch %33 %39 = OpSLessThanEqual %bool %37 %int_1 OpBranchConditional %39 %34 %36 %34 = OpLabel -%40 = OpExtInst %float %1 FAbs %float_2 -OpStore %result %40 +OpStore %result %float_2 OpBranch %35 %35 = OpLabel -%42 = OpLoad %int %x -%43 = OpIAdd %int %42 %int_1 -OpStore %x %43 +%41 = OpLoad %int %x +%42 = OpIAdd %int %41 %int_1 +OpStore %x %42 OpBranch %32 %36 = OpLabel -%44 = OpLoad %float %result -%45 = OpFOrdEqual %bool %44 %float_2 -OpSelectionMerge %50 None -OpBranchConditional %45 %48 %49 +%43 = OpLoad %float %result +%44 = OpFOrdEqual %bool %43 %float_2 +OpSelectionMerge %49 None +OpBranchConditional %44 %47 %48 +%47 = OpLabel +%50 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 +%52 = OpLoad %v4float %50 +OpStore %45 %52 +OpBranch %49 %48 = OpLabel -%51 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0 -%53 = OpLoad %v4float %51 -OpStore %46 %53 -OpBranch %50 +%53 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 +%54 = OpLoad %v4float %53 +OpStore %45 %54 +OpBranch %49 %49 = OpLabel -%54 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1 -%55 = OpLoad %v4float %54 -OpStore %46 %55 -OpBranch %50 -%50 = OpLabel -%56 = OpLoad %v4float %46 -OpReturnValue %56 +%55 = OpLoad %v4float %45 +OpReturnValue %55 OpFunctionEnd diff --git a/tests/sksl/shared/StaticSwitchWithContinue.glsl b/tests/sksl/shared/StaticSwitchWithContinue.glsl index be465dbfd1..c15d3fc7c2 100644 --- a/tests/sksl/shared/StaticSwitchWithContinue.glsl +++ b/tests/sksl/shared/StaticSwitchWithContinue.glsl @@ -6,7 +6,7 @@ vec4 main() { float result = 0.0; for (int x = 0;x <= 1; x++) { { - result = abs(2.0); + result = 2.0; continue; } } diff --git a/tests/sksl/shared/StaticSwitchWithContinue.metal b/tests/sksl/shared/StaticSwitchWithContinue.metal index cc1cf51f05..f422829288 100644 --- a/tests/sksl/shared/StaticSwitchWithContinue.metal +++ b/tests/sksl/shared/StaticSwitchWithContinue.metal @@ -17,7 +17,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo float result = 0.0; for (int x = 0;x <= 1; x++) { { - result = abs(2.0); + result = 2.0; continue; } } diff --git a/tests/sksl/spirv/ConstantVectorFromVector.asm.frag b/tests/sksl/spirv/ConstantVectorFromVector.asm.frag index 027c270889..678fa60ea0 100644 --- a/tests/sksl/spirv/ConstantVectorFromVector.asm.frag +++ b/tests/sksl/spirv/ConstantVectorFromVector.asm.frag @@ -10,7 +10,6 @@ OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %19 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -20,17 +19,13 @@ OpDecorate %19 RelaxedPrecision %sk_Clockwise = OpVariable %_ptr_Input_bool Input %void = OpTypeVoid %11 = OpTypeFunction %void +%float_0 = OpConstant %float 0 +%_ptr_Output_float = OpTypePointer Output %float %int = OpTypeInt 32 1 -%v2int = OpTypeVector %int 2 %int_0 = OpConstant %int 0 -%17 = OpConstantComposite %v2int %int_0 %int_0 -%_ptr_Output_float = OpTypePointer Output %float %main = OpFunction %void None %11 %12 = OpLabel -%13 = OpExtInst %v2int %1 SAbs %17 -%18 = OpCompositeExtract %int %13 0 -%19 = OpConvertSToF %float %18 -%20 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 -OpStore %20 %19 +%14 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 +OpStore %14 %float_0 OpReturn OpFunctionEnd diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp index b5efcad471..c4159c824a 100644 --- a/tools/gpu/GrContextFactory.cpp +++ b/tools/gpu/GrContextFactory.cpp @@ -189,7 +189,7 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv // using this backend. if (glCtx) { GrGLDriverInfo info = GrGLGetDriverInfo(glCtx->gl()); - if (info.fANGLEVendor == GrGLANGLEVendor::kNVIDIA) { + if (info.fANGLEVendor == GrGLVendor::kNVIDIA) { delete glCtx; return ContextInfo(); } |