Compare commits
2 Commits
kpiascik/c
...
idris/rend
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ff62402c2 | ||
|
|
595a313686 |
@@ -464,13 +464,21 @@ void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
|
||||
uint32_t height, uint64_t flags) {}
|
||||
|
||||
void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes) {}
|
||||
uint8_t attributeCount, AttributeArray attributes) {
|
||||
constructHandle<WGPUVertexBufferInfo>(vbih, bufferCount, attributeCount, attributes);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh, uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih) {}
|
||||
Handle<HwVertexBufferInfo> vbih) {
|
||||
auto* vertexBufferInfo = handleCast<WGPUVertexBufferInfo>(vbih);
|
||||
constructHandle<WGPUVertexBuffer>(vbh, mDevice, vertexCount,vertexBufferInfo->bufferCount, vbih);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage) {}
|
||||
uint32_t indexCount, BufferUsage usage) {
|
||||
auto elementSize = (uint8_t)getElementTypeSize(elementType);
|
||||
constructHandle<WGPUIndexBuffer>(ibh, mDevice, elementSize, indexCount);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage) {}
|
||||
@@ -503,7 +511,18 @@ void WebGPUDriver::importTextureR(Handle<HwTexture> th, intptr_t id, SamplerType
|
||||
uint32_t depth, TextureUsage usage) {}
|
||||
|
||||
void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph, Handle<HwVertexBuffer> vbh,
|
||||
Handle<HwIndexBuffer> ibh, PrimitiveType pt) {}
|
||||
Handle<HwIndexBuffer> ibh, PrimitiveType pt) {
|
||||
assert_invariant(mDevice);
|
||||
|
||||
auto* renderPrimitive = handleCast<WGPURenderPrimitive>(rph);
|
||||
auto* vertexBuffer = handleCast<WGPUVertexBuffer>(vbh);
|
||||
auto* indexBuffer = handleCast<WGPUIndexBuffer>(ibh);
|
||||
// auto* vertexBufferInfo = handleCast<WGPUVertexBufferInfo>(vertexBuffer->vbih);
|
||||
// renderPrimitive->setBuffers(vertexBufferInfo, vertexBuffer, indexBuffer);
|
||||
renderPrimitive->vertexBuffer = vertexBuffer;
|
||||
renderPrimitive->indexBuffer = indexBuffer;
|
||||
renderPrimitive->type = pt;
|
||||
}
|
||||
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {}
|
||||
|
||||
@@ -715,6 +734,7 @@ void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
};
|
||||
mCommandEncoder = mDevice.CreateCommandEncoder(&commandEncoderDescriptor);
|
||||
assert_invariant(mCommandEncoder);
|
||||
|
||||
// TODO: Remove this code once WebGPU pipeline is implemented
|
||||
static float red = 1.0f;
|
||||
if (red - 0.01 > 0) {
|
||||
@@ -828,6 +848,70 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
// VulkanCommandBuffer* commands = mCurrentRenderPass.commandBuffer;
|
||||
// VkCommandBuffer cmdbuffer = commands->buffer();
|
||||
// auto prim = resource_ptr<VulkanRenderPrimitive>::cast(&mResourceManager, rph);
|
||||
auto* renderPrimitive = handleCast<WGPURenderPrimitive>(rph);
|
||||
// commands->acquire(prim);
|
||||
|
||||
// This *must* match the VulkanVertexBufferInfo that was bound in bindPipeline(). But we want
|
||||
// to allow to call this before bindPipeline(), so the validation can only happen in draw()
|
||||
auto vbi = handleCast<WGPUVertexBufferInfo>(renderPrimitive->vertexBuffer->vbih);
|
||||
(void) vbi;
|
||||
|
||||
// mRenderPassEncoder.SetVertexBuffer(uint32_t slot, Buffer const& buffer = nullptr, uint64_t offset = 0, uint64_t size = kWholeSize);
|
||||
mRenderPassEncoder.SetIndexBuffer(renderPrimitive->indexBuffer->buffer, renderPrimitive->indexBuffer->indexFormat);
|
||||
|
||||
// uint32_t const bufferCount = vbi->getAttributeCount();
|
||||
// VkDeviceSize const* offsets = vbi->getOffsets();
|
||||
// VkBuffer const* buffers = prim->vertexBuffer->getVkBuffers();
|
||||
//
|
||||
// // Next bind the vertex buffers and index buffer. One potential performance improvement is to
|
||||
// // avoid rebinding these if they are already bound, but since we do not (yet) support subranges
|
||||
// // it would be rare for a client to make consecutive draw calls with the same render primitive.
|
||||
// vkCmdBindVertexBuffers(cmdbuffer, 0, bufferCount, buffers, offsets);
|
||||
// vkCmdBindIndexBuffer(cmdbuffer, prim->indexBuffer->buffer.getGpuBuffer(), 0,
|
||||
// prim->indexBuffer->indexType);
|
||||
|
||||
|
||||
// METAL
|
||||
// if (UTILS_UNLIKELY(mContext->currentRenderPassAbandoned)) {
|
||||
// return;
|
||||
// }
|
||||
// FILAMENT_CHECK_PRECONDITION(mContext->currentRenderPassEncoder != nullptr)
|
||||
// << "bindRenderPrimitive() without a valid command encoder.";
|
||||
//
|
||||
// // Bind the user vertex buffers.
|
||||
// MetalBuffer* vertexBuffers[MAX_VERTEX_BUFFER_COUNT] = {};
|
||||
// size_t vertexBufferOffsets[MAX_VERTEX_BUFFER_COUNT] = {};
|
||||
// size_t maxBufferIndex = 0;
|
||||
//
|
||||
// MetalRenderPrimitive const* const primitive = handle_cast<MetalRenderPrimitive>(rph);
|
||||
// MetalVertexBufferInfo const* const vbi =
|
||||
// handle_cast<MetalVertexBufferInfo>(primitive->vertexBuffer->vbih);
|
||||
//
|
||||
// mContext->currentRenderPrimitive = rph;
|
||||
//
|
||||
// auto vb = primitive->vertexBuffer;
|
||||
// for (auto m : vbi->bufferMapping) {
|
||||
// assert_invariant(
|
||||
// m.bufferArgumentIndex >= USER_VERTEX_BUFFER_BINDING_START &&
|
||||
// m.bufferArgumentIndex < USER_VERTEX_BUFFER_BINDING_START + MAX_VERTEX_BUFFER_COUNT);
|
||||
// size_t const vertexBufferIndex = m.bufferArgumentIndex - USER_VERTEX_BUFFER_BINDING_START;
|
||||
// vertexBuffers[vertexBufferIndex] = vb->buffers[m.sourceBufferIndex];
|
||||
// maxBufferIndex = std::max(maxBufferIndex, vertexBufferIndex);
|
||||
// }
|
||||
//
|
||||
// const auto bufferCount = maxBufferIndex + 1;
|
||||
// MetalBuffer::bindBuffers(getPendingCommandBuffer(mContext), mContext->currentRenderPassEncoder,
|
||||
// USER_VERTEX_BUFFER_BINDING_START, MetalBuffer::Stage::VERTEX, vertexBuffers,
|
||||
// vertexBufferOffsets, bufferCount);
|
||||
//
|
||||
// // Bind the zero buffer, used for missing vertex attributes.
|
||||
// static const char bytes[16] = { 0 };
|
||||
// [mContext->currentRenderPassEncoder setVertexBytes:bytes
|
||||
// length:16
|
||||
// atIndex:ZERO_VERTEX_BUFFER_BINDING];
|
||||
}
|
||||
|
||||
void WebGPUDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
|
||||
|
||||
@@ -112,7 +112,7 @@ private:
|
||||
template<typename D, typename B>
|
||||
void destructHandle(Handle<B>& handle) noexcept {
|
||||
auto* p = mHandleAllocator.handle_cast<D*>(handle);
|
||||
return mHandleAllocator.deallocate(handle, p);
|
||||
mHandleAllocator.deallocate(handle, p);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,18 +27,126 @@ wgpu::Buffer createIndexBuffer(wgpu::Device const& device, uint8_t elementSize,
|
||||
.mappedAtCreation = false };
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::VertexFormat getVertexFormat(filament::backend::ElementType type, bool normalized, bool integer) {
|
||||
using ElementType = filament::backend::ElementType;
|
||||
// using VertexFormat = wgpu::VertexFormat;
|
||||
if (normalized) {
|
||||
switch (type) {
|
||||
// Single Component Types
|
||||
case ElementType::BYTE: return wgpu::VertexFormat::Snorm8;
|
||||
case ElementType::UBYTE: return wgpu::VertexFormat::Unorm8;
|
||||
case ElementType::SHORT: return wgpu::VertexFormat::Snorm16;
|
||||
case ElementType::USHORT: return wgpu::VertexFormat::Unorm16;
|
||||
// Two Component Types
|
||||
case ElementType::BYTE2: return wgpu::VertexFormat::Snorm8x2;
|
||||
case ElementType::UBYTE2: return wgpu::VertexFormat::Unorm8x2;
|
||||
case ElementType::SHORT2: return wgpu::VertexFormat::Snorm16x2;
|
||||
case ElementType::USHORT2: return wgpu::VertexFormat::Unorm16x2;
|
||||
// Three Component Types
|
||||
// There is no vertex format type for 3 byte data in webgpu. Use
|
||||
// 4 byte signed normalized type and ignore the last byte.
|
||||
// TODO: This is to be verified.
|
||||
case ElementType::BYTE3: return wgpu::VertexFormat::Snorm8x4; // NOT MINSPEC
|
||||
case ElementType::UBYTE3: return wgpu::VertexFormat::Unorm8x4; // NOT MINSPEC
|
||||
case ElementType::SHORT3: return wgpu::VertexFormat::Snorm16x4; // NOT MINSPEC
|
||||
case ElementType::USHORT3: return wgpu::VertexFormat::Unorm16x4; // NOT MINSPEC
|
||||
// Four Component Types
|
||||
case ElementType::BYTE4: return wgpu::VertexFormat::Snorm8x4;
|
||||
case ElementType::UBYTE4: return wgpu::VertexFormat::Unorm8x4;
|
||||
case ElementType::SHORT4: return wgpu::VertexFormat::Snorm16x4;
|
||||
case ElementType::USHORT4: return wgpu::VertexFormat::Unorm8x4;
|
||||
default:
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Normalized format does not exist.";
|
||||
return wgpu::VertexFormat::Float32x3;
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
// Single Component Types
|
||||
// There is no direct alternative for SSCALED in webgpu. Convert them to Float32 directly.
|
||||
// This will result in increased memory on the cpu side.
|
||||
// TODO: Is Float16 acceptable instead with some potential accuracy errors?
|
||||
case ElementType::BYTE: return integer ? wgpu::VertexFormat::Sint8 : wgpu::VertexFormat::Float32;
|
||||
case ElementType::UBYTE: return integer ? wgpu::VertexFormat::Uint8 : wgpu::VertexFormat::Float32;
|
||||
case ElementType::SHORT: return integer ? wgpu::VertexFormat::Sint16 : wgpu::VertexFormat::Float32;
|
||||
case ElementType::USHORT: return integer ? wgpu::VertexFormat::Uint16 : wgpu::VertexFormat::Float32;
|
||||
case ElementType::HALF: return wgpu::VertexFormat::Float16;
|
||||
case ElementType::INT: return wgpu::VertexFormat::Sint32;
|
||||
case ElementType::UINT: return wgpu::VertexFormat::Uint32;
|
||||
case ElementType::FLOAT: return wgpu::VertexFormat::Float32;
|
||||
// Two Component Types
|
||||
case ElementType::BYTE2: return integer ? wgpu::VertexFormat::Sint8x2 : wgpu::VertexFormat::Float32x2;
|
||||
case ElementType::UBYTE2: return integer ? wgpu::VertexFormat::Uint8x2 : wgpu::VertexFormat::Float32x2;
|
||||
case ElementType::SHORT2: return integer ? wgpu::VertexFormat::Sint16x2 : wgpu::VertexFormat::Float32x2;
|
||||
case ElementType::USHORT2: return integer ? wgpu::VertexFormat::Uint16x2 : wgpu::VertexFormat::Float32x2;
|
||||
case ElementType::HALF2: return wgpu::VertexFormat::Float16x2;
|
||||
case ElementType::FLOAT2: return wgpu::VertexFormat::Float32x2;
|
||||
// Three Component Types
|
||||
case ElementType::BYTE3: return wgpu::VertexFormat::Sint8x4; // NOT MINSPEC
|
||||
case ElementType::UBYTE3: return wgpu::VertexFormat::Uint8x4; // NOT MINSPEC
|
||||
case ElementType::SHORT3: return wgpu::VertexFormat::Sint16x4; // NOT MINSPEC
|
||||
case ElementType::USHORT3: return wgpu::VertexFormat::Uint16x4; // NOT MINSPEC
|
||||
case ElementType::HALF3: return wgpu::VertexFormat::Float16x4; // NOT MINSPEC
|
||||
case ElementType::FLOAT3: return wgpu::VertexFormat::Float32x3;
|
||||
// Four Component Types
|
||||
case ElementType::BYTE4: return integer ? wgpu::VertexFormat::Sint8x4 : wgpu::VertexFormat::Float32x4;
|
||||
case ElementType::UBYTE4: return integer ? wgpu::VertexFormat::Uint8x4 : wgpu::VertexFormat::Float32x4;
|
||||
case ElementType::SHORT4: return integer ? wgpu::VertexFormat::Sint16x4 : wgpu::VertexFormat::Float32x4;
|
||||
case ElementType::USHORT4: return integer ? wgpu::VertexFormat::Uint16x4 : wgpu::VertexFormat::Float32x4;
|
||||
case ElementType::HALF4: return wgpu::VertexFormat::Float16x4;
|
||||
case ElementType::FLOAT4: return wgpu::VertexFormat::Float32x4;
|
||||
}
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Vertex format should always be defined.";
|
||||
return wgpu::VertexFormat::Float32x3;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||
AttributeArray const& attributes)
|
||||
: HwVertexBufferInfo(bufferCount, attributeCount),
|
||||
mVertexBufferLayout(bufferCount),
|
||||
mAttributes(bufferCount) {
|
||||
for (uint32_t attribIndex = 0; attribIndex < attributes.size(); attribIndex++) {
|
||||
Attribute attrib = attributes[attribIndex];
|
||||
// Ignore the attributes which are not bind to vertex buffers.
|
||||
if (attrib.buffer == Attribute::BUFFER_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert_invariant(attrib.buffer < bufferCount);
|
||||
bool const isInteger = attrib.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||
bool const isNormalized = attrib.flags & Attribute::FLAG_NORMALIZED;
|
||||
wgpu::VertexFormat vertexFormat = getVertexFormat(attrib.type, isNormalized, isInteger);
|
||||
|
||||
mAttributes[attrib.buffer].push_back({
|
||||
.format = vertexFormat,
|
||||
.offset = attrib.offset,
|
||||
.shaderLocation = attribIndex,
|
||||
});
|
||||
mVertexBufferLayout[attrib.buffer] = {
|
||||
.arrayStride = attrib.stride,
|
||||
};
|
||||
}
|
||||
|
||||
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; bufferIndex++) {
|
||||
mVertexBufferLayout[bufferIndex] = {
|
||||
.attributeCount = mAttributes[bufferIndex].size(),
|
||||
.attributes = mAttributes[bufferIndex].data(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
WGPUIndexBuffer::WGPUIndexBuffer(wgpu::Device const& device, uint8_t elementSize,
|
||||
uint32_t indexCount)
|
||||
: buffer(createIndexBuffer(device, elementSize, indexCount)) {}
|
||||
: buffer(createIndexBuffer(device, elementSize, indexCount)),
|
||||
indexFormat(elementSize == 2 ? wgpu::IndexFormat::Uint16 : wgpu::IndexFormat::Uint32) {}
|
||||
|
||||
|
||||
WGPUVertexBuffer::WGPUVertexBuffer(wgpu::Device const &device, uint32_t vextexCount, uint32_t bufferCount,
|
||||
Handle<WGPUVertexBufferInfo> vbih)
|
||||
Handle<HwVertexBufferInfo> vbih)
|
||||
: HwVertexBuffer(vextexCount),
|
||||
vbih(vbih),
|
||||
buffers(bufferCount) {
|
||||
@@ -150,4 +258,10 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
mLayout = device->CreateBindGroupLayout(&layoutDescriptor);
|
||||
}
|
||||
WebGPUDescriptorSetLayout::~WebGPUDescriptorSetLayout() {}
|
||||
|
||||
void WGPURenderPrimitive::setBuffers(WGPUVertexBufferInfo const* const vbi,
|
||||
WGPUVertexBuffer* vertexBuffer, WGPUIndexBuffer* indexBuffer) {
|
||||
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
// #include <utils/StructureOfArrays.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
@@ -32,23 +33,40 @@
|
||||
namespace filament::backend {
|
||||
|
||||
struct WGPUBufferObject;
|
||||
// TODO: Currently WGPUVertexBufferInfo is not used by WebGPU for useful task.
|
||||
// Update the struct when used by WebGPU driver.
|
||||
|
||||
// VertexBufferInfo contains layout info for Vertex Buffer based on WebGPU structs. In WebGPU each
|
||||
// VertexBufferLayout is associated with a single vertex buffer. So number of mVertexBufferLayout
|
||||
// is equal to bufferCount. Each VertexBufferLayout can contain multiple VertexAttribute. Bind index
|
||||
// of vertex buffer is implicitly calculated by the position of VertexBufferLayout in an array.
|
||||
struct WGPUVertexBufferInfo : public HwVertexBufferInfo {
|
||||
|
||||
WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||
AttributeArray const& attributes)
|
||||
: HwVertexBufferInfo(bufferCount, attributeCount),
|
||||
attributes(attributes) {}
|
||||
AttributeArray attributes;
|
||||
AttributeArray const& attributes);
|
||||
inline wgpu::VertexBufferLayout const* getVertexBufferLayout() const {
|
||||
return mVertexBufferLayout.data();
|
||||
}
|
||||
inline uint32_t getVertexBufferLayoutSize() const {
|
||||
return mVertexBufferLayout.size();
|
||||
}
|
||||
|
||||
inline wgpu::VertexAttribute const* getVertexAttributeForIndex(uint32_t index) const {
|
||||
return mAttributes[index].data();
|
||||
}
|
||||
inline uint32_t getVertexAttributeSize(uint32_t index) const {
|
||||
return mAttributes[index].size();
|
||||
}
|
||||
private:
|
||||
std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout;
|
||||
std::vector<std::vector<wgpu::VertexAttribute>> mAttributes;
|
||||
};
|
||||
|
||||
struct WGPUVertexBuffer : public HwVertexBuffer {
|
||||
WGPUVertexBuffer(wgpu::Device const &device, uint32_t vextexCount, uint32_t bufferCount,
|
||||
Handle<WGPUVertexBufferInfo> vbih);
|
||||
Handle<HwVertexBufferInfo> vbih);
|
||||
|
||||
void setBuffer(WGPUBufferObject *bufferObject, uint32_t index);
|
||||
|
||||
Handle<WGPUVertexBufferInfo> vbih;
|
||||
Handle<HwVertexBufferInfo> vbih;
|
||||
utils::FixedCapacityVector<wgpu::Buffer> buffers;
|
||||
};
|
||||
|
||||
@@ -57,9 +75,10 @@ struct WGPUIndexBuffer : public HwIndexBuffer {
|
||||
uint32_t indexCount);
|
||||
|
||||
wgpu::Buffer buffer;
|
||||
wgpu::IndexFormat indexFormat;
|
||||
};
|
||||
|
||||
// TODO: Currently WGPUVertexBufferInfo is not used by WebGPU for useful task.
|
||||
// TODO: Currently WGPUBufferObject is not used by WebGPU for useful task.
|
||||
// Update the struct when used by WebGPU driver.
|
||||
struct WGPUBufferObject : HwBufferObject {
|
||||
WGPUBufferObject(BufferObjectBinding bindingType, uint32_t byteCount);
|
||||
@@ -67,6 +86,7 @@ struct WGPUBufferObject : HwBufferObject {
|
||||
wgpu::Buffer buffer;
|
||||
const BufferObjectBinding bufferObjectBinding;
|
||||
};
|
||||
|
||||
class WebGPUDescriptorSetLayout : public HwDescriptorSetLayout {
|
||||
public:
|
||||
WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout, wgpu::Device const* device);
|
||||
|
||||
Reference in New Issue
Block a user