Compare commits
4 Commits
ebridgewat
...
moreGemini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e2798f861 | ||
|
|
f9842fd40b | ||
|
|
109908c460 | ||
|
|
3a1987406b |
@@ -582,7 +582,6 @@ void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph, Handle<
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||
constructHandle<WGPUProgram>(ph, mDevice, program);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
||||
assert_invariant(!mDefaultRenderTarget);
|
||||
mDefaultRenderTarget = constructHandle<WGPURenderTarget>(rth);
|
||||
@@ -1030,10 +1029,20 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
// VulkanPipelineCache to handle this, may be missing nuance
|
||||
static auto pipleineStateHasher = utils::hash::MurmurHashFn<filament::backend::PipelineState>();
|
||||
auto hash = pipleineStateHasher(pipelineState);
|
||||
if(mPipelineMap.find(hash) != mPipelineMap.end()){
|
||||
if(mPipelineMap.find(hash) != mPipelineMap.end()) {
|
||||
mRenderPassEncoder.SetPipeline(mPipelineMap[hash]);
|
||||
return;
|
||||
}
|
||||
for (size_t index = 0; index < MAX_DESCRIPTOR_SET_COUNT; ++index) {
|
||||
auto& entry = currentDescriptorSets[index];
|
||||
if (entry.bg != nullptr) {
|
||||
mRenderPassEncoder.SetBindGroup(index, entry.bg, entry.dynamicOffsetCount,
|
||||
entry.offsets.data());
|
||||
entry.bg = nullptr;
|
||||
entry.dynamicOffsetCount = 0;
|
||||
entry.offsets.clear();
|
||||
}
|
||||
}
|
||||
const auto* program = handleCast<WGPUProgram>(pipelineState.program);
|
||||
assert_invariant(program);
|
||||
assert_invariant(program->computeShaderModule == nullptr &&
|
||||
@@ -1076,14 +1085,20 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
|
||||
void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
auto* renderPrimitive = handleCast<WGPURenderPrimitive>(rph);
|
||||
auto* vbi = handleCast<WGPUVertexBufferInfo>(renderPrimitive->vertexBuffer->vbih);
|
||||
|
||||
// This *must* match the WGPUVertexBufferInfo 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);
|
||||
assert_invariant(
|
||||
vbi->getVertexBufferLayoutSize() == renderPrimitive->vertexBuffer->buffers.size());
|
||||
for (uint32_t i = 0; i < vbi->getVertexBufferLayoutSize(); i++) {
|
||||
mRenderPassEncoder.SetVertexBuffer(i, renderPrimitive->vertexBuffer->buffers[i]);
|
||||
// Loop over the WebGPU vertex buffer slots defined by the VertexBufferInfo.
|
||||
// For each WebGPU slot, find the corresponding Filament buffer that supplies the data.
|
||||
for (uint32_t webGPUSlot = 0; webGPUSlot < vbi->getWebGPULayoutCount(); ++webGPUSlot) {
|
||||
uint8_t filamentBufferIndex = vbi->getFilamentBufferIndexForSlot(webGPUSlot);
|
||||
|
||||
// Ensure the Filament buffer index is valid for the vertexBuffer's internal storage.
|
||||
// This check assumes renderPrimitive->vertexBuffer->buffers is sized by the
|
||||
// original Filament buffer count.
|
||||
assert_invariant(filamentBufferIndex < renderPrimitive->vertexBuffer->buffers.size());
|
||||
|
||||
mRenderPassEncoder.SetVertexBuffer(webGPUSlot,
|
||||
renderPrimitive->vertexBuffer->buffers[filamentBufferIndex]);
|
||||
}
|
||||
|
||||
mRenderPassEncoder.SetIndexBuffer(renderPrimitive->indexBuffer->getBuffer(),
|
||||
@@ -1157,9 +1172,12 @@ void WebGPUDriver::bindDescriptorSet(Handle<HwDescriptorSet> dsh,
|
||||
backend::descriptor_set_t setIndex, backend::DescriptorSetOffsetArray&& offsets) {
|
||||
const auto bindGroup = handleCast<WebGPUDescriptorSet>(dsh);
|
||||
const auto wbg = bindGroup->lockAndReturn(mDevice);
|
||||
assert_invariant(mRenderPassEncoder);
|
||||
const size_t dynamicOffsetCount = bindGroup->countEntitiesWithDynamicOffsets();
|
||||
mRenderPassEncoder.SetBindGroup(setIndex, wbg, dynamicOffsetCount, offsets.data());
|
||||
|
||||
if(mRenderPassEncoder){
|
||||
mRenderPassEncoder.SetBindGroup(setIndex, wbg, dynamicOffsetCount, offsets.data());
|
||||
}
|
||||
currentDescriptorSets[setIndex] = {wbg, dynamicOffsetCount, std::move(offsets)};
|
||||
}
|
||||
|
||||
void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||
|
||||
@@ -72,6 +72,12 @@ private:
|
||||
wgpu::CommandEncoder mCommandEncoder = nullptr;
|
||||
wgpu::TextureView mTextureView = nullptr;
|
||||
wgpu::RenderPassEncoder mRenderPassEncoder = nullptr;
|
||||
struct bgInfo{
|
||||
wgpu::BindGroup bg;
|
||||
size_t dynamicOffsetCount;
|
||||
backend::DescriptorSetOffsetArray offsets;
|
||||
};
|
||||
std::array<bgInfo, MAX_DESCRIPTOR_SET_COUNT> currentDescriptorSets = {};
|
||||
wgpu::CommandBuffer mCommandBuffer = nullptr;
|
||||
WGPURenderTarget* mDefaultRenderTarget = nullptr;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -196,43 +197,77 @@ void WGPUBufferBase::updateGPUBuffer(BufferDescriptor& bufferDescriptor, uint32_
|
||||
queue.WriteBuffer(buffer, byteOffset + legalSize, &mRemainderChunk, 4);
|
||||
}
|
||||
}
|
||||
|
||||
WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||
AttributeArray const& attributes)
|
||||
: HwVertexBufferInfo(bufferCount, attributeCount),
|
||||
mVertexBufferLayout(bufferCount),
|
||||
mAttributes(bufferCount) {
|
||||
: HwVertexBufferInfo(bufferCount, attributeCount) { // Base class constructor
|
||||
|
||||
assert_invariant(attributeCount > 0);
|
||||
assert_invariant(bufferCount > 0);
|
||||
// bufferCount is Filament's buffer count. The number of WebGPU slots might differ.
|
||||
|
||||
struct LayoutKey {
|
||||
uint8_t filamentBufferIndex;
|
||||
uint16_t stride;
|
||||
bool operator<(const LayoutKey& other) const {
|
||||
if (filamentBufferIndex != other.filamentBufferIndex) {
|
||||
return filamentBufferIndex < other.filamentBufferIndex;
|
||||
}
|
||||
return stride < other.stride;
|
||||
}
|
||||
};
|
||||
std::map<LayoutKey, uint32_t> layoutKeyToWebGPUSlot;
|
||||
uint32_t nextWebGPUSlot = 0;
|
||||
|
||||
for (uint32_t attribIndex = 0; attribIndex < attributes.size(); attribIndex++) {
|
||||
Attribute const& attrib = attributes[attribIndex];
|
||||
// Ignore the attributes which are not bind to vertex buffers.
|
||||
// Ignore attributes not bound to any vertex buffer.
|
||||
if (attrib.buffer == Attribute::BUFFER_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert_invariant(attrib.buffer < bufferCount);
|
||||
assert_invariant(attrib.buffer < bufferCount); // Ensure Filament buffer index is valid
|
||||
|
||||
LayoutKey key = {attrib.buffer, attrib.stride};
|
||||
uint32_t currentWebGPUSlot;
|
||||
|
||||
auto it = layoutKeyToWebGPUSlot.find(key);
|
||||
if (it == layoutKeyToWebGPUSlot.end()) {
|
||||
currentWebGPUSlot = nextWebGPUSlot++;
|
||||
layoutKeyToWebGPUSlot[key] = currentWebGPUSlot;
|
||||
|
||||
mActualWebGPULayouts.emplace_back();
|
||||
mActualWebGPULayouts.back().arrayStride = attrib.stride;
|
||||
mActualWebGPULayouts.back().stepMode = wgpu::VertexStepMode::Vertex;
|
||||
// .attributes and .attributeCount will be set later
|
||||
|
||||
mSlotMappings.emplace_back(SlotMapping{attrib.buffer});
|
||||
mActualWebGPUAttributes.emplace_back(); // Add a new vector for this slot's attributes
|
||||
} else {
|
||||
currentWebGPUSlot = it->second;
|
||||
// Sanity check: if we found an existing slot for this key, its stride should match.
|
||||
assert_invariant(mActualWebGPULayouts[currentWebGPUSlot].arrayStride == attrib.stride);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Attributes are sequential per buffer
|
||||
mAttributes[attrib.buffer].push_back({
|
||||
mActualWebGPUAttributes[currentWebGPUSlot].push_back({
|
||||
.format = vertexFormat,
|
||||
.offset = attrib.offset,
|
||||
.shaderLocation = attribIndex,
|
||||
.shaderLocation = attribIndex, // Use original attribIndex as shaderLocation
|
||||
});
|
||||
|
||||
mVertexBufferLayout[attrib.buffer].stepMode = wgpu::VertexStepMode::Vertex;
|
||||
if (mVertexBufferLayout[attrib.buffer].arrayStride == 0) {
|
||||
mVertexBufferLayout[attrib.buffer].arrayStride = attrib.stride;
|
||||
} else {
|
||||
assert_invariant(mVertexBufferLayout[attrib.buffer].arrayStride == attrib.stride);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; bufferIndex++) {
|
||||
mVertexBufferLayout[bufferIndex].attributeCount = mAttributes[bufferIndex].size();
|
||||
mVertexBufferLayout[bufferIndex].attributes = mAttributes[bufferIndex].data();
|
||||
// Finalize attribute pointers and counts in mActualWebGPULayouts
|
||||
for (uint32_t slot = 0; slot < mActualWebGPULayouts.size(); ++slot) {
|
||||
if (!mActualWebGPUAttributes[slot].empty()) {
|
||||
mActualWebGPULayouts[slot].attributeCount = mActualWebGPUAttributes[slot].size();
|
||||
mActualWebGPULayouts[slot].attributes = mActualWebGPUAttributes[slot].data();
|
||||
} else {
|
||||
mActualWebGPULayouts[slot].attributeCount = 0;
|
||||
mActualWebGPULayouts[slot].attributes = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,30 +52,40 @@ class WGPUVertexBufferInfo : public HwVertexBufferInfo {
|
||||
public:
|
||||
WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||
AttributeArray const& attributes);
|
||||
inline wgpu::VertexBufferLayout const* getVertexBufferLayout() const {
|
||||
return mVertexBufferLayout.data();
|
||||
|
||||
// Returns the WebGPU native vertex buffer layouts
|
||||
inline wgpu::VertexBufferLayout const* getWebGPULayouts() const {
|
||||
return mActualWebGPULayouts.data();
|
||||
}
|
||||
|
||||
inline uint32_t getVertexBufferLayoutSize() const {
|
||||
return mVertexBufferLayout.size();
|
||||
// Returns the count of WebGPU native vertex buffer layouts
|
||||
inline uint32_t getWebGPULayoutCount() const {
|
||||
return mActualWebGPULayouts.size();
|
||||
}
|
||||
|
||||
inline wgpu::VertexAttribute const* getVertexAttributeForIndex(uint32_t index) const {
|
||||
assert_invariant(index < mAttributes.size());
|
||||
return mAttributes[index].data();
|
||||
}
|
||||
|
||||
inline uint32_t getVertexAttributeSize(uint32_t index) const {
|
||||
assert_invariant(index < mAttributes.size());
|
||||
return mAttributes[index].size();
|
||||
// Returns the Filament buffer index for a given WebGPU layout slot
|
||||
inline uint8_t getFilamentBufferIndexForSlot(uint32_t webgpuSlotIndex) const {
|
||||
assert_invariant(webgpuSlotIndex < mSlotMappings.size());
|
||||
return mSlotMappings[webgpuSlotIndex].filamentBufferIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO: can we do better in terms on heap management.
|
||||
std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout{};
|
||||
std::vector<std::vector<wgpu::VertexAttribute>> mAttributes{};
|
||||
};
|
||||
// Stores the final WebGPU vertex buffer layouts
|
||||
std::vector<wgpu::VertexBufferLayout> mActualWebGPULayouts;
|
||||
// Stores attributes per WebGPU layout, parallel to mActualWebGPULayouts.
|
||||
// Each wgpu::VertexBufferLayout in mActualWebGPULayouts will point to its attributes here.
|
||||
std::vector<std::vector<wgpu::VertexAttribute>> mActualWebGPUAttributes;
|
||||
|
||||
struct SlotMapping {
|
||||
uint8_t filamentBufferIndex; // Original Filament buffer index for this WebGPU slot
|
||||
};
|
||||
// Maps a WebGPU slot index to its original Filament buffer index
|
||||
std::vector<SlotMapping> mSlotMappings;
|
||||
|
||||
// Remove or comment out old members if they were similarly named:
|
||||
// std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout {}; // OLD
|
||||
// std::vector<std::vector<wgpu::VertexAttribute>> mAttributes {}; // OLD
|
||||
};
|
||||
struct WGPUVertexBuffer : public HwVertexBuffer {
|
||||
WGPUVertexBuffer(wgpu::Device const &device, uint32_t vertexCount, uint32_t bufferCount,
|
||||
Handle<HwVertexBufferInfo> vbih);
|
||||
|
||||
@@ -191,8 +191,8 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device,
|
||||
.entryPoint = "main",
|
||||
.constantCount = program.constants.size(),
|
||||
.constants = program.constants.data(),
|
||||
.bufferCount = vertexBufferInfo.getVertexBufferLayoutSize(),
|
||||
.buffers = vertexBufferInfo.getVertexBufferLayout()
|
||||
.bufferCount = vertexBufferInfo.getWebGPULayoutCount(),
|
||||
.buffers = vertexBufferInfo.getWebGPULayouts()
|
||||
},
|
||||
.primitive = {
|
||||
.topology = toWebGPU(primitiveType),
|
||||
|
||||
@@ -320,11 +320,14 @@ wgpu::TextureView WebGPUSwapChain::getCurrentSurfaceTextureView(
|
||||
if (surfaceTexture.status != wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mCurrentSurfaceTexture = nullptr;
|
||||
mCurrentSurfaceTexture = surfaceTexture.texture;
|
||||
// Create a view for this surface texture
|
||||
// TODO: review these initiliazations as webgpu pipeline gets mature
|
||||
wgpu::TextureViewDescriptor textureViewDescriptor = {
|
||||
.label = "surface_texture_view",
|
||||
.format = surfaceTexture.texture.GetFormat(),
|
||||
.format = mCurrentSurfaceTexture.GetFormat(),
|
||||
.dimension = wgpu::TextureViewDimension::e2D,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
@@ -337,6 +340,7 @@ wgpu::TextureView WebGPUSwapChain::getCurrentSurfaceTextureView(
|
||||
void WebGPUSwapChain::present() {
|
||||
assert_invariant(mSurface);
|
||||
mSurface.Present();
|
||||
mCurrentSurfaceTexture = nullptr;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -52,6 +52,8 @@ private:
|
||||
wgpu::TextureFormat mDepthFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::Texture mDepthTexture = nullptr;
|
||||
wgpu::TextureView mDepthTextureView = nullptr;
|
||||
wgpu::Texture mCurrentSurfaceTexture = nullptr; // To hold the texture from getCurrentTexture()
|
||||
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "regex"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -601,7 +601,6 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
tint::Result<tint::wgsl::writer::Output> wgslOut = tint::wgsl::writer::Generate(tintRead,writerOpts);
|
||||
/// An instance of SuccessType that can be used to check a tint Result.
|
||||
tint::SuccessType tintSuccess;
|
||||
@@ -610,7 +609,9 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
slog.e << "Tint writer error: " << wgslOut.Failure().reason << io::endl;
|
||||
return false;
|
||||
}
|
||||
*outWsl = wgslOut->wgsl;
|
||||
//Tint adds some annotations that Dawn complains about and needs removal
|
||||
std::regex stride_regex(R"(@stride\([0-9]+\)\s*@internal\(disable_validation__ignore_stride\))");
|
||||
*outWsl = std::regex_replace(wgslOut->wgsl, stride_regex, "");
|
||||
return true;
|
||||
#else
|
||||
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
|
||||
|
||||
Reference in New Issue
Block a user