Compare commits
4 Commits
bjd/comman
...
moreGemini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e2798f861 | ||
|
|
f9842fd40b | ||
|
|
109908c460 | ||
|
|
3a1987406b |
@@ -354,6 +354,17 @@ void WebGPUDriver::destroyProgram(Handle<HwProgram> ph) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
|
void WebGPUDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
|
||||||
|
if (rth) {
|
||||||
|
WGPURenderTarget* rt = handleCast<WGPURenderTarget>(rth);
|
||||||
|
if (rt == mDefaultRenderTarget) {
|
||||||
|
mDefaultRenderTarget = nullptr;
|
||||||
|
}
|
||||||
|
// WGPURenderTarget destructor is trivial.
|
||||||
|
// The HwTexture handles stored within WGPURenderTarget (via MRT, TargetBufferInfo)
|
||||||
|
// are not owned by WGPURenderTarget, so they are not destroyed here.
|
||||||
|
// They are destroyed via WebGPUDriver::destroyTexture.
|
||||||
|
destructHandle<WGPURenderTarget>(rth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::destroySwapChain(Handle<HwSwapChain> sch) {
|
void WebGPUDriver::destroySwapChain(Handle<HwSwapChain> sch) {
|
||||||
@@ -571,7 +582,6 @@ void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph, Handle<
|
|||||||
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||||
constructHandle<WGPUProgram>(ph, mDevice, program);
|
constructHandle<WGPUProgram>(ph, mDevice, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
||||||
assert_invariant(!mDefaultRenderTarget);
|
assert_invariant(!mDefaultRenderTarget);
|
||||||
mDefaultRenderTarget = constructHandle<WGPURenderTarget>(rth);
|
mDefaultRenderTarget = constructHandle<WGPURenderTarget>(rth);
|
||||||
@@ -580,7 +590,21 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
|||||||
|
|
||||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> rth, TargetBufferFlags targets,
|
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> rth, TargetBufferFlags targets,
|
||||||
uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color,
|
uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color,
|
||||||
TargetBufferInfo depth, TargetBufferInfo stencil) {}
|
TargetBufferInfo depth, TargetBufferInfo stencil) {
|
||||||
|
// The `targets` flags indicate which of the `color`, `depth`, `stencil` TargetBufferInfo
|
||||||
|
// are actually active for this render target.
|
||||||
|
// We'll pass all TargetBufferInfo to WGPURenderTarget; it will use them if their handles are valid.
|
||||||
|
|
||||||
|
// Ensure that textures intended for use as attachments were created with
|
||||||
|
// wgpu::TextureUsage::RenderAttachment. This check should ideally be in createTextureR
|
||||||
|
// or validated here if possible.
|
||||||
|
|
||||||
|
// The `layerCount` parameter might be for creating array textures that this RT targets.
|
||||||
|
// Individual attachments (color[i].layer, depth.layer, stencil.layer) specify which layer
|
||||||
|
// of an array texture to bind. For now, we assume textures are pre-configured.
|
||||||
|
|
||||||
|
constructHandle<WGPURenderTarget>(rth, width, height, samples, color, depth, stencil);
|
||||||
|
}
|
||||||
|
|
||||||
void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {}
|
void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {}
|
||||||
|
|
||||||
@@ -845,35 +869,74 @@ void WebGPUDriver::compilePrograms(CompilerPriorityQueue priority,
|
|||||||
|
|
||||||
void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> rth, RenderPassParams const& params) {
|
void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> rth, RenderPassParams const& params) {
|
||||||
assert_invariant(mCommandEncoder);
|
assert_invariant(mCommandEncoder);
|
||||||
|
|
||||||
auto* renderTarget = handleCast<WGPURenderTarget>(rth);
|
auto* renderTarget = handleCast<WGPURenderTarget>(rth);
|
||||||
// if (renderTarget == mDefaultRenderTarget) {
|
|
||||||
// FWGPU_LOGW << "Default render target"
|
|
||||||
// << utils::io::endl;
|
|
||||||
// } else {
|
|
||||||
// FWGPU_LOGW << "Non Default render target"
|
|
||||||
// << utils::io::endl;
|
|
||||||
// }
|
|
||||||
wgpu::RenderPassDescriptor renderPassDescriptor;
|
|
||||||
wgpu::RenderPassDepthStencilAttachment depthStencilAttachment{
|
|
||||||
.view = mSwapChain->getDepthTextureView(),
|
|
||||||
.depthLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH),
|
|
||||||
.depthStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH),
|
|
||||||
.depthClearValue = static_cast<float>(params.clearDepth),
|
|
||||||
.depthReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0,
|
|
||||||
.stencilLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL),
|
|
||||||
.stencilStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::STENCIL),
|
|
||||||
.stencilClearValue = params.clearStencil,
|
|
||||||
.stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0
|
|
||||||
};
|
|
||||||
renderTarget->setUpRenderPassAttachments(renderPassDescriptor, mTextureView, params);
|
|
||||||
renderPassDescriptor.depthStencilAttachment = &depthStencilAttachment;
|
|
||||||
|
|
||||||
assert_invariant(mTextureView);
|
wgpu::RenderPassDescriptor renderPassDescriptor{};
|
||||||
|
wgpu::TextureView defaultColorView = nullptr;
|
||||||
|
wgpu::TextureView defaultDepthStencilView = nullptr;
|
||||||
|
|
||||||
|
std::array<wgpu::TextureView, MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT> customColorViews{};
|
||||||
|
uint32_t customColorViewCount = 0;
|
||||||
|
wgpu::TextureView customDepthView = nullptr;
|
||||||
|
wgpu::TextureView customStencilView = nullptr;
|
||||||
|
|
||||||
|
if (renderTarget->isDefaultRenderTarget()) {
|
||||||
|
assert_invariant(mSwapChain && mTextureView);
|
||||||
|
defaultColorView = mTextureView;
|
||||||
|
defaultDepthStencilView = mSwapChain->getDepthTextureView();
|
||||||
|
} else {
|
||||||
|
// Resolve views for custom render target
|
||||||
|
const auto& colorInfos = renderTarget->getColorAttachmentInfos();
|
||||||
|
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; ++i) {
|
||||||
|
if (colorInfos[i].handle) {
|
||||||
|
auto* hwTexture = handleCast<WGPUTexture>(colorInfos[i].handle);
|
||||||
|
if (hwTexture) {
|
||||||
|
// TODO: Consider colorInfos[i].level and colorInfos[i].layer for view creation
|
||||||
|
// if WGPUTexture::getTexView() isn't sufficient or needs parameters.
|
||||||
|
customColorViews[customColorViewCount++] = hwTexture->getTexView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& depthInfo = renderTarget->getDepthAttachmentInfo();
|
||||||
|
if (depthInfo.handle) {
|
||||||
|
auto* hwTexture = handleCast<WGPUTexture>(depthInfo.handle);
|
||||||
|
if (hwTexture) {
|
||||||
|
customDepthView = hwTexture->getTexView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& stencilInfo = renderTarget->getStencilAttachmentInfo();
|
||||||
|
if (stencilInfo.handle) {
|
||||||
|
// If depth and stencil use the same texture handle, this will re-cast but that's fine.
|
||||||
|
auto* hwTexture = handleCast<WGPUTexture>(stencilInfo.handle);
|
||||||
|
if (hwTexture) {
|
||||||
|
customStencilView = hwTexture->getTexView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTarget->setUpRenderPassAttachments(renderPassDescriptor,
|
||||||
|
params,
|
||||||
|
defaultColorView,
|
||||||
|
defaultDepthStencilView,
|
||||||
|
customColorViews.data(),
|
||||||
|
customColorViewCount,
|
||||||
|
customDepthView,
|
||||||
|
customStencilView);
|
||||||
|
|
||||||
mRenderPassEncoder = mCommandEncoder.BeginRenderPass(&renderPassDescriptor);
|
mRenderPassEncoder = mCommandEncoder.BeginRenderPass(&renderPassDescriptor);
|
||||||
mRenderPassEncoder.SetViewport(params.viewport.left, params.viewport.bottom,
|
// Ensure viewport dimensions are positive
|
||||||
params.viewport.width, params.viewport.height, params.depthRange.near, params.depthRange.far);
|
uint32_t viewportWidth = params.viewport.width > 0 ? params.viewport.width : 1;
|
||||||
|
uint32_t viewportHeight = params.viewport.height > 0 ? params.viewport.height : 1;
|
||||||
|
|
||||||
|
mRenderPassEncoder.SetViewport(
|
||||||
|
static_cast<float>(params.viewport.left),
|
||||||
|
static_cast<float>(params.viewport.bottom),
|
||||||
|
static_cast<float>(viewportWidth),
|
||||||
|
static_cast<float>(viewportHeight),
|
||||||
|
params.depthRange.near,
|
||||||
|
params.depthRange.far);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::endRenderPass(int /* dummy */) {
|
void WebGPUDriver::endRenderPass(int /* dummy */) {
|
||||||
@@ -966,10 +1029,20 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
|||||||
// VulkanPipelineCache to handle this, may be missing nuance
|
// VulkanPipelineCache to handle this, may be missing nuance
|
||||||
static auto pipleineStateHasher = utils::hash::MurmurHashFn<filament::backend::PipelineState>();
|
static auto pipleineStateHasher = utils::hash::MurmurHashFn<filament::backend::PipelineState>();
|
||||||
auto hash = pipleineStateHasher(pipelineState);
|
auto hash = pipleineStateHasher(pipelineState);
|
||||||
if(mPipelineMap.find(hash) != mPipelineMap.end()){
|
if(mPipelineMap.find(hash) != mPipelineMap.end()) {
|
||||||
mRenderPassEncoder.SetPipeline(mPipelineMap[hash]);
|
mRenderPassEncoder.SetPipeline(mPipelineMap[hash]);
|
||||||
return;
|
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);
|
const auto* program = handleCast<WGPUProgram>(pipelineState.program);
|
||||||
assert_invariant(program);
|
assert_invariant(program);
|
||||||
assert_invariant(program->computeShaderModule == nullptr &&
|
assert_invariant(program->computeShaderModule == nullptr &&
|
||||||
@@ -1012,14 +1085,20 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) {
|
|||||||
|
|
||||||
void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||||
auto* renderPrimitive = handleCast<WGPURenderPrimitive>(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
|
// Loop over the WebGPU vertex buffer slots defined by the VertexBufferInfo.
|
||||||
// to allow to call this before bindPipeline(), so the validation can only happen in draw()
|
// For each WebGPU slot, find the corresponding Filament buffer that supplies the data.
|
||||||
auto vbi = handleCast<WGPUVertexBufferInfo>(renderPrimitive->vertexBuffer->vbih);
|
for (uint32_t webGPUSlot = 0; webGPUSlot < vbi->getWebGPULayoutCount(); ++webGPUSlot) {
|
||||||
assert_invariant(
|
uint8_t filamentBufferIndex = vbi->getFilamentBufferIndexForSlot(webGPUSlot);
|
||||||
vbi->getVertexBufferLayoutSize() == renderPrimitive->vertexBuffer->buffers.size());
|
|
||||||
for (uint32_t i = 0; i < vbi->getVertexBufferLayoutSize(); i++) {
|
// Ensure the Filament buffer index is valid for the vertexBuffer's internal storage.
|
||||||
mRenderPassEncoder.SetVertexBuffer(i, renderPrimitive->vertexBuffer->buffers[i]);
|
// 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(),
|
mRenderPassEncoder.SetIndexBuffer(renderPrimitive->indexBuffer->getBuffer(),
|
||||||
@@ -1093,9 +1172,12 @@ void WebGPUDriver::bindDescriptorSet(Handle<HwDescriptorSet> dsh,
|
|||||||
backend::descriptor_set_t setIndex, backend::DescriptorSetOffsetArray&& offsets) {
|
backend::descriptor_set_t setIndex, backend::DescriptorSetOffsetArray&& offsets) {
|
||||||
const auto bindGroup = handleCast<WebGPUDescriptorSet>(dsh);
|
const auto bindGroup = handleCast<WebGPUDescriptorSet>(dsh);
|
||||||
const auto wbg = bindGroup->lockAndReturn(mDevice);
|
const auto wbg = bindGroup->lockAndReturn(mDevice);
|
||||||
assert_invariant(mRenderPassEncoder);
|
|
||||||
const size_t dynamicOffsetCount = bindGroup->countEntitiesWithDynamicOffsets();
|
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) {
|
void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ private:
|
|||||||
wgpu::CommandEncoder mCommandEncoder = nullptr;
|
wgpu::CommandEncoder mCommandEncoder = nullptr;
|
||||||
wgpu::TextureView mTextureView = nullptr;
|
wgpu::TextureView mTextureView = nullptr;
|
||||||
wgpu::RenderPassEncoder mRenderPassEncoder = 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;
|
wgpu::CommandBuffer mCommandBuffer = nullptr;
|
||||||
WGPURenderTarget* mDefaultRenderTarget = nullptr;
|
WGPURenderTarget* mDefaultRenderTarget = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -196,43 +197,77 @@ void WGPUBufferBase::updateGPUBuffer(BufferDescriptor& bufferDescriptor, uint32_
|
|||||||
queue.WriteBuffer(buffer, byteOffset + legalSize, &mRemainderChunk, 4);
|
queue.WriteBuffer(buffer, byteOffset + legalSize, &mRemainderChunk, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
WGPUVertexBufferInfo::WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||||
AttributeArray const& attributes)
|
AttributeArray const& attributes)
|
||||||
: HwVertexBufferInfo(bufferCount, attributeCount),
|
: HwVertexBufferInfo(bufferCount, attributeCount) { // Base class constructor
|
||||||
mVertexBufferLayout(bufferCount),
|
|
||||||
mAttributes(bufferCount) {
|
|
||||||
assert_invariant(attributeCount > 0);
|
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++) {
|
for (uint32_t attribIndex = 0; attribIndex < attributes.size(); attribIndex++) {
|
||||||
Attribute const& attrib = attributes[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) {
|
if (attrib.buffer == Attribute::BUFFER_UNUSED) {
|
||||||
continue;
|
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 isInteger = attrib.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||||
bool const isNormalized = attrib.flags & Attribute::FLAG_NORMALIZED;
|
bool const isNormalized = attrib.flags & Attribute::FLAG_NORMALIZED;
|
||||||
wgpu::VertexFormat vertexFormat = getVertexFormat(attrib.type, isNormalized, isInteger);
|
wgpu::VertexFormat vertexFormat = getVertexFormat(attrib.type, isNormalized, isInteger);
|
||||||
|
|
||||||
// Attributes are sequential per buffer
|
mActualWebGPUAttributes[currentWebGPUSlot].push_back({
|
||||||
mAttributes[attrib.buffer].push_back({
|
|
||||||
.format = vertexFormat,
|
.format = vertexFormat,
|
||||||
.offset = attrib.offset,
|
.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++) {
|
// Finalize attribute pointers and counts in mActualWebGPULayouts
|
||||||
mVertexBufferLayout[bufferIndex].attributeCount = mAttributes[bufferIndex].size();
|
for (uint32_t slot = 0; slot < mActualWebGPULayouts.size(); ++slot) {
|
||||||
mVertexBufferLayout[bufferIndex].attributes = mAttributes[bufferIndex].data();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,58 +958,147 @@ wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const u
|
|||||||
return textureView;
|
return textureView;
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPURenderTarget::Attachment WGPURenderTarget::getDrawColorAttachment(size_t index) {
|
WGPURenderTarget::WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples,
|
||||||
assert_invariant( index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT);
|
const MRT& colorAttachmentsMRT,
|
||||||
auto result = color[index];
|
const Attachment& depthAttachmentInfo,
|
||||||
if (index == 0 && defaultRenderTarget) {
|
const Attachment& stencilAttachmentInfo)
|
||||||
|
: HwRenderTarget(width, height),
|
||||||
}
|
defaultRenderTarget(false),
|
||||||
|
samples(samples),
|
||||||
return result;
|
mColorAttachments(colorAttachmentsMRT),
|
||||||
|
mDepthAttachment(depthAttachmentInfo),
|
||||||
|
mStencilAttachment(stencilAttachmentInfo) {
|
||||||
|
mColorAttachmentDescriptors.reserve(MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static helper to map MRT index to TargetBufferFlags
|
||||||
|
TargetBufferFlags WGPURenderTarget::getTargetBufferFlagsAt(int mrtIndex) {
|
||||||
|
if (mrtIndex < 0 || mrtIndex >= MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) {
|
||||||
|
return TargetBufferFlags::NONE;
|
||||||
|
}
|
||||||
|
// This mapping assumes TargetBufferFlags::COLOR_0, COLOR_1 etc. are contiguous
|
||||||
|
return static_cast<TargetBufferFlags>(
|
||||||
|
static_cast<uint32_t>(TargetBufferFlags::COLOR0) << mrtIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Corrected getLoadOperation
|
||||||
wgpu::LoadOp WGPURenderTarget::getLoadOperation(RenderPassParams const& params,
|
wgpu::LoadOp WGPURenderTarget::getLoadOperation(RenderPassParams const& params,
|
||||||
TargetBufferFlags buffer) {
|
TargetBufferFlags bufferToOperateOn) {
|
||||||
auto clearFlags = params.flags.clear;
|
if (any(params.flags.clear & bufferToOperateOn)) {
|
||||||
auto discardStartFlags = params.flags.discardStart;
|
|
||||||
if (any(clearFlags & buffer)) {
|
|
||||||
return wgpu::LoadOp::Clear;
|
|
||||||
} else if (any(discardStartFlags & buffer)) {
|
|
||||||
return wgpu::LoadOp::Clear;
|
return wgpu::LoadOp::Clear;
|
||||||
}
|
}
|
||||||
|
if (any(params.flags.discardStart & bufferToOperateOn)) {
|
||||||
|
return wgpu::LoadOp::Clear; // Or wgpu::LoadOp::Undefined if clear is not desired on discard
|
||||||
|
}
|
||||||
return wgpu::LoadOp::Load;
|
return wgpu::LoadOp::Load;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Corrected getStoreOperation
|
||||||
wgpu::StoreOp WGPURenderTarget::getStoreOperation(RenderPassParams const& params,
|
wgpu::StoreOp WGPURenderTarget::getStoreOperation(RenderPassParams const& params,
|
||||||
TargetBufferFlags buffer) {
|
TargetBufferFlags bufferToOperateOn) {
|
||||||
const auto discardEndFlags = params.flags.discardEnd;
|
if (any(params.flags.discardEnd & bufferToOperateOn)) {
|
||||||
if (any(discardEndFlags & buffer)) {
|
|
||||||
return wgpu::StoreOp::Discard;
|
return wgpu::StoreOp::Discard;
|
||||||
}
|
}
|
||||||
return wgpu::StoreOp::Store;
|
return wgpu::StoreOp::Store;
|
||||||
}
|
}
|
||||||
void WGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& descriptor,
|
|
||||||
wgpu::TextureView const& textureView, RenderPassParams const& params) {
|
void WGPURenderTarget::setUpRenderPassAttachments(
|
||||||
// auto discardFlags = params.flags.discardEnd;
|
wgpu::RenderPassDescriptor& descriptor,
|
||||||
// (void) discardFlags;
|
RenderPassParams const& params,
|
||||||
// std::vector<wgpu::RenderPassColorAttachment> colorAttachments;
|
wgpu::TextureView const& defaultColorTextureView,
|
||||||
colorAttachments.clear();
|
wgpu::TextureView const& defaultDepthStencilTextureView,
|
||||||
for (size_t i = 0; i < 1/*MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT*/; i++) {
|
wgpu::TextureView const* customColorTextureViews,
|
||||||
// auto attachment = getDrawColorAttachment(i);
|
uint32_t customColorTextureViewCount,
|
||||||
// if (attachment) {
|
wgpu::TextureView const& customDepthTextureView,
|
||||||
wgpu::RenderPassColorAttachment colorAttachment;
|
wgpu::TextureView const& customStencilTextureView) {
|
||||||
colorAttachment.view = textureView;
|
mColorAttachmentDescriptors.clear();
|
||||||
colorAttachment.loadOp = getLoadOperation(params, getTargetBufferFlagsAt(i));
|
mHasDepthStencilAttachment = false;
|
||||||
colorAttachment.storeOp = getStoreOperation(params, getTargetBufferFlagsAt(i));
|
|
||||||
colorAttachment.clearValue = { params.clearColor.r, params.clearColor.g, params.clearColor.b, params.clearColor.a };
|
if (defaultRenderTarget) {
|
||||||
colorAttachments.emplace_back(colorAttachment);
|
assert_invariant(defaultColorTextureView);
|
||||||
// }
|
wgpu::RenderPassColorAttachment colorAttDesc{};
|
||||||
|
colorAttDesc.view = defaultColorTextureView;
|
||||||
|
colorAttDesc.resolveTarget = nullptr;
|
||||||
|
colorAttDesc.loadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::COLOR0);
|
||||||
|
colorAttDesc.storeOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::COLOR0);
|
||||||
|
colorAttDesc.clearValue = {params.clearColor.r, params.clearColor.g,
|
||||||
|
params.clearColor.b, params.clearColor.a};
|
||||||
|
mColorAttachmentDescriptors.push_back(colorAttDesc);
|
||||||
|
|
||||||
|
if (defaultDepthStencilTextureView) {
|
||||||
|
mDepthStencilAttachmentDescriptor = {
|
||||||
|
.view = defaultDepthStencilTextureView,
|
||||||
|
.depthLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH),
|
||||||
|
.depthStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH),
|
||||||
|
.depthClearValue = static_cast<float>(params.clearDepth),
|
||||||
|
.depthReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0,
|
||||||
|
.stencilLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL),
|
||||||
|
.stencilStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::STENCIL),
|
||||||
|
.stencilClearValue = params.clearStencil,
|
||||||
|
.stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0,
|
||||||
|
};
|
||||||
|
mHasDepthStencilAttachment = true;
|
||||||
|
}
|
||||||
|
} else { // Custom Render Target
|
||||||
|
for (uint32_t i = 0; i < customColorTextureViewCount; ++i) {
|
||||||
|
if (customColorTextureViews[i]) {
|
||||||
|
wgpu::RenderPassColorAttachment colorAttDesc{};
|
||||||
|
colorAttDesc.view = customColorTextureViews[i];
|
||||||
|
colorAttDesc.resolveTarget = nullptr; // TODO: MSAA resolve for custom RT
|
||||||
|
colorAttDesc.loadOp = WGPURenderTarget::getLoadOperation(params, getTargetBufferFlagsAt(i));
|
||||||
|
colorAttDesc.storeOp = WGPURenderTarget::getStoreOperation(params, getTargetBufferFlagsAt(i));
|
||||||
|
colorAttDesc.clearValue = {params.clearColor.r, params.clearColor.g,
|
||||||
|
params.clearColor.b, params.clearColor.a};
|
||||||
|
mColorAttachmentDescriptors.push_back(colorAttDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::TextureView combinedDsView = customDepthTextureView ? customDepthTextureView : customStencilTextureView;
|
||||||
|
|
||||||
|
if (combinedDsView) {
|
||||||
|
mDepthStencilAttachmentDescriptor = {};
|
||||||
|
mDepthStencilAttachmentDescriptor.view = combinedDsView;
|
||||||
|
|
||||||
|
if (customDepthTextureView) {
|
||||||
|
mDepthStencilAttachmentDescriptor.depthLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH);
|
||||||
|
mDepthStencilAttachmentDescriptor.depthStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH);
|
||||||
|
mDepthStencilAttachmentDescriptor.depthClearValue = static_cast<float>(params.clearDepth);
|
||||||
|
mDepthStencilAttachmentDescriptor.depthReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
|
||||||
|
} else {
|
||||||
|
mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined;
|
||||||
|
mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined;
|
||||||
|
mDepthStencilAttachmentDescriptor.depthReadOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customStencilTextureView) {
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL);
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::STENCIL);
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilClearValue = params.clearStencil;
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0;
|
||||||
|
} else {
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilLoadOp = wgpu::LoadOp::Undefined;
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilStoreOp = wgpu::StoreOp::Undefined;
|
||||||
|
mDepthStencilAttachmentDescriptor.stencilReadOnly = true;
|
||||||
|
}
|
||||||
|
mHasDepthStencilAttachment = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
descriptor.colorAttachments = colorAttachments.data();
|
|
||||||
descriptor.colorAttachmentCount = colorAttachments.size();
|
descriptor.colorAttachmentCount = mColorAttachmentDescriptors.size();
|
||||||
descriptor.depthStencilAttachment = nullptr;
|
descriptor.colorAttachments = mColorAttachmentDescriptors.data();
|
||||||
descriptor.timestampWrites = nullptr;
|
descriptor.depthStencilAttachment = mHasDepthStencilAttachment ? &mDepthStencilAttachmentDescriptor : nullptr;
|
||||||
|
// descriptor.sampleCount was removed from the core spec. If your webgpu.h still has it,
|
||||||
|
// and your Dawn version expects it, you might need to set it here based on this->samples.
|
||||||
|
// e.g., descriptor.sampleCount = this->samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
math::uint2 WGPURenderTarget::getAttachmentSize() const noexcept {
|
||||||
|
if (!defaultRenderTarget) {
|
||||||
|
return {width, height};
|
||||||
|
}
|
||||||
|
// For default RT, size is dynamic and usually obtained from the swapchain.
|
||||||
|
// The caller (WebGPUDriver::beginRenderPass) should know the current swapchain size.
|
||||||
|
return {0,0};
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace filament::backend
|
}// namespace filament::backend
|
||||||
|
|||||||
@@ -52,30 +52,40 @@ class WGPUVertexBufferInfo : public HwVertexBufferInfo {
|
|||||||
public:
|
public:
|
||||||
WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
|
||||||
AttributeArray const& attributes);
|
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 {
|
// Returns the count of WebGPU native vertex buffer layouts
|
||||||
return mVertexBufferLayout.size();
|
inline uint32_t getWebGPULayoutCount() const {
|
||||||
|
return mActualWebGPULayouts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline wgpu::VertexAttribute const* getVertexAttributeForIndex(uint32_t index) const {
|
// Returns the Filament buffer index for a given WebGPU layout slot
|
||||||
assert_invariant(index < mAttributes.size());
|
inline uint8_t getFilamentBufferIndexForSlot(uint32_t webgpuSlotIndex) const {
|
||||||
return mAttributes[index].data();
|
assert_invariant(webgpuSlotIndex < mSlotMappings.size());
|
||||||
}
|
return mSlotMappings[webgpuSlotIndex].filamentBufferIndex;
|
||||||
|
|
||||||
inline uint32_t getVertexAttributeSize(uint32_t index) const {
|
|
||||||
assert_invariant(index < mAttributes.size());
|
|
||||||
return mAttributes[index].size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO: can we do better in terms on heap management.
|
// Stores the final WebGPU vertex buffer layouts
|
||||||
std::vector<wgpu::VertexBufferLayout> mVertexBufferLayout{};
|
std::vector<wgpu::VertexBufferLayout> mActualWebGPULayouts;
|
||||||
std::vector<std::vector<wgpu::VertexAttribute>> mAttributes{};
|
// 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 {
|
struct WGPUVertexBuffer : public HwVertexBuffer {
|
||||||
WGPUVertexBuffer(wgpu::Device const &device, uint32_t vertexCount, uint32_t bufferCount,
|
WGPUVertexBuffer(wgpu::Device const &device, uint32_t vertexCount, uint32_t bufferCount,
|
||||||
Handle<HwVertexBufferInfo> vbih);
|
Handle<HwVertexBufferInfo> vbih);
|
||||||
@@ -197,57 +207,66 @@ struct WGPURenderPrimitive : public HwRenderPrimitive {
|
|||||||
WGPUIndexBuffer* indexBuffer = nullptr;
|
WGPUIndexBuffer* indexBuffer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WGPURenderTarget : public HwRenderTarget {
|
class WGPURenderTarget : public HwRenderTarget {
|
||||||
public:
|
public:
|
||||||
class Attachment {
|
using Attachment = TargetBufferInfo; // Using TargetBufferInfo directly for attachments
|
||||||
public:
|
|
||||||
friend class WGPURenderTarget;
|
|
||||||
|
|
||||||
Attachment() = default;
|
|
||||||
Attachment(WGPUTexture* gpuTexture, uint8_t level = 0, uint16_t layer = 0)
|
|
||||||
: level(level),
|
|
||||||
layer(layer),
|
|
||||||
texture(gpuTexture->getTexture()),
|
|
||||||
mWGPUTexture(gpuTexture) {}
|
|
||||||
operator bool() const {
|
|
||||||
return mWGPUTexture != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t level = 0;
|
|
||||||
uint16_t layer = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
wgpu::Texture texture = nullptr;
|
|
||||||
WGPUTexture* mWGPUTexture = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples,
|
WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples,
|
||||||
Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]);
|
const MRT& colorAttachments,
|
||||||
|
const Attachment& depthAttachment,
|
||||||
|
const Attachment& stencilAttachment);
|
||||||
|
|
||||||
|
// Default constructor for the default render target
|
||||||
WGPURenderTarget()
|
WGPURenderTarget()
|
||||||
: HwRenderTarget(0, 0),
|
: HwRenderTarget(0, 0),
|
||||||
defaultRenderTarget(true) {}
|
defaultRenderTarget(true),
|
||||||
|
samples(1) {}
|
||||||
|
|
||||||
void setUpRenderPassAttachments(wgpu::RenderPassDescriptor& descriptor,
|
// Updated signature: takes resolved views for custom RTs, and default views for default RT
|
||||||
wgpu::TextureView const& textureView, RenderPassParams const& params);
|
void setUpRenderPassAttachments(
|
||||||
|
wgpu::RenderPassDescriptor& descriptor,
|
||||||
|
RenderPassParams const& params,
|
||||||
|
// For default render target:
|
||||||
|
wgpu::TextureView const& defaultColorTextureView,
|
||||||
|
wgpu::TextureView const& defaultDepthStencilTextureView,
|
||||||
|
// For custom render targets:
|
||||||
|
wgpu::TextureView const* customColorTextureViews, // Array of views
|
||||||
|
uint32_t customColorTextureViewCount,
|
||||||
|
wgpu::TextureView const& customDepthTextureView,
|
||||||
|
wgpu::TextureView const& customStencilTextureView);
|
||||||
|
|
||||||
math::uint2 getAttachmentSize() noexcept;
|
|
||||||
|
math::uint2 getAttachmentSize() const noexcept;
|
||||||
|
|
||||||
bool isDefaultRenderTarget() const { return defaultRenderTarget; }
|
bool isDefaultRenderTarget() const { return defaultRenderTarget; }
|
||||||
uint8_t getSamples() const { return samples; }
|
uint8_t getSamples() const { return samples; }
|
||||||
|
|
||||||
Attachment getDrawColorAttachment(size_t index);
|
// Accessors for the driver to get stored attachment info
|
||||||
Attachment getReadColorAttachment(size_t index);
|
const MRT& getColorAttachmentInfos() const { return mColorAttachments; }
|
||||||
|
const Attachment& getDepthAttachmentInfo() const { return mDepthAttachment; }
|
||||||
|
const Attachment& getStencilAttachmentInfo() const { return mStencilAttachment; }
|
||||||
|
|
||||||
|
// Static helpers for load/store operations
|
||||||
static wgpu::LoadOp getLoadOperation(const RenderPassParams& params, TargetBufferFlags buffer);
|
static wgpu::LoadOp getLoadOperation(const RenderPassParams& params, TargetBufferFlags buffer);
|
||||||
static wgpu::StoreOp getStoreOperation(const RenderPassParams& params, TargetBufferFlags buffer);
|
static wgpu::StoreOp getStoreOperation(const RenderPassParams& params, TargetBufferFlags buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Helper to map MRT index to TargetBufferFlags
|
||||||
|
static TargetBufferFlags getTargetBufferFlagsAt(int mrtIndex);
|
||||||
|
|
||||||
bool defaultRenderTarget = false;
|
bool defaultRenderTarget = false;
|
||||||
uint8_t samples = 1;
|
uint8_t samples = 1;
|
||||||
|
|
||||||
Attachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
MRT mColorAttachments{};
|
||||||
math::uint2 attachmentSize = {};
|
Attachment mDepthAttachment{};
|
||||||
std::vector<wgpu::RenderPassColorAttachment> colorAttachments{};
|
Attachment mStencilAttachment{};
|
||||||
};
|
|
||||||
|
|
||||||
|
// Cached descriptors for the render pass
|
||||||
|
std::vector<wgpu::RenderPassColorAttachment> mColorAttachmentDescriptors;
|
||||||
|
wgpu::RenderPassDepthStencilAttachment mDepthStencilAttachmentDescriptor{};
|
||||||
|
bool mHasDepthStencilAttachment = false;
|
||||||
|
};
|
||||||
}// namespace filament::backend
|
}// namespace filament::backend
|
||||||
#endif// TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
|
#endif// TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device,
|
|||||||
.entryPoint = "main",
|
.entryPoint = "main",
|
||||||
.constantCount = program.constants.size(),
|
.constantCount = program.constants.size(),
|
||||||
.constants = program.constants.data(),
|
.constants = program.constants.data(),
|
||||||
.bufferCount = vertexBufferInfo.getVertexBufferLayoutSize(),
|
.bufferCount = vertexBufferInfo.getWebGPULayoutCount(),
|
||||||
.buffers = vertexBufferInfo.getVertexBufferLayout()
|
.buffers = vertexBufferInfo.getWebGPULayouts()
|
||||||
},
|
},
|
||||||
.primitive = {
|
.primitive = {
|
||||||
.topology = toWebGPU(primitiveType),
|
.topology = toWebGPU(primitiveType),
|
||||||
|
|||||||
@@ -320,11 +320,14 @@ wgpu::TextureView WebGPUSwapChain::getCurrentSurfaceTextureView(
|
|||||||
if (surfaceTexture.status != wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal) {
|
if (surfaceTexture.status != wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrentSurfaceTexture = nullptr;
|
||||||
|
mCurrentSurfaceTexture = surfaceTexture.texture;
|
||||||
// Create a view for this surface texture
|
// Create a view for this surface texture
|
||||||
// TODO: review these initiliazations as webgpu pipeline gets mature
|
// TODO: review these initiliazations as webgpu pipeline gets mature
|
||||||
wgpu::TextureViewDescriptor textureViewDescriptor = {
|
wgpu::TextureViewDescriptor textureViewDescriptor = {
|
||||||
.label = "surface_texture_view",
|
.label = "surface_texture_view",
|
||||||
.format = surfaceTexture.texture.GetFormat(),
|
.format = mCurrentSurfaceTexture.GetFormat(),
|
||||||
.dimension = wgpu::TextureViewDimension::e2D,
|
.dimension = wgpu::TextureViewDimension::e2D,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.mipLevelCount = 1,
|
.mipLevelCount = 1,
|
||||||
@@ -337,6 +340,7 @@ wgpu::TextureView WebGPUSwapChain::getCurrentSurfaceTextureView(
|
|||||||
void WebGPUSwapChain::present() {
|
void WebGPUSwapChain::present() {
|
||||||
assert_invariant(mSurface);
|
assert_invariant(mSurface);
|
||||||
mSurface.Present();
|
mSurface.Present();
|
||||||
|
mCurrentSurfaceTexture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}// namespace filament::backend
|
}// namespace filament::backend
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ private:
|
|||||||
wgpu::TextureFormat mDepthFormat = wgpu::TextureFormat::Undefined;
|
wgpu::TextureFormat mDepthFormat = wgpu::TextureFormat::Undefined;
|
||||||
wgpu::Texture mDepthTexture = nullptr;
|
wgpu::Texture mDepthTexture = nullptr;
|
||||||
wgpu::TextureView mDepthTextureView = nullptr;
|
wgpu::TextureView mDepthTextureView = nullptr;
|
||||||
|
wgpu::Texture mCurrentSurfaceTexture = nullptr; // To hold the texture from getCurrentTexture()
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace filament::backend
|
} // namespace filament::backend
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "regex"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -601,7 +601,6 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
tint::Result<tint::wgsl::writer::Output> wgslOut = tint::wgsl::writer::Generate(tintRead,writerOpts);
|
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.
|
/// An instance of SuccessType that can be used to check a tint Result.
|
||||||
tint::SuccessType tintSuccess;
|
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;
|
slog.e << "Tint writer error: " << wgslOut.Failure().reason << io::endl;
|
||||||
return false;
|
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;
|
return true;
|
||||||
#else
|
#else
|
||||||
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
|
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
|
||||||
|
|||||||
Reference in New Issue
Block a user