Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
well I tried.
  • Loading branch information
jonahwilliams committed Oct 30, 2023
commit bd3e5dddc0476405712ca40fde6eae34cf75e05c
1 change: 1 addition & 0 deletions impeller/renderer/backend/gles/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ impeller_component("gles_unittests") {
"test/mock_gles.cc",
"test/mock_gles.h",
"test/mock_gles_unittests.cc",
"test/specialization_constants_unittests.cc",
]
deps = [
":gles",
Expand Down
24 changes: 18 additions & 6 deletions impeller/renderer/backend/gles/proc_table_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,29 @@ void ProcTableGLES::ShaderSourceMapping(
ShaderSource(shader, 1u, sources, lengths);
return;
}
const auto& shader_source = ComputeShaderWithDefines(mapping, defines);
if (!shader_source.has_value()) {
VALIDATION_LOG << "Failed to append constant data to shader";
return;
}

const GLchar* sources[] = {
reinterpret_cast<const GLchar*>(shader_source->c_str())};
const GLint lengths[] = {static_cast<GLint>(shader_source->size())};
ShaderSource(shader, 1u, sources, lengths);
}

// Visible For testing.
std::optional<std::string> ProcTableGLES::ComputeShaderWithDefines(
const fml::Mapping& mapping,
const std::vector<int32_t>& defines) const {
auto shader_source = std::string{
reinterpret_cast<const char*>(mapping.GetMapping()), mapping.GetSize()};

auto index = shader_source.find('\n');
if (index == std::string::npos) {
VALIDATION_LOG << "Failed to append constant data to shader";
return;
return std::nullopt;
}

std::stringstream ss;
Expand All @@ -165,11 +181,7 @@ void ProcTableGLES::ShaderSourceMapping(
}
auto define_string = ss.str();
shader_source.insert(index + 1, define_string);

const GLchar* sources[] = {
reinterpret_cast<const GLchar*>(shader_source.c_str())};
const GLint lengths[] = {static_cast<GLint>(shader_source.size())};
ShaderSource(shader, 1u, sources, lengths);
return shader_source;
}

const DescriptionGLES* ProcTableGLES::GetDescription() const {
Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ class ProcTableGLES {

void PopDebugGroup() const;

// Visible For testing.
std::optional<std::string> ComputeShaderWithDefines(
const fml::Mapping& mapping,
const std::vector<int32_t>& defines) const;

private:
bool is_valid_ = false;
std::unique_ptr<DescriptionGLES> description_;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/testing/testing.h" // IWYU pragma: keep
#include "fml/mapping.h"
#include "gtest/gtest.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h"
#include "impeller/renderer/backend/gles/test/mock_gles.h"

namespace impeller {
namespace testing {

TEST(SpecConstant, CanCreateShaderWithSpecializationConstant) {
auto mock_gles = MockGLES::Init();
auto& proc_table = mock_gles->GetProcTable();
auto shader_source =
"#version 100\n"
"#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
"#endif\n"
"void main() { return vec4(0.0); }";
auto test_shader = std::make_shared<fml::DataMapping>(shader_source);

auto result = proc_table.ComputeShaderWithDefines(*test_shader, {0});

auto expected_shader_source =
"#version 100\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 0\n"
"#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
"#endif\n"
"void main() { return vec4(0.0); }";

if (!result.has_value()) {
GTEST_FAIL() << "Expected shader source";
}
ASSERT_EQ(result.value(), expected_shader_source);
}

TEST(SpecConstant, CanCreateShaderWithSpecializationConstantMultipleValues) {
auto mock_gles = MockGLES::Init();
auto& proc_table = mock_gles->GetProcTable();
auto shader_source =
"#version 100\n"
"#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
"#endif\n"
"void main() { return vec4(0.0); }";
auto test_shader = std::make_shared<fml::DataMapping>(shader_source);

auto result =
proc_table.ComputeShaderWithDefines(*test_shader, {0, 1, 2, 3, 4, 5});

auto expected_shader_source =
"#version 100\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 0\n"
"#define SPIRV_CROSS_CONSTANT_ID_1 1\n"
"#define SPIRV_CROSS_CONSTANT_ID_2 2\n"
"#define SPIRV_CROSS_CONSTANT_ID_3 3\n"
"#define SPIRV_CROSS_CONSTANT_ID_4 4\n"
"#define SPIRV_CROSS_CONSTANT_ID_5 5\n"
"#ifndef SPIRV_CROSS_CONSTANT_ID_0\n"
"#define SPIRV_CROSS_CONSTANT_ID_0 1\n"
"#endif\n"
"void main() { return vec4(0.0); }";

if (!result.has_value()) {
GTEST_FAIL() << "Expected shader source";
}
ASSERT_EQ(result.value(), expected_shader_source);
}

} // namespace testing
} // namespace impeller