void ShaderCompiler::compileProgram(IO* io, const ProgramDesc& programDesc, std::weak_ptr<DX12DeviceContext> context) { auto fmt = boost::format("Compiling program \"%1%\"") % programDesc.name; LOGS_INDENT_START << boost::str(fmt); Program prog; for (auto shaderDesc : programDesc.shaders) { auto fmt = boost::format("Path: %1%, Type: %2%, Entry: %3%") % shaderDesc.path % shaderDesc.type % shaderDesc.main; LOGS << boost::str(fmt); auto buffer = io->loadFile(shaderDesc.path); ID3DBlob* shaderBlob = nullptr; ID3DBlob* errorBlob = nullptr; auto hr = D3DCompile(buffer.c_str(), buffer.size(), shaderDesc.path.c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, shaderDesc.main.c_str(), getDXShaderType(shaderDesc.type).c_str(), shaderDesc.flags, 0, &shaderBlob, &errorBlob); if (FAILED(hr)) { if (errorBlob != nullptr) { LOGE << "Compilation failed" << std::endl << static_cast<char*>(errorBlob->GetBufferPointer()); errorBlob->Release(); } if (shaderBlob != nullptr) shaderBlob->Release(); fmt = boost::format("Shader compilation failed: %1%") % shaderDesc.path; throw new std::runtime_error(boost::str(fmt)); } D3D12_SHADER_BYTECODE bc; bc.BytecodeLength = shaderBlob->GetBufferSize(); bc.pShaderBytecode = shaderBlob->GetBufferPointer(); if (shaderDesc.type == "vs") prog.vs = bc; else if (shaderDesc.type == "ps") prog.ps = bc; getShaderResources(shaderBlob, context); } LOGS_INDENT_END << "Program done."; }
/* * SHM IN: * fname : * * operation: DBG_GET_SHADER_CODE * SHM out: * fname : * * result : DBG_SHADER_CODE or DBG_ERROR_CODE on error * numItems : number of returned shader codes (0 or 3) * items[0] : pointer to vertex shader src * items[1] : length of vertex shader src * items[2] : pointer to geometry shader src * items[3] : length of geometry shader src * items[4] : pointer to fragment shader src * items[5] : length of fragment shader src * items[6] : pointer to shader resources (TBuiltInResource*) * items[7] : number of active uniforms * items[8] : size of serialized uniforms array * items[9] : pointer to serialzied active uniforms */ void getShaderCode(void) { char** source[3] = {NULL, NULL, NULL}; char* shaderSource[3] = {NULL, NULL, NULL}; struct TBuiltInResource *shaderResources = NULL; GLint numUniforms = 0; char* serializedUniforms = NULL; GLint serializedUniformsSize = 0; int numSourceStrings[3] = {0, 0, 0}; int lenSourceStrings[3] = {0, 0, 0}; int error; ShaderProgram shader; DbgRec* rec; int i, j; #ifdef _WIN32 /* HAZARD BUG OMGWTF This is plain wrong. Use GetCurrentThreadId() */ rec = getThreadRecord(GetCurrentProcessId()); #else /* _WIN32 */ rec = getThreadRecord(getpid()); #endif /* _WIN32 */ /* clear smem */ rec->numItems = 0; for (i = 0; i < 9; ++i) { rec->items[i] = 0; } error = getCurrentShader(&shader); if (error) { setErrorCode(error); return; } if (shader.programHandle == 0) { rec->result = DBG_SHADER_CODE; rec->numItems = 0; return; } for (i = 0; i < shader.numObjects; i++) { void *tmpAlloc; int typeId = getTypeId(shader.objects[i].type); numSourceStrings[typeId]++; lenSourceStrings[typeId] += shader.objects[i].srcLength; tmpAlloc = realloc(source[typeId], numSourceStrings[typeId] * sizeof(char*)); if (!tmpAlloc) { dbgPrint(DBGLVL_ERROR, "Allocating memory for shaders failed: %s\n", strerror(errno)); freeShaderProgram(&shader); for (i = 0; i < 3; i++) { free(source[i]); } setErrorCode(DBG_ERROR_MEMORY_ALLOCATION_FAILED); return; } source[typeId] = tmpAlloc; source[typeId][numSourceStrings[typeId] - 1] = shader.objects[i].src; dbgPrint(DBGLVL_INFO, "source[%d][%d] = %s\n", typeId, numSourceStrings[typeId] - 1, shader.objects[i].src); } /* TODO: do something better than just append!!!! * GLSL allows for multiple strings per objects and the order is important for reconstructing * a correct single file code */ for (i = 0; i < 3; i++) { if (numSourceStrings[i] > 0) { lenSourceStrings[i]++; if (!(shaderSource[i] = malloc(lenSourceStrings[i] * sizeof(char)))) { dbgPrint(DBGLVL_ERROR, "not enough memory to combine all your shaders\n"); for (i = 0; i < 3; i++) { free(source[i]); free(shaderSource[i]); } freeShaderProgram(&shader); setErrorCode(DBG_ERROR_MEMORY_ALLOCATION_FAILED); return; } shaderSource[i][0] = '\0'; for (j = 0; j < numSourceStrings[i]; j++) { strcat(shaderSource[i], source[i][j]); } free(source[i]); source[i] = NULL; } } if (!serializeUniforms(&shader, &serializedUniforms, &serializedUniformsSize)) { for (i = 0; i < 3; i++) { free(shaderSource[i]); } setErrorCode(DBG_ERROR_MEMORY_ALLOCATION_FAILED); return; } numUniforms = shader.numUniforms; freeShaderProgram(&shader); /* query shader resources */ if (!(shaderResources = malloc(sizeof(struct TBuiltInResource)))) { for (i = 0; i < 3; i++) { free(shaderSource[i]); } setErrorCode(DBG_ERROR_MEMORY_ALLOCATION_FAILED); return; } error = getShaderResources(&shader, shaderResources); if (error) { for (i = 0; i < 3; i++) { free(shaderSource[i]); } free(serializedUniforms); free(shaderResources); setErrorCode(error); return; } /* set results */ rec->result = DBG_SHADER_CODE; rec->numItems = 3; for (i = 0; i < 3; i++) { rec->items[2 * i] = (ALIGNED_DATA) shaderSource[i]; rec->items[2 * i + 1] = (ALIGNED_DATA) lenSourceStrings[i]; } rec->items[6] = (ALIGNED_DATA) shaderResources; rec->items[7] = (ALIGNED_DATA) numUniforms; rec->items[8] = (ALIGNED_DATA) serializedUniformsSize; rec->items[9] = (ALIGNED_DATA) serializedUniforms; }