wg_engine: render buffers usage refactorings

[issues 1479: strokes](#1479)

- update buffers via memory mapping
- refactoring of winding fill rule computation
This commit is contained in:
Sergii Liebodkin 2024-03-27 18:00:14 +02:00 committed by Hermet Park
parent 736a79674b
commit fafec9fa46
5 changed files with 72 additions and 72 deletions

View file

@ -204,6 +204,30 @@ WGPUBuffer WgContext::createBuffer(WGPUBufferUsageFlags usage, uint64_t size,cha
}
void WgContext::createOrUpdateBuffer(WGPUBuffer& buffer, WGPUBufferUsageFlags usage, const void *data, uint64_t size, char const * label)
{
if ((buffer) && (wgpuBufferGetSize(buffer) >= size)) {
// update data in existing buffer
wgpuQueueWriteBuffer(queue, buffer, 0, data, size);
} else {
// create new buffer and upload data
releaseBuffer(buffer);
WGPUBufferDescriptor bufferDesc{};
bufferDesc.nextInChain = nullptr;
bufferDesc.label = label;
bufferDesc.usage = usage;
bufferDesc.size = size;
bufferDesc.mappedAtCreation = true;
buffer = wgpuDeviceCreateBuffer(device, &bufferDesc);
assert(buffer);
void* buff = wgpuBufferGetMappedRange(buffer, 0, size);
assert(buff);
memcpy(buff, data, size);
wgpuBufferUnmap(buffer);
}
}
void WgContext::releaseSampler(WGPUSampler& sampler)
{
if (sampler) {

View file

@ -54,7 +54,8 @@ struct WgContext {
WGPUTexture createTexture2d(WGPUTextureUsageFlags usage, WGPUTextureFormat format, uint32_t width, uint32_t height, char const * label);
WGPUTexture createTexture2dMS(WGPUTextureUsageFlags usage, WGPUTextureFormat format, uint32_t width, uint32_t height, uint32_t sc, char const * label);
WGPUTextureView createTextureView2d(WGPUTexture texture, char const * label);
WGPUBuffer createBuffer(WGPUBufferUsageFlags usage, uint64_t size,char const * label);
WGPUBuffer createBuffer(WGPUBufferUsageFlags usage, uint64_t size, char const * label);
void createOrUpdateBuffer(WGPUBuffer& buffer, WGPUBufferUsageFlags usage, const void *data, uint64_t size, char const * label);
void releaseSampler(WGPUSampler& sampler);
void releaseTexture(WGPUTexture& texture);

View file

@ -60,19 +60,10 @@ void WgGeometryData::computeContour(WgGeometryData* data)
isIntersected = true;
p0 = pi;
// operate intersection point
if (isClockWise) { // clock wise behavior
if (isCW(p0, pi, data->positions[ii])) {
inext = ii;
} else {
inext = ((ii + 1) % icnt);
}
} else { // contr-clock wise behavior
if (isCW(p0, pi, data->positions[ii])) {
inext = ((ii + 1) % icnt);
} else {
inext = ii;
}
}
if (isClockWise) // clock wise behavior
inext = isCW(p0, pi, data->positions[ii]) ? ii : ((ii + 1) % icnt);
else // contr-clock wise behavior
inext = isCW(p0, pi, data->positions[ii]) ? ((ii + 1) % icnt) : ii;
} else { // simple next point
isIntersected = false;
p0 = data->positions[inext];
@ -352,7 +343,16 @@ void WgGeometryDataGroup::getBBox(WgPoint& pmin, WgPoint& pmax) {
void WgGeometryDataGroup::tesselate(const RenderShape& rshape)
{
decodePath(rshape, this);
// windiwg fill rule
if (rshape.rule == FillRule::Winding) {
WgGeometryDataGroup polylines{};
decodePath(rshape, &polylines);
contourPolyline(&polylines, this);
} else // even-odd fill rule
if (rshape.rule == FillRule::EvenOdd) {
decodePath(rshape, this);
}
// update triangle fans indexes
for (uint32_t i = 0; i < geometries.count; i++)
geometries[i]->computeTriFansIndexes();
}
@ -390,16 +390,6 @@ void WgGeometryDataGroup::stroke(const RenderShape& rshape)
}
void WgGeometryDataGroup::contours(WgGeometryDataGroup& outlines)
{
for (uint32_t i = 0 ; i < outlines.geometries.count; i++) {
WgGeometryData* geometry = new WgGeometryData();
geometry->computeContour(outlines.geometries[i]);
geometry->computeTriFansIndexes();
this->geometries.push(geometry);
}
}
void WgGeometryDataGroup::release()
{
for (uint32_t i = 0; i < geometries.count; i++)
@ -441,6 +431,18 @@ void WgGeometryDataGroup::decodePath(const RenderShape& rshape, WgGeometryDataGr
}
void WgGeometryDataGroup::contourPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* contours)
{
assert(polyline);
assert(contours);
for (uint32_t i = 0 ; i < polyline->geometries.count; i++) {
WgGeometryData* geometry = new WgGeometryData();
geometry->computeContour(polyline->geometries[i]);
contours->geometries.push(geometry);
}
}
void WgGeometryDataGroup::trimPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* trimmed, RenderStroke *stroke)
{
assert(stroke);

View file

@ -117,10 +117,10 @@ struct WgGeometryDataGroup
void getBBox(WgPoint& pmin, WgPoint& pmax);
void tesselate(const RenderShape& rshape);
void stroke(const RenderShape& rshape);
void contours(WgGeometryDataGroup& outlines);
void release();
private:
static void decodePath(const RenderShape& rshape, WgGeometryDataGroup* polyline);
static void contourPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* contours);
static void trimPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* trimmed, RenderStroke *stroke);
static void splitPolyline(WgGeometryDataGroup* polyline, WgGeometryDataGroup* splitted, RenderStroke *stroke);
static void strokePolyline(WgGeometryDataGroup* polyline, WgGeometryData* strokes, RenderStroke *stroke);

View file

@ -49,47 +49,26 @@ void WgMeshData::drawImage(WGPURenderPassEncoder renderPassEncoder)
void WgMeshData::update(WgContext& context, WgGeometryData* geometryData){
assert(geometryData);
vertexCount = geometryData->positions.count;
indexCount = geometryData->indexes.count;
// buffer position data create and write
if(geometryData->positions.count > 0) {
vertexCount = geometryData->positions.count;
if (bufferPosition && (wgpuBufferGetSize(bufferPosition) < sizeof(float) * vertexCount * 2))
context.releaseBuffer(bufferPosition);
if (!bufferPosition) {
bufferPosition = context.createBuffer(
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
sizeof(float) * vertexCount * 2,
"Buffer position geometry data");
}
assert(bufferPosition);
wgpuQueueWriteBuffer(context.queue, bufferPosition, 0, &geometryData->positions[0], vertexCount * sizeof(float) * 2);
}
// buffer vertex data create and write
if(geometryData->texCoords.count > 0) {
if (bufferTexCoord && (wgpuBufferGetSize(bufferTexCoord) < sizeof(float) * vertexCount * 2))
context.releaseBuffer(bufferTexCoord);
if (!bufferTexCoord) {
bufferTexCoord = context.createBuffer(
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
sizeof(float) * vertexCount * 2,
"Buffer tex coords geometry data");
}
assert(bufferTexCoord);
wgpuQueueWriteBuffer(context.queue, bufferTexCoord, 0, &geometryData->texCoords[0], vertexCount * sizeof(float) * 2);
}
if (geometryData->positions.count > 0)
context.createOrUpdateBuffer(
bufferPosition, WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
&geometryData->positions[0], vertexCount * sizeof(float) * 2,
"Buffer position geometry data");
// buffer tex coords data create and write
if (geometryData->texCoords.count > 0)
context.createOrUpdateBuffer(
bufferTexCoord, WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
&geometryData->texCoords[0], vertexCount * sizeof(float) * 2,
"Buffer tex coords geometry data");
// buffer index data create and write
if(geometryData->indexes.count > 0) {
indexCount = geometryData->indexes.count;
if (bufferIndex && (wgpuBufferGetSize(bufferIndex) < sizeof(uint32_t) * indexCount))
context.releaseBuffer(bufferIndex);
if (!bufferIndex) {
bufferIndex = context.createBuffer(
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
sizeof(uint32_t) * indexCount,
"Buffer index geometry data");
}
assert(bufferIndex);
wgpuQueueWriteBuffer(context.queue, bufferIndex, 0, &geometryData->indexes[0], indexCount * sizeof(uint32_t));
}
if (geometryData->indexes.count > 0)
context.createOrUpdateBuffer(
bufferIndex, WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
&geometryData->indexes[0], indexCount * sizeof(uint32_t),
"Buffer index geometry data");
};
@ -217,13 +196,7 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha
strokeFirst = false;
// update shapes geometry
WgGeometryDataGroup shapes;
if(rshape.rule == tvg::FillRule::EvenOdd) {
shapes.tesselate(rshape);
} else if(rshape.rule == tvg::FillRule::Winding) {
WgGeometryDataGroup lines;
lines.tesselate(rshape);
shapes.contours(lines);
}
shapes.tesselate(rshape);
meshGroupShapes.update(context, &shapes);
// update shapes bbox
WgPoint pmin{}, pmax{};