diff options
| author | 2018-03-24 03:59:51 -0400 | |
|---|---|---|
| committer | 2018-03-26 21:16:53 -0400 | |
| commit | 0162a2d5cbfb0e0df7f99187a87c031416fd79cc (patch) | |
| tree | 978bf094dae0f6a369065adeb8eb234f00b02a99 /src | |
| parent | Maxwell3D: Call AccelerateDrawBatch on DrawArrays. (diff) | |
| download | yuzu-0162a2d5cbfb0e0df7f99187a87c031416fd79cc.tar.gz yuzu-0162a2d5cbfb0e0df7f99187a87c031416fd79cc.tar.xz yuzu-0162a2d5cbfb0e0df7f99187a87c031416fd79cc.zip | |
gl_rasterizer: Implement DrawTriangles.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 195 |
1 files changed, 194 insertions, 1 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 982e84768..c44ce4a18 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -197,8 +197,201 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | void RasterizerOpenGL::DrawTriangles() { | 199 | void RasterizerOpenGL::DrawTriangles() { |
| 200 | if (accelerate_draw == AccelDraw::Disabled) | ||
| 201 | return; | ||
| 202 | |||
| 200 | MICROPROFILE_SCOPE(OpenGL_Drawing); | 203 | MICROPROFILE_SCOPE(OpenGL_Drawing); |
| 201 | UNIMPLEMENTED(); | 204 | const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; |
| 205 | |||
| 206 | // TODO(bunnei): Implement these | ||
| 207 | const bool has_stencil = false; | ||
| 208 | const bool using_color_fb = true; | ||
| 209 | const bool using_depth_fb = false; | ||
| 210 | |||
| 211 | MathUtil::Rectangle<s32> viewport_rect_unscaled{ | ||
| 212 | static_cast<s32>(regs.viewport[0].x), // left | ||
| 213 | static_cast<s32>(regs.viewport[0].y + regs.viewport[0].height), // top | ||
| 214 | static_cast<s32>(regs.viewport[0].x + regs.viewport[0].width), // right | ||
| 215 | static_cast<s32>(regs.viewport[0].y) // bottom | ||
| 216 | }; | ||
| 217 | |||
| 218 | const bool write_color_fb = | ||
| 219 | state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE || | ||
| 220 | state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE; | ||
| 221 | |||
| 222 | const bool write_depth_fb = | ||
| 223 | (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) || | ||
| 224 | (has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0); | ||
| 225 | |||
| 226 | Surface color_surface; | ||
| 227 | Surface depth_surface; | ||
| 228 | MathUtil::Rectangle<u32> surfaces_rect; | ||
| 229 | std::tie(color_surface, depth_surface, surfaces_rect) = | ||
| 230 | res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect_unscaled); | ||
| 231 | |||
| 232 | const u16 res_scale = color_surface != nullptr | ||
| 233 | ? color_surface->res_scale | ||
| 234 | : (depth_surface == nullptr ? 1u : depth_surface->res_scale); | ||
| 235 | |||
| 236 | MathUtil::Rectangle<u32> draw_rect{ | ||
| 237 | static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.left) + | ||
| 238 | viewport_rect_unscaled.left * res_scale, | ||
| 239 | surfaces_rect.left, surfaces_rect.right)), // Left | ||
| 240 | static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + | ||
| 241 | viewport_rect_unscaled.top * res_scale, | ||
| 242 | surfaces_rect.bottom, surfaces_rect.top)), // Top | ||
| 243 | static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.left) + | ||
| 244 | viewport_rect_unscaled.right * res_scale, | ||
| 245 | surfaces_rect.left, surfaces_rect.right)), // Right | ||
| 246 | static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + | ||
| 247 | viewport_rect_unscaled.bottom * res_scale, | ||
| 248 | surfaces_rect.bottom, surfaces_rect.top))}; // Bottom | ||
| 249 | |||
| 250 | // Bind the framebuffer surfaces | ||
| 251 | state.draw.draw_framebuffer = framebuffer.handle; | ||
| 252 | state.Apply(); | ||
| 253 | |||
| 254 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | ||
| 255 | color_surface != nullptr ? color_surface->texture.handle : 0, 0); | ||
| 256 | if (depth_surface != nullptr) { | ||
| 257 | if (has_stencil) { | ||
| 258 | // attach both depth and stencil | ||
| 259 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 260 | depth_surface->texture.handle, 0); | ||
| 261 | } else { | ||
| 262 | // attach depth | ||
| 263 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, | ||
| 264 | depth_surface->texture.handle, 0); | ||
| 265 | // clear stencil attachment | ||
| 266 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 267 | } | ||
| 268 | } else { | ||
| 269 | // clear both depth and stencil attachment | ||
| 270 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||
| 271 | 0); | ||
| 272 | } | ||
| 273 | |||
| 274 | // Sync the viewport | ||
| 275 | state.viewport.x = | ||
| 276 | static_cast<GLint>(surfaces_rect.left) + viewport_rect_unscaled.left * res_scale; | ||
| 277 | state.viewport.y = | ||
| 278 | static_cast<GLint>(surfaces_rect.bottom) + viewport_rect_unscaled.bottom * res_scale; | ||
| 279 | state.viewport.width = static_cast<GLsizei>(viewport_rect_unscaled.GetWidth() * res_scale); | ||
| 280 | state.viewport.height = static_cast<GLsizei>(viewport_rect_unscaled.GetHeight() * res_scale); | ||
| 281 | |||
| 282 | // TODO(bunnei): Sync framebuffer_scale uniform here | ||
| 283 | // TODO(bunnei): Sync scissorbox uniform(s) here | ||
| 284 | // TODO(bunnei): Sync and bind the texture surfaces | ||
| 285 | |||
| 286 | // Sync and bind the shader | ||
| 287 | if (shader_dirty) { | ||
| 288 | SetShader(); | ||
| 289 | shader_dirty = false; | ||
| 290 | } | ||
| 291 | |||
| 292 | // Sync the uniform data | ||
| 293 | if (uniform_block_data.dirty) { | ||
| 294 | glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformData), &uniform_block_data.data); | ||
| 295 | uniform_block_data.dirty = false; | ||
| 296 | } | ||
| 297 | |||
| 298 | // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable | ||
| 299 | // scissor test to prevent drawing outside of the framebuffer region | ||
| 300 | state.scissor.enabled = true; | ||
| 301 | state.scissor.x = draw_rect.left; | ||
| 302 | state.scissor.y = draw_rect.bottom; | ||
| 303 | state.scissor.width = draw_rect.GetWidth(); | ||
| 304 | state.scissor.height = draw_rect.GetHeight(); | ||
| 305 | state.Apply(); | ||
| 306 | |||
| 307 | // Draw the vertex batch | ||
| 308 | GLenum primitive_mode; | ||
| 309 | switch (regs.draw.topology) { | ||
| 310 | case Maxwell::PrimitiveTopology::TriangleStrip: | ||
| 311 | primitive_mode = GL_TRIANGLE_STRIP; | ||
| 312 | break; | ||
| 313 | default: | ||
| 314 | UNREACHABLE(); | ||
| 315 | } | ||
| 316 | |||
| 317 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | ||
| 318 | |||
| 319 | AnalyzeVertexArray(is_indexed); | ||
| 320 | state.draw.vertex_buffer = stream_buffer->GetHandle(); | ||
| 321 | state.Apply(); | ||
| 322 | |||
| 323 | size_t buffer_size = static_cast<size_t>(vs_input_size); | ||
| 324 | if (is_indexed) { | ||
| 325 | UNREACHABLE(); | ||
| 326 | } | ||
| 327 | buffer_size += sizeof(VSUniformData); | ||
| 328 | |||
| 329 | size_t ptr_pos = 0; | ||
| 330 | u8* buffer_ptr; | ||
| 331 | GLintptr buffer_offset; | ||
| 332 | std::tie(buffer_ptr, buffer_offset) = | ||
| 333 | stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4); | ||
| 334 | |||
| 335 | SetupVertexArray(buffer_ptr, buffer_offset); | ||
| 336 | ptr_pos += vs_input_size; | ||
| 337 | |||
| 338 | GLintptr index_buffer_offset = 0; | ||
| 339 | if (is_indexed) { | ||
| 340 | UNREACHABLE(); | ||
| 341 | } | ||
| 342 | |||
| 343 | SetupVertexShader(reinterpret_cast<VSUniformData*>(&buffer_ptr[ptr_pos]), | ||
| 344 | buffer_offset + static_cast<GLintptr>(ptr_pos)); | ||
| 345 | const GLintptr vs_ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); | ||
| 346 | ptr_pos += sizeof(VSUniformData); | ||
| 347 | |||
| 348 | stream_buffer->Unmap(); | ||
| 349 | |||
| 350 | const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { | ||
| 351 | if (has_ARB_direct_state_access) { | ||
| 352 | glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size); | ||
| 353 | } else { | ||
| 354 | glBindBuffer(GL_COPY_WRITE_BUFFER, handle); | ||
| 355 | glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size); | ||
| 356 | } | ||
| 357 | }; | ||
| 358 | |||
| 359 | copy_buffer(vs_uniform_buffer.handle, vs_ubo_offset, sizeof(VSUniformData)); | ||
| 360 | |||
| 361 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_shader->shader.handle); | ||
| 362 | |||
| 363 | if (is_indexed) { | ||
| 364 | UNREACHABLE(); | ||
| 365 | } else { | ||
| 366 | glDrawArrays(primitive_mode, 0, regs.vertex_buffer.count); | ||
| 367 | } | ||
| 368 | |||
| 369 | // Disable scissor test | ||
| 370 | state.scissor.enabled = false; | ||
| 371 | |||
| 372 | accelerate_draw = AccelDraw::Disabled; | ||
| 373 | |||
| 374 | // Unbind textures for potential future use as framebuffer attachments | ||
| 375 | for (auto& texture_unit : state.texture_units) { | ||
| 376 | texture_unit.texture_2d = 0; | ||
| 377 | } | ||
| 378 | state.Apply(); | ||
| 379 | |||
| 380 | // Mark framebuffer surfaces as dirty | ||
| 381 | MathUtil::Rectangle<u32> draw_rect_unscaled{ | ||
| 382 | draw_rect.left / res_scale, draw_rect.top / res_scale, draw_rect.right / res_scale, | ||
| 383 | draw_rect.bottom / res_scale}; | ||
| 384 | |||
| 385 | if (color_surface != nullptr && write_color_fb) { | ||
| 386 | auto interval = color_surface->GetSubRectInterval(draw_rect_unscaled); | ||
| 387 | res_cache.InvalidateRegion(boost::icl::first(interval), boost::icl::length(interval), | ||
| 388 | color_surface); | ||
| 389 | } | ||
| 390 | if (depth_surface != nullptr && write_depth_fb) { | ||
| 391 | auto interval = depth_surface->GetSubRectInterval(draw_rect_unscaled); | ||
| 392 | res_cache.InvalidateRegion(boost::icl::first(interval), boost::icl::length(interval), | ||
| 393 | depth_surface); | ||
| 394 | } | ||
| 202 | } | 395 | } |
| 203 | 396 | ||
| 204 | void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {} | 397 | void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {} |