Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GPU/thin3d.h
5683 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
EMPTY_RENDERPASS_BROKEN_MALI = 16,
358
MAX_BUG,
359
};
360
361
protected:
362
uint32_t flags_ = 0;
363
364
static_assert(sizeof(flags_) * 8 > MAX_BUG, "Ran out of space for bugs.");
365
};
366
367
class RefCountedObject {
368
public:
369
explicit RefCountedObject(const char *name) : name_(name) {
370
refcount_ = 1;
371
}
372
RefCountedObject(const RefCountedObject &other) = delete;
373
RefCountedObject& operator=(RefCountedObject const&) = delete;
374
virtual ~RefCountedObject();
375
376
void AddRef() { refcount_++; }
377
bool Release();
378
bool ReleaseAssertLast();
379
380
private:
381
std::atomic<int> refcount_;
382
const char * const name_;
383
};
384
385
template <typename T>
386
struct AutoRef {
387
AutoRef() {}
388
explicit AutoRef(T *p) {
389
ptr = p;
390
if (ptr)
391
ptr->AddRef();
392
}
393
AutoRef(const AutoRef<T> &p) {
394
*this = p.ptr;
395
}
396
~AutoRef() {
397
if (ptr)
398
ptr->Release();
399
}
400
401
T *operator =(T *p) {
402
if (ptr)
403
ptr->Release();
404
ptr = p;
405
if (ptr)
406
ptr->AddRef();
407
return ptr;
408
}
409
AutoRef<T> &operator =(const AutoRef<T> &p) {
410
*this = p.ptr;
411
return *this;
412
}
413
bool operator !=(const AutoRef<T> &p) const {
414
return ptr != p.ptr;
415
}
416
417
T *operator->() const {
418
return ptr;
419
}
420
operator T *() {
421
return ptr;
422
}
423
operator bool() const {
424
return ptr != nullptr;
425
}
426
427
// Takes over ownership over newItem, so we don't need to AddRef it, the number of owners didn't change.
428
void reset(T *newItem) {
429
if (ptr) {
430
ptr->Release();
431
}
432
ptr = newItem;
433
}
434
435
T *ptr = nullptr;
436
};
437
438
class BlendState : public RefCountedObject {
439
public:
440
BlendState() : RefCountedObject("BlendState") {}
441
};
442
443
class SamplerState : public RefCountedObject {
444
public:
445
SamplerState() : RefCountedObject("SamplerState") {}
446
};
447
448
class DepthStencilState : public RefCountedObject {
449
public:
450
DepthStencilState() : RefCountedObject("DepthStencilState") {}
451
};
452
453
class Framebuffer : public RefCountedObject {
454
public:
455
Framebuffer() : RefCountedObject("Framebuffer") {}
456
int Width() const { return width_; }
457
int Height() const { return height_; }
458
int Layers() const { return layers_; }
459
int MultiSampleLevel() const { return multiSampleLevel_; }
460
461
virtual void UpdateTag(const char *tag) {}
462
virtual const char *Tag() const { return "(no name)"; }
463
464
protected:
465
int width_ = -1, height_ = -1, layers_ = 1, multiSampleLevel_ = 0;
466
};
467
468
class Buffer : public RefCountedObject {
469
public:
470
Buffer() : RefCountedObject("Buffer") {}
471
};
472
473
class Texture : public RefCountedObject {
474
public:
475
Texture() : RefCountedObject("Texture") {}
476
int Width() const { return width_; }
477
int Height() const { return height_; }
478
int Depth() const { return depth_; }
479
DataFormat Format() const { return format_; }
480
int DataSize() const {
481
// Rough estimate, discounts padding etc.
482
return width_ * height_ * (int)DataFormatSizeInBytes(format_);
483
}
484
485
protected:
486
int width_ = -1, height_ = -1, depth_ = -1;
487
DataFormat format_ = DataFormat::UNDEFINED;
488
};
489
490
struct AttributeDesc {
491
int location; // corresponds to semantic
492
DataFormat format;
493
int offset;
494
};
495
496
struct InputLayoutDesc {
497
int stride;
498
std::vector<AttributeDesc> attributes;
499
};
500
501
class InputLayout : public RefCountedObject {
502
public:
503
InputLayout() : RefCountedObject("InputLayout") {}
504
};
505
506
// Uniform types have moved to Shader.h.
507
508
class ShaderModule : public RefCountedObject {
509
public:
510
ShaderModule() : RefCountedObject("ShaderModule") {}
511
virtual ShaderStage GetStage() const = 0;
512
};
513
514
class Pipeline : public RefCountedObject {
515
public:
516
Pipeline() : RefCountedObject("Pipeline") {}
517
};
518
519
class RasterState : public RefCountedObject {
520
public:
521
RasterState() : RefCountedObject("RasterState") {}
522
};
523
524
struct StencilSetup {
525
StencilOp failOp;
526
StencilOp passOp;
527
StencilOp depthFailOp;
528
Comparison compareOp;
529
};
530
531
struct DepthStencilStateDesc {
532
bool depthTestEnabled;
533
bool depthWriteEnabled;
534
Comparison depthCompare;
535
bool stencilEnabled;
536
StencilSetup stencil;
537
};
538
539
struct BlendStateDesc {
540
bool enabled;
541
int colorMask;
542
BlendFactor srcCol;
543
BlendFactor dstCol;
544
BlendOp eqCol;
545
BlendFactor srcAlpha;
546
BlendFactor dstAlpha;
547
BlendOp eqAlpha;
548
bool logicEnabled;
549
LogicOp logicOp;
550
};
551
552
struct SamplerStateDesc {
553
TextureFilter magFilter;
554
TextureFilter minFilter;
555
TextureFilter mipFilter;
556
float maxAniso;
557
TextureAddressMode wrapU;
558
TextureAddressMode wrapV;
559
TextureAddressMode wrapW;
560
bool shadowCompareEnabled;
561
Comparison shadowCompareFunc;
562
BorderColor borderColor;
563
};
564
565
struct RasterStateDesc {
566
CullMode cull;
567
Facing frontFace;
568
};
569
570
struct PipelineDesc {
571
Primitive prim;
572
std::vector<ShaderModule *> shaders;
573
InputLayout *inputLayout;
574
DepthStencilState *depthStencil;
575
BlendState *blend;
576
RasterState *raster;
577
const UniformBufferDesc *uniformDesc;
578
const Slice<SamplerDef> samplers;
579
};
580
581
// Not normally used as a bitfield, but useful as a capability flag.
582
enum class PresentMode {
583
FIFO = 1,
584
IMMEDIATE = 2,
585
MAILBOX = 4,
586
};
587
ENUM_CLASS_BITOPS(PresentMode);
588
589
inline bool PresentationModeBlocks(PresentMode mode) {
590
return mode & PresentMode::FIFO;
591
}
592
593
struct DeviceCaps {
594
GPUVendor vendor;
595
uint32_t deviceID; // use caution!
596
597
uint32_t maxTextureSize; // largest side.
598
uint32_t maxClipPlanes;
599
600
CoordConvention coordConvention;
601
DataFormat preferredDepthBufferFormat;
602
DataFormat preferredShadowMapFormatLow;
603
DataFormat preferredShadowMapFormatHigh;
604
bool anisoSupported;
605
bool depthRangeMinusOneToOne; // OpenGL style depth
606
bool geometryShaderSupported;
607
bool tesselationShaderSupported;
608
bool dualSourceBlend;
609
bool logicOpSupported;
610
bool depthClampSupported;
611
bool clipDistanceSupported;
612
bool cullDistanceSupported;
613
bool framebufferCopySupported;
614
bool framebufferBlitSupported;
615
bool framebufferDepthCopySupported;
616
bool framebufferSeparateDepthCopySupported;
617
bool framebufferDepthBlitSupported;
618
bool framebufferStencilBlitSupported;
619
bool framebufferFetchSupported;
620
bool texture3DSupported;
621
bool fragmentShaderInt32Supported;
622
bool textureNPOTFullySupported;
623
bool fragmentShaderDepthWriteSupported;
624
bool fragmentShaderStencilWriteSupported;
625
bool textureDepthSupported;
626
bool blendMinMaxSupported;
627
bool multiViewSupported;
628
bool isTilingGPU; // This means that it benefits from correct store-ops, msaa without backing memory, etc.
629
bool sampleRateShadingSupported;
630
bool setMaxFrameLatencySupported;
631
bool textureSwizzleSupported;
632
bool requiresHalfPixelOffset;
633
bool provokingVertexLast; // GL behavior, what the PSP does
634
bool verySlowShaderCompiler;
635
636
// Old style, for older GL or Direct3D 9.
637
u32 clipPlanesSupported;
638
639
// Presentation caps (simplified). Note: Vulkan supports more, we handle that separately now.
640
int presentMaxInterval; // 1 on many backends
641
bool presentInstantModeChange;
642
PresentMode presentModesSupported;
643
644
u32 multiSampleLevelsMask; // Bit n is set if (1 << n) is a valid multisample level. Bit 0 is always set.
645
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
646
};
647
648
// Use to write data directly to texture memory. initData is the pointer passed in TextureDesc.
649
// Important: only write to the provided pointer, don't read from it.
650
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;
651
652
enum class TextureSwizzle {
653
DEFAULT,
654
R8_AS_ALPHA,
655
R8_AS_GRAYSCALE,
656
R8_AS_PREMUL_ALPHA,
657
};
658
659
struct TextureDesc {
660
TextureType type;
661
DataFormat format;
662
663
int width;
664
int height;
665
int depth;
666
int mipLevels;
667
bool generateMips;
668
TextureSwizzle swizzle;
669
// Optional, for tracking memory usage and graphcis debuggers.
670
const char *tag;
671
// Does not take ownership over pointed-to data.
672
std::vector<const uint8_t *> initData;
673
TextureCallback initDataCallback;
674
};
675
676
enum class RPAction {
677
KEEP = 0,
678
CLEAR = 1,
679
DONT_CARE = 2,
680
};
681
682
struct RenderPassInfo {
683
RPAction color;
684
RPAction depth;
685
RPAction stencil;
686
uint32_t clearColor;
687
float clearDepth;
688
uint8_t clearStencil;
689
const char *tag;
690
};
691
692
const int ALL_LAYERS = -1;
693
694
enum class TextureBindFlags {
695
NONE = 0,
696
VULKAN_BIND_ARRAY = 1,
697
};
698
ENUM_CLASS_BITOPS(TextureBindFlags);
699
700
enum class DebugFlags {
701
NONE = 0,
702
PROFILE_TIMESTAMPS = 1,
703
PROFILE_SCOPES = 2,
704
};
705
ENUM_CLASS_BITOPS(DebugFlags);
706
707
struct BackendState {
708
u32 passes;
709
bool valid;
710
};
711
712
struct ClippedDraw {
713
int indexOffset;
714
int indexCount;
715
s16 clipx;
716
s16 clipy;
717
s16 clipw;
718
s16 cliph;
719
Draw::Texture *bindTexture;
720
Draw::Framebuffer *bindFramebufferAsTex;
721
void *bindNativeTexture;
722
Draw::SamplerState *samplerState;
723
Draw::Pipeline *pipeline;
724
Draw::Aspect aspect;
725
};
726
727
class DrawContext {
728
public:
729
virtual ~DrawContext() = default;
730
bool CreatePresets();
731
void DestroyPresets();
732
733
Bugs GetBugs() const { return bugs_; }
734
735
virtual void Wait() {}
736
737
virtual const DeviceCaps &GetDeviceCaps() const = 0;
738
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
739
virtual std::vector<std::string> GetFeatureList() const { return std::vector<std::string>(); }
740
virtual std::vector<std::string> GetExtensionList(bool device, bool enabledOnly) const { return std::vector<std::string>(); }
741
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
742
virtual std::vector<std::string> GetPresentModeList(std::string_view currentMarkerString) const { return std::vector<std::string>(); }
743
virtual std::vector<std::string> GetSurfaceFormatList() const { return std::vector<std::string>(); }
744
745
virtual BackendState GetCurrentBackendState() const {
746
return BackendState{};
747
}
748
749
// Describes the primary shader language that this implementation prefers.
750
const ShaderLanguageDesc &GetShaderLanguageDesc() {
751
return shaderLanguageDesc_;
752
}
753
754
virtual uint32_t GetSupportedShaderLanguages() const = 0;
755
756
virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {}
757
758
virtual void DebugAnnotate(const char *annotation) {}
759
760
// Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly).
761
// TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits.
762
virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0;
763
virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0;
764
virtual SamplerState *CreateSamplerState(const SamplerStateDesc &desc) = 0;
765
virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0;
766
virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0;
767
virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const char *tag = "thin3d") = 0;
768
virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc, const char *tag) = 0;
769
770
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
771
ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return vsPresets_[preset]; }
772
ShaderModule *GetFshaderPreset(FragmentShaderPreset preset) { return fsPresets_[preset]; }
773
774
// Resources
775
virtual Buffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
776
// Does not take ownership over pointed-to initData. After this returns, can dispose of it.
777
virtual Texture *CreateTexture(const TextureDesc &desc) = 0;
778
// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one.
779
virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0;
780
781
// 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.
782
virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0;
783
784
// Used to optimize DrawPixels by re-using previously allocated temp textures.
785
// 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
786
// while in Vulkan this might cause various strangeness like image corruption.
787
virtual void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) = 0;
788
789
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;
790
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;
791
792
// If the backend doesn't support old data, it's "OK" to block.
793
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) {
794
return false;
795
}
796
virtual DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) {
797
return DataFormat::R8G8B8A8_UNORM;
798
}
799
800
// These functions should be self explanatory.
801
// Binding a zero render target means binding the backbuffer.
802
// If an fbo has two layers, we bind for stereo rendering ALWAYS. There's no rendering to one layer anymore.
803
virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) = 0;
804
805
// binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2).
806
virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect aspect, int layer) = 0;
807
808
// Framebuffer fetch / input attachment support, needs to be explicit in Vulkan.
809
virtual void BindCurrentFramebufferForColorInput() {}
810
811
virtual void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) = 0;
812
813
// Could be useful in OpenGL ES to give hints about framebuffers on tiler GPUs
814
// using glInvalidateFramebuffer, although drivers are known to botch that so we currently don't use it.
815
// In Vulkan, this sets the LOAD_OP or the STORE_OP (depending on stage) of the current render pass instance to DONT_CARE.
816
// channels is a bitwise combination of Aspect::COLOR, DEPTH and STENCIL.
817
virtual void InvalidateFramebuffer(FBInvalidationStage stage, Aspect aspects) {}
818
819
// Dynamic state
820
virtual void SetScissorRect(int left, int top, int width, int height) = 0;
821
virtual void SetViewport(const Viewport &viewport) = 0;
822
virtual void SetBlendFactor(float color[4]) = 0;
823
virtual void SetStencilParams(uint8_t refValue, uint8_t writeMask, uint8_t compareMask) = 0;
824
825
virtual void BindSamplerStates(int start, int count, SamplerState **state) = 0;
826
virtual void BindTextures(int start, int count, Texture **textures, TextureBindFlags flags = TextureBindFlags::NONE) = 0;
827
virtual void BindVertexBuffer(Buffer *vertexBuffer, int offset) = 0;
828
virtual void BindIndexBuffer(Buffer *indexBuffer, int offset) = 0;
829
830
// Sometimes it's necessary to bind a texture not created by thin3d, and use with a thin3d pipeline.
831
// Not pretty, and one way in the future could be to create all textures through thin3d.
832
// Data types:
833
// * Vulkan: VkImageView
834
// * D3D11: ID3D11ShaderResourceView*
835
// * OpenGL: GLRTexture
836
virtual void BindNativeTexture(int sampler, void *nativeTexture) = 0;
837
838
// Only supports a single dynamic uniform buffer, for maximum compatibility with the old APIs and ease of emulation.
839
// More modern methods will be added later.
840
virtual void UpdateDynamicUniformBuffer(const void *ub, size_t size) = 0;
841
842
void BindTexture(int stage, Texture *texture) {
843
Texture *textures[1] = { texture };
844
BindTextures(stage, 1, textures);
845
} // from sampler 0 and upwards
846
847
// Clear state cached within thin3d. Must be called after directly calling API functions.
848
// Note that framebuffer state (which framebuffer is bounds) may not be cached.
849
// Must not actually perform any API calls itself since this can be called when no framebuffer is bound for rendering.
850
virtual void Invalidate(InvalidationFlags flags) = 0;
851
852
virtual void BindPipeline(Pipeline *pipeline) = 0;
853
854
virtual void Draw(int vertexCount, int offset) = 0;
855
virtual void DrawIndexed(int vertexCount, int offset) = 0; // Always 16-bit indices.
856
virtual void DrawUP(const void *vdata, int vertexCount) = 0;
857
virtual void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount) = 0;
858
// Intended for ImGui display lists, easier to do optimally this way.
859
virtual void DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, const void *idata, int indexCount, Slice<ClippedDraw> draws, const void *dynUniforms, size_t size) = 0;
860
861
// Frame management (for the purposes of sync and resource management, necessary with modern APIs). Default implementations here.
862
virtual void BeginFrame(DebugFlags debugFlags) = 0;
863
virtual void EndFrame() = 0;
864
865
// Some backends also can't change presentation mode immediately.
866
virtual void Present(PresentMode presentMode) = 0;
867
virtual PresentMode GetCurrentPresentMode() const = 0;
868
869
// This should be avoided as much as possible, in favor of clearing when binding a render target, which is native
870
// on Vulkan.
871
virtual void Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) = 0;
872
873
// Necessary to correctly flip scissor rectangles etc for OpenGL.
874
virtual void SetTargetSize(int w, int h) {
875
targetWidth_ = w;
876
targetHeight_ = h;
877
}
878
879
// In Vulkan, when changing things like MSAA mode, we can't have draw commands in flight (since we only support one at a time).
880
virtual void StopThreads() {}
881
virtual void StartThreads() {}
882
883
virtual std::string GetInfoString(InfoField info) const = 0;
884
virtual uint64_t GetNativeObject(NativeObject obj, void *srcObject = nullptr) = 0; // Most uses don't need an srcObject.
885
886
virtual void HandleEvent(Event ev, int width, int height, void *param1 = nullptr, void *param2 = nullptr) = 0;
887
888
// Flush state like scissors etc so the caller can do its own custom drawing.
889
virtual void FlushState() {}
890
891
// This is called when we launch a new game, so any collected internal stats in the backends don't carry over.
892
virtual void ResetStats() {}
893
894
// Used by the DrawEngines to know when they have to re-apply some state.
895
// Not very elegant, but more elegant than the old passId hack.
896
virtual void SetInvalidationCallback(InvalidationCallback callback) = 0;
897
898
// Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.numFlips
899
virtual int GetFrameCount() = 0;
900
901
virtual std::string GetGpuProfileString() const {
902
return "";
903
}
904
905
const HistoryBuffer<FrameTimeData, FRAME_TIME_HISTORY_LENGTH> &FrameTimeHistory() const {
906
return frameTimeHistory_;
907
}
908
909
protected:
910
HistoryBuffer<FrameTimeData, FRAME_TIME_HISTORY_LENGTH> frameTimeHistory_;
911
912
ShaderModule *vsPresets_[VS_MAX_PRESET];
913
ShaderModule *fsPresets_[FS_MAX_PRESET];
914
915
ShaderLanguageDesc shaderLanguageDesc_;
916
917
int targetWidth_;
918
int targetHeight_;
919
920
Bugs bugs_;
921
};
922
923
extern const UniformBufferDesc UBPresetDesc;
924
925
// UBs for the preset shaders
926
927
struct VsTexColUB {
928
float WorldViewProj[16];
929
float tint;
930
float saturation;
931
float pad[2];
932
};
933
extern const UniformBufferDesc vsTexColBufDesc;
934
struct VsColUB {
935
float WorldViewProj[16];
936
float tint;
937
float saturation;
938
float pad[2];
939
};
940
extern const UniformBufferDesc vsColBufDesc;
941
942
// Useful utility for specifying a shader in multiple languages.
943
944
struct ShaderSource {
945
ShaderLanguage lang;
946
const char *src;
947
};
948
949
ShaderModule *CreateShader(DrawContext *draw, ShaderStage stage, const std::vector<ShaderSource> &sources);
950
951
const char *PresentModeToString(PresentMode presentMode);
952
953
} // namespace Draw
954
955