Compare commits

...

1 Commits

Author SHA1 Message Date
Matt Hoffman
667da2aabe Create a helper for setting texture uniforms in backend tests.
BUGS=[407799122]
2025-04-14 16:06:03 -05:00
6 changed files with 83 additions and 53 deletions

View File

@@ -23,6 +23,14 @@ namespace test {
using namespace filament::backend; using namespace filament::backend;
filament::backend::descriptor_binding_t TextureBindingConfig::getBinding() const {
return binding.value_or(0);
}
filament::backend::SamplerParams TextureBindingConfig::getParams() const {
return samplerParams.value_or(SamplerParams{});
}
Shader::Shader(DriverApi& api, Cleanup& cleanup, ShaderConfig config) : mCleanup(cleanup) { Shader::Shader(DriverApi& api, Cleanup& cleanup, ShaderConfig config) : mCleanup(cleanup) {
utils::FixedCapacityVector<DescriptorSetLayoutBinding> kLayouts(config.uniforms.size()); utils::FixedCapacityVector<DescriptorSetLayoutBinding> kLayouts(config.uniforms.size());
for (unsigned char i = 0; i < config.uniforms.size(); ++i) { for (unsigned char i = 0; i < config.uniforms.size(); ++i) {
@@ -57,6 +65,19 @@ Shader::Shader(DriverApi& api, Cleanup& cleanup, ShaderConfig config) : mCleanup
mDescriptorSetLayout = cleanup.add( mDescriptorSetLayout = cleanup.add(
api.createDescriptorSetLayout(DescriptorSetLayout{ kLayouts })); api.createDescriptorSetLayout(DescriptorSetLayout{ kLayouts }));
mDefaultDescriptorSet = createDescriptorSet(api);
}
void Shader::updateTextureUniform(filament::backend::DriverApi& api,
TextureBindingConfig config) const {
DescriptorSetHandle descriptorSet = config.descriptorSet.value_or(mDefaultDescriptorSet);
api.updateDescriptorSetTexture(descriptorSet, config.getBinding(), config.textureHandle,
config.getParams());
if (config.alsoBindToSet.has_value()) {
api.bindDescriptorSet(descriptorSet, *config.alsoBindToSet, {});
}
} }
filament::backend::DescriptorSetHandle Shader::createDescriptorSet(DriverApi& api) const { filament::backend::DescriptorSetHandle Shader::createDescriptorSet(DriverApi& api) const {

View File

@@ -61,6 +61,18 @@ struct UniformBindingConfig {
ResolvedUniformBindingConfig resolve(); ResolvedUniformBindingConfig resolve();
}; };
struct TextureBindingConfig {
filament::backend::TextureHandle textureHandle;
std::optional<filament::backend::DescriptorSetHandle> descriptorSet;
std::optional<filament::backend::descriptor_binding_t> binding;
std::optional<filament::backend::SamplerParams> samplerParams;
// If present then the call to update the texture will also bind the descriptor set.
std::optional<filament::backend::descriptor_set_t> alsoBindToSet;
filament::backend::descriptor_binding_t getBinding() const;
filament::backend::SamplerParams getParams() const;
};
class Shader { class Shader {
public: public:
// All graphics resources have their lifetime controlled by the Cleanup and not this object. // All graphics resources have their lifetime controlled by the Cleanup and not this object.
@@ -86,17 +98,20 @@ public:
void bindUniform(filament::backend::DriverApi& api, void bindUniform(filament::backend::DriverApi& api,
filament::backend::Handle<filament::backend::HwBufferObject> hwBuffer, filament::backend::Handle<filament::backend::HwBufferObject> hwBuffer,
UniformBindingConfig config) const; UniformBindingConfig config) const;
void updateTextureUniform(filament::backend::DriverApi& api, TextureBindingConfig config) const;
filament::backend::ProgramHandle getProgram() const;
filament::backend::DescriptorSetLayoutHandle getDescriptorSetLayout() const;
filament::backend::DescriptorSetHandle createDescriptorSet( filament::backend::DescriptorSetHandle createDescriptorSet(
filament::backend::DriverApi& api) const; filament::backend::DriverApi& api) const;
filament::backend::ProgramHandle getProgram() const;
filament::backend::DescriptorSetLayoutHandle getDescriptorSetLayout() const;
protected: protected:
Cleanup& mCleanup; Cleanup& mCleanup;
filament::backend::ProgramHandle mProgram; filament::backend::ProgramHandle mProgram;
filament::backend::DescriptorSetLayoutHandle mDescriptorSetLayout; filament::backend::DescriptorSetLayoutHandle mDescriptorSetLayout;
// Used whenever the caller doesn't provide a descriptor set.
filament::backend::DescriptorSetHandle mDefaultDescriptorSet;
}; };
template<typename UniformType> template<typename UniformType>
@@ -133,12 +148,8 @@ void Shader::bindUniform(filament::backend::DriverApi& api,
UniformBindingConfig config) const { UniformBindingConfig config) const {
auto resolvedConfig = config.resolve<UniformType>(); auto resolvedConfig = config.resolve<UniformType>();
filament::backend::DescriptorSetHandle descriptorSet; filament::backend::DescriptorSetHandle descriptorSet =
if (resolvedConfig.descriptorSet.has_value()) { resolvedConfig.descriptorSet.value_or(mDefaultDescriptorSet);
descriptorSet = *resolvedConfig.descriptorSet;
} else {
descriptorSet = createDescriptorSet(api);
}
api.updateDescriptorSetBuffer(descriptorSet, resolvedConfig.binding, hwBuffer, 0, api.updateDescriptorSetBuffer(descriptorSet, resolvedConfig.binding, hwBuffer, 0,
resolvedConfig.bufferSize); resolvedConfig.bufferSize);

View File

@@ -198,12 +198,14 @@ TEST_F(BackendTest, FeedbackLoops) {
params.viewport.width = kTexWidth >> targetLevel; params.viewport.width = kTexWidth >> targetLevel;
params.viewport.height = kTexHeight >> targetLevel; params.viewport.height = kTexHeight >> targetLevel;
// Each pass needs its own descriptor set.
auto descriptorSet = shader.createDescriptorSet(api); auto descriptorSet = shader.createDescriptorSet(api);
auto textureView = passCleanup.add(api.createTextureView(texture, sourceLevel, 1)); auto textureView = passCleanup.add(api.createTextureView(texture, sourceLevel, 1));
api.updateDescriptorSetTexture(descriptorSet, 0, textureView, { shader.updateTextureUniform(api,
.filterMag = SamplerMagFilter::LINEAR, TextureBindingConfig{ .textureHandle = textureView,
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST .descriptorSet = descriptorSet,
}); .samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST } });
UniformBindingConfig uniformBinding{ UniformBindingConfig uniformBinding{
.binding = 1, .binding = 1,

View File

@@ -329,12 +329,14 @@ TEST_F(LoadImageTest, UpdateImage2D) {
checkerboardPixelBuffer(t.pixelFormat, t.pixelType, 512, t.bufferPadding)); checkerboardPixelBuffer(t.pixelFormat, t.pixelType, 512, t.bufferPadding));
} }
// Each loop needs its own descriptor set.
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api);
api.updateDescriptorSetTexture(descriptorSet, 0, texture, { shader.updateTextureUniform(api,
.filterMag = SamplerMagFilter::NEAREST, TextureBindingConfig{ .textureHandle = texture,
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST }); .descriptorSet = descriptorSet,
.samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::NEAREST,
api.bindDescriptorSet(descriptorSet, 1, {}); .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST },
.alsoBindToSet = 1 });
renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }}, renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }},
defaultRenderTarget, swapChain, shader.getProgram()); defaultRenderTarget, swapChain, shader.getProgram());
@@ -405,13 +407,11 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
api.beginFrame(0, 0, 0); api.beginFrame(0, 0, 0);
// Update samplers. // Update samplers.
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); shader.updateTextureUniform(api,
api.updateDescriptorSetTexture(descriptorSet, 0, texture, { TextureBindingConfig{ .textureHandle = texture,
.filterMag = SamplerMagFilter::LINEAR, .samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST },
}); .alsoBindToSet = 1 });
api.bindDescriptorSet(descriptorSet, 1, {});
renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }}, renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }},
defaultRenderTarget, swapChain, shader.getProgram()); defaultRenderTarget, swapChain, shader.getProgram());
@@ -467,13 +467,11 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
api.beginFrame(0, 0, 0); api.beginFrame(0, 0, 0);
// Update samplers. // Update samplers.
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); shader.updateTextureUniform(api,
api.updateDescriptorSetTexture(descriptorSet, 0, texture, { TextureBindingConfig{ .textureHandle = texture,
.filterMag = SamplerMagFilter::LINEAR, .samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST },
}); .alsoBindToSet = 1 });
api.bindDescriptorSet(descriptorSet, 1, {});
renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }}, renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }},
defaultRenderTarget, swapChain, shader.getProgram()); defaultRenderTarget, swapChain, shader.getProgram());
@@ -541,13 +539,11 @@ TEST_F(LoadImageTest, UpdateImage3D) {
api.beginFrame(0, 0, 0); api.beginFrame(0, 0, 0);
// Update samplers. // Update samplers.
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); shader.updateTextureUniform(api,
api.updateDescriptorSetTexture(descriptorSet, 0, texture, { TextureBindingConfig{ .textureHandle = texture,
.filterMag = SamplerMagFilter::LINEAR, .samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST },
}); .alsoBindToSet = 1 });
api.bindDescriptorSet(descriptorSet, 1, {});
renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }}, renderTriangle({{ DescriptorSetLayoutHandle{}, shader.getDescriptorSetLayout() }},
defaultRenderTarget, swapChain, shader.getProgram()); defaultRenderTarget, swapChain, shader.getProgram());

View File

@@ -171,11 +171,12 @@ TEST_F(BackendTest, TextureViewLod) {
state.rasterState.culling = CullingMode::NONE; state.rasterState.culling = CullingMode::NONE;
DescriptorSetHandle descriptorSet13 = texturedShader.createDescriptorSet(api); DescriptorSetHandle descriptorSet13 = texturedShader.createDescriptorSet(api);
api.updateDescriptorSetTexture(descriptorSet13, 0, texture13, { texturedShader.updateTextureUniform(api,
.filterMag = SamplerMagFilter::NEAREST, TextureBindingConfig{ .textureHandle = texture13,
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST }); .descriptorSet = descriptorSet13,
.samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::NEAREST,
api.bindDescriptorSet(descriptorSet13, 0, {}); .filterMin = SamplerMinFilter::NEAREST },
.alsoBindToSet = 0 });
// Render a triangle to the screen, sampling from mip level 1. // Render a triangle to the screen, sampling from mip level 1.
// Because the min level is 1, the result color should be the white triangle drawn in the // Because the min level is 1, the result color should be the white triangle drawn in the
@@ -189,11 +190,12 @@ TEST_F(BackendTest, TextureViewLod) {
auto texture22 = cleanup.add(api.createTextureView(texture, 2, 2)); auto texture22 = cleanup.add(api.createTextureView(texture, 2, 2));
DescriptorSetHandle descriptorSet22 = texturedShader.createDescriptorSet(api); DescriptorSetHandle descriptorSet22 = texturedShader.createDescriptorSet(api);
api.updateDescriptorSetTexture(descriptorSet22, 0, texture22, { texturedShader.updateTextureUniform(api,
.filterMag = SamplerMagFilter::NEAREST, TextureBindingConfig{ .textureHandle = texture22,
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST }); .descriptorSet = descriptorSet22,
.samplerParams = SamplerParams{ .filterMag = SamplerMagFilter::NEAREST,
api.bindDescriptorSet(descriptorSet22, 0, {}); .filterMin = SamplerMinFilter::NEAREST },
.alsoBindToSet = 0 });
// Render a second, smaller, triangle, again sampling from mip level 1. // Render a second, smaller, triangle, again sampling from mip level 1.
// This triangle should be yellow striped. // This triangle should be yellow striped.

View File

@@ -84,14 +84,12 @@ TEST_F(BackendTest, RenderExternalImageWithoutSet) {
state.rasterState.depthFunc = RasterState::DepthFunc::A; state.rasterState.depthFunc = RasterState::DepthFunc::A;
state.rasterState.culling = CullingMode::NONE; state.rasterState.culling = CullingMode::NONE;
DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api);
api.startCapture(0); api.startCapture(0);
api.makeCurrent(swapChain, swapChain); api.makeCurrent(swapChain, swapChain);
api.beginFrame(0, 0, 0); api.beginFrame(0, 0, 0);
api.updateDescriptorSetTexture(descriptorSet, 0, texture, {}); shader.updateTextureUniform(api,
api.bindDescriptorSet(descriptorSet, 1, {}); TextureBindingConfig{ .textureHandle = texture, .alsoBindToSet = 1 });
// Render a triangle. // Render a triangle.
api.beginRenderPass(defaultRenderTarget, params); api.beginRenderPass(defaultRenderTarget, params);