예제 #1
0
bool GLDriver::compilePixelShader(PixelShader &pixel, uint8_t *buffer, size_t size)
{
   auto sq_config = getRegister<latte::SQ_CONFIG>(latte::Register::SQ_CONFIG);
   auto spi_ps_in_control_0 = getRegister<latte::SPI_PS_IN_CONTROL_0>(latte::Register::SPI_PS_IN_CONTROL_0);
   auto spi_ps_in_control_1 = getRegister<latte::SPI_PS_IN_CONTROL_1>(latte::Register::SPI_PS_IN_CONTROL_1);
   auto cb_shader_mask = getRegister<latte::CB_SHADER_MASK>(latte::Register::CB_SHADER_MASK);
   fmt::MemoryWriter out;
   latte::Shader shader;
   std::string body;

   shader.type = latte::Shader::Pixel;

   if (!latte::decode(shader, gsl::as_span(buffer, size))) {
      gLog->error("Failed to decode pixel shader");
      return false;
   }

   latte::disassemble(shader, pixel.disassembly);

   if (!latte::blockify(shader)) {
      gLog->error("Failed to blockify pixel shader");
      return false;
   }

   if (!glsl::generateBody(shader, body)) {
      gLog->warn("Failed to translate 100% of instructions for pixel shader");
   }

   // Get pixel sampler types
   for (auto i = 0; i < MAX_SAMPLERS_PER_TYPE; ++i) {
      auto sq_tex_resource_word0 = getRegister<latte::SQ_TEX_RESOURCE_WORD0_N>(latte::Register::SQ_TEX_RESOURCE_WORD0_0 + 4 * (latte::SQ_PS_TEX_RESOURCE_0 + i * 7));
      auto sq_tex_resource_word4 = getRegister<latte::SQ_TEX_RESOURCE_WORD4_N>(latte::Register::SQ_TEX_RESOURCE_WORD4_0 + 4 * (latte::SQ_PS_TEX_RESOURCE_0 + i * 7));

      pixel.samplerTypes[i] = getSamplerType(sq_tex_resource_word0.DIM,
                                             sq_tex_resource_word4.NUM_FORMAT_ALL,
                                             sq_tex_resource_word4.FORMAT_COMP_X);
   }

   // Write header
   writeHeader(out);

   // Uniforms
   writeUniforms(out, shader, sq_config, pixel.samplerTypes);
   out << '\n';

   // Pixel Shader Inputs
   for (auto i = 0u; i < spi_ps_in_control_0.NUM_INTERP; ++i) {
      auto spi_ps_input_cntl = getRegister<latte::SPI_PS_INPUT_CNTL_0>(latte::Register::SPI_PS_INPUT_CNTL_0 + i * 4);

      if (spi_ps_input_cntl.FLAT_SHADE) {
         out << "flat ";
      }

      out << "in vec4 vs_out_" << spi_ps_input_cntl.SEMANTIC << ";\n";
   }
   out << '\n';

   // Pixel Shader Exports
   auto maskBits = cb_shader_mask.value;

   for (auto i = 0; i < 8; ++i) {
      if (maskBits & 0xf) {
         out << "out vec4 ps_out_" << i << ";\n";
      }

      maskBits >>= 4;
   }
   out << '\n';

   // Program code
   out << "void main()\n"
      << "{\n";

   writeLocals(out, shader);
   writeExports(out, shader);

   // Assign vertex shader output to our GPR
   for (auto i = 0u; i < spi_ps_in_control_0.NUM_INTERP; ++i) {
      auto spi_ps_input_cntl = getRegister<latte::SPI_PS_INPUT_CNTL_0>(latte::Register::SPI_PS_INPUT_CNTL_0 + i * 4);
      auto id = spi_ps_input_cntl.SEMANTIC;

      if (id == 0xff) {
         continue;
      }

      out << "R[" << i << "] = vs_out_" << id << ";\n";
   }

   out << '\n' << body << '\n';

   for (auto exp : shader.exports) {
      switch (exp->exportType) {
      case latte::SQ_EXPORT_PIXEL: {
         auto mask = cb_shader_mask.value >> (4 * exp->arrayBase);

         if (!mask) {
            gLog->warn("Export is masked by cb_shader_mask");
         } else {
            out
               << "ps_out_"
               << exp->arrayBase
               << " = exp_pixel_"
               << exp->arrayBase << '.';

            if (mask & (1 << 0)) {
               out << 'x';
            }

            if (mask & (1 << 1)) {
               out << 'y';
            }

            if (mask & (1 << 2)) {
               out << 'z';
            }

            if (mask & (1 << 3)) {
               out << 'w';
            }

            out << ";\n";
         }
      } break;
      case latte::SQ_EXPORT_POS:
         throw std::logic_error("Unexpected position export in pixel shader.");
         break;
      case latte::SQ_EXPORT_PARAM:
         throw std::logic_error("Unexpected parameter export in pixel shader.");
         break;
      }
   }

   out << "}\n";

   pixel.code = out.str();
   return true;
}
예제 #2
0
std::string TransFunc::getShaderDefines() const {
    return "#define TF_SAMPLER_TYPE " + getSamplerType() + "\n";
}
예제 #3
0
bool GLDriver::compileVertexShader(VertexShader &vertex, FetchShader &fetch, uint8_t *buffer, size_t size)
{
   auto sq_config = getRegister<latte::SQ_CONFIG>(latte::Register::SQ_CONFIG);
   auto spi_vs_out_config = getRegister<latte::SPI_VS_OUT_CONFIG>(latte::Register::SPI_VS_OUT_CONFIG);
   fmt::MemoryWriter out;
   latte::Shader shader;
   std::string body;
   FetchShader::Attrib *semanticAttribs[32];
   memset(semanticAttribs, 0, sizeof(FetchShader::Attrib *) * 32);

   shader.type = latte::Shader::Vertex;

   if (!latte::decode(shader, gsl::as_span(buffer, size))) {
      gLog->error("Failed to decode vertex shader");
      return false;
   }

   latte::disassemble(shader, vertex.disassembly);

   if (!latte::blockify(shader)) {
      gLog->error("Failed to blockify vertex shader");
      return false;
   }

   if (!glsl::generateBody(shader, body)) {
      gLog->warn("Failed to translate 100% of instructions for vertex shader");
   }

   // Get vertex sampler types
   for (auto i = 0; i < MAX_SAMPLERS_PER_TYPE; ++i) {
      auto sq_tex_resource_word0 = getRegister<latte::SQ_TEX_RESOURCE_WORD0_N>(latte::Register::SQ_TEX_RESOURCE_WORD0_0 + 4 * (latte::SQ_PS_TEX_RESOURCE_0 + i * 7));
      auto sq_tex_resource_word4 = getRegister<latte::SQ_TEX_RESOURCE_WORD4_N>(latte::Register::SQ_TEX_RESOURCE_WORD4_0 + 4 * (latte::SQ_PS_TEX_RESOURCE_0 + i * 7));

      vertex.samplerTypes[i] = getSamplerType(sq_tex_resource_word0.DIM,
                                              sq_tex_resource_word4.NUM_FORMAT_ALL,
                                              sq_tex_resource_word4.FORMAT_COMP_X);
   }

   // Write header
   writeHeader(out);

   // Uniforms
   writeUniforms(out, shader, sq_config, vertex.samplerTypes);
   out << '\n';

   // Vertex Shader Inputs
   for (auto &attrib : fetch.attribs) {
      semanticAttribs[attrib.location] = &attrib;

      out << "in "
          << getGLSLDataFormat(attrib.format, attrib.numFormat, attrib.formatComp)
          << " fs_out_" << attrib.location << ";\n";
   }
   out << '\n';

   // Vertex Shader Exports
   for (auto i = 0u; i <= spi_vs_out_config.VS_EXPORT_COUNT; i++) {
      out << "out vec4 vs_out_" << i << ";\n";
   }
   out << '\n';

   // Program code
   out << "void main()\n"
       << "{\n";

   writeLocals(out, shader);
   writeExports(out, shader);

   // Initialise registers
   if (shader.gprsUsed.find(0) != shader.gprsUsed.end()) {
      // TODO: Check which order of VertexID and InstanceID for r0.x, r0.y
      out << "R[0] = vec4(intBitsToFloat(gl_VertexID), intBitsToFloat(gl_InstanceID), 0.0, 0.0);\n";
   }

   // Assign fetch shader output to our GPR
   for (auto i = 0u; i < 32; ++i) {
      auto sq_vtx_semantic = getRegister<latte::SQ_VTX_SEMANTIC_N>(latte::Register::SQ_VTX_SEMANTIC_0 + i * 4);
      auto id = sq_vtx_semantic.SEMANTIC_ID;

      if (sq_vtx_semantic.SEMANTIC_ID == 0xff) {
         continue;
      }

      auto attrib = semanticAttribs[id];

      if (!attrib) {
         gLog->error("Invalid semantic mapping: {}", id);
         continue;
      }

      out << "R[" << (i + 1) << "] = ";

      auto channels = getDataFormatChannels(attrib->format);

      switch (channels) {
      case 1:
         out << "vec4(fs_out_" << attrib->location << ", 0.0, 0.0, 0.0);\n";
         break;
      case 2:
         out << "vec4(fs_out_" << attrib->location << ", 0.0, 0.0);\n";
         break;
      case 3:
         out << "vec4(fs_out_" << attrib->location << ", 0.0);\n";
         break;
      case 4:
         out << "fs_out_" << attrib->location << ";\n";
         break;
      }
   }

   out << '\n' << body << '\n';

   for (auto exp : shader.exports) {
      switch (exp->exportType) {
      case latte::SQ_EXPORT_POS:
         out << "gl_Position = exp_position_" << (exp->arrayBase - 60) << ";\n";
         break;
      case latte::SQ_EXPORT_PARAM:
         // TODO: Use vs_out semantics?
         out << "vs_out_" << exp->arrayBase << " = exp_param_" << exp->arrayBase << ";\n";
         break;
      case latte::SQ_EXPORT_PIXEL:
         throw std::logic_error("Unexpected pixel export in vertex shader.");
         break;
      }
   }

   out << "}\n";

   vertex.code = out.str();
   return true;
}