Compare commits
2 Commits
v1.59.4
...
idris/rend
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ff62402c2 | ||
|
|
595a313686 |
11
.github/workflows/presubmit.yml
vendored
11
.github/workflows/presubmit.yml
vendored
@@ -112,12 +112,11 @@ jobs:
|
||||
run: pip install mako setuptools pyyaml
|
||||
- name: Run script
|
||||
run: |
|
||||
echo "disabled test"
|
||||
# bash test/renderdiff/test.sh
|
||||
# - uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: presubmit-renderdiff-result
|
||||
# path: ./out/renderdiff_tests
|
||||
bash test/renderdiff/test.sh
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: presubmit-renderdiff-result
|
||||
path: ./out/renderdiff_tests
|
||||
|
||||
validate-wgsl-webgpu:
|
||||
name: validate-wgsl-webgpu
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.59.4'
|
||||
implementation 'com.google.android.filament:filament-android:1.59.2'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.59.4'
|
||||
pod 'Filament', '~> 1.59.2'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,9 +7,6 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.59.4
|
||||
|
||||
|
||||
## v1.59.3
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.59.4
|
||||
VERSION_NAME=1.59.2
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -534,9 +534,6 @@ if (APPLE OR LINUX)
|
||||
filamat
|
||||
SPIRV
|
||||
spirv-cross-glsl)
|
||||
# Create input/output directories for test result images.
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/images/actual_images)
|
||||
file(COPY test/expected_images DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/images)
|
||||
endif()
|
||||
|
||||
# TODO: Disabling IOS test due to breakage wrt glslang update
|
||||
|
||||
@@ -35,12 +35,7 @@ using namespace bluevk;
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanPipelineCache::VulkanPipelineCache(VkDevice device)
|
||||
: mDevice(device) {
|
||||
VkPipelineCacheCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
|
||||
};
|
||||
bluevk::vkCreatePipelineCache(mDevice, &createInfo, VKALLOC, &mPipelineCache);
|
||||
}
|
||||
: mDevice(device) {}
|
||||
|
||||
void VulkanPipelineCache::bindLayout(VkPipelineLayout layout) noexcept {
|
||||
mPipelineRequirements.layout = layout;
|
||||
@@ -220,7 +215,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
PipelineCacheEntry cacheEntry = {
|
||||
.lastUsed = mCurrentTime,
|
||||
};
|
||||
VkResult error = vkCreateGraphicsPipelines(mDevice, mPipelineCache, 1, &pipelineCreateInfo,
|
||||
VkResult error = vkCreateGraphicsPipelines(mDevice, VK_NULL_HANDLE, 1, &pipelineCreateInfo,
|
||||
VKALLOC, &cacheEntry.handle);
|
||||
assert_invariant(error == VK_SUCCESS);
|
||||
if (error != VK_SUCCESS) {
|
||||
@@ -276,8 +271,6 @@ void VulkanPipelineCache::terminate() noexcept {
|
||||
}
|
||||
mPipelines.clear();
|
||||
mBoundPipeline = {};
|
||||
|
||||
vkDestroyPipelineCache(mDevice, mPipelineCache, VKALLOC);
|
||||
}
|
||||
|
||||
void VulkanPipelineCache::gc() noexcept {
|
||||
|
||||
@@ -198,10 +198,6 @@ private:
|
||||
// Immutable state.
|
||||
VkDevice mDevice = VK_NULL_HANDLE;
|
||||
|
||||
// Vuklan Driver pipeline cache handle. In the cases a pipeline has been evicted by the `gc`,
|
||||
// recreating the same pipeline is cheaper, helping with frame stalling.
|
||||
VkPipelineCache mPipelineCache = VK_NULL_HANDLE;
|
||||
|
||||
// Current requirements for the pipeline layout, pipeline, and descriptor sets.
|
||||
PipelineKey mPipelineRequirements = {};
|
||||
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -523,7 +542,7 @@ void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
backend::DescriptorSetLayout&& info) {
|
||||
constructHandle<WebGPUDescriptorSetLayout>(dslh, std::move(info), mDevice);
|
||||
constructHandle<WebGPUDescriptorSetLayout>(dslh, std::move(info), &mDevice);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
@@ -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) {
|
||||
@@ -802,7 +822,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> src,
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
|
||||
void WebGPUDriver::readBufferSubData(Handle<HwBufferObject> boh,
|
||||
void WebGPUDriver::readBufferSubData(backend::BufferObjectHandle boh,
|
||||
uint32_t offset, uint32_t size, backend::BufferDescriptor&& p) {
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -854,22 +938,22 @@ void WebGPUDriver::resetState(int) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateDescriptorSetBuffer(
|
||||
Handle<HwDescriptorSet> dsh,
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_binding_t binding,
|
||||
Handle<HwBufferObject> boh,
|
||||
backend::BufferObjectHandle boh,
|
||||
uint32_t offset,
|
||||
uint32_t size) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateDescriptorSetTexture(
|
||||
Handle<HwDescriptorSet> dsh,
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_binding_t binding,
|
||||
Handle<HwTexture> th,
|
||||
backend::TextureHandle th,
|
||||
SamplerParams params) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::bindDescriptorSet(
|
||||
Handle<HwDescriptorSet> dsh,
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_set_t set,
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -76,13 +184,14 @@ wgpu::ShaderStage WebGPUDescriptorSetLayout::filamentStageToWGPUStage(ShaderStag
|
||||
}
|
||||
|
||||
WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout,
|
||||
wgpu::Device const& device) {
|
||||
assert_invariant(device);
|
||||
wgpu::Device const* device) {
|
||||
assert_invariant(device->Get());
|
||||
|
||||
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
|
||||
// debugging. For now, hack an incrementing value.
|
||||
static int layoutNum = 0;
|
||||
|
||||
|
||||
uint samplerCount =
|
||||
std::count_if(layout.bindings.begin(), layout.bindings.end(), [](auto& fEntry) {
|
||||
return fEntry.type == DescriptorType::SAMPLER ||
|
||||
@@ -146,7 +255,13 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
|
||||
.entries = wEntries.data()
|
||||
};
|
||||
// TODO Do we need to defer this until we have more info on textures and samplers??
|
||||
mLayout = device.CreateBindGroupLayout(&layoutDescriptor);
|
||||
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,9 +86,10 @@ struct WGPUBufferObject : HwBufferObject {
|
||||
wgpu::Buffer buffer;
|
||||
const BufferObjectBinding bufferObjectBinding;
|
||||
};
|
||||
|
||||
class WebGPUDescriptorSetLayout : public HwDescriptorSetLayout {
|
||||
public:
|
||||
WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout, wgpu::Device const& device);
|
||||
WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout, wgpu::Device const* device);
|
||||
~WebGPUDescriptorSetLayout();
|
||||
|
||||
private:
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "ImageExpectations.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "utils/Hash.h"
|
||||
@@ -27,17 +28,14 @@
|
||||
#ifndef FILAMENT_IOS
|
||||
|
||||
#include <imageio/ImageEncoder.h>
|
||||
#include <imageio/ImageDecoder.h>
|
||||
#include <image/ColorTransform.h>
|
||||
|
||||
#endif
|
||||
|
||||
ScreenshotParams::ScreenshotParams(int width, int height, std::string fileName,
|
||||
uint32_t expectedHash)
|
||||
: mWidth(width),
|
||||
mHeight(height),
|
||||
mExpectedPixelHash(expectedHash),
|
||||
mFileName(std::move(fileName)) {}
|
||||
uint32_t expectedPixelHash)
|
||||
: mWidth(width), mHeight(height), mFileName(std::move(fileName)),
|
||||
mExpectedPixelHash(expectedPixelHash) {}
|
||||
|
||||
int ScreenshotParams::width() const {
|
||||
return mWidth;
|
||||
@@ -51,28 +49,24 @@ uint32_t ScreenshotParams::expectedHash() const {
|
||||
return mExpectedPixelHash;
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::actualDirectoryPath() {
|
||||
return "images/actual_images";
|
||||
std::string ScreenshotParams::outputDirectoryPath() const {
|
||||
return ".";
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::actualFileName() const {
|
||||
std::string ScreenshotParams::generatedActualFileName() const {
|
||||
return absl::StrFormat("%s_actual.png", mFileName);
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::actualFilePath() const {
|
||||
return absl::StrFormat("%s/%s", actualDirectoryPath(), actualFileName());
|
||||
std::string ScreenshotParams::generatedActualFilePath() const {
|
||||
return absl::StrFormat("%s/%s", outputDirectoryPath(), generatedActualFileName());
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::expectedDirectoryPath() {
|
||||
return "images/expected_images";
|
||||
std::string ScreenshotParams::goldenFileName() const {
|
||||
return absl::StrFormat("%s_golden.png", mFileName);
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::expectedFileName() const {
|
||||
return absl::StrFormat("%s.png", mFileName);
|
||||
}
|
||||
|
||||
std::string ScreenshotParams::expectedFilePath() const {
|
||||
return absl::StrFormat("%s/%s", expectedDirectoryPath(), expectedFileName());
|
||||
std::string ScreenshotParams::goldenFilePath() const {
|
||||
return absl::StrFormat("%s/%s", outputDirectoryPath(), goldenFileName());
|
||||
}
|
||||
|
||||
ImageExpectation::ImageExpectation(const char* fileName, int lineNumber,
|
||||
@@ -100,14 +94,8 @@ void ImageExpectation::compareImage() const {
|
||||
EXPECT_THAT(bytesFilled, testing::IsTrue())
|
||||
<< "Render target wasn't copied to the buffer for " << mFileName;
|
||||
if (bytesFilled) {
|
||||
LoadedPng loadedImage(mParams.expectedFilePath());
|
||||
// Rather than directly compare the two images compare their hashes because comparing very
|
||||
// large arrays generates way too much debug output to be useful.
|
||||
uint32_t actualHash = mResult.hash();
|
||||
uint32_t loadedImageHash = loadedImage.hash();
|
||||
EXPECT_THAT(actualHash, testing::Eq(loadedImageHash));
|
||||
EXPECT_THAT(actualHash, testing::Eq(mParams.expectedHash()));
|
||||
// TODO: Add better debug output, such as generating a diff image.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +136,7 @@ RenderTargetDump::RenderTargetDump(filament::backend::DriverApi& api,
|
||||
image = image::toLinearWithAlpha<uint8_t>(internal->params.width(),
|
||||
internal->params.height(),
|
||||
internal->params.width() * 4, (uint8_t*)buffer);
|
||||
std::string filePath = internal->params.actualFilePath();
|
||||
std::string filePath = internal->params.generatedActualFilePath();
|
||||
std::ofstream pngStream(filePath, std::ios::binary | std::ios::trunc);
|
||||
image::ImageEncoder::encode(pngStream, image::ImageEncoder::Format::PNG, image, "",
|
||||
filePath);
|
||||
@@ -181,29 +169,4 @@ bool RenderTargetDump::bytesFilled() const {
|
||||
return mInternal->bytesFilled;
|
||||
}
|
||||
|
||||
RenderTargetDump::Internal::Internal(const ScreenshotParams& params) : params(params) {}
|
||||
|
||||
LoadedPng::LoadedPng(std::string filePath) {
|
||||
#ifndef FILAMENT_IOS
|
||||
std::ifstream pngStream(filePath, std::ios::binary);
|
||||
image::LinearImage loadedImage = image::ImageDecoder::decode(pngStream, filePath,
|
||||
image::ImageDecoder::ColorSpace::LINEAR);
|
||||
size_t valuesInImage = loadedImage.getWidth() * loadedImage.getHeight() *
|
||||
loadedImage.getChannels();
|
||||
// The linear image is loaded with each component as [0.0, 1.0] but should be [0, 255], so
|
||||
// convert them.
|
||||
mBytes = std::vector<unsigned char>(valuesInImage);
|
||||
for (int i = 0; i < valuesInImage; ++i) {
|
||||
mBytes[i] = static_cast<uint8_t>(loadedImage.get<float>()[i] * 255.0f);
|
||||
}
|
||||
#endif
|
||||
// For platforms that don't support the image loading library, leave the loaded data blank.
|
||||
}
|
||||
|
||||
uint32_t LoadedPng::hash() const {
|
||||
EXPECT_THAT(mBytes, testing::Not(testing::IsEmpty()));
|
||||
if (mBytes.empty()) {
|
||||
return 0;
|
||||
}
|
||||
return utils::hash::murmur3((uint32_t*)mBytes.data(), mBytes.size() / 4, 0);
|
||||
}
|
||||
RenderTargetDump::Internal::Internal(const ScreenshotParams& params) : params(params) {}
|
||||
@@ -46,12 +46,11 @@ public:
|
||||
int height() const;
|
||||
uint32_t expectedHash() const;
|
||||
|
||||
static std::string actualDirectoryPath();
|
||||
std::string actualFileName() const;
|
||||
std::string actualFilePath() const;
|
||||
static std::string expectedDirectoryPath();
|
||||
std::string expectedFileName() const;
|
||||
std::string expectedFilePath() const;
|
||||
std::string outputDirectoryPath() const;
|
||||
std::string generatedActualFileName() const;
|
||||
std::string generatedActualFilePath() const;
|
||||
std::string goldenFileName() const;
|
||||
std::string goldenFilePath() const;
|
||||
|
||||
private:
|
||||
int mWidth;
|
||||
@@ -99,16 +98,6 @@ private:
|
||||
std::unique_ptr<Internal> mInternal;
|
||||
};
|
||||
|
||||
class LoadedPng {
|
||||
public:
|
||||
explicit LoadedPng(std::string filePath);
|
||||
|
||||
uint32_t hash() const;
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> mBytes;
|
||||
};
|
||||
|
||||
class ImageExpectation {
|
||||
public:
|
||||
ImageExpectation(const char* fileName, int lineNumber, filament::backend::DriverApi& api,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.59.4"
|
||||
spec.version = "1.59.2"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.4/filament-v1.59.4-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.2/filament-v1.59.2-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.59.4",
|
||||
"version": "1.59.2",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user