Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GPU/thin3d.h
3186 views
1
// Very thin API wrapper, suitable for porting UI code (like the native/ui framework) and similar but not real rendering.
2
// Does not involve context creation etc, that should be handled separately - only does drawing.
3
4
// The goals may change in the future though.
5
// MIT licensed, by Henrik RydgÄrd 2014.
6
7
#pragma once
8
9
#include <atomic>
10
#include <cstdint>
11
#include <cstddef>
12
#include <functional>
13
#include <string>
14
#include <vector>
15
16
#include "Common/Common.h"
17
#include "Common/GPU/DataFormat.h"
18
#include "Common/GPU/Shader.h"
19
#include "Common/GPU/MiscTypes.h"
20
#include "Common/Data/Collections/Slice.h"
21
#include "Common/Data/Collections/FastVec.h"
22
23
namespace Lin {
24
class Matrix4x4;
25
}
26
27
namespace Draw {
28
29
// Useful in UBOs
30
typedef int bool32;
31
32
enum class Comparison : uint8_t {
33
NEVER,
34
LESS,
35
EQUAL,
36
LESS_EQUAL,
37
GREATER,
38
NOT_EQUAL,
39
GREATER_EQUAL,
40
ALWAYS,
41
};
42
43
// Had to prefix with LOGIC, too many clashes
44
enum class LogicOp : uint8_t {
45
LOGIC_CLEAR,
46
LOGIC_SET,
47
LOGIC_COPY,
48
LOGIC_COPY_INVERTED,
49
LOGIC_NOOP,
50
LOGIC_INVERT,
51
LOGIC_AND,
52
LOGIC_NAND,
53
LOGIC_OR,
54
LOGIC_NOR,
55
LOGIC_XOR,
56
LOGIC_EQUIV,
57
LOGIC_AND_REVERSE,
58
LOGIC_AND_INVERTED,
59
LOGIC_OR_REVERSE,
60
LOGIC_OR_INVERTED,
61
};
62
63
enum class BlendOp : uint8_t {
64
ADD,
65
SUBTRACT,
66
REV_SUBTRACT,
67
MIN,
68
MAX,
69
};
70
71
enum class BlendFactor : uint8_t {
72
ZERO,
73
ONE,
74
SRC_COLOR,
75
ONE_MINUS_SRC_COLOR,
76
DST_COLOR,
77
ONE_MINUS_DST_COLOR,
78
SRC_ALPHA,
79
ONE_MINUS_SRC_ALPHA,
80
DST_ALPHA,
81
ONE_MINUS_DST_ALPHA,
82
CONSTANT_COLOR,
83
ONE_MINUS_CONSTANT_COLOR,
84
CONSTANT_ALPHA,
85
ONE_MINUS_CONSTANT_ALPHA,
86
SRC1_COLOR,
87
ONE_MINUS_SRC1_COLOR,
88
SRC1_ALPHA,
89
ONE_MINUS_SRC1_ALPHA,
90
};
91
92
enum class StencilOp : uint8_t {
93
KEEP = 0,
94
ZERO = 1,
95
REPLACE = 2,
96
INCREMENT_AND_CLAMP = 3,
97
DECREMENT_AND_CLAMP = 4,
98
INVERT = 5,
99
INCREMENT_AND_WRAP = 6,
100
DECREMENT_AND_WRAP = 7,
101
};
102
103
enum class TextureFilter : uint8_t {
104
NEAREST = 0,
105
LINEAR = 1,
106
};
107
108
enum BufferUsageFlag : int {
109
VERTEXDATA = 1,
110
INDEXDATA = 2,
111
GENERIC = 4,
112
UNIFORM = 8,
113
114
DYNAMIC = 16,
115
};
116
117
enum Semantic : int {
118
SEM_POSITION,
119
SEM_COLOR0,
120
SEM_COLOR1,
121
SEM_TEXCOORD0,
122
SEM_TEXCOORD1,
123
SEM_NORMAL,
124
SEM_TANGENT,
125
SEM_BINORMAL, // really BITANGENT
126
SEM_MAX,
127
};
128
129
enum class Primitive {
130
POINT_LIST,
131
LINE_LIST,
132
LINE_STRIP,
133
TRIANGLE_LIST,
134
TRIANGLE_STRIP,
135
TRIANGLE_FAN,
136
// Tesselation shader only
137
PATCH_LIST,
138
// These are for geometry shaders only.
139
LINE_LIST_ADJ,
140
LINE_STRIP_ADJ,
141
TRIANGLE_LIST_ADJ,
142
TRIANGLE_STRIP_ADJ,
143
144
UNDEFINED,
145
PRIMITIVE_TYPE_COUNT,
146
};
147
148
enum VertexShaderPreset : int {
149
VS_COLOR_2D,
150
VS_TEXTURE_COLOR_2D,
151
VS_MAX_PRESET,
152
};
153
154
enum FragmentShaderPreset : int {
155
FS_COLOR_2D,
156
FS_TEXTURE_COLOR_2D,
157
FS_TEXTURE_COLOR_2D_RB_SWIZZLE,
158
FS_MAX_PRESET,
159
};
160
161
enum class TextureType : uint8_t {
162
UNKNOWN,
163
LINEAR1D,
164
LINEAR2D,
165
LINEAR3D,
166
CUBE,
167
ARRAY1D,
168
ARRAY2D,
169
};
170
171
enum class CullMode : uint8_t {
172
NONE,
173
FRONT,
174
BACK,
175
FRONT_AND_BACK,
176
};
177
178
enum class Facing {
179
CCW,
180
CW,
181
};
182
183
enum BorderColor {
184
DONT_CARE,
185
TRANSPARENT_BLACK,
186
OPAQUE_BLACK,
187
OPAQUE_WHITE,
188
};
189
190
enum {
191
COLOR_MASK_R = 1,
192
COLOR_MASK_G = 2,
193
COLOR_MASK_B = 4,
194
COLOR_MASK_A = 8,
195
};
196
197
enum class TextureAddressMode {
198
REPEAT = 0,
199
REPEAT_MIRROR,
200
CLAMP_TO_EDGE,
201
CLAMP_TO_BORDER,
202
};
203
204
enum FormatSupport {
205
FMT_RENDERTARGET = 1,
206
FMT_TEXTURE = 2,
207
FMT_INPUTLAYOUT = 4,
208
FMT_DEPTHSTENCIL = 8,
209
FMT_AUTOGEN_MIPS = 16,
210
FMT_BLIT = 32,
211
FMT_STORAGE_IMAGE = 64,
212
};
213
214
enum class InfoField {
215
APINAME,
216
APIVERSION,
217
VENDORSTRING,
218
VENDOR,
219
SHADELANGVERSION,
220
DRIVER,
221
DEVICE_API_VERSION, // Vulkan-only
222
};
223
224
enum class GPUVendor {
225
VENDOR_UNKNOWN,
226
VENDOR_NVIDIA,
227
VENDOR_INTEL,
228
VENDOR_AMD,
229
VENDOR_ARM, // Mali
230
VENDOR_QUALCOMM,
231
VENDOR_IMGTEC, // PowerVR
232
VENDOR_BROADCOM, // Raspberry
233
VENDOR_VIVANTE,
234
VENDOR_APPLE,
235
VENDOR_MESA,
236
};
237
238
enum class NativeObject {
239
CONTEXT,
240
CONTEXT_EX,
241
DEVICE,
242
DEVICE_EX,
243
BACKBUFFER_COLOR_VIEW,
244
BACKBUFFER_DEPTH_VIEW,
245
BACKBUFFER_COLOR_TEX,
246
BACKBUFFER_DEPTH_TEX,
247
FEATURE_LEVEL,
248
INIT_COMMANDBUFFER,
249
BOUND_TEXTURE0_IMAGEVIEW, // Layer etc depends on how you bound it...
250
BOUND_TEXTURE1_IMAGEVIEW, // Layer etc depends on how you bound it...
251
BOUND_FRAMEBUFFER_COLOR_IMAGEVIEW_ALL_LAYERS,
252
BOUND_FRAMEBUFFER_COLOR_IMAGEVIEW_RT,
253
RENDER_MANAGER,
254
TEXTURE_VIEW,
255
NULL_IMAGEVIEW,
256
NULL_IMAGEVIEW_ARRAY,
257
THIN3D_PIPELINE_LAYOUT,
258
PUSH_POOL,
259
};
260
261
enum class Aspect {
262
NO_BIT = 0,
263
COLOR_BIT = 1,
264
DEPTH_BIT = 2,
265
STENCIL_BIT = 4,
266
267
// Implementation specific
268
VIEW_BIT = 64, // Used in conjunction with the others in D3D11 to get shader resource views through get_api_texture
269
FORMAT_BIT = 128, // Actually retrieves the native format instead. D3D11 only.
270
};
271
ENUM_CLASS_BITOPS(Aspect);
272
273
enum FBInvalidationStage {
274
FB_INVALIDATION_LOAD = 1,
275
FB_INVALIDATION_STORE = 2,
276
};
277
278
enum FBBlitFilter {
279
FB_BLIT_NEAREST = 0,
280
FB_BLIT_LINEAR = 1,
281
};
282
283
enum UpdateBufferFlags {
284
UPDATE_DISCARD = 1,
285
};
286
287
enum class Event {
288
// These happen on D3D resize. Only the backbuffer needs to be resized.
289
LOST_BACKBUFFER,
290
GOT_BACKBUFFER,
291
292
// These are a bit more serious...
293
LOST_DEVICE,
294
GOT_DEVICE,
295
296
RESIZED,
297
PRESENTED,
298
};
299
300
enum class ReadbackMode {
301
BLOCK,
302
OLD_DATA_OK, // Lets the backend return old results that won't need any waiting to get.
303
};
304
305
constexpr uint32_t MAX_TEXTURE_SLOTS = 3;
306
307
struct FramebufferDesc {
308
int width;
309
int height;
310
int depth;
311
int numLayers;
312
int multiSampleLevel; // 0 = 1xaa, 1 = 2xaa, and so on.
313
bool z_stencil;
314
const char *tag; // For graphics debuggers
315
};
316
317
// Binary compatible with D3D11 viewport.
318
struct Viewport {
319
float TopLeftX;
320
float TopLeftY;
321
float Width;
322
float Height;
323
float MinDepth;
324
float MaxDepth;
325
};
326
327
class Bugs {
328
public:
329
bool Has(uint32_t bug) const {
330
return (flags_ & (1 << bug)) != 0;
331
}
332
void Infest(uint32_t bug) {
333
flags_ |= (1 << bug);
334
}
335
uint32_t MaxBugIndex() const {
336
return (uint32_t)MAX_BUG;
337
}
338
static const char *GetBugName(uint32_t bug);
339
340
enum : uint32_t {
341
NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO = 0,
342
DUAL_SOURCE_BLENDING_BROKEN = 1,
343
ANY_MAP_BUFFER_RANGE_SLOW = 2,
344
PVR_GENMIPMAP_HEIGHT_GREATER = 3,
345
BROKEN_NAN_IN_CONDITIONAL = 4,
346
COLORWRITEMASK_BROKEN_WITH_DEPTHTEST = 5,
347
BROKEN_FLAT_IN_SHADER = 6,
348
EQUAL_WZ_CORRUPTS_DEPTH = 7,
349
RASPBERRY_SHADER_COMP_HANG = 8,
350
MALI_CONSTANT_LOAD_BUG = 9,
351
SUBPASS_FEEDBACK_BROKEN = 10,
352
GEOMETRY_SHADERS_SLOW_OR_BROKEN = 11,
353
ADRENO_RESOURCE_DEADLOCK = 12,
354
UNIFORM_INDEXING_BROKEN = 13, // not a properly diagnosed issue, a workaround attempt: #17386
355
PVR_BAD_16BIT_TEXFORMATS = 14,
356
NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI = 15,
357
MAX_BUG,
358
};
359
360
protected:
361
uint32_t flags_ = 0;
362
363
static_assert(sizeof(flags_) * 8 > MAX_BUG, "Ran out of space for bugs.");
364
};
365
366
class RefCountedObject {
367
public:
368
explicit RefCountedObject(const char *name) : name_(name) {
369
refcount_ = 1;
370
}
371
RefCountedObject(const RefCountedObject &other) = delete;
372
RefCountedObject& operator=(RefCountedObject const&) = delete;
373
virtual ~RefCountedObject();
374
375
void AddRef() { refcount_++; }
376
bool Release();
377
bool ReleaseAssertLast();
378
379
private:
380
std::atomic<int> refcount_;
381
const char * const name_;
382
};
383
384
template <typename T>
385
struct AutoRef {
386
AutoRef() {}
387
explicit AutoRef(T *p) {
388
ptr = p;
389
if (ptr)
390
ptr->AddRef();
391
}
392
AutoRef(const AutoRef<T> &p) {
393
*this = p.ptr;
394
}
395
~AutoRef() {
396
if (ptr)
397
ptr->Release();
398
}
399
400
T *operator =(T *p) {
401
if (ptr)
402
ptr->Release();
403
ptr = p;
404
if (ptr)
405
ptr->AddRef();
406
return ptr;
407
}
408
AutoRef<T> &operator =(const AutoRef<T> &p) {
409
*this = p.ptr;
410
return *this;
411
}
412
bool operator !=(const AutoRef<T> &p) const {
413
return ptr != p.ptr;
414
}
415
416
T *operator->() const {
417
return ptr;
418
}
419
operator T *() {
420
return ptr;
421
}
422
operator bool() const {
423
return ptr != nullptr;
424
}
425
426
// Takes over ownership over newItem, so we don't need to AddRef it, the number of owners didn't change.
427
void reset(T *newItem) {
428
if (ptr) {
429
ptr->Release();
430
}
431
ptr = newItem;
432
}
433
434
T *ptr = nullptr;
435
};
436
437
class BlendState : public RefCountedObject {
438
public:
439
BlendState() : RefCountedObject("BlendState") {}
440
};
441
442
class SamplerState : public RefCountedObject {
443
public:
444
SamplerState() : RefCountedObject("SamplerState") {}
445
};
446
447
class DepthStencilState : public RefCountedObject {
448
public:
449
DepthStencilState() : RefCountedObject("DepthStencilState") {}
450
};
451
452
class Framebuffer : public RefCountedObject {
453
public:
454
Framebuffer() : RefCountedObject("Framebuffer") {}
455
int Width() const { return width_; }
456
int Height() const { return height_; }
457
int Layers() const { return layers_; }
458
int MultiSampleLevel() const { return multiSampleLevel_; }
459
460
virtual void UpdateTag(const char *tag) {}
461
virtual const char *Tag() const { return "(no name)"; }
462
463
protected:
464
int width_ = -1, height_ = -1, layers_ = 1, multiSampleLevel_ = 0;
465
};
466
467
class Buffer : public RefCountedObject {
468
public:
469
Buffer() : RefCountedObject("Buffer") {}
470
};
471
472
class Texture : public RefCountedObject {
473
public:
474
Texture() : RefCountedObject("Texture") {}
475
int Width() const { return width_; }
476
int Height() const { return height_; }
477
int Depth() const { return depth_; }
478
DataFormat Format() const { return format_; }
479
int DataSize() const {
480
// Rough estimate, discounts padding etc.
481
return width_ * height_ * (int)DataFormatSizeInBytes(format_);
482
}
483
484
protected:
485
int width_ = -1, height_ = -1, depth_ = -1;
486
DataFormat format_ = DataFormat::UNDEFINED;
487
};
488
489
struct AttributeDesc {
490
int location; // corresponds to semantic
491
DataFormat format;
492
int offset;
493
};
494
495
struct InputLayoutDesc {
496
int stride;
497
std::vector<AttributeDesc> attributes;
498
};
499
500
class InputLayout : public RefCountedObject {
501
public:
502
InputLayout() : RefCountedObject("InputLayout") {}
503
};
504
505
// Uniform types have moved to Shader.h.
506
507
class ShaderModule : public RefCountedObject {
508
public:
509
ShaderModule() : RefCountedObject("ShaderModule") {}
510
virtual ShaderStage GetStage() const = 0;
511
};
512
513
class Pipeline : public RefCountedObject {
514
public:
515
Pipeline() : RefCountedObject("Pipeline") {}
516
};
517
518
class RasterState : public RefCountedObject {
519
public:
520
RasterState() : RefCountedObject("RasterState") {}
521
};
522
523
struct StencilSetup {
524
StencilOp failOp;
525
StencilOp passOp;
526
StencilOp depthFailOp;
527
Comparison compareOp;
528
};
529
530
struct DepthStencilStateDesc {
531
bool depthTestEnabled;
532
bool depthWriteEnabled;
533
Comparison depthCompare;
534
bool stencilEnabled;
535
StencilSetup stencil;
536
};
537
538
struct BlendStateDesc {
539
bool enabled;
540
int colorMask;
541
BlendFactor srcCol;
542
BlendFactor dstCol;
543
BlendOp eqCol;
544
BlendFactor srcAlpha;
545
BlendFactor dstAlpha;
546
BlendOp eqAlpha;
547
bool logicEnabled;
548
LogicOp logicOp;
549
};
550
551
struct SamplerStateDesc {
552
TextureFilter magFilter;
553
TextureFilter minFilter;
554
TextureFilter mipFilter;
555
float maxAniso;
556
TextureAddressMode wrapU;
557
TextureAddressMode wrapV;
558
TextureAddressMode wrapW;
559
bool shadowCompareEnabled;
560
Comparison shadowCompareFunc;
561
BorderColor borderColor;
562
};
563
564
struct RasterStateDesc {
565
CullMode cull;
566
Facing frontFace;
567
};
568
569
struct PipelineDesc {
570
Primitive prim;
571
std::vector<ShaderModule *> shaders;
572
InputLayout *inputLayout;
573
DepthStencilState *depthStencil;
574
BlendState *blend;
575
RasterState *raster;
576
const UniformBufferDesc *uniformDesc;
577
const Slice<SamplerDef> samplers;
578
};
579
580
enum class PresentMode {
581
FIFO = 1,
582
IMMEDIATE = 2,
583
MAILBOX = 4,
584
};
585
ENUM_CLASS_BITOPS(PresentMode);
586
587
struct DeviceCaps {
588
GPUVendor vendor;
589
uint32_t deviceID; // use caution!
590
591
CoordConvention coordConvention;
592
DataFormat preferredDepthBufferFormat;
593
DataFormat preferredShadowMapFormatLow;
594
DataFormat preferredShadowMapFormatHigh;
595
bool anisoSupported;
596
bool depthRangeMinusOneToOne; // OpenGL style depth
597
bool geometryShaderSupported;
598
bool tesselationShaderSupported;
599
bool dualSourceBlend;
600
bool logicOpSupported;
601
bool depthClampSupported;
602
bool clipDistanceSupported;
603
bool cullDistanceSupported;
604
bool framebufferCopySupported;
605
bool framebufferBlitSupported;
606
bool framebufferDepthCopySupported;
607
bool framebufferSeparateDepthCopySupported;
608
bool framebufferDepthBlitSupported;
609
bool framebufferStencilBlitSupported;
610
bool framebufferFetchSupported;
611
bool texture3DSupported;
612
bool fragmentShaderInt32Supported;
613
bool textureNPOTFullySupported;
614
bool fragmentShaderDepthWriteSupported;
615
bool fragmentShaderStencilWriteSupported;
616
bool textureDepthSupported;
617
bool blendMinMaxSupported;
618
bool multiViewSupported;
619
bool isTilingGPU; // This means that it benefits from correct store-ops, msaa without backing memory, etc.
620
bool sampleRateShadingSupported;
621
bool setMaxFrameLatencySupported;
622
bool textureSwizzleSupported;
623
bool requiresHalfPixelOffset;
624
bool provokingVertexLast; // GL behavior, what the PSP does
625
bool verySlowShaderCompiler;
626
627
// Old style, for older GL or Direct3D 9.
628
u32 clipPlanesSupported;
629
630
// Presentation caps
631
int presentMaxInterval; // 1 on many backends
632
bool presentInstantModeChange;
633
PresentMode presentModesSupported;
634
635
u32 multiSampleLevelsMask; // Bit n is set if (1 << n) is a valid multisample level. Bit 0 is always set.
636
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
637
};
638
639
// Use to write data directly to texture memory. initData is the pointer passed in TextureDesc.
640
// Important: only write to the provided pointer, don't read from it.
641
typedef std::function<bool(uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride)> TextureCallback;
642
643
enum class TextureSwizzle {
644
DEFAULT,
645
R8_AS_ALPHA,
646
R8_AS_GRAYSCALE,
647
};
648
649
struct TextureDesc {
650
TextureType type;
651
DataFormat format;
652
653
int width;
654
int height;
655
int depth;
656
int mipLevels;
657
bool generateMips;
658
TextureSwizzle swizzle;
659
// Optional, for tracking memory usage and graphcis debuggers.
660
const char *tag;
661
// Does not take ownership over pointed-to data.
662
std::vector<const uint8_t *> initData;
663
TextureCallback initDataCallback;
664
};
665
666
enum class RPAction {
667
KEEP = 0,
668
CLEAR = 1,
669
DONT_CARE = 2,
670
};
671
672
struct RenderPassInfo {
673
RPAction color;
674
RPAction depth;
675
RPAction stencil;
676
uint32_t clearColor;
677
float clearDepth;
678
uint8_t clearStencil;
679
const char *tag;
680
};
681
682
const int ALL_LAYERS = -1;
683
684
enum class TextureBindFlags {
685
NONE = 0,
686
VULKAN_BIND_ARRAY = 1,
687
};
688
ENUM_CLASS_BITOPS(TextureBindFlags);
689
690
enum class DebugFlags {
691
NONE = 0,
692
PROFILE_TIMESTAMPS = 1,
693
PROFILE_SCOPES = 2,
694
};
695
ENUM_CLASS_BITOPS(DebugFlags);
696
697
struct BackendState {
698
u32 passes;
699
bool valid;
700
};
701
702
struct ClippedDraw {
703
int indexOffset;
704
int indexCount;
705
s16 clipx;
706
s16 clipy;
707
s16 clipw;
708
s16 cliph;
709
Draw::Texture *bindTexture;
710
Draw::Framebuffer *bindFramebufferAsTex;
711
void *bindNativeTexture;
712
Draw::SamplerState *samplerState;
713
Draw::Pipeline *pipeline;
714
Draw::Aspect aspect;
715
};
716
717
class DrawContext {
718
public:
719
virtual ~DrawContext() = default;
720
bool CreatePresets();
721
void DestroyPresets();
722
723
Bugs GetBugs() const { return bugs_; }
724
725
virtual void Wait() {}
726
727
virtual const DeviceCaps &GetDeviceCaps() const = 0;
728
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
729
virtual std::vector<std::string> GetFeatureList() const { return std::vector<std::string>(); }
730
virtual std::vector<std::string> GetExtensionList(bool device, bool enabledOnly) const { return std::vector<std::string>(); }
731
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
732
virtual std::vector<std::string> GetPresentModeList(std::string_view currentMarkerString) const { return std::vector<std::string>(); }
733
virtual std::vector<std::string> GetSurfaceFormatList() const { return std::vector<std::string>(); }
734
735
virtual BackendState GetCurrentBackendState() const {
736
return BackendState{};
737
}
738
739
// Describes the primary shader language that this implementation prefers.
740
const ShaderLanguageDesc &GetShaderLanguageDesc() {
741
return shaderLanguageDesc_;
742
}
743
744
virtual uint32_t GetSupportedShaderLanguages() const = 0;
745
746
virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {}
747
748
virtual void DebugAnnotate(const char *annotation) {}
749
750
// Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly).
751
// TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits.
752
virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0;
753
virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0;
754
virtual SamplerState *CreateSamplerState(const SamplerStateDesc &desc) = 0;
755
virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0;
756
virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0;
757
virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const char *tag = "thin3d") = 0;
758
virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc, const char *tag) = 0;
759
760
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
761
ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return vsPresets_[preset]; }
762
ShaderModule *GetFshaderPreset(FragmentShaderPreset preset) { return fsPresets_[preset]; }
763
764
// Resources
765
virtual Buffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
766
// Does not take ownership over pointed-to initData. After this returns, can dispose of it.
767
virtual Texture *CreateTexture(const TextureDesc &desc) = 0;
768
// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one.
769
virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0;
770
771
// Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it.
772
virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0;
773
774
// Used to optimize DrawPixels by re-using previously allocated temp textures.
775
// Do not try to update a texture that might be used by an in-flight command buffer! In OpenGL and D3D, this will cause stalls
776
// while in Vulkan this might cause various strangeness like image corruption.
777
virtual void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) = 0;
778
779
virtual 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, Aspect aspects, const char *tag) = 0;
780
virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) = 0;
781
782
// If the backend doesn't support old data, it's "OK" to block.
783
virtual bool CopyFramebufferToMemory(Framebuffer *src, Aspect aspect, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
784
return false;
785
}
786
virtual DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) {
787
return DataFormat::R8G8B8A8_UNORM;
788
}
789
790
// These functions should be self explanatory.
791
// Binding a zero render target means binding the backbuffer.
792
// If an fbo has two layers, we bind for stereo rendering ALWAYS. There's no rendering to one layer anymore.
793
virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) = 0;
794
795
// binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2).
796
virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect aspect, int layer) = 0;
797
798
// Framebuffer fetch / input attachment support, needs to be explicit in Vulkan.
799
virtual void BindCurrentFramebufferForColorInput() {}
800
801
virtual void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) = 0;
802
803
// Could be useful in OpenGL ES to give hints about framebuffers on tiler GPUs
804
// using glInvalidateFramebuffer, although drivers are known to botch that so we currently don't use it.
805
// In Vulkan, this sets the LOAD_OP or the STORE_OP (depending on stage) of the current render pass instance to DONT_CARE.
806
// channels is a bitwise combination of Aspect::COLOR, DEPTH and STENCIL.
807
virtual void InvalidateFramebuffer(FBInvalidationStage stage, Aspect aspects) {}
808
809
// Dynamic state
810
virtual void SetScissorRect(int left, int top, int width, int height) = 0;
811
virtual void SetViewport(const Viewport &viewport) = 0;
812
virtual void SetBlendFactor(float color[4]) = 0;
813
virtual void SetStencilParams(uint8_t refValue, uint8_t writeMask, uint8_t compareMask) = 0;
814
815
virtual void BindSamplerStates(int start, int count, SamplerState **state) = 0;
816
virtual void BindTextures(int start, int count, Texture **textures, TextureBindFlags flags = TextureBindFlags::NONE) = 0;
817
virtual void BindVertexBuffer(Buffer *vertexBuffer, int offset) = 0;
818
virtual void BindIndexBuffer(Buffer *indexBuffer, int offset) = 0;
819
820
// Sometimes it's necessary to bind a texture not created by thin3d, and use with a thin3d pipeline.
821
// Not pretty, and one way in the future could be to create all textures through thin3d.
822
// Data types:
823
// * Vulkan: VkImageView
824
// * D3D11: ID3D11ShaderResourceView*
825
// * OpenGL: GLRTexture
826
virtual void BindNativeTexture(int sampler, void *nativeTexture) = 0;
827
828
// Only supports a single dynamic uniform buffer, for maximum compatibility with the old APIs and ease of emulation.
829
// More modern methods will be added later.
830
virtual void UpdateDynamicUniformBuffer(const void *ub, size_t size) = 0;
831
832
void BindTexture(int stage, Texture *texture) {
833
Texture *textures[1] = { texture };
834
BindTextures(stage, 1, textures);
835
} // from sampler 0 and upwards
836
837
// Clear state cached within thin3d. Must be called after directly calling API functions.
838
// Note that framebuffer state (which framebuffer is bounds) may not be cached.
839
// Must not actually perform any API calls itself since this can be called when no framebuffer is bound for rendering.
840
virtual void Invalidate(InvalidationFlags flags) = 0;
841
842
virtual void BindPipeline(Pipeline *pipeline) = 0;
843
844
virtual void Draw(int vertexCount, int offset) = 0;
845
virtual void DrawIndexed(int vertexCount, int offset) = 0; // Always 16-bit indices.
846
virtual void DrawUP(const void *vdata, int vertexCount) = 0;
847
virtual void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount) = 0;
848
// Intended for ImGui display lists, easier to do optimally this way.
849
virtual void DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, const void *idata, int indexCount, Slice<ClippedDraw> draws, const void *dynUniforms, size_t size) = 0;
850
851
// Frame management (for the purposes of sync and resource management, necessary with modern APIs). Default implementations here.
852
virtual void BeginFrame(DebugFlags debugFlags) = 0;
853
virtual void EndFrame() = 0;
854
855
// vblanks is only relevant in FIFO present mode.
856
// NOTE: Not all backends support vblanks > 1. Some backends also can't change presentation mode immediately.
857
virtual void Present(PresentMode presentMode, int vblanks) = 0;
858
859
// This should be avoided as much as possible, in favor of clearing when binding a render target, which is native
860
// on Vulkan.
861
virtual void Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) = 0;
862
863
// Necessary to correctly flip scissor rectangles etc for OpenGL.
864
virtual void SetTargetSize(int w, int h) {
865
targetWidth_ = w;
866
targetHeight_ = h;
867
}
868
869
// In Vulkan, when changing things like MSAA mode, we can't have draw commands in flight (since we only support one at a time).
870
virtual void StopThreads() {}
871
virtual void StartThreads() {}
872
873
virtual std::string GetInfoString(InfoField info) const = 0;
874
virtual uint64_t GetNativeObject(NativeObject obj, void *srcObject = nullptr) = 0; // Most uses don't need an srcObject.
875
876
virtual void HandleEvent(Event ev, int width, int height, void *param1 = nullptr, void *param2 = nullptr) = 0;
877
878
// Flush state like scissors etc so the caller can do its own custom drawing.
879
virtual void FlushState() {}
880
881
// This is called when we launch a new game, so any collected internal stats in the backends don't carry over.
882
virtual void ResetStats() {}
883
884
// Used by the DrawEngines to know when they have to re-apply some state.
885
// Not very elegant, but more elegant than the old passId hack.
886
virtual void SetInvalidationCallback(InvalidationCallback callback) = 0;
887
888
// Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.numFlips
889
virtual int GetFrameCount() = 0;
890
891
virtual std::string GetGpuProfileString() const {
892
return "";
893
}
894
895
const HistoryBuffer<FrameTimeData, FRAME_TIME_HISTORY_LENGTH> &FrameTimeHistory() const {
896
return frameTimeHistory_;
897
}
898
899
protected:
900
HistoryBuffer<FrameTimeData, FRAME_TIME_HISTORY_LENGTH> frameTimeHistory_;
901
902
ShaderModule *vsPresets_[VS_MAX_PRESET];
903
ShaderModule *fsPresets_[FS_MAX_PRESET];
904
905
ShaderLanguageDesc shaderLanguageDesc_;
906
907
int targetWidth_;
908
int targetHeight_;
909
910
Bugs bugs_;
911
};
912
913
extern const UniformBufferDesc UBPresetDesc;
914
915
// UBs for the preset shaders
916
917
struct VsTexColUB {
918
float WorldViewProj[16];
919
float tint;
920
float saturation;
921
float pad[2];
922
};
923
extern const UniformBufferDesc vsTexColBufDesc;
924
struct VsColUB {
925
float WorldViewProj[16];
926
float tint;
927
float saturation;
928
float pad[2];
929
};
930
extern const UniformBufferDesc vsColBufDesc;
931
932
// Useful utility for specifying a shader in multiple languages.
933
934
struct ShaderSource {
935
ShaderLanguage lang;
936
const char *src;
937
};
938
939
ShaderModule *CreateShader(DrawContext *draw, ShaderStage stage, const std::vector<ShaderSource> &sources);
940
941
const char *PresentModeToString(PresentMode presentMode);
942
943
} // namespace Draw
944
945