1 #include <cstdio>
2 #include <vector>
3 #include <string>
4 #include <algorithm>
5 #include <map>
6
7 #include "ppsspp_config.h"
8
9 #include "Common/Data/Convert/ColorConv.h"
10 #include "Common/Data/Convert/SmallDataConvert.h"
11 #include "Common/Math/math_util.h"
12 #include "Common/Math/lin/matrix4x4.h"
13 #include "Common/GPU/thin3d.h"
14 #include "Common/GPU/Shader.h"
15 #include "Common/GPU/OpenGL/DataFormatGL.h"
16 #include "Common/GPU/OpenGL/GLCommon.h"
17 #include "Common/GPU/OpenGL/GLDebugLog.h"
18 #include "Common/GPU/OpenGL/GLFeatures.h"
19
20 #include "Common/GPU/OpenGL/GLRenderManager.h"
21
22 // #define DEBUG_READ_PIXELS 1
23
24 namespace Draw {
25
26 static const unsigned short compToGL[] = {
27 GL_NEVER,
28 GL_LESS,
29 GL_EQUAL,
30 GL_LEQUAL,
31 GL_GREATER,
32 GL_NOTEQUAL,
33 GL_GEQUAL,
34 GL_ALWAYS
35 };
36
37 static const unsigned short blendEqToGL[] = {
38 GL_FUNC_ADD,
39 GL_FUNC_SUBTRACT,
40 GL_FUNC_REVERSE_SUBTRACT,
41 GL_MIN,
42 GL_MAX,
43 };
44
45 static const unsigned short blendFactorToGL[] = {
46 GL_ZERO,
47 GL_ONE,
48 GL_SRC_COLOR,
49 GL_ONE_MINUS_SRC_COLOR,
50 GL_DST_COLOR,
51 GL_ONE_MINUS_DST_COLOR,
52 GL_SRC_ALPHA,
53 GL_ONE_MINUS_SRC_ALPHA,
54 GL_DST_ALPHA,
55 GL_ONE_MINUS_DST_ALPHA,
56 GL_CONSTANT_COLOR,
57 GL_ONE_MINUS_CONSTANT_COLOR,
58 GL_CONSTANT_ALPHA,
59 GL_ONE_MINUS_CONSTANT_ALPHA,
60 #if !defined(USING_GLES2) // TODO: Remove when we have better headers
61 GL_SRC1_COLOR,
62 GL_ONE_MINUS_SRC1_COLOR,
63 GL_SRC1_ALPHA,
64 GL_ONE_MINUS_SRC1_ALPHA,
65 #elif !PPSSPP_PLATFORM(IOS)
66 GL_SRC1_COLOR_EXT,
67 GL_ONE_MINUS_SRC1_COLOR_EXT,
68 GL_SRC1_ALPHA_EXT,
69 GL_ONE_MINUS_SRC1_ALPHA_EXT,
70 #else
71 GL_INVALID_ENUM,
72 GL_INVALID_ENUM,
73 GL_INVALID_ENUM,
74 GL_INVALID_ENUM,
75 #endif
76 };
77
78 static const unsigned short texWrapToGL[] = {
79 GL_REPEAT,
80 GL_MIRRORED_REPEAT,
81 GL_CLAMP_TO_EDGE,
82 #if !defined(USING_GLES2)
83 GL_CLAMP_TO_BORDER,
84 #else
85 GL_CLAMP_TO_EDGE,
86 #endif
87 };
88
89 static const unsigned short texFilterToGL[] = {
90 GL_NEAREST,
91 GL_LINEAR,
92 };
93
94 static const unsigned short texMipFilterToGL[2][2] = {
95 // Min nearest:
96 { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR },
97 // Min linear:
98 { GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR },
99 };
100
101 #ifndef USING_GLES2
102 static const unsigned short logicOpToGL[] = {
103 GL_CLEAR,
104 GL_SET,
105 GL_COPY,
106 GL_COPY_INVERTED,
107 GL_NOOP,
108 GL_INVERT,
109 GL_AND,
110 GL_NAND,
111 GL_OR,
112 GL_NOR,
113 GL_XOR,
114 GL_EQUIV,
115 GL_AND_REVERSE,
116 GL_AND_INVERTED,
117 GL_OR_REVERSE,
118 GL_OR_INVERTED,
119 };
120 #endif
121
122 static const GLuint stencilOpToGL[8] = {
123 GL_KEEP,
124 GL_ZERO,
125 GL_REPLACE,
126 GL_INCR,
127 GL_DECR,
128 GL_INVERT,
129 GL_INCR_WRAP,
130 GL_DECR_WRAP,
131 };
132
133 static const unsigned short primToGL[] = {
134 GL_POINTS,
135 GL_LINES,
136 GL_LINE_STRIP,
137 GL_TRIANGLES,
138 GL_TRIANGLE_STRIP,
139 GL_TRIANGLE_FAN,
140 };
141
142 class OpenGLBuffer;
143
144 class OpenGLBlendState : public BlendState {
145 public:
146 bool enabled;
147 GLuint eqCol, eqAlpha;
148 GLuint srcCol, srcAlpha, dstCol, dstAlpha;
149 int colorMask;
150 // uint32_t fixedColor;
151
Apply(GLRenderManager * render)152 void Apply(GLRenderManager *render) {
153 render->SetBlendAndMask(colorMask, enabled, srcCol, dstCol, srcAlpha, dstAlpha, eqCol, eqAlpha);
154 }
155 };
156
157 class OpenGLSamplerState : public SamplerState {
158 public:
159 GLint wrapU;
160 GLint wrapV;
161 GLint wrapW;
162 GLint magFilt;
163 GLint minFilt;
164 GLint mipMinFilt;
165 };
166
167 class OpenGLDepthStencilState : public DepthStencilState {
168 public:
169 bool depthTestEnabled;
170 bool depthWriteEnabled;
171 GLuint depthComp;
172 // TODO: Two-sided. Although in practice, do we care?
173 bool stencilEnabled;
174 GLuint stencilFail;
175 GLuint stencilZFail;
176 GLuint stencilPass;
177 GLuint stencilCompareOp;
178 uint8_t stencilCompareMask;
179 uint8_t stencilWriteMask;
180
Apply(GLRenderManager * render,uint8_t stencilRef)181 void Apply(GLRenderManager *render, uint8_t stencilRef) {
182 render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp);
183 render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilRef, stencilCompareMask);
184 render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass);
185 }
186 };
187
188 class OpenGLRasterState : public RasterState {
189 public:
Apply(GLRenderManager * render)190 void Apply(GLRenderManager *render) {
191 render->SetRaster(cullEnable, frontFace, cullMode, GL_FALSE, GL_FALSE);
192 }
193
194 GLboolean cullEnable;
195 GLenum cullMode;
196 GLenum frontFace;
197 };
198
ShaderStageToOpenGL(ShaderStage stage)199 GLuint ShaderStageToOpenGL(ShaderStage stage) {
200 switch (stage) {
201 case ShaderStage::Vertex: return GL_VERTEX_SHADER;
202 #ifndef USING_GLES2
203 case ShaderStage::Compute: return GL_COMPUTE_SHADER;
204 case ShaderStage::Geometry: return GL_GEOMETRY_SHADER;
205 #endif
206 case ShaderStage::Fragment:
207 default:
208 return GL_FRAGMENT_SHADER;
209 }
210 }
211
212 class OpenGLShaderModule : public ShaderModule {
213 public:
OpenGLShaderModule(GLRenderManager * render,ShaderStage stage,const std::string & tag)214 OpenGLShaderModule(GLRenderManager *render, ShaderStage stage, const std::string &tag) : render_(render), stage_(stage), tag_(tag) {
215 DEBUG_LOG(G3D, "Shader module created (%p)", this);
216 glstage_ = ShaderStageToOpenGL(stage);
217 }
218
~OpenGLShaderModule()219 ~OpenGLShaderModule() {
220 if (shader_)
221 render_->DeleteShader(shader_);
222 }
223
224 bool Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize);
GetShader() const225 GLRShader *GetShader() const {
226 return shader_;
227 }
GetSource() const228 const std::string &GetSource() const { return source_; }
229
GetLanguage()230 ShaderLanguage GetLanguage() {
231 return language_;
232 }
GetStage() const233 ShaderStage GetStage() const override {
234 return stage_;
235 }
236
237 private:
238 GLRenderManager *render_;
239 ShaderStage stage_;
240 ShaderLanguage language_ = GLSL_1xx;
241 GLRShader *shader_ = nullptr;
242 GLuint glstage_ = 0;
243 std::string source_; // So we can recompile in case of context loss.
244 std::string tag_;
245 };
246
Compile(GLRenderManager * render,ShaderLanguage language,const uint8_t * data,size_t dataSize)247 bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize) {
248 source_ = std::string((const char *)data);
249 // Add the prelude on automatically.
250 if (glstage_ == GL_FRAGMENT_SHADER || glstage_ == GL_VERTEX_SHADER) {
251 if (source_.find("#version") == source_.npos) {
252 source_ = ApplyGLSLPrelude(source_, glstage_);
253 }
254 }
255
256 shader_ = render->CreateShader(glstage_, source_, tag_);
257 return true;
258 }
259
260 class OpenGLInputLayout : public InputLayout {
261 public:
OpenGLInputLayout(GLRenderManager * render)262 OpenGLInputLayout(GLRenderManager *render) : render_(render) {}
263 ~OpenGLInputLayout();
264
265 void Compile(const InputLayoutDesc &desc);
RequiresBuffer()266 bool RequiresBuffer() {
267 return false;
268 }
269
270 GLRInputLayout *inputLayout_ = nullptr;
271 int stride = 0;
272 private:
273 GLRenderManager *render_;
274 };
275
276 class OpenGLPipeline : public Pipeline {
277 public:
OpenGLPipeline(GLRenderManager * render)278 OpenGLPipeline(GLRenderManager *render) : render_(render) {
279 }
~OpenGLPipeline()280 ~OpenGLPipeline() {
281 for (auto &iter : shaders) {
282 iter->Release();
283 }
284 if (program_) render_->DeleteProgram(program_);
285 }
286
287 bool LinkShaders();
288
RequiresBuffer()289 bool RequiresBuffer() override {
290 return inputLayout && inputLayout->RequiresBuffer();
291 }
292
293 GLuint prim = 0;
294 std::vector<OpenGLShaderModule *> shaders;
295 AutoRef<OpenGLInputLayout> inputLayout;
296 AutoRef<OpenGLDepthStencilState> depthStencil;
297 AutoRef<OpenGLBlendState> blend;
298 AutoRef<OpenGLRasterState> raster;
299
300 // TODO: Optimize by getting the locations first and putting in a custom struct
301 UniformBufferDesc dynamicUniforms;
302 GLint samplerLocs_[MAX_TEXTURE_SLOTS]{};
303 std::vector<GLint> dynamicUniformLocs_;
304 GLRProgram *program_ = nullptr;
305
306 private:
307 GLRenderManager *render_;
308 };
309
310 class OpenGLFramebuffer;
311 class OpenGLTexture;
312
313 class OpenGLContext : public DrawContext {
314 public:
315 OpenGLContext();
316 virtual ~OpenGLContext();
317
SetTargetSize(int w,int h)318 void SetTargetSize(int w, int h) override {
319 DrawContext::SetTargetSize(w, h);
320 renderManager_.Resize(w, h);
321 }
322
GetDeviceCaps() const323 const DeviceCaps &GetDeviceCaps() const override {
324 return caps_;
325 }
GetSupportedShaderLanguages() const326 uint32_t GetSupportedShaderLanguages() const override {
327 if (gl_extensions.GLES3) {
328 return (uint32_t)(ShaderLanguage::GLSL_3xx | ShaderLanguage::GLSL_1xx);
329 } else {
330 return (uint32_t)ShaderLanguage::GLSL_1xx;
331 }
332 }
333
334 uint32_t GetDataFormatSupport(DataFormat fmt) const override;
335
SetErrorCallback(ErrorCallbackFn callback,void * userdata)336 void SetErrorCallback(ErrorCallbackFn callback, void *userdata) override {
337 renderManager_.SetErrorCallback(callback, userdata);
338 }
339
340 DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
341 BlendState *CreateBlendState(const BlendStateDesc &desc) override;
342 SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override;
343 RasterState *CreateRasterState(const RasterStateDesc &desc) override;
344 Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) override;
345 InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override;
346 ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag) override;
347
348 Texture *CreateTexture(const TextureDesc &desc) override;
349 Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
350 Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override;
351
352 void BeginFrame() override;
353 void EndFrame() override;
354
355 void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
356
357 void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
358 bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
359 bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override;
360
361 // These functions should be self explanatory.
362 void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
GetCurrentRenderTarget()363 Framebuffer *GetCurrentRenderTarget() override {
364 return curRenderTarget_;
365 }
366 void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override;
367
368 void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
369
BindSamplerStates(int start,int count,SamplerState ** states)370 void BindSamplerStates(int start, int count, SamplerState **states) override {
371 _assert_(start + count <= MAX_TEXTURE_SLOTS);
372 for (int i = 0; i < count; i++) {
373 int index = i + start;
374 boundSamplers_[index] = static_cast<OpenGLSamplerState *>(states[i]);
375 }
376 }
377
SetScissorRect(int left,int top,int width,int height)378 void SetScissorRect(int left, int top, int width, int height) override {
379 renderManager_.SetScissor({ left, top, width, height });
380 }
381
SetViewports(int count,Viewport * viewports)382 void SetViewports(int count, Viewport *viewports) override {
383 // Same structure, different name.
384 renderManager_.SetViewport((GLRViewport &)*viewports);
385 }
386
SetBlendFactor(float color[4])387 void SetBlendFactor(float color[4]) override {
388 renderManager_.SetBlendFactor(color);
389 }
390
SetStencilRef(uint8_t ref)391 void SetStencilRef(uint8_t ref) override {
392 stencilRef_ = ref;
393 renderManager_.SetStencilFunc(
394 curPipeline_->depthStencil->stencilEnabled,
395 curPipeline_->depthStencil->stencilCompareOp,
396 ref,
397 curPipeline_->depthStencil->stencilCompareMask);
398 }
399
400 void BindTextures(int start, int count, Texture **textures) override;
401 void BindPipeline(Pipeline *pipeline) override;
BindVertexBuffers(int start,int count,Buffer ** buffers,const int * offsets)402 void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override {
403 _assert_(start + count <= ARRAY_SIZE(curVBuffers_));
404 for (int i = 0; i < count; i++) {
405 curVBuffers_[i + start] = (OpenGLBuffer *)buffers[i];
406 curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
407 }
408 }
BindIndexBuffer(Buffer * indexBuffer,int offset)409 void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
410 curIBuffer_ = (OpenGLBuffer *)indexBuffer;
411 curIBufferOffset_ = offset;
412 }
413
414 void UpdateDynamicUniformBuffer(const void *ub, size_t size) override;
415
416 // TODO: Add more sophisticated draws.
417 void Draw(int vertexCount, int offset) override;
418 void DrawIndexed(int vertexCount, int offset) override;
419 void DrawUP(const void *vdata, int vertexCount) override;
420
421 void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
422
GetInfoString(InfoField info) const423 std::string GetInfoString(InfoField info) const override {
424 // TODO: Make these actually query the right information
425 switch (info) {
426 case APINAME:
427 if (gl_extensions.IsGLES) {
428 return "OpenGL ES";
429 } else {
430 return "OpenGL";
431 }
432 case VENDORSTRING: return renderManager_.GetGLString(GL_VENDOR);
433 case VENDOR:
434 switch (caps_.vendor) {
435 case GPUVendor::VENDOR_AMD: return "VENDOR_AMD";
436 case GPUVendor::VENDOR_IMGTEC: return "VENDOR_POWERVR";
437 case GPUVendor::VENDOR_NVIDIA: return "VENDOR_NVIDIA";
438 case GPUVendor::VENDOR_INTEL: return "VENDOR_INTEL";
439 case GPUVendor::VENDOR_QUALCOMM: return "VENDOR_ADRENO";
440 case GPUVendor::VENDOR_ARM: return "VENDOR_ARM";
441 case GPUVendor::VENDOR_BROADCOM: return "VENDOR_BROADCOM";
442 case GPUVendor::VENDOR_VIVANTE: return "VENDOR_VIVANTE";
443 case GPUVendor::VENDOR_APPLE: return "VENDOR_APPLE";
444 case GPUVendor::VENDOR_UNKNOWN:
445 default:
446 return "VENDOR_UNKNOWN";
447 }
448 break;
449 case DRIVER: return renderManager_.GetGLString(GL_RENDERER);
450 case SHADELANGVERSION: return renderManager_.GetGLString(GL_SHADING_LANGUAGE_VERSION);
451 case APIVERSION: return renderManager_.GetGLString(GL_VERSION);
452 default: return "?";
453 }
454 }
455
GetNativeObject(NativeObject obj)456 uint64_t GetNativeObject(NativeObject obj) override {
457 switch (obj) {
458 case NativeObject::RENDER_MANAGER:
459 return (uint64_t)(uintptr_t)&renderManager_;
460 default:
461 return 0;
462 }
463 }
464
HandleEvent(Event ev,int width,int height,void * param1,void * param2)465 void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {}
466
GetCurrentStepId() const467 int GetCurrentStepId() const override {
468 return renderManager_.GetCurrentStepId();
469 }
470
471 void InvalidateCachedState() override;
472
473 private:
474 void ApplySamplers();
475
476 GLRenderManager renderManager_;
477
478 DeviceCaps caps_{};
479
480 // Bound state
481 AutoRef<OpenGLSamplerState> boundSamplers_[MAX_TEXTURE_SLOTS];
482 // Point to GLRTexture directly because they can point to the textures
483 // in framebuffers too (which also can be bound).
484 const GLRTexture *boundTextures_[MAX_TEXTURE_SLOTS]{};
485
486 AutoRef<OpenGLPipeline> curPipeline_;
487 AutoRef<OpenGLBuffer> curVBuffers_[4]{};
488 int curVBufferOffsets_[4]{};
489 AutoRef<OpenGLBuffer> curIBuffer_;
490 int curIBufferOffset_ = 0;
491 AutoRef<Framebuffer> curRenderTarget_;
492
493 uint8_t stencilRef_ = 0;
494
495 // Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences.
496 // But might as well have the structure ready, and can't hurt to rotate buffers.
497 struct FrameData {
498 GLPushBuffer *push;
499 };
500 FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]{};
501 };
502
MakeIntelSimpleVer(int v1,int v2,int v3)503 static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) {
504 return (v1 << 16) | (v2 << 8) | v3;
505 }
506
HasIntelDualSrcBug(int versions[4])507 static bool HasIntelDualSrcBug(int versions[4]) {
508 // Intel uses a confusing set of at least 3 version numbering schemes. This is the one given to OpenGL.
509 switch (MakeIntelSimpleVer(versions[0], versions[1], versions[2])) {
510 case MakeIntelSimpleVer(9, 17, 10):
511 case MakeIntelSimpleVer(9, 18, 10):
512 return false;
513 case MakeIntelSimpleVer(10, 18, 10):
514 return versions[3] < 4061;
515 case MakeIntelSimpleVer(10, 18, 14):
516 return versions[3] < 4080;
517 default:
518 // Older than above didn't support dual src anyway, newer should have the fix.
519 return false;
520 }
521 }
522
OpenGLContext()523 OpenGLContext::OpenGLContext() {
524 // TODO: Detect more caps
525 if (gl_extensions.IsGLES) {
526 if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) {
527 caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
528 } else {
529 caps_.preferredDepthBufferFormat = DataFormat::D16;
530 }
531 } else {
532 caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
533 }
534 caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object;
535 caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
536 caps_.depthClampSupported = gl_extensions.ARB_depth_clamp;
537
538 // Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader):
539 // This will induce a performance penalty on many architectures though so a blanket enable of this
540 // is probably not a good idea.
541 // https://stackoverflow.com/questions/5960757/how-to-emulate-gl-depth-clamp-nv
542
543 switch (gl_extensions.gpuVendor) {
544 case GPU_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
545 case GPU_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
546 case GPU_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
547 case GPU_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
548 case GPU_VENDOR_BROADCOM: caps_.vendor = GPUVendor::VENDOR_BROADCOM; break;
549 case GPU_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
550 case GPU_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
551 case GPU_VENDOR_VIVANTE: caps_.vendor = GPUVendor::VENDOR_VIVANTE; break;
552 case GPU_VENDOR_APPLE: caps_.vendor = GPUVendor::VENDOR_APPLE; break;
553 case GPU_VENDOR_UNKNOWN:
554 default:
555 caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
556 break;
557 }
558 for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
559 frameData_[i].push = renderManager_.CreatePushBuffer(i, GL_ARRAY_BUFFER, 64 * 1024);
560 }
561
562 if (!gl_extensions.VersionGEThan(3, 0, 0)) {
563 // Don't use this extension on sub 3.0 OpenGL versions as it does not seem reliable.
564 bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
565 } else if (caps_.vendor == GPUVendor::VENDOR_INTEL) {
566 // Note: this is for Intel drivers with GL3+.
567 // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/10117
568 // TODO: Remove entirely sometime reasonably far in driver years after 2015.
569 const std::string ver = GetInfoString(Draw::InfoField::APIVERSION);
570 int versions[4]{};
571 if (sscanf(ver.c_str(), "Build %d.%d.%d.%d", &versions[0], &versions[1], &versions[2], &versions[3]) == 4) {
572 if (HasIntelDualSrcBug(versions)) {
573 bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
574 }
575 }
576 }
577
578 // Try to detect old Tegra chips by checking for sub 3.0 GL versions. Like Vivante and Broadcom,
579 // those can't handle NaN values in conditionals.
580 if (caps_.vendor == GPUVendor::VENDOR_VIVANTE ||
581 caps_.vendor == GPUVendor::VENDOR_BROADCOM ||
582 (caps_.vendor == GPUVendor::VENDOR_NVIDIA && !gl_extensions.VersionGEThan(3, 0, 0))) {
583 bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL);
584 }
585
586 // TODO: Make this check more lenient. Disabled for all right now
587 // because it murders performance on Mali.
588 if (caps_.vendor != GPUVendor::VENDOR_NVIDIA) {
589 bugs_.Infest(Bugs::ANY_MAP_BUFFER_RANGE_SLOW);
590 }
591
592 if (caps_.vendor == GPUVendor::VENDOR_IMGTEC) {
593 // See https://github.com/hrydgard/ppsspp/commit/8974cd675e538f4445955e3eac572a9347d84232
594 // TODO: Should this workaround be removed for newer devices/drivers?
595 bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER);
596 }
597
598 #if PPSSPP_PLATFORM(IOS)
599 // For some reason, this bug does not appear on M1.
600 if (caps_.vendor == GPUVendor::VENDOR_APPLE) {
601 bugs_.Infest(Bugs::BROKEN_FLAT_IN_SHADER);
602 }
603 #endif
604
605 shaderLanguageDesc_.Init(GLSL_1xx);
606
607 shaderLanguageDesc_.glslVersionNumber = gl_extensions.GLSLVersion();
608
609 snprintf(shaderLanguageDesc_.driverInfo, sizeof(shaderLanguageDesc_.driverInfo),
610 "%s - GLSL %d", gl_extensions.model, gl_extensions.GLSLVersion());
611 // Detect shader language features.
612 if (gl_extensions.IsGLES) {
613 shaderLanguageDesc_.gles = true;
614 if (gl_extensions.GLES3) {
615 shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
616 shaderLanguageDesc_.fragColor0 = "fragColor0";
617 shaderLanguageDesc_.texture = "texture";
618 shaderLanguageDesc_.glslES30 = true;
619 shaderLanguageDesc_.bitwiseOps = true;
620 shaderLanguageDesc_.texelFetch = "texelFetch";
621 shaderLanguageDesc_.varying_vs = "out";
622 shaderLanguageDesc_.varying_fs = "in";
623 shaderLanguageDesc_.attribute = "in";
624 } else {
625 shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
626 if (gl_extensions.EXT_gpu_shader4) {
627 shaderLanguageDesc_.bitwiseOps = true;
628 shaderLanguageDesc_.texelFetch = "texelFetch2D";
629 }
630 if (gl_extensions.EXT_blend_func_extended) {
631 // Oldy moldy GLES, so use the fixed output name.
632 shaderLanguageDesc_.fragColor1 = "gl_SecondaryFragColorEXT";
633 }
634 }
635 } else {
636 // I don't know why we were checking for IsCoreContext here before.
637 if (gl_extensions.VersionGEThan(3, 3, 0)) {
638 shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
639 shaderLanguageDesc_.fragColor0 = "fragColor0";
640 shaderLanguageDesc_.texture = "texture";
641 shaderLanguageDesc_.glslES30 = true;
642 shaderLanguageDesc_.bitwiseOps = true;
643 shaderLanguageDesc_.texelFetch = "texelFetch";
644 shaderLanguageDesc_.varying_vs = "out";
645 shaderLanguageDesc_.varying_fs = "in";
646 shaderLanguageDesc_.attribute = "in";
647 } else if (gl_extensions.VersionGEThan(3, 0, 0)) {
648 shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
649 shaderLanguageDesc_.fragColor0 = "fragColor0";
650 shaderLanguageDesc_.texture = "texture";
651 shaderLanguageDesc_.bitwiseOps = true;
652 shaderLanguageDesc_.texelFetch = "texelFetch";
653 shaderLanguageDesc_.varying_vs = "out";
654 shaderLanguageDesc_.varying_fs = "in";
655 shaderLanguageDesc_.attribute = "in";
656 } else {
657 // This too...
658 shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
659 if (gl_extensions.EXT_gpu_shader4) {
660 shaderLanguageDesc_.bitwiseOps = true;
661 shaderLanguageDesc_.texelFetch = "texelFetch2D";
662 }
663 }
664 }
665
666 if (gl_extensions.IsGLES) {
667 caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch);
668 if (gl_extensions.EXT_shader_framebuffer_fetch) {
669 shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
670 shaderLanguageDesc_.lastFragData = gl_extensions.GLES3 ? "fragColor0" : "gl_LastFragData[0]";
671 } else if (gl_extensions.ARM_shader_framebuffer_fetch) {
672 shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
673 shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM";
674 }
675 }
676 }
677
~OpenGLContext()678 OpenGLContext::~OpenGLContext() {
679 DestroyPresets();
680 for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
681 renderManager_.DeletePushBuffer(frameData_[i].push);
682 }
683 }
684
BeginFrame()685 void OpenGLContext::BeginFrame() {
686 renderManager_.BeginFrame();
687 FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
688 renderManager_.BeginPushBuffer(frameData.push);
689 }
690
EndFrame()691 void OpenGLContext::EndFrame() {
692 FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
693 renderManager_.EndPushBuffer(frameData.push); // upload the data!
694 renderManager_.Finish();
695
696 InvalidateCachedState();
697 }
698
InvalidateCachedState()699 void OpenGLContext::InvalidateCachedState() {
700 // Unbind stuff.
701 for (auto &texture : boundTextures_) {
702 texture = nullptr;
703 }
704 for (auto &sampler : boundSamplers_) {
705 sampler = nullptr;
706 }
707 curPipeline_ = nullptr;
708 }
709
CreateInputLayout(const InputLayoutDesc & desc)710 InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) {
711 OpenGLInputLayout *fmt = new OpenGLInputLayout(&renderManager_);
712 fmt->Compile(desc);
713 return fmt;
714 }
715
TypeToTarget(TextureType type)716 GLuint TypeToTarget(TextureType type) {
717 switch (type) {
718 #ifndef USING_GLES2
719 case TextureType::LINEAR1D: return GL_TEXTURE_1D;
720 #endif
721 case TextureType::LINEAR2D: return GL_TEXTURE_2D;
722 case TextureType::LINEAR3D: return GL_TEXTURE_3D;
723 case TextureType::CUBE: return GL_TEXTURE_CUBE_MAP;
724 #ifndef USING_GLES2
725 case TextureType::ARRAY1D: return GL_TEXTURE_1D_ARRAY;
726 #endif
727 case TextureType::ARRAY2D: return GL_TEXTURE_2D_ARRAY;
728 default:
729 ERROR_LOG(G3D, "Bad texture type %d", (int)type);
730 return GL_NONE;
731 }
732 }
733
734 class OpenGLTexture : public Texture {
735 public:
736 OpenGLTexture(GLRenderManager *render, const TextureDesc &desc);
737 ~OpenGLTexture();
738
HasMips() const739 bool HasMips() const {
740 return mipLevels_ > 1 || generatedMips_;
741 }
742
GetType() const743 TextureType GetType() const { return type_; }
Bind(int stage)744 void Bind(int stage) {
745 render_->BindTexture(stage, tex_);
746 }
NumMipmaps() const747 int NumMipmaps() const {
748 return mipLevels_;
749 }
GetTex() const750 const GLRTexture *GetTex() const {
751 return tex_;
752 }
753
754 private:
755 void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback);
756
757 GLRenderManager *render_;
758 GLRTexture *tex_;
759
760 DataFormat format_;
761 TextureType type_;
762 int mipLevels_;
763 bool generatedMips_;
764 };
765
OpenGLTexture(GLRenderManager * render,const TextureDesc & desc)766 OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) {
767 generatedMips_ = false;
768 width_ = desc.width;
769 height_ = desc.height;
770 depth_ = desc.depth;
771 format_ = desc.format;
772 type_ = desc.type;
773 GLenum target = TypeToTarget(desc.type);
774 tex_ = render->CreateTexture(target, desc.width, desc.height, desc.mipLevels);
775
776 mipLevels_ = desc.mipLevels;
777 if (desc.initData.empty())
778 return;
779
780 int level = 0;
781 for (auto data : desc.initData) {
782 SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data, desc.initDataCallback);
783 width_ = (width_ + 1) / 2;
784 height_ = (height_ + 1) / 2;
785 depth_ = (depth_ + 1) / 2;
786 level++;
787 }
788 mipLevels_ = desc.generateMips ? desc.mipLevels : level;
789
790 bool genMips = false;
791 if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) {
792 // Assumes the texture is bound for editing
793 genMips = true;
794 generatedMips_ = true;
795 }
796 render->FinalizeTexture(tex_, mipLevels_, genMips);
797 }
798
~OpenGLTexture()799 OpenGLTexture::~OpenGLTexture() {
800 if (tex_) {
801 render_->DeleteTexture(tex_);
802 tex_ = 0;
803 generatedMips_ = false;
804 }
805 }
806
807 class OpenGLFramebuffer : public Framebuffer {
808 public:
OpenGLFramebuffer(GLRenderManager * render,GLRFramebuffer * framebuffer)809 OpenGLFramebuffer(GLRenderManager *render, GLRFramebuffer *framebuffer) : render_(render), framebuffer_(framebuffer) {
810 width_ = framebuffer->width;
811 height_ = framebuffer->height;
812 }
~OpenGLFramebuffer()813 ~OpenGLFramebuffer() {
814 render_->DeleteFramebuffer(framebuffer_);
815 }
816
817 GLRenderManager *render_;
818 GLRFramebuffer *framebuffer_ = nullptr;
819 };
820
SetImageData(int x,int y,int z,int width,int height,int depth,int level,int stride,const uint8_t * data,TextureCallback callback)821 void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback) {
822 if ((width != width_ || height != height_ || depth != depth_) && level == 0) {
823 // When switching to texStorage we need to handle this correctly.
824 width_ = width;
825 height_ = height;
826 depth_ = depth;
827 }
828
829 if (stride == 0)
830 stride = width;
831
832 size_t alignment = DataFormatSizeInBytes(format_);
833 // Make a copy of data with stride eliminated.
834 uint8_t *texData = new uint8_t[(size_t)(width * height * depth * alignment)];
835
836 bool texDataPopulated = false;
837 if (callback) {
838 texDataPopulated = callback(texData, data, width, height, depth, width * (int)alignment, height * width * (int)alignment);
839 }
840 if (texDataPopulated) {
841 if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) {
842 format_ = DataFormat::R5G5B5A1_UNORM_PACK16;
843 ConvertBGRA5551ToABGR1555((u16 *)texData, (const u16 *)texData, width * height * depth);
844 }
845 } else {
846 // Emulate support for DataFormat::A1R5G5B5_UNORM_PACK16.
847 if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) {
848 format_ = DataFormat::R5G5B5A1_UNORM_PACK16;
849 for (int y = 0; y < height; y++) {
850 ConvertBGRA5551ToABGR1555((u16 *)(texData + y * width * alignment), (const u16 *)(data + y * stride * alignment), width);
851 }
852 } else {
853 for (int y = 0; y < height; y++) {
854 memcpy(texData + y * width * alignment, data + y * stride * alignment, width * alignment);
855 }
856 }
857 }
858
859 render_->TextureImage(tex_, level, width, height, format_, texData);
860 }
861
862 #ifdef DEBUG_READ_PIXELS
863 // TODO: Make more generic.
LogReadPixelsError(GLenum error)864 static void LogReadPixelsError(GLenum error) {
865 switch (error) {
866 case GL_NO_ERROR:
867 break;
868 case GL_INVALID_ENUM:
869 ERROR_LOG(G3D, "glReadPixels: GL_INVALID_ENUM");
870 break;
871 case GL_INVALID_VALUE:
872 ERROR_LOG(G3D, "glReadPixels: GL_INVALID_VALUE");
873 break;
874 case GL_INVALID_OPERATION:
875 ERROR_LOG(G3D, "glReadPixels: GL_INVALID_OPERATION");
876 break;
877 case GL_INVALID_FRAMEBUFFER_OPERATION:
878 ERROR_LOG(G3D, "glReadPixels: GL_INVALID_FRAMEBUFFER_OPERATION");
879 break;
880 case GL_OUT_OF_MEMORY:
881 ERROR_LOG(G3D, "glReadPixels: GL_OUT_OF_MEMORY");
882 break;
883 #ifndef USING_GLES2
884 case GL_STACK_UNDERFLOW:
885 ERROR_LOG(G3D, "glReadPixels: GL_STACK_UNDERFLOW");
886 break;
887 case GL_STACK_OVERFLOW:
888 ERROR_LOG(G3D, "glReadPixels: GL_STACK_OVERFLOW");
889 break;
890 #endif
891 default:
892 ERROR_LOG(G3D, "glReadPixels: %08x", error);
893 break;
894 }
895 }
896 #endif
897
CopyFramebufferToMemorySync(Framebuffer * src,int channelBits,int x,int y,int w,int h,Draw::DataFormat dataFormat,void * pixels,int pixelStride,const char * tag)898 bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, const char *tag) {
899 if (gl_extensions.IsGLES && (channelBits & FB_COLOR_BIT) == 0) {
900 // Can't readback depth or stencil on GLES.
901 return false;
902 }
903 OpenGLFramebuffer *fb = (OpenGLFramebuffer *)src;
904 GLuint aspect = 0;
905 if (channelBits & FB_COLOR_BIT)
906 aspect |= GL_COLOR_BUFFER_BIT;
907 if (channelBits & FB_DEPTH_BIT)
908 aspect |= GL_DEPTH_BUFFER_BIT;
909 if (channelBits & FB_STENCIL_BIT)
910 aspect |= GL_STENCIL_BUFFER_BIT;
911 renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag);
912 return true;
913 }
914
915
CreateTexture(const TextureDesc & desc)916 Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) {
917 return new OpenGLTexture(&renderManager_, desc);
918 }
919
CreateDepthStencilState(const DepthStencilStateDesc & desc)920 DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
921 OpenGLDepthStencilState *ds = new OpenGLDepthStencilState();
922 ds->depthTestEnabled = desc.depthTestEnabled;
923 ds->depthWriteEnabled = desc.depthWriteEnabled;
924 ds->depthComp = compToGL[(int)desc.depthCompare];
925 ds->stencilEnabled = desc.stencilEnabled;
926 ds->stencilCompareOp = compToGL[(int)desc.front.compareOp];
927 ds->stencilPass = stencilOpToGL[(int)desc.front.passOp];
928 ds->stencilFail = stencilOpToGL[(int)desc.front.failOp];
929 ds->stencilZFail = stencilOpToGL[(int)desc.front.depthFailOp];
930 ds->stencilWriteMask = desc.front.writeMask;
931 ds->stencilCompareMask = desc.front.compareMask;
932 return ds;
933 }
934
CreateBlendState(const BlendStateDesc & desc)935 BlendState *OpenGLContext::CreateBlendState(const BlendStateDesc &desc) {
936 OpenGLBlendState *bs = new OpenGLBlendState();
937 bs->enabled = desc.enabled;
938 bs->eqCol = blendEqToGL[(int)desc.eqCol];
939 bs->srcCol = blendFactorToGL[(int)desc.srcCol];
940 bs->dstCol = blendFactorToGL[(int)desc.dstCol];
941 bs->eqAlpha = blendEqToGL[(int)desc.eqAlpha];
942 bs->srcAlpha = blendFactorToGL[(int)desc.srcAlpha];
943 bs->dstAlpha = blendFactorToGL[(int)desc.dstAlpha];
944 bs->colorMask = desc.colorMask;
945 return bs;
946 }
947
CreateSamplerState(const SamplerStateDesc & desc)948 SamplerState *OpenGLContext::CreateSamplerState(const SamplerStateDesc &desc) {
949 OpenGLSamplerState *samps = new OpenGLSamplerState();
950 samps->wrapU = texWrapToGL[(int)desc.wrapU];
951 samps->wrapV = texWrapToGL[(int)desc.wrapV];
952 samps->wrapW = texWrapToGL[(int)desc.wrapW];
953 samps->magFilt = texFilterToGL[(int)desc.magFilter];
954 samps->minFilt = texFilterToGL[(int)desc.minFilter];
955 samps->mipMinFilt = texMipFilterToGL[(int)desc.minFilter][(int)desc.mipFilter];
956 return samps;
957 }
958
CreateRasterState(const RasterStateDesc & desc)959 RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) {
960 OpenGLRasterState *rs = new OpenGLRasterState();
961 if (desc.cull == CullMode::NONE) {
962 rs->cullEnable = GL_FALSE;
963 return rs;
964 }
965 rs->cullEnable = GL_TRUE;
966 switch (desc.frontFace) {
967 case Facing::CW:
968 rs->frontFace = GL_CW;
969 break;
970 case Facing::CCW:
971 rs->frontFace = GL_CCW;
972 break;
973 }
974 switch (desc.cull) {
975 case CullMode::FRONT:
976 rs->cullMode = GL_FRONT;
977 break;
978 case CullMode::BACK:
979 rs->cullMode = GL_BACK;
980 break;
981 case CullMode::FRONT_AND_BACK:
982 rs->cullMode = GL_FRONT_AND_BACK;
983 break;
984 case CullMode::NONE:
985 // Unsupported
986 break;
987 }
988 return rs;
989 }
990
991 class OpenGLBuffer : public Buffer {
992 public:
OpenGLBuffer(GLRenderManager * render,size_t size,uint32_t flags)993 OpenGLBuffer(GLRenderManager *render, size_t size, uint32_t flags) : render_(render) {
994 target_ = (flags & BufferUsageFlag::INDEXDATA) ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
995 usage_ = 0;
996 if (flags & BufferUsageFlag::DYNAMIC)
997 usage_ = GL_STREAM_DRAW;
998 else
999 usage_ = GL_STATIC_DRAW;
1000 buffer_ = render->CreateBuffer(target_, size, usage_);
1001 totalSize_ = size;
1002 }
~OpenGLBuffer()1003 ~OpenGLBuffer() override {
1004 render_->DeleteBuffer(buffer_);
1005 }
1006
1007 GLRenderManager *render_;
1008 GLRBuffer *buffer_;
1009 GLuint target_;
1010 GLuint usage_;
1011
1012 size_t totalSize_;
1013 };
1014
CreateBuffer(size_t size,uint32_t usageFlags)1015 Buffer *OpenGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
1016 return new OpenGLBuffer(&renderManager_, size, usageFlags);
1017 }
1018
UpdateBuffer(Buffer * buffer,const uint8_t * data,size_t offset,size_t size,UpdateBufferFlags flags)1019 void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) {
1020 OpenGLBuffer *buf = (OpenGLBuffer *)buffer;
1021
1022 if (size + offset > buf->totalSize_) {
1023 Crash();
1024 }
1025
1026 uint8_t *dataCopy = new uint8_t[size];
1027 memcpy(dataCopy, data, size);
1028 // if (flags & UPDATE_DISCARD) we could try to orphan the buffer using glBufferData.
1029 // But we're much better off using separate buffers per FrameData...
1030 renderManager_.BufferSubdata(buf->buffer_, offset, size, dataCopy);
1031 }
1032
CreateGraphicsPipeline(const PipelineDesc & desc)1033 Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
1034 if (!desc.shaders.size()) {
1035 ERROR_LOG(G3D, "Pipeline requires at least one shader");
1036 return nullptr;
1037 }
1038 if ((uint32_t)desc.prim >= (uint32_t)Primitive::PRIMITIVE_TYPE_COUNT) {
1039 ERROR_LOG(G3D, "Invalid primitive type");
1040 return nullptr;
1041 }
1042 if (!desc.depthStencil || !desc.blend || !desc.raster) {
1043 ERROR_LOG(G3D, "Incomplete prim desciption");
1044 return nullptr;
1045 }
1046
1047 OpenGLPipeline *pipeline = new OpenGLPipeline(&renderManager_);
1048 for (auto iter : desc.shaders) {
1049 if (iter) {
1050 iter->AddRef();
1051 pipeline->shaders.push_back(static_cast<OpenGLShaderModule *>(iter));
1052 } else {
1053 ERROR_LOG(G3D, "ERROR: Tried to create graphics pipeline with a null shader module");
1054 delete pipeline;
1055 return nullptr;
1056 }
1057 }
1058 if (desc.uniformDesc) {
1059 pipeline->dynamicUniforms = *desc.uniformDesc;
1060 pipeline->dynamicUniformLocs_.resize(desc.uniformDesc->uniforms.size());
1061 }
1062 if (pipeline->LinkShaders()) {
1063 // Build the rest of the virtual pipeline object.
1064 pipeline->prim = primToGL[(int)desc.prim];
1065 pipeline->depthStencil = (OpenGLDepthStencilState *)desc.depthStencil;
1066 pipeline->blend = (OpenGLBlendState *)desc.blend;
1067 pipeline->raster = (OpenGLRasterState *)desc.raster;
1068 pipeline->inputLayout = (OpenGLInputLayout *)desc.inputLayout;
1069 return pipeline;
1070 } else {
1071 ERROR_LOG(G3D, "Failed to create pipeline - shaders failed to link");
1072 delete pipeline;
1073 return nullptr;
1074 }
1075 }
1076
BindTextures(int start,int count,Texture ** textures)1077 void OpenGLContext::BindTextures(int start, int count, Texture **textures) {
1078 _assert_(start + count <= MAX_TEXTURE_SLOTS);
1079 for (int i = start; i < start + count; i++) {
1080 OpenGLTexture *glTex = static_cast<OpenGLTexture *>(textures[i - start]);
1081 if (!glTex) {
1082 boundTextures_[i] = nullptr;
1083 renderManager_.BindTexture(i, nullptr);
1084 continue;
1085 }
1086 glTex->Bind(i);
1087 boundTextures_[i] = glTex->GetTex();
1088 }
1089 }
1090
ApplySamplers()1091 void OpenGLContext::ApplySamplers() {
1092 for (int i = 0; i < MAX_TEXTURE_SLOTS; i++) {
1093 const OpenGLSamplerState *samp = boundSamplers_[i];
1094 const GLRTexture *tex = boundTextures_[i];
1095 if (tex) {
1096 _assert_(samp);
1097 } else {
1098 continue;
1099 }
1100 GLenum wrapS;
1101 GLenum wrapT;
1102 if (tex->canWrap) {
1103 wrapS = samp->wrapU;
1104 wrapT = samp->wrapV;
1105 } else {
1106 wrapS = GL_CLAMP_TO_EDGE;
1107 wrapT = GL_CLAMP_TO_EDGE;
1108 }
1109 GLenum magFilt = samp->magFilt;
1110 GLenum minFilt = tex->numMips > 1 ? samp->mipMinFilt : samp->minFilt;
1111 renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f);
1112 renderManager_.SetTextureLod(i, 0.0, (float)(tex->numMips - 1), 0.0);
1113 }
1114 }
1115
CreateShaderModule(ShaderStage stage,ShaderLanguage language,const uint8_t * data,size_t dataSize,const std::string & tag)1116 ShaderModule *OpenGLContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag) {
1117 OpenGLShaderModule *shader = new OpenGLShaderModule(&renderManager_, stage, tag);
1118 if (shader->Compile(&renderManager_, language, data, dataSize)) {
1119 return shader;
1120 } else {
1121 shader->Release();
1122 return nullptr;
1123 }
1124 }
1125
LinkShaders()1126 bool OpenGLPipeline::LinkShaders() {
1127 std::vector<GLRShader *> linkShaders;
1128 for (auto shaderModule : shaders) {
1129 if (shaderModule) {
1130 GLRShader *shader = shaderModule->GetShader();
1131 if (shader) {
1132 linkShaders.push_back(shader);
1133 } else {
1134 ERROR_LOG(G3D, "LinkShaders: Bad shader module");
1135 return false;
1136 }
1137 } else {
1138 ERROR_LOG(G3D, "LinkShaders: Bad shader in module");
1139 return false;
1140 }
1141 }
1142
1143 std::vector<GLRProgram::Semantic> semantics;
1144 // Bind all the common vertex data points. Mismatching ones will be ignored.
1145 semantics.push_back({ SEM_POSITION, "Position" });
1146 semantics.push_back({ SEM_COLOR0, "Color0" });
1147 semantics.push_back({ SEM_TEXCOORD0, "TexCoord0" });
1148 semantics.push_back({ SEM_NORMAL, "Normal" });
1149 semantics.push_back({ SEM_TANGENT, "Tangent" });
1150 semantics.push_back({ SEM_BINORMAL, "Binormal" });
1151 // For postshaders.
1152 semantics.push_back({ SEM_POSITION, "a_position" });
1153 semantics.push_back({ SEM_TEXCOORD0, "a_texcoord0" });
1154 std::vector<GLRProgram::UniformLocQuery> queries;
1155 queries.push_back({ &samplerLocs_[0], "sampler0" });
1156 queries.push_back({ &samplerLocs_[1], "sampler1" });
1157 queries.push_back({ &samplerLocs_[2], "sampler2" });
1158 _assert_(queries.size() >= MAX_TEXTURE_SLOTS);
1159 for (size_t i = 0; i < dynamicUniforms.uniforms.size(); ++i) {
1160 queries.push_back({ &dynamicUniformLocs_[i], dynamicUniforms.uniforms[i].name });
1161 }
1162 std::vector<GLRProgram::Initializer> initialize;
1163 for (int i = 0; i < MAX_TEXTURE_SLOTS; ++i)
1164 initialize.push_back({ &samplerLocs_[i], 0, i });
1165 program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false);
1166 return true;
1167 }
1168
BindPipeline(Pipeline * pipeline)1169 void OpenGLContext::BindPipeline(Pipeline *pipeline) {
1170 curPipeline_ = (OpenGLPipeline *)pipeline;
1171 if (!curPipeline_) {
1172 return;
1173 }
1174 curPipeline_->blend->Apply(&renderManager_);
1175 curPipeline_->depthStencil->Apply(&renderManager_, stencilRef_);
1176 curPipeline_->raster->Apply(&renderManager_);
1177 renderManager_.BindProgram(curPipeline_->program_);
1178 }
1179
UpdateDynamicUniformBuffer(const void * ub,size_t size)1180 void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
1181 if (curPipeline_->dynamicUniforms.uniformBufferSize != size) {
1182 Crash();
1183 }
1184
1185 for (size_t i = 0; i < curPipeline_->dynamicUniforms.uniforms.size(); ++i) {
1186 const auto &uniform = curPipeline_->dynamicUniforms.uniforms[i];
1187 const GLint &loc = curPipeline_->dynamicUniformLocs_[i];
1188 const float *data = (const float *)((uint8_t *)ub + uniform.offset);
1189 switch (uniform.type) {
1190 case UniformType::FLOAT1:
1191 case UniformType::FLOAT2:
1192 case UniformType::FLOAT3:
1193 case UniformType::FLOAT4:
1194 renderManager_.SetUniformF(&loc, 1 + (int)uniform.type - (int)UniformType::FLOAT1, data);
1195 break;
1196 case UniformType::MATRIX4X4:
1197 renderManager_.SetUniformM4x4(&loc, data);
1198 break;
1199 }
1200 }
1201 }
1202
Draw(int vertexCount,int offset)1203 void OpenGLContext::Draw(int vertexCount, int offset) {
1204 _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call Draw without a vertex buffer");
1205 ApplySamplers();
1206 if (curPipeline_->inputLayout) {
1207 renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
1208 }
1209 renderManager_.Draw(curPipeline_->prim, offset, vertexCount);
1210 }
1211
DrawIndexed(int vertexCount,int offset)1212 void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
1213 _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call DrawIndexed without a vertex buffer");
1214 _dbg_assert_msg_(curIBuffer_ != nullptr, "Can't call DrawIndexed without an index buffer");
1215 ApplySamplers();
1216 if (curPipeline_->inputLayout) {
1217 renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
1218 }
1219 renderManager_.BindIndexBuffer(curIBuffer_->buffer_);
1220 renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t)));
1221 }
1222
DrawUP(const void * vdata,int vertexCount)1223 void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
1224 _assert_(curPipeline_->inputLayout != nullptr);
1225 int stride = curPipeline_->inputLayout->stride;
1226 size_t dataSize = stride * vertexCount;
1227
1228 FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
1229
1230 GLRBuffer *buf;
1231 size_t offset = frameData.push->Push(vdata, dataSize, &buf);
1232
1233 ApplySamplers();
1234 if (curPipeline_->inputLayout) {
1235 renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset);
1236 }
1237 renderManager_.Draw(curPipeline_->prim, 0, vertexCount);
1238 }
1239
Clear(int mask,uint32_t colorval,float depthVal,int stencilVal)1240 void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
1241 float col[4];
1242 Uint8x4ToFloat4(col, colorval);
1243 GLuint glMask = 0;
1244 if (mask & FBChannel::FB_COLOR_BIT) {
1245 glMask |= GL_COLOR_BUFFER_BIT;
1246 }
1247 if (mask & FBChannel::FB_DEPTH_BIT) {
1248 glMask |= GL_DEPTH_BUFFER_BIT;
1249 }
1250 if (mask & FBChannel::FB_STENCIL_BIT) {
1251 glMask |= GL_STENCIL_BUFFER_BIT;
1252 }
1253 renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_);
1254 }
1255
T3DCreateGLContext()1256 DrawContext *T3DCreateGLContext() {
1257 return new OpenGLContext();
1258 }
1259
~OpenGLInputLayout()1260 OpenGLInputLayout::~OpenGLInputLayout() {
1261 render_->DeleteInputLayout(inputLayout_);
1262 }
1263
Compile(const InputLayoutDesc & desc)1264 void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) {
1265 // TODO: This is only accurate if there's only one stream. But whatever, for now we
1266 // never use multiple streams anyway.
1267 stride = desc.bindings.empty() ? 0 : (GLsizei)desc.bindings[0].stride;
1268
1269 std::vector<GLRInputLayout::Entry> entries;
1270 for (auto &attr : desc.attributes) {
1271 GLRInputLayout::Entry entry;
1272 entry.location = attr.location;
1273 entry.stride = (GLsizei)desc.bindings[attr.binding].stride;
1274 entry.offset = attr.offset;
1275 switch (attr.format) {
1276 case DataFormat::R32G32_FLOAT:
1277 entry.count = 2;
1278 entry.type = GL_FLOAT;
1279 entry.normalized = GL_FALSE;
1280 break;
1281 case DataFormat::R32G32B32_FLOAT:
1282 entry.count = 3;
1283 entry.type = GL_FLOAT;
1284 entry.normalized = GL_FALSE;
1285 break;
1286 case DataFormat::R32G32B32A32_FLOAT:
1287 entry.count = 4;
1288 entry.type = GL_FLOAT;
1289 entry.normalized = GL_FALSE;
1290 break;
1291 case DataFormat::R8G8B8A8_UNORM:
1292 entry.count = 4;
1293 entry.type = GL_UNSIGNED_BYTE;
1294 entry.normalized = GL_TRUE;
1295 break;
1296 case DataFormat::UNDEFINED:
1297 default:
1298 ERROR_LOG(G3D, "Thin3DGLVertexFormat: Invalid or unknown component type applied.");
1299 break;
1300 }
1301
1302 entries.push_back(entry);
1303 }
1304 if (!entries.empty()) {
1305 inputLayout_ = render_->CreateInputLayout(entries);
1306 } else {
1307 inputLayout_ = nullptr;
1308 }
1309 }
1310
CreateFramebuffer(const FramebufferDesc & desc)1311 Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
1312 CheckGLExtensions();
1313
1314 GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil);
1315 OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer);
1316 return fbo;
1317 }
1318
BindFramebufferAsRenderTarget(Framebuffer * fbo,const RenderPassInfo & rp,const char * tag)1319 void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) {
1320 OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1321 GLRRenderPassAction color = (GLRRenderPassAction)rp.color;
1322 GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth;
1323 GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil;
1324
1325 renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer_ : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
1326 curRenderTarget_ = fb;
1327 }
1328
CopyFramebufferImage(Framebuffer * fbsrc,int srcLevel,int srcX,int srcY,int srcZ,Framebuffer * fbdst,int dstLevel,int dstX,int dstY,int dstZ,int width,int height,int depth,int channelBits,const char * tag)1329 void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) {
1330 OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
1331 OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
1332
1333 int aspect = 0;
1334 if (channelBits & FB_COLOR_BIT) {
1335 aspect |= GL_COLOR_BUFFER_BIT;
1336 } else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) {
1337 if (channelBits & FB_DEPTH_BIT)
1338 aspect |= GL_DEPTH_BUFFER_BIT;
1339 if (channelBits & FB_STENCIL_BIT)
1340 aspect |= GL_STENCIL_BUFFER_BIT;
1341 }
1342 renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, aspect, tag);
1343 }
1344
BlitFramebuffer(Framebuffer * fbsrc,int srcX1,int srcY1,int srcX2,int srcY2,Framebuffer * fbdst,int dstX1,int dstY1,int dstX2,int dstY2,int channels,FBBlitFilter linearFilter,const char * tag)1345 bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter, const char *tag) {
1346 OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
1347 OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
1348 GLuint aspect = 0;
1349 if (channels & FB_COLOR_BIT)
1350 aspect |= GL_COLOR_BUFFER_BIT;
1351 if (channels & FB_DEPTH_BIT)
1352 aspect |= GL_DEPTH_BUFFER_BIT;
1353 if (channels & FB_STENCIL_BIT)
1354 aspect |= GL_STENCIL_BUFFER_BIT;
1355
1356 renderManager_.BlitFramebuffer(src->framebuffer_, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer_, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag);
1357 return true;
1358 }
1359
BindFramebufferAsTexture(Framebuffer * fbo,int binding,FBChannel channelBit,int color)1360 void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) {
1361 OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1362 _assert_(binding < MAX_TEXTURE_SLOTS);
1363
1364 GLuint aspect = 0;
1365 if (channelBit & FB_COLOR_BIT) {
1366 aspect |= GL_COLOR_BUFFER_BIT;
1367 boundTextures_[binding] = &fb->framebuffer_->color_texture;
1368 }
1369 if (channelBit & FB_DEPTH_BIT) {
1370 aspect |= GL_DEPTH_BUFFER_BIT;
1371 boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
1372 }
1373 if (channelBit & FB_STENCIL_BIT) {
1374 aspect |= GL_STENCIL_BUFFER_BIT;
1375 boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
1376 }
1377 renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect, color);
1378 }
1379
GetFramebufferDimensions(Framebuffer * fbo,int * w,int * h)1380 void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
1381 OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1382 if (fb) {
1383 *w = fb->Width();
1384 *h = fb->Height();
1385 } else {
1386 *w = targetWidth_;
1387 *h = targetHeight_;
1388 }
1389 }
1390
GetDataFormatSupport(DataFormat fmt) const1391 uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const {
1392 switch (fmt) {
1393 case DataFormat::R4G4B4A4_UNORM_PACK16:
1394 case DataFormat::R5G6B5_UNORM_PACK16:
1395 case DataFormat::R5G5B5A1_UNORM_PACK16:
1396 return FMT_RENDERTARGET | FMT_TEXTURE | FMT_AUTOGEN_MIPS; // native support
1397
1398 case DataFormat::R8G8B8A8_UNORM:
1399 return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT | FMT_AUTOGEN_MIPS;
1400
1401 case DataFormat::A1R5G5B5_UNORM_PACK16:
1402 return FMT_TEXTURE; // we will emulate this! Very fast to convert from R5G5B5A1_UNORM_PACK16 during upload.
1403
1404 case DataFormat::R32_FLOAT:
1405 case DataFormat::R32G32_FLOAT:
1406 case DataFormat::R32G32B32_FLOAT:
1407 case DataFormat::R32G32B32A32_FLOAT:
1408 return FMT_INPUTLAYOUT;
1409
1410 case DataFormat::R8_UNORM:
1411 return 0;
1412 case DataFormat::BC1_RGBA_UNORM_BLOCK:
1413 case DataFormat::BC2_UNORM_BLOCK:
1414 case DataFormat::BC3_UNORM_BLOCK:
1415 return FMT_TEXTURE;
1416 default:
1417 return 0;
1418 }
1419 }
1420
1421 } // namespace Draw
1422