gpu: [compute] pre-transform images before rendering

We're about to change the last stage of the compute pipeline to only
accept images, not sampled textures. This change prepares materials
for pixel-aligned image copying by pre-rendering images to a texture,
applying transforms.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-02-08 17:35:31 +01:00
parent 87ffaaf8c4
commit c9a8265126
13 changed files with 533 additions and 241 deletions
+36 -40
View File
@@ -8,9 +8,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#ifdef VULKAN
#extension GL_EXT_nonuniform_qualifier : enable
#endif
#include "mem.h"
#include "setup.h"
@@ -25,10 +23,10 @@ layout(set = 0, binding = 1) readonly buffer ConfigBuf {
layout(rgba8, set = 0, binding = 2) uniform writeonly image2D image;
#ifdef VULKAN
layout(set = 0, binding = 3) uniform sampler2D textures[];
#if GL_EXT_nonuniform_qualifier
layout(rgba8, set = 0, binding = 3) uniform readonly image2D images[];
#else
layout(set = 0, binding = 3) uniform sampler2D atlas;
layout(rgba8, set = 0, binding = 3) uniform readonly image2D images[1];
#endif
#include "ptcl.h"
@@ -92,25 +90,6 @@ float[CHUNK] computeArea(vec2 xy, int backdrop, uint tile_ref) {
return area;
}
vec4[CHUNK] fillTexture(vec2 xy, CmdSolidTexture cmd_tex) {
vec2 uvmin = unpackUnorm2x16(cmd_tex.uv_bounds.x);
vec2 uvmax = unpackUnorm2x16(cmd_tex.uv_bounds.y);
vec4 rgba[CHUNK];
for (uint i = 0; i < CHUNK; i++) {
float dy = float(i * CHUNK_DY);
vec2 uv = vec2(xy.x, xy.y + dy) + vec2(0.5, 0.5);
uv = cmd_tex.mat.xy * uv.x + cmd_tex.mat.zw * uv.y + cmd_tex.translate;
uv = clamp(uv, uvmin, uvmax);
#ifdef VULKAN
vec4 fg_rgba = textureGrad(textures[0], uv, cmd_tex.mat.xy, cmd_tex.mat.zw);
#else
vec4 fg_rgba = textureGrad(atlas, uv, cmd_tex.mat.xy, cmd_tex.mat.zw);
#endif
rgba[i] = fg_rgba;
}
return rgba;
}
vec3 tosRGB(vec3 rgb) {
bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308));
vec3 below = vec3(12.92)*rgb;
@@ -118,17 +97,19 @@ vec3 tosRGB(vec3 rgb) {
return mix(below, above, cutoff);
}
vec3 fromsRGB(vec3 srgb) {
// Formula from EXT_sRGB.
bvec3 cutoff = greaterThanEqual(srgb, vec3(0.04045));
vec3 below = srgb/vec3(12.92);
vec3 above = pow((srgb + vec3(0.055))/vec3(1.055), vec3(2.4));
return mix(below, above, cutoff);
}
// unpacksRGB unpacks a color in the sRGB color space to a vec4 in the linear color
// space.
vec4 unpacksRGB(uint srgba) {
vec4 color = unpackUnorm4x8(srgba).wzyx;
// Formula from EXT_sRGB.
vec3 rgb = color.rgb;
bvec3 cutoff = greaterThanEqual(rgb, vec3(0.04045));
vec3 below = rgb/vec3(12.92);
vec3 above = pow((rgb + vec3(0.055))/vec3(1.055), vec3(2.4));
rgb = mix(below, above, cutoff);
return vec4(rgb, color.a);
return vec4(fromsRGB(color.rgb), color.a);
}
// packsRGB packs a color in the linear color space into its 8-bit sRGB equivalent.
@@ -137,6 +118,21 @@ uint packsRGB(vec4 rgba) {
return packUnorm4x8(rgba.wzyx);
}
vec4[CHUNK] fillImage(uvec2 xy, CmdSolidImage cmd_img) {
vec4 rgba[CHUNK];
for (uint i = 0; i < CHUNK; i++) {
ivec2 uv = ivec2(xy.x, xy.y + i * CHUNK_DY) + cmd_img.offset;
#ifdef ENABLE_IMAGE_INDICES
vec4 fg_rgba = imageLoad(images[cmd_img.index], uv);
#else
vec4 fg_rgba = imageLoad(images[0], uv);
#endif
fg_rgba.rgb = fromsRGB(fg_rgba.rgb);
rgba[i] = fg_rgba;
}
return rgba;
}
void main() {
if (mem_error != NO_ERROR) {
return;
@@ -156,9 +152,9 @@ void main() {
Alloc clip_tos = new_alloc(0, 0);
for (uint i = 0; i < CHUNK; i++) {
rgb[i] = vec3(0.5);
#ifdef VULKAN
#ifdef ENABLE_IMAGE_INDICES
if (xy_uint.x < 1024 && xy_uint.y < 1024) {
rgb[i] = texture(textures[gl_WorkGroupID.x / 64], vec2(xy_uint.x, xy_uint.y + CHUNK_DY * i) / 1024.0).rgb;
rgb[i] = imageLoad(images[gl_WorkGroupID.x / 64], ivec2(xy_uint.x, xy_uint.y + CHUNK_DY * i)/4).rgb;
}
#endif
mask[i] = 1.0;
@@ -212,10 +208,10 @@ void main() {
rgb[k] = mix(rgb[k], fg_rgba.rgb, mask[k] * area[k] * fg_rgba.a);
}
break;
case Cmd_FillTexture:
CmdFillTexture fill_tex = Cmd_FillTexture_read(cmd_alloc, cmd_ref);
area = computeArea(xy, fill_tex.backdrop, fill_tex.tile_ref);
vec4 rgba[CHUNK] = fillTexture(xy, CmdSolidTexture(fill_tex.mat, fill_tex.translate, fill_tex.uv_bounds));
case Cmd_FillImage:
CmdFillImage fill_img = Cmd_FillImage_read(cmd_alloc, cmd_ref);
area = computeArea(xy, fill_img.backdrop, fill_img.tile_ref);
vec4 rgba[CHUNK] = fillImage(xy_uint, CmdSolidImage(fill_img.index, fill_img.offset));
for (uint k = 0; k < CHUNK; k++) {
rgb[k] = mix(rgb[k], rgba[k].rgb, mask[k] * area[k] * rgba[k].a);
}
@@ -275,9 +271,9 @@ void main() {
rgb[k] = mix(rgb[k], fg_rgba.rgb, mask[k] * fg_rgba.a);
}
break;
case Cmd_SolidTexture:
CmdSolidTexture solid_tex = Cmd_SolidTexture_read(cmd_alloc, cmd_ref);
rgba = fillTexture(xy, solid_tex);
case Cmd_SolidImage:
CmdSolidImage solid_img = Cmd_SolidImage_read(cmd_alloc, cmd_ref);
rgba = fillImage(xy_uint, solid_img);
for (uint k = 0; k < CHUNK; k++) {
rgb[k] = mix(rgb[k], rgba[k].rgb, mask[k] * rgba[k].a);
}