Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Unified Diff: gpu/command_buffer/service/program_manager.cc

Issue 935333002: Update from https://crrev.com/316786 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/program_manager.cc
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 1f6b2d49fc95933ade0c24e9c6dc0506d1a1e177..aef7e44976e7f70709ec78c1ca5e62e28d7f3b87 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -24,7 +24,6 @@
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/shader_manager.h"
-#include "gpu/command_buffer/service/shader_translator.h"
#include "third_party/re2/re2/re2.h"
using base::TimeDelta;
@@ -515,48 +514,14 @@ void Program::ExecuteBindAttribLocationCalls() {
}
bool Program::Link(ShaderManager* manager,
- ShaderTranslator* vertex_translator,
- ShaderTranslator* fragment_translator,
Program::VaryingsPackingOption varyings_packing_option,
const ShaderCacheCallback& shader_callback) {
ClearLinkStatus();
- if (!CanLink()) {
+
+ if (!AttachedShadersExist()) {
set_log_info("missing shaders");
return false;
}
- if (DetectAttribLocationBindingConflicts()) {
- set_log_info("glBindAttribLocation() conflicts");
- return false;
- }
- std::string conflicting_name;
- if (DetectUniformsMismatch(&conflicting_name)) {
- std::string info_log = "Uniforms with the same name but different "
- "type/precision: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (DetectVaryingsMismatch(&conflicting_name)) {
- std::string info_log = "Varyings with the same name but different type, "
- "or statically used varyings in fragment shader are "
- "not declared in vertex shader: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (DetectBuiltInInvariantConflicts()) {
- set_log_info("Invariant settings for certain built-in varyings "
- "have to match");
- return false;
- }
- if (DetectGlobalNameConflicts(&conflicting_name)) {
- std::string info_log = "Name conflicts between an uniform and an "
- "attribute: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (!CheckVaryingsPacking(varyings_packing_option)) {
- set_log_info("Varyings over maximum register limit");
- return false;
- }
TimeTicks before_time = TimeTicks::Now();
bool link = true;
@@ -565,19 +530,15 @@ bool Program::Link(ShaderManager* manager,
DCHECK(!attached_shaders_[0]->last_compiled_source().empty() &&
!attached_shaders_[1]->last_compiled_source().empty());
ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
- attached_shaders_[0]->last_compiled_source(),
- vertex_translator,
- attached_shaders_[1]->last_compiled_source(),
- fragment_translator,
+ attached_shaders_[0]->last_compiled_signature(),
+ attached_shaders_[1]->last_compiled_signature(),
&bind_attrib_location_map_);
if (status == ProgramCache::LINK_SUCCEEDED) {
ProgramCache::ProgramLoadResult success =
cache->LoadLinkedProgram(service_id(),
attached_shaders_[0].get(),
- vertex_translator,
attached_shaders_[1].get(),
- fragment_translator,
&bind_attrib_location_map_,
shader_callback);
link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
@@ -586,6 +547,47 @@ bool Program::Link(ShaderManager* manager,
}
if (link) {
+ CompileAttachedShaders();
+
+ if (!CanLink()) {
+ set_log_info("invalid shaders");
+ return false;
+ }
+ if (DetectAttribLocationBindingConflicts()) {
+ set_log_info("glBindAttribLocation() conflicts");
+ return false;
+ }
+ std::string conflicting_name;
+ if (DetectUniformsMismatch(&conflicting_name)) {
+ std::string info_log = "Uniforms with the same name but different "
+ "type/precision: " + conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (DetectVaryingsMismatch(&conflicting_name)) {
+ std::string info_log = "Varyings with the same name but different type, "
+ "or statically used varyings in fragment shader "
+ "are not declared in vertex shader: " +
+ conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (DetectBuiltInInvariantConflicts()) {
+ set_log_info("Invariant settings for certain built-in varyings "
+ "have to match");
+ return false;
+ }
+ if (DetectGlobalNameConflicts(&conflicting_name)) {
+ std::string info_log = "Name conflicts between an uniform and an "
+ "attribute: " + conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (!CheckVaryingsPacking(varyings_packing_option)) {
+ set_log_info("Varyings over maximum register limit");
+ return false;
+ }
+
ExecuteBindAttribLocationCalls();
before_time = TimeTicks::Now();
if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
@@ -604,9 +606,7 @@ bool Program::Link(ShaderManager* manager,
if (cache) {
cache->SaveLinkedProgram(service_id(),
attached_shaders_[0].get(),
- vertex_translator,
attached_shaders_[1].get(),
- fragment_translator,
&bind_attrib_location_map_,
shader_callback);
}
@@ -1001,6 +1001,23 @@ void Program::DetachShaders(ShaderManager* shader_manager) {
}
}
+void Program::CompileAttachedShaders() {
+ for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
+ Shader* shader = attached_shaders_[ii].get();
+ if (shader) {
+ shader->DoCompile();
+ }
+ }
+}
+
+bool Program::AttachedShadersExist() const {
+ for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
+ if (!attached_shaders_[ii].get())
+ return false;
+ }
+ return true;
+}
+
bool Program::CanLink() const {
for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->valid()) {
@@ -1303,6 +1320,7 @@ bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
GLuint program = service_id();
uint32_t header_size = sizeof(UniformBlocksHeader);
+ bucket->SetSize(header_size); // In case we fail.
uint32_t num_uniform_blocks = 0;
GLint param = GL_FALSE;
@@ -1316,10 +1334,6 @@ bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
if (num_uniform_blocks == 0) {
// Although spec allows an implementation to return uniform block info
// even if a link fails, for consistency, we disallow that.
- bucket->SetSize(header_size);
- UniformBlocksHeader* header =
- bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
- header->num_uniform_blocks = 0;
return true;
}
@@ -1390,7 +1404,7 @@ bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
bucket->SetSize(total_size);
UniformBlocksHeader* header =
- bucket->GetDataAs<UniformBlocksHeader*>(0, total_size);
+ bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>(
header_size, entry_size);
char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
@@ -1405,8 +1419,8 @@ bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
std::vector<GLint> params;
for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
// Get active uniform name.
- memcpy(data, names[ii].c_str(), blocks[ii].name_length);
- data += blocks[ii].name_length;
+ memcpy(data, names[ii].c_str(), names[ii].length() + 1);
+ data += names[ii].length() + 1;
// Get active uniform indices.
if (params.size() < blocks[ii].active_uniforms)
@@ -1425,6 +1439,170 @@ bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
return true;
}
+bool Program::GetTransformFeedbackVaryings(
+ CommonDecoder::Bucket* bucket) const {
+ // The data is packed into the bucket in the following order
+ // 1) header
+ // 2) N entries of varying data (except for name)
+ // 3) name1, name2, ..., nameN
+ //
+ // We query all the data directly through GL calls, assuming they are
+ // cheap through MANGLE.
+
+ DCHECK(bucket);
+ GLuint program = service_id();
+
+ uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
+ bucket->SetSize(header_size); // In case we fail.
+
+ uint32_t num_transform_feedback_varyings = 0;
+ GLint param = GL_FALSE;
+ // We assume program is a valid program service id.
+ glGetProgramiv(program, GL_LINK_STATUS, &param);
+ if (param == GL_TRUE) {
+ param = 0;
+ glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &param);
+ num_transform_feedback_varyings = static_cast<uint32_t>(param);
+ }
+ if (num_transform_feedback_varyings == 0) {
+ return true;
+ }
+
+ std::vector<TransformFeedbackVaryingInfo> varyings(
+ num_transform_feedback_varyings);
+ base::CheckedNumeric<uint32_t> size = sizeof(TransformFeedbackVaryingInfo);
+ size *= num_transform_feedback_varyings;
+ uint32_t entry_size = size.ValueOrDefault(0);
+ size += header_size;
+ std::vector<std::string> names(num_transform_feedback_varyings);
+ GLint max_name_length = 0;
+ glGetProgramiv(
+ program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length);
+ if (max_name_length < 1)
+ max_name_length = 1;
+ std::vector<char> buffer(max_name_length);
+ for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
+ GLsizei var_size = 0;
+ GLsizei var_name_length = 0;
+ GLenum var_type = 0;
+ glGetTransformFeedbackVarying(
+ program, ii, max_name_length,
+ &var_name_length, &var_size, &var_type, &buffer[0]);
+ varyings[ii].size = static_cast<uint32_t>(var_size);
+ varyings[ii].type = static_cast<uint32_t>(var_type);
+ varyings[ii].name_offset = static_cast<uint32_t>(size.ValueOrDefault(0));
+ DCHECK_GT(max_name_length, var_name_length);
+ names[ii] = std::string(&buffer[0], var_name_length);
+ // TODO(zmo): optimize the name mapping lookup.
+ const std::string* original_name = GetOriginalNameFromHashedName(names[ii]);
+ if (original_name)
+ names[ii] = *original_name;
+ varyings[ii].name_length = names[ii].size() + 1;
+ size += names[ii].size();
+ size += 1;
+ }
+ if (!size.IsValid())
+ return false;
+ uint32_t total_size = size.ValueOrDefault(0);
+ DCHECK_LE(header_size + entry_size, total_size);
+ uint32_t data_size = total_size - header_size - entry_size;
+
+ bucket->SetSize(total_size);
+ TransformFeedbackVaryingsHeader* header =
+ bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
+ TransformFeedbackVaryingInfo* entries =
+ bucket->GetDataAs<TransformFeedbackVaryingInfo*>(header_size, entry_size);
+ char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
+ DCHECK(header);
+ DCHECK(entries);
+ DCHECK(data);
+
+ // Copy over data for the header and entries.
+ header->num_transform_feedback_varyings = num_transform_feedback_varyings;
+ memcpy(entries, &varyings[0], entry_size);
+
+ for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
+ memcpy(data, names[ii].c_str(), names[ii].length() + 1);
+ data += names[ii].length() + 1;
+ }
+ DCHECK_EQ(ComputeOffset(header, data), total_size);
+ return true;
+}
+
+bool Program::GetUniformsES3(CommonDecoder::Bucket* bucket) const {
+ // The data is packed into the bucket in the following order
+ // 1) header
+ // 2) N entries of UniformES3Info
+ //
+ // We query all the data directly through GL calls, assuming they are
+ // cheap through MANGLE.
+
+ DCHECK(bucket);
+ GLuint program = service_id();
+
+ uint32_t header_size = sizeof(UniformsES3Header);
+ bucket->SetSize(header_size); // In case we fail.
+
+ GLsizei count = 0;
+ GLint param = GL_FALSE;
+ // We assume program is a valid program service id.
+ glGetProgramiv(program, GL_LINK_STATUS, &param);
+ if (param == GL_TRUE) {
+ param = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
+ }
+ if (count == 0) {
+ return true;
+ }
+
+ base::CheckedNumeric<uint32_t> size = sizeof(UniformES3Info);
+ size *= count;
+ uint32_t entry_size = size.ValueOrDefault(0);
+ size += header_size;
+ if (!size.IsValid())
+ return false;
+ uint32_t total_size = size.ValueOrDefault(0);
+ bucket->SetSize(total_size);
+ UniformsES3Header* header =
+ bucket->GetDataAs<UniformsES3Header*>(0, header_size);
+ DCHECK(header);
+ header->num_uniforms = static_cast<uint32_t>(count);
+
+ // Instead of GetDataAs<UniformES3Info*>, we do GetDataAs<int32_t>. This is
+ // because struct UniformES3Info is defined as five int32_t.
+ // By doing this, we can fill the structs through loops.
+ int32_t* entries =
+ bucket->GetDataAs<int32_t*>(header_size, entry_size);
+ DCHECK(entries);
+ const size_t kStride = sizeof(UniformES3Info) / sizeof(int32_t);
+
+ const GLenum kPname[] = {
+ GL_UNIFORM_BLOCK_INDEX,
+ GL_UNIFORM_OFFSET,
+ GL_UNIFORM_ARRAY_STRIDE,
+ GL_UNIFORM_MATRIX_STRIDE,
+ GL_UNIFORM_IS_ROW_MAJOR,
+ };
+ const GLint kDefaultValue[] = { -1, -1, -1, -1, 0 };
+ const size_t kNumPnames = arraysize(kPname);
+ std::vector<GLuint> indices(count);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ indices[ii] = ii;
+ }
+ std::vector<GLint> params(count);
+ for (size_t pname_index = 0; pname_index < kNumPnames; ++pname_index) {
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = kDefaultValue[pname_index];
+ }
+ glGetActiveUniformsiv(
+ program, count, &indices[0], kPname[pname_index], &params[0]);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ entries[kStride * ii + pname_index] = params[ii];
+ }
+ }
+ return true;
+}
+
Program::~Program() {
if (manager_) {
if (manager_->have_context_) {
« no previous file with comments | « gpu/command_buffer/service/program_manager.h ('k') | gpu/command_buffer/service/program_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698