Compare commits
12 Commits
mhoff/back
...
ebridgewat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31f96c9065 | ||
|
|
1305303f2e | ||
|
|
8532511107 | ||
|
|
b762ccb78c | ||
|
|
3296eb153c | ||
|
|
ae6d1028f7 | ||
|
|
92579b6307 | ||
|
|
315b53c339 | ||
|
|
c55d459986 | ||
|
|
7876695545 | ||
|
|
e1a1464c5d | ||
|
|
67ed5141bf |
@@ -7,5 +7,3 @@ for next branch cut* header.
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.60.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.60.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.60.0'
|
||||
pod 'Filament', '~> 1.60.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,6 +7,12 @@ 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.61.0
|
||||
|
||||
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
|
||||
- samples/texturedquad.cpp now has CLI to select backend api
|
||||
- samples/hellopbr.cpp CLI now allows for selecting webgpu
|
||||
|
||||
## v1.60.1
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.60.0
|
||||
VERSION_NAME=1.60.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -204,23 +204,15 @@ public:
|
||||
}, new T(std::forward<T>(functor))
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the size in bytes needed to fit an image of given dimensions and format
|
||||
* Computes the size in bytes for a pixel of given dimensions and format
|
||||
*
|
||||
* @param format Format of the image pixels
|
||||
* @param type Type of the image pixels
|
||||
* @param stride Stride of a row in pixels
|
||||
* @param height Height of the image in rows
|
||||
* @param alignment Alignment in bytes of pixel rows
|
||||
* @return The buffer size needed to fit this image in bytes
|
||||
* @return The size of the specified pixel in bytes
|
||||
*/
|
||||
static constexpr size_t computeDataSize(PixelDataFormat format, PixelDataType type,
|
||||
size_t stride, size_t height, size_t alignment) noexcept {
|
||||
assert_invariant(alignment);
|
||||
|
||||
static constexpr size_t computePixelSize(PixelDataFormat format, PixelDataType type) noexcept {
|
||||
if (type == PixelDataType::COMPRESSED) {
|
||||
return 0;
|
||||
}
|
||||
@@ -242,7 +234,7 @@ public:
|
||||
case PixelDataFormat::RGB_INTEGER:
|
||||
n = 3;
|
||||
break;
|
||||
case PixelDataFormat::UNUSED: // shouldn't happen (used to be rgbm)
|
||||
case PixelDataFormat::UNUSED:// shouldn't happen (used to be rgbm)
|
||||
case PixelDataFormat::RGBA:
|
||||
case PixelDataFormat::RGBA_INTEGER:
|
||||
n = 4;
|
||||
@@ -251,7 +243,7 @@ public:
|
||||
|
||||
size_t bpp = n;
|
||||
switch (type) {
|
||||
case PixelDataType::COMPRESSED: // Impossible -- to squash the IDE warnings
|
||||
case PixelDataType::COMPRESSED:// Impossible -- to squash the IDE warnings
|
||||
case PixelDataType::UBYTE:
|
||||
case PixelDataType::BYTE:
|
||||
// nothing to do
|
||||
@@ -282,16 +274,35 @@ public:
|
||||
bpp = 2;
|
||||
break;
|
||||
}
|
||||
return bpp;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the size in bytes needed to fit an image of given dimensions and format
|
||||
*
|
||||
* @param format Format of the image pixels
|
||||
* @param type Type of the image pixels
|
||||
* @param stride Stride of a row in pixels
|
||||
* @param height Height of the image in rows
|
||||
* @param alignment Alignment in bytes of pixel rows
|
||||
* @return The buffer size needed to fit this image in bytes
|
||||
*/
|
||||
static constexpr size_t computeDataSize(PixelDataFormat format, PixelDataType type,
|
||||
size_t stride, size_t height, size_t alignment) noexcept {
|
||||
assert_invariant(alignment);
|
||||
|
||||
size_t bpp = computePixelSize(format, type);
|
||||
size_t const bpr = bpp * stride;
|
||||
size_t const bprAligned = (bpr + (alignment - 1)) & (~alignment + 1);
|
||||
return bprAligned * height;
|
||||
}
|
||||
|
||||
//! left coordinate in pixels
|
||||
uint32_t left = 0;
|
||||
uint32_t left = 0;
|
||||
//! top coordinate in pixels
|
||||
uint32_t top = 0;
|
||||
uint32_t top = 0;
|
||||
union {
|
||||
struct {
|
||||
//! stride in pixels
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include <private/backend/BackendUtils.h>
|
||||
#include <math/mat3.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Panic.h>
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
@@ -353,6 +354,17 @@ void WebGPUDriver::destroyProgram(Handle<HwProgram> ph) {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -472,9 +484,9 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
mDevice, flags);
|
||||
assert_invariant(mSwapChain);
|
||||
|
||||
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
|
||||
"background components have been instantiated/selected, such as surface/screen, "
|
||||
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
|
||||
FWGPU_LOGW << "WebGPU support is highly experimental, in development, and tested for only a "
|
||||
"small set of simple samples (e.g. hellotriangle and texturedquad), thus issues "
|
||||
"are likely to be encountered at this stage."
|
||||
<< utils::io::endl;
|
||||
#if !FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) && !defined(NDEBUG)
|
||||
FWGPU_LOGI << "If the FILAMENT_BACKEND_DEBUG_FLAG variable were set with the " << utils::io::hex
|
||||
@@ -579,7 +591,21 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
|
||||
|
||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> rth, TargetBufferFlags targets,
|
||||
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) {}
|
||||
|
||||
@@ -752,11 +778,72 @@ void WebGPUDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh, uint32_t in
|
||||
vertexBuffer->buffers[index] = bufferObject->getBuffer();
|
||||
}
|
||||
|
||||
void WebGPUDriver::update3DImage(Handle<HwTexture> th,
|
||||
uint32_t level, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& data) {
|
||||
scheduleDestroy(std::move(data));
|
||||
void WebGPUDriver::update3DImage(Handle<HwTexture> th, uint32_t level, uint32_t xoffset,
|
||||
uint32_t yoffset, uint32_t zoffset, uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& p) {
|
||||
PixelBufferDescriptor* data = &p;
|
||||
PixelBufferDescriptor reshapedData;
|
||||
if (reshape(p, reshapedData)) {
|
||||
data = &reshapedData;
|
||||
}
|
||||
auto texture = handleCast<WGPUTexture>(th);
|
||||
|
||||
// TODO: Writing to a depth texture is illegal and errors. I'm not sure why Filament is trying
|
||||
// to do so, but early returning is working?
|
||||
if(texture->getAspect() == wgpu::TextureAspect::DepthOnly){
|
||||
scheduleDestroy(std::move(p));
|
||||
return;
|
||||
}
|
||||
size_t blockWidth = texture->getBlockWidth();
|
||||
size_t blockHeight = texture->getBlockHeight();
|
||||
// WebGPU specification requires that for compressed textures, the x and y offsets
|
||||
// must be a multiple of the compressed texture format's block width and height.
|
||||
// See: https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gputexelcopytextureinfo
|
||||
if (blockWidth > 1 || blockHeight > 1) {
|
||||
FILAMENT_CHECK_PRECONDITION(xoffset % blockWidth == 0)
|
||||
<< "xoffset must be aligned to blockwidth, but offset is " << blockWidth
|
||||
<< "and offset is " << xoffset;
|
||||
FILAMENT_CHECK_PRECONDITION(yoffset % blockHeight == 0)
|
||||
<< "yoffset must be aligned to blockHeight, but offset is " << blockHeight
|
||||
<< "and offset is " << yoffset;
|
||||
}
|
||||
|
||||
auto copyInfo = wgpu::TexelCopyTextureInfo{ .texture = texture->getTexture(),
|
||||
.mipLevel = level,
|
||||
.origin = { .x = xoffset, .y = yoffset, .z = zoffset },
|
||||
.aspect = texture->getAspect() };
|
||||
uint32_t bytesPerRow = static_cast<uint32_t>(
|
||||
PixelBufferDescriptor::computePixelSize(data->format, data->type) * width);
|
||||
auto extent = wgpu::Extent3D{ .width = width, .height = height, .depthOrArrayLayers = depth };
|
||||
|
||||
const uint8_t* dataBuff = static_cast<const uint8_t*>(data->buffer);
|
||||
size_t dataSize = data->size;
|
||||
std::unique_ptr<uint8_t[]> paddedBuffer;
|
||||
|
||||
if (bytesPerRow % 256 != 0) {
|
||||
uint32_t padding = 256 - (bytesPerRow % 256);
|
||||
uint32_t paddedBytesPerRow = bytesPerRow + padding;
|
||||
|
||||
size_t paddedBufferSize = static_cast<size_t>(paddedBytesPerRow) * height * depth;
|
||||
paddedBuffer = std::make_unique<uint8_t[]>(paddedBufferSize);
|
||||
uint8_t* dest = paddedBuffer.get();
|
||||
|
||||
for (uint32_t z = 0; z < depth; ++z) {
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
std::memcpy(dest, dataBuff, bytesPerRow);
|
||||
dest += paddedBytesPerRow;
|
||||
dataBuff += bytesPerRow;
|
||||
}
|
||||
}
|
||||
dataBuff = paddedBuffer.get();
|
||||
dataSize = paddedBufferSize;
|
||||
bytesPerRow = paddedBytesPerRow;
|
||||
}
|
||||
|
||||
auto layout = wgpu::TexelCopyBufferLayout{ .bytesPerRow = bytesPerRow, .rowsPerImage = height };
|
||||
|
||||
mQueue.WriteTexture(©Info, dataBuff, dataSize, &layout, &extent);
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
|
||||
void WebGPUDriver::setupExternalImage(void* image) {
|
||||
@@ -783,35 +870,74 @@ void WebGPUDriver::compilePrograms(CompilerPriorityQueue priority,
|
||||
|
||||
void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> rth, RenderPassParams const& params) {
|
||||
assert_invariant(mCommandEncoder);
|
||||
|
||||
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.SetViewport(params.viewport.left, params.viewport.bottom,
|
||||
params.viewport.width, params.viewport.height, params.depthRange.near, params.depthRange.far);
|
||||
// Ensure viewport dimensions are positive
|
||||
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 */) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <private/backend/BackendUtils.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -68,7 +68,7 @@ wgpu::VertexFormat getVertexFormat(filament::backend::ElementType type, bool nor
|
||||
case ElementType::BYTE4: return VertexFormat::Snorm8x4;
|
||||
case ElementType::UBYTE4: return VertexFormat::Unorm8x4;
|
||||
case ElementType::SHORT4: return VertexFormat::Snorm16x4;
|
||||
case ElementType::USHORT4: return VertexFormat::Unorm8x4;
|
||||
case ElementType::USHORT4: return VertexFormat::Unorm16x4;
|
||||
default:
|
||||
FILAMENT_CHECK_POSTCONDITION(false) << "Normalized format does not exist.";
|
||||
return VertexFormat::Float32x3;
|
||||
@@ -502,6 +502,8 @@ WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat forma
|
||||
mUsage = fToWGPUTextureUsage(usage);
|
||||
mFormat = fToWGPUTextureFormat(format);
|
||||
mAspect = fToWGPUTextureViewAspect(usage, format);
|
||||
mBlockWidth = filament::backend::getBlockWidth(format);
|
||||
mBlockHeight = filament::backend::getBlockHeight(format);
|
||||
wgpu::TextureDescriptor textureDescriptor{
|
||||
.label = getUserTextureLabel(target),
|
||||
.usage = mUsage,
|
||||
@@ -548,6 +550,10 @@ WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat forma
|
||||
|
||||
WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept {
|
||||
mTexture = src->mTexture;
|
||||
mAspect = src->mAspect;
|
||||
mBlockWidth = src->mBlockWidth;
|
||||
mBlockHeight = src->mBlockHeight;
|
||||
|
||||
mTexView = makeTextureView(baseLevel, levelCount, target);
|
||||
}
|
||||
|
||||
@@ -917,58 +923,147 @@ wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const u
|
||||
return textureView;
|
||||
}
|
||||
|
||||
WGPURenderTarget::Attachment WGPURenderTarget::getDrawColorAttachment(size_t index) {
|
||||
assert_invariant( index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT);
|
||||
auto result = color[index];
|
||||
if (index == 0 && defaultRenderTarget) {
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
WGPURenderTarget::WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples,
|
||||
const MRT& colorAttachmentsMRT,
|
||||
const Attachment& depthAttachmentInfo,
|
||||
const Attachment& stencilAttachmentInfo)
|
||||
: HwRenderTarget(width, height),
|
||||
defaultRenderTarget(false),
|
||||
samples(samples),
|
||||
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,
|
||||
TargetBufferFlags buffer) {
|
||||
auto clearFlags = params.flags.clear;
|
||||
auto discardStartFlags = params.flags.discardStart;
|
||||
if (any(clearFlags & buffer)) {
|
||||
return wgpu::LoadOp::Clear;
|
||||
} else if (any(discardStartFlags & buffer)) {
|
||||
TargetBufferFlags bufferToOperateOn) {
|
||||
if (any(params.flags.clear & bufferToOperateOn)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Corrected getStoreOperation
|
||||
wgpu::StoreOp WGPURenderTarget::getStoreOperation(RenderPassParams const& params,
|
||||
TargetBufferFlags buffer) {
|
||||
const auto discardEndFlags = params.flags.discardEnd;
|
||||
if (any(discardEndFlags & buffer)) {
|
||||
TargetBufferFlags bufferToOperateOn) {
|
||||
if (any(params.flags.discardEnd & bufferToOperateOn)) {
|
||||
return wgpu::StoreOp::Discard;
|
||||
}
|
||||
return wgpu::StoreOp::Store;
|
||||
}
|
||||
void WGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& descriptor,
|
||||
wgpu::TextureView const& textureView, RenderPassParams const& params) {
|
||||
// auto discardFlags = params.flags.discardEnd;
|
||||
// (void) discardFlags;
|
||||
// std::vector<wgpu::RenderPassColorAttachment> colorAttachments;
|
||||
colorAttachments.clear();
|
||||
for (size_t i = 0; i < 1/*MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT*/; i++) {
|
||||
// auto attachment = getDrawColorAttachment(i);
|
||||
// if (attachment) {
|
||||
wgpu::RenderPassColorAttachment colorAttachment;
|
||||
colorAttachment.view = textureView;
|
||||
colorAttachment.loadOp = getLoadOperation(params, getTargetBufferFlagsAt(i));
|
||||
colorAttachment.storeOp = getStoreOperation(params, getTargetBufferFlagsAt(i));
|
||||
colorAttachment.clearValue = { params.clearColor.r, params.clearColor.g, params.clearColor.b, params.clearColor.a };
|
||||
colorAttachments.emplace_back(colorAttachment);
|
||||
// }
|
||||
|
||||
void WGPURenderTarget::setUpRenderPassAttachments(
|
||||
wgpu::RenderPassDescriptor& descriptor,
|
||||
RenderPassParams const& params,
|
||||
wgpu::TextureView const& defaultColorTextureView,
|
||||
wgpu::TextureView const& defaultDepthStencilTextureView,
|
||||
wgpu::TextureView const* customColorTextureViews,
|
||||
uint32_t customColorTextureViewCount,
|
||||
wgpu::TextureView const& customDepthTextureView,
|
||||
wgpu::TextureView const& customStencilTextureView) {
|
||||
mColorAttachmentDescriptors.clear();
|
||||
mHasDepthStencilAttachment = false;
|
||||
|
||||
if (defaultRenderTarget) {
|
||||
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.depthStencilAttachment = nullptr;
|
||||
descriptor.timestampWrites = nullptr;
|
||||
|
||||
descriptor.colorAttachmentCount = mColorAttachmentDescriptors.size();
|
||||
descriptor.colorAttachments = mColorAttachmentDescriptors.data();
|
||||
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
|
||||
|
||||
@@ -161,6 +161,9 @@ public:
|
||||
wgpu::Device const& device) noexcept;
|
||||
|
||||
WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept;
|
||||
wgpu::TextureAspect getAspect() const { return mAspect; }
|
||||
size_t getBlockWidth() const { return mBlockWidth; }
|
||||
size_t getBlockHeight() const { return mBlockHeight; }
|
||||
|
||||
[[nodiscard]] const wgpu::Texture& getTexture() const { return mTexture; }
|
||||
[[nodiscard]] const wgpu::TextureView& getTexView() const { return mTexView; }
|
||||
@@ -184,6 +187,8 @@ private:
|
||||
uint32_t mArrayLayerCount = 1;
|
||||
wgpu::TextureView mTexView = nullptr;
|
||||
wgpu::TextureUsage fToWGPUTextureUsage(filament::backend::TextureUsage const& fUsage);
|
||||
size_t mBlockWidth;
|
||||
size_t mBlockHeight;
|
||||
};
|
||||
|
||||
struct WGPURenderPrimitive : public HwRenderPrimitive {
|
||||
@@ -192,57 +197,66 @@ struct WGPURenderPrimitive : public HwRenderPrimitive {
|
||||
WGPUIndexBuffer* indexBuffer = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class WGPURenderTarget : public HwRenderTarget {
|
||||
public:
|
||||
class Attachment {
|
||||
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;
|
||||
};
|
||||
using Attachment = TargetBufferInfo; // Using TargetBufferInfo directly for attachments
|
||||
|
||||
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()
|
||||
: HwRenderTarget(0, 0),
|
||||
defaultRenderTarget(true) {}
|
||||
defaultRenderTarget(true),
|
||||
samples(1) {}
|
||||
|
||||
void setUpRenderPassAttachments(wgpu::RenderPassDescriptor& descriptor,
|
||||
wgpu::TextureView const& textureView, RenderPassParams const& params);
|
||||
// Updated signature: takes resolved views for custom RTs, and default views for default RT
|
||||
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; }
|
||||
uint8_t getSamples() const { return samples; }
|
||||
|
||||
Attachment getDrawColorAttachment(size_t index);
|
||||
Attachment getReadColorAttachment(size_t index);
|
||||
// Accessors for the driver to get stored attachment info
|
||||
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::StoreOp getStoreOperation(const RenderPassParams& params, TargetBufferFlags buffer);
|
||||
|
||||
private:
|
||||
// Helper to map MRT index to TargetBufferFlags
|
||||
static TargetBufferFlags getTargetBufferFlagsAt(int mrtIndex);
|
||||
|
||||
bool defaultRenderTarget = false;
|
||||
uint8_t samples = 1;
|
||||
|
||||
Attachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
||||
math::uint2 attachmentSize = {};
|
||||
std::vector<wgpu::RenderPassColorAttachment> colorAttachments{};
|
||||
};
|
||||
MRT mColorAttachments{};
|
||||
Attachment mDepthAttachment{};
|
||||
Attachment mStencilAttachment{};
|
||||
|
||||
// Cached descriptors for the render pass
|
||||
std::vector<wgpu::RenderPassColorAttachment> mColorAttachmentDescriptors;
|
||||
wgpu::RenderPassDepthStencilAttachment mDepthStencilAttachmentDescriptor{};
|
||||
bool mHasDepthStencilAttachment = false;
|
||||
};
|
||||
}// namespace filament::backend
|
||||
#endif// TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
|
||||
|
||||
@@ -32,6 +32,7 @@ static constexpr size_t CONFIG_COMMAND_BUFFERS_SIZE = 3 * CONFIG_MIN_COMMAND
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::backend;
|
||||
using namespace filament::math;
|
||||
|
||||
#ifndef FILAMENT_IOS
|
||||
#include <imageio/ImageEncoder.h>
|
||||
@@ -114,16 +115,27 @@ PipelineState BackendTest::getColorWritePipelineState() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void BackendTest::fullViewport(RenderPassParams& params) {
|
||||
fullViewport(params.viewport);
|
||||
filament::backend::Viewport BackendTest::getFullViewport() const {
|
||||
const NativeView& view = getNativeView();
|
||||
return Viewport {
|
||||
.left = 0,
|
||||
.bottom = 0,
|
||||
.width = static_cast<uint32_t>(view.width),
|
||||
.height = static_cast<uint32_t>(view.height)
|
||||
};
|
||||
}
|
||||
|
||||
void BackendTest::fullViewport(Viewport& viewport) {
|
||||
const NativeView& view = getNativeView();
|
||||
viewport.left = 0;
|
||||
viewport.bottom = 0;
|
||||
viewport.width = view.width;
|
||||
viewport.height = view.height;
|
||||
filament::backend::RenderPassParams BackendTest::getClearColorRenderPass(float4 color) {
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.clearColor = color;
|
||||
return params;
|
||||
}
|
||||
|
||||
filament::backend::RenderPassParams BackendTest::getNoClearRenderPass() {
|
||||
return RenderPassParams{};
|
||||
}
|
||||
|
||||
void BackendTest::renderTriangle(
|
||||
@@ -131,14 +143,9 @@ void BackendTest::renderTriangle(
|
||||
Handle<filament::backend::HwRenderTarget> renderTarget,
|
||||
Handle<filament::backend::HwSwapChain> swapChain,
|
||||
Handle<filament::backend::HwProgram> program) {
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = {0.f, 0.f, 1.f, 1.f};
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.viewport.height = 512;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport.width = 512;
|
||||
params.viewport.height = 512;
|
||||
renderTriangle(pipelineLayout, renderTarget, swapChain, program, params);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,12 @@ protected:
|
||||
|
||||
static filament::backend::PipelineState getColorWritePipelineState();
|
||||
|
||||
// Helper methods to set the viewport to the full extent of the swap chain.
|
||||
static void fullViewport(filament::backend::RenderPassParams& params);
|
||||
static void fullViewport(filament::backend::Viewport& viewport);
|
||||
// Gets the full back buffer's viewport
|
||||
filament::backend::Viewport getFullViewport() const;
|
||||
// If color is unset this defaults to using opaque cyan
|
||||
static filament::backend::RenderPassParams getClearColorRenderPass(
|
||||
filament::math::float4 color = filament::math::float4(0, 1, 1, 1));
|
||||
static filament::backend::RenderPassParams getNoClearRenderPass();
|
||||
|
||||
void renderTriangle(
|
||||
filament::backend::PipelineLayout const& pipelineLayout,
|
||||
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -151,3 +151,6 @@ if __name__ == "__main__":
|
||||
results.show_images(file_prefix)
|
||||
else:
|
||||
results.batch_move(args.batch)
|
||||
print("--------------------------------------------------------")
|
||||
print("REMEMBER TO RESYNC CMAKE AND UPDATE HASHES IN TEST FILES")
|
||||
print("--------------------------------------------------------")
|
||||
|
||||
@@ -305,11 +305,7 @@ TEST_F(BlitTest, ColorResolve) {
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.clearColor = float4(1, 1, 0, 1);
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport.width = kSrcTexWidth;
|
||||
params.viewport.height = kSrcTexHeight;
|
||||
|
||||
@@ -337,7 +333,7 @@ TEST_F(BlitTest, ColorResolve) {
|
||||
SamplerMagFilter::NEAREST);
|
||||
|
||||
EXPECT_IMAGE(dstRenderTarget, getExpectations(),
|
||||
ScreenshotParams(kDstTexWidth, kDstTexHeight, "ColorResolve", 0xebfac2ef));
|
||||
ScreenshotParams(kDstTexWidth, kDstTexHeight, "ColorResolve", 531759687));
|
||||
}
|
||||
|
||||
TEST_F(BlitTest, Blit2DTextureArray) {
|
||||
|
||||
@@ -79,12 +79,8 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) {
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 1.f, 0.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
// Create a uniform buffer.
|
||||
// We use STATIC here, even though the buffer is updated, to force the Metal backend to use
|
||||
@@ -157,6 +153,9 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) {
|
||||
TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
|
||||
NONFATAL_FAIL_IF(SkipEnvironment(OperatingSystem::APPLE, Backend::VULKAN),
|
||||
"All values including alpha are written as 0, see b/417254943");
|
||||
constexpr int kTexWidth = 512;
|
||||
constexpr int kTexHeight = 512;
|
||||
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(api);
|
||||
|
||||
@@ -177,9 +176,9 @@ TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
|
||||
|
||||
// Create a render target.
|
||||
auto colorTexture = cleanup.add(api.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::RGBA8, 1, 512, 512, 1, TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureFormat::RGBA8, 1, kTexWidth, kTexHeight, 1, TextureUsage::COLOR_ATTACHMENT));
|
||||
auto renderTarget = cleanup.add(api.createRenderTarget(
|
||||
TargetBufferFlags::COLOR0, 512, 512, 1, 0, {{ colorTexture }}, {}, {}));
|
||||
TargetBufferFlags::COLOR0, kTexWidth, kTexHeight, 1, 0, {{ colorTexture }}, {}, {}));
|
||||
|
||||
// Upload uniforms for the first triangle.
|
||||
// Upload the uniform, but with an offset to accommodate the padding in the shader's
|
||||
@@ -190,13 +189,9 @@ TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
|
||||
.offset = { 0.0f, 0.0f, 0.0f, 0.0f }
|
||||
});
|
||||
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 0.f, 1.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.viewport.height = 512;
|
||||
params.viewport.width = 512;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport.height = kTexWidth;
|
||||
params.viewport.width = kTexHeight;
|
||||
renderTriangle({ { shader.getDescriptorSetLayout() } }, renderTarget, swapChain,
|
||||
shader.getProgram(), params);
|
||||
|
||||
@@ -221,7 +216,7 @@ TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) {
|
||||
|
||||
|
||||
EXPECT_IMAGE(renderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "BufferObjectUpdateWithOffset", 91322442));
|
||||
ScreenshotParams(kTexWidth, kTexHeight, "BufferObjectUpdateWithOffset", 2320747245));
|
||||
|
||||
api.flush();
|
||||
api.commit(swapChain);
|
||||
|
||||
@@ -161,12 +161,11 @@ TEST_F(BackendTest, FeedbackLoops) {
|
||||
for (int frame = 0; frame < kNumFrames; frame++) {
|
||||
|
||||
// Prep for rendering.
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::NONE;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
|
||||
RenderPassParams params = getNoClearRenderPass();
|
||||
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
api.beginFrame(0, 0, 0);
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ TEST_F(LoadImageTest, UpdateImage2D) {
|
||||
FAIL_IF(Backend::VULKAN, "Multiple test cases crash, see b/417481434");
|
||||
|
||||
// All of these test cases should result in the same rendered image, and thus the same hash.
|
||||
static const uint32_t expectedHash = 3644679986;
|
||||
static const uint32_t expectedHash = 1875922935;
|
||||
|
||||
struct TestCase {
|
||||
const char* name;
|
||||
@@ -417,7 +417,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
|
||||
defaultRenderTarget, swapChain, shader.getProgram());
|
||||
|
||||
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "UpdateImageSRGB", 359858623));
|
||||
ScreenshotParams(512, 512, "UpdateImageSRGB", 3300305265));
|
||||
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
@@ -476,7 +476,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
|
||||
defaultRenderTarget, swapChain, shader.getProgram());
|
||||
|
||||
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "UpdateImageMipLevel", 3644679986));
|
||||
ScreenshotParams(512, 512, "UpdateImageMipLevel", 1875922935));
|
||||
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
@@ -550,7 +550,7 @@ TEST_F(LoadImageTest, UpdateImage3D) {
|
||||
defaultRenderTarget, swapChain, shader.getProgram());
|
||||
|
||||
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "UpdateImage3D", 3644679986));
|
||||
ScreenshotParams(512, 512, "UpdateImage3D", 1875922935));
|
||||
}
|
||||
|
||||
api.stopCapture();
|
||||
|
||||
@@ -104,12 +104,9 @@ TEST_F(BackendTest, MRT) {
|
||||
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = {0.f, 1.f, 0.f, 1.f};
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
api.startCapture(0);
|
||||
|
||||
|
||||
@@ -138,13 +138,12 @@ TEST_F(BackendTest, TextureViewLod) {
|
||||
TargetBufferFlags::COLOR, 32, 32, 1, 0,
|
||||
{texture, 2 /* level */, 0 /* layer */}, {}, {}));
|
||||
{
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::NONE;
|
||||
params.flags.discardStart = TargetBufferFlags::NONE;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
whiteShader.addProgramToPipelineState(state);
|
||||
|
||||
RenderPassParams params = getNoClearRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
api.beginRenderPass(renderTarget, params);
|
||||
api.draw(state, triangle.getRenderPrimitive(), 0, 3, 1);
|
||||
api.endRenderPass();
|
||||
@@ -153,15 +152,12 @@ TEST_F(BackendTest, TextureViewLod) {
|
||||
backend::Handle<HwRenderTarget> defaultRenderTarget =
|
||||
cleanup.add(api.createDefaultRenderTarget(0));
|
||||
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = {0.f, 0.f, 0.5f, 1.f};
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
texturedShader.addProgramToPipelineState(state);
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
DescriptorSetHandle descriptorSet13 = texturedShader.createDescriptorSet(api);
|
||||
api.updateDescriptorSetTexture(descriptorSet13, 0, texture13, {
|
||||
.filterMag = SamplerMagFilter::NEAREST,
|
||||
|
||||
@@ -81,12 +81,9 @@ TEST_F(BackendTest, MissingRequiredAttributes) {
|
||||
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 1.f, 0.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
api.startCapture(0);
|
||||
|
||||
|
||||
@@ -130,12 +130,8 @@ TEST_F(BackendTest, PushConstants) {
|
||||
|
||||
TrianglePrimitive triangle(api);
|
||||
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR0;
|
||||
params.viewport = { 0, 0, 512, 512 };
|
||||
params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
PipelineState ps = {};
|
||||
ps.program = program;
|
||||
@@ -183,7 +179,8 @@ TEST_F(BackendTest, PushConstants) {
|
||||
api.endRenderPass();
|
||||
|
||||
EXPECT_IMAGE(renderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "pushConstants", 1957275826));
|
||||
ScreenshotParams(params.viewport.width, params.viewport.height, "pushConstants",
|
||||
3575588741));
|
||||
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
@@ -279,14 +279,9 @@ TEST_F(ReadPixelsTest, ReadPixels) {
|
||||
|
||||
TrianglePrimitive const triangle(api);
|
||||
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 0.f, 1.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.viewport.height = t.getRenderTargetSize();
|
||||
RenderPassParams params = getClearColorRenderPass(math::float4(0, 0, 1, 1));
|
||||
params.viewport.width = t.getRenderTargetSize();
|
||||
params.viewport.height = t.getRenderTargetSize();
|
||||
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
api.beginFrame(0, 0, 0);
|
||||
@@ -399,14 +394,10 @@ TEST_F(ReadPixelsTest, ReadPixelsPerformance) {
|
||||
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 0.f, 1.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
params.viewport.height = renderTargetSize;
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass(math::float4(0, 0, 1, 1));
|
||||
params.viewport.width = renderTargetSize;
|
||||
params.viewport.height = renderTargetSize;
|
||||
|
||||
void* buffer = calloc(1, renderTargetSize * renderTargetSize * 4);
|
||||
|
||||
|
||||
@@ -75,12 +75,9 @@ TEST_F(BackendTest, RenderExternalImageWithoutSet) {
|
||||
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 1.f, 0.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api);
|
||||
|
||||
@@ -175,12 +172,9 @@ TEST_F(BackendTest, RenderExternalImage) {
|
||||
|
||||
PipelineState state = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(state);
|
||||
RenderPassParams params = {};
|
||||
fullViewport(params);
|
||||
params.flags.clear = TargetBufferFlags::COLOR;
|
||||
params.clearColor = { 0.f, 1.f, 0.f, 1.f };
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = getFullViewport();
|
||||
|
||||
api.startCapture(0);
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
@@ -198,7 +192,7 @@ TEST_F(BackendTest, RenderExternalImage) {
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
EXPECT_IMAGE(defaultRenderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "RenderExternalImage", 267229901));
|
||||
ScreenshotParams(512, 512, "RenderExternalImage", 1206264951));
|
||||
|
||||
api.stopCapture(0);
|
||||
api.finish();
|
||||
|
||||
@@ -114,12 +114,8 @@ TEST_F(BackendTest, ScissorViewportRegion) {
|
||||
TrianglePrimitive triangle(api);
|
||||
|
||||
// Render a white triangle over blue.
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR0;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = srcRect;
|
||||
params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
PipelineState ps = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(ps);
|
||||
@@ -133,7 +129,7 @@ TEST_F(BackendTest, ScissorViewportRegion) {
|
||||
api.endRenderPass();
|
||||
|
||||
EXPECT_IMAGE(fullRenderTarget, getExpectations(),
|
||||
ScreenshotParams(kSrcTexWidth >> 1, kSrcTexHeight >> 1, "scissor", 0xAB3D1C53));
|
||||
ScreenshotParams(kSrcTexWidth >> 1, kSrcTexHeight >> 1, "scissor", 15842520));
|
||||
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
@@ -194,12 +190,8 @@ TEST_F(BackendTest, ScissorViewportEdgeCases) {
|
||||
TrianglePrimitive triangle(api);
|
||||
|
||||
// Render a white triangle over blue.
|
||||
RenderPassParams params = {};
|
||||
params.flags.clear = TargetBufferFlags::COLOR0;
|
||||
RenderPassParams params = getClearColorRenderPass();
|
||||
params.viewport = bottomLeftViewport;
|
||||
params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
params.flags.discardStart = TargetBufferFlags::ALL;
|
||||
params.flags.discardEnd = TargetBufferFlags::NONE;
|
||||
|
||||
PipelineState ps = getColorWritePipelineState();
|
||||
shader.addProgramToPipelineState(ps);
|
||||
@@ -221,7 +213,7 @@ TEST_F(BackendTest, ScissorViewportEdgeCases) {
|
||||
api.endRenderPass();
|
||||
|
||||
EXPECT_IMAGE(renderTarget, getExpectations(),
|
||||
ScreenshotParams(512, 512, "ScissorViewportEdgeCases", 0x6BF00F31));
|
||||
ScreenshotParams(512, 512, "ScissorViewportEdgeCases", 2199186852));
|
||||
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.60.0"
|
||||
spec.version = "1.60.1"
|
||||
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.60.0/filament-v1.60.0-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.60.1/filament-v1.60.1-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>// for printing usage/help
|
||||
|
||||
#include "generated/resources/resources.h"
|
||||
#include "generated/resources/monkey.h"
|
||||
@@ -63,7 +64,8 @@ static void printUsage(char* name) {
|
||||
" --help, -h\n"
|
||||
" Prints this message\n\n"
|
||||
" --api, -a\n"
|
||||
" Specify the backend API: opengl, vulkan, or metal\n"
|
||||
" Specify the backend API: opengl, vulkan, metal, or webgpu\n"
|
||||
" NOTE that webgpu is not yet functional (it is in development).\n"
|
||||
);
|
||||
const std::string from("EXEC");
|
||||
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
|
||||
@@ -95,8 +97,11 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
|
||||
app->config.backend = Engine::Backend::VULKAN;
|
||||
} else if (arg == "metal") {
|
||||
app->config.backend = Engine::Backend::METAL;
|
||||
} else if (arg == "webgpu") {
|
||||
app->config.backend = Engine::Backend::WEBGPU;
|
||||
} else {
|
||||
std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n";
|
||||
std::cerr << "Unrecognized backend. Must be "
|
||||
"'opengl'|'vulkan'|'metal'|'webgpu'.\n";
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <string>// for printing usage/help
|
||||
|
||||
|
||||
#include "generated/resources/resources.h"
|
||||
@@ -78,10 +79,6 @@ static void printUsage(char* name) {
|
||||
" Prints this message\n\n"
|
||||
" --api, -a\n"
|
||||
" Specify the backend API: opengl, vulkan, metal, or webgpu\n"
|
||||
" (note: webgpu is a no-op for now, printing backend\n"
|
||||
" component info if FILAMENT_BACKEND_DEBUG_FLAG, \n"
|
||||
" set at build time, includes the \n"
|
||||
" FWGPU_PRINT_SYSTEM bit flag 0x2)\n"
|
||||
);
|
||||
const std::string from("HELLOTRIANGLE");
|
||||
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
#include <filamentapp/Config.h>
|
||||
#include <filamentapp/FilamentApp.h>
|
||||
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <iostream> // for cerr
|
||||
#include <string> // for printing usage/help
|
||||
|
||||
#include "generated/resources/resources.h"
|
||||
|
||||
@@ -76,9 +79,63 @@ static constexpr uint16_t QUAD_INDICES[6] = {
|
||||
3, 2, 1,
|
||||
};
|
||||
|
||||
static void printUsage(char* name) {
|
||||
std::string exec_name(utils::Path(name).getName());
|
||||
std::string usage("TEXTUREDQUAD renders a textured quad moving back and forth in a loop\n"
|
||||
"Usage:\n"
|
||||
" TEXTUREDQUAD [options]\n"
|
||||
"Options:\n"
|
||||
" --help, -h\n"
|
||||
" Prints this message\n\n"
|
||||
" --api, -a\n"
|
||||
" Specify the backend API: opengl, vulkan, metal, or webgpu\n");
|
||||
const std::string from("TEXTUREDQUAD");
|
||||
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
|
||||
usage.replace(pos, from.length(), exec_name);
|
||||
}
|
||||
std::cout << usage;
|
||||
}
|
||||
|
||||
static int handleCommandLineArguments(int argc, char* argv[], Config& config) {
|
||||
static constexpr const char* OPTSTR = "ha:";
|
||||
static const struct option OPTIONS[] = {
|
||||
{ "help", no_argument, nullptr, 'h' },
|
||||
{ "api", required_argument, nullptr, 'a' },
|
||||
{ nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
|
||||
std::string arg(optarg ? optarg : "");
|
||||
switch (opt) {
|
||||
default:
|
||||
case 'h':
|
||||
printUsage(argv[0]);
|
||||
exit(0);
|
||||
case 'a':
|
||||
if (arg == "opengl") {
|
||||
config.backend = Engine::Backend::OPENGL;
|
||||
} else if (arg == "vulkan") {
|
||||
config.backend = Engine::Backend::VULKAN;
|
||||
} else if (arg == "metal") {
|
||||
config.backend = Engine::Backend::METAL;
|
||||
} else if (arg == "webgpu") {
|
||||
config.backend = Engine::Backend::WEBGPU;
|
||||
} else {
|
||||
std::cerr << "Unrecognized backend. Must be "
|
||||
"'opengl'|'vulkan'|'metal'|'webgpu'.\n";
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Config config;
|
||||
config.title = "texturedquad";
|
||||
handleCommandLineArguments(argc, argv, config);
|
||||
|
||||
App app;
|
||||
auto setup = [&app](Engine* engine, View* view, Scene* scene) {
|
||||
|
||||
@@ -155,15 +155,15 @@ Light getLight(const uint lightIndex) {
|
||||
light.channels = int(channels);
|
||||
light.contactShadows = bool(typeShadow & 0x10u);
|
||||
#if defined(VARIANT_HAS_DYNAMIC_LIGHTING)
|
||||
light.type = (typeShadow & 0x1u);
|
||||
light.lightType = (typeShadow & 0x1u);
|
||||
#if defined(VARIANT_HAS_SHADOWING)
|
||||
light.shadowIndex = int((typeShadow >> 8u) & 0xFFu);
|
||||
light.castsShadows = bool(channels & 0x10000u);
|
||||
if (light.type == LIGHT_TYPE_SPOT) {
|
||||
if (light.lightType == LIGHT_TYPE_SPOT) {
|
||||
light.zLight = dot(shadowUniforms.shadows[light.shadowIndex].lightFromWorldZ, vec4(worldPosition, 1.0));
|
||||
}
|
||||
#endif
|
||||
if (light.type == LIGHT_TYPE_SPOT) {
|
||||
if (light.lightType == LIGHT_TYPE_SPOT) {
|
||||
light.attenuation *= getAngleAttenuation(-direction, light.l, scaleOffset);
|
||||
}
|
||||
#endif
|
||||
@@ -211,7 +211,7 @@ void evaluatePunctualLights(const MaterialInputs material,
|
||||
if (light.NoL > 0.0) {
|
||||
if (light.castsShadows) {
|
||||
int shadowIndex = light.shadowIndex;
|
||||
if (light.type == LIGHT_TYPE_POINT) {
|
||||
if (light.lightType == LIGHT_TYPE_POINT) {
|
||||
// point-light shadows are sampled from a direction
|
||||
highp vec3 r = getWorldPosition() - light.worldPosition;
|
||||
int face = getPointLightFace(r);
|
||||
|
||||
@@ -8,7 +8,7 @@ struct Light {
|
||||
float zLight;
|
||||
bool castsShadows;
|
||||
bool contactShadows;
|
||||
uint type;
|
||||
uint lightType;
|
||||
int shadowIndex;
|
||||
int channels;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.60.0",
|
||||
"version": "1.60.1",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||