Skip to content

Commit

Permalink
fix false application of color space conversion during compositing an…
Browse files Browse the repository at this point in the history
…d add time stemps to all render passes
  • Loading branch information
YoanWithY committed Sep 20, 2024
1 parent e3ff95a commit dee8569
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class HeightFieldPipeline extends AbstractPipeline {
this.preProzessedShaderCoder = resolveShader(this.shaderCode);
this.vertexConstants = {};
this.vertexBufferLayout = [];
this.fragmentConstants = project.getDisplayFragmentOutputConstantsCopy();
this.fragmentConstants = project.getDisplayFragmentOutputConstants();
this.topology = "triangle-strip";
this.cullMode = "none";
this.depthCompare = "less";
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/ts/project/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export class Project {
this.renderer.requestAnimationFrameWith(vp);
}

getDisplayFragmentOutputConstantsCopy(): Record<string, number> {
getTargetColorspaceConstants(): Record<string, number> {
return {
targetColorSpace: this.config.output.display.swapChainColorSpace == "srgb" ? 0 : 1,
};
}

getDisplayFragmentOutputConstants(): Record<string, number> {
return {
targetColorSpace: this.config.output.display.swapChainColorSpace == "srgb" ? 0 : 1,
componentTranfere: this.config.output.render.mode === "deferred" ? 0 : 1,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/rendering/CompositingPipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class CompositingPipeline extends AbstractPipeline {
this.preProzessedShaderCoder = resolveShader(this.shaderCode);
this.vertexConstants = {};
this.vertexBufferLayout = [];
this.fragmentConstants = project.getDisplayFragmentOutputConstantsCopy();
this.fragmentConstants = project.getTargetColorspaceConstants();
this.topology = "triangle-strip";
this.cullMode = "none";
this.depthCompare = "always";
Expand Down
72 changes: 39 additions & 33 deletions frontend/src/ts/rendering/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export default class Renderer {
},
]
});

this.bindGroupR3Layout = gpuDevice.createBindGroupLayout({
label: "Default R3 bind group layout",
entries: [
Expand All @@ -76,7 +75,6 @@ export default class Renderer {
},
]
});

this.compositingBindGroupLayout = gpuDevice.createBindGroupLayout({
label: "Compositing bind group layout",
entries: [
Expand Down Expand Up @@ -123,7 +121,6 @@ export default class Renderer {
},
]
});

this.bindGroup0 = gpuDevice.createBindGroup({
label: "Global default bind group 0",
entries: [
Expand Down Expand Up @@ -159,71 +156,80 @@ export default class Renderer {
endOfPassWriteIndex: 1
},
};
this.overlayRenderPassDescriptor = {
label: "Overlay Render Pass",
this.r16ResolveRenderPassDescriptor = {
label: "r16 Resolve Render Pass",
colorAttachments: [
{
loadOp: "clear",
storeOp: "store",
clearValue: [0, 0, 0, 0],
storeOp: "store",
view: null as unknown as GPUTextureView,
}
],
depthStencilAttachment: {
depthLoadOp: "load",
depthStoreOp: "discard",
view: null as unknown as GPUTextureView,
},
timestampWrites: {
querySet: null as unknown as GPUQuerySet,
beginningOfPassWriteIndex: 2,
endOfPassWriteIndex: 3
},
}
this.compositingRenderPassDescriptor = {
label: "Overlay Render Pass",
};
this.selectionRenderPassDescriptor = {
label: "Selection Render Pass",
colorAttachments: [
{
loadOp: "load",
loadOp: "clear",
storeOp: "store",
clearValue: [0, 0, 0, 0],
view: null as unknown as GPUTextureView,
}
],
depthStencilAttachment: {
depthLoadOp: "clear",
depthClearValue: 1.0,
depthStoreOp: "store",
view: null as unknown as GPUTextureView,
},
timestampWrites: {
querySet: null as unknown as GPUQuerySet,
beginningOfPassWriteIndex: 4,
endOfPassWriteIndex: 5
},
}
this.r16ResolveRenderPassDescriptor = {
label: "r16 Resolve Render Pass",
};
this.overlayRenderPassDescriptor = {
label: "Overlay Render Pass",
colorAttachments: [
{
loadOp: "clear",
clearValue: [0, 0, 0, 0],
storeOp: "store",
clearValue: [0, 0, 0, 0],
view: null as unknown as GPUTextureView,
}
],
depthStencilAttachment: {
depthLoadOp: "load",
depthStoreOp: "discard",
view: null as unknown as GPUTextureView,
},
timestampWrites: {
querySet: null as unknown as GPUQuerySet,
beginningOfPassWriteIndex: 6,
endOfPassWriteIndex: 7
},
}
this.selectionRenderPassDescriptor = {
label: "Selection Render Pass",
this.compositingRenderPassDescriptor = {
label: "Overlay Render Pass",
colorAttachments: [
{
loadOp: "clear",
loadOp: "load",
storeOp: "store",
clearValue: [0, 0, 0, 0],
view: null as unknown as GPUTextureView,
}
],
depthStencilAttachment: {
depthLoadOp: "clear",
depthClearValue: 1.0,
depthStoreOp: "store",
view: null as unknown as GPUTextureView,
}
}

timestampWrites: {
querySet: null as unknown as GPUQuerySet,
beginningOfPassWriteIndex: 8,
endOfPassWriteIndex: 9
},
};
}

reconfigureContext() {
Expand All @@ -234,7 +240,7 @@ export default class Renderer {
}

rebuildDisplayOutputPipelines() {
const outConsts = this.project.getDisplayFragmentOutputConstantsCopy();
const outConsts = this.project.getDisplayFragmentOutputConstants();
const format = this.project.getSwapChainFormat();
const msaa = (this.project.config.output.render as OutputForwardRenderConfig).msaa;
for (const hf of this.project.scene.heightFieldObjects) {
Expand Down Expand Up @@ -289,9 +295,9 @@ export default class Renderer {
const config = this.project.config.output.render as OutputForwardRenderConfig;
viewportCache.setupRenderPasses(
this.r3renderPassDescriptor,
this.overlayRenderPassDescriptor,
this.r16ResolveRenderPassDescriptor,
this.selectionRenderPassDescriptor,
this.overlayRenderPassDescriptor,
this.compositingRenderPassDescriptor,
config);

Expand Down
8 changes: 5 additions & 3 deletions frontend/src/ts/rendering/Shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import sRGB_OETF from "../../wgsl/utility/sRGB_OETF.wgsl?raw";
import fragmentOutput from "../../wgsl/utility/fragmentOutput.wgsl?raw";
import frame from "../../wgsl/utility/frame.wgsl?raw";
import fullScreenQuad from "../../wgsl/utility/fullScreenQuadVertex.wgsl?raw";
import targetColorSpace from "../../wgsl/utility/targetColorSpace.wgsl?raw";
import r3 from "../../wgsl/utility/r3.wgsl?raw";

const snippets: { [key: string]: string } = {
Expand All @@ -14,6 +15,7 @@ const snippets: { [key: string]: string } = {
"utility/frame": frame,
"utility/fullScreenQuadVertex": fullScreenQuad,
"utility/r3": r3,
"utility/targetColorSpace": targetColorSpace,
};

export function resolveIncludes(code: string): string {
Expand All @@ -27,13 +29,13 @@ export function resolveIncludes(code: string): string {
});
}

export function resolveVariables(code: string, map: {[key: string]: string}): string {
for(const key in map)
export function resolveVariables(code: string, map: { [key: string]: string }): string {
for (const key in map)
code = code.replaceAll(`#${key}`, map[key]);
return code;
}

export function resolveShader(code: string, map: {[key: string]: string} = {}): string {
export function resolveShader(code: string, map: { [key: string]: string } = {}): string {
return resolveVariables(resolveIncludes(code), map);
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/rendering/Viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface Viewport {
* This method recieves the GPU time spend the render passes on this viewport in nanoseconds.
* @param time The time spend in nanoseconds.
*/
setGPUTime(r3Time: number, overlayTime: number, compositingTime: number): void;
setGPUTime(r3Time: number, r16ResolveTime: number, selectionTime: number, overlayTime: number, compositingTime: number): void;
/**
* @param viewUBO The buffer to write to.
* @param frame The current frame time to upload.
Expand Down
32 changes: 23 additions & 9 deletions frontend/src/ts/rendering/ViewportCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ export class ViewportCache {
this.querySet = gpuDevice.createQuerySet({
label: `time stamp query set for ${viewport.lable}`,
type: 'timestamp',
count: 6,
count: 10,
});
this.timeStempBufferResolve = gpuDevice.createBuffer({
label: `time stemp querey resolve buffer for ${viewport.lable}`,
size: this.querySet.count * 8,
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE,
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.QUERY_RESOLVE,
});

this.timeStempMapBuffer = gpuDevice.createBuffer({
Expand Down Expand Up @@ -237,9 +237,9 @@ export class ViewportCache {

public setupRenderPasses(
r3renderPassDescriptor: GPURenderPassDescriptor,
overlayRenderPassDescriptor: GPURenderPassDescriptor,
r16ResolveRenderPassDescriptor: GPURenderPassDescriptor,
selectionRenderPassDescriptor: GPURenderPassDescriptor,
overlayRenderPassDescriptor: GPURenderPassDescriptor,
compositingRenderPassDescriptor: GPURenderPassDescriptor,
config: OutputForwardRenderConfig) {
const colorAttachment = getElement(r3renderPassDescriptor.colorAttachments, 0);
Expand Down Expand Up @@ -334,12 +334,16 @@ export class ViewportCache {
}

const r3TimestampWrites = r3renderPassDescriptor.timestampWrites;
const r16ResolveTimestampWrites = r16ResolveRenderPassDescriptor.timestampWrites;
const selectionTimestampWrites = selectionRenderPassDescriptor.timestampWrites;
const overlayTimestampWrites = overlayRenderPassDescriptor.timestampWrites;
const compositingTimestampWrites = compositingRenderPassDescriptor.timestampWrites;
if (r3TimestampWrites && overlayTimestampWrites && compositingTimestampWrites) {
if (r3TimestampWrites && overlayTimestampWrites && compositingTimestampWrites && r16ResolveTimestampWrites && selectionTimestampWrites) {
r3TimestampWrites.querySet = this.querySet;
r16ResolveTimestampWrites.querySet = this.querySet;
overlayTimestampWrites.querySet = this.querySet;
compositingTimestampWrites.querySet = this.querySet;
selectionTimestampWrites.querySet = this.querySet;
}
}

Expand All @@ -352,17 +356,27 @@ export class ViewportCache {
this.timeStempBufferResolve.size);
}
}

private resetBuffer = new BigInt64Array(10);
public asyncGPUPerformanceUpdate() {
if (this.timeStempMapBuffer.mapState === "unmapped") {
this.timeStempMapBuffer.mapAsync(GPUMapMode.READ).then(() => {
const times = new BigInt64Array(this.timeStempMapBuffer.getMappedRange());
const r3Time = Number(times[1] - times[0]);
const overlayTime = Number(times[3] - times[2]);
const compositingTime = Number(times[5] - times[4]);
// console.log(r3Time / 1000000, overlayTime / 1000000, compositingTime / 1000000);
const r16Time = Number(times[3] - times[2]);
const selectionTime = Number(times[5] - times[4]);
const overlayTime = Number(times[7] - times[6]);
const compositingTime = Number(times[9] - times[8]);
// console.log(
// "R3:", r3Time / 1000000,
// "R16 Resolve:", r16Time / 1000000,
// "Selection", selectionTime / 1000000,
// "Overlay", overlayTime / 1000000,
// "Compositing", compositingTime / 1000000,
// "total:", (r3Time + r16Time + selectionTime + overlayTime + compositingTime) / 1000000);

this.timeStempMapBuffer.unmap();
this.viewport.setGPUTime(r3Time, overlayTime, compositingTime);
gpuDevice.queue.writeBuffer(this.timeStempBufferResolve, 0, this.resetBuffer, 0, this.resetBuffer.length)
this.viewport.setGPUTime(r3Time, r16Time, selectionTime, overlayTime, compositingTime);
});
}
}
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/ts/ui/panes/ViewportPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,12 @@ export class ViewportPane extends HTMLElement implements Viewport {
return this.canvasContext.getCurrentTexture();
}

setGPUTime(r3Time: number, overlayTime: number): void {
setGPUTime(r3Time: number, r16ResolveTime: number, selectionTime: number, overlayTime: number, compositingTime: number): void {
r3Time;
r16ResolveTime;
selectionTime;
overlayTime;
compositingTime;
}

connectedCallback() {
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/wgsl/compositing.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
@group(0) @binding(1) var idRT: texture_2d<u32>;
@group(0) @binding(2) var selectionRT: texture_2d<u32>;

#include <utility/fragmentOutput>
#include <utility/targetColorSpace>

const searchSize = 1;
const searchSize = 2;
const edgeColorArray: array<vec4f, 3> = array<vec4f, 3>(
vec4f(0.0, 0.0, 0.0, 0.2),
vec4f(0.93, 0.34, 0.0, 1.0),
Expand All @@ -18,13 +18,15 @@ fn selectionOverlay(tc: vec2i) -> vec4f {
var maxSelection = thisSelection;
var idChange = false;
var selectionChange = false;
let texSize = vec2i(textureDimensions(idRT, 0));
for(var y = -searchSize; y <= searchSize; y += searchSize) {
for(var x = -searchSize; x <= searchSize; x += searchSize) {
if(x == 0 && y == 0) {
let tcS = tc + vec2i(x, y);
if((x == 0 && y == 0) || tcS.x < 0 || tcS.y < 0 || tcS.x >= texSize.x || tcS.y >= texSize.y) {
continue;
}
let val = textureLoad(idRT, tc + vec2i(x, y), 0).x;
let selection = textureLoad(selectionRT, tc + vec2i(x, y), 0).x;
let val = textureLoad(idRT, tcS, 0).x;
let selection = textureLoad(selectionRT, tcS, 0).x;
maxSelection = max(maxSelection, selection);
idChange |= val != thisID;
selectionChange |= selection != thisSelection;
Expand Down Expand Up @@ -55,6 +57,6 @@ fn fragment_main(@builtin(position) position: vec4f) -> @location(0) vec4f {
let tc = vec2i(position.xy);
let overlay = textureLoad(overlayRT, tc, 0);
let selection = selectionOverlay(tc);
let color = createOutputFragment(mix(overlay.rgb, selection.rgb, selection.a));
let color = convertToTargetColorSpace(select(overlay.rgb, selection.rgb, selection.a > 0.0));
return vec4f(color, max(overlay.a, selection.a));
}
4 changes: 2 additions & 2 deletions frontend/src/wgsl/debug/grid.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ fn fragment_main(vertexData: VertexOut) -> @location(0) vec4f {
if(a <= 0) {
discard;
}
var color = vec3f(0.2);
var color = vec3f(0.3);

if(a1000 > 0) {
let abs_ws_pos = abs(ws_pos);
let isXAxis = abs_ws_pos.x < 500 && g1000_2D.x >= g1000_2D.y;
let isYAxis = abs_ws_pos.y < 500 && g1000_2D.y >= g1000_2D.x;

if(isXAxis && isYAxis) {
color = vec3f(0.1);
color = vec3f(0.5);
} else if(isXAxis) {
color = vec3f(1.0, 0.2, 0.2);
} else if(isYAxis) {
Expand Down
11 changes: 1 addition & 10 deletions frontend/src/wgsl/utility/fragmentOutput.wgsl
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
#include <utility/linearRGBToLinearDisplayP3>
#include <utility/targetColorSpace>
#include <utility/sRGB_EOTF>
#include <utility/sRGB_OETF>

override targetColorSpace: i32; // 0: sRGB; 1: Display-P3
override componentTranfere: i32; // 0: none; 1: sRGB

fn convertToTargetColorSpace(linearRGB: vec3f) -> vec3f {
if(targetColorSpace == 1) {
return linearRGBToLinearDisplayP3(linearRGB);
}
return linearRGB;
}

fn createOutputFragment(linearRGB: vec3f) -> vec3f {
var color = convertToTargetColorSpace(linearRGB);
if(componentTranfere == 1) {
Expand Down
Loading

0 comments on commit dee8569

Please sign in to comment.