Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions tensorflow_graphics/rendering/opengl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ py_test(

cc_library(
name = "rasterizer",
srcs = ["rasterizer.cc"],
hdrs = ["rasterizer.h"],
deps = [
":gl_program",
Expand Down Expand Up @@ -303,8 +304,10 @@ tf_custom_op_library(
"gl_shader_storage_buffer.cc",
"gl_shader_storage_buffer.h",
"macros.h",
"rasterizer.cc",
"rasterizer.h",
"rasterizer_op.cc",
"rasterizer_with_context.cc",
"rasterizer_with_context.h",
"thread_safe_resource_pool.h",
],
Expand Down Expand Up @@ -362,6 +365,7 @@ py_test(

cc_library(
name = "rasterizer_with_context",
srcs = ["rasterizer_with_context.cc"],
hdrs = ["rasterizer_with_context.h"],
deps = [
":egl_offscreen_context",
Expand All @@ -384,6 +388,7 @@ cc_test(
":thread_safe_resource_pool",
"//third_party/tensorflow/core:lib",
"//third_party/tensorflow/core:test",
"@com_google_absl//absl/types:span",
"@com_google_googletest//:gtest_main",
],
)
Expand Down
99 changes: 99 additions & 0 deletions tensorflow_graphics/rendering/opengl/rasterizer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* Copyright 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow_graphics/rendering/opengl/rasterizer.h"

Rasterizer::Rasterizer(
std::unique_ptr<gl_utils::Program>&& program,
std::unique_ptr<gl_utils::RenderTargets>&& render_targets, float clear_r,
float clear_g, float clear_b, float clear_depth)
: program_(std::move(program)),
render_targets_(std::move(render_targets)),
clear_r_(clear_r),
clear_g_(clear_g),
clear_b_(clear_b),
clear_depth_(clear_depth) {}

Rasterizer::~Rasterizer() {}

void Rasterizer::Reset() {
program_.reset();
render_targets_.reset();
for (auto&& buffer : shader_storage_buffers_) buffer.second.reset();
}

tensorflow::Status Rasterizer::Render(int num_points,
absl::Span<float> result) {
return RenderImpl(num_points, result);
}

tensorflow::Status Rasterizer::Render(int num_points,
absl::Span<unsigned char> result) {
return RenderImpl(num_points, result);
}

tensorflow::Status Rasterizer::SetUniformMatrix(
const std::string& name, int num_columns, int num_rows, bool transpose,
absl::Span<const float> matrix) {
if (size_t(num_rows * num_columns) != matrix.size())
return TFG_INTERNAL_ERROR("num_rows * num_columns != matrix.size()");

typedef void (*setter_fn)(GLint location, GLsizei count, GLboolean transpose,
const GLfloat* value);

static const auto type_mapping =
std::unordered_map<int, std::tuple<int, int, setter_fn>>({
{GL_FLOAT_MAT2, std::make_tuple(2, 2, glUniformMatrix2fv)},
{GL_FLOAT_MAT3, std::make_tuple(3, 3, glUniformMatrix3fv)},
{GL_FLOAT_MAT4, std::make_tuple(4, 4, glUniformMatrix4fv)},
{GL_FLOAT_MAT2x3, std::make_tuple(2, 3, glUniformMatrix2x3fv)},
{GL_FLOAT_MAT2x4, std::make_tuple(2, 4, glUniformMatrix2x4fv)},
{GL_FLOAT_MAT3x2, std::make_tuple(3, 2, glUniformMatrix3x2fv)},
{GL_FLOAT_MAT3x4, std::make_tuple(3, 4, glUniformMatrix3x4fv)},
{GL_FLOAT_MAT4x2, std::make_tuple(4, 2, glUniformMatrix4x2fv)},
{GL_FLOAT_MAT4x3, std::make_tuple(4, 3, glUniformMatrix4x3fv)},
});

GLint uniform_type;
GLenum property = GL_TYPE;

TF_RETURN_IF_ERROR(program_->GetResourceProperty(
name, GL_UNIFORM, 1, &property, 1, &uniform_type));

// Is a resource active under that name?
if (uniform_type == GLint(GL_INVALID_INDEX))
return TFG_INTERNAL_ERROR("GL_INVALID_INDEX");

auto type_info = type_mapping.find(uniform_type);
if (type_info == type_mapping.end())
return TFG_INTERNAL_ERROR("Unsupported type");
if (std::get<0>(type_info->second) != num_columns ||
std::get<1>(type_info->second) != num_rows)
return TFG_INTERNAL_ERROR("Invalid dimensions");

GLint uniform_location;
property = GL_LOCATION;
TF_RETURN_IF_ERROR(program_->GetResourceProperty(
name, GL_UNIFORM, 1, &property, 1, &uniform_location));

TF_RETURN_IF_ERROR(program_->Use());
auto program_cleanup = MakeCleanup([this]() { return program_->Detach(); });

// Specify the value of the uniform in the current program.
TFG_RETURN_IF_GL_ERROR(std::get<2>(type_info->second)(
uniform_location, 1, transpose ? GL_TRUE : GL_FALSE, matrix.data()));

// Cleanup the program; no program is active at this point.
return tensorflow::Status::OK();
}
135 changes: 34 additions & 101 deletions tensorflow_graphics/rendering/opengl/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ limitations under the License.
#include "tensorflow_graphics/rendering/opengl/gl_shader_storage_buffer.h"
#include "tensorflow_graphics/util/cleanup.h"

template <typename T>
class RasterizerWithContext;

template <typename T>
class Rasterizer {
public:
virtual ~Rasterizer();

// Creates a Rasterizer holding a valid OpenGL program and render buffers.
//
// Note: the template argument defines the data type stored in the render
// buffer. See the documentation of RenderTargets::Create for more details.
//
// Arguments:
// * width: width of the render buffers.
// * height: height of the render buffers.
Expand All @@ -46,6 +47,7 @@ class Rasterizer {
// Returns:
// A tensorflow::Status object storing tensorflow::Status::OK() on success,
// and an object of type tensorflow::errors otherwise.
template <typename T>
static tensorflow::Status Create(const int width, const int height,
const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
Expand All @@ -70,6 +72,7 @@ class Rasterizer {
// Returns:
// A tensorflow::Status object storing tensorflow::Status::OK() on success,
// and an object of type tensorflow::errors otherwise.
template <typename T>
static tensorflow::Status Create(const int width, const int height,
const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
Expand All @@ -83,12 +86,15 @@ class Rasterizer {
// Arguments:
// * num_points: the number of primitives to render.
// * result: if the method succeeds, a buffer that stores the rendering
// result.
// result. This buffer must be of size 4 * width * height, where the values
// of width and height must at least match those used in when calling Create.
//
// Returns:
// A tensorflow::Status object storing tensorflow::Status::OK() on success,
// and an object of type tensorflow::errors otherwise.
virtual tensorflow::Status Render(int num_points, absl::Span<T> result);
virtual tensorflow::Status Render(int num_points, absl::Span<float> result);
virtual tensorflow::Status Render(int num_points,
absl::Span<unsigned char> result);

// Uploads data to a shader storage buffer.
//
Expand All @@ -99,9 +105,9 @@ class Rasterizer {
// Returns:
// A tensorflow::Status object storing tensorflow::Status::OK() on success,
// and an object of type tensorflow::errors otherwise.
template <typename S>
template <typename T>
tensorflow::Status SetShaderStorageBuffer(const std::string& name,
absl::Span<const S> data);
absl::Span<const T> data);

// Specifies the value of a uniform matrix.
//
Expand Down Expand Up @@ -132,6 +138,8 @@ class Rasterizer {
Rasterizer(Rasterizer&&) = delete;
Rasterizer& operator=(const Rasterizer&) = delete;
Rasterizer& operator=(Rasterizer&&) = delete;
template <typename T>
tensorflow::Status RenderImpl(int num_points, absl::Span<T> result);
void Reset();

std::unique_ptr<gl_utils::Program> program_;
Expand All @@ -141,40 +149,27 @@ class Rasterizer {
shader_storage_buffers_;
float clear_r_, clear_g_, clear_b_, clear_depth_;

friend class RasterizerWithContext<T>;
friend class RasterizerWithContext;
};

template <typename T>
Rasterizer<T>::Rasterizer(
std::unique_ptr<gl_utils::Program>&& program,
std::unique_ptr<gl_utils::RenderTargets>&& render_targets, float clear_r,
float clear_g, float clear_b, float clear_depth)
: program_(std::move(program)),
render_targets_(std::move(render_targets)),
clear_r_(clear_r),
clear_g_(clear_g),
clear_b_(clear_b),
clear_depth_(clear_depth) {}

template <typename T>
Rasterizer<T>::~Rasterizer() {}

template <typename T>
tensorflow::Status Rasterizer<T>::Create(
const int width, const int height, const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
const std::string& fragment_shader_source,
std::unique_ptr<Rasterizer>* rasterizer) {
return Create(width, height, vertex_shader_source, geometry_shader_source,
fragment_shader_source, 0.0, 0.0, 0.0, 1.0, rasterizer);
tensorflow::Status Rasterizer::Create(const int width, const int height,
const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
const std::string& fragment_shader_source,
std::unique_ptr<Rasterizer>* rasterizer) {
return Create<T>(width, height, vertex_shader_source, geometry_shader_source,
fragment_shader_source, 0.0, 0.0, 0.0, 1.0, rasterizer);
}

template <typename T>
tensorflow::Status Rasterizer<T>::Create(
const int width, const int height, const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
const std::string& fragment_shader_source, float clear_r, float clear_g,
float clear_b, float clear_depth, std::unique_ptr<Rasterizer>* rasterizer) {
tensorflow::Status Rasterizer::Create(const int width, const int height,
const std::string& vertex_shader_source,
const std::string& geometry_shader_source,
const std::string& fragment_shader_source,
float clear_r, float clear_g,
float clear_b, float clear_depth,
std::unique_ptr<Rasterizer>* rasterizer) {
std::unique_ptr<gl_utils::Program> program;
std::unique_ptr<gl_utils::RenderTargets> render_targets;
std::vector<std::pair<std::string, GLenum>> shaders = {
Expand All @@ -193,7 +188,8 @@ tensorflow::Status Rasterizer<T>::Create(
}

template <typename T>
tensorflow::Status Rasterizer<T>::Render(int num_points, absl::Span<T> result) {
tensorflow::Status Rasterizer::RenderImpl(int num_points,
absl::Span<T> result) {
const GLenum kProperty = GL_BUFFER_BINDING;

TFG_RETURN_IF_GL_ERROR(glDisable(GL_BLEND));
Expand Down Expand Up @@ -228,23 +224,16 @@ tensorflow::Status Rasterizer<T>::Render(int num_points, absl::Span<T> result) {
TFG_RETURN_IF_GL_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

TFG_RETURN_IF_GL_ERROR(glDrawArrays(GL_POINTS, 0, num_points));

TF_RETURN_IF_ERROR(render_targets_->CopyPixelsInto(result));

// The program and framebuffer and released here.
return tensorflow::Status::OK();
}

template <typename T>
void Rasterizer<T>::Reset() {
program_.reset();
render_targets_.reset();
for (auto&& buffer : shader_storage_buffers_) buffer.second.reset();
}

template <typename T>
template <typename S>
tensorflow::Status Rasterizer<T>::SetShaderStorageBuffer(
const std::string& name, absl::Span<const S> data) {
tensorflow::Status Rasterizer::SetShaderStorageBuffer(
const std::string& name, absl::Span<const T> data) {
// If the buffer does not exist, create it.
if (shader_storage_buffers_.count(name) == 0) {
std::unique_ptr<gl_utils::ShaderStorageBuffer> shader_storage_buffer;
Expand All @@ -259,60 +248,4 @@ tensorflow::Status Rasterizer<T>::SetShaderStorageBuffer(
return tensorflow::Status::OK();
}

template <typename T>
tensorflow::Status Rasterizer<T>::SetUniformMatrix(
const std::string& name, int num_columns, int num_rows, bool transpose,
absl::Span<const float> matrix) {
if (size_t(num_rows * num_columns) != matrix.size())
return TFG_INTERNAL_ERROR("num_rows * num_columns != matrix.size()");

typedef void (*setter_fn)(GLint location, GLsizei count, GLboolean transpose,
const GLfloat* value);

static const auto type_mapping =
std::unordered_map<int, std::tuple<int, int, setter_fn>>({
{GL_FLOAT_MAT2, std::make_tuple(2, 2, glUniformMatrix2fv)},
{GL_FLOAT_MAT3, std::make_tuple(3, 3, glUniformMatrix3fv)},
{GL_FLOAT_MAT4, std::make_tuple(4, 4, glUniformMatrix4fv)},
{GL_FLOAT_MAT2x3, std::make_tuple(2, 3, glUniformMatrix2x3fv)},
{GL_FLOAT_MAT2x4, std::make_tuple(2, 4, glUniformMatrix2x4fv)},
{GL_FLOAT_MAT3x2, std::make_tuple(3, 2, glUniformMatrix3x2fv)},
{GL_FLOAT_MAT3x4, std::make_tuple(3, 4, glUniformMatrix3x4fv)},
{GL_FLOAT_MAT4x2, std::make_tuple(4, 2, glUniformMatrix4x2fv)},
{GL_FLOAT_MAT4x3, std::make_tuple(4, 3, glUniformMatrix4x3fv)},
});

GLint uniform_type;
GLenum property = GL_TYPE;

TF_RETURN_IF_ERROR(program_->GetResourceProperty(
name, GL_UNIFORM, 1, &property, 1, &uniform_type));

// Is a resource active under that name?
if (uniform_type == GLint(GL_INVALID_INDEX))
return TFG_INTERNAL_ERROR("GL_INVALID_INDEX");

auto type_info = type_mapping.find(uniform_type);
if (type_info == type_mapping.end())
return TFG_INTERNAL_ERROR("Unsupported type");
if (std::get<0>(type_info->second) != num_columns ||
std::get<1>(type_info->second) != num_rows)
return TFG_INTERNAL_ERROR("Invalid dimensions");

GLint uniform_location;
property = GL_LOCATION;
TF_RETURN_IF_ERROR(program_->GetResourceProperty(
name, GL_UNIFORM, 1, &property, 1, &uniform_location));

TF_RETURN_IF_ERROR(program_->Use());
auto program_cleanup = MakeCleanup([this]() { return program_->Detach(); });

// Specify the value of the uniform in the current program.
TFG_RETURN_IF_GL_ERROR(std::get<2>(type_info->second)(
uniform_location, 1, transpose ? GL_TRUE : GL_FALSE, matrix.data()));

// Cleanup the program; no program is active at this point.
return tensorflow::Status::OK();
}

#endif // THIRD_PARTY_PY_TENSORFLOW_GRAPHICS_RENDERING_OPENGL_TESTS_RASTERIZER_H_
Loading