summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrlp@google.com <rlp@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-02 23:28:00 +0000
committerrlp@google.com <rlp@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-02 23:28:00 +0000
commitac300913ded24c0e6887c72fa48435dc671bd16c (patch)
tree89a09fe8171122c66f74b1d6fbf2ec6df35ff37d
parentdcdae9eeabbf866f98d7fab10096bb19054458cc (diff)
downloadchromium_src-ac300913ded24c0e6887c72fa48435dc671bd16c.zip
chromium_src-ac300913ded24c0e6887c72fa48435dc671bd16c.tar.gz
chromium_src-ac300913ded24c0e6887c72fa48435dc671bd16c.tar.bz2
Adding GetStreamInfo functionality (and passing corresponding unit test).
Review URL: http://codereview.chromium.org/147237 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19859 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--o3d/command_buffer/client/cross/effect_helper.cc63
-rw-r--r--o3d/command_buffer/client/cross/effect_helper.h21
-rw-r--r--o3d/command_buffer/common/cross/cmd_buffer_format.h2
-rw-r--r--o3d/command_buffer/common/cross/gapi_interface.h28
-rw-r--r--o3d/command_buffer/common/cross/resource.h7
-rw-r--r--o3d/command_buffer/service/cross/gapi_decoder.cc25
-rw-r--r--o3d/command_buffer/service/cross/resource.h7
-rw-r--r--o3d/command_buffer/service/win/d3d9/d3d9_utils.h53
-rw-r--r--o3d/command_buffer/service/win/d3d9/effect_d3d9.cc98
-rw-r--r--o3d/command_buffer/service/win/d3d9/effect_d3d9.h13
-rw-r--r--o3d/command_buffer/service/win/d3d9/gapi_d3d9.h11
-rw-r--r--o3d/core/cross/command_buffer/effect_cb.cc59
-rw-r--r--o3d/core/cross/command_buffer/effect_cb.h2
13 files changed, 384 insertions, 5 deletions
diff --git a/o3d/command_buffer/client/cross/effect_helper.cc b/o3d/command_buffer/client/cross/effect_helper.cc
index 0cab6ee..1552e29 100644
--- a/o3d/command_buffer/client/cross/effect_helper.cc
+++ b/o3d/command_buffer/client/cross/effect_helper.cc
@@ -207,5 +207,68 @@ void EffectHelper::DestroyEffectParameters(
}
}
+bool EffectHelper::GetEffectStreams(ResourceID effect_id,
+ std::vector<EffectStreamDesc> *descs) {
+ using effect_stream::Desc;
+ DCHECK_NE(effect_id, kInvalidResource);
+
+ // Get the param count.
+ Uint32 *retval = shm_allocator_->AllocTyped<Uint32>(1);
+ CommandBufferEntry args[5];
+ args[0].value_uint32 = effect_id;
+ args[1].value_uint32 = sizeof(*retval);
+ args[2].value_uint32 = shm_id_;
+ args[3].value_uint32 = shm_allocator_->GetOffset(retval);
+ helper_->AddCommand(GET_STREAM_COUNT, 4, args);
+ // Finish has to be called to get the result.
+ helper_->Finish();
+
+ // We could have failed if the effect_id is invalid.
+ if (helper_->interface()->GetParseError() !=
+ BufferSyncInterface::PARSE_NO_ERROR) {
+ shm_allocator_->Free(retval);
+ return false;
+ }
+ unsigned int stream_count = *retval;
+ shm_allocator_->Free(retval);
+ unsigned int max_buffer_size = shm_allocator_->GetLargestFreeOrPendingSize();
+ if (max_buffer_size < sizeof(Desc)) { // NOLINT
+ // Not enough memory to get at least 1 stream desc.
+ return false;
+ }
+ descs->resize(stream_count);
+
+ // Read stream descriptions in batches. We use as much shared memory as
+ // possible so that we only call Finish as little as possible.
+ unsigned int max_stream_per_batch =
+ std::min(stream_count, max_buffer_size / sizeof(Desc)); // NOLINT
+ Desc *raw_descs = shm_allocator_->AllocTyped<Desc>(max_stream_per_batch);
+ DCHECK(raw_descs);
+ for (unsigned int i = 0; i < stream_count; i += max_stream_per_batch) {
+ unsigned int count = std::min(stream_count - i, max_stream_per_batch);
+ for (unsigned int j = 0 ; j < count; ++j) {
+ EffectStreamDesc *desc = &((*descs)[i + j]);
+ Desc *raw_desc = raw_descs + j;
+ args[0].value_uint32 = effect_id;
+ args[1].value_uint32 = i+j;
+ args[2].value_uint32 = sizeof(*raw_desc);
+ args[3].value_uint32 = shm_id_;
+ args[4].value_uint32 = shm_allocator_->GetOffset(raw_desc);
+ helper_->AddCommand(GET_STREAM_DESC, 5, args);
+ }
+ // Finish to get the results.
+ helper_->Finish();
+ DCHECK_EQ(helper_->interface()->GetParseError(),
+ BufferSyncInterface::PARSE_NO_ERROR);
+ for (unsigned int j = 0 ; j < count; ++j) {
+ EffectStreamDesc *desc = &((*descs)[i + j]);
+ Desc *raw_desc = raw_descs + j;
+ desc->semantic = static_cast<vertex_struct::Semantic>(raw_desc->semantic);
+ desc->semantic_index = raw_desc->semantic_index;
+ }
+ }
+ shm_allocator_->Free(raw_descs);
+ return true;
+}
} // namespace command_buffer
} // namespace o3d
diff --git a/o3d/command_buffer/client/cross/effect_helper.h b/o3d/command_buffer/client/cross/effect_helper.h
index 19523ee..4c62487 100644
--- a/o3d/command_buffer/client/cross/effect_helper.h
+++ b/o3d/command_buffer/client/cross/effect_helper.h
@@ -59,6 +59,10 @@ class EffectHelper {
// structure (counting strings) for a
// param.
};
+ struct EffectStreamDesc {
+ vertex_struct::Semantic semantic; // The semantic enum type.
+ unsigned int semantic_index;
+ };
EffectHelper(CommandBufferHelper *helper,
FencedAllocatorWrapper *shm_allocator,
@@ -119,6 +123,23 @@ class EffectHelper {
// descs: the vector of descriptions containing the ResourceIDs of the
// parameters to destroy.
void DestroyEffectParameters(const std::vector<EffectParamDesc> &descs);
+
+ // Gets all the input stream semantics and semantic indices in an
+ // array. These will be retrieved as many as possible at a time. At least
+ // sizeof(effect_param::Desc) must be available for this function to succeed.
+ // This function will call Finish(), hence will block.
+ //
+ // Parameters:
+ // effect_id: the ResourceID of the effect.
+ // descs: A pointer to a vector containing the returned descriptions.
+ // The pointed vector will be cleared.
+ // Returns:
+ // true if successful. Reasons for failure are:
+ // - invalid effect_id,
+ // - not enough memory in the shm_allocator_.
+ bool GetEffectStreams(ResourceID effect_id,
+ std::vector<EffectStreamDesc> *descs);
+
private:
CommandBufferHelper *helper_;
FencedAllocatorWrapper *shm_allocator_;
diff --git a/o3d/command_buffer/common/cross/cmd_buffer_format.h b/o3d/command_buffer/common/cross/cmd_buffer_format.h
index b0b9386..1872a34 100644
--- a/o3d/command_buffer/common/cross/cmd_buffer_format.h
+++ b/o3d/command_buffer/common/cross/cmd_buffer_format.h
@@ -293,6 +293,8 @@ enum CommandId {
SET_PARAM_DATA, // SetParamData, 4 args
SET_PARAM_DATA_IMMEDIATE, // SetParamData, 2 args + data
GET_PARAM_DESC, // GetParamDesc, 4 args
+ GET_STREAM_COUNT, // GetStreamCount, 4 args.
+ GET_STREAM_DESC, // GetStreamDesc, 5 args
DESTROY_TEXTURE, // DestroyTexture, 1 arg
CREATE_TEXTURE_2D, // CreateTexture2D, 3 args
CREATE_TEXTURE_3D, // CreateTexture3D, 4 args
diff --git a/o3d/command_buffer/common/cross/gapi_interface.h b/o3d/command_buffer/common/cross/gapi_interface.h
index 9531973..67700b7 100644
--- a/o3d/command_buffer/common/cross/gapi_interface.h
+++ b/o3d/command_buffer/common/cross/gapi_interface.h
@@ -481,6 +481,34 @@ class GAPIInterface {
unsigned int size,
void *data) = 0;
+ // Gets the number of input streams for an effect, returning it in a memory
+ // buffer as a Uint32.
+ // Parameters:
+ // id: the resource ID of the effect.
+ // size: the size of the data buffer. Must be at least 4 (the size of the
+ // Uint32).
+ // data: the buffer receiving the data.
+ // Returns:
+ // BufferSyncInterface::PARSE_INVALID_ARGUMENTS if invalid arguments are
+ // passed, BufferSyncInterface::PARSE_NO_ERROR otherwise.
+ virtual ParseError GetStreamCount(ResourceID id,
+ unsigned int size,
+ void *data) = 0;
+
+ // Gets the stream semantics, storing them in the data buffer. The stream
+ // is described by an effect_stream::Desc structure which contains a
+ // semantic type and a semantic index.
+ // Parameters:
+ // id: the resource ID of the effect.
+ // index: which stream semantic to get
+ // size: the size of the data buffer. Must be at least 8 (the size of two
+ // Uint32).
+ // data: the buffer receiving the data.
+ virtual ParseError GetStreamDesc(ResourceID id,
+ unsigned int index,
+ unsigned int size,
+ void *data) = 0;
+
// Creates a 2D texture resource.
// Parameters:
// id: the resource ID of the texture.
diff --git a/o3d/command_buffer/common/cross/resource.h b/o3d/command_buffer/common/cross/resource.h
index 8e86723..861d24f 100644
--- a/o3d/command_buffer/common/cross/resource.h
+++ b/o3d/command_buffer/common/cross/resource.h
@@ -134,6 +134,13 @@ struct Desc {
};
} // namespace effect_param
+namespace effect_stream {
+struct Desc {
+ Uint32 semantic; // the semantic type
+ Uint32 semantic_index;
+};
+} // namespace effect_stream
+
namespace texture {
// Texture flags.
enum Flags {
diff --git a/o3d/command_buffer/service/cross/gapi_decoder.cc b/o3d/command_buffer/service/cross/gapi_decoder.cc
index efd3bc5..dfd0cff 100644
--- a/o3d/command_buffer/service/cross/gapi_decoder.cc
+++ b/o3d/command_buffer/service/cross/gapi_decoder.cc
@@ -367,6 +367,31 @@ BufferSyncInterface::ParseError GAPIDecoder::DoCommand(
} else {
return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
}
+ case GET_STREAM_COUNT:
+ if (arg_count == 4) {
+ ResourceID id = args[0].value_uint32;
+ unsigned int size = args[1].value_uint32;
+ void *data = GetAddressAndCheckSize(args[2].value_uint32,
+ args[3].value_uint32,
+ size);
+ if (!data) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return gapi_->GetStreamCount(id, size, data);
+ } else {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ case GET_STREAM_DESC:
+ if (arg_count == 5) {
+ ResourceID id = args[0].value_uint32;
+ unsigned int index = args[1].value_uint32;
+ unsigned int size = args[2].value_uint32;
+ void *data = GetAddressAndCheckSize(args[3].value_uint32,
+ args[4].value_uint32,
+ size);
+ if (!data) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return gapi_->GetStreamDesc(id, index, size, data);
+ } else {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
case DESTROY_TEXTURE:
if (arg_count == 1) {
return gapi_->DestroyTexture(args[0].value_uint32);
diff --git a/o3d/command_buffer/service/cross/resource.h b/o3d/command_buffer/service/cross/resource.h
index 5c6e6ed..9df3ca4 100644
--- a/o3d/command_buffer/service/cross/resource.h
+++ b/o3d/command_buffer/service/cross/resource.h
@@ -153,6 +153,13 @@ class EffectParam: public Resource {
DISALLOW_COPY_AND_ASSIGN(EffectParam);
};
+class EffectStream: public Resource {
+ public:
+ explicit EffectStream() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EffectStream);
+};
+
// Texture class, representing a texture resource.
class Texture: public Resource {
public:
diff --git a/o3d/command_buffer/service/win/d3d9/d3d9_utils.h b/o3d/command_buffer/service/win/d3d9/d3d9_utils.h
index 647d984..17cd621 100644
--- a/o3d/command_buffer/service/win/d3d9/d3d9_utils.h
+++ b/o3d/command_buffer/service/win/d3d9/d3d9_utils.h
@@ -96,6 +96,59 @@ inline D3DCOLOR RGBAToD3DCOLOR(const RGBA &color) {
FloatToClampedByte(color.alpha));
}
+inline bool VerifyHResult(HRESULT hr, const char* file, int line,
+ const char* call) {
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "DX Error in file " << file
+ << " line " << line << L": "
+ << DXGetErrorStringA(hr) << L": " << call;
+ return false;
+ }
+ return true;
+}
+
+static bool D3DSemanticToCBSemantic(
+ D3DDECLUSAGE semantic,
+ unsigned int semantic_index,
+ vertex_struct::Semantic *out_semantic,
+ unsigned int *out_semantic_index) {
+ // TODO: what meaning do we really want to put to our semantics ? How
+ // do they match the semantics that are set in the effect ? What combination
+ // of (semantic, index) are supposed to work ?
+ switch (semantic) {
+ case D3DDECLUSAGE_POSITION:
+ if (semantic_index != 0) return false;
+ *out_semantic = vertex_struct::POSITION;
+ *out_semantic_index = 0;
+ return true;
+ case D3DDECLUSAGE_NORMAL:
+ if (semantic_index != 0) return false;
+ *out_semantic = vertex_struct::NORMAL;
+ *out_semantic_index = 0;
+ return true;
+ case D3DDECLUSAGE_TANGENT:
+ if (semantic_index != 0) return false;
+ *out_semantic = vertex_struct::TEX_COORD;
+ *out_semantic_index = 6;
+ return true;
+ case D3DDECLUSAGE_BINORMAL:
+ if (semantic_index != 0) return false;
+ *out_semantic = vertex_struct::TEX_COORD;
+ *out_semantic_index = 7;
+ return true;
+ case D3DDECLUSAGE_COLOR:
+ if (semantic_index > 1) return false;
+ *out_semantic = vertex_struct::COLOR;
+ *out_semantic_index = semantic_index;
+ return true;
+ case D3DDECLUSAGE_TEXCOORD:
+ *out_semantic = vertex_struct::TEX_COORD;
+ *out_semantic_index = semantic_index;
+ return true;
+ default:
+ return false;
+ }
+}
} // namespace command_buffer
} // namespace o3d
diff --git a/o3d/command_buffer/service/win/d3d9/effect_d3d9.cc b/o3d/command_buffer/service/win/d3d9/effect_d3d9.cc
index 7cfee14..c55c345 100644
--- a/o3d/command_buffer/service/win/d3d9/effect_d3d9.cc
+++ b/o3d/command_buffer/service/win/d3d9/effect_d3d9.cc
@@ -69,13 +69,16 @@ static void LogFXError(LPD3DXBUFFER error_buffer) {
}
EffectD3D9::EffectD3D9(ID3DXEffect *d3d_effect,
- ID3DXConstantTable *fs_constant_table)
+ ID3DXConstantTable *fs_constant_table,
+ IDirect3DVertexShader9 *d3d_vertex_shader)
: d3d_effect_(d3d_effect),
fs_constant_table_(fs_constant_table),
+ d3d_vertex_shader_(d3d_vertex_shader),
sync_parameters_(false) {
for (unsigned int i = 0; i < kMaxSamplerUnits; ++i) {
samplers_[i] = kInvalidResource;
}
+ SetStreams();
}
// Releases the D3D effect.
EffectD3D9::~EffectD3D9() {
@@ -86,6 +89,8 @@ EffectD3D9::~EffectD3D9() {
d3d_effect_->Release();
DCHECK(fs_constant_table_);
fs_constant_table_->Release();
+ DCHECK(d3d_vertex_shader_);
+ d3d_vertex_shader_->Release();
}
// Compiles the effect, and checks that the effect conforms to what we expect
@@ -152,7 +157,17 @@ EffectD3D9 *EffectD3D9::Create(GAPID3D9 *gapi,
d3d_effect->Release();
return NULL;
}
- return new EffectD3D9(d3d_effect, table);
+ IDirect3DVertexShader9 *d3d_vertex_shader = NULL;
+ HR(device->CreateVertexShader(pass_desc.pVertexShaderFunction,
+ &d3d_vertex_shader));
+ if (!d3d_vertex_shader) {
+ d3d_effect->Release();
+ table->Release();
+ DLOG(ERROR) << "Failed to create vertex shader";
+ return NULL;
+ }
+
+ return new EffectD3D9(d3d_effect, table, d3d_vertex_shader);
}
// Begins rendering with the effect, setting all the appropriate states.
@@ -177,6 +192,11 @@ unsigned int EffectD3D9::GetParamCount() {
return effect_desc.Parameters;
}
+// Gets the number of input streams from the shader.
+unsigned int EffectD3D9::GetStreamCount() {
+ return streams_.size();
+}
+
// Retrieves the matching DataType from a D3D parameter description.
static effect_param::DataType GetDataTypeFromD3D(
const D3DXPARAMETER_DESC &desc) {
@@ -282,6 +302,38 @@ bool EffectD3D9::SetSamplers(GAPID3D9 *gapi) {
return result;
}
+bool EffectD3D9::SetStreams() {
+ if (!d3d_vertex_shader_) {
+ return false;
+ }
+ UINT size;
+ d3d_vertex_shader_->GetFunction(NULL, &size);
+ scoped_array<DWORD> function(new DWORD[size]);
+ d3d_vertex_shader_->GetFunction(function.get(), &size);
+
+ UINT num_semantics;
+ HR(D3DXGetShaderInputSemantics(function.get(),
+ NULL,
+ &num_semantics));
+ scoped_array<D3DXSEMANTIC> semantics(new D3DXSEMANTIC[num_semantics]);
+ HR(D3DXGetShaderInputSemantics(function.get(),
+ semantics.get(),
+ &num_semantics));
+
+ streams_.resize(num_semantics);
+ for (UINT i = 0; i < num_semantics; ++i) {
+ vertex_struct::Semantic semantic;
+ unsigned int semantic_index;
+ if (D3DSemanticToCBSemantic(static_cast<D3DDECLUSAGE>(semantics[i].Usage),
+ static_cast<int>(semantics[i].UsageIndex),
+ &semantic, &semantic_index)) {
+ streams_[i].semantic = semantic;
+ streams_[i].semantic_index = semantic_index;
+ }
+ }
+ return true;
+}
+
void EffectD3D9::LinkParam(EffectParamD3D9 *param) {
params_.push_back(param);
}
@@ -290,6 +342,23 @@ void EffectD3D9::UnlinkParam(EffectParamD3D9 *param) {
std::remove(params_.begin(), params_.end(), param);
}
+// Fills the Desc structure, appending name and semantic if any, and if enough
+// room is available in the buffer.
+bool EffectD3D9::GetStreamDesc(unsigned int index,
+ unsigned int size,
+ void *data) {
+ using effect_stream::Desc;
+ if (size < sizeof(Desc)) // NOLINT
+ return false;
+
+ Desc stream = streams_[index];
+ Desc *desc = static_cast<Desc *>(data);
+ memset(desc, 0, sizeof(*desc));
+ desc->semantic = stream.semantic;
+ desc->semantic_index = stream.semantic_index;
+ return true;
+}
+
EffectParamD3D9::EffectParamD3D9(effect_param::DataType data_type,
EffectD3D9 *effect,
D3DXHANDLE handle)
@@ -559,6 +628,31 @@ BufferSyncInterface::ParseError GAPID3D9::GetParamDesc(
BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
}
+// Gets the stream count from the effect and store it in the memory buffer.
+BufferSyncInterface::ParseError GAPID3D9::GetStreamCount(
+ ResourceID id,
+ unsigned int size,
+ void *data) {
+ EffectD3D9 *effect = effects_.Get(id);
+ if (!effect || size < sizeof(Uint32)) // NOLINT
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ *static_cast<Uint32 *>(data) = effect->GetStreamCount();
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPID3D9::GetStreamDesc(
+ ResourceID id,
+ unsigned int index,
+ unsigned int size,
+ void *data) {
+ EffectD3D9 *effect = effects_.Get(id);
+ if (!effect) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return effect->GetStreamDesc(index, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+
// If the current effect is valid, call End on it, and tag for revalidation.
void GAPID3D9::DirtyEffect() {
if (validate_effect_) return;
diff --git a/o3d/command_buffer/service/win/d3d9/effect_d3d9.h b/o3d/command_buffer/service/win/d3d9/effect_d3d9.h
index 318598c..1180fb8 100644
--- a/o3d/command_buffer/service/win/d3d9/effect_d3d9.h
+++ b/o3d/command_buffer/service/win/d3d9/effect_d3d9.h
@@ -80,7 +80,8 @@ class EffectParamD3D9: public EffectParam {
class EffectD3D9 : public Effect {
public:
EffectD3D9(ID3DXEffect *d3d_effect,
- ID3DXConstantTable *fs_constant_table);
+ ID3DXConstantTable *fs_constant_table,
+ IDirect3DVertexShader9 *d3d_vertex_shader);
virtual ~EffectD3D9();
// Compiles and creates an effect from source code.
static EffectD3D9 *Create(GAPID3D9 *gapi,
@@ -101,8 +102,13 @@ class EffectD3D9 : public Effect {
EffectParamD3D9 *CreateParam(unsigned int index);
// Creates an effect parameter of the specified name.
EffectParamD3D9 *CreateParamByName(const char *name);
+ // Gets the number of stream inputs for the effect.
+ unsigned int GetStreamCount();
+ // Gets the stream data with the specified index.
+ bool GetStreamDesc(unsigned int index, unsigned int size, void *data);
private:
typedef std::vector<EffectParamD3D9 *> ParamList;
+ typedef std::vector<effect_stream::Desc> StreamList;
// Links a param into this effect.
void LinkParam(EffectParamD3D9 *param);
@@ -110,14 +116,19 @@ class EffectD3D9 : public Effect {
void UnlinkParam(EffectParamD3D9 *param);
// Sets sampler states.
bool SetSamplers(GAPID3D9 *gapi);
+ // Sets streams vector.
+ bool SetStreams();
ID3DXEffect *d3d_effect_;
+ IDirect3DVertexShader9 *d3d_vertex_shader_;
ID3DXConstantTable *fs_constant_table_;
ParamList params_;
+ StreamList streams_;
bool sync_parameters_;
ResourceID samplers_[kMaxSamplerUnits];
friend class EffectParamD3D9;
+ friend class EffectStreamD3D9;
DISALLOW_COPY_AND_ASSIGN(EffectD3D9);
};
diff --git a/o3d/command_buffer/service/win/d3d9/gapi_d3d9.h b/o3d/command_buffer/service/win/d3d9/gapi_d3d9.h
index e94f35c..c757cc6 100644
--- a/o3d/command_buffer/service/win/d3d9/gapi_d3d9.h
+++ b/o3d/command_buffer/service/win/d3d9/gapi_d3d9.h
@@ -195,6 +195,17 @@ class GAPID3D9 : public GAPIInterface {
unsigned int size,
void *data);
+ // Implements the GetStreamCount function for D3D9.
+ virtual ParseError GetStreamCount(ResourceID id,
+ unsigned int size,
+ void *data);
+
+ // Implements the GetStreamDesc function for D3D9.
+ virtual ParseError GetStreamDesc(ResourceID id,
+ unsigned int index,
+ unsigned int size,
+ void *data);
+
// Implements the CreateTexture2D function for D3D9.
virtual ParseError CreateTexture2D(ResourceID id,
unsigned int width,
diff --git a/o3d/core/cross/command_buffer/effect_cb.cc b/o3d/core/cross/command_buffer/effect_cb.cc
index afa9e0f..27afbd7 100644
--- a/o3d/core/cross/command_buffer/effect_cb.cc
+++ b/o3d/core/cross/command_buffer/effect_cb.cc
@@ -49,6 +49,7 @@ using command_buffer::CommandBufferEntry;
using command_buffer::CommandBufferHelper;
using command_buffer::ResourceID;
namespace effect_param = command_buffer::effect_param;
+namespace vertex_struct = command_buffer::vertex_struct;
EffectCB::EffectCB(ServiceLocator *service_locator, RendererCB *renderer)
: Effect(service_locator),
@@ -125,6 +126,11 @@ bool EffectCB::LoadFromFXString(const String& source) {
return false;
}
}
+ if (!effect_helper.GetEffectStreams(resource_id, &stream_descs_)) {
+ O3D_ERROR(service_locator()) << "Failed to get streams.";
+ Destroy();
+ return false;
+ }
set_source(source);
return true;
}
@@ -200,8 +206,59 @@ void EffectCB::GetParameterInfo(EffectParameterInfoArray *array) {
}
}
+
+static bool CBSemanticToO3DSemantic(
+ vertex_struct::Semantic semantic,
+ unsigned int semantic_index,
+ Stream::Semantic *out_semantic,
+ unsigned int *out_semantic_index) {
+ switch (semantic) {
+ case vertex_struct::POSITION:
+ if (semantic_index != 0) return false;
+ *out_semantic = Stream::POSITION;
+ *out_semantic_index = 0;
+ return true;
+ case vertex_struct::NORMAL:
+ if (semantic_index != 0) return false;
+ *out_semantic = Stream::NORMAL;
+ *out_semantic_index = 0;
+ return true;
+ case vertex_struct::COLOR:
+ if (semantic_index > 1) return false;
+ *out_semantic = Stream::COLOR;
+ *out_semantic_index = semantic_index;
+ return true;
+ case vertex_struct::TEX_COORD:
+ if (semantic_index == 6) {
+ *out_semantic = Stream::TANGENT;
+ *out_semantic_index = 0;
+ return true;
+ } else if (semantic_index == 7) {
+ *out_semantic = Stream::BINORMAL;
+ *out_semantic_index = 0;
+ return true;
+ } else {
+ *out_semantic = Stream::TEXCOORD;
+ *out_semantic_index = semantic_index;
+ return true;
+ }
+ default:
+ return false;
+ }
+}
void EffectCB::GetStreamInfo(EffectStreamInfoArray *array) {
- // TODO(rlp)
+ DCHECK(array);
+ array->clear();
+ for (unsigned int i = 0; i < stream_descs_.size(); ++i) {
+ Stream::Semantic semantic;
+ unsigned int semantic_index;
+ if (CBSemanticToO3DSemantic(stream_descs_[i].semantic,
+ stream_descs_[i].semantic_index,
+ &semantic,
+ &semantic_index)) {
+ array->push_back(EffectStreamInfo(semantic, semantic_index));
+ }
+ }
}
} // namespace o3d
diff --git a/o3d/core/cross/command_buffer/effect_cb.h b/o3d/core/cross/command_buffer/effect_cb.h
index a50638e..3d310bc 100644
--- a/o3d/core/cross/command_buffer/effect_cb.h
+++ b/o3d/core/cross/command_buffer/effect_cb.h
@@ -75,9 +75,9 @@ class EffectCB : public Effect {
// The command buffer resource ID for the effect.
command_buffer::ResourceID resource_id_;
std::vector<EffectHelper::EffectParamDesc> param_descs_;
+ std::vector<EffectHelper::EffectStreamDesc> stream_descs_;
// A generation counter to dirty ParamCacheCBs.
unsigned int generation_;
-
// The renderer that created this effect.
RendererCB *renderer_;
DISALLOW_IMPLICIT_CONSTRUCTORS(EffectCB);