|
|
@@ -81,16 +81,6 @@ compile_module(const ShaderModule *module, DWORD *&data) {
|
|
|
<< spv->get_source_filename() << "\n";
|
|
|
}
|
|
|
|
|
|
- // Create a mapping from locations to parameter index. This makes
|
|
|
- // reflection a little easier later on.
|
|
|
- pmap<int, unsigned int> params_by_location;
|
|
|
- for (size_t i = 0; i < module->get_num_parameters(); ++i) {
|
|
|
- const ShaderModule::Variable &var = module->get_parameter(i);
|
|
|
- if (var.has_location()) {
|
|
|
- params_by_location[var.get_location()] = (unsigned int)i;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
spirv_cross::CompilerHLSL compiler(std::vector<uint32_t>(spv->get_data(), spv->get_data() + spv->get_data_size()));
|
|
|
spirv_cross::CompilerHLSL::Options options;
|
|
|
options.shader_model = 30;
|
|
|
@@ -131,6 +121,16 @@ compile_module(const ShaderModule *module, DWORD *&data) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Create a mapping from locations to parameter index. This makes
|
|
|
+ // reflection a little easier later on.
|
|
|
+ pmap<int, unsigned int> params_by_location;
|
|
|
+ for (size_t i = 0; i < module->get_num_parameters(); ++i) {
|
|
|
+ const ShaderModule::Variable &var = module->get_parameter(i);
|
|
|
+ if (var.has_location()) {
|
|
|
+ params_by_location[var.get_location()] = (unsigned int)i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Tell spirv-cross to rename the constants to "p#", where # is the index of
|
|
|
// the original parameter. This makes it easier to map the compiled
|
|
|
// constants back to the original parameters later on.
|
|
|
@@ -180,15 +180,33 @@ compile_module(const ShaderModule *module, DWORD *&data) {
|
|
|
nassertr(shader != nullptr, false);
|
|
|
data = (DWORD *)shader->GetBufferPointer();
|
|
|
|
|
|
+#ifndef NDEBUG
|
|
|
+ if (dxgsg9_cat.is_debug()) {
|
|
|
+ std::ostream &out = dxgsg9_cat.debug()
|
|
|
+ << "Disassembly of compiled " << profile << " module:\n";
|
|
|
+ LPD3DXBUFFER dis;
|
|
|
+ if (SUCCEEDED(D3DXDisassembleShader(data, FALSE, NULL, &dis))) {
|
|
|
+ out << (char *)dis->GetBufferPointer();
|
|
|
+ dis->Release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (errors != nullptr) {
|
|
|
+ errors->Release();
|
|
|
+ }
|
|
|
+
|
|
|
return query_constants(module, data);
|
|
|
}
|
|
|
else {
|
|
|
dxgsg9_cat.error()
|
|
|
- << "Failed to compile " << module->get_stage() << " shader (" << DXGetErrorString(result) << "):\n";
|
|
|
+ << "Failed to compile " << module->get_stage() << " shader ("
|
|
|
+ << DXGetErrorString(result) << "):\n";
|
|
|
|
|
|
if (errors != nullptr) {
|
|
|
std::string messages((const char *)errors->GetBufferPointer(), errors->GetBufferSize());
|
|
|
dxgsg9_cat.error(false) << messages << "\n";
|
|
|
+ errors->Release();
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
@@ -219,6 +237,8 @@ query_constants(const ShaderModule *module, DWORD *data) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ Shader::Stage stage = module->get_stage();
|
|
|
+
|
|
|
for (DWORD ci = 0; ci < table->Constants; ++ci) {
|
|
|
D3DXSHADER_CONSTANTINFO &constant = constants[ci];
|
|
|
D3DXSHADER_TYPEINFO *type = (D3DXSHADER_TYPEINFO *)(offset + constant.TypeInfo);
|
|
|
@@ -227,15 +247,13 @@ query_constants(const ShaderModule *module, DWORD *data) {
|
|
|
// parameter index.
|
|
|
const char *name = (const char *)(offset + constant.Name);
|
|
|
if (name[0] != 'p') {
|
|
|
- if (module->get_stage() == Shader::Stage::vertex &&
|
|
|
- strcmp(name, "gl_HalfPixel") == 0) {
|
|
|
+ if (stage == Shader::Stage::vertex && strcmp(name, "gl_HalfPixel") == 0) {
|
|
|
// This is a special input generated by spirv-cross.
|
|
|
_half_pixel_register = constant.RegisterIndex;
|
|
|
continue;
|
|
|
}
|
|
|
dxgsg9_cat.warning()
|
|
|
- << "Ignoring unknown " << module->get_stage()
|
|
|
- << " shader constant " << name << "\n";
|
|
|
+ << "Ignoring unknown " << stage << " shader constant " << name << "\n";
|
|
|
continue;
|
|
|
}
|
|
|
int index = atoi(name + 1);
|
|
|
@@ -256,99 +274,87 @@ query_constants(const ShaderModule *module, DWORD *data) {
|
|
|
num_elements = array_type->get_num_elements();
|
|
|
}
|
|
|
|
|
|
- if (type->Class == D3DXPC_STRUCT) {
|
|
|
- const ShaderType::Struct *struct_type = element_type->as_struct();
|
|
|
- nassertr(struct_type != nullptr, false);
|
|
|
+ int reg_set = constant.RegisterSet;
|
|
|
+ int reg_idx = constant.RegisterIndex;
|
|
|
+ int reg_end = reg_idx + constant.RegisterCount;
|
|
|
+ if (!r_query_constants(stage, offset, *type, loc, reg_set, reg_idx, reg_end)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
- if (dxgsg9_cat.is_debug()) {
|
|
|
- const char sets[] = {'b', 'i', 'c', 's'};
|
|
|
+ if (dxgsg9_cat.is_debug()) {
|
|
|
+ const char sets[] = {'b', 'i', 'c', 's'};
|
|
|
+ if (type->Class == D3DXPC_STRUCT) {
|
|
|
dxgsg9_cat.debug()
|
|
|
<< " struct " << name << "[" << type->Elements << "] (" << *var.name
|
|
|
<< "@" << loc << ") at register " << sets[constant.RegisterSet]
|
|
|
<< constant.RegisterIndex;
|
|
|
-
|
|
|
- if (constant.RegisterCount > 1) {
|
|
|
- dxgsg9_cat.debug(false)
|
|
|
- << ".." << (constant.RegisterIndex + constant.RegisterCount - 1);
|
|
|
- }
|
|
|
- dxgsg9_cat.debug(false) << std::endl;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- D3DXSHADER_STRUCTMEMBERINFO *members = (D3DXSHADER_STRUCTMEMBERINFO *)(offset + type->StructMemberInfo);
|
|
|
- int reg_index = constant.RegisterIndex;
|
|
|
-
|
|
|
- for (WORD ei = 0; ei < type->Elements; ++ei) {
|
|
|
- for (DWORD mi = 0; mi < type->StructMembers; ++mi) {
|
|
|
- D3DXSHADER_TYPEINFO *type = (D3DXSHADER_TYPEINFO *)(offset + members[mi].TypeInfo);
|
|
|
- const char *name = (char *)(offset + members[mi].Name);
|
|
|
-
|
|
|
- if (type->StructMembers > 0) {
|
|
|
- dxgsg9_cat.error()
|
|
|
- << "Nested structs are not currently supported.\n";
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- ConstantRegister ® = _register_map[(size_t)loc];
|
|
|
- reg.set = (D3DXREGISTER_SET)constant.RegisterSet;
|
|
|
- reg.count = std::max(reg.count, (UINT)(type->Elements * type->Rows));
|
|
|
- switch (module->get_stage()) {
|
|
|
- case ShaderModule::Stage::vertex:
|
|
|
- reg.vreg = reg_index;
|
|
|
- break;
|
|
|
- case ShaderModule::Stage::fragment:
|
|
|
- reg.freg = reg_index;
|
|
|
- break;
|
|
|
- default:
|
|
|
- reg.count = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- reg_index += type->Elements * type->Rows;
|
|
|
- loc += type->Elements;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Non-aggregate type. Note that arrays of arrays are not supported.
|
|
|
- nassertr(!element_type->is_aggregate_type(), false);
|
|
|
-
|
|
|
- // Note that RegisterCount may be lower than Rows * Elements if the
|
|
|
- // optimizer decided that eg. the last row of a matrix is not used!
|
|
|
-
|
|
|
- ConstantRegister ® = _register_map[(size_t)loc];
|
|
|
- reg.set = (D3DXREGISTER_SET)constant.RegisterSet;
|
|
|
- reg.count = std::max(reg.count, (UINT)constant.RegisterCount);
|
|
|
- switch (module->get_stage()) {
|
|
|
- case ShaderModule::Stage::vertex:
|
|
|
- reg.vreg = constant.RegisterIndex;
|
|
|
- break;
|
|
|
- case ShaderModule::Stage::fragment:
|
|
|
- reg.freg = constant.RegisterIndex;
|
|
|
- break;
|
|
|
- default:
|
|
|
- reg.count = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-#ifndef NDEBUG
|
|
|
- if (dxgsg9_cat.is_debug()) {
|
|
|
+ } else {
|
|
|
const char *types[] = {"void", "bool", "int", "float", "string", "texture", "texture1D", "texture2D", "texture3D", "textureCUBE", "sampler", "sampler1D", "sampler2D", "sampler3D", "samplerCUBE"};
|
|
|
- const char sets[] = {'b', 'i', 'c', 's'};
|
|
|
dxgsg9_cat.debug()
|
|
|
<< " " << ((type->Type <= D3DXPT_SAMPLERCUBE) ? types[type->Type] : "unknown")
|
|
|
<< " " << name << "[" << type->Elements << "] (" << *var.name
|
|
|
<< "@" << loc << ") at register " << sets[constant.RegisterSet]
|
|
|
<< constant.RegisterIndex;
|
|
|
+ }
|
|
|
+ if (constant.RegisterCount > 1) {
|
|
|
+ dxgsg9_cat.debug(false)
|
|
|
+ << ".." << (constant.RegisterIndex + constant.RegisterCount - 1);
|
|
|
+ }
|
|
|
+ dxgsg9_cat.debug(false) << std::endl;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
|
|
|
- if (constant.RegisterCount > 1) {
|
|
|
- dxgsg9_cat.debug(false)
|
|
|
- << ".." << (constant.RegisterIndex + constant.RegisterCount - 1);
|
|
|
+/**
|
|
|
+ * Recursive method used by query_constants.
|
|
|
+ */
|
|
|
+bool DXShaderContext9::
|
|
|
+r_query_constants(Shader::Stage stage, BYTE *offset, D3DXSHADER_TYPEINFO &typeinfo,
|
|
|
+ int &loc, int reg_set, int ®_idx, int reg_end) {
|
|
|
+ if (typeinfo.Class == D3DXPC_STRUCT) {
|
|
|
+ //const ShaderType::Struct *struct_type = element_type->as_struct();
|
|
|
+ //nassertr(struct_type != nullptr, false);
|
|
|
+ D3DXSHADER_STRUCTMEMBERINFO *members = (D3DXSHADER_STRUCTMEMBERINFO *)(offset + typeinfo.StructMemberInfo);
|
|
|
+
|
|
|
+ for (WORD ei = 0; ei < typeinfo.Elements && reg_idx < reg_end; ++ei) {
|
|
|
+ for (DWORD mi = 0; mi < typeinfo.StructMembers && reg_idx < reg_end; ++mi) {
|
|
|
+ D3DXSHADER_TYPEINFO *typeinfo = (D3DXSHADER_TYPEINFO *)(offset + members[mi].TypeInfo);
|
|
|
+
|
|
|
+ if (!r_query_constants(stage, offset, *typeinfo, loc, reg_set, reg_idx, reg_end)) {
|
|
|
+ return false;
|
|
|
}
|
|
|
- dxgsg9_cat.debug(false) << std::endl;
|
|
|
}
|
|
|
-#endif
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // Non-aggregate type. Note that arrays of arrays are not supported.
|
|
|
+ //nassertr(!element_type->is_aggregate_type(), false);
|
|
|
+
|
|
|
+ // Note that RegisterCount may be lower than Rows * Elements if the
|
|
|
+ // optimizer decided that eg. the last row of a matrix is not used!
|
|
|
+
|
|
|
+ nassertr((size_t)loc < _register_map.size(), false);
|
|
|
+
|
|
|
+ ConstantRegister ® = _register_map[(size_t)loc];
|
|
|
+ reg.set = (D3DXREGISTER_SET)reg_set;
|
|
|
+ reg.count = std::max(reg.count, (UINT)(reg_end - reg_idx));
|
|
|
+ switch (stage) {
|
|
|
+ case ShaderModule::Stage::vertex:
|
|
|
+ reg.vreg = reg_idx;
|
|
|
+ break;
|
|
|
+ case ShaderModule::Stage::fragment:
|
|
|
+ reg.freg = reg_idx;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ reg.count = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ loc += typeinfo.Elements;
|
|
|
+ reg_idx += typeinfo.Elements * typeinfo.Rows;
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
@@ -547,7 +553,7 @@ issue_parameters(GSG *gsg, int altered) {
|
|
|
// error.
|
|
|
reg.count = -1;
|
|
|
}
|
|
|
- if (num_cols == 4) {
|
|
|
+ else if (num_cols == 4) {
|
|
|
// Straight passthrough, hooray!
|
|
|
void *data = ptr_data._ptr;
|
|
|
if (reg.vreg >= 0) {
|